diff --git a/debian/config/config b/debian/config/config index 1dd5b4408..e8a45e58e 100644 --- a/debian/config/config +++ b/debian/config/config @@ -527,6 +527,34 @@ CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y ## CONFIG_CRYPTO_DEV_CHELSIO=m +## +## file: drivers/dahdi/Kconfig +## +CONFIG_DAHDI=m +# CONFIG_DAHDI_ECHOCAN is not set +# CONFIG_DAHDI_ECHOCAN_MG2 is not set +# CONFIG_DAHDI_ECHOCAN_KB1 is not set +# CONFIG_DAHDI_ECHOCAN_SEC is not set +# CONFIG_DAHDI_ECHOCAN_SEC2 is not set +# CONFIG_DAHDI_ECHOCAN_HPEC is not set +CONFIG_DAHDI_WCT4XXP=m +# CONFIG_DAHDI_TRANSCODE is not set +# CONFIG_DAHDI_WCTC4XXP is not set +# CONFIG_DAHDI_VOICEBUS is not set +# CONFIG_DAHDI_WCTDM24XXP is not set +# CONFIG_DAHDI_PCIRADIO is not set +CONFIG_DAHDI_DUMMY=m +CONFIG_DAHDI_DYNAMIC=m +CONFIG_DAHDI_DYNAMIC_ETH=m +CONFIG_DAHDI_DYNAMIC_ETHMF=m +CONFIG_DAHDI_DYNAMIC_LOC=m +# CONFIG_DAHDI_XPP is not set +# CONFIG_DAHDI_XPP_USB is not set +# CONFIG_DAHDI_XPD_FXS is not set +# CONFIG_DAHDI_XPD_FXO is not set +# CONFIG_DAHDI_XPD_BRI is not set +# CONFIG_DAHDI_XPD_PRI is not set + ## ## file: drivers/dax/Kconfig ## diff --git a/debian/patches/dahdi-integration.patch b/debian/patches/dahdi-integration.patch new file mode 100644 index 000000000..5806fdbfd --- /dev/null +++ b/debian/patches/dahdi-integration.patch @@ -0,0 +1,20 @@ +Index: linux/drivers/Kconfig +=================================================================== +--- linux.orig/drivers/Kconfig ++++ linux/drivers/Kconfig +@@ -219,4 +219,6 @@ source "drivers/siox/Kconfig" + + source "drivers/slimbus/Kconfig" + ++source "drivers/dahdi/Kconfig" ++ + endmenu +Index: linux/drivers/Makefile +=================================================================== +--- linux.orig/drivers/Makefile ++++ linux/drivers/Makefile +@@ -186,3 +186,4 @@ obj-$(CONFIG_MULTIPLEXER) += mux/ + obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/ + obj-$(CONFIG_SIOX) += siox/ + obj-$(CONFIG_GNSS) += gnss/ ++obj-$(CONFIG_DAHDI) += dahdi/ diff --git a/debian/patches/dahdi-no-vpm.patch b/debian/patches/dahdi-no-vpm.patch new file mode 100644 index 000000000..ffb75b25f --- /dev/null +++ b/debian/patches/dahdi-no-vpm.patch @@ -0,0 +1,26 @@ +Index: linux-source-4.19/drivers/dahdi/wct4xxp/Kbuild +=================================================================== +--- linux-source-4.19.orig/drivers/dahdi/wct4xxp/Kbuild ++++ linux-source-4.19/drivers/dahdi/wct4xxp/Kbuild +@@ -14,7 +14,7 @@ + EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE + endif + +-wct4xxp-objs := base.o vpm450m.o ++wct4xxp-objs := base.o + + ifneq ($(HOTPLUG_FIRMWARE),yes) + wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o +Index: linux-source-4.19/drivers/dahdi/wct4xxp/base.c +=================================================================== +--- linux-source-4.19.orig/drivers/dahdi/wct4xxp/base.c ++++ linux-source-4.19/drivers/dahdi/wct4xxp/base.c +@@ -56,7 +56,7 @@ + #undef FANCY_ALARM + + /* Define to support Digium Voice Processing Module expansion card */ +-#define VPM_SUPPORT ++//#define VPM_SUPPORRT + + #define DEBUG_MAIN (1 << 0) + #define DEBUG_DTMF (1 << 1) diff --git a/debian/patches/hdlc-mtu.patch b/debian/patches/hdlc-mtu.patch new file mode 100644 index 000000000..0fda68882 --- /dev/null +++ b/debian/patches/hdlc-mtu.patch @@ -0,0 +1,13 @@ +Index: linux-source-4.19/include/uapi/linux/hdlc.h +=================================================================== +--- linux-source-4.19.orig/include/uapi/linux/hdlc.h ++++ linux-source-4.19/include/uapi/linux/hdlc.h +@@ -13,7 +13,7 @@ + #define _UAPI__HDLC_H + + +-#define HDLC_MAX_MTU 1500 /* Ethernet 1500 bytes */ ++#define HDLC_MAX_MTU 1700 /* Ethernet 1500 bytes */ + #if 0 + #define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */ + #else diff --git a/debian/patches/linux-4.19-dahdi-3.1.0-7-g699e7a0.patch b/debian/patches/linux-4.19-dahdi-3.1.0-7-g699e7a0.patch new file mode 100644 index 000000000..b1aebccca --- /dev/null +++ b/debian/patches/linux-4.19-dahdi-3.1.0-7-g699e7a0.patch @@ -0,0 +1,213259 @@ +diff -Nru linux-source-4.19/drivers/dahdi/Kbuild linux-source-4.19-dahdi/drivers/dahdi/Kbuild +--- linux-source-4.19/drivers/dahdi/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/Kbuild 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,159 @@ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI) += dahdi.o ++#obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DUMMY) += dahdi_dummy.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC) += dahdi_dynamic.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_LOC) += dahdi_dynamic_loc.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETH) += dahdi_dynamic_eth.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF) += dahdi_dynamic_ethmf.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o ++ ++ifdef CONFIG_PCI ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) += oct612x/ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o ++ ++wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o ++CFLAGS_wcte13xp-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api ++ifeq ($(HOTPLUG_FIRMWARE),yes) ++ CFLAGS_wcte13xp-base.o += -DHOTPLUG_FIRMWARE ++endif ++ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE43X) += wcte43x.o ++ ++wcte43x-objs := wcte43x-base.o wcxb_spi.o wcxb.o wcxb_flash.o ++CFLAGS_wcte43x-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api ++ifeq ($(HOTPLUG_FIRMWARE),yes) ++ CFLAGS_wcte43x-base.o += -DHOTPLUG_FIRMWARE ++endif ++ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCAXX) += wcaxx.o ++ ++wcaxx-objs := wcaxx-base.o wcxb_spi.o wcxb.o wcxb_flash.o ++CFLAGS_wcaxx-base.o += -I$(src)/oct612x/ -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api ++ifeq ($(HOTPLUG_FIRMWARE),yes) ++ CFLAGS_wcaxx-base.o += -DHOTPLUG_FIRMWARE ++endif ++ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/ ++ ++ ++endif ++ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/ ++ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_JPAH) += dahdi_echocan_jpah.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE) += dahdi_echocan_sec.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE2) += dahdi_echocan_sec2.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_KB1) += dahdi_echocan_kb1.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_MG2) += dahdi_echocan_mg2.o ++ ++obj-m += $(DAHDI_MODULES_EXTRA) ++ ++# If you want to build OSLEC, include the code in the standard location: ++# drivers/staging/echo . The DAHDI OSLEC echo canceller will be built as ++# well: ++ifneq (,$(wildcard $(src)/../staging/echo/echo.c)) ++obj-m += dahdi_echocan_oslec.o ++obj-m += ../staging/echo/echo.o ++endif ++ ++CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src) -Wno-format-truncation ++ ++ifndef HOTPLUG_FIRMWARE ++ifneq (,$(filter y m,$(CONFIG_FW_LOADER))) ++HOTPLUG_FIRMWARE := yes ++else ++HOTPLUG_FIRMWARE := no ++endif ++export HOTPLUG_FIRMWARE ++endif ++ ++# fix typo present in CentOS and RHEL 2.6.9 kernels ++BAD_KERNELS_VERS := 22 34 34.0.1 34.0.2 ++BAD_KERNELS := $(foreach ver,$(BAD_KERNELS_VERS),2.6.9-$(ver).EL 2.6.9-$(ver).ELsmp) ++ifneq (,$(filter $(KVERS),$(BAD_KERNELS))) ++EXTRA_CFLAGS+=-Drw_lock_t=rwlock_t ++endif ++ ++# A number of Fedora 10 (9 also?) kernels backported hrtimer to 2.6.27 ++# as part of an ALSA backport. TODO: Any better way to detect that? ++ifeq (1,$(shell fgrep -q ' hrtimer_set_expires' include/linux/hrtimer.h 2>/dev/null && echo 1)) ++EXTRA_CFLAGS+=-DHAVE_HRTIMER_ACCESSORS=1 ++endif ++ ++ifeq (1,$(shell fgrep -q 'wait_for_completion_timeout' include/linux/completion.h 2>/dev/null && echo 1)) ++CFLAGS_MODULE+=-DHAVE_WAIT_FOR_COMPLETION_TIMEOUT=1 ++endif ++ ++# In 2.6.18 skb_linearize changed; however, some distros backported the change ++ifneq (,$(wildcard $(srctree)/include/linux/skbuff.h)) ++ifeq ($(shell grep "skb_linearize.*(.*, .* gfp)" $(srctree)/include/linux/skbuff.h),) ++CFLAGS_dahdi_dynamic_eth.o := -DNEW_SKB_LINEARIZE ++CFLAGS_dahdi_dynamic_ethmf.o := -DNEW_SKB_LINEARIZE ++endif ++endif ++ ++dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-sysfs-chan.o dahdi-version.o ++ ++############################################################################### ++# Find appropriate ARCH value for VPMADT032 and HPEC binary modules ++############################################################################### ++ ++ifeq ($(ARCH),i386) ++ DAHDI_ARCH=x86_32 ++else ++ ifeq ($(ARCH),x86_64) ++ DAHDI_ARCH=x86_64 ++ else ++ ifeq ($(ARCH),x86) ++ ifeq ($(CONFIG_X86_32),y) ++ DAHDI_ARCH=x86_32 ++ else ++ DAHDI_ARCH=x86_64 ++ endif ++ else ++$(warning CPU Architecture '$(ARCH)' does not support VPMADT032 or HPEC. Skipping.) ++ endif ++ endif ++endif ++ ++############################################################################### ++# VPMADT032 Loader ++############################################################################### ++ ++dahdi_vpmadt032_loader-objs := vpmadt032_loader/dahdi_vpmadt032_loader.o ++ ++ifneq ($(DAHDI_ARCH),) ++ ifneq ($(wildcard $(src)/vpmadt032_loader/vpmadt032_$(DAHDI_ARCH).o_shipped),) ++ VPMADT032_LOADER_PRESENT=yes ++ dahdi_vpmadt032_loader-objs += vpmadt032_loader/vpmadt032_$(DAHDI_ARCH).o ++ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VPMADT032_LOADER) += dahdi_vpmadt032_loader.o ++ endif ++endif ++ ++############################################################################### ++# HPEC Support ++############################################################################### ++ ++dahdi_echocan_hpec-objs := hpec/dahdi_echocan_hpec.o ++CFLAGS_dahdi_echocan_hpec.o := -I$(src)/hpec ++ ++ifneq ($(DAHDI_ARCH),) ++ ifneq ($(wildcard $(src)/hpec/hpec_$(DAHDI_ARCH).o_shipped),) ++ HPEC_PRESENT=yes ++ dahdi_echocan_hpec-objs += hpec/hpec_$(DAHDI_ARCH).o ++ endif ++endif ++ ++ifeq ($(HPEC_PRESENT),yes) ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_HPEC) += dahdi_echocan_hpec.o ++endif ++ ++ ++hostprogs-y := makefw ++ ++ ++ ++clean-files := radfw.h +diff -Nru linux-source-4.19/drivers/dahdi/Kconfig linux-source-4.19-dahdi/drivers/dahdi/Kconfig +--- linux-source-4.19/drivers/dahdi/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/Kconfig 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,226 @@ ++# ++# DAHDI configuration ++# ++ ++menuconfig DAHDI ++ tristate "DAHDI support" ++ select CRC_CCITT ++ default m ++ ---help--- ++ DAHDI basic infrastructure. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi. ++ ++ If unsure, say Y. ++ ++config DAHDI_ECHOCAN ++ tristate "DADHI Echo Cancelers (software)" ++ depends on DAHDI ++ default DAHDI ++ ++config DAHDI_ECHOCAN_MG2 ++ tristate "DADHI MG2 Echo Canceler" ++ depends on DAHDI_ECHOCAN ++ default DAHDI_ECHOCAN ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_echocancel_mg2. ++ ++ If unsure, say Y. ++ ++config DAHDI_ECHOCAN_KB1 ++ tristate "DADHI KB1 Echo Canceler" ++ depends on DAHDI_ECHOCAN ++ default DAHDI_ECHOCAN ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_echocancel_kb1. ++ ++ If unsure, say Y. ++ ++config DAHDI_ECHOCAN_SEC ++ tristate "DADHI SEC Echo Canceler" ++ depends on DAHDI_ECHOCAN ++ default DAHDI_ECHOCAN ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_echocancel_sec. ++ ++ If unsure, say Y. ++ ++config DAHDI_ECHOCAN_SEC2 ++ tristate "DADHI SEC2 Echo Canceler" ++ depends on DAHDI_ECHOCAN ++ default DAHDI_ECHOCAN ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_echocancel_sec2. ++ ++ If unsure, say Y. ++ ++config DAHDI_ECHOCAN_HPEC ++ tristate "DADHI HPEC Echo Canceler" ++ depends on DAHDI_ECHOCAN ++ default DAHDI_ECHOCAN ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_echocancel_hpec. ++ ++ If unsure, say Y. ++ ++config DAHDI_WCT4XXP ++ tristate "Digium Wildcard dual- and quad-T1/E1/J1 Support" ++ depends on DAHDI && PCI ++ default DAHDI ++ ---help--- ++ This driver provides support for the following Digium ++ Wildcard products: ++ ++ * TE205/206/207/210/211/212P (PCI/PCI-X) ++ * TE220 (PCI-E) ++ * TE405/406/407/410/411/412P (PCI/PCI-X) ++ * TE420 (PCI-E) ++ ++ To compile this driver as a module, choose M here: the ++ module will be called wct4xxp. ++ ++ If unsure, say Y. ++ ++config DAHDI_TRANSCODE ++ tristate "DAHDI transcoding support" ++ depends on DAHDI ++ default DAHDI ++ ---help--- ++ DAHDI transcoding infrastructure. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_transcode. ++ ++ If unsure, say Y. ++ ++config DAHDI_WCTC4XXP ++ tristate "Digium Wildcard TC400B Support" ++ depends on DAHDI_TRANSCODE && PCI ++ default DAHDI ++ ---help--- ++ This driver provides support for the Digium Wildcard TC400B. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called 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 && DAHDI_VOICEBUS ++ default DAHDI ++ ---help--- ++ This driver provides support for the following Digium ++ Wildcard products: ++ ++ * TDM410P (PCI/PCI-X) ++ * AEX410 (PCI-E) ++ * TDM800P (PCI/PCI-X) ++ * AEX800 (PCI-E) ++ * TDM2400P (PCI/PCI-X) ++ * AEX2400 (PCI-E) ++ ++ To compile this driver as a module, choose M here: the ++ module will be called wctdm24xxp. ++ ++ If unsure, say Y. ++ ++config DAHDI_PCIRADIO ++ tristate "PCI Radio Support" ++ depends on DAHDI && PCI ++ default DAHDI ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called pciradio. ++ ++ If unsure, say Y. ++ ++config DAHDI_DUMMY ++ tristate "Dummy (no hardware) Timing Support" ++ depends on DAHDI ++ default DAHDI ++ ---help--- ++ This module provides timing support for applications that ++ use DAHDI conference mixing services, pseudo channels or ++ for other purposes. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_dummy. ++ ++ If unsure, say Y. ++ ++config DAHDI_DYNAMIC ++ tristate "Dynamic (virtual) Span Support" ++ depends on DAHDI ++ default DAHDI ++ ---help--- ++ This module provides support for virtual spans, which are ++ emulated or provided using various technologies. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_dynamic. ++ ++ If unsure, say Y. ++ ++config DAHDI_DYNAMIC_ETH ++ tristate "Ethernet (TDMoE) Span Support" ++ depends on DAHDI && DAHDI_DYNAMIC ++ default DAHDI ++ ---help--- ++ This module provides support for spans over Ethernet, ++ using the TDMoE protocol. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_dynamic_eth. ++ ++ If unsure, say Y. ++ ++config DAHDI_DYNAMIC_ETHMF ++ tristate "Ethernet (TDMoE) Multi-Frame Span Support" ++ depends on DAHDI && DAHDI_DYNAMIC ++ default DAHDI ++ ---help--- ++ This module provides support for spans over Ethernet, ++ using the TDMoE-Multi-Frame protocol. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_dynamic_ethmf. ++ ++ If unsure, say Y. ++ ++config DAHDI_DYNAMIC_LOC ++ tristate "Local (loopback) Span Support" ++ depends on DAHDI && DAHDI_DYNAMIC ++ default DAHDI ++ ---help--- ++ This module provides support for spans in the local system, ++ primarily used for looping and monitoring other spans. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called dahdi_dynamic_loc. ++ ++ If unsure, say Y. ++ ++ ++source "drivers/dahdi/xpp/Kconfig" +diff -Nru linux-source-4.19/drivers/dahdi/adt_lec.c linux-source-4.19-dahdi/drivers/dahdi/adt_lec.c +--- linux-source-4.19/drivers/dahdi/adt_lec.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/adt_lec.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,73 @@ ++/* ++ * ADT Line Echo Canceller Parameter Parsing ++ * ++ * Copyright (C) 2008-2009 Digium, Inc. ++ * ++ * Kevin P. Fleming ++ * ++ * 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 _ADT_LEC_C ++#define _ADT_LEC_C ++ ++#include ++ ++static inline void adt_lec_init_defaults(struct adt_lec_params *params, __u32 tap_length) ++{ ++ params->tap_length = tap_length; ++ params->nlp_type = 0; ++ params->nlp_max_suppress = 0; ++ params->nlp_threshold = 0; ++} ++ ++static int adt_lec_parse_params(struct adt_lec_params *params, ++ struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) ++{ ++ unsigned int x; ++ char *c; ++ ++ params->tap_length = ecp->tap_length; ++ ++ for (x = 0; x < ecp->param_count; x++) { ++ for (c = p[x].name; *c; c++) ++ *c = tolower(*c); ++ if (!strcmp(p[x].name, "nlp_type")) { ++ switch (p[x].value) { ++ case ADT_LEC_NLP_OFF: ++ case ADT_LEC_NLP_MUTE: ++ case ADT_LEC_RANDOM_NOISE: ++ case ADT_LEC_HOTH_NOISE: ++ case ADT_LEC_SUPPRESS: ++ params->nlp_type = p[x].value; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } else if (!strcmp(p[x].name, "nlp_thresh")) { ++ params->nlp_threshold = p[x].value; ++ } else if (!strcmp(p[x].name, "nlp_suppress")) { ++ params->nlp_max_suppress = p[x].value; ++ } else { ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++#endif /* _ADT_LEC_C */ +diff -Nru linux-source-4.19/drivers/dahdi/adt_lec.h linux-source-4.19-dahdi/drivers/dahdi/adt_lec.h +--- linux-source-4.19/drivers/dahdi/adt_lec.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/adt_lec.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,48 @@ ++/* ++ * ADT Line Echo Canceller Parameter Parsing ++ * ++ * Copyright (C) 2008 Digium, Inc. ++ * ++ * Kevin P. Fleming ++ * ++ * 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 _ADT_LEC_H ++#define _ADT_LEC_H ++ ++enum adt_lec_nlp_type { ++ ADT_LEC_NLP_OFF = 0, ++ ADT_LEC_NLP_MUTE, ++ ADT_LEC_RANDOM_NOISE, ++ ADT_LEC_HOTH_NOISE, ++ ADT_LEC_SUPPRESS, ++}; ++ ++enum adt_companding { ++ ADT_COMP_ULAW = 0, ++ ADT_COMP_ALAW, ++}; ++ ++struct adt_lec_params { ++ __u32 tap_length; ++ enum adt_lec_nlp_type nlp_type; ++ __u32 nlp_threshold; ++ __u32 nlp_max_suppress; ++ enum adt_companding companding; ++}; ++ ++#endif /* _ADT_LEC_H */ +diff -Nru linux-source-4.19/drivers/dahdi/arith.h linux-source-4.19-dahdi/drivers/dahdi/arith.h +--- linux-source-4.19/drivers/dahdi/arith.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/arith.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,378 @@ ++/* ++ * Handy add/subtract functions to operate on chunks of shorts. ++ * Feel free to add customizations for additional architectures ++ * ++ */ ++ ++/* ++ * 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 _DAHDI_ARITH_H ++#define _DAHDI_ARITH_H ++ ++#ifdef CONFIG_DAHDI_MMX ++#ifdef DAHDI_CHUNKSIZE ++static inline void __ACSS(volatile short *dst, const short *src) ++{ ++ __asm__ __volatile__ ( ++ "movq 0(%0), %%mm0;\n" ++ "movq 0(%1), %%mm1;\n" ++ "movq 8(%0), %%mm2;\n" ++ "movq 8(%1), %%mm3;\n" ++ "paddsw %%mm1, %%mm0;\n" ++ "paddsw %%mm3, %%mm2;\n" ++ "movq %%mm0, 0(%0);\n" ++ "movq %%mm2, 8(%0);\n" ++ : "=r" (dst) ++ : "r" (src), "0" (dst) ++ : "memory" ++#ifdef CLOBBERMMX ++ , "%mm0", "%mm1", "%mm2", "%mm3" ++#endif ++ ); ++ ++} ++static inline void __SCSS(volatile short *dst, const short *src) ++{ ++ __asm__ __volatile__ ( ++ "movq 0(%0), %%mm0;\n" ++ "movq 0(%1), %%mm1;\n" ++ "movq 8(%0), %%mm2;\n" ++ "movq 8(%1), %%mm3;\n" ++ "psubsw %%mm1, %%mm0;\n" ++ "psubsw %%mm3, %%mm2;\n" ++ "movq %%mm0, 0(%0);\n" ++ "movq %%mm2, 8(%0);\n" ++ : "=r" (dst) ++ : "r" (src), "0" (dst) ++ : "memory" ++#ifdef CLOBBERMMX ++ , "%mm0", "%mm1", "%mm2", "%mm3" ++#endif ++ ); ++ ++} ++ ++#if (DAHDI_CHUNKSIZE == 8) ++#define ACSS(a,b) __ACSS(a,b) ++#define SCSS(a,b) __SCSS(a,b) ++#elif (DAHDI_CHUNKSIZE > 8) ++static inline void ACSS(volatile short *dst, const short *src) ++{ ++ int x; ++ for (x=0;x>= 4; ++ ++ /* Clear our accumulator, mm4 */ ++ ++ /* ++ ++ For every set of eight... ++ ++ Load 16 coefficients into four registers... ++ Shift each word right 16 to make them shorts... ++ Pack the resulting shorts into two registers... ++ With the coefficients now in mm0 and mm2, load the ++ history into mm1 and mm3... ++ Multiply/add mm1 into mm0, and mm3 into mm2... ++ Add mm2 into mm0 (without saturation, alas). Now we have two half-results. ++ Accumulate in mm4 (again, without saturation, alas) ++ */ ++ __asm__ ( ++ "pxor %%mm4, %%mm4;\n" ++ "mov %1, %%edi;\n" ++ "mov %2, %%esi;\n" ++ "mov %3, %%ecx;\n" ++ "1:" ++ "movq 0(%%edi), %%mm0;\n" ++ "movq 8(%%edi), %%mm1;\n" ++ "movq 16(%%edi), %%mm2;\n" ++ "movq 24(%%edi), %%mm3;\n" ++ /* can't use 4/5 since 4 is the accumulator for us */ ++ "movq 32(%%edi), %%mm6;\n" ++ "movq 40(%%edi), %%mm7;\n" ++ "psrad $16, %%mm0;\n" ++ "psrad $16, %%mm1;\n" ++ "psrad $16, %%mm2;\n" ++ "psrad $16, %%mm3;\n" ++ "psrad $16, %%mm6;\n" ++ "psrad $16, %%mm7;\n" ++ "packssdw %%mm1, %%mm0;\n" ++ "packssdw %%mm3, %%mm2;\n" ++ "packssdw %%mm7, %%mm6;\n" ++ "movq 0(%%esi), %%mm1;\n" ++ "movq 8(%%esi), %%mm3;\n" ++ "movq 16(%%esi), %%mm7;\n" ++ "pmaddwd %%mm1, %%mm0;\n" ++ "pmaddwd %%mm3, %%mm2;\n" ++ "pmaddwd %%mm7, %%mm6;\n" ++ "paddd %%mm6, %%mm4;\n" ++ "paddd %%mm2, %%mm4;\n" ++ "paddd %%mm0, %%mm4;\n" ++ /* Come back and do for the last few bytes */ ++ "movq 48(%%edi), %%mm6;\n" ++ "movq 56(%%edi), %%mm7;\n" ++ "psrad $16, %%mm6;\n" ++ "psrad $16, %%mm7;\n" ++ "packssdw %%mm7, %%mm6;\n" ++ "movq 24(%%esi), %%mm7;\n" ++ "pmaddwd %%mm7, %%mm6;\n" ++ "paddd %%mm6, %%mm4;\n" ++ "add $64, %%edi;\n" ++ "add $32, %%esi;\n" ++ "dec %%ecx;\n" ++ "jnz 1b;\n" ++ "movq %%mm4, %%mm0;\n" ++ "psrlq $32, %%mm0;\n" ++ "paddd %%mm0, %%mm4;\n" ++ "movd %%mm4, %0;\n" ++ : "=r" (sum) ++ : "r" (coeffs), "r" (hist), "r" (len) ++ : "%ecx", "%edi", "%esi" ++ ); ++ ++ return sum; ++} ++ ++static inline void UPDATE(volatile int *taps, const short *history, const int nsuppr, const int ntaps) ++{ ++ int i; ++ int correction; ++ for (i=0;i>= 4; ++ /* First, load up taps, */ ++ __asm__ ( ++ "pxor %%mm4, %%mm4;\n" ++ "mov %0, %%edi;\n" ++ "mov %1, %%esi;\n" ++ "mov %3, %%ecx;\n" ++ "1:" ++ "jnz 1b;\n" ++ "movq %%mm4, %%mm0;\n" ++ "psrlq $32, %%mm0;\n" ++ "paddd %%mm0, %%mm4;\n" ++ "movd %%mm4, %0;\n" ++ : "=r" (taps), "=r" (taps_short) ++ : "r" (history), "r" (nsuppr), "r" (ntaps), "0" (taps) ++ : "%ecx", "%edi", "%esi" ++ ); ++#endif ++#if 1 ++ for (i=0;i> 16; ++ } ++#endif ++} ++ ++static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) ++{ ++ int sum; ++ /* Divide length by 16 */ ++ len >>= 4; ++ ++ /* Clear our accumulator, mm4 */ ++ ++ /* ++ ++ For every set of eight... ++ Load in eight coefficients and eight historic samples, multliply add and ++ accumulate the result ++ */ ++ __asm__ ( ++ "pxor %%mm4, %%mm4;\n" ++ "mov %1, %%edi;\n" ++ "mov %2, %%esi;\n" ++ "mov %3, %%ecx;\n" ++ "1:" ++ "movq 0(%%edi), %%mm0;\n" ++ "movq 8(%%edi), %%mm2;\n" ++ "movq 0(%%esi), %%mm1;\n" ++ "movq 8(%%esi), %%mm3;\n" ++ "pmaddwd %%mm1, %%mm0;\n" ++ "pmaddwd %%mm3, %%mm2;\n" ++ "paddd %%mm2, %%mm4;\n" ++ "paddd %%mm0, %%mm4;\n" ++ "movq 16(%%edi), %%mm0;\n" ++ "movq 24(%%edi), %%mm2;\n" ++ "movq 16(%%esi), %%mm1;\n" ++ "movq 24(%%esi), %%mm3;\n" ++ "pmaddwd %%mm1, %%mm0;\n" ++ "pmaddwd %%mm3, %%mm2;\n" ++ "paddd %%mm2, %%mm4;\n" ++ "paddd %%mm0, %%mm4;\n" ++ "add $32, %%edi;\n" ++ "add $32, %%esi;\n" ++ "dec %%ecx;\n" ++ "jnz 1b;\n" ++ "movq %%mm4, %%mm0;\n" ++ "psrlq $32, %%mm0;\n" ++ "paddd %%mm0, %%mm4;\n" ++ "movd %%mm4, %0;\n" ++ : "=r" (sum) ++ : "r" (coeffs), "r" (hist), "r" (len) ++ : "%ecx", "%edi", "%esi" ++ ); ++ ++ return sum; ++} ++static inline short MAX16(const short *y, int len, int *pos) ++{ ++ int k; ++ short max = 0; ++ int bestpos = 0; ++ for (k=0;k 32767) ++ sum = 32767; ++ else if (sum < -32768) ++ sum = -32768; ++ dst[x] = sum; ++ } ++#endif ++} ++ ++static inline void SCSS(short *dst, short *src) ++{ ++ int x; ++ ++ /* Subtract src from dst with saturation, storing in dst */ ++#ifdef BFIN ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ dst[x] = __builtin_bfin_sub_fr1x16(dst[x], src[x]); ++#else ++ int sum; ++ ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) { ++ sum = dst[x] - src[x]; ++ if (sum > 32767) ++ sum = 32767; ++ else if (sum < -32768) ++ sum = -32768; ++ dst[x] = sum; ++ } ++#endif ++} ++ ++#endif /* DAHDI_CHUNKSIZE */ ++ ++static inline int CONVOLVE(const int *coeffs, const short *hist, int len) ++{ ++ int x; ++ int sum = 0; ++ for (x=0;x> 16) * hist[x]; ++ return sum; ++} ++ ++static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) ++{ ++ int x; ++ int sum = 0; ++ for (x=0;x> 16; ++ } ++} ++ ++static inline short MAX16(const short *y, int len, int *pos) ++{ ++ int k; ++ short max = 0; ++ int bestpos = 0; ++ for (k=0;k ++ * ++ * Copyright (C) 2001 Steve Underwood ++ * ++ * 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. ++ */ ++ ++static inline void biquad2_init (biquad2_state_t *bq, ++ int32_t gain, ++ int32_t a1, ++ int32_t a2, ++ int32_t b1, ++ int32_t b2) ++{ ++ bq->gain = gain; ++ bq->a1 = a1; ++ bq->a2 = a2; ++ bq->b1 = b1; ++ bq->b2 = b2; ++ ++ bq->z1 = 0; ++ bq->z2 = 0; ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline int16_t biquad2 (biquad2_state_t *bq, int16_t sample) ++{ ++ int32_t y; ++ int32_t z0; ++ ++ z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2; ++ y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2; ++ ++ bq->z2 = bq->z1; ++ bq->z1 = z0 >> 15; ++ y >>= 15; ++ return y; ++} ++/*- End of function --------------------------------------------------------*/ ++/*- End of file ------------------------------------------------------------*/ +diff -Nru linux-source-4.19/drivers/dahdi/dahdi-base.c linux-source-4.19-dahdi/drivers/dahdi/dahdi-base.c +--- linux-source-4.19/drivers/dahdi/dahdi-base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi-base.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,10568 @@ ++/* ++ * DAHDI Telephony Interface Driver ++ * ++ * Written by Mark Spencer ++ * Based on previous works, designs, and architectures conceived and ++ * written by Jim Dixon . ++ * ++ * Special thanks to Steve Underwood ++ * for substantial contributions to signal processing functions ++ * in DAHDI and the Zapata library. ++ * ++ * Yury Bokhoncovich ++ * Adaptation for 2.4.20+ kernels (HDLC API was changed) ++ * The work has been performed as a part of our move ++ * from Cisco 3620 to IBM x305 here in F1 Group ++ * ++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony. ++ * Copyright (C) 2001 - 2012 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL) ++#include ++#endif ++ ++#include ++ ++#include ++ ++#define DAHDI_PRINK_MACROS_USE_debug ++ ++/* Grab fasthdlc with tables */ ++#define FAST_HDLC_NEED_TABLES ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#include ++#endif /* 4.11.0 */ ++ ++#include "ecdis.h" ++#include "dahdi.h" ++ ++#ifdef CONFIG_DAHDI_PPP ++#include ++#include ++#include ++#endif ++ ++#ifdef CONFIG_DAHDI_NET ++#include ++#endif ++ ++#include "hpec/hpec_user.h" ++ ++#include ++ ++#if defined(EMPULSE) && defined(EMFLASH) ++#error "You cannot define both EMPULSE and EMFLASH" ++#endif ++ ++/* Get helper arithmetic */ ++#include "arith.h" ++#if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP) ++#include ++#endif ++ ++#define hdlc_to_chan(h) (((struct dahdi_hdlc *)(h))->chan) ++#define netdev_to_chan(h) (((struct dahdi_hdlc *)(dev_to_hdlc(h)->priv))->chan) ++#define chan_to_netdev(h) ((h)->hdlcnetdev->netdev) ++ ++/* macro-oni for determining a unit (channel) number */ ++#define UNIT(file) MINOR(file->f_path.dentry->d_inode->i_rdev) ++ ++EXPORT_SYMBOL(dahdi_transcode_fops); ++EXPORT_SYMBOL(dahdi_init_tone_state); ++EXPORT_SYMBOL(dahdi_mf_tone); ++EXPORT_SYMBOL(__dahdi_mulaw); ++EXPORT_SYMBOL(__dahdi_alaw); ++#ifdef CONFIG_CALC_XLAW ++EXPORT_SYMBOL(__dahdi_lineartoulaw); ++EXPORT_SYMBOL(__dahdi_lineartoalaw); ++#else ++EXPORT_SYMBOL(__dahdi_lin2mu); ++EXPORT_SYMBOL(__dahdi_lin2a); ++#endif ++EXPORT_SYMBOL(dahdi_rbsbits); ++EXPORT_SYMBOL(dahdi_qevent_nolock); ++EXPORT_SYMBOL(dahdi_qevent_lock); ++EXPORT_SYMBOL(dahdi_hooksig); ++EXPORT_SYMBOL(dahdi_alarm_notify); ++EXPORT_SYMBOL(dahdi_hdlc_abort); ++EXPORT_SYMBOL(dahdi_hdlc_finish); ++EXPORT_SYMBOL(dahdi_hdlc_getbuf); ++EXPORT_SYMBOL(dahdi_hdlc_putbuf); ++EXPORT_SYMBOL(dahdi_alarm_channel); ++ ++EXPORT_SYMBOL(dahdi_register_echocan_factory); ++EXPORT_SYMBOL(dahdi_unregister_echocan_factory); ++ ++EXPORT_SYMBOL(dahdi_set_hpec_ioctl); ++ ++#ifdef CONFIG_PROC_FS ++static struct proc_dir_entry *root_proc_entry; ++#endif ++ ++static int deftaps = 64; ++ ++int debug; ++#define DEBUG_MAIN (1 << 0) ++#define DEBUG_RBS (1 << 5) ++ ++static int hwec_overrides_swec = 1; ++ ++/*! ++ * \brief states for transmit signalling ++ */ ++enum dahdi_txstate { ++ DAHDI_TXSTATE_ONHOOK, ++ DAHDI_TXSTATE_OFFHOOK, ++ DAHDI_TXSTATE_START, ++ DAHDI_TXSTATE_PREWINK, ++ DAHDI_TXSTATE_WINK, ++ DAHDI_TXSTATE_PREFLASH, ++ DAHDI_TXSTATE_FLASH, ++ DAHDI_TXSTATE_DEBOUNCE, ++ DAHDI_TXSTATE_AFTERSTART, ++ DAHDI_TXSTATE_RINGON, ++ DAHDI_TXSTATE_RINGOFF, ++ DAHDI_TXSTATE_KEWL, ++ DAHDI_TXSTATE_AFTERKEWL, ++ DAHDI_TXSTATE_PULSEBREAK, ++ DAHDI_TXSTATE_PULSEMAKE, ++ DAHDI_TXSTATE_PULSEAFTER, ++}; ++ ++typedef short sumtype[DAHDI_MAX_CHUNKSIZE]; ++ ++static sumtype sums[(DAHDI_MAX_CONF + 1) * 3]; ++ ++/* Translate conference aliases into actual conferences ++ and vice-versa */ ++static short confalias[DAHDI_MAX_CONF + 1]; ++static short confrev[DAHDI_MAX_CONF + 1]; ++ ++static sumtype *conf_sums_next; ++static sumtype *conf_sums; ++static sumtype *conf_sums_prev; ++ ++static struct dahdi_span *master_span; ++struct file_operations *dahdi_transcode_fops = NULL; ++ ++ ++#ifdef CONFIG_DAHDI_CONFLINK ++static struct { ++ int src; /* source conf number */ ++ int dst; /* dst conf number */ ++} conf_links[DAHDI_MAX_CONF + 1]; ++ ++static int maxlinks; ++ ++#endif ++ ++#ifdef CONFIG_DAHDI_CORE_TIMER ++ ++static struct core_timer { ++ struct timer_list timer; ++ ktime_t start_interval; ++ unsigned long interval; ++ int dahdi_receive_used; ++ atomic_t count; ++ atomic_t shutdown; ++ atomic_t last_count; ++} core_timer; ++ ++#endif /* CONFIG_DAHDI_CORE_TIMER */ ++ ++ ++enum dahdi_digit_mode { ++ DIGIT_MODE_DTMF, ++ DIGIT_MODE_MFR1, ++ DIGIT_MODE_PULSE, ++ DIGIT_MODE_MFR2_FWD, ++ DIGIT_MODE_MFR2_REV, ++}; ++ ++/* At the end of silence, the tone stops */ ++static struct dahdi_tone dtmf_silence = { ++ .tonesamples = DAHDI_MS_TO_SAMPLES(DAHDI_CONFIG_DEFAULT_DTMF_LENGTH), ++}; ++ ++/* At the end of silence, the tone stops */ ++static struct dahdi_tone mfr1_silence = { ++ .tonesamples = DAHDI_MS_TO_SAMPLES(DAHDI_CONFIG_DEFAULT_MFR1_LENGTH), ++}; ++ ++/* At the end of silence, the tone stops */ ++static struct dahdi_tone mfr2_silence = { ++ .tonesamples = DAHDI_MS_TO_SAMPLES(DAHDI_CONFIG_DEFAULT_MFR2_LENGTH), ++}; ++ ++/* A pause in the dialing */ ++static struct dahdi_tone tone_pause = { ++ .tonesamples = DAHDI_MS_TO_SAMPLES(DAHDI_CONFIG_PAUSE_LENGTH), ++}; ++ ++static struct dahdi_dialparams global_dialparams = { ++ .dtmf_tonelen = DAHDI_MS_TO_SAMPLES(DAHDI_CONFIG_DEFAULT_DTMF_LENGTH), ++ .mfv1_tonelen = DAHDI_MS_TO_SAMPLES(DAHDI_CONFIG_DEFAULT_MFR1_LENGTH), ++ .mfr2_tonelen = DAHDI_MS_TO_SAMPLES(DAHDI_CONFIG_DEFAULT_MFR2_LENGTH), ++}; ++ ++static DEFINE_MUTEX(global_dialparamslock); ++ ++static int dahdi_chan_ioctl(struct file *file, unsigned int cmd, unsigned long data); ++ ++#if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP) ++#if (defined(CONFIG_X86) && !defined(CONFIG_X86_64)) || defined(CONFIG_I386) ++struct fpu_save_buf { ++ unsigned long cr0; ++ unsigned long fpu_buf[128]; ++}; ++ ++static DEFINE_PER_CPU(struct fpu_save_buf, fpu_buf); ++ ++/** dahdi_kernel_fpu_begin() - Save floating point registers ++ * ++ * This function is similar to kernel_fpu_begin() . However it is ++ * designed to work in an interrupt context. Restoring must be done with ++ * dahdi_kernel_fpu_end(). ++ * ++ * Furthermore, the whole code between the call to ++ * dahdi_kernel_fpu_begin() and dahdi_kernel_fpu_end() must reside ++ * inside a spinlock. Otherwise the context might be restored to the ++ * wrong process. ++ * ++ * Current implementation is x86/ia32-specific and will not even build on ++ * x86_64) ++ * */ ++static inline void dahdi_kernel_fpu_begin(void) ++{ ++ struct fpu_save_buf *buf = &__get_cpu_var(fpu_buf); ++ __asm__ __volatile__ ("movl %%cr0,%0; clts" : "=r" (buf->cr0)); ++ __asm__ __volatile__ ("fnsave %0" : "=m" (buf->fpu_buf)); ++} ++ ++/** dahdi_kernel_fpu_end() - restore floating point context ++ * ++ * Must be used with context saved by dahdi_kernel_fpu_begin(). See its ++ * documentation for further information. ++ */ ++static inline void dahdi_kernel_fpu_end(void) ++{ ++ struct fpu_save_buf *buf = &__get_cpu_var(fpu_buf); ++ __asm__ __volatile__ ("frstor %0" : "=m" (buf->fpu_buf)); ++ __asm__ __volatile__ ("movl %0,%%cr0" : : "r" (buf->cr0)); ++} ++ ++#else /* We haven't fixed FP context saving/restoring yet */ ++/* Very strange things can happen when the context is not properly ++ * restored. OTOH, some people do report success with this. Hence we ++ * so far just issue a warning */ ++#warning CONFIG_DAHDI_MMX may behave randomly on this platform ++#define dahdi_kernel_fpu_begin kernel_fpu_begin ++#define dahdi_kernel_fpu_end kernel_fpu_end ++#endif ++ ++#endif ++ ++struct dahdi_timer { ++ spinlock_t lock; ++ int ms; /* Countdown */ ++ int pos; /* Position */ ++ int ping; /* Whether we've been ping'd */ ++ int tripped; /* Whether we're tripped */ ++ struct list_head list; ++ wait_queue_head_t sel; ++}; ++ ++static LIST_HEAD(dahdi_timers); ++ ++static DEFINE_SPINLOCK(dahdi_timer_lock); ++ ++#define DEFAULT_TONE_ZONE (-1) ++ ++struct dahdi_zone { ++ int ringcadence[DAHDI_MAX_CADENCE]; ++ struct dahdi_tone *tones[DAHDI_TONE_MAX]; ++ /* Each of these is a circular list ++ of dahdi_tones to generate what we ++ want. Use NULL if the tone is ++ unavailable */ ++ struct dahdi_tone dtmf[16]; /* DTMF tones for this zone, with desired length */ ++ struct dahdi_tone dtmf_continuous[16]; /* DTMF tones for this zone, continuous play */ ++ struct dahdi_tone mfr1[15]; /* MFR1 tones for this zone, with desired length */ ++ struct dahdi_tone mfr2_fwd[15]; /* MFR2 FWD tones for this zone, with desired length */ ++ struct dahdi_tone mfr2_rev[15]; /* MFR2 REV tones for this zone, with desired length */ ++ struct dahdi_tone mfr2_fwd_continuous[16]; /* MFR2 FWD tones for this zone, continuous play */ ++ struct dahdi_tone mfr2_rev_continuous[16]; /* MFR2 REV tones for this zone, continuous play */ ++ struct list_head node; ++ struct kref refcount; ++ const char *name; /* Informational, only */ ++ u8 num; ++}; ++ ++static void tone_zone_release(struct kref *kref) ++{ ++ struct dahdi_zone *z = container_of(kref, struct dahdi_zone, refcount); ++ kfree(z->name); ++ kfree(z); ++} ++ ++/** ++ * tone_zone_put() - Release the reference on the tone_zone. ++ * ++ * On old kernels, since kref_put does not have a return value, we'll just ++ * always report that we released the memory. ++ * ++ */ ++static inline int tone_zone_put(struct dahdi_zone *z) ++{ ++ return kref_put(&z->refcount, tone_zone_release); ++} ++ ++static inline void tone_zone_get(struct dahdi_zone *z) ++{ ++ kref_get(&z->refcount); ++} ++ ++static DEFINE_SPINLOCK(zone_lock); ++ ++/* The first zone on the list is the default zone. */ ++static LIST_HEAD(tone_zones); ++ ++static inline struct device *span_device(struct dahdi_span *span) ++{ ++ return &span->parent->dev; ++} ++ ++/* Protects the span_list and pseudo_chans lists from concurrent access in ++ * process context. The spin_lock is needed to synchronize with the interrupt ++ * handler. */ ++static DEFINE_SPINLOCK(chan_lock); ++ ++struct pseudo_chan { ++ struct dahdi_chan chan; ++ struct list_head node; ++}; ++ ++static inline struct pseudo_chan *chan_to_pseudo(struct dahdi_chan *chan) ++{ ++ return container_of(chan, struct pseudo_chan, chan); ++} ++ ++enum { FIRST_PSEUDO_CHANNEL = 0x8000, }; ++/* This list is protected by the chan_lock. */ ++static LIST_HEAD(pseudo_chans); ++ ++/** ++ * is_pseudo_chan() - By definition pseudo channels are not on a span. ++ */ ++static inline bool is_pseudo_chan(const struct dahdi_chan *chan) ++{ ++ return (NULL == chan->span); ++} ++ ++static DEFINE_MUTEX(registration_mutex); ++static LIST_HEAD(span_list); ++ ++static unsigned long ++__for_each_channel(unsigned long (*func)(struct dahdi_chan *chan, ++ unsigned long data), ++ unsigned long data) ++{ ++ int res; ++ struct dahdi_span *s; ++ struct pseudo_chan *pseudo; ++ ++ list_for_each_entry(s, &span_list, spans_node) { ++ unsigned long x; ++ for (x = 0; x < s->channels; x++) { ++ struct dahdi_chan *const chan = s->chans[x]; ++ res = func(chan, data); ++ if (res) ++ return res; ++ } ++ } ++ ++ list_for_each_entry(pseudo, &pseudo_chans, node) { ++ res = func(&pseudo->chan, data); ++ if (res) ++ return res; ++ } ++ return 0; ++} ++ ++/** ++ * _chan_from_num - Lookup a channel ++ * ++ * Must be called with the registration_mutex held. ++ * ++ */ ++static struct dahdi_chan *_chan_from_num(unsigned int channo) ++{ ++ struct dahdi_span *s; ++ struct pseudo_chan *pseudo; ++ ++ if (channo >= FIRST_PSEUDO_CHANNEL) { ++ list_for_each_entry(pseudo, &pseudo_chans, node) { ++ if (pseudo->chan.channo == channo) ++ return &pseudo->chan; ++ } ++ return NULL; ++ } ++ ++ /* When searching for the channel amongst the spans, we can use the ++ * fact that channels on a span must be numbered consecutively to skip ++ * checking each individual channel. */ ++ list_for_each_entry(s, &span_list, spans_node) { ++ unsigned int basechan; ++ struct dahdi_chan *chan; ++ ++ if (unlikely(!s->channels)) ++ continue; ++ ++ basechan = s->chans[0]->channo; ++ if (channo >= (basechan + s->channels)) ++ continue; ++ ++ /* Since all the spans should be on the list in sorted order, ++ * if channo is less than base chan, the caller must be ++ * looking for a channel that has already been removed. */ ++ if (unlikely(channo < basechan)) ++ return NULL; ++ ++ chan = s->chans[channo - basechan]; ++ WARN_ON(chan->channo != channo); ++ return chan; ++ } ++ ++ return NULL; ++} ++ ++static struct dahdi_chan *chan_from_num(unsigned int channo) ++{ ++ struct dahdi_chan *chan; ++ mutex_lock(®istration_mutex); ++ chan = _chan_from_num(channo); ++ mutex_unlock(®istration_mutex); ++ return chan; ++} ++ ++static inline struct dahdi_chan *chan_from_file(struct file *file) ++{ ++ return (file->private_data) ? ++ file->private_data : chan_from_num(UNIT(file)); ++} ++ ++/** ++ * _find_span() - Find a span by span number. ++ * ++ * Must be called with registration_mutex held. ++ * ++ */ ++static struct dahdi_span *_find_span(int spanno) ++{ ++ struct dahdi_span *s; ++ list_for_each_entry(s, &span_list, spans_node) { ++ if (s->spanno == spanno) { ++ return s; ++ } ++ } ++ return NULL; ++} ++/** ++ * span_find_and_get() - Search for the span by number, and if found take out ++ * a reference on it. ++ * ++ * When you are no longer using the returned pointer, you must release it with ++ * a put_span call. ++ * ++ */ ++static struct dahdi_span *span_find_and_get(int spanno) ++{ ++ struct dahdi_span *found; ++ ++ mutex_lock(®istration_mutex); ++ found = _find_span(spanno); ++ if (found && !get_span(found)) ++ found = NULL; ++ mutex_unlock(®istration_mutex); ++ return found; ++} ++ ++static unsigned int span_count(void) ++{ ++ unsigned int count = 0; ++ struct dahdi_span *s; ++ unsigned long flags; ++ spin_lock_irqsave(&chan_lock, flags); ++ list_for_each_entry(s, &span_list, spans_node) ++ ++count; ++ spin_unlock_irqrestore(&chan_lock, flags); ++ return count; ++} ++ ++static inline bool can_provide_timing(const struct dahdi_span *const s) ++{ ++ return !s->cannot_provide_timing; ++} ++ ++static int maxconfs; ++ ++short __dahdi_mulaw[256]; ++short __dahdi_alaw[256]; ++ ++#ifndef CONFIG_CALC_XLAW ++u_char __dahdi_lin2mu[16384]; ++ ++u_char __dahdi_lin2a[16384]; ++#endif ++ ++static u_char defgain[256]; ++ ++#define NUM_SIGS 10 ++ ++static DEFINE_SPINLOCK(ecfactory_list_lock); ++ ++static LIST_HEAD(ecfactory_list); ++ ++struct ecfactory { ++ const struct dahdi_echocan_factory *ec; ++ struct list_head list; ++}; ++ ++int dahdi_register_echocan_factory(const struct dahdi_echocan_factory *ec) ++{ ++ struct ecfactory *cur; ++ struct ecfactory *new; ++ ++ WARN_ON(!ec->owner); ++ ++ new = kzalloc(sizeof(*new), GFP_KERNEL); ++ if (!new) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&new->list); ++ ++ spin_lock(&ecfactory_list_lock); ++ ++ /* make sure it isn't already registered */ ++ list_for_each_entry(cur, &ecfactory_list, list) { ++ if (cur->ec == ec) { ++ spin_unlock(&ecfactory_list_lock); ++ kfree(new); ++ return -EPERM; ++ } ++ } ++ ++ new->ec = ec; ++ list_add_tail(&new->list, &ecfactory_list); ++ ++ spin_unlock(&ecfactory_list_lock); ++ ++ return 0; ++} ++ ++void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec) ++{ ++ struct ecfactory *cur, *next; ++ ++ spin_lock(&ecfactory_list_lock); ++ ++ list_for_each_entry_safe(cur, next, &ecfactory_list, list) { ++ if (cur->ec == ec) { ++ list_del(&cur->list); ++ kfree(cur); ++ break; ++ } ++ } ++ ++ spin_unlock(&ecfactory_list_lock); ++} ++ ++/* Is this span our syncronization master? */ ++int dahdi_is_sync_master(const struct dahdi_span *span) ++{ ++ return span == master_span; ++} ++ ++static inline void rotate_sums(void) ++{ ++ /* Rotate where we sum and so forth */ ++ static int pos = 0; ++ conf_sums_prev = sums + (DAHDI_MAX_CONF + 1) * pos; ++ conf_sums = sums + (DAHDI_MAX_CONF + 1) * ((pos + 1) % 3); ++ conf_sums_next = sums + (DAHDI_MAX_CONF + 1) * ((pos + 2) % 3); ++ pos = (pos + 1) % 3; ++ memset(conf_sums_next, 0, maxconfs * sizeof(sumtype)); ++} ++ ++/** ++ * is_chan_dacsed() - True if chan is sourcing it's data from another channel. ++ * ++ */ ++static inline bool is_chan_dacsed(const struct dahdi_chan *const chan) ++{ ++ return (NULL != chan->dacs_chan); ++} ++ ++/** ++ * can_dacs_chans() - Returns true if it may be possible to dacs two channels. ++ * ++ */ ++static bool can_dacs_chans(struct dahdi_chan *dst, struct dahdi_chan *src) ++{ ++ if (src && dst && src->span && dst->span && src->span->ops && ++ dst->span->ops && src->span->ops->dacs && ++ (src->span->ops->dacs == dst->span->ops->dacs)) ++ return true; ++ else ++ return false; ++} ++ ++/** ++ * dahdi_chan_dacs() - Cross (or uncross) connect two channels. ++ * @dst: Channel on which to transmit the src data. ++ * @src: NULL to disable cross connect, otherwise the source of the ++ * data. ++ * ++ * This allows those boards that support it to cross connect one channel to ++ * another in hardware. If the cards cannot be crossed, uncross the ++ * destination channel by default.. ++ * ++ */ ++static int dahdi_chan_dacs(struct dahdi_chan *dst, struct dahdi_chan *src) ++{ ++ int ret = 0; ++ if (can_dacs_chans(dst, src)) ++ ret = dst->span->ops->dacs(dst, src); ++ else if (dst->span && dst->span->ops->dacs) ++ ret = dst->span->ops->dacs(dst, NULL); ++ return ret; ++} ++ ++static void dahdi_disable_dacs(struct dahdi_chan *chan) ++{ ++ dahdi_chan_dacs(chan, NULL); ++} ++ ++/*! ++ * \return quiescent (idle) signalling states, for the various signalling types ++ */ ++static int dahdi_q_sig(struct dahdi_chan *chan) ++{ ++ int x; ++ static const unsigned int in_sig[NUM_SIGS][2] = { ++ { DAHDI_SIG_NONE, 0 }, ++ { DAHDI_SIG_EM, (DAHDI_ABIT << 8) }, ++ { DAHDI_SIG_FXSLS, DAHDI_BBIT | (DAHDI_BBIT << 8) }, ++ { DAHDI_SIG_FXSGS, DAHDI_ABIT | DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8) }, ++ { DAHDI_SIG_FXSKS, DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8) }, ++ { DAHDI_SIG_FXOLS, (DAHDI_ABIT << 8) }, ++ { DAHDI_SIG_FXOGS, DAHDI_BBIT | ((DAHDI_ABIT | DAHDI_BBIT) << 8) }, ++ { DAHDI_SIG_FXOKS, (DAHDI_ABIT << 8) }, ++ { DAHDI_SIG_SF, 0 }, ++ { DAHDI_SIG_EM_E1, DAHDI_DBIT | ((DAHDI_ABIT | DAHDI_DBIT) << 8) }, ++ }; ++ ++ /* must have span to begin with */ ++ if (!chan->span) ++ return -1; ++ ++ /* if RBS does not apply, return error */ ++ if (!(chan->span->flags & DAHDI_FLAG_RBS) || !chan->span->ops->rbsbits) ++ return -1; ++ ++ if (chan->sig == DAHDI_SIG_CAS) ++ return chan->idlebits; ++ ++ for (x = 0; x < NUM_SIGS; x++) { ++ if (in_sig[x][0] == chan->sig) ++ return in_sig[x][1]; ++ } ++ ++ return -1; /* not found -- error */ ++} ++ ++enum spantypes dahdi_str2spantype(const char *name) ++{ ++ if (strcasecmp("FXS", name) == 0) ++ return SPANTYPE_ANALOG_FXS; ++ else if (strcasecmp("FXO", name) == 0) ++ return SPANTYPE_ANALOG_FXO; ++ else if (strcasecmp("ANALOG_MIXED", name) == 0) ++ return SPANTYPE_ANALOG_MIXED; ++ else if (strcasecmp("E1", name) == 0) ++ return SPANTYPE_DIGITAL_E1; ++ else if (strcasecmp("T1", name) == 0) ++ return SPANTYPE_DIGITAL_T1; ++ else if (strcasecmp("J1", name) == 0) ++ return SPANTYPE_DIGITAL_J1; ++ else if (strcasecmp("BRI_NT", name) == 0) ++ return SPANTYPE_DIGITAL_BRI_NT; ++ else if (strcasecmp("BRI_TE", name) == 0) ++ return SPANTYPE_DIGITAL_BRI_TE; ++ else if (strcasecmp("BRI_SOFT", name) == 0) ++ return SPANTYPE_DIGITAL_BRI_SOFT; ++ else if (strcasecmp("DYNAMIC", name) == 0) ++ return SPANTYPE_DIGITAL_DYNAMIC; ++ else ++ return SPANTYPE_INVALID; ++} ++EXPORT_SYMBOL(dahdi_str2spantype); ++ ++const char *dahdi_spantype2str(enum spantypes st) ++{ ++ switch (st) { ++ case SPANTYPE_ANALOG_FXS: return "FXS"; ++ case SPANTYPE_ANALOG_FXO: return "FXO"; ++ case SPANTYPE_ANALOG_MIXED: return "ANALOG_MIXED"; ++ case SPANTYPE_DIGITAL_E1: return "E1"; ++ case SPANTYPE_DIGITAL_T1: return "T1"; ++ case SPANTYPE_DIGITAL_J1: return "J1"; ++ case SPANTYPE_DIGITAL_BRI_NT: return "BRI_NT"; ++ case SPANTYPE_DIGITAL_BRI_TE: return "BRI_TE"; ++ case SPANTYPE_DIGITAL_BRI_SOFT: return "BRI_SOFT"; ++ case SPANTYPE_DIGITAL_DYNAMIC: return "DYNAMIC"; ++ default: ++ case SPANTYPE_INVALID: return "INVALID"; ++ }; ++} ++EXPORT_SYMBOL(dahdi_spantype2str); ++ ++ ++const char *dahdi_lineconfig_bit_name(int lineconfig_bit) ++{ ++ static const char * const table[] = { ++ /* These apply to T1 */ ++ [4] = "D4", ++ [5] = "ESF", ++ [6] = "AMI", ++ [7] = "B8ZS", ++ /* These apply to E1 */ ++ [8] = "CCS", ++ [9] = "HDB3", ++ [10] = "CRC4", ++ /* These apply to BRI */ ++ [11] = "NTTE", ++ [12] = "TERM", ++ /* Finish */ ++ [16] = "NOTOPEN", ++ }; ++ if (lineconfig_bit < 0 || lineconfig_bit >= ARRAY_SIZE(table)) ++ return NULL; ++ return table[lineconfig_bit]; ++} ++EXPORT_SYMBOL(dahdi_lineconfig_bit_name); ++ ++ssize_t lineconfig_str(int lineconfig, char buf[], size_t size) ++{ ++ int framing_bit = 0; ++ int coding_bit = 0; ++ int crc4_bit = 0; ++ int len = 0; ++ int bit; ++ bool written = false; ++ ++ for (bit = 4; bit <= 12; bit++) { ++ int mask = (1 << bit); ++ if (!(lineconfig & mask)) ++ continue; ++ if (!framing_bit) { ++ switch (mask) { ++ case DAHDI_CONFIG_B8ZS: ++ case DAHDI_CONFIG_AMI: ++ case DAHDI_CONFIG_HDB3: ++ framing_bit = bit; ++ len += snprintf(buf + len, size, "%s%s", ++ (written) ? "/" : "", ++ dahdi_lineconfig_bit_name(bit)); ++ written = true; ++ } ++ } ++ if (!coding_bit) { ++ switch (mask) { ++ case DAHDI_CONFIG_ESF: ++ case DAHDI_CONFIG_D4: ++ case DAHDI_CONFIG_CCS: ++ coding_bit = bit; ++ len += snprintf(buf + len, size, "%s%s", ++ (written) ? "/" : "", ++ dahdi_lineconfig_bit_name(bit)); ++ written = true; ++ } ++ } ++ if (!crc4_bit && mask == DAHDI_CONFIG_CRC4) { ++ crc4_bit = bit; ++ len += snprintf(buf + len, size, "%s%s", ++ (written) ? "/" : "", ++ dahdi_lineconfig_bit_name(bit)); ++ written = true; ++ } ++ } ++ return len; ++} ++EXPORT_SYMBOL(lineconfig_str); ++ ++#ifdef CONFIG_PROC_FS ++const char *sigstr(int sig) ++{ ++ switch (sig) { ++ case DAHDI_SIG_FXSLS: ++ return "FXSLS"; ++ case DAHDI_SIG_FXSKS: ++ return "FXSKS"; ++ case DAHDI_SIG_FXSGS: ++ return "FXSGS"; ++ case DAHDI_SIG_FXOLS: ++ return "FXOLS"; ++ case DAHDI_SIG_FXOKS: ++ return "FXOKS"; ++ case DAHDI_SIG_FXOGS: ++ return "FXOGS"; ++ case DAHDI_SIG_EM: ++ return "E&M"; ++ case DAHDI_SIG_EM_E1: ++ return "E&M-E1"; ++ case DAHDI_SIG_CLEAR: ++ return "Clear"; ++ case DAHDI_SIG_HDLCRAW: ++ return "HDLCRAW"; ++ case DAHDI_SIG_HDLCFCS: ++ return "HDLCFCS"; ++ case DAHDI_SIG_HDLCNET: ++ return "HDLCNET"; ++ case DAHDI_SIG_HARDHDLC: ++ return "Hardware-assisted HDLC"; ++ case DAHDI_SIG_MTP2: ++ return "MTP2"; ++ case DAHDI_SIG_SLAVE: ++ return "Slave"; ++ case DAHDI_SIG_CAS: ++ return "CAS"; ++ case DAHDI_SIG_DACS: ++ return "DACS"; ++ case DAHDI_SIG_DACS_RBS: ++ return "DACS+RBS"; ++ case DAHDI_SIG_SF: ++ return "SF (ToneOnly)"; ++ case DAHDI_SIG_NONE: ++ default: ++ return "Unconfigured"; ++ } ++} ++ ++int fill_alarm_string(char *buf, int count, int alarms) ++{ ++ int len; ++ ++ if (alarms <= 0) ++ return 0; ++ ++ len = snprintf(buf, count, "%s%s%s%s%s%s", ++ (alarms & DAHDI_ALARM_BLUE) ? "BLUE " : "", ++ (alarms & DAHDI_ALARM_YELLOW) ? "YELLOW " : "", ++ (alarms & DAHDI_ALARM_RED) ? "RED " : "", ++ (alarms & DAHDI_ALARM_LOOPBACK) ? "LOOP " : "", ++ (alarms & DAHDI_ALARM_RECOVER) ? "RECOVERING " : "", ++ (alarms & DAHDI_ALARM_NOTOPEN) ? "NOTOPEN " : ""); ++ ++ return len; ++} ++ ++/* ++ * Sequential proc interface ++ */ ++ ++static void seq_fill_alarm_string(struct seq_file *sfile, int alarms) ++{ ++ char tmp[70]; ++ ++ if (fill_alarm_string(tmp, sizeof(tmp), alarms)) ++ seq_printf(sfile, "%s", tmp); ++} ++ ++static int dahdi_seq_show(struct seq_file *sfile, void *data) ++{ ++ long spanno = (long)sfile->private; ++ int x; ++ struct dahdi_span *s; ++ ++ s = span_find_and_get(spanno); ++ if (!s) ++ return -ENODEV; ++ ++ if (s->name) ++ seq_printf(sfile, "Span %d: %s ", s->spanno, s->name); ++ if (s->desc) ++ seq_printf(sfile, "\"%s\"", s->desc); ++ else ++ seq_printf(sfile, "\"\""); ++ ++ if (dahdi_is_sync_master(s)) ++ seq_printf(sfile, " (MASTER)"); ++ ++ if (s->lineconfig) { ++ char tmpbuf[20]; ++ lineconfig_str(s->lineconfig, tmpbuf, sizeof(tmpbuf)); ++ seq_printf(sfile, " %s", tmpbuf); ++ } ++ ++ seq_printf(sfile, " "); ++ ++ /* list alarms */ ++ seq_fill_alarm_string(sfile, s->alarms); ++ if (s->syncsrc && ++ (s->syncsrc == s->spanno)) ++ seq_printf(sfile, "ClockSource "); ++ seq_printf(sfile, "\n"); ++ if (s->count.bpv) ++ seq_printf(sfile, "\tBPV count: %d\n", s->count.bpv); ++ if (s->count.crc4) ++ seq_printf(sfile, "\tCRC4 error count: %d\n", s->count.crc4); ++ if (s->count.ebit) ++ seq_printf(sfile, "\tE-bit error count: %d\n", s->count.ebit); ++ if (s->count.fas) ++ seq_printf(sfile, "\tFAS error count: %d\n", s->count.fas); ++ if (s->parent->irqmisses) ++ seq_printf(sfile, "\tIRQ misses: %d\n", s->parent->irqmisses); ++ if (s->count.timingslips) ++ seq_printf(sfile, "\tTiming slips: %d\n", s->count.timingslips); ++ seq_printf(sfile, "\n"); ++ ++ for (x = 0; x < s->channels; x++) { ++ struct dahdi_chan *chan = s->chans[x]; ++ ++ if (chan->name) ++ seq_printf(sfile, "\t%4d %s ", chan->channo, ++ chan->name); ++ ++ if (chan->sig) { ++ if (chan->sig == DAHDI_SIG_SLAVE) ++ seq_printf(sfile, "%s ", ++ sigstr(chan->master->sig)); ++ else { ++ seq_printf(sfile, "%s ", sigstr(chan->sig)); ++ if (chan->nextslave && ++ (chan->master->channo == chan->channo)) ++ seq_printf(sfile, "Master "); ++ } ++ } else if (!chan->sigcap) { ++ seq_printf(sfile, "Reserved "); ++ } ++ ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) ++ seq_printf(sfile, "(In use) "); ++ ++#ifdef OPTIMIZE_CHANMUTE ++ if (chan->chanmute) ++ seq_printf(sfile, "(no pcm) "); ++#endif ++ ++ seq_fill_alarm_string(sfile, chan->chan_alarms); ++ ++ mutex_lock(&chan->mutex); ++ if (chan->ec_factory) { ++ seq_printf(sfile, "(EC: %s - %s) ", ++ chan->ec_factory->get_name(chan), ++ chan->ec_state ? "ACTIVE" : "INACTIVE"); ++ } ++ mutex_unlock(&chan->mutex); ++ ++ seq_printf(sfile, "\n"); ++ } ++ put_span(s); ++ return 0; ++} ++ ++static int dahdi_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dahdi_seq_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops dahdi_proc_ops = { ++ .proc_open = dahdi_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations dahdi_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = dahdi_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++#endif ++ ++static int dahdi_first_empty_alias(void) ++{ ++ /* Find the first conference which has no alias pointing to it */ ++ int x; ++ for (x=1;x 0; x--) { ++ if (confrev[x]) { ++ maxconfs = x + 1; ++ return; ++ } ++ } ++ ++ maxconfs = 0; ++} ++ ++static int dahdi_first_empty_conference(void) ++{ ++ /* Find the first conference which has no alias */ ++ int x; ++ ++ for (x = DAHDI_MAX_CONF - 1; x > 0; x--) { ++ if (!confalias[x]) ++ return x; ++ } ++ ++ return -1; ++} ++ ++static int dahdi_get_conf_alias(int x) ++{ ++ int a; ++ ++ if (confalias[x]) ++ return confalias[x]; ++ ++ /* Allocate an alias */ ++ a = dahdi_first_empty_alias(); ++ confalias[x] = a; ++ confrev[a] = x; ++ ++ /* Highest conference may have changed */ ++ recalc_maxconfs(); ++ ++ return a; ++} ++ ++static unsigned long _chan_in_conf(struct dahdi_chan *chan, unsigned long x) ++{ ++ const int confmode = chan->confmode & DAHDI_CONF_MODE_MASK; ++ return (chan && (chan->confna == x) && ++ (confmode == DAHDI_CONF_CONF || ++ confmode == DAHDI_CONF_CONFANN || ++ confmode == DAHDI_CONF_CONFMON || ++ confmode == DAHDI_CONF_CONFANNMON || ++ confmode == DAHDI_CONF_REALANDPSEUDO)) ? 1 : 0; ++} ++ ++#ifdef CONFIG_DAHDI_CONFLINK ++static void recalc_maxlinks(void) ++{ ++ int x; ++ ++ for (x = DAHDI_MAX_CONF - 1; x > 0; x--) { ++ if (conf_links[x].src || conf_links[x].dst) { ++ maxlinks = x + 1; ++ return; ++ } ++ } ++ ++ maxlinks = 0; ++} ++#endif ++ ++static void dahdi_check_conf(int x) ++{ ++ unsigned long res; ++ unsigned long flags; ++#ifdef CONFIG_DAHDI_CONFLINK ++ int i; ++#endif ++ ++ /* return if no valid conf number */ ++ if (x <= 0) ++ return; ++ ++ /* Return if there is no alias */ ++ if (!confalias[x]) ++ return; ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ res = __for_each_channel(_chan_in_conf, x); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ if (res) ++ return; ++ ++ /* If we get here, nobody is in the conference anymore. Clear it out ++ both forward and reverse */ ++ confrev[confalias[x]] = 0; ++ confalias[x] = 0; ++ ++ /* Highest conference may have changed */ ++ recalc_maxconfs(); ++ ++#ifdef CONFIG_DAHDI_CONFLINK ++ /* And unlink it from any conflinks */ ++ for (i = DAHDI_MAX_CONF - 1; i > 0; i--) { ++ if (conf_links[i].src == x) ++ conf_links[i].src = 0; ++ if (conf_links[i].dst == x) ++ conf_links[i].dst = 0; ++ } ++ recalc_maxlinks(); ++#endif ++} ++ ++/* enqueue an event on a channel */ ++static void __qevent(struct dahdi_chan *chan, int event) ++{ ++ /* if full, ignore */ ++ if ((chan->eventoutidx == 0) && (chan->eventinidx == (DAHDI_MAX_EVENTSIZE - 1))) ++ return; ++ ++ /* if full, ignore */ ++ if (chan->eventinidx == (chan->eventoutidx - 1)) ++ return; ++ ++ /* save the event */ ++ chan->eventbuf[chan->eventinidx++] = event; ++ ++ /* wrap the index, if necessary */ ++ if (chan->eventinidx >= DAHDI_MAX_EVENTSIZE) ++ chan->eventinidx = 0; ++ ++ /* wake em all up */ ++ wake_up_interruptible(&chan->waitq); ++ ++ return; ++} ++ ++void dahdi_qevent_nolock(struct dahdi_chan *chan, int event) ++{ ++ __qevent(chan, event); ++} ++ ++void dahdi_qevent_lock(struct dahdi_chan *chan, int event) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&chan->lock, flags); ++ __qevent(chan, event); ++ spin_unlock_irqrestore(&chan->lock, flags); ++} ++ ++static inline void calc_fcs(struct dahdi_chan *ss, int inwritebuf) ++{ ++ int x; ++ unsigned int fcs = PPP_INITFCS; ++ unsigned char *data = ss->writebuf[inwritebuf]; ++ int len = ss->writen[inwritebuf]; ++ ++ /* Not enough space to do FCS calculation */ ++ if (len < 2) ++ return; ++ ++ for (x = 0; x < len - 2; x++) ++ fcs = PPP_FCS(fcs, data[x]); ++ ++ fcs ^= 0xffff; ++ /* Send out the FCS */ ++ data[len - 2] = (fcs & 0xff); ++ data[len - 1] = (fcs >> 8) & 0xff; ++} ++ ++static int dahdi_reallocbufs(struct dahdi_chan *ss, int blocksize, int numbufs) ++{ ++ unsigned char *newtxbuf = NULL; ++ unsigned char *newrxbuf = NULL; ++ unsigned char *oldtxbuf = NULL; ++ unsigned char *oldrxbuf = NULL; ++ unsigned long flags; ++ int x; ++ ++ /* Check numbufs */ ++ if (numbufs < 2) ++ numbufs = 2; ++ ++ if (numbufs > DAHDI_MAX_NUM_BUFS) ++ numbufs = DAHDI_MAX_NUM_BUFS; ++ ++ /* We need to allocate our buffers now */ ++ if (blocksize) { ++ newtxbuf = kzalloc(blocksize * numbufs, GFP_KERNEL); ++ if (NULL == newtxbuf) ++ return -ENOMEM; ++ newrxbuf = kzalloc(blocksize * numbufs, GFP_KERNEL); ++ if (NULL == newrxbuf) { ++ kfree(newtxbuf); ++ return -ENOMEM; ++ } ++ } ++ ++ /* Now that we've allocated our new buffers, we can safely ++ move things around... */ ++ ++ spin_lock_irqsave(&ss->lock, flags); ++ ++ ss->blocksize = blocksize; /* set the blocksize */ ++ oldrxbuf = ss->readbuf[0]; /* Keep track of the old buffer */ ++ oldtxbuf = ss->writebuf[0]; ++ ss->readbuf[0] = NULL; ++ ++ if (newrxbuf) { ++ BUG_ON(NULL == newtxbuf); ++ for (x = 0; x < numbufs; x++) { ++ ss->readbuf[x] = newrxbuf + x * blocksize; ++ ss->writebuf[x] = newtxbuf + x * blocksize; ++ } ++ } else { ++ for (x = 0; x < numbufs; x++) { ++ ss->readbuf[x] = NULL; ++ ss->writebuf[x] = NULL; ++ } ++ } ++ ++ /* Mark all buffers as empty */ ++ for (x = 0; x < numbufs; x++) { ++ ss->writen[x] = ++ ss->writeidx[x]= ++ ss->readn[x]= ++ ss->readidx[x] = 0; ++ } ++ ++ /* Keep track of where our data goes (if it goes ++ anywhere at all) */ ++ if (newrxbuf) { ++ ss->inreadbuf = 0; ++ ss->inwritebuf = 0; ++ } else { ++ ss->inreadbuf = -1; ++ ss->inwritebuf = -1; ++ } ++ ++ ss->outreadbuf = -1; ++ ss->outwritebuf = -1; ++ ss->numbufs = numbufs; ++ ++ if ((ss->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || (ss->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ++ ss->txdisable = 1; ++ else ++ ss->txdisable = 0; ++ ++ spin_unlock_irqrestore(&ss->lock, flags); ++ ++ kfree(oldtxbuf); ++ kfree(oldrxbuf); ++ ++ return 0; ++} ++ ++static int dahdi_hangup(struct dahdi_chan *chan); ++static void dahdi_set_law(struct dahdi_chan *chan, int law); ++ ++/* Pull a DAHDI_CHUNKSIZE piece off the queue. Returns ++ 0 on success or -1 on failure. If failed, provides ++ silence */ ++static int __buf_pull(struct confq *q, u_char *data, struct dahdi_chan *c) ++{ ++ int oldoutbuf = q->outbuf; ++ /* Ain't nuffin to read */ ++ if (q->outbuf < 0) { ++ if (data) ++ memset(data, DAHDI_LIN2X(0,c), DAHDI_CHUNKSIZE); ++ return -1; ++ } ++ if (data) ++ memcpy(data, q->buf[q->outbuf], DAHDI_CHUNKSIZE); ++ q->outbuf = (q->outbuf + 1) % DAHDI_CB_SIZE; ++ ++ /* Won't be nuffin next time */ ++ if (q->outbuf == q->inbuf) { ++ q->outbuf = -1; ++ } ++ ++ /* If they thought there was no space then ++ there is now where we just read */ ++ if (q->inbuf < 0) ++ q->inbuf = oldoutbuf; ++ return 0; ++} ++ ++/* Returns a place to put stuff, or NULL if there is ++ no room */ ++ ++static u_char *__buf_pushpeek(struct confq *q) ++{ ++ if (q->inbuf < 0) ++ return NULL; ++ return q->buf[q->inbuf]; ++} ++ ++static u_char *__buf_peek(struct confq *q) ++{ ++ if (q->outbuf < 0) ++ return NULL; ++ return q->buf[q->outbuf]; ++} ++ ++/* Push something onto the queue, or assume what ++ is there is valid if data is NULL */ ++static int __buf_push(struct confq *q, const u_char *data) ++{ ++ int oldinbuf = q->inbuf; ++ if (q->inbuf < 0) { ++ return -1; ++ } ++ if (data) ++ /* Copy in the data */ ++ memcpy(q->buf[q->inbuf], data, DAHDI_CHUNKSIZE); ++ ++ /* Advance the inbuf pointer */ ++ q->inbuf = (q->inbuf + 1) % DAHDI_CB_SIZE; ++ ++ if (q->inbuf == q->outbuf) { ++ /* No space anymore... */ ++ q->inbuf = -1; ++ } ++ /* If they don't think data is ready, let ++ them know it is now */ ++ if (q->outbuf < 0) { ++ q->outbuf = oldinbuf; ++ } ++ return 0; ++} ++ ++static void reset_conf(struct dahdi_chan *chan) ++{ ++ int x; ++ ++ /* Empty out buffers and reset to initialization */ ++ ++ for (x = 0; x < DAHDI_CB_SIZE; x++) ++ chan->confin.buf[x] = chan->confin.buffer + DAHDI_CHUNKSIZE * x; ++ ++ chan->confin.inbuf = 0; ++ chan->confin.outbuf = -1; ++ ++ for (x = 0; x < DAHDI_CB_SIZE; x++) ++ chan->confout.buf[x] = chan->confout.buffer + DAHDI_CHUNKSIZE * x; ++ ++ chan->confout.inbuf = 0; ++ chan->confout.outbuf = -1; ++} ++ ++ ++static const struct dahdi_echocan_factory *find_echocan(const char *name) ++{ ++ struct ecfactory *cur; ++ char *name_upper; ++ char *c; ++ const char *d; ++ char modname_buf[128] = "dahdi_echocan_"; ++ unsigned int tried_once = 0; ++ ++ name_upper = kmalloc(strlen(name) + 1, GFP_KERNEL); ++ if (!name_upper) ++ return NULL; ++ ++ for (c = name_upper, d = name; *d; c++, d++) { ++ *c = toupper(*d); ++ } ++ ++ *c = '\0'; ++ ++retry: ++ spin_lock(&ecfactory_list_lock); ++ ++ list_for_each_entry(cur, &ecfactory_list, list) { ++ if (!strcmp(name_upper, cur->ec->get_name(NULL))) { ++ if (try_module_get(cur->ec->owner)) { ++ spin_unlock(&ecfactory_list_lock); ++ kfree(name_upper); ++ return cur->ec; ++ } else { ++ spin_unlock(&ecfactory_list_lock); ++ kfree(name_upper); ++ return NULL; ++ } ++ } ++ } ++ ++ spin_unlock(&ecfactory_list_lock); ++ ++ if (tried_once) { ++ kfree(name_upper); ++ return NULL; ++ } ++ ++ /* couldn't find it, let's try to load it */ ++ ++ for (c = &modname_buf[strlen(modname_buf)], d = name; *d; c++, d++) { ++ *c = tolower(*d); ++ } ++ ++ request_module("%s", modname_buf); ++ ++ tried_once = 1; ++ ++ /* and try one more time */ ++ goto retry; ++} ++ ++static void release_echocan(const struct dahdi_echocan_factory *ec) ++{ ++ if (ec) ++ module_put(ec->owner); ++} ++ ++/** ++ * is_gain_allocated() - True if gain tables were dynamically allocated. ++ * @chan: The channel to check. ++ */ ++static inline bool is_gain_allocated(const struct dahdi_chan *chan) ++{ ++ return (chan->rxgain && (chan->rxgain != defgain)); ++} ++ ++static const char *hwec_def_name = "HWEC"; ++static const char *hwec_get_name(const struct dahdi_chan *chan) ++{ ++ if (chan && chan->span && chan->span->ops->echocan_name) ++ return chan->span->ops->echocan_name(chan); ++ else ++ return hwec_def_name; ++} ++ ++static int hwec_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ if (chan->span && chan->span->ops->echocan_create) ++ return chan->span->ops->echocan_create(chan, ecp, p, ec); ++ else ++ return -ENODEV; ++} ++ ++static const struct dahdi_echocan_factory hwec_factory = { ++ .get_name = hwec_get_name, ++ .owner = THIS_MODULE, ++ .echocan_create = hwec_echocan_create, ++}; ++ ++/** ++ * dahdi_enable_hw_preechocan - Let the board driver enable hwpreec if possible. ++ * @chan: The channel to monitor. ++ * ++ * Returns 0 on success, if there is a software echocanceler attached on ++ * the channel, or the span does not have an enable_hw_preechocan callback. ++ * Otherwise an error code. ++ * ++ */ ++static int dahdi_enable_hw_preechocan(struct dahdi_chan *chan) ++{ ++ int res; ++ ++ mutex_lock(&chan->mutex); ++ if (chan->ec_factory != &hwec_factory) ++ res = -ENODEV; ++ else ++ res = 0; ++ mutex_unlock(&chan->mutex); ++ ++ if (-ENODEV == res) ++ return 0; ++ ++ if (chan->span->ops->enable_hw_preechocan) ++ return chan->span->ops->enable_hw_preechocan(chan); ++ else ++ return 0; ++} ++ ++/** ++ * dahdi_disable_hw_preechocan - Disable any hardware pre echocan monitoring. ++ * @chan: The channel to stop monitoring. ++ * ++ * Give the board driver the option to free any resources needed to monitor ++ * the preechocan stream. ++ * ++ */ ++static void dahdi_disable_hw_preechocan(struct dahdi_chan *chan) ++{ ++ if (chan->span->ops->disable_hw_preechocan) ++ chan->span->ops->disable_hw_preechocan(chan); ++} ++ ++/* ++ * close_channel - close the channel, resetting any channel variables ++ * @chan: the dahdi_chan to close ++ * ++ * This function is called before either the parent span is linked into the ++ * span list, or for pseudos, place on the psuedo_list. Therefore, this ++ * function nor it's callers should depend on the channel being findable ++ * via those methods. ++ */ ++static void close_channel(struct dahdi_chan *chan) ++{ ++ unsigned long flags; ++ const void *rxgain = NULL; ++ struct dahdi_echocan_state *ec_state; ++ const struct dahdi_echocan_factory *ec_current; ++ int oldconf; ++ short *readchunkpreec; ++#ifdef CONFIG_DAHDI_PPP ++ struct ppp_channel *ppp; ++#endif ++ ++ might_sleep(); ++ ++ if (chan->conf_chan && ++ ((DAHDI_CONF_MONITOR_RX_PREECHO == chan->confmode) || ++ (DAHDI_CONF_MONITOR_TX_PREECHO == chan->confmode) || ++ (DAHDI_CONF_MONITORBOTH_PREECHO == chan->confmode))) { ++ void *readchunkpreec; ++ ++ spin_lock_irqsave(&chan->conf_chan->lock, flags); ++ readchunkpreec = chan->conf_chan->readchunkpreec; ++ chan->conf_chan->readchunkpreec = NULL; ++ spin_unlock_irqrestore(&chan->conf_chan->lock, flags); ++ ++ if (readchunkpreec) { ++ dahdi_disable_hw_preechocan(chan->conf_chan); ++ kfree(readchunkpreec); ++ } ++ } ++ ++ /* XXX Buffers should be send out before reallocation!!! XXX */ ++ if (!(chan->flags & DAHDI_FLAG_NOSTDTXRX)) ++ dahdi_reallocbufs(chan, 0, 0); ++ spin_lock_irqsave(&chan->lock, flags); ++#ifdef CONFIG_DAHDI_PPP ++ ppp = chan->ppp; ++ chan->ppp = NULL; ++#endif ++ ec_state = chan->ec_state; ++ chan->ec_state = NULL; ++ ec_current = chan->ec_current; ++ chan->ec_current = NULL; ++ readchunkpreec = chan->readchunkpreec; ++ chan->readchunkpreec = NULL; ++ chan->curtone = NULL; ++ if (chan->curzone) { ++ struct dahdi_zone *zone = chan->curzone; ++ chan->curzone = NULL; ++ tone_zone_put(zone); ++ } ++ chan->cadencepos = 0; ++ chan->pdialcount = 0; ++ dahdi_hangup(chan); ++ chan->itimerset = chan->itimer = 0; ++ chan->pulsecount = 0; ++ chan->pulsetimer = 0; ++ chan->ringdebtimer = 0; ++ chan->txdialbuf[0] = '\0'; ++ chan->digitmode = DIGIT_MODE_DTMF; ++ chan->dialing = 0; ++ chan->afterdialingtimer = 0; ++ /* initialize IO MUX mask */ ++ chan->iomask = 0; ++ /* save old conf number, if any */ ++ oldconf = chan->confna; ++ /* initialize conference variables */ ++ chan->_confn = 0; ++ chan->confna = 0; ++ chan->confmode = 0; ++ if ((chan->sig & __DAHDI_SIG_DACS) != __DAHDI_SIG_DACS) ++ chan->dacs_chan = NULL; ++ ++ chan->confmute = 0; ++ chan->gotgs = 0; ++ reset_conf(chan); ++ chan->dacs_chan = NULL; ++ ++ if (is_gain_allocated(chan)) ++ rxgain = chan->rxgain; ++ ++ chan->rxgain = defgain; ++ chan->txgain = defgain; ++ chan->eventinidx = chan->eventoutidx = 0; ++ chan->flags &= ~(DAHDI_FLAG_LOOPED | DAHDI_FLAG_LINEAR | DAHDI_FLAG_PPP | DAHDI_FLAG_SIGFREEZE); ++ ++ dahdi_set_law(chan, DAHDI_LAW_DEFAULT); ++ ++ memset(chan->conflast, 0, sizeof(chan->conflast)); ++ memset(chan->conflast1, 0, sizeof(chan->conflast1)); ++ memset(chan->conflast2, 0, sizeof(chan->conflast2)); ++ ++ if (chan->span && oldconf) ++ dahdi_disable_dacs(chan); ++ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ if (ec_state) { ++ ec_state->ops->echocan_free(chan, ec_state); ++ release_echocan(ec_current); ++ } ++ ++ /* release conference resource, if any to release */ ++ if (oldconf) ++ dahdi_check_conf(oldconf); ++ ++ if (rxgain) ++ kfree(rxgain); ++ ++ if (readchunkpreec) { ++ dahdi_disable_hw_preechocan(chan); ++ kfree(readchunkpreec); ++ } ++ ++#ifdef CONFIG_DAHDI_PPP ++ if (ppp) { ++ tasklet_kill(&chan->ppp_calls); ++ skb_queue_purge(&chan->ppp_rq); ++ ppp_unregister_channel(ppp); ++ kfree(ppp); ++ } ++#endif ++ ++} ++ ++static int dahdi_ioctl_freezone(unsigned long data) ++{ ++ struct dahdi_zone *z; ++ struct dahdi_zone *found = NULL; ++ int num; ++ ++ if (get_user(num, (int __user *) data)) ++ return -EFAULT; ++ ++ spin_lock(&zone_lock); ++ list_for_each_entry(z, &tone_zones, node) { ++ if (z->num == num) { ++ found = z; ++ break; ++ } ++ } ++ if (found) { ++ list_del(&found->node); ++ } ++ spin_unlock(&zone_lock); ++ ++ if (found) { ++ if (debug) { ++ module_printk(KERN_INFO, ++ "Unregistering tone zone %d (%s)\n", ++ found->num, found->name); ++ } ++ tone_zone_put(found); ++ } ++ return 0; ++} ++ ++static int dahdi_register_tone_zone(struct dahdi_zone *zone) ++{ ++ struct dahdi_zone *cur; ++ int res = 0; ++ ++ kref_init(&zone->refcount); ++ spin_lock(&zone_lock); ++ list_for_each_entry(cur, &tone_zones, node) { ++ if (cur->num == zone->num) { ++ res = -EINVAL; ++ break; ++ } ++ } ++ if (!res) { ++ list_add_tail(&zone->node, &tone_zones); ++ if (debug) { ++ module_printk(KERN_INFO, ++ "Registered tone zone %d (%s)\n", ++ zone->num, zone->name); ++ } ++ } ++ spin_unlock(&zone_lock); ++ ++ return res; ++} ++ ++static int start_tone_digit(struct dahdi_chan *chan, int tone) ++{ ++ struct dahdi_tone *playtone = NULL; ++ int base, max; ++ ++ if (!chan->curzone) ++ return -ENODATA; ++ ++ switch (chan->digitmode) { ++ case DIGIT_MODE_DTMF: ++ /* Set dialing so that a dial operation doesn't interrupt this tone */ ++ chan->dialing = 1; ++ base = DAHDI_TONE_DTMF_BASE; ++ max = DAHDI_TONE_DTMF_MAX; ++ break; ++ case DIGIT_MODE_MFR2_FWD: ++ base = DAHDI_TONE_MFR2_FWD_BASE; ++ max = DAHDI_TONE_MFR2_FWD_MAX; ++ break; ++ case DIGIT_MODE_MFR2_REV: ++ base = DAHDI_TONE_MFR2_REV_BASE; ++ max = DAHDI_TONE_MFR2_REV_MAX; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if ((tone < base) || (tone > max)) ++ return -EINVAL; ++ ++ switch (chan->digitmode) { ++ case DIGIT_MODE_DTMF: ++ playtone = &chan->curzone->dtmf_continuous[tone - base]; ++ break; ++ case DIGIT_MODE_MFR2_FWD: ++ playtone = &chan->curzone->mfr2_fwd_continuous[tone - base]; ++ break; ++ case DIGIT_MODE_MFR2_REV: ++ playtone = &chan->curzone->mfr2_rev_continuous[tone - base]; ++ break; ++ } ++ ++ if (!playtone || !playtone->tonesamples) ++ return -ENOSYS; ++ ++ chan->curtone = playtone; ++ ++ return 0; ++} ++ ++static int start_tone(struct dahdi_chan *chan, int tone) ++{ ++ int res = -EINVAL; ++ ++ /* Stop the current tone, no matter what */ ++ chan->tonep = 0; ++ chan->curtone = NULL; ++ chan->pdialcount = 0; ++ chan->txdialbuf[0] = '\0'; ++ chan->dialing = 0; ++ ++ if (tone == -1) { ++ /* Just stop the current tone */ ++ res = 0; ++ } else if (!chan->curzone) { ++ static int __warnonce = 1; ++ if (__warnonce) { ++ __warnonce = 0; ++ /* The tonezones are loaded by dahdi_cfg based on /etc/dahdi/system.conf. */ ++ module_printk(KERN_WARNING, "DAHDI: Cannot start tones until tone zone is loaded.\n"); ++ } ++ /* Note that no tone zone exists at the moment */ ++ res = -ENODATA; ++ } else if ((tone >= 0 && tone <= DAHDI_TONE_MAX)) { ++ /* Have a tone zone */ ++ if (chan->curzone->tones[tone]) { ++ chan->curtone = chan->curzone->tones[tone]; ++ res = 0; ++ } else { /* Indicate that zone is loaded but no such tone exists */ ++ res = -ENOSYS; ++ } ++ } else if (chan->digitmode == DIGIT_MODE_DTMF || ++ chan->digitmode == DIGIT_MODE_MFR2_FWD || ++ chan->digitmode == DIGIT_MODE_MFR2_REV) { ++ res = start_tone_digit(chan, tone); ++ } else { ++ chan->dialing = 0; ++ res = -EINVAL; ++ } ++ ++ if (chan->curtone) ++ dahdi_init_tone_state(&chan->ts, chan->curtone); ++ ++ return res; ++} ++ ++/** ++ * stop_tone - Stops any tones on a channel. ++ * ++ * Must be called with chan->lock held. ++ * ++ */ ++static inline int stop_tone(struct dahdi_chan *chan) ++{ ++ return start_tone(chan, -1); ++} ++ ++static int set_tone_zone(struct dahdi_chan *chan, int zone) ++{ ++ int res = 0; ++ struct dahdi_zone *cur; ++ struct dahdi_zone *z; ++ unsigned long flags; ++ ++ z = NULL; ++ spin_lock(&zone_lock); ++ if ((DEFAULT_TONE_ZONE == zone) && !list_empty(&tone_zones)) { ++ z = list_entry(tone_zones.next, struct dahdi_zone, node); ++ tone_zone_get(z); ++ } else { ++ list_for_each_entry(cur, &tone_zones, node) { ++ if (cur->num != (u8)zone) ++ continue; ++ z = cur; ++ tone_zone_get(z); ++ break; ++ } ++ } ++ spin_unlock(&zone_lock); ++ ++ if (unlikely(!z)) ++ return -ENODATA; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ ++ stop_tone(chan); ++ ++ if (chan->curzone) { ++ struct dahdi_zone *zone = chan->curzone; ++ chan->curzone = NULL; ++ tone_zone_put(zone); ++ } ++ chan->curzone = z; ++ memcpy(chan->ringcadence, z->ringcadence, sizeof(chan->ringcadence)); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ return res; ++} ++ ++static void dahdi_set_law(struct dahdi_chan *chan, int law) ++{ ++ if (DAHDI_LAW_DEFAULT == law) { ++ if (chan->deflaw) ++ law = chan->deflaw; ++ else ++ if (chan->span) law = chan->span->deflaw; ++ else law = DAHDI_LAW_MULAW; ++ } ++ if (law == DAHDI_LAW_ALAW) { ++ chan->xlaw = __dahdi_alaw; ++#ifdef CONFIG_CALC_XLAW ++ chan->lineartoxlaw = __dahdi_lineartoalaw; ++#else ++ chan->lin2x = __dahdi_lin2a; ++#endif ++ } else { ++ chan->xlaw = __dahdi_mulaw; ++#ifdef CONFIG_CALC_XLAW ++ chan->lineartoxlaw = __dahdi_lineartoulaw; ++#else ++ chan->lin2x = __dahdi_lin2mu; ++#endif ++ } ++} ++ ++/** ++ * __dahdi_init_chan - Initialize the channel data structures. ++ * @chan: The channel to initialize ++ * ++ */ ++static void __dahdi_init_chan(struct dahdi_chan *chan) ++{ ++ might_sleep(); ++ ++ spin_lock_init(&chan->lock); ++ mutex_init(&chan->mutex); ++ init_waitqueue_head(&chan->waitq); ++ if (!chan->master) ++ chan->master = chan; ++ if (!chan->readchunk) ++ chan->readchunk = chan->sreadchunk; ++ if (!chan->writechunk) ++ chan->writechunk = chan->swritechunk; ++ chan->rxgain = NULL; ++ chan->txgain = NULL; ++ close_channel(chan); ++} ++ ++/** ++ * dahdi_chan_reg - Mark the channel registered. ++ * ++ * This must be called after close channel during registration, normally ++ * covered by the call to __dahdi_init_chan, to avoid "HDLC hangage" ++ */ ++static inline void dahdi_chan_reg(struct dahdi_chan *chan) ++{ ++ set_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags); ++} ++ ++/** ++ * dahdi_lboname() - Convert line build out number to string. ++ * ++ */ ++const char *dahdi_lboname(int lbo) ++{ ++ /* names of tx level settings */ ++ static const char *const dahdi_txlevelnames[] = { ++ "0 db (CSU)/0-133 feet (DSX-1)", ++ "133-266 feet (DSX-1)", ++ "266-399 feet (DSX-1)", ++ "399-533 feet (DSX-1)", ++ "533-655 feet (DSX-1)", ++ "-7.5db (CSU)", ++ "-15db (CSU)", ++ "-22.5db (CSU)" ++ }; ++ ++ if ((lbo < 0) || (lbo > 7)) ++ return "Unknown"; ++ return dahdi_txlevelnames[lbo]; ++} ++EXPORT_SYMBOL(dahdi_lboname); ++ ++#if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP) ++static inline void print_debug_writebuf(struct dahdi_chan* ss, struct sk_buff *skb, int oldbuf) ++{ ++#ifdef CONFIG_DAHDI_DEBUG ++ int x; ++ ++ module_printk(KERN_NOTICE, "Buffered %d bytes to go out in buffer %d\n", ss->writen[oldbuf], oldbuf); ++ module_printk(KERN_DEBUG ""); ++ for (x=0;xwriten[oldbuf];x++) ++ printk("%02x ", ss->writebuf[oldbuf][x]); ++ printk("\n"); ++#endif ++} ++#endif ++ ++#ifdef CONFIG_DAHDI_NET ++static inline struct net_device_stats *hdlc_stats(struct net_device *dev) ++{ ++ return &dev->stats; ++} ++ ++static int dahdi_net_open(struct net_device *dev) ++{ ++ int res = hdlc_open(dev); ++ struct dahdi_chan *ms = netdev_to_chan(dev); ++ ++/* if (!dev->hard_start_xmit) return res; is this really necessary? --byg */ ++ if (res) /* this is necessary to avoid kernel panic when UNSPEC link encap, proven --byg */ ++ return res; ++ ++ if (!ms) { ++ module_printk(KERN_NOTICE, "dahdi_net_open: nothing??\n"); ++ return -EINVAL; ++ } ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &ms->flags)) { ++ module_printk(KERN_NOTICE, "%s is already open!\n", ms->name); ++ return -EBUSY; ++ } ++ if (!dahdi_have_netdev(ms)) { ++ module_printk(KERN_NOTICE, "%s is not a net device!\n", ms->name); ++ return -EINVAL; ++ } ++ ms->txbufpolicy = DAHDI_POLICY_IMMEDIATE; ++ ++ res = dahdi_reallocbufs(ms, DAHDI_DEFAULT_MTU_MRU, DAHDI_DEFAULT_NUM_BUFS); ++ if (res) ++ return res; ++ ++ fasthdlc_init(&ms->rxhdlc, (ms->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ fasthdlc_init(&ms->txhdlc, (ms->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ ms->infcs = PPP_INITFCS; ++ ++ netif_start_queue(chan_to_netdev(ms)); ++ ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "DAHDINET: Opened channel %d name %s\n", ms->channo, ms->name); ++#endif ++ return 0; ++} ++ ++static int dahdi_register_hdlc_device(struct net_device *dev, const char *dev_name) ++{ ++ int result; ++ ++ if (dev_name && *dev_name) { ++ if ((result = dev_alloc_name(dev, dev_name)) < 0) ++ return result; ++ } ++ result = register_netdev(dev); ++ if (result != 0) ++ return -EIO; ++ return 0; ++} ++ ++static int dahdi_net_stop(struct net_device *dev) ++{ ++ hdlc_device *h = dev_to_hdlc(dev); ++ struct dahdi_hdlc *hdlc = h->priv; ++ ++ struct dahdi_chan *ms = hdlc_to_chan(hdlc); ++ if (!ms) { ++ module_printk(KERN_NOTICE, "dahdi_net_stop: nothing??\n"); ++ return 0; ++ } ++ if (!dahdi_have_netdev(ms)) { ++ module_printk(KERN_NOTICE, "dahdi_net_stop: %s is not a net device!\n", ms->name); ++ return 0; ++ } ++ /* Not much to do here. Just deallocate the buffers */ ++ netif_stop_queue(chan_to_netdev(ms)); ++ dahdi_reallocbufs(ms, 0, 0); ++ hdlc_close(dev); ++ return 0; ++} ++ ++/* kernel 2.4.20+ has introduced attach function, dunno what to do, ++ just copy sources from dscc4 to be sure and ready for further mastering, ++ NOOP right now (i.e. really a stub) --byg */ ++static int dahdi_net_attach(struct net_device *dev, unsigned short encoding, ++ unsigned short parity) ++{ ++/* struct net_device *dev = hdlc_to_dev(hdlc); ++ struct dscc4_dev_priv *dpriv = dscc4_priv(dev); ++ ++ if (encoding != ENCODING_NRZ && ++ encoding != ENCODING_NRZI && ++ encoding != ENCODING_FM_MARK && ++ encoding != ENCODING_FM_SPACE && ++ encoding != ENCODING_MANCHESTER) ++ return -EINVAL; ++ ++ if (parity != PARITY_NONE && ++ parity != PARITY_CRC16_PR0_CCITT && ++ parity != PARITY_CRC16_PR1_CCITT && ++ parity != PARITY_CRC32_PR0_CCITT && ++ parity != PARITY_CRC32_PR1_CCITT) ++ return -EINVAL; ++ ++ dpriv->encoding = encoding; ++ dpriv->parity = parity;*/ ++ return 0; ++} ++ ++static struct dahdi_hdlc *dahdi_hdlc_alloc(void) ++{ ++ return kzalloc(sizeof(struct dahdi_hdlc), GFP_KERNEL); ++} ++ ++static int dahdi_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ /* FIXME: this construction seems to be not very optimal for me but I ++ * could find nothing better at the moment (Friday, 10PM :( ) --byg ++ * */ ++ struct dahdi_chan *ss = netdev_to_chan(dev); ++ struct net_device_stats *stats = hdlc_stats(dev); ++ ++ int retval = 1; ++ int x,oldbuf; ++ unsigned int fcs; ++ unsigned char *data; ++ unsigned long flags; ++ /* See if we have any buffers */ ++ spin_lock_irqsave(&ss->lock, flags); ++ if (skb->len > ss->blocksize - 2) { ++ module_printk(KERN_ERR, "dahdi_xmit(%s): skb is too large (%d > %d)\n", dev->name, skb->len, ss->blocksize -2); ++ stats->tx_dropped++; ++ retval = 0; ++ } else if (ss->inwritebuf >= 0) { ++ /* We have a place to put this packet */ ++ /* XXX We should keep the SKB and avoid the memcpy XXX */ ++ data = ss->writebuf[ss->inwritebuf]; ++ memcpy(data, skb->data, skb->len); ++ ss->writen[ss->inwritebuf] = skb->len; ++ ss->writeidx[ss->inwritebuf] = 0; ++ /* Calculate the FCS */ ++ fcs = PPP_INITFCS; ++ for (x=0;xlen;x++) ++ fcs = PPP_FCS(fcs, data[x]); ++ /* Invert it */ ++ fcs ^= 0xffff; ++ /* Send it out LSB first */ ++ data[ss->writen[ss->inwritebuf]++] = (fcs & 0xff); ++ data[ss->writen[ss->inwritebuf]++] = (fcs >> 8) & 0xff; ++ /* Advance to next window */ ++ oldbuf = ss->inwritebuf; ++ ss->inwritebuf = (ss->inwritebuf + 1) % ss->numbufs; ++ ++ if (ss->inwritebuf == ss->outwritebuf) { ++ /* Whoops, no more space. */ ++ ss->inwritebuf = -1; ++ ++ netif_stop_queue(chan_to_netdev(ss)); ++ } ++ if (ss->outwritebuf < 0) { ++ /* Let the interrupt handler know there's ++ some space for us */ ++ ss->outwritebuf = oldbuf; ++ } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) ++ netif_trans_update(dev); ++#else ++ dev->trans_start = jiffies; ++#endif ++ stats->tx_packets++; ++ stats->tx_bytes += ss->writen[oldbuf]; ++ print_debug_writebuf(ss, skb, oldbuf); ++ retval = 0; ++ /* Free the SKB */ ++ dev_kfree_skb_any(skb); ++ } ++ spin_unlock_irqrestore(&ss->lock, flags); ++ return retval; ++} ++ ++static int dahdi_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ return hdlc_ioctl(dev, ifr, cmd); ++} ++ ++#endif ++ ++#ifdef CONFIG_DAHDI_PPP ++ ++static int dahdi_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb) ++{ ++ ++ /* ++ * If we can't handle the packet right now, return 0. If we ++ * we handle or drop it, return 1. Always free if we return ++ * 1 and never if we return 0 ++ */ ++ struct dahdi_chan *ss = ppp->private; ++ int x,oldbuf; ++ unsigned int fcs; ++ unsigned char *data; ++ unsigned long flags; ++ int retval = 0; ++ ++ /* See if we have any buffers */ ++ spin_lock_irqsave(&ss->lock, flags); ++ if (!(test_bit(DAHDI_FLAGBIT_OPEN, &ss->flags))) { ++ module_printk(KERN_ERR, "Can't transmit on closed channel\n"); ++ retval = 1; ++ } else if (skb->len > ss->blocksize - 4) { ++ module_printk(KERN_ERR, "dahdi_ppp_xmit(%s): skb is too large (%d > %d)\n", ss->name, skb->len, ss->blocksize -2); ++ retval = 1; ++ } else if (ss->inwritebuf >= 0) { ++ /* We have a place to put this packet */ ++ /* XXX We should keep the SKB and avoid the memcpy XXX */ ++ data = ss->writebuf[ss->inwritebuf]; ++ /* Start with header of two bytes */ ++ /* Add "ALL STATIONS" and "UNNUMBERED" */ ++ data[0] = 0xff; ++ data[1] = 0x03; ++ ss->writen[ss->inwritebuf] = 2; ++ ++ /* Copy real data and increment amount written */ ++ memcpy(data + 2, skb->data, skb->len); ++ ++ ss->writen[ss->inwritebuf] += skb->len; ++ ++ /* Re-set index back to zero */ ++ ss->writeidx[ss->inwritebuf] = 0; ++ ++ /* Calculate the FCS */ ++ fcs = PPP_INITFCS; ++ for (x=0;xlen + 2;x++) ++ fcs = PPP_FCS(fcs, data[x]); ++ /* Invert it */ ++ fcs ^= 0xffff; ++ ++ /* Point past the real data now */ ++ data += (skb->len + 2); ++ ++ /* Send FCS out LSB first */ ++ data[0] = (fcs & 0xff); ++ data[1] = (fcs >> 8) & 0xff; ++ ++ /* Account for FCS length */ ++ ss->writen[ss->inwritebuf]+=2; ++ ++ /* Advance to next window */ ++ oldbuf = ss->inwritebuf; ++ ss->inwritebuf = (ss->inwritebuf + 1) % ss->numbufs; ++ ++ if (ss->inwritebuf == ss->outwritebuf) { ++ /* Whoops, no more space. */ ++ ss->inwritebuf = -1; ++ } ++ if (ss->outwritebuf < 0) { ++ /* Let the interrupt handler know there's ++ some space for us */ ++ ss->outwritebuf = oldbuf; ++ } ++ print_debug_writebuf(ss, skb, oldbuf); ++ retval = 1; ++ } ++ spin_unlock_irqrestore(&ss->lock, flags); ++ if (retval) { ++ /* Get rid of the SKB if we're returning non-zero */ ++ /* N.B. this is called in process or BH context so ++ dev_kfree_skb is OK. */ ++ dev_kfree_skb(skb); ++ } ++ return retval; ++} ++ ++static int dahdi_ppp_ioctl(struct ppp_channel *ppp, unsigned int cmd, unsigned long flags) ++{ ++ return -EIO; ++} ++ ++static struct ppp_channel_ops ztppp_ops = ++{ ++ .start_xmit = dahdi_ppp_xmit, ++ .ioctl = dahdi_ppp_ioctl, ++}; ++ ++#endif ++ ++/** ++ * is_monitor_mode() - True if the confmode indicates that one channel is monitoring another. ++ * ++ */ ++static bool is_monitor_mode(int confmode) ++{ ++ confmode &= DAHDI_CONF_MODE_MASK; ++ if ((confmode == DAHDI_CONF_MONITOR) || ++ (confmode == DAHDI_CONF_MONITORTX) || ++ (confmode == DAHDI_CONF_MONITORBOTH) || ++ (confmode == DAHDI_CONF_MONITOR_RX_PREECHO) || ++ (confmode == DAHDI_CONF_MONITOR_TX_PREECHO) || ++ (confmode == DAHDI_CONF_MONITORBOTH_PREECHO)) { ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++static unsigned long _chan_cleanup(struct dahdi_chan *pos, unsigned long data) ++{ ++ unsigned long flags; ++ struct dahdi_chan *const chan = (struct dahdi_chan *)data; ++ /* Remove anyone pointing to us as master ++ and make them their own thing */ ++ if (pos->master == chan) ++ pos->master = pos; ++ ++ if (((pos->confna == chan->channo) && ++ is_monitor_mode(pos->confmode)) || ++ (pos->dacs_chan == chan) || ++ (pos->conf_chan == chan)) { ++ /* Take them out of conference with us */ ++ /* release conference resource if any */ ++ if (pos->confna) ++ dahdi_check_conf(pos->confna); ++ ++ dahdi_disable_dacs(pos); ++ spin_lock_irqsave(&pos->lock, flags); ++ pos->confna = 0; ++ pos->_confn = 0; ++ pos->confmode = 0; ++ pos->conf_chan = NULL; ++ pos->dacs_chan = NULL; ++ spin_unlock_irqrestore(&pos->lock, flags); ++ } ++ ++ return 0; ++} ++ ++static const struct file_operations nodev_fops; ++ ++static void dahdi_chan_unreg(struct dahdi_chan *chan) ++{ ++ unsigned long flags; ++ ++ might_sleep(); ++ ++ /* In the case of surprise removal of hardware, make sure any open ++ * file handles to this channel are disassociated with the actual ++ * dahdi_chan. */ ++ if (chan->file) { ++ module_printk(KERN_NOTICE, ++ "%s: surprise removal: chan %d\n", ++ __func__, chan->channo); ++ chan->file->private_data = NULL; ++ chan->file->f_op = &nodev_fops; ++ /* ++ * From now on, any file_operations for this device ++ * would call the nodev_fops methods. ++ */ ++ } ++ ++ mutex_lock(&chan->mutex); ++ release_echocan(chan->ec_factory); ++ chan->ec_factory = NULL; ++ mutex_unlock(&chan->mutex); ++ ++#ifdef CONFIG_DAHDI_NET ++ if (dahdi_have_netdev(chan)) { ++ unregister_hdlc_device(chan->hdlcnetdev->netdev); ++ free_netdev(chan->hdlcnetdev->netdev); ++ kfree(chan->hdlcnetdev); ++ chan->hdlcnetdev = NULL; ++ } ++#endif ++ clear_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags); ++ ++#ifdef CONFIG_DAHDI_PPP ++ if (chan->ppp) { ++ module_printk(KERN_NOTICE, "HUH??? PPP still attached??\n"); ++ } ++#endif ++ spin_lock_irqsave(&chan_lock, flags); ++ __for_each_channel(_chan_cleanup, (unsigned long)chan); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ ++ chan->channo = -1; ++ ++ /* Let processeses out of their poll_wait() */ ++ wake_up_interruptible(&chan->waitq); ++ ++ /* release tone_zone */ ++ close_channel(chan); ++ ++ if (chan->file) { ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) { ++ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags); ++ if (chan->span) { ++ if (chan->span->ops->close) { ++ int res; ++ ++ res = chan->span->ops->close(chan); ++ if (res) ++ module_printk(KERN_NOTICE, ++ "%s: close() failed: %d\n", ++ __func__, res); ++ } ++ } ++ } ++ msleep(20); ++ /* ++ * FIXME: THE BIG SLEEP above, is hiding a terrible ++ * race condition: ++ * - the module_put() ahead, would allow the low-level driver ++ * to free the channel. ++ * - We should make sure no-one reference this channel ++ * from now on. ++ */ ++ if (chan->span) ++ put_span(chan->span); ++ } ++} ++ ++static ssize_t dahdi_chan_read(struct file *file, char __user *usrbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct dahdi_chan *chan = file->private_data; ++ int amnt; ++ int res, rv; ++ int oldbuf,x; ++ unsigned long flags; ++ ++ /* Make sure count never exceeds 65k, and make sure it's unsigned */ ++ count &= 0xffff; ++ ++ if (unlikely(!chan)) { ++ /* ++ * This should never happen. Surprise device removal ++ * should lead us to the nodev_* file_operations ++ */ ++ msleep(5); ++ module_printk(KERN_ERR, "%s: NODEV\n", __func__); ++ return -ENODEV; ++ } ++ ++ if (unlikely(count < 1)) ++ return -EINVAL; ++ ++ if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags))) ++ return -ENODEV; ++ ++ for (;;) { ++ spin_lock_irqsave(&chan->lock, flags); ++ if (chan->eventinidx != chan->eventoutidx) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -ELAST /* - chan->eventbuf[chan->eventoutidx]*/; ++ } ++ res = chan->outreadbuf; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (res >= 0) ++ break; ++ if (file->f_flags & O_NONBLOCK) ++ return -EAGAIN; ++ ++ /* Wake up when data is available or when the board driver ++ * unregistered the channel. */ ++ rv = wait_event_interruptible(chan->waitq, ++ (!chan->file->private_data || chan->outreadbuf > -1)); ++ if (rv) ++ return rv; ++ if (unlikely(!chan->file->private_data)) ++ return -ENODEV; ++ } ++ amnt = count; ++ if (chan->flags & DAHDI_FLAG_LINEAR) { ++ if (amnt > (chan->readn[res] << 1)) ++ amnt = chan->readn[res] << 1; ++ if (amnt) { ++ /* There seems to be a max stack size, so we have ++ to do this in smaller pieces */ ++ short lindata[128]; ++ int left = amnt >> 1; /* amnt is in bytes */ ++ int pos = 0; ++ int pass; ++ while (left) { ++ pass = left; ++ if (pass > 128) ++ pass = 128; ++ for (x = 0; x < pass; x++) ++ lindata[x] = DAHDI_XLAW(chan->readbuf[res][x + pos], chan); ++ if (copy_to_user(usrbuf + (pos << 1), lindata, pass << 1)) ++ return -EFAULT; ++ left -= pass; ++ pos += pass; ++ } ++ } ++ } else { ++ if (amnt > chan->readn[res]) ++ amnt = chan->readn[res]; ++ if (amnt) { ++ if (copy_to_user(usrbuf, chan->readbuf[res], amnt)) ++ return -EFAULT; ++ } ++ } ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->readidx[res] = 0; ++ chan->readn[res] = 0; ++ oldbuf = res; ++ chan->outreadbuf = (res + 1) % chan->numbufs; ++ if (chan->outreadbuf == chan->inreadbuf) { ++ /* Out of stuff */ ++ chan->outreadbuf = -1; ++ } ++ if (chan->inreadbuf < 0) { ++ /* Notify interrupt handler that we have some space now */ ++ chan->inreadbuf = oldbuf; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ return amnt; ++} ++ ++static int num_filled_bufs(struct dahdi_chan *chan) ++{ ++ int range1, range2; ++ ++ if (chan->inwritebuf < 0) { ++ return chan->numbufs; ++ } ++ ++ if (chan->outwritebuf < 0) { ++ return 0; ++ } ++ ++ if (chan->outwritebuf <= chan->inwritebuf) { ++ return chan->inwritebuf - chan->outwritebuf; ++ } ++ ++ /* This means (in > out) and we have wrap around */ ++ range1 = chan->numbufs - chan->outwritebuf; ++ range2 = chan->inwritebuf; ++ ++ return range1 + range2; ++} ++ ++static ssize_t dahdi_chan_write(struct file *file, const char __user *usrbuf, ++ size_t count, loff_t *ppos) ++{ ++ unsigned long flags; ++ struct dahdi_chan *chan = file->private_data; ++ int res, amnt, oldbuf, rv, x; ++ ++ /* Make sure count never exceeds 65k, and make sure it's unsigned */ ++ count &= 0xffff; ++ ++ if (unlikely(!chan)) { ++ /* ++ * This should never happen. Surprise device removal ++ * should lead us to the nodev_* file_operations ++ */ ++ msleep(5); ++ module_printk(KERN_ERR, "%s: NODEV\n", __func__); ++ return -ENODEV; ++ } ++ ++ if (unlikely(count < 1)) ++ return -EINVAL; ++ ++ if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags))) ++ return -ENODEV; ++ ++ for (;;) { ++ spin_lock_irqsave(&chan->lock, flags); ++ if ((chan->curtone || chan->pdialcount) && !is_pseudo_chan(chan)) { ++ chan->curtone = NULL; ++ chan->tonep = 0; ++ chan->dialing = 0; ++ chan->txdialbuf[0] = '\0'; ++ chan->pdialcount = 0; ++ } ++ if (chan->eventinidx != chan->eventoutidx) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -ELAST; ++ } ++ res = chan->inwritebuf; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (res >= 0) ++ break; ++ if (file->f_flags & O_NONBLOCK) { ++#ifdef BUFFER_DEBUG ++ printk("Error: Nonblock\n"); ++#endif ++ return -EAGAIN; ++ } ++ ++ /* Wake up when room in the write queue is available or when ++ * the board driver unregistered the channel. */ ++ rv = wait_event_interruptible(chan->waitq, ++ (!chan->file->private_data || chan->inwritebuf > -1)); ++ if (rv) ++ return rv; ++ if (unlikely(!chan->file->private_data)) ++ return -ENODEV; ++ } ++ ++ amnt = count; ++ if (chan->flags & DAHDI_FLAG_LINEAR) { ++ if (amnt > (chan->blocksize << 1)) ++ amnt = chan->blocksize << 1; ++ } else { ++ if (amnt > chan->blocksize) ++ amnt = chan->blocksize; ++ } ++ ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "dahdi_chan_write(chan: %d, res: %d, outwritebuf: %d amnt: %d\n", ++ chan->channo, res, chan->outwritebuf, amnt); ++#endif ++ ++ if (amnt) { ++ if (chan->flags & DAHDI_FLAG_LINEAR) { ++ /* There seems to be a max stack size, so we have ++ to do this in smaller pieces */ ++ short lindata[128]; ++ int left = amnt >> 1; /* amnt is in bytes */ ++ int pos = 0; ++ int pass; ++ while (left) { ++ pass = left; ++ if (pass > 128) ++ pass = 128; ++ if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1)) { ++ return -EFAULT; ++ } ++ left -= pass; ++ for (x = 0; x < pass; x++) ++ chan->writebuf[res][x + pos] = DAHDI_LIN2X(lindata[x], chan); ++ pos += pass; ++ } ++ chan->writen[res] = amnt >> 1; ++ } else { ++ if (copy_from_user(chan->writebuf[res], usrbuf, amnt)) { ++ return -EFAULT; ++ } ++ chan->writen[res] = amnt; ++ } ++#ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX ++ if ((chan->ec_state) && ++ (ECHO_MODE_ACTIVE == chan->ec_state->status.mode) && ++ (chan->ec_state->ops->echocan_process_tx)) { ++ struct dahdi_echocan_state *const ec = chan->ec_state; ++ for (x = 0; x < chan->writen[res]; ++x) { ++ short tx; ++ tx = DAHDI_XLAW(chan->writebuf[res][x], chan); ++ ec->ops->echocan_process_tx(ec, &tx, 1); ++ chan->writebuf[res][x] = DAHDI_LIN2X((int) tx, ++ chan); ++ } ++ } ++#endif ++ chan->writeidx[res] = 0; ++ if (chan->flags & DAHDI_FLAG_FCS) ++ calc_fcs(chan, res); ++ oldbuf = res; ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->inwritebuf = (res + 1) % chan->numbufs; ++ ++ if (chan->inwritebuf == chan->outwritebuf) { ++ /* Don't stomp on the transmitter, just wait for them to ++ wake us up */ ++ chan->inwritebuf = -1; ++ /* Make sure the transmitter is transmitting in case of POLICY_WHEN_FULL */ ++ chan->txdisable = 0; ++ } ++ ++ if (chan->outwritebuf < 0) { ++ /* Okay, the interrupt handler has been waiting for us. Give them a buffer */ ++ chan->outwritebuf = oldbuf; ++ } ++ ++ if ((chan->txbufpolicy == DAHDI_POLICY_HALF_FULL) && (chan->txdisable)) { ++ if (num_filled_bufs(chan) >= (chan->numbufs >> 1)) { ++#ifdef BUFFER_DEBUG ++ printk("Reached buffer fill mark of %d\n", num_filled_bufs(chan)); ++#endif ++ chan->txdisable = 0; ++ } ++ } ++ ++#ifdef BUFFER_DEBUG ++ if ((chan->statcount <= 0) || (amnt != 128) || (num_filled_bufs(chan) != chan->lastnumbufs)) { ++ printk("amnt: %d Number of filled buffers: %d\n", amnt, num_filled_bufs(chan)); ++ chan->statcount = 32000; ++ chan->lastnumbufs = num_filled_bufs(chan); ++ } ++#endif ++ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ if (chan->flags & DAHDI_FLAG_NOSTDTXRX && chan->span->ops->hdlc_hard_xmit) ++ chan->span->ops->hdlc_hard_xmit(chan); ++ } ++ return amnt; ++} ++ ++static int dahdi_ctl_open(struct file *file) ++{ ++ /* Nothing to do, really */ ++ return 0; ++} ++ ++static int dahdi_chan_open(struct file *file) ++{ ++ /* Nothing to do here for now either */ ++ return 0; ++} ++ ++static int dahdi_ctl_release(struct file *file) ++{ ++ /* Nothing to do */ ++ return 0; ++} ++ ++static int dahdi_chan_release(struct file *file) ++{ ++ /* Nothing to do for now */ ++ return 0; ++} ++ ++static void set_txtone(struct dahdi_chan *ss, int fac, int init_v2, int init_v3) ++{ ++ if (fac == 0) { ++ ss->v2_1 = 0; ++ ss->v3_1 = 0; ++ return; ++ } ++ ss->txtone = fac; ++ ss->v1_1 = 0; ++ ss->v2_1 = init_v2; ++ ss->v3_1 = init_v3; ++ return; ++} ++ ++static void dahdi_rbs_sethook(struct dahdi_chan *chan, int txsig, int txstate, ++ int timeout) ++{ ++ static const struct { ++ unsigned int sig_type; ++ /* Index is dahdi_txsig enum */ ++ unsigned int bits[DAHDI_TXSIG_TOTAL]; ++ } outs[NUM_SIGS] = { ++ { ++ /* ++ * We set the idle case of the DAHDI_SIG_NONE to this pattern to make idle E1 CAS ++ * channels happy. Should not matter with T1, since on an un-configured channel, ++ * who cares what the sig bits are as long as they are stable ++ */ ++ .sig_type = DAHDI_SIG_NONE, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_ACD, ++ }, { ++ .sig_type = DAHDI_SIG_EM, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_ABCD, ++ .bits[DAHDI_TXSIG_START] = DAHDI_BITS_ABCD, ++ }, { ++ .sig_type = DAHDI_SIG_FXSLS, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_BD, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_ABCD, ++ .bits[DAHDI_TXSIG_START] = DAHDI_BITS_ABCD, ++ }, { ++ .sig_type = DAHDI_SIG_FXSGS, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_BD, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_ABCD, ++#ifndef CONFIG_CAC_GROUNDSTART ++ .bits[DAHDI_TXSIG_START] = DAHDI_BITS_AC, ++#endif ++ }, { ++ .sig_type = DAHDI_SIG_FXSKS, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_BD, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_ABCD, ++ .bits[DAHDI_TXSIG_START] = DAHDI_BITS_ABCD, ++ }, { ++ .sig_type = DAHDI_SIG_FXOLS, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_BD, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_BD, ++ }, { ++ .sig_type = DAHDI_SIG_FXOGS, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_ABCD, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_BD, ++ }, { ++ .sig_type = DAHDI_SIG_FXOKS, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_BD, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_BD, ++ .bits[DAHDI_TXSIG_KEWL] = DAHDI_BITS_ABCD, ++ }, { ++ .sig_type = DAHDI_SIG_SF, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_BITS_BCD, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_ABCD, ++ .bits[DAHDI_TXSIG_START] = DAHDI_BITS_ABCD, ++ .bits[DAHDI_TXSIG_KEWL] = DAHDI_BITS_BCD, ++ }, { ++ .sig_type = DAHDI_SIG_EM_E1, ++ .bits[DAHDI_TXSIG_ONHOOK] = DAHDI_DBIT, ++ .bits[DAHDI_TXSIG_OFFHOOK] = DAHDI_BITS_ABD, ++ .bits[DAHDI_TXSIG_START] = DAHDI_BITS_ABD, ++ .bits[DAHDI_TXSIG_KEWL] = DAHDI_DBIT, ++ } ++ }; ++ int x; ++ ++ /* if no span, return doing nothing */ ++ if (!chan->span) ++ return; ++ ++ if (!(chan->span->flags & DAHDI_FLAG_RBS)) { ++ module_printk(KERN_NOTICE, "dahdi_rbs: Tried to set RBS hook state on non-RBS channel %s\n", chan->name); ++ return; ++ } ++ if ((txsig > 3) || (txsig < 0)) { ++ module_printk(KERN_NOTICE, "dahdi_rbs: Tried to set RBS hook state %d (> 3) on channel %s\n", txsig, chan->name); ++ return; ++ } ++ if (!chan->span->ops->rbsbits && !chan->span->ops->hooksig) { ++ module_printk(KERN_NOTICE, "dahdi_rbs: Tried to set RBS hook state %d on channel %s while span %s lacks rbsbits or hooksig function\n", ++ txsig, chan->name, chan->span->name); ++ return; ++ } ++ /* Don't do anything for RBS */ ++ if (chan->sig == DAHDI_SIG_DACS_RBS) ++ return; ++ chan->txstate = txstate; ++ ++ /* if tone signalling */ ++ if (chan->sig == DAHDI_SIG_SF) { ++ chan->txhooksig = txsig; ++ if (chan->txtone) { /* if set to make tone for tx */ ++ if ((txsig && !(chan->toneflags & DAHDI_REVERSE_TXTONE)) || ++ ((!txsig) && (chan->toneflags & DAHDI_REVERSE_TXTONE))) { ++ set_txtone(chan,chan->txtone,chan->tx_v2,chan->tx_v3); ++ } else { ++ set_txtone(chan,0,0,0); ++ } ++ } ++ chan->otimer = timeout * DAHDI_CHUNKSIZE; /* Otimer is timer in samples */ ++ return; ++ } ++ if (chan->span->ops->hooksig) { ++ if (chan->txhooksig != txsig) { ++ chan->txhooksig = txsig; ++ chan->span->ops->hooksig(chan, txsig); ++ } ++ chan->otimer = timeout * DAHDI_CHUNKSIZE; /* Otimer is timer in samples */ ++ return; ++ } else { ++ for (x = 0; x < NUM_SIGS; x++) { ++ if (outs[x].sig_type == chan->sig) { ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Setting bits to %d for channel %s state %d in %d signalling\n", outs[x].bits[txsig], chan->name, txsig, chan->sig); ++#endif ++ chan->txhooksig = txsig; ++ chan->txsig = outs[x].bits[txsig]; ++ chan->span->ops->rbsbits(chan, chan->txsig); ++ chan->otimer = timeout * DAHDI_CHUNKSIZE; /* Otimer is timer in samples */ ++ return; ++ } ++ } ++ } ++ module_printk(KERN_NOTICE, "dahdi_rbs: Don't know RBS signalling type %d on channel %s\n", chan->sig, chan->name); ++} ++ ++static int dahdi_cas_setbits(struct dahdi_chan *chan, int bits) ++{ ++ /* if no span, return as error */ ++ if (!chan->span) ++ return -1; ++ if (chan->span->ops->rbsbits) { ++ chan->txsig = bits; ++ chan->span->ops->rbsbits(chan, bits); ++ } else { ++ module_printk(KERN_NOTICE, "Huh? CAS setbits, but no RBS bits function\n"); ++ } ++ ++ return 0; ++} ++ ++static int dahdi_hangup(struct dahdi_chan *chan) ++{ ++ int x, res = 0; ++ ++ /* Can't hangup pseudo channels */ ++ if (!chan->span) ++ return 0; ++ ++ /* Can't hang up a clear channel */ ++ if (chan->flags & (DAHDI_FLAG_CLEAR | DAHDI_FLAG_NOSTDTXRX)) ++ return -EINVAL; ++ ++ chan->kewlonhook = 0; ++ ++ if ((chan->sig == DAHDI_SIG_FXSLS) || (chan->sig == DAHDI_SIG_FXSKS) || ++ (chan->sig == DAHDI_SIG_FXSGS)) { ++ chan->ringdebtimer = RING_DEBOUNCE_TIME; ++ } ++ ++ if (chan->span->flags & DAHDI_FLAG_RBS) { ++ if (chan->sig == DAHDI_SIG_CAS) { ++ dahdi_cas_setbits(chan, chan->idlebits); ++ } else if ((chan->sig == DAHDI_SIG_FXOKS) && (chan->txstate != DAHDI_TXSTATE_ONHOOK) ++ /* if other party is already on-hook we shouldn't do any battery drop */ ++ && !((chan->rxhooksig == DAHDI_RXSIG_ONHOOK) && (chan->itimer <= 0))) { ++ /* Do RBS signalling on the channel's behalf */ ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_KEWL, DAHDI_TXSTATE_KEWL, DAHDI_KEWLTIME); ++ } else ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_ONHOOK, 0); ++ } else { ++ /* Let the driver hang up the line if it wants to */ ++ if (chan->span->ops->sethook) { ++ if (chan->txhooksig != DAHDI_ONHOOK) { ++ chan->txhooksig = DAHDI_ONHOOK; ++ res = chan->span->ops->sethook(chan, DAHDI_ONHOOK); ++ } else ++ res = 0; ++ } ++ } ++ ++ /* if not registered yet, just return here */ ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)) ++ return res; ++ ++ /* Mark all buffers as empty */ ++ for (x = 0; x < chan->numbufs; x++) { ++ chan->writen[x] = ++ chan->writeidx[x]= ++ chan->readn[x]= ++ chan->readidx[x] = 0; ++ } ++ ++ if (chan->readbuf[0]) { ++ chan->inreadbuf = 0; ++ chan->inwritebuf = 0; ++ } else { ++ chan->inreadbuf = -1; ++ chan->inwritebuf = -1; ++ } ++ chan->outreadbuf = -1; ++ chan->outwritebuf = -1; ++ chan->dialing = 0; ++ chan->afterdialingtimer = 0; ++ chan->curtone = NULL; ++ chan->pdialcount = 0; ++ chan->cadencepos = 0; ++ chan->txdialbuf[0] = 0; ++ ++ return res; ++} ++ ++static int initialize_channel(struct dahdi_chan *chan) ++{ ++ int res; ++ unsigned long flags; ++ const void *rxgain = NULL; ++ struct dahdi_echocan_state *ec_state; ++ const struct dahdi_echocan_factory *ec_current; ++ ++ if ((res = dahdi_reallocbufs(chan, DAHDI_DEFAULT_BLOCKSIZE, DAHDI_DEFAULT_NUM_BUFS))) ++ return res; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ ++ chan->txbufpolicy = DAHDI_POLICY_IMMEDIATE; ++ ++ ec_state = chan->ec_state; ++ chan->ec_state = NULL; ++ ec_current = chan->ec_current; ++ chan->ec_current = NULL; ++ ++ chan->txdisable = 0; ++ ++ chan->digitmode = DIGIT_MODE_DTMF; ++ chan->dialing = 0; ++ chan->afterdialingtimer = 0; ++ ++ chan->cadencepos = 0; ++ chan->firstcadencepos = 0; /* By default loop back to first cadence position */ ++ ++ /* HDLC & FCS stuff */ ++ fasthdlc_init(&chan->rxhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ fasthdlc_init(&chan->txhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ chan->infcs = PPP_INITFCS; ++ ++ /* Timings for RBS */ ++ chan->prewinktime = DAHDI_DEFAULT_PREWINKTIME; ++ chan->preflashtime = DAHDI_DEFAULT_PREFLASHTIME; ++ chan->winktime = DAHDI_DEFAULT_WINKTIME; ++ chan->flashtime = DAHDI_DEFAULT_FLASHTIME; ++ ++ if (chan->sig & __DAHDI_SIG_FXO) ++ chan->starttime = DAHDI_DEFAULT_RINGTIME; ++ else ++ chan->starttime = DAHDI_DEFAULT_STARTTIME; ++ chan->rxwinktime = DAHDI_DEFAULT_RXWINKTIME; ++ chan->rxflashtime = DAHDI_DEFAULT_RXFLASHTIME; ++ chan->debouncetime = DAHDI_DEFAULT_DEBOUNCETIME; ++ chan->pulsemaketime = DAHDI_DEFAULT_PULSEMAKETIME; ++ chan->pulsebreaktime = DAHDI_DEFAULT_PULSEBREAKTIME; ++ chan->pulseaftertime = DAHDI_DEFAULT_PULSEAFTERTIME; ++ ++ /* Initialize RBS timers */ ++ chan->itimerset = chan->itimer = chan->otimer = 0; ++ chan->ringdebtimer = 0; ++ ++ /* Reset conferences */ ++ reset_conf(chan); ++ ++ chan->dacs_chan = NULL; ++ ++ /* I/O Mask, etc */ ++ chan->iomask = 0; ++ /* release conference resource if any */ ++ if (chan->confna) ++ dahdi_check_conf(chan->confna); ++ if ((chan->sig & __DAHDI_SIG_DACS) != __DAHDI_SIG_DACS) { ++ chan->confna = 0; ++ chan->confmode = 0; ++ chan->conf_chan = NULL; ++ dahdi_disable_dacs(chan); ++ } ++ chan->_confn = 0; ++ memset(chan->conflast, 0, sizeof(chan->conflast)); ++ memset(chan->conflast1, 0, sizeof(chan->conflast1)); ++ memset(chan->conflast2, 0, sizeof(chan->conflast2)); ++ chan->confmute = 0; ++ chan->gotgs = 0; ++ chan->curtone = NULL; ++ chan->tonep = 0; ++ chan->pdialcount = 0; ++ if (is_gain_allocated(chan)) ++ rxgain = chan->rxgain; ++ chan->rxgain = defgain; ++ chan->txgain = defgain; ++ chan->eventinidx = chan->eventoutidx = 0; ++ dahdi_set_law(chan, DAHDI_LAW_DEFAULT); ++ dahdi_hangup(chan); ++ ++ /* Make sure that the audio flag is cleared on a clear channel */ ++ if ((chan->sig & DAHDI_SIG_CLEAR) || (chan->sig & DAHDI_SIG_HARDHDLC)) ++ chan->flags &= ~DAHDI_FLAG_AUDIO; ++ ++ if ((chan->sig == DAHDI_SIG_CLEAR) || (chan->sig == DAHDI_SIG_HARDHDLC)) ++ chan->flags &= ~(DAHDI_FLAG_PPP | DAHDI_FLAG_FCS | DAHDI_FLAG_HDLC); ++ ++ chan->flags &= ~DAHDI_FLAG_LINEAR; ++ if (chan->curzone) { ++ /* Take cadence from tone zone */ ++ memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence)); ++ } else { ++ /* Do a default */ ++ memset(chan->ringcadence, 0, sizeof(chan->ringcadence)); ++ chan->ringcadence[0] = chan->starttime; ++ chan->ringcadence[1] = DAHDI_RINGOFFTIME; ++ } ++ ++ if (ec_state) { ++ ec_state->ops->echocan_free(chan, ec_state); ++ release_echocan(ec_current); ++ } ++ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ set_tone_zone(chan, DEFAULT_TONE_ZONE); ++ ++ if (rxgain) ++ kfree(rxgain); ++ ++ return 0; ++} ++ ++static const struct file_operations dahdi_timer_fops; ++ ++static int dahdi_timer_open(struct file *file) ++{ ++ struct dahdi_timer *t = kzalloc(sizeof(*t), GFP_KERNEL); ++ if (!t) ++ return -ENOMEM; ++ INIT_LIST_HEAD(&t->list); ++ init_waitqueue_head(&t->sel); ++ file->private_data = t; ++ spin_lock_init(&t->lock); ++ file->f_op = &dahdi_timer_fops; ++ ++ return 0; ++} ++ ++static int dahdi_timer_release(struct inode *inode, struct file *file) ++{ ++ struct dahdi_timer *timer = file->private_data; ++ unsigned long flags; ++ ++ if (!timer) ++ return 0; ++ ++ spin_lock_irqsave(&timer->lock, flags); ++ if (!list_empty(&timer->list)) { ++ spin_unlock(&timer->lock); ++ spin_lock(&dahdi_timer_lock); ++ spin_lock(&timer->lock); ++ list_del_init(&timer->list); ++ spin_unlock(&dahdi_timer_lock); ++ } ++ file->private_data = NULL; ++ spin_unlock_irqrestore(&timer->lock, flags); ++ ++ kfree(timer); ++ ++ return 0; ++} ++ ++static const struct file_operations dahdi_chan_fops; ++ ++static int dahdi_specchan_open(struct file *file) ++{ ++ int res = -ENXIO; ++ struct dahdi_chan *const chan = chan_from_file(file); ++ ++ if (!chan || !chan->sig) ++ return -ENXIO; ++ ++ /* Make sure we're not already open, a net device, or a slave ++ * device */ ++ if (dahdi_have_netdev(chan)) ++ res = -EBUSY; ++ else if (chan->master != chan) ++ res = -EBUSY; ++ else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS) ++ res = -EBUSY; ++ else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) { ++ unsigned long flags; ++ const struct dahdi_span_ops *const ops = ++ (!is_pseudo_chan(chan)) ? chan->span->ops : NULL; ++ ++ if (ops && !try_module_get(ops->owner)) { ++ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags); ++ return -ENXIO; ++ } ++ ++ res = initialize_channel(chan); ++ if (res) { ++ /* Reallocbufs must have failed */ ++ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags); ++ return res; ++ } ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ if (is_pseudo_chan(chan)) ++ chan->flags |= DAHDI_FLAG_AUDIO; ++ chan->file = file; ++ file->private_data = chan; ++ /* Since we know we're a channel now, we can ++ * update the f_op pointer and bypass a few of ++ * the checks on the minor number. */ ++ file->f_op = &dahdi_chan_fops; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ if (ops && ops->open) { ++ res = ops->open(chan); ++ if (res) { ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->file = NULL; ++ file->private_data = NULL; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ module_put(ops->owner); ++ close_channel(chan); ++ clear_bit(DAHDI_FLAGBIT_OPEN, ++ &chan->flags); ++ } ++ } ++ } else { ++ res = -EBUSY; ++ } ++ return res; ++} ++ ++static int dahdi_specchan_release(struct file *file) ++{ ++ int res=0; ++ unsigned long flags; ++ struct dahdi_chan *chan = chan_from_file(file); ++ ++ if (chan) { ++ /* Chan lock protects contents against potentially non atomic accesses. ++ * So if the pointer setting is not atomic, we should protect */ ++#ifdef CONFIG_DAHDI_MIRROR ++ if (chan->srcmirror) { ++ struct dahdi_chan *const srcmirror = chan->srcmirror; ++ spin_lock_irqsave(&srcmirror->lock, flags); ++ if (chan == srcmirror->txmirror) { ++ module_printk(KERN_INFO, "Chan %d tx mirror " \ ++ "to %d stopped\n", ++ srcmirror->txmirror->channo, ++ srcmirror->channo); ++ srcmirror->txmirror = NULL; ++ } ++ ++ if (chan == srcmirror->rxmirror) { ++ module_printk(KERN_INFO, "Chan %d rx mirror " \ ++ "to %d stopped\n", ++ srcmirror->rxmirror->channo, ++ srcmirror->channo); ++ chan->srcmirror->rxmirror = NULL; ++ } ++ spin_unlock_irqrestore(&chan->srcmirror->lock, flags); ++ } ++#endif /* CONFIG_DAHDI_MIRROR */ ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->file = NULL; ++ file->private_data = NULL; ++#ifdef CONFIG_DAHDI_MIRROR ++ chan->srcmirror = NULL; ++#endif /* CONFIG_DAHDI_MIRROR */ ++ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ close_channel(chan); ++ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags); ++ if (chan->span) { ++ struct module *owner = chan->span->ops->owner; ++ ++ if (chan->span->ops->close) ++ res = chan->span->ops->close(chan); ++ module_put(owner); ++ } ++ } else ++ res = -ENXIO; ++ return res; ++} ++ ++static int can_open_timer(void) ++{ ++#ifdef CONFIG_DAHDI_CORE_TIMER ++ return 1; ++#else ++ return (list_empty(&span_list)) ? 0 : 1; ++#endif ++} ++ ++static unsigned int max_pseudo_channels = 512; ++static unsigned int num_pseudo_channels; ++ ++/** ++ * dahdi_alloc_pseudo() - Returns a new pseudo channel. ++ * ++ * Call with the registration_mutex held since this function will determine a ++ * channel number, and must be protected from additional registrations while ++ * that is happening. ++ * ++ */ ++static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file) ++{ ++ struct pseudo_chan *pseudo; ++ unsigned long flags; ++ unsigned int channo; ++ struct pseudo_chan *p; ++ struct list_head *pos = &pseudo_chans; ++ ++ /* Don't allow /dev/dahdi/pseudo to open if there is not a timing ++ * source. */ ++ if (!can_open_timer()) ++ return NULL; ++ ++ if (unlikely(num_pseudo_channels >= max_pseudo_channels)) ++ return NULL; ++ ++ pseudo = kzalloc(sizeof(*pseudo), GFP_KERNEL); ++ if (NULL == pseudo) ++ return NULL; ++ ++ pseudo->chan.sig = DAHDI_SIG_CLEAR; ++ pseudo->chan.sigcap = DAHDI_SIG_CLEAR; ++ pseudo->chan.flags = DAHDI_FLAG_AUDIO; ++ pseudo->chan.span = NULL; /* No span == psuedo channel */ ++ ++ channo = FIRST_PSEUDO_CHANNEL; ++ list_for_each_entry(p, &pseudo_chans, node) { ++ if (channo != p->chan.channo) ++ break; ++ pos = &p->node; ++ ++channo; ++ } ++ ++ pseudo->chan.channo = channo; ++ pseudo->chan.chanpos = channo - FIRST_PSEUDO_CHANNEL + 1; ++ __dahdi_init_chan(&pseudo->chan); ++ dahdi_chan_reg(&pseudo->chan); ++ ++ snprintf(pseudo->chan.name, sizeof(pseudo->chan.name)-1, ++ "Pseudo/%d", pseudo->chan.chanpos); ++ ++ file->private_data = &pseudo->chan; ++ ++ /* Once we place the pseudo chan on the list...it's registered and ++ * live. */ ++ spin_lock_irqsave(&chan_lock, flags); ++ ++num_pseudo_channels; ++ list_add(&pseudo->node, pos); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ ++ return &pseudo->chan; ++} ++ ++static void dahdi_free_pseudo(struct dahdi_chan *chan) ++{ ++ struct pseudo_chan *pseudo; ++ unsigned long flags; ++ ++ if (!chan) ++ return; ++ ++ mutex_lock(®istration_mutex); ++ pseudo = chan_to_pseudo(chan); ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ list_del(&pseudo->node); ++ --num_pseudo_channels; ++ spin_unlock_irqrestore(&chan_lock, flags); ++ ++ dahdi_chan_unreg(chan); ++ mutex_unlock(®istration_mutex); ++ kfree(pseudo); ++} ++ ++static int dahdi_open(struct inode *inode, struct file *file) ++{ ++ int unit = UNIT(file); ++ struct dahdi_chan *chan; ++ /* Minor 0: Special "control" descriptor */ ++ if (unit == DAHDI_CTL) ++ return dahdi_ctl_open(file); ++ if (unit == DAHDI_TRANSCODE) { ++ if (!dahdi_transcode_fops) { ++ if (request_module("dahdi_transcode")) { ++ return -ENXIO; ++ } ++ } ++ if (!try_module_get(dahdi_transcode_fops->owner)) { ++ return -ENXIO; ++ } ++ if (dahdi_transcode_fops && dahdi_transcode_fops->open) { ++ return dahdi_transcode_fops->open(inode, file); ++ } else { ++ /* dahdi_transcode module should have exported a ++ * file_operations table. */ ++ WARN_ON(1); ++ } ++ return -ENXIO; ++ } ++ if (unit == DAHDI_TIMER) { ++ if (can_open_timer()) { ++ return dahdi_timer_open(file); ++ } else { ++ return -ENXIO; ++ } ++ } ++ if (unit == DAHDI_CHANNEL) ++ return dahdi_chan_open(file); ++ if (unit == DAHDI_PSEUDO) { ++ mutex_lock(®istration_mutex); ++ chan = dahdi_alloc_pseudo(file); ++ mutex_unlock(®istration_mutex); ++ if (unlikely(!chan)) ++ return -ENOMEM; ++ return dahdi_specchan_open(file); ++ } ++ return dahdi_specchan_open(file); ++} ++ ++/** ++ * dahdi_ioctl_defaultzone() - Set defzone to the default. ++ * @defzone: The number of the default zone. ++ * ++ * The default zone is the zone that will be used if the channels request the ++ * default zone in dahdi_ioctl_chanconfig. The first entry on the tone_zones ++ * list is the default zone. This function searches the list for the zone, ++ * and if found, moves it to the head of the list. ++ */ ++static int dahdi_ioctl_defaultzone(unsigned long data) ++{ ++ int defzone; ++ struct dahdi_zone *cur; ++ struct dahdi_zone *dz = NULL; ++ ++ if (get_user(defzone, (int __user *)data)) ++ return -EFAULT; ++ ++ spin_lock(&zone_lock); ++ list_for_each_entry(cur, &tone_zones, node) { ++ if (cur->num != defzone) ++ continue; ++ dz = cur; ++ break; ++ } ++ if (dz) ++ list_move(&dz->node, &tone_zones); ++ spin_unlock(&zone_lock); ++ ++ return (dz) ? 0 : -EINVAL; ++} ++ ++/* No bigger than 32k for everything per tone zone */ ++#define MAX_SIZE 32768 ++/* No more than 128 subtones */ ++#define MAX_TONES 128 ++ ++/* The tones to be loaded can (will) be a mix of regular tones, ++ DTMF tones and MF tones. We need to load DTMF and MF tones ++ a bit differently than regular tones because their storage ++ format is much simpler (an array structure field of the zone ++ structure, rather an array of pointers). ++*/ ++static int dahdi_ioctl_loadzone(unsigned long data) ++{ ++ struct load_zone_workarea { ++ struct dahdi_tone *samples[MAX_TONES]; ++ short next[MAX_TONES]; ++ struct dahdi_tone_def_header th; ++ struct dahdi_tone_def td; ++ } *work; ++ ++ size_t space; ++ size_t size; ++ int res; ++ int x; ++ void *ptr; ++ struct dahdi_zone *z = NULL; ++ struct dahdi_tone *t = NULL; ++ void __user * user_data = (void __user *)data; ++ const unsigned char MAX_ZONE = -1; ++ ++ work = kzalloc(sizeof(*work), GFP_KERNEL); ++ if (!work) ++ return -ENOMEM; ++ ++ if (copy_from_user(&work->th, user_data, sizeof(work->th))) { ++ res = -EFAULT; ++ goto error_exit; ++ } ++ ++ if ((work->th.zone < 0) || (work->th.zone > MAX_ZONE)) { ++ res = -EINVAL; ++ goto error_exit; ++ } ++ ++ user_data += sizeof(work->th); ++ ++ if ((work->th.count < 0) || (work->th.count > MAX_TONES)) { ++ module_printk(KERN_NOTICE, "Too many tones included\n"); ++ res = -EINVAL; ++ goto error_exit; ++ } ++ ++ space = size = sizeof(*z) + work->th.count * sizeof(*t); ++ ++ if (size > MAX_SIZE) { ++ res = -E2BIG; ++ goto error_exit; ++ } ++ ++ z = ptr = kzalloc(size, GFP_KERNEL); ++ if (!z) { ++ res = -ENOMEM; ++ goto error_exit; ++ } ++ ++ ptr = (char *) ptr + sizeof(*z); ++ space -= sizeof(*z); ++ ++ z->name = kasprintf(GFP_KERNEL, work->th.name); ++ if (!z->name) { ++ res = -ENOMEM; ++ goto error_exit; ++ } ++ ++ for (x = 0; x < DAHDI_MAX_CADENCE; x++) ++ z->ringcadence[x] = work->th.ringcadence[x]; ++ ++ mutex_lock(&global_dialparamslock); ++ for (x = 0; x < work->th.count; x++) { ++ enum { ++ REGULAR_TONE, ++ DTMF_TONE, ++ MFR1_TONE, ++ MFR2_FWD_TONE, ++ MFR2_REV_TONE, ++ } tone_type; ++ ++ if (space < sizeof(*t)) { ++ module_printk(KERN_NOTICE, "Insufficient tone zone space\n"); ++ res = -EINVAL; ++ goto unlock_error_exit; ++ } ++ ++ res = copy_from_user(&work->td, user_data, ++ sizeof(work->td)); ++ if (res) { ++ res = -EFAULT; ++ goto unlock_error_exit; ++ } ++ ++ user_data += sizeof(work->td); ++ ++ if ((work->td.tone >= 0) && (work->td.tone < DAHDI_TONE_MAX)) { ++ tone_type = REGULAR_TONE; ++ ++ t = work->samples[x] = ptr; ++ ++ space -= sizeof(*t); ++ ptr = (char *) ptr + sizeof(*t); ++ ++ /* Remember which sample is work->next */ ++ work->next[x] = work->td.next; ++ ++ /* Make sure the "next" one is sane */ ++ if ((work->next[x] >= work->th.count) || ++ (work->next[x] < 0)) { ++ module_printk(KERN_NOTICE, ++ "Invalid 'next' pointer: %d\n", ++ work->next[x]); ++ res = -EINVAL; ++ goto unlock_error_exit; ++ } ++ } else if ((work->td.tone >= DAHDI_TONE_DTMF_BASE) && ++ (work->td.tone <= DAHDI_TONE_DTMF_MAX)) { ++ tone_type = DTMF_TONE; ++ work->td.tone -= DAHDI_TONE_DTMF_BASE; ++ t = &z->dtmf[work->td.tone]; ++ } else if ((work->td.tone >= DAHDI_TONE_MFR1_BASE) && ++ (work->td.tone <= DAHDI_TONE_MFR1_MAX)) { ++ tone_type = MFR1_TONE; ++ work->td.tone -= DAHDI_TONE_MFR1_BASE; ++ t = &z->mfr1[work->td.tone]; ++ } else if ((work->td.tone >= DAHDI_TONE_MFR2_FWD_BASE) && ++ (work->td.tone <= DAHDI_TONE_MFR2_FWD_MAX)) { ++ tone_type = MFR2_FWD_TONE; ++ work->td.tone -= DAHDI_TONE_MFR2_FWD_BASE; ++ t = &z->mfr2_fwd[work->td.tone]; ++ } else if ((work->td.tone >= DAHDI_TONE_MFR2_REV_BASE) && ++ (work->td.tone <= DAHDI_TONE_MFR2_REV_MAX)) { ++ tone_type = MFR2_REV_TONE; ++ work->td.tone -= DAHDI_TONE_MFR2_REV_BASE; ++ t = &z->mfr2_rev[work->td.tone]; ++ } else { ++ module_printk(KERN_NOTICE, ++ "Invalid tone (%d) defined\n", ++ work->td.tone); ++ res = -EINVAL; ++ goto unlock_error_exit; ++ } ++ ++ t->fac1 = work->td.fac1; ++ t->init_v2_1 = work->td.init_v2_1; ++ t->init_v3_1 = work->td.init_v3_1; ++ t->fac2 = work->td.fac2; ++ t->init_v2_2 = work->td.init_v2_2; ++ t->init_v3_2 = work->td.init_v3_2; ++ t->modulate = work->td.modulate; ++ ++ switch (tone_type) { ++ case REGULAR_TONE: ++ t->tonesamples = work->td.samples; ++ if (!z->tones[work->td.tone]) ++ z->tones[work->td.tone] = t; ++ break; ++ case DTMF_TONE: ++ t->tonesamples = global_dialparams.dtmf_tonelen; ++ t->next = &dtmf_silence; ++ z->dtmf_continuous[work->td.tone] = *t; ++ z->dtmf_continuous[work->td.tone].next = ++ &z->dtmf_continuous[work->td.tone]; ++ break; ++ case MFR1_TONE: ++ switch (work->td.tone + DAHDI_TONE_MFR1_BASE) { ++ case DAHDI_TONE_MFR1_KP: ++ case DAHDI_TONE_MFR1_ST: ++ case DAHDI_TONE_MFR1_STP: ++ case DAHDI_TONE_MFR1_ST2P: ++ case DAHDI_TONE_MFR1_ST3P: ++ /* signaling control tones are always 100ms */ ++ t->tonesamples = 100 * DAHDI_CHUNKSIZE; ++ break; ++ default: ++ t->tonesamples = global_dialparams.mfv1_tonelen; ++ break; ++ } ++ t->next = &mfr1_silence; ++ break; ++ case MFR2_FWD_TONE: ++ t->tonesamples = global_dialparams.mfr2_tonelen; ++ t->next = &dtmf_silence; ++ z->mfr2_fwd_continuous[work->td.tone] = *t; ++ z->mfr2_fwd_continuous[work->td.tone].next = ++ &z->mfr2_fwd_continuous[work->td.tone]; ++ break; ++ case MFR2_REV_TONE: ++ t->tonesamples = global_dialparams.mfr2_tonelen; ++ t->next = &dtmf_silence; ++ z->mfr2_rev_continuous[work->td.tone] = *t; ++ z->mfr2_rev_continuous[work->td.tone].next = ++ &z->mfr2_rev_continuous[work->td.tone]; ++ break; ++ } ++ } ++ mutex_unlock(&global_dialparamslock); ++ ++ for (x = 0; x < work->th.count; x++) { ++ if (work->samples[x]) ++ work->samples[x]->next = work->samples[work->next[x]]; ++ } ++ ++ z->num = work->th.zone; ++ ++ /* After we call dahdi_register_tone_zone, the only safe way to free ++ * the zone is with a tone_zone_put call. */ ++ res = dahdi_register_tone_zone(z); ++ if (res) ++ tone_zone_put(z); ++ ++ kfree(work); ++ return res; ++ ++unlock_error_exit: ++ mutex_unlock(&global_dialparamslock); ++error_exit: ++ if (z) ++ kfree(z->name); ++ kfree(z); ++ kfree(work); ++ return res; ++} ++ ++void dahdi_init_tone_state(struct dahdi_tone_state *ts, struct dahdi_tone *zt) ++{ ++ ts->v1_1 = 0; ++ ts->v2_1 = zt->init_v2_1; ++ ts->v3_1 = zt->init_v3_1; ++ ts->v1_2 = 0; ++ ts->v2_2 = zt->init_v2_2; ++ ts->v3_2 = zt->init_v3_2; ++ ts->modulate = zt->modulate; ++} ++ ++struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int digitmode) ++{ ++ unsigned int tone_index; ++ ++ if (!chan->curzone) { ++ static int __warnonce = 1; ++ if (__warnonce) { ++ __warnonce = 0; ++ /* The tonezones are loaded by dahdi_cfg based on /etc/dahdi/system.conf. */ ++ module_printk(KERN_WARNING, "Cannot get dtmf tone until tone zone is loaded.\n"); ++ } ++ return NULL; ++ } ++ ++ switch (digitmode) { ++ case DIGIT_MODE_PULSE: ++ /* We should only get here with a pulse digit if we need ++ * to "dial" 'W' (wait 0.5 second) ++ */ ++ if (digit == 'W') ++ return &tone_pause; ++ ++ return NULL; ++ case DIGIT_MODE_DTMF: ++ switch (digit) { ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ tone_index = DAHDI_TONE_DTMF_0 + (digit - '0'); ++ break; ++ case '*': ++ tone_index = DAHDI_TONE_DTMF_s; ++ break; ++ case '#': ++ tone_index = DAHDI_TONE_DTMF_p; ++ break; ++ case 'A': ++ case 'B': ++ case 'C': ++ case 'D': ++ tone_index = DAHDI_TONE_DTMF_A + (digit - 'A'); ++ break; ++ case 'W': ++ return &tone_pause; ++ default: ++ return NULL; ++ } ++ return &chan->curzone->dtmf[tone_index - DAHDI_TONE_DTMF_BASE]; ++ case DIGIT_MODE_MFR1: ++ switch (digit) { ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ tone_index = DAHDI_TONE_MFR1_0 + (digit - '0'); ++ break; ++ case '*': ++ tone_index = DAHDI_TONE_MFR1_KP; ++ break; ++ case '#': ++ tone_index = DAHDI_TONE_MFR1_ST; ++ break; ++ case 'A': ++ tone_index = DAHDI_TONE_MFR1_STP; ++ break; ++ case 'B': ++ tone_index = DAHDI_TONE_MFR1_ST2P; ++ break; ++ case 'C': ++ tone_index = DAHDI_TONE_MFR1_ST3P; ++ break; ++ case 'W': ++ return &tone_pause; ++ default: ++ return NULL; ++ } ++ return &chan->curzone->mfr1[tone_index - DAHDI_TONE_MFR1_BASE]; ++ case DIGIT_MODE_MFR2_FWD: ++ switch (digit) { ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ tone_index = DAHDI_TONE_MFR2_FWD_1 + (digit - '1'); ++ break; ++ case 'A': ++ case 'B': ++ case 'C': ++ case 'D': ++ case 'E': ++ case 'F': ++ tone_index = DAHDI_TONE_MFR2_FWD_10 + (digit - 'A'); ++ break; ++ case 'W': ++ return &tone_pause; ++ default: ++ return NULL; ++ } ++ return &chan->curzone->mfr2_fwd[tone_index - DAHDI_TONE_MFR2_FWD_BASE]; ++ case DIGIT_MODE_MFR2_REV: ++ switch (digit) { ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ tone_index = DAHDI_TONE_MFR2_REV_1 + (digit - '1'); ++ break; ++ case 'A': ++ case 'B': ++ case 'C': ++ case 'D': ++ case 'E': ++ case 'F': ++ tone_index = DAHDI_TONE_MFR2_REV_10 + (digit - 'A'); ++ break; ++ case 'W': ++ return &tone_pause; ++ default: ++ return NULL; ++ } ++ return &chan->curzone->mfr2_rev[tone_index - DAHDI_TONE_MFR2_REV_BASE]; ++ default: ++ return NULL; ++ } ++} ++ ++static void __do_dtmf(struct dahdi_chan *chan) ++{ ++ char c; ++ ++ /* Called with chan->lock held */ ++ while ((c = chan->txdialbuf[0])) { ++ memmove(chan->txdialbuf, chan->txdialbuf + 1, sizeof(chan->txdialbuf) - 1); ++ switch (c) { ++ case 'T': ++ chan->digitmode = DIGIT_MODE_DTMF; ++ chan->tonep = 0; ++ break; ++ case 'M': ++ chan->digitmode = DIGIT_MODE_MFR1; ++ chan->tonep = 0; ++ break; ++ case 'O': ++ chan->digitmode = DIGIT_MODE_MFR2_FWD; ++ chan->tonep = 0; ++ break; ++ case 'R': ++ chan->digitmode = DIGIT_MODE_MFR2_REV; ++ chan->tonep = 0; ++ break; ++ case 'P': ++ chan->digitmode = DIGIT_MODE_PULSE; ++ chan->tonep = 0; ++ break; ++ default: ++ if ((c != 'W') && (chan->digitmode == DIGIT_MODE_PULSE)) { ++ if ((c >= '0') && (c <= '9') && (chan->txhooksig == DAHDI_TXSIG_OFFHOOK)) { ++ chan->pdialcount = (c == '0') ? 10 : c - '0'; ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_PULSEBREAK, ++ chan->pulsebreaktime); ++ return; ++ } ++ } else { ++ chan->curtone = dahdi_mf_tone(chan, c, chan->digitmode); ++ chan->tonep = 0; ++ if (chan->curtone) { ++ dahdi_init_tone_state(&chan->ts, chan->curtone); ++ return; ++ } ++ } ++ } ++ } ++ ++ /* Notify userspace process if there is nothing left */ ++ chan->dialing = 0; ++ __qevent(chan, DAHDI_EVENT_DIALCOMPLETE); ++} ++ ++static int dahdi_release(struct inode *inode, struct file *file) ++{ ++ int unit = UNIT(file); ++ int res; ++ struct dahdi_chan *chan; ++ ++ if (unit == DAHDI_CTL) ++ return dahdi_ctl_release(file); ++ if (unit == DAHDI_TIMER) { ++ return dahdi_timer_release(inode, file); ++ } ++ if (unit == DAHDI_TRANSCODE) { ++ /* We should not be here because the dahdi_transcode.ko module ++ * should have updated the file_operations for this file ++ * handle when the file was opened. */ ++ WARN_ON(1); ++ return -EFAULT; ++ } ++ if (unit == DAHDI_CHANNEL) { ++ chan = file->private_data; ++ if (!chan) ++ return dahdi_chan_release(file); ++ else ++ return dahdi_specchan_release(file); ++ } ++ if (unit == DAHDI_PSEUDO) { ++ chan = file->private_data; ++ if (chan) { ++ res = dahdi_specchan_release(file); ++ dahdi_free_pseudo(chan); ++ } else { ++ module_printk(KERN_NOTICE, "Pseudo release and no private data??\n"); ++ res = 0; ++ } ++ return res; ++ } ++ return dahdi_specchan_release(file); ++} ++ ++/** ++ * dahdi_alarm_channel() - notify userspace channel is (not) in alarm ++ * @chan: the DAHDI channel ++ * @alarms: alarm bits set ++ * ++ * Notify userspace about a change in alarm status of this channel. ++ * ++ * Note that channel drivers should only use this function directly if ++ * they have a single port per channel. Whole-span alarms should be sent ++ * using dahdi_alarm_notify() . ++ * ++ * Does nothing if alarms on the channel have not changed. If they have, ++ * triggers sending either DAHDI_EVENT_NOALARM (if they were cleared) or ++ * DAHDI_EVENT_ALARM (otherwise). ++ * ++ * Currently it is only used by drivers of FXO ports to notify (with a ++ * red alarm) they have no battery current. ++ */ ++void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ if (chan->chan_alarms != alarms) { ++ chan->chan_alarms = alarms; ++ dahdi_qevent_nolock(chan, alarms ? DAHDI_EVENT_ALARM : DAHDI_EVENT_NOALARM); ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++} ++ ++struct dahdi_span *get_master_span(void) ++{ ++ return master_span; ++} ++ ++void set_master_span(int spanno) ++{ ++ struct dahdi_span *s; ++ unsigned long flags; ++ struct dahdi_span *old_master; ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ old_master = master_span; ++ list_for_each_entry(s, &span_list, spans_node) { ++ if (spanno == s->spanno) { ++ master_span = s; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&chan_lock, flags); ++ if ((debug & DEBUG_MAIN) && (old_master != master_span)) ++ module_printk(KERN_NOTICE, "Master span is set to %d (%s)\n", ++ master_span->spanno, master_span->name); ++} ++ ++static void __dahdi_find_master_span(void) ++{ ++ struct dahdi_span *s; ++ unsigned long flags; ++ struct dahdi_span *old_master; ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ old_master = master_span; ++ list_for_each_entry(s, &span_list, spans_node) { ++ if (s->alarms && old_master) ++ continue; ++ if (dahdi_is_digital_span(s) && ++ !test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags) && ++ old_master) ++ continue; ++ if (!can_provide_timing(s)) ++ continue; ++ if (master_span == s) ++ continue; ++ ++ master_span = s; ++ break; ++ } ++ spin_unlock_irqrestore(&chan_lock, flags); ++ ++ if ((debug & DEBUG_MAIN) && (old_master != master_span)) ++ module_printk(KERN_NOTICE, "Master changed to %s\n", s->name); ++} ++ ++static void _dahdi_find_master_span(struct work_struct *work) ++{ ++ __dahdi_find_master_span(); ++} ++static DECLARE_WORK(find_master_work, _dahdi_find_master_span); ++ ++static void dahdi_find_master_span(void) ++{ ++ schedule_work(&find_master_work); ++} ++ ++void dahdi_alarm_notify(struct dahdi_span *span) ++{ ++ int x; ++ ++ span->alarms &= ~DAHDI_ALARM_LOOPBACK; ++ /* Determine maint status */ ++ if (span->maintstat || span->mainttimer) ++ span->alarms |= DAHDI_ALARM_LOOPBACK; ++ /* DON'T CHANGE THIS AGAIN. THIS WAS DONE FOR A REASON. ++ The expression (a != b) does *NOT* do the same thing ++ as ((!a) != (!b)) */ ++ /* if change in general state */ ++ if ((!span->alarms) != (!span->lastalarms)) { ++ span->lastalarms = span->alarms; ++ for (x = 0; x < span->channels; x++) ++ dahdi_alarm_channel(span->chans[x], span->alarms); ++ ++ /* If we're going into or out of alarm we should try to find a ++ * new master_span that may be a better fit. */ ++ dahdi_find_master_span(); ++ ++ /* Report more detailed alarms */ ++ if (debug & DEBUG_MAIN) { ++ if (span->alarms & DAHDI_ALARM_LOS) { ++ module_printk(KERN_NOTICE, ++ "Span %d: Loss of signal\n", ++ span->spanno); ++ } ++ if (span->alarms & DAHDI_ALARM_LFA) { ++ module_printk(KERN_NOTICE, ++ "Span %d: Loss of Frame Alignment\n", ++ span->spanno); ++ } ++ if (span->alarms & DAHDI_ALARM_LMFA) { ++ module_printk(KERN_NOTICE, ++ "Span %d: Loss of Multi-Frame "\ ++ "Alignment\n", span->spanno); ++ } ++ } ++ } ++} ++ ++static long ++dahdi_timer_unlocked_ioctl(struct file *file, unsigned int cmd, ++ unsigned long data) ++{ ++ int j; ++ unsigned long flags; ++ struct dahdi_timer *const timer = file->private_data; ++ ++ switch(cmd) { ++ case DAHDI_TIMERCONFIG: ++ get_user(j, (int __user *)data); ++ if (j < 0) ++ j = 0; ++ spin_lock_irqsave(&timer->lock, flags); ++ if (timer->ms != j) { ++ if (j && list_empty(&timer->list)) { ++ /* The timer is being activated so add to the ++ * global timer list. */ ++ spin_unlock(&timer->lock); ++ spin_lock(&dahdi_timer_lock); ++ spin_lock(&timer->lock); ++ timer->ms = timer->pos = j; ++ list_add(&timer->list, &dahdi_timers); ++ spin_unlock(&dahdi_timer_lock); ++ } else if (!j && !list_empty(&timer->list)) { ++ /* The timer is being disabled so we can remove ++ * from the global timer list. */ ++ spin_unlock(&timer->lock); ++ spin_lock(&dahdi_timer_lock); ++ spin_lock(&timer->lock); ++ list_del_init(&timer->list); ++ timer->ms = timer->pos = j; ++ spin_unlock(&dahdi_timer_lock); ++ } else { ++ timer->ms = timer->pos = j; ++ } ++ } ++ spin_unlock_irqrestore(&timer->lock, flags); ++ break; ++ case DAHDI_TIMERACK: ++ get_user(j, (int __user *)data); ++ spin_lock_irqsave(&timer->lock, flags); ++ if ((j < 1) || (j > timer->tripped)) ++ j = timer->tripped; ++ timer->tripped -= j; ++ spin_unlock_irqrestore(&timer->lock, flags); ++ break; ++ case DAHDI_GETEVENT: /* Get event on queue */ ++ j = DAHDI_EVENT_NONE; ++ spin_lock_irqsave(&timer->lock, flags); ++ /* set up for no event */ ++ if (timer->tripped) ++ j = DAHDI_EVENT_TIMER_EXPIRED; ++ if (timer->ping) ++ j = DAHDI_EVENT_TIMER_PING; ++ spin_unlock_irqrestore(&timer->lock, flags); ++ put_user(j, (int __user *)data); ++ break; ++ case DAHDI_TIMERPING: ++ spin_lock_irqsave(&timer->lock, flags); ++ timer->ping = 1; ++ wake_up_interruptible(&timer->sel); ++ spin_unlock_irqrestore(&timer->lock, flags); ++ break; ++ case DAHDI_TIMERPONG: ++ spin_lock_irqsave(&timer->lock, flags); ++ timer->ping = 0; ++ spin_unlock_irqrestore(&timer->lock, flags); ++ break; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++#ifndef HAVE_UNLOCKED_IOCTL ++static int dahdi_timer_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long data) ++{ ++ return dahdi_timer_unlocked_ioctl(file, cmd, data); ++} ++#endif ++ ++static int dahdi_ioctl_getgains(struct file *file, unsigned long data) ++{ ++ int res = 0; ++ struct dahdi_gains *gain; ++ int j; ++ void __user * const user_data = (void __user *)data; ++ struct dahdi_chan *chan; ++ ++ gain = kzalloc(sizeof(*gain), GFP_KERNEL); ++ if (!gain) ++ return -ENOMEM; ++ ++ if (copy_from_user(gain, user_data, sizeof(*gain))) { ++ res = -EFAULT; ++ goto cleanup; ++ } ++ chan = (!gain->chan) ? chan_from_file(file) : ++ chan_from_num(gain->chan); ++ if (!chan) { ++ res = -EINVAL; ++ goto cleanup; ++ } ++ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) { ++ res = -EINVAL; ++ goto cleanup; ++ } ++ gain->chan = chan->channo; ++ for (j = 0; j < 256; ++j) { ++ gain->txgain[j] = chan->txgain[j]; ++ gain->rxgain[j] = chan->rxgain[j]; ++ } ++ if (copy_to_user(user_data, gain, sizeof(*gain))) { ++ res = -EFAULT; ++ goto cleanup; ++ } ++cleanup: ++ ++ kfree(gain); ++ return res; ++} ++ ++static int dahdi_ioctl_setgains(struct file *file, unsigned long data) ++{ ++ int res = 0; ++ struct dahdi_gains *gain; ++ unsigned char *txgain, *rxgain; ++ int j; ++ unsigned long flags; ++ const int GAIN_TABLE_SIZE = sizeof(defgain); ++ void __user * const user_data = (void __user *)data; ++ struct dahdi_chan *chan; ++ ++ gain = kzalloc(sizeof(*gain), GFP_KERNEL); ++ if (!gain) ++ return -ENOMEM; ++ ++ if (copy_from_user(gain, user_data, sizeof(*gain))) { ++ res = -EFAULT; ++ goto cleanup; ++ } ++ ++ chan = (!gain->chan) ? chan_from_file(file) : ++ chan_from_num(gain->chan); ++ if (!chan) { ++ res = -EINVAL; ++ goto cleanup; ++ } ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) { ++ res = -EINVAL; ++ goto cleanup; ++ } ++ ++ rxgain = kzalloc(GAIN_TABLE_SIZE*2, GFP_KERNEL); ++ if (!rxgain) { ++ res = -ENOMEM; ++ goto cleanup; ++ } ++ ++ gain->chan = chan->channo; ++ txgain = rxgain + GAIN_TABLE_SIZE; ++ ++ for (j = 0; j < GAIN_TABLE_SIZE; ++j) { ++ rxgain[j] = gain->rxgain[j]; ++ txgain[j] = gain->txgain[j]; ++ } ++ ++ if (!memcmp(rxgain, defgain, GAIN_TABLE_SIZE) && ++ !memcmp(txgain, defgain, GAIN_TABLE_SIZE)) { ++ kfree(rxgain); ++ spin_lock_irqsave(&chan->lock, flags); ++ if (is_gain_allocated(chan)) ++ kfree(chan->rxgain); ++ chan->rxgain = defgain; ++ chan->txgain = defgain; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ } else { ++ /* This is a custom gain setting */ ++ spin_lock_irqsave(&chan->lock, flags); ++ if (is_gain_allocated(chan)) ++ kfree(chan->rxgain); ++ chan->rxgain = rxgain; ++ chan->txgain = txgain; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ } ++ ++ if (copy_to_user(user_data, gain, sizeof(*gain))) { ++ res = -EFAULT; ++ goto cleanup; ++ } ++cleanup: ++ ++ kfree(gain); ++ return res; ++} ++ ++static int dahdi_ioctl_chandiag(struct file *file, unsigned long data) ++{ ++ unsigned long flags; ++ int channo; ++ /* there really is no need to initialize this structure because when it is used it has ++ * already been completely overwritten, but apparently the compiler cannot figure that ++ * out and warns about uninitialized usage... so initialize it. ++ */ ++ struct dahdi_echocan_state ec_state = { .ops = NULL, }; ++ struct dahdi_chan *chan; ++ struct dahdi_chan *temp; ++ ++ /* get channel number from user */ ++ get_user(channo, (int __user *)data); ++ ++ chan = chan_from_num(channo); ++ if (!chan) ++ return -EINVAL; ++ ++ temp = kmalloc(sizeof(*chan), GFP_KERNEL); ++ if (!temp) ++ return -ENOMEM; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ *temp = *chan; ++ if (temp->ec_state) ++ ec_state = *temp->ec_state; ++ if (temp->curzone) ++ tone_zone_get(temp->curzone); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ module_printk(KERN_INFO, "Dump of DAHDI Channel %d (%s,%d,%d):\n\n", ++ channo, temp->name, temp->channo, temp->chanpos); ++ module_printk(KERN_INFO, "flags: %x hex, writechunk: %p, readchunk: %p\n", ++ (unsigned int) temp->flags, temp->writechunk, temp->readchunk); ++ module_printk(KERN_INFO, "rxgain: %p, txgain: %p, gainalloc: %d\n", ++ temp->rxgain, temp->txgain, is_gain_allocated(temp)); ++ module_printk(KERN_INFO, "span: %p, sig: %x hex, sigcap: %x hex\n", ++ temp->span, temp->sig, temp->sigcap); ++ module_printk(KERN_INFO, "inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n", ++ temp->inreadbuf, temp->outreadbuf, temp->inwritebuf, temp->outwritebuf); ++ module_printk(KERN_INFO, "blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n", ++ temp->blocksize, temp->numbufs, temp->txbufpolicy, ++ DAHDI_POLICY_IMMEDIATE); ++ module_printk(KERN_INFO, "txdisable: %d, rxdisable: %d, iomask: %d\n", ++ temp->txdisable, 0, temp->iomask); ++ module_printk(KERN_INFO, "curzone: %p, tonezone: %d, curtone: %p, tonep: %d\n", ++ temp->curzone, ++ ((temp->curzone) ? temp->curzone->num : -1), ++ temp->curtone, temp->tonep); ++ module_printk(KERN_INFO, "digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n", ++ temp->digitmode, temp->txdialbuf, temp->dialing, ++ temp->afterdialingtimer, temp->cadencepos); ++ module_printk(KERN_INFO, "confna: %d, confn: %d, confmode: %d, confmute: %d\n", ++ temp->confna, temp->_confn, temp->confmode, temp->confmute); ++ module_printk(KERN_INFO, "ec: %p, deflaw: %d, xlaw: %p\n", ++ temp->ec_state, temp->deflaw, temp->xlaw); ++ if (temp->ec_state) { ++ module_printk(KERN_INFO, "echostate: %02x, echotimer: %d, echolastupdate: %d\n", ++ ec_state.status.mode, ec_state.status.pretrain_timer, ec_state.status.last_train_tap); ++ } ++ module_printk(KERN_INFO, "itimer: %d, otimer: %d, ringdebtimer: %d\n\n", ++ temp->itimer, temp->otimer, temp->ringdebtimer); ++ ++ if (temp->curzone) ++ tone_zone_put(temp->curzone); ++ kfree(temp); ++ return 0; ++} ++ ++/** ++ * dahdi_ioctl_getparams() - Get channel parameters. ++ * ++ */ ++static int dahdi_ioctl_getparams(struct file *file, unsigned long data) ++{ ++ size_t size_to_copy; ++ struct dahdi_params param; ++ bool return_master = false; ++ struct dahdi_chan *chan; ++ int j; ++ size_to_copy = sizeof(struct dahdi_params); ++ if (copy_from_user(¶m, (void __user *)data, size_to_copy)) ++ return -EFAULT; ++ ++ /* check to see if the caller wants to receive our master channel ++ * number */ ++ if (param.channo & DAHDI_GET_PARAMS_RETURN_MASTER) { ++ return_master = true; ++ param.channo &= ~DAHDI_GET_PARAMS_RETURN_MASTER; ++ } ++ ++ /* Pick the right channo's */ ++ chan = chan_from_file(file); ++ if (!chan) ++ chan = chan_from_num(param.channo); ++ ++ if (!chan) ++ return -EINVAL; ++ ++ /* point to relevant structure */ ++ param.sigtype = chan->sig; /* get signalling type */ ++ /* return non-zero if rx not in idle state */ ++ if (chan->span) { ++ j = dahdi_q_sig(chan); ++ if (j >= 0) { /* if returned with success */ ++ param.rxisoffhook = ((chan->rxsig & (j >> 8)) != ++ (j & 0xff)); ++ } else { ++ const int sig = chan->rxhooksig; ++ param.rxisoffhook = ((sig != DAHDI_RXSIG_ONHOOK) && ++ (sig != DAHDI_RXSIG_INITIAL)); ++ } ++ } else if ((chan->txstate == DAHDI_TXSTATE_KEWL) || ++ (chan->txstate == DAHDI_TXSTATE_AFTERKEWL)) { ++ param.rxisoffhook = 1; ++ } else { ++ param.rxisoffhook = 0; ++ } ++ ++ if (chan->span && ++ chan->span->ops->rbsbits && !(chan->sig & DAHDI_SIG_CLEAR)) { ++ param.rxbits = chan->rxsig; ++ param.txbits = chan->txsig; ++ param.idlebits = chan->idlebits; ++ } else { ++ param.rxbits = -1; ++ param.txbits = -1; ++ param.idlebits = 0; ++ } ++ if (chan->span && ++ (chan->span->ops->rbsbits || chan->span->ops->hooksig) && ++ !(chan->sig & DAHDI_SIG_CLEAR)) { ++ param.rxhooksig = chan->rxhooksig; ++ param.txhooksig = chan->txhooksig; ++ } else { ++ param.rxhooksig = -1; ++ param.txhooksig = -1; ++ } ++ param.prewinktime = chan->prewinktime; ++ param.preflashtime = chan->preflashtime; ++ param.winktime = chan->winktime; ++ param.flashtime = chan->flashtime; ++ param.starttime = chan->starttime; ++ param.rxwinktime = chan->rxwinktime; ++ param.rxflashtime = chan->rxflashtime; ++ param.debouncetime = chan->debouncetime; ++ param.channo = chan->channo; ++ param.chan_alarms = chan->chan_alarms; ++ ++ /* if requested, put the master channel number in the top 16 bits of ++ * the result */ ++ if (return_master) ++ param.channo |= chan->master->channo << 16; ++ ++ param.pulsemaketime = chan->pulsemaketime; ++ param.pulsebreaktime = chan->pulsebreaktime; ++ param.pulseaftertime = chan->pulseaftertime; ++ param.spanno = (chan->span) ? chan->span->spanno : 0; ++ strlcpy(param.name, chan->name, sizeof(param.name)); ++ param.chanpos = chan->chanpos; ++ param.sigcap = chan->sigcap; ++ /* Return current law */ ++ if (chan->xlaw == __dahdi_alaw) ++ param.curlaw = DAHDI_LAW_ALAW; ++ else ++ param.curlaw = DAHDI_LAW_MULAW; ++ ++ if (copy_to_user((void __user *)data, ¶m, size_to_copy)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++/** ++ * dahdi_ioctl_setparams() - Set channel parameters. ++ * ++ */ ++static int dahdi_ioctl_setparams(struct file *file, unsigned long data) ++{ ++ struct dahdi_params param; ++ struct dahdi_chan *chan; ++ ++ if (copy_from_user(¶m, (void __user *)data, sizeof(param))) ++ return -EFAULT; ++ ++ param.chan_alarms = 0; /* be explicit about the above */ ++ ++ /* Pick the right channo's */ ++ chan = chan_from_file(file); ++ if (!chan) ++ chan = chan_from_num(param.channo); ++ ++ if (!chan) ++ return -EINVAL; ++ ++ /* point to relevant structure */ ++ /* NOTE: sigtype is *not* included in this */ ++ /* get timing paramters */ ++ chan->prewinktime = param.prewinktime; ++ chan->preflashtime = param.preflashtime; ++ chan->winktime = param.winktime; ++ chan->flashtime = param.flashtime; ++ chan->starttime = param.starttime; ++ /* Update ringtime if not using a tone zone */ ++ if (!chan->curzone) ++ chan->ringcadence[0] = chan->starttime; ++ chan->rxwinktime = param.rxwinktime; ++ chan->rxflashtime = param.rxflashtime; ++ chan->debouncetime = param.debouncetime; ++ chan->pulsemaketime = param.pulsemaketime; ++ chan->pulsebreaktime = param.pulsebreaktime; ++ chan->pulseaftertime = param.pulseaftertime; ++ return 0; ++} ++ ++/** ++ * dahdi_ioctl_spanstat() - Return statistics for a span. ++ * ++ */ ++static int dahdi_ioctl_spanstat(struct file *file, unsigned long data) ++{ ++ int ret = 0; ++ struct dahdi_spaninfo spaninfo; ++ struct dahdi_span *s; ++ int j; ++ size_t size_to_copy; ++ bool via_chan = false; ++ ++ size_to_copy = sizeof(struct dahdi_spaninfo); ++ if (copy_from_user(&spaninfo, (void __user *)data, size_to_copy)) ++ return -EFAULT; ++ if (!spaninfo.spanno) { ++ struct dahdi_chan *const chan = chan_from_file(file); ++ if (!chan) ++ return -EINVAL; ++ ++ s = chan->span; ++ via_chan = true; ++ } else { ++ s = span_find_and_get(spaninfo.spanno); ++ } ++ if (!s) ++ return -EINVAL; ++ ++ spaninfo.spanno = s->spanno; /* put the span # in here */ ++ spaninfo.totalspans = span_count(); ++ strlcpy(spaninfo.desc, s->desc, sizeof(spaninfo.desc)); ++ strlcpy(spaninfo.name, s->name, sizeof(spaninfo.name)); ++ spaninfo.alarms = s->alarms; /* get alarm status */ ++ spaninfo.rxlevel = s->rxlevel; /* get rx level */ ++ spaninfo.txlevel = s->txlevel; /* get tx level */ ++ ++ spaninfo.bpvcount = s->count.bpv; ++ spaninfo.crc4count = s->count.crc4; ++ spaninfo.ebitcount = s->count.ebit; ++ spaninfo.fascount = s->count.fas; ++ spaninfo.fecount = s->count.fe; ++ spaninfo.cvcount = s->count.cv; ++ spaninfo.becount = s->count.be; ++ spaninfo.prbs = s->count.prbs; ++ spaninfo.errsec = s->count.errsec; ++ ++ spaninfo.irqmisses = s->parent->irqmisses; /* get IRQ miss count */ ++ spaninfo.syncsrc = s->syncsrc; /* get active sync source */ ++ spaninfo.totalchans = s->channels; ++ spaninfo.numchans = 0; ++ for (j = 0; j < s->channels; j++) { ++ if (s->chans[j]->sig) ++ spaninfo.numchans++; ++ } ++ spaninfo.lbo = s->lbo; ++ spaninfo.lineconfig = s->lineconfig; ++ spaninfo.irq = 0; ++ spaninfo.linecompat = s->linecompat; ++ strlcpy(spaninfo.lboname, dahdi_lboname(s->lbo), ++ sizeof(spaninfo.lboname)); ++ if (s->parent->manufacturer) { ++ strlcpy(spaninfo.manufacturer, s->parent->manufacturer, ++ sizeof(spaninfo.manufacturer)); ++ } ++ if (s->parent->devicetype) { ++ strlcpy(spaninfo.devicetype, s->parent->devicetype, ++ sizeof(spaninfo.devicetype)); ++ } ++ if (s->parent->location) { ++ strlcpy(spaninfo.location, s->parent->location, ++ sizeof(spaninfo.location)); ++ } ++ if (s->spantype) { ++ /* ++ * The API is brain-damaged, returning fixed length ++ * null terminated strings via ioctl() is... ++ * ++ * This field contain only 6 characters ++ * (including null termination, 5 effective characters). ++ * ++ * For backward compatibility, massage this info for dahdi-scan ++ * and friends, until: ++ * - They either learn to read the info from sysfs ++ * - Or this API is broken to return the enum value ++ */ ++ const char *st = dahdi_spantype2str(s->spantype); ++ switch (s->spantype) { ++ case SPANTYPE_DIGITAL_BRI_NT: ++ strlcpy(spaninfo.spantype, "NT", ++ sizeof(spaninfo.spantype)); ++ break; ++ case SPANTYPE_DIGITAL_BRI_TE: ++ strlcpy(spaninfo.spantype, "TE", ++ sizeof(spaninfo.spantype)); ++ break; ++ default: ++ /* ++ * The rest are either short (FXS, FXO, E1, T1, J1) ++ * Or new (BRI_SOFT, ANALOG_MIXED, INVALID), ++ * so no backward compatibility for this ++ * broken interface. ++ */ ++ strlcpy(spaninfo.spantype, st, ++ sizeof(spaninfo.spantype)); ++ break; ++ } ++ } ++ ++ if (copy_to_user((void __user *)data, &spaninfo, size_to_copy)) ++ ret = -EFAULT; ++ ++ if (!via_chan) ++ put_span(s); ++ ++ return ret; ++} ++ ++/** ++ * dahdi_ioctl_spanstat_v1() - Return statistics for a span in a legacy format. ++ * ++ */ ++static int dahdi_ioctl_spanstat_v1(struct file *file, unsigned long data) ++{ ++ int ret = 0; ++ struct dahdi_spaninfo_v1 spaninfo_v1; ++ struct dahdi_span *s; ++ int j; ++ bool via_chan = false; ++ ++ if (copy_from_user(&spaninfo_v1, (void __user *)data, ++ sizeof(spaninfo_v1))) { ++ return -EFAULT; ++ } ++ ++ if (!spaninfo_v1.spanno) { ++ struct dahdi_chan *const chan = chan_from_file(file); ++ if (!chan) ++ return -EINVAL; ++ ++ s = chan->span; ++ via_chan = true; ++ } else { ++ s = span_find_and_get(spaninfo_v1.spanno); ++ } ++ ++ if (!s) ++ return -EINVAL; ++ ++ spaninfo_v1.spanno = s->spanno; /* put the span # in here */ ++ spaninfo_v1.totalspans = 0; ++ spaninfo_v1.totalspans = span_count(); ++ strlcpy(spaninfo_v1.desc, ++ s->desc, ++ sizeof(spaninfo_v1.desc)); ++ strlcpy(spaninfo_v1.name, ++ s->name, ++ sizeof(spaninfo_v1.name)); ++ spaninfo_v1.alarms = s->alarms; ++ spaninfo_v1.bpvcount = s->count.bpv; ++ spaninfo_v1.rxlevel = s->rxlevel; ++ spaninfo_v1.txlevel = s->txlevel; ++ spaninfo_v1.crc4count = s->count.crc4; ++ spaninfo_v1.ebitcount = s->count.ebit; ++ spaninfo_v1.fascount = s->count.fas; ++ spaninfo_v1.irqmisses = s->parent->irqmisses; ++ spaninfo_v1.syncsrc = s->syncsrc; ++ spaninfo_v1.totalchans = s->channels; ++ spaninfo_v1.numchans = 0; ++ for (j = 0; j < s->channels; j++) { ++ if (s->chans[j]->sig) ++ spaninfo_v1.numchans++; ++ } ++ spaninfo_v1.lbo = s->lbo; ++ spaninfo_v1.lineconfig = s->lineconfig; ++ spaninfo_v1.irq = 0; ++ spaninfo_v1.linecompat = s->linecompat; ++ strlcpy(spaninfo_v1.lboname, ++ dahdi_lboname(s->lbo), ++ sizeof(spaninfo_v1.lboname)); ++ ++ if (s->parent->manufacturer) { ++ strlcpy(spaninfo_v1.manufacturer, s->parent->manufacturer, ++ sizeof(spaninfo_v1.manufacturer)); ++ } ++ ++ if (s->parent->devicetype) { ++ strlcpy(spaninfo_v1.devicetype, s->parent->devicetype, ++ sizeof(spaninfo_v1.devicetype)); ++ } ++ ++ strlcpy(spaninfo_v1.location, s->parent->location, ++ sizeof(spaninfo_v1.location)); ++ ++ if (s->spantype) { ++ strlcpy(spaninfo_v1.spantype, ++ dahdi_spantype2str(s->spantype), ++ sizeof(spaninfo_v1.spantype)); ++ } ++ ++ if (copy_to_user((void __user *)data, &spaninfo_v1, ++ sizeof(spaninfo_v1))) { ++ ret = -EFAULT; ++ } ++ if (!via_chan) ++ put_span(s); ++ return ret; ++} ++ ++#ifdef CONFIG_DAHDI_CONFLINK ++static int dahdi_ioctl_conflink(struct file *file, unsigned long data) ++{ ++ struct dahdi_chan *chan; ++ struct dahdi_confinfo conf; ++ unsigned long flags; ++ int res = 0; ++ int i; ++ ++ chan = chan_from_file(file); ++ if (!chan) ++ return -EINVAL; ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) ++ return -EINVAL; ++ if (copy_from_user(&conf, (void __user *)data, sizeof(conf))) ++ return -EFAULT; ++ /* check sanity of arguments */ ++ if ((conf.chan < 0) || (conf.chan > DAHDI_MAX_CONF)) ++ return -EINVAL; ++ if ((conf.confno < 0) || (conf.confno > DAHDI_MAX_CONF)) ++ return -EINVAL; ++ /* cant listen to self!! */ ++ if (conf.chan && (conf.chan == conf.confno)) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ spin_lock(&chan->lock); ++ ++ /* if to clear all links */ ++ if ((!conf.chan) && (!conf.confno)) { ++ /* clear all the links */ ++ memset(conf_links, 0, sizeof(conf_links)); ++ recalc_maxlinks(); ++ spin_unlock(&chan->lock); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ return 0; ++ } ++ /* look for already existant specified combination */ ++ for (i = 1; i <= DAHDI_MAX_CONF; i++) { ++ /* if found, exit */ ++ if ((conf_links[i].src == conf.chan) && ++ (conf_links[i].dst == conf.confno)) ++ break; ++ } ++ if (i <= DAHDI_MAX_CONF) { /* if found */ ++ if (!conf.confmode) { /* if to remove link */ ++ conf_links[i].src = 0; ++ conf_links[i].dst = 0; ++ } else { /* if to add and already there, error */ ++ res = -EEXIST; ++ } ++ } else { /* if not found */ ++ if (conf.confmode) { /* if to add link */ ++ /* look for empty location */ ++ for (i = 1; i <= DAHDI_MAX_CONF; i++) { ++ /* if empty, exit loop */ ++ if ((!conf_links[i].src) && ++ (!conf_links[i].dst)) ++ break; ++ } ++ /* if empty spot found */ ++ if (i <= DAHDI_MAX_CONF) { ++ conf_links[i].src = conf.chan; ++ conf_links[i].dst = conf.confno; ++ } else { /* if no empties -- error */ ++ res = -ENOSPC; ++ } ++ } else { /* if to remove, and not found -- error */ ++ res = -ENOENT; ++ } ++ } ++ recalc_maxlinks(); ++ spin_unlock(&chan->lock); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ return res; ++} ++#else ++static int dahdi_ioctl_conflink(struct file *file, unsigned long data) ++{ ++ return -ENOSYS; ++} ++#endif ++ ++ ++static int dahdi_common_ioctl(struct file *file, unsigned int cmd, ++ unsigned long data) ++{ ++ switch (cmd) { ++ /* get channel parameters */ ++ case DAHDI_GET_PARAMS_V1: /* Intentional drop through. */ ++ case DAHDI_GET_PARAMS: ++ return dahdi_ioctl_getparams(file, data); ++ ++ case DAHDI_SET_PARAMS: ++ return dahdi_ioctl_setparams(file, data); ++ ++ case DAHDI_GETGAINS_V1: /* Intentional drop through. */ ++ case DAHDI_GETGAINS: /* get gain stuff */ ++ return dahdi_ioctl_getgains(file, data); ++ ++ case DAHDI_SETGAINS: /* set gain stuff */ ++ return dahdi_ioctl_setgains(file, data); ++ ++ case DAHDI_SPANSTAT: ++ return dahdi_ioctl_spanstat(file, data); ++ ++ case DAHDI_SPANSTAT_V1: ++ return dahdi_ioctl_spanstat_v1(file, data); ++ ++ case DAHDI_CHANDIAG_V1: /* Intentional drop through. */ ++ case DAHDI_CHANDIAG: ++ return dahdi_ioctl_chandiag(file, data); ++ ++ case DAHDI_CONFLINK: ++ return dahdi_ioctl_conflink(file, data); ++ ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static const struct dahdi_dynamic_ops *dahdi_dynamic_ops; ++void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops) ++{ ++ mutex_lock(®istration_mutex); ++ dahdi_dynamic_ops = ops; ++ mutex_unlock(®istration_mutex); ++} ++EXPORT_SYMBOL(dahdi_set_dynamic_ops); ++ ++static int (*dahdi_hpec_ioctl)(unsigned int cmd, unsigned long data); ++ ++void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data)) ++{ ++ dahdi_hpec_ioctl = func; ++} ++ ++static void recalc_slaves(struct dahdi_chan *chan) ++{ ++ int x; ++ struct dahdi_chan *last = chan; ++ ++ /* Makes no sense if you don't have a span */ ++ if (!chan->span) ++ return; ++ ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Recalculating slaves on %s\n", chan->name); ++#endif ++ ++ /* Link all slaves appropriately */ ++ for (x=chan->chanpos;xspan->channels;x++) ++ if (chan->span->chans[x]->master == chan) { ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Channel %s, slave to %s, last is %s, its next will be %d\n", ++ chan->span->chans[x]->name, chan->name, last->name, x); ++#endif ++ last->nextslave = chan->span->chans[x]; ++ last = last->nextslave; ++ } ++ /* Terminate list */ ++ last->nextslave = NULL; ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Done Recalculating slaves on %s (last is %s)\n", chan->name, last->name); ++#endif ++} ++ ++#if defined(CONFIG_DAHDI_NET) && defined(HAVE_NET_DEVICE_OPS) ++static const struct net_device_ops dahdi_netdev_ops = { ++ .ndo_open = dahdi_net_open, ++ .ndo_stop = dahdi_net_stop, ++ .ndo_do_ioctl = dahdi_net_ioctl, ++ .ndo_start_xmit = hdlc_start_xmit, ++}; ++#endif ++ ++static int dahdi_ioctl_chanconfig(struct file *file, unsigned long data) ++{ ++ int res = 0; ++ int y; ++ struct dahdi_chanconfig ch; ++ struct dahdi_chan *newmaster; ++ struct dahdi_chan *chan; ++ struct dahdi_chan *dacs_chan = NULL; ++ unsigned long flags; ++ int sigcap; ++ ++ if (copy_from_user(&ch, (void __user *)data, sizeof(ch))) ++ return -EFAULT; ++ ++ chan = chan_from_num(ch.chan); ++ if (!chan) { ++ printk(KERN_NOTICE "%s: No channel for number %d\n", ++ __func__, ch.chan); ++ return -EINVAL; ++ } ++ ++ if (ch.sigtype == DAHDI_SIG_SLAVE) { ++ newmaster = chan_from_num(ch.master); ++ if (!newmaster) { ++ chan_notice(chan, "%s: slave channel without master.\n", ++ __func__); ++ return -EINVAL; ++ } ++ ch.sigtype = newmaster->sig; ++ } else if ((ch.sigtype & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS) { ++ newmaster = chan; ++ dacs_chan = chan_from_num(ch.idlebits); ++ if (!dacs_chan) { ++ chan_notice(chan, "%s: dacs channel not found: %d.\n", ++ __func__, ch.idlebits); ++ return -EINVAL; ++ } ++ } else { ++ newmaster = chan; ++ } ++ spin_lock_irqsave(&chan->lock, flags); ++#ifdef CONFIG_DAHDI_NET ++ if (dahdi_have_netdev(chan)) { ++ if (chan_to_netdev(chan)->flags & IFF_UP) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ module_printk(KERN_WARNING, "Can't switch HDLC net mode on channel %s, since current interface is up\n", chan->name); ++ return -EBUSY; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ unregister_hdlc_device(chan->hdlcnetdev->netdev); ++ spin_lock_irqsave(&chan->lock, flags); ++ free_netdev(chan->hdlcnetdev->netdev); ++ kfree(chan->hdlcnetdev); ++ chan->hdlcnetdev = NULL; ++ clear_bit(DAHDI_FLAGBIT_NETDEV, &chan->flags); ++ } ++#else ++ if (ch.sigtype == DAHDI_SIG_HDLCNET) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ module_printk(KERN_WARNING, "DAHDI networking not supported by this build.\n"); ++ return -ENOSYS; ++ } ++#endif ++ sigcap = chan->sigcap; ++ /* If they support clear channel, then they support the HDLC and such through ++ us. */ ++ if (sigcap & DAHDI_SIG_CLEAR) ++ sigcap |= (DAHDI_SIG_HDLCRAW | DAHDI_SIG_HDLCFCS | DAHDI_SIG_HDLCNET | DAHDI_SIG_DACS); ++ ++ if ((sigcap & ch.sigtype) != ch.sigtype) { ++ if (debug) { ++ chan_notice(chan, "%s: bad sigtype. sigcap: %x, sigtype: %x.\n", ++ __func__, sigcap, ch.sigtype); ++ } ++ res = -EINVAL; ++ } ++ ++ if (chan->master != chan) { ++ struct dahdi_chan *oldmaster = chan->master; ++ ++ /* Clear the master channel */ ++ chan->master = chan; ++ chan->nextslave = NULL; ++ /* Unlink this channel from the master's channel list */ ++ recalc_slaves(oldmaster); ++ } ++ ++ if (!res) { ++ chan->sig = ch.sigtype; ++ if (chan->sig == DAHDI_SIG_CAS) ++ chan->idlebits = ch.idlebits; ++ else ++ chan->idlebits = 0; ++ if ((ch.sigtype & DAHDI_SIG_CLEAR) == DAHDI_SIG_CLEAR) { ++ /* Set clear channel flag if appropriate */ ++ chan->flags &= ~DAHDI_FLAG_AUDIO; ++ chan->flags |= DAHDI_FLAG_CLEAR; ++ } else { ++ /* Set audio flag and not clear channel otherwise */ ++ chan->flags |= DAHDI_FLAG_AUDIO; ++ chan->flags &= ~DAHDI_FLAG_CLEAR; ++ } ++ if ((ch.sigtype & DAHDI_SIG_HDLCRAW) == DAHDI_SIG_HDLCRAW) { ++ /* Set the HDLC flag */ ++ chan->flags |= DAHDI_FLAG_HDLC; ++ } else { ++ /* Clear the HDLC flag */ ++ chan->flags &= ~DAHDI_FLAG_HDLC; ++ } ++ if ((ch.sigtype & DAHDI_SIG_HDLCFCS) == DAHDI_SIG_HDLCFCS) { ++ /* Set FCS to be calculated if appropriate */ ++ chan->flags |= DAHDI_FLAG_FCS; ++ } else { ++ /* Clear FCS flag */ ++ chan->flags &= ~DAHDI_FLAG_FCS; ++ } ++ if ((ch.sigtype & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS) { ++ if (unlikely(!dacs_chan)) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ chan_notice(chan, "%s: dacs but no dacs_chan\n", ++ __func__); ++ return -EINVAL; ++ } ++ /* Setup conference properly */ ++ chan->confmode = DAHDI_CONF_DIGITALMON; ++ chan->confna = ch.idlebits; ++ chan->dacs_chan = dacs_chan; ++ res = dahdi_chan_dacs(chan, dacs_chan); ++ } else { ++ dahdi_disable_dacs(chan); ++ } ++ chan->master = newmaster; ++ /* Note new slave if we are not our own master */ ++ if (newmaster != chan) { ++ recalc_slaves(chan->master); ++ } ++ if ((ch.sigtype & DAHDI_SIG_HARDHDLC) == DAHDI_SIG_HARDHDLC) { ++ chan->flags &= ~DAHDI_FLAG_FCS; ++ chan->flags &= ~DAHDI_FLAG_HDLC; ++ chan->flags |= DAHDI_FLAG_NOSTDTXRX; ++ } else { ++ chan->flags &= ~DAHDI_FLAG_NOSTDTXRX; ++ } ++ ++ if ((ch.sigtype & DAHDI_SIG_MTP2) == DAHDI_SIG_MTP2) ++ chan->flags |= DAHDI_FLAG_MTP2; ++ else ++ chan->flags &= ~DAHDI_FLAG_MTP2; ++ } ++ ++ /* Chanconfig can block, do not call through the function pointer with ++ * the channel lock held. */ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (!res && chan->span->ops->chanconfig) ++ res = chan->span->ops->chanconfig(file, chan, ch.sigtype); ++ spin_lock_irqsave(&chan->lock, flags); ++ ++ ++#ifdef CONFIG_DAHDI_NET ++ if (!res && ++ (newmaster == chan) && ++ (chan->sig == DAHDI_SIG_HDLCNET)) { ++ chan->hdlcnetdev = dahdi_hdlc_alloc(); ++ if (chan->hdlcnetdev) { ++/* struct hdlc_device *hdlc = chan->hdlcnetdev; ++ struct net_device *d = hdlc_to_dev(hdlc); mmm...get it right later --byg */ ++ ++ chan->hdlcnetdev->netdev = alloc_hdlcdev(chan->hdlcnetdev); ++ if (chan->hdlcnetdev->netdev) { ++ chan->hdlcnetdev->chan = chan; ++ chan->hdlcnetdev->netdev->tx_queue_len = 50; ++#ifdef HAVE_NET_DEVICE_OPS ++ chan->hdlcnetdev->netdev->netdev_ops = &dahdi_netdev_ops; ++#else ++ chan->hdlcnetdev->netdev->do_ioctl = dahdi_net_ioctl; ++ chan->hdlcnetdev->netdev->open = dahdi_net_open; ++ chan->hdlcnetdev->netdev->stop = dahdi_net_stop; ++#endif ++ dev_to_hdlc(chan->hdlcnetdev->netdev)->attach = dahdi_net_attach; ++ dev_to_hdlc(chan->hdlcnetdev->netdev)->xmit = dahdi_xmit; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ /* Briefly restore interrupts while we register the device */ ++ res = dahdi_register_hdlc_device(chan->hdlcnetdev->netdev, ch.netdev_name); ++ spin_lock_irqsave(&chan->lock, flags); ++ } else { ++ module_printk(KERN_NOTICE, "Unable to allocate hdlc: *shrug*\n"); ++ res = -1; ++ } ++ if (!res) ++ set_bit(DAHDI_FLAGBIT_NETDEV, &chan->flags); ++ } else { ++ module_printk(KERN_NOTICE, "Unable to allocate netdev: out of memory\n"); ++ res = -1; ++ } ++ } ++#endif ++ if ((chan->sig == DAHDI_SIG_HDLCNET) && ++ (chan == newmaster) && ++ !dahdi_have_netdev(chan)) ++ module_printk(KERN_NOTICE, "Unable to register HDLC device for channel %s\n", chan->name); ++ if (!res) { ++ /* Setup default law */ ++ chan->deflaw = ch.deflaw; ++ /* Copy back any modified settings */ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (copy_to_user((void __user *)data, &ch, sizeof(ch))) ++ return -EFAULT; ++ spin_lock_irqsave(&chan->lock, flags); ++ /* And hangup */ ++ dahdi_hangup(chan); ++ y = dahdi_q_sig(chan) & 0xff; ++ if (y >= 0) ++ chan->rxsig = (unsigned char) y; ++ chan->rxhooksig = DAHDI_RXSIG_INITIAL; ++ } ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Configured channel %s, flags %04lx, sig %04x\n", chan->name, chan->flags, chan->sig); ++#endif ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ return res; ++} ++ ++/** ++ * dahdi_ioctl_set_dialparms - Set the global dial parameters. ++ * @data: Pointer to user space that contains dahdi_dialparams. ++ */ ++static int dahdi_ioctl_set_dialparams(unsigned long data) ++{ ++ unsigned int i; ++ struct dahdi_dialparams tdp; ++ struct dahdi_zone *z; ++ struct dahdi_dialparams *const gdp = &global_dialparams; ++ ++ if (copy_from_user(&tdp, (void __user *)data, sizeof(tdp))) ++ return -EFAULT; ++ ++ mutex_lock(&global_dialparamslock); ++ ++ if ((tdp.dtmf_tonelen >= 10) && (tdp.dtmf_tonelen <= 4000)) ++ gdp->dtmf_tonelen = tdp.dtmf_tonelen; ++ ++ if ((tdp.mfv1_tonelen >= 10) && (tdp.mfv1_tonelen <= 4000)) ++ gdp->mfv1_tonelen = tdp.mfv1_tonelen; ++ ++ if ((tdp.mfr2_tonelen >= 10) && (tdp.mfr2_tonelen <= 4000)) ++ gdp->mfr2_tonelen = tdp.mfr2_tonelen; ++ ++ /* update the lengths in all currently loaded zones */ ++ spin_lock(&zone_lock); ++ list_for_each_entry(z, &tone_zones, node) { ++ ++ for (i = 0; i < ARRAY_SIZE(z->dtmf); i++) { ++ z->dtmf[i].tonesamples = ++ gdp->dtmf_tonelen * DAHDI_CHUNKSIZE; ++ } ++ ++ /* for MFR1, we only adjust the length of the digits */ ++ for (i = DAHDI_TONE_MFR1_0; i <= DAHDI_TONE_MFR1_9; i++) { ++ z->mfr1[i - DAHDI_TONE_MFR1_BASE].tonesamples = ++ gdp->mfv1_tonelen * DAHDI_CHUNKSIZE; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(z->mfr2_fwd); i++) { ++ z->mfr2_fwd[i].tonesamples = ++ gdp->mfr2_tonelen * DAHDI_CHUNKSIZE; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(z->mfr2_rev); i++) { ++ z->mfr2_rev[i].tonesamples = ++ gdp->mfr2_tonelen * DAHDI_CHUNKSIZE; ++ } ++ } ++ spin_unlock(&zone_lock); ++ ++ dtmf_silence.tonesamples = gdp->dtmf_tonelen * DAHDI_CHUNKSIZE; ++ mfr1_silence.tonesamples = gdp->mfv1_tonelen * DAHDI_CHUNKSIZE; ++ mfr2_silence.tonesamples = gdp->mfr2_tonelen * DAHDI_CHUNKSIZE; ++ ++ mutex_unlock(&global_dialparamslock); ++ ++ return 0; ++} ++ ++static int dahdi_ioctl_get_dialparams(unsigned long data) ++{ ++ struct dahdi_dialparams tdp; ++ ++ mutex_lock(&global_dialparamslock); ++ tdp = global_dialparams; ++ mutex_unlock(&global_dialparamslock); ++ if (copy_to_user((void __user *)data, &tdp, sizeof(tdp))) ++ return -EFAULT; ++ return 0; ++} ++ ++static int dahdi_ioctl_indirect(struct file *file, unsigned long data) ++{ ++ int res; ++ struct dahdi_indirect_data ind; ++ void *old; ++ static bool warned; ++ struct dahdi_chan *chan; ++ ++ if (copy_from_user(&ind, (void __user *)data, sizeof(ind))) ++ return -EFAULT; ++ ++ chan = chan_from_num(ind.chan); ++ if (!chan) ++ return -EINVAL; ++ ++ if (!warned) { ++ warned = true; ++ module_printk(KERN_WARNING, "Using deprecated " \ ++ "DAHDI_INDIRECT. Please update " \ ++ "dahdi-tools.\n"); ++ } ++ ++ /* Since dahdi_chan_ioctl expects to be called on file handles ++ * associated with channels, we'll temporarily set the ++ * private_data pointer on the ctl file handle just for this ++ * call. */ ++ old = file->private_data; ++ file->private_data = chan; ++ res = dahdi_chan_ioctl(file, ind.op, (unsigned long) ind.data); ++ file->private_data = old; ++ return res; ++} ++ ++static int dahdi_ioctl_spanconfig(struct file *file, unsigned long data) ++{ ++ int res = 0; ++ struct dahdi_lineconfig lc; ++ struct dahdi_span *s; ++ ++ if (copy_from_user(&lc, (void __user *)data, sizeof(lc))) ++ return -EFAULT; ++ s = span_find_and_get(lc.span); ++ if (!s) ++ return -ENXIO; ++ ++ if ((lc.lineconfig & 0x1ff0 & s->linecompat) != ++ (lc.lineconfig & 0x1ff0)) { ++ put_span(s); ++ return -EINVAL; ++ } ++ if (s->ops->spanconfig) { ++ s->lineconfig = lc.lineconfig; ++ s->lbo = lc.lbo; ++ s->txlevel = lc.lbo; ++ s->rxlevel = 0; ++ ++ res = s->ops->spanconfig(file, s, &lc); ++ } ++ put_span(s); ++ return res; ++} ++ ++static int dahdi_ioctl_startup(struct file *file, unsigned long data) ++{ ++ /* I/O CTL's for control interface */ ++ int j; ++ int res = 0; ++ int x, y; ++ unsigned long flags; ++ struct dahdi_span *s; ++ ++ if (get_user(j, (int __user *)data)) ++ return -EFAULT; ++ s = span_find_and_get(j); ++ if (!s) ++ return -ENXIO; ++ ++ if (s->flags & DAHDI_FLAG_RUNNING) { ++ put_span(s); ++ return 0; ++ } ++ ++ if (s->ops->startup) ++ res = s->ops->startup(file, s); ++ ++ if (!res) { ++ /* Mark as running and hangup any channels */ ++ s->flags |= DAHDI_FLAG_RUNNING; ++ for (x = 0; x < s->channels; x++) { ++ y = dahdi_q_sig(s->chans[x]) & 0xff; ++ if (y >= 0) ++ s->chans[x]->rxsig = (unsigned char)y; ++ spin_lock_irqsave(&s->chans[x]->lock, flags); ++ dahdi_hangup(s->chans[x]); ++ spin_unlock_irqrestore(&s->chans[x]->lock, flags); ++ /* ++ * Set the rxhooksig back to ++ * DAHDI_RXSIG_INITIAL so that new events are ++ * queued on the channel with the actual ++ * received hook state. ++ * ++ */ ++ s->chans[x]->rxhooksig = DAHDI_RXSIG_INITIAL; ++ } ++ ++ /* Now that this span is running, it might be selected as the ++ * master_span */ ++ __dahdi_find_master_span(); ++ } ++ put_span(s); ++ return res; ++} ++ ++static int dahdi_shutdown_span(struct dahdi_span *s) ++{ ++ int res = 0; ++ int x; ++ ++ /* Unconfigure channels */ ++ for (x = 0; x < s->channels; x++) ++ s->chans[x]->sig = 0; ++ ++ if (s->ops->shutdown) ++ res = s->ops->shutdown(s); ++ ++ clear_bit(DAHDI_FLAGBIT_RUNNING, &s->flags); ++ return res; ++} ++ ++static int dahdi_ioctl_shutdown(unsigned long data) ++{ ++ int res; ++ /* I/O CTL's for control interface */ ++ int j; ++ ++ struct dahdi_span *s; ++ ++ if (get_user(j, (int __user *)data)) ++ return -EFAULT; ++ s = span_find_and_get(j); ++ if (!s) ++ return -ENXIO; ++ res = dahdi_shutdown_span(s); ++ put_span(s); ++ return res; ++} ++ ++/** ++ * dahdi_is_hwec_available - Is hardware echocan available on a channel? ++ * @chan: The channel to check ++ * ++ * Returns true if there is a hardware echocan available for the attached ++ * channel, or false otherwise. ++ * ++ */ ++static bool dahdi_is_hwec_available(const struct dahdi_chan *chan) ++{ ++ if (!chan->span || !chan->span->ops->echocan_name || ++ !hwec_factory.get_name(chan)) ++ return false; ++ ++ return true; ++} ++ ++static int dahdi_ioctl_attach_echocan(unsigned long data) ++{ ++ struct dahdi_chan *chan; ++ struct dahdi_attach_echocan ae; ++ const struct dahdi_echocan_factory *new = NULL, *old; ++ ++ if (copy_from_user(&ae, (void __user *)data, sizeof(ae))) ++ return -EFAULT; ++ ++ chan = chan_from_num(ae.chan); ++ if (!chan) ++ return -EINVAL; ++ ++ ae.echocan[sizeof(ae.echocan) - 1] = '\0'; ++ if (dahdi_is_hwec_available(chan)) { ++ if (hwec_overrides_swec) { ++ chan_dbg(GENERAL, chan, ++ "Using echocan '%s' instead of requested " \ ++ "'%s'.\n", hwec_def_name, ae.echocan); ++ /* If there is a hardware echocan available we'll ++ * always use it instead of any configured software ++ * echocan. This matches the behavior in dahdi 2.4.1.2 ++ * and earlier releases. */ ++ strlcpy(ae.echocan, hwec_def_name, sizeof(ae.echocan)); ++ ++ } else if (strcasecmp(ae.echocan, hwec_def_name) != 0) { ++ chan_dbg(GENERAL, chan, ++ "Using '%s' on channel even though '%s' is " \ ++ "available.\n", ae.echocan, hwec_def_name); ++ } ++ } ++ ++ if (ae.echocan[0]) { ++ new = find_echocan(ae.echocan); ++ if (!new) ++ return -EINVAL; ++ ++ if (!new->get_name(chan)) { ++ release_echocan(new); ++ return -EINVAL; ++ } ++ } ++ ++ mutex_lock(&chan->mutex); ++ old = chan->ec_factory; ++ chan->ec_factory = new; ++ mutex_unlock(&chan->mutex); ++ ++ if (old) ++ release_echocan(old); ++ ++ return 0; ++} ++ ++static int dahdi_ioctl_sfconfig(unsigned long data) ++{ ++ int res = 0; ++ unsigned long flags; ++ struct dahdi_chan *chan; ++ struct dahdi_sfconfig sf; ++ ++ if (copy_from_user(&sf, (void __user *)data, sizeof(sf))) ++ return -EFAULT; ++ chan = chan_from_num(sf.chan); ++ if (!chan) ++ return -EINVAL; ++ ++ if (chan->sig != DAHDI_SIG_SF) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->rxp1 = sf.rxp1; ++ chan->rxp2 = sf.rxp2; ++ chan->rxp3 = sf.rxp3; ++ chan->txtone = sf.txtone; ++ chan->tx_v2 = sf.tx_v2; ++ chan->tx_v3 = sf.tx_v3; ++ chan->toneflags = sf.toneflag; ++ if (sf.txtone) { /* if set to make tone for tx */ ++ if ((chan->txhooksig && ++ !(sf.toneflag & DAHDI_REVERSE_TXTONE)) || ++ ((!chan->txhooksig) && ++ (sf.toneflag & DAHDI_REVERSE_TXTONE))) { ++ set_txtone(chan, sf.txtone, sf.tx_v2, sf.tx_v3); ++ } else { ++ set_txtone(chan, 0, 0, 0); ++ } ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return res; ++} ++ ++/* Returns true if there are any hardware echocan on any span. */ ++static bool dahdi_any_hwec_available(void) ++{ ++ int i; ++ bool hwec_available = false; ++ struct dahdi_span *s; ++ ++ mutex_lock(®istration_mutex); ++ list_for_each_entry(s, &span_list, spans_node) { ++ for (i = 0; i < s->channels; ++i) { ++ struct dahdi_chan *const chan = s->chans[i]; ++ if (dahdi_is_hwec_available(chan)) { ++ hwec_available = true; ++ break; ++ } ++ } ++ } ++ mutex_unlock(®istration_mutex); ++ ++ return hwec_available; ++} ++ ++static int dahdi_ioctl_get_version(unsigned long data) ++{ ++ struct dahdi_versioninfo vi; ++ struct ecfactory *cur; ++ size_t space = sizeof(vi.echo_canceller) - 1; ++ bool have_hwec = dahdi_any_hwec_available(); ++ ++ memset(&vi, 0, sizeof(vi)); ++ strlcpy(vi.version, dahdi_version, sizeof(vi.version)); ++ spin_lock(&ecfactory_list_lock); ++ list_for_each_entry(cur, &ecfactory_list, list) { ++ const char * const ec_name = cur->ec->get_name(NULL); ++ if ((ec_name == hwec_def_name) && !have_hwec) { ++ /* ++ * The hardware echocan factory is always registered so ++ * that hwec can be configured on the channels as if it ++ * was a software echocan. However, it can be confusing ++ * to list it as one of the available options in the ++ * output of dahdi_cfg if there isn't a REAL hardware ++ * echocanceler attached to any of the spans. In that ++ * case, do not report the presence of the hardware ++ * echocan factory to userspace. ++ * ++ */ ++ continue; ++ } ++ strncat(vi.echo_canceller + strlen(vi.echo_canceller), ++ ec_name, space); ++ space -= strlen(ec_name); ++ if (space < 1) ++ break; ++ if (cur->list.next && (cur->list.next != &ecfactory_list)) { ++ strncat(vi.echo_canceller + strlen(vi.echo_canceller), ++ ", ", space); ++ space -= 2; ++ if (space < 1) ++ break; ++ } ++ } ++ spin_unlock(&ecfactory_list_lock); ++ if (copy_to_user((void __user *)data, &vi, sizeof(vi))) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int dahdi_ioctl_maint(unsigned long data) ++{ ++ int i; ++ unsigned long flags; ++ int rv; ++ struct dahdi_span *s; ++ struct dahdi_maintinfo maint; ++ ++ /* get struct from user */ ++ if (copy_from_user(&maint, (void __user *)data, sizeof(maint))) ++ return -EFAULT; ++ s = span_find_and_get(maint.spanno); ++ if (!s) ++ return -EINVAL; ++ if (!s->ops->maint) { ++ put_span(s); ++ return -ENOSYS; ++ } ++ spin_lock_irqsave(&s->lock, flags); ++ /* save current maint state */ ++ i = s->maintstat; ++ /* set maint mode */ ++ s->maintstat = maint.command; ++ switch (maint.command) { ++ case DAHDI_MAINT_NONE: ++ case DAHDI_MAINT_LOCALLOOP: ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ /* if same, ignore it */ ++ if (i == maint.command) ++ break; ++ rv = s->ops->maint(s, maint.command); ++ spin_unlock_irqrestore(&s->lock, flags); ++ if (rv) { ++ put_span(s); ++ /* Restore the state on error */ ++ s->maintstat = i; ++ return rv; ++ } ++ spin_lock_irqsave(&s->lock, flags); ++ break; ++ case DAHDI_MAINT_LOOPUP: ++ case DAHDI_MAINT_LOOPDOWN: ++ s->mainttimer = DAHDI_LOOPCODE_TIME * DAHDI_CHUNKSIZE; ++ rv = s->ops->maint(s, maint.command); ++ spin_unlock_irqrestore(&s->lock, flags); ++ if (rv) { ++ put_span(s); ++ /* Restore the state on error */ ++ s->maintstat = i; ++ return rv; ++ } ++ spin_lock_irqsave(&s->lock, flags); ++ break; ++ case DAHDI_MAINT_FAS_DEFECT: ++ case DAHDI_MAINT_MULTI_DEFECT: ++ case DAHDI_MAINT_CRC_DEFECT: ++ case DAHDI_MAINT_CAS_DEFECT: ++ case DAHDI_MAINT_PRBS_DEFECT: ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ case DAHDI_MAINT_PRBS: ++ case DAHDI_RESET_COUNTERS: ++ case DAHDI_MAINT_ALARM_SIM: ++ /* Prevent notifying an alarm state for generic ++ maintenance functions, unless the driver is ++ already in a maint state */ ++ if (!i) ++ s->maintstat = 0; ++ ++ rv = s->ops->maint(s, maint.command); ++ spin_unlock_irqrestore(&s->lock, flags); ++ if (rv) { ++ put_span(s); ++ /* Restore the state on error */ ++ s->maintstat = i; ++ return rv; ++ } ++ spin_lock_irqsave(&s->lock, flags); ++ break; ++ default: ++ spin_unlock_irqrestore(&s->lock, flags); ++ module_printk(KERN_NOTICE, ++ "Unknown maintenance event: %d\n", ++ maint.command); ++ put_span(s); ++ /* Restore the state on error */ ++ s->maintstat = i; ++ return -ENOSYS; ++ } ++ dahdi_alarm_notify(s); /* process alarm-related events */ ++ spin_unlock_irqrestore(&s->lock, flags); ++ put_span(s); ++ ++ return 0; ++} ++ ++static int dahdi_ioctl_dynamic(unsigned int cmd, unsigned long data) ++{ ++ bool tried_load = false; ++ int res; ++ ++retry_check: ++ mutex_lock(®istration_mutex); ++ if (!dahdi_dynamic_ops) { ++ mutex_unlock(®istration_mutex); ++ if (tried_load) ++ return -ENOSYS; ++ ++ request_module("dahdi_dynamic"); ++ tried_load = true; ++ goto retry_check; ++ } ++ if (!try_module_get(dahdi_dynamic_ops->owner)) { ++ mutex_unlock(®istration_mutex); ++ return -ENOSYS; ++ } ++ mutex_unlock(®istration_mutex); ++ ++ res = dahdi_dynamic_ops->ioctl(cmd, data); ++ module_put(dahdi_dynamic_ops->owner); ++ return res; ++} ++ ++static int ++dahdi_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long data) ++{ ++ switch (cmd) { ++ case DAHDI_INDIRECT: ++ return dahdi_ioctl_indirect(file, data); ++ case DAHDI_SPANCONFIG: ++ return dahdi_ioctl_spanconfig(file, data); ++ case DAHDI_STARTUP: ++ return dahdi_ioctl_startup(file, data); ++ case DAHDI_SHUTDOWN: ++ return dahdi_ioctl_shutdown(data); ++ case DAHDI_ATTACH_ECHOCAN: ++ return dahdi_ioctl_attach_echocan(data); ++ case DAHDI_CHANCONFIG: ++ return dahdi_ioctl_chanconfig(file, data); ++ case DAHDI_SFCONFIG: ++ return dahdi_ioctl_sfconfig(data); ++ case DAHDI_DEFAULTZONE: ++ return dahdi_ioctl_defaultzone(data); ++ case DAHDI_LOADZONE: ++ return dahdi_ioctl_loadzone(data); ++ case DAHDI_FREEZONE: ++ return dahdi_ioctl_freezone(data); ++ case DAHDI_SET_DIALPARAMS: ++ return dahdi_ioctl_set_dialparams(data); ++ case DAHDI_GET_DIALPARAMS: ++ return dahdi_ioctl_get_dialparams(data); ++ case DAHDI_GETVERSION: ++ return dahdi_ioctl_get_version(data); ++ case DAHDI_MAINT: ++ return dahdi_ioctl_maint(data); ++ case DAHDI_DYNAMIC_CREATE: ++ case DAHDI_DYNAMIC_DESTROY: ++ return dahdi_ioctl_dynamic(cmd, data); ++ case DAHDI_EC_LICENSE_CHALLENGE: ++ case DAHDI_EC_LICENSE_RESPONSE: ++ if (dahdi_hpec_ioctl) { ++ return dahdi_hpec_ioctl(cmd, data); ++ } else { ++ request_module("dahdi_echocan_hpec"); ++ if (dahdi_hpec_ioctl) ++ return dahdi_hpec_ioctl(cmd, data); ++ } ++ return -ENOSYS; ++ } ++ ++ return dahdi_common_ioctl(file, cmd, data); ++} ++ ++static int ioctl_dahdi_dial(struct dahdi_chan *chan, unsigned long data) ++{ ++ struct dahdi_dialoperation *tdo; ++ unsigned long flags; ++ char *s; ++ int rv; ++ void __user * const user_data = (void __user *)data; ++ ++ tdo = kmalloc(sizeof(*tdo), GFP_KERNEL); ++ ++ if (!tdo) ++ return -ENOMEM; ++ ++ if (copy_from_user(tdo, user_data, sizeof(*tdo))) ++ return -EFAULT; ++ rv = 0; ++ /* Force proper NULL termination and uppercase entry */ ++ tdo->dialstr[DAHDI_MAX_DTMF_BUF - 1] = '\0'; ++ for (s = tdo->dialstr; *s; s++) ++ *s = toupper(*s); ++ spin_lock_irqsave(&chan->lock, flags); ++ if (!chan->curzone) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ /* The tone zones are loaded by dahdi_cfg from /etc/dahdi/system.conf */ ++ module_printk(KERN_WARNING, "Cannot dial until a tone zone is loaded.\n"); ++ return -ENODATA; ++ } ++ switch (tdo->op) { ++ case DAHDI_DIAL_OP_CANCEL: ++ chan->curtone = NULL; ++ chan->dialing = 0; ++ chan->txdialbuf[0] = '\0'; ++ chan->tonep = 0; ++ chan->pdialcount = 0; ++ break; ++ case DAHDI_DIAL_OP_REPLACE: ++ strcpy(chan->txdialbuf, tdo->dialstr); ++ chan->dialing = 1; ++ __do_dtmf(chan); ++ break; ++ case DAHDI_DIAL_OP_APPEND: ++ if (strlen(tdo->dialstr) + strlen(chan->txdialbuf) >= (DAHDI_MAX_DTMF_BUF - 1)) { ++ rv = -EBUSY; ++ break; ++ } ++ strlcpy(chan->txdialbuf + strlen(chan->txdialbuf), tdo->dialstr, ++ DAHDI_MAX_DTMF_BUF - strlen(chan->txdialbuf)); ++ if (!chan->dialing) { ++ chan->dialing = 1; ++ __do_dtmf(chan); ++ } ++ break; ++ default: ++ rv = -EINVAL; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return rv; ++} ++ ++static int dahdi_ioctl_setconf(struct file *file, unsigned long data) ++{ ++ struct dahdi_confinfo conf; ++ struct dahdi_chan *chan; ++ struct dahdi_chan *conf_chan = NULL; ++ unsigned long flags; ++ unsigned int confmode; ++ int oldconf; ++ enum {NONE, ENABLE_HWPREEC, DISABLE_HWPREEC} preec = NONE; ++ ++ if (copy_from_user(&conf, (void __user *)data, sizeof(conf))) ++ return -EFAULT; ++ ++ confmode = conf.confmode & DAHDI_CONF_MODE_MASK; ++ ++ chan = (conf.chan) ? chan_from_num(conf.chan) : ++ chan_from_file(file); ++ if (!chan) ++ return -EINVAL; ++ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) ++ return -EINVAL; ++ ++ if ((DAHDI_CONF_DIGITALMON == confmode) || ++ is_monitor_mode(conf.confmode)) { ++ conf_chan = chan_from_num(conf.confno); ++ if (!conf_chan) ++ return -EINVAL; ++ } else { ++ /* make sure conf number makes sense, too */ ++ if ((conf.confno < -1) || (conf.confno > DAHDI_MAX_CONF)) ++ return -EINVAL; ++ } ++ ++ /* if taking off of any conf, must have 0 mode */ ++ if ((!conf.confno) && conf.confmode) ++ return -EINVAL; ++ /* likewise if 0 mode must have no conf */ ++ if ((!conf.confmode) && conf.confno) ++ return -EINVAL; ++ dahdi_check_conf(conf.confno); ++ conf.chan = chan->channo; /* return with real channel # */ ++ spin_lock_irqsave(&chan_lock, flags); ++ spin_lock(&chan->lock); ++ if (conf.confno == -1) ++ conf.confno = dahdi_first_empty_conference(); ++ if ((conf.confno < 1) && (conf.confmode)) { ++ /* No more empty conferences */ ++ spin_unlock(&chan->lock); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ return -EBUSY; ++ } ++ /* if changing confs, clear last added info */ ++ if (conf.confno != chan->confna) { ++ memset(chan->conflast, 0, sizeof(chan->conflast)); ++ memset(chan->conflast1, 0, sizeof(chan->conflast1)); ++ memset(chan->conflast2, 0, sizeof(chan->conflast2)); ++ } ++ oldconf = chan->confna; /* save old conference number */ ++ chan->confna = conf.confno; /* set conference number */ ++ chan->conf_chan = conf_chan; ++ chan->confmode = conf.confmode; /* set conference mode */ ++ chan->_confn = 0; /* Clear confn */ ++ if (chan->span && chan->span->ops->dacs) { ++ if ((confmode == DAHDI_CONF_DIGITALMON) && ++ (chan->txgain == defgain) && ++ (chan->rxgain == defgain) && ++ (conf_chan->txgain == defgain) && ++ (conf_chan->rxgain == defgain)) { ++ dahdi_chan_dacs(chan, conf_chan); ++ } else { ++ dahdi_disable_dacs(chan); ++ } ++ } ++ /* if we are going onto a conf */ ++ if (conf.confno && ++ (confmode == DAHDI_CONF_CONF || ++ confmode == DAHDI_CONF_CONFANN || ++ confmode == DAHDI_CONF_CONFMON || ++ confmode == DAHDI_CONF_CONFANNMON || ++ confmode == DAHDI_CONF_REALANDPSEUDO)) { ++ /* Get alias */ ++ chan->_confn = dahdi_get_conf_alias(conf.confno); ++ } ++ ++ spin_unlock(&chan->lock); ++ ++ if (conf_chan) { ++ if ((confmode == DAHDI_CONF_MONITOR_RX_PREECHO) || ++ (confmode == DAHDI_CONF_MONITOR_TX_PREECHO) || ++ (confmode == DAHDI_CONF_MONITORBOTH_PREECHO)) { ++ if (!conf_chan->readchunkpreec) { ++ void *temp = kmalloc(sizeof(short) * ++ DAHDI_CHUNKSIZE, GFP_ATOMIC); ++ if (temp) { ++ preec = ENABLE_HWPREEC; ++ ++ spin_lock(&conf_chan->lock); ++ conf_chan->readchunkpreec = temp; ++ spin_unlock(&conf_chan->lock); ++ } ++ } ++ } else { ++ preec = DISABLE_HWPREEC; ++ ++ spin_lock(&conf_chan->lock); ++ kfree(conf_chan->readchunkpreec); ++ conf_chan->readchunkpreec = NULL; ++ spin_unlock(&conf_chan->lock); ++ } ++ } ++ ++ spin_unlock_irqrestore(&chan_lock, flags); ++ ++ if (ENABLE_HWPREEC == preec) { ++ int res = dahdi_enable_hw_preechocan(conf_chan); ++ if (res) { ++ spin_lock_irqsave(&chan_lock, flags); ++ spin_lock(&conf_chan->lock); ++ kfree(conf_chan->readchunkpreec); ++ conf_chan->readchunkpreec = NULL; ++ spin_unlock(&conf_chan->lock); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ } ++ return res; ++ } else if (DISABLE_HWPREEC == preec) { ++ dahdi_disable_hw_preechocan(conf_chan); ++ } ++ ++ dahdi_check_conf(oldconf); ++ if (copy_to_user((void __user *)data, &conf, sizeof(conf))) ++ return -EFAULT; ++ return 0; ++} ++ ++/** ++ * dahdi_ioctl_confdiag() - Output debug info about conferences to console. ++ * ++ * This is a pure debugging aide since the only result is to the console. ++ * ++ * TODO: Does anyone use this anymore? Should it be hidden behind a debug ++ * compile time option? ++ */ ++static int dahdi_ioctl_confdiag(struct file *file, unsigned long data) ++{ ++ struct dahdi_chan *chan; ++ unsigned long flags; ++ int i; ++ int j; ++ int c; ++ ++ chan = chan_from_file(file); ++ if (!chan) ++ return -EINVAL; ++ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) ++ return -EINVAL; ++ ++ get_user(j, (int __user *)data); /* get conf # */ ++ ++ /* loop thru the interesting ones */ ++ for (i = ((j) ? j : 1); i <= ((j) ? j : DAHDI_MAX_CONF); i++) { ++ struct dahdi_span *s; ++ struct pseudo_chan *pseudo; ++ int k; ++ c = 0; ++ spin_lock_irqsave(&chan_lock, flags); ++ list_for_each_entry(s, &span_list, spans_node) { ++ for (k = 0; k < s->channels; k++) { ++ chan = s->chans[k]; ++ if (chan->confna != i) ++ continue; ++ if (!c) ++ module_printk(KERN_NOTICE, "Conf #%d:\n", i); ++ c = 1; ++ module_printk(KERN_NOTICE, "chan %d, mode %x\n", ++ chan->channo, chan->confmode); ++ } ++ } ++ list_for_each_entry(pseudo, &pseudo_chans, node) { ++ /* skip if not in this conf */ ++ if (pseudo->chan.confna != i) ++ continue; ++ if (!c) ++ module_printk(KERN_NOTICE, "Conf #%d:\n", i); ++ c = 1; ++ module_printk(KERN_NOTICE, "chan %d, mode %x\n", ++ pseudo->chan.channo, pseudo->chan.confmode); ++ } ++ ++#ifdef CONFIG_DAHDI_CONFLINK ++ { ++ int rv; ++ rv = 0; ++ for (k = 1; k <= DAHDI_MAX_CONF; k++) { ++ if (conf_links[k].dst == i) { ++ if (!c) { ++ c = 1; ++ module_printk(KERN_NOTICE, ++ "Conf #%d:\n", i); ++ } ++ if (!rv) { ++ rv = 1; ++ module_printk(KERN_NOTICE, ++ "Snooping on:\n"); ++ } ++ module_printk(KERN_NOTICE, "conf %d\n", ++ conf_links[k].src); ++ } ++ } ++ } ++#endif ++ spin_unlock_irqrestore(&chan_lock, flags); ++ if (c) ++ module_printk(KERN_NOTICE, "\n"); ++ } ++ return 0; ++} ++ ++static int dahdi_ioctl_getconf(struct file *file, unsigned long data) ++{ ++ struct dahdi_confinfo conf; ++ struct dahdi_chan *chan; ++ ++ if (copy_from_user(&conf, (void __user *)data, sizeof(conf))) ++ return -EFAULT; ++ ++ chan = (!conf.chan) ? chan_from_file(file) : ++ chan_from_num(conf.chan); ++ if (!chan) ++ return -EINVAL; ++ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) ++ return -EINVAL; ++ conf.chan = chan->channo; /* get channel number */ ++ conf.confno = chan->confna; /* get conference number */ ++ conf.confmode = chan->confmode; /* get conference mode */ ++ if (copy_to_user((void __user *)data, &conf, sizeof(conf))) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++/** ++ * dahdi_ioctl_iomux() - Wait for *something* to happen. ++ * ++ * This is now basically like the wait_event_interruptible function, but with ++ * a much more involved wait condition. ++ */ ++static int dahdi_ioctl_iomux(struct file *file, unsigned long data) ++{ ++ struct dahdi_chan *const chan = chan_from_file(file); ++ unsigned long flags; ++ unsigned int iomask; ++ int ret = 0; ++ DEFINE_WAIT(wait); ++ ++ if (get_user(iomask, (int __user *)data)) ++ return -EFAULT; ++ ++ if (unlikely(!iomask || !chan)) ++ return -EINVAL; ++ ++ while (1) { ++ unsigned int wait_result; ++ ++ wait_result = 0; ++ prepare_to_wait(&chan->waitq, &wait, TASK_INTERRUPTIBLE); ++ if (unlikely(!chan->file->private_data)) { ++ /* ++ * This should never happen. Surprise device removal ++ * should lead us to the nodev_* file_operations ++ */ ++ msleep(5); ++ module_printk(KERN_ERR, "%s: NODEV\n", __func__); ++ ret = -ENODEV; ++ break; ++ } ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->iomask = iomask; ++ if (iomask & DAHDI_IOMUX_READ) { ++ if (chan->outreadbuf > -1) ++ wait_result |= DAHDI_IOMUX_READ; ++ } ++ if (iomask & DAHDI_IOMUX_WRITE) { ++ if (chan->inwritebuf > -1) ++ wait_result |= DAHDI_IOMUX_WRITE; ++ } ++ if (iomask & DAHDI_IOMUX_WRITEEMPTY) { ++ /* if everything empty -- be sure the transmitter is ++ * enabled */ ++ chan->txdisable = 0; ++ if (chan->outwritebuf < 0) ++ wait_result |= DAHDI_IOMUX_WRITEEMPTY; ++ } ++ if (iomask & DAHDI_IOMUX_SIGEVENT) { ++ if (chan->eventinidx != chan->eventoutidx) ++ wait_result |= DAHDI_IOMUX_SIGEVENT; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ if (wait_result || (iomask & DAHDI_IOMUX_NOWAIT)) { ++ put_user(wait_result, (int __user *)data); ++ break; ++ } ++ ++ if (signal_pending(current)) { ++ finish_wait(&chan->waitq, &wait); ++ return -ERESTARTSYS; ++ } ++ ++ schedule(); ++ } ++ ++ finish_wait(&chan->waitq, &wait); ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->iomask = 0; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return ret; ++} ++ ++#ifdef CONFIG_DAHDI_MIRROR ++static int dahdi_ioctl_rxmirror(struct file *file, unsigned long data) ++{ ++ int res; ++ int i; ++ unsigned long flags; ++ struct dahdi_chan *const chan = chan_from_file(file); ++ struct dahdi_chan *srcmirror; ++ ++ if (!chan || chan->srcmirror) ++ return -ENODEV; ++ ++ res = get_user(i, (int __user *)data); ++ if (res) ++ return res; ++ ++ srcmirror = chan_from_num(i); ++ if (!srcmirror) ++ return -EINVAL; ++ ++ module_printk(KERN_INFO, "Chan %d rx mirrored to %d\n", ++ srcmirror->channo, chan->channo); ++ ++ spin_lock_irqsave(&srcmirror->lock, flags); ++ if (srcmirror->rxmirror == NULL) ++ srcmirror->rxmirror = chan; ++ ++ spin_unlock_irqrestore(&srcmirror->lock, flags); ++ if (srcmirror->rxmirror != chan) { ++ module_printk(KERN_INFO, "Chan %d cannot be rxmirrored, " \ ++ "already in use\n", srcmirror->channo); ++ return -EFAULT; ++ } ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->srcmirror = srcmirror; ++ chan->flags = srcmirror->flags; ++ chan->sig = srcmirror->sig; ++ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ return 0; ++} ++ ++static int dahdi_ioctl_txmirror(struct file *file, unsigned long data) ++{ ++ int res; ++ int i; ++ unsigned long flags; ++ struct dahdi_chan *const chan = chan_from_file(file); ++ struct dahdi_chan *srcmirror; ++ ++ if (!chan || chan->srcmirror) ++ return -ENODEV; ++ ++ res = get_user(i, (int __user *)data); ++ if (res) ++ return res; ++ ++ srcmirror = chan_from_num(i); ++ if (!srcmirror) ++ return -EINVAL; ++ ++ module_printk(KERN_INFO, "Chan %d tx mirrored to %d\n", ++ srcmirror->channo, chan->channo); ++ ++ spin_lock_irqsave(&srcmirror->lock, flags); ++ srcmirror->txmirror = chan; ++ if (srcmirror->txmirror == NULL) ++ srcmirror->txmirror = chan; ++ spin_unlock_irqrestore(&srcmirror->lock, flags); ++ ++ if (srcmirror->txmirror != chan) { ++ module_printk(KERN_INFO, "Chan %d cannot be txmirrored, " \ ++ "already in use\n", i); ++ return -EFAULT; ++ } ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->srcmirror = srcmirror; ++ chan->flags = srcmirror->flags; ++ chan->sig = srcmirror->sig; ++ clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ return 0; ++} ++#endif /* CONFIG_DAHDI_MIRROR */ ++ ++static int ++dahdi_chanandpseudo_ioctl(struct file *file, unsigned int cmd, ++ unsigned long data) ++{ ++ struct dahdi_chan *chan = chan_from_file(file); ++ union { ++ struct dahdi_bufferinfo bi; ++ struct dahdi_ring_cadence cad; ++ } stack; ++ unsigned long flags; ++ int i, j, rv; ++ void __user * const user_data = (void __user *)data; ++ ++ if (!chan) ++ return -EINVAL; ++ switch(cmd) { ++#ifdef CONFIG_DAHDI_MIRROR ++ case DAHDI_RXMIRROR: ++ return dahdi_ioctl_rxmirror(file, data); ++ ++ case DAHDI_TXMIRROR: ++ return dahdi_ioctl_txmirror(file, data); ++#endif /* CONFIG_DAHDI_MIRROR */ ++ ++ case DAHDI_DIALING: ++ spin_lock_irqsave(&chan->lock, flags); ++ j = chan->dialing; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (copy_to_user(user_data, &j, sizeof(int))) ++ return -EFAULT; ++ return 0; ++ case DAHDI_DIAL: ++ return ioctl_dahdi_dial(chan, data); ++ case DAHDI_GET_BUFINFO: ++ memset(&stack.bi, 0, sizeof(stack.bi)); ++ stack.bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; ++ stack.bi.txbufpolicy = chan->txbufpolicy; ++ stack.bi.numbufs = chan->numbufs; ++ stack.bi.bufsize = chan->blocksize; ++ /* XXX FIXME! XXX */ ++ stack.bi.readbufs = -1; ++ stack.bi.writebufs = -1; ++ if (copy_to_user(user_data, &stack.bi, sizeof(stack.bi))) ++ return -EFAULT; ++ break; ++ case DAHDI_SET_BUFINFO: ++ if (copy_from_user(&stack.bi, user_data, sizeof(stack.bi))) ++ return -EFAULT; ++ if (stack.bi.bufsize > DAHDI_MAX_BLOCKSIZE) ++ return -EINVAL; ++ if (stack.bi.bufsize < 16) ++ return -EINVAL; ++ if (stack.bi.bufsize * stack.bi.numbufs > DAHDI_MAX_BUF_SPACE) ++ return -EINVAL; ++ /* It does not make sense to allow user mode to change the ++ * receive buffering policy. DAHDI always provides received ++ * buffers to upper layers immediately. Transmission is ++ * different since we might want to allow the kernel to build ++ * up a buffer in order to prevent underruns from the ++ * interrupt context. */ ++ chan->txbufpolicy = stack.bi.txbufpolicy & 0x3; ++ if ((rv = dahdi_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs))) ++ return (rv); ++ break; ++ case DAHDI_GET_BLOCKSIZE: /* get blocksize */ ++ /* return block size */ ++ put_user(chan->blocksize, (int __user *)data); ++ break; ++ case DAHDI_SET_BLOCKSIZE: /* set blocksize */ ++ get_user(j, (int __user *)data); ++ /* cannot be larger than max amount */ ++ if (j > DAHDI_MAX_BLOCKSIZE) return(-EINVAL); ++ /* cannot be less then 16 */ ++ if (j < 16) return(-EINVAL); ++ /* allocate a single kernel buffer which we then ++ sub divide into four pieces */ ++ if ((rv = dahdi_reallocbufs(chan, j, chan->numbufs))) ++ return (rv); ++ break; ++ case DAHDI_FLUSH: /* flush input buffer, output buffer, and/or event queue */ ++ get_user(i, (int __user *)data); /* get param */ ++ spin_lock_irqsave(&chan->lock, flags); ++ if (i & DAHDI_FLUSH_READ) /* if for read (input) */ ++ { ++ /* initialize read buffers and pointers */ ++ chan->inreadbuf = 0; ++ chan->outreadbuf = -1; ++ for (j=0;jnumbufs;j++) { ++ /* Do we need this? */ ++ chan->readn[j] = 0; ++ chan->readidx[j] = 0; ++ } ++ wake_up_interruptible(&chan->waitq); /* wake_up_interruptible waiting on read */ ++ } ++ if (i & DAHDI_FLUSH_WRITE) /* if for write (output) */ ++ { ++ /* initialize write buffers and pointers */ ++ chan->outwritebuf = -1; ++ chan->inwritebuf = 0; ++ for (j=0;jnumbufs;j++) { ++ /* Do we need this? */ ++ chan->writen[j] = 0; ++ chan->writeidx[j] = 0; ++ } ++ wake_up_interruptible(&chan->waitq); /* wake_up_interruptible waiting on write */ ++ } ++ if (i & DAHDI_FLUSH_EVENT) /* if for events */ ++ { ++ /* initialize the event pointers */ ++ chan->eventinidx = chan->eventoutidx = 0; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ break; ++ case DAHDI_SYNC: /* wait for no tx */ ++ for(;;) /* loop forever */ ++ { ++ spin_lock_irqsave(&chan->lock, flags); ++ /* Know if there is a write pending */ ++ i = (chan->outwritebuf > -1); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (!i) ++ break; /* skip if none */ ++ rv = wait_event_interruptible(chan->waitq, ++ (!chan->file->private_data || chan->outwritebuf > -1)); ++ if (rv) ++ return rv; ++ if (unlikely(!chan->file->private_data)) ++ return -ENODEV; ++ } ++ break; ++ case DAHDI_IOMUX: /* wait for something to happen */ ++ return dahdi_ioctl_iomux(file, data); ++ ++ case DAHDI_GETEVENT: /* Get event on queue */ ++ /* set up for no event */ ++ j = DAHDI_EVENT_NONE; ++ spin_lock_irqsave(&chan->lock, flags); ++ /* if some event in queue */ ++ if (chan->eventinidx != chan->eventoutidx) ++ { ++ j = chan->eventbuf[chan->eventoutidx++]; ++ /* get the data, bump index */ ++ /* if index overflow, set to beginning */ ++ if (chan->eventoutidx >= DAHDI_MAX_EVENTSIZE) ++ chan->eventoutidx = 0; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ put_user(j, (int __user *)data); ++ break; ++ case DAHDI_CONFMUTE: /* set confmute flag */ ++ get_user(j, (int __user *)data); /* get conf # */ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL); ++ spin_lock_irqsave(&chan_lock, flags); ++ chan->confmute = j; ++ spin_unlock_irqrestore(&chan_lock, flags); ++ break; ++ case DAHDI_GETCONFMUTE: /* get confmute flag */ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) return (-EINVAL); ++ j = chan->confmute; ++ put_user(j, (int __user *)data); /* get conf # */ ++ rv = 0; ++ break; ++ case DAHDI_SETTONEZONE: ++ get_user(j, (int __user *) data); ++ rv = set_tone_zone(chan, j); ++ return rv; ++ case DAHDI_GETTONEZONE: ++ spin_lock_irqsave(&chan->lock, flags); ++ j = (chan->curzone) ? chan->curzone->num : 0; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ put_user(j, (int __user *) data); ++ break; ++ case DAHDI_SENDTONE: ++ get_user(j, (int __user *)data); ++ spin_lock_irqsave(&chan->lock, flags); ++ rv = start_tone(chan, j); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return rv; ++ case DAHDI_GETCONF_V1: /* intentional drop through */ ++ case DAHDI_GETCONF: /* get conf stuff */ ++ return dahdi_ioctl_getconf(file, data); ++ ++ case DAHDI_SETCONF_V1: /* Intentional fall through. */ ++ case DAHDI_SETCONF: /* set conf stuff */ ++ return dahdi_ioctl_setconf(file, data); ++ ++ case DAHDI_CONFDIAG_V1: /* Intentional fall-through */ ++ case DAHDI_CONFDIAG: /* output diagnostic info to console */ ++ return dahdi_ioctl_confdiag(file, data); ++ ++ case DAHDI_CHANNO: /* get channel number of stream */ ++ /* return channel number */ ++ put_user(chan->channo, (int __user *)data); ++ break; ++ case DAHDI_SETLAW: ++ get_user(j, (int __user *)data); ++ if ((j < 0) || (j > DAHDI_LAW_ALAW)) ++ return -EINVAL; ++ dahdi_set_law(chan, j); ++ break; ++ case DAHDI_SETLINEAR: ++ get_user(j, (int __user *)data); ++ /* Makes no sense on non-audio channels */ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) ++ return -EINVAL; ++ ++ if (j) ++ chan->flags |= DAHDI_FLAG_LINEAR; ++ else ++ chan->flags &= ~DAHDI_FLAG_LINEAR; ++ break; ++ case DAHDI_SETCADENCE: ++ if (data) { ++ /* Use specific ring cadence */ ++ if (copy_from_user(&stack.cad, user_data, ++ sizeof(stack.cad))) { ++ return -EFAULT; ++ } ++ memcpy(chan->ringcadence, &stack.cad, sizeof(chan->ringcadence)); ++ chan->firstcadencepos = 0; ++ /* Looking for negative ringing time indicating where to loop back into ringcadence */ ++ for (i=0; iringcadence[i]<0) { ++ chan->ringcadence[i] *= -1; ++ chan->firstcadencepos = i; ++ break; ++ } ++ } ++ } else { ++ /* Reset to default */ ++ chan->firstcadencepos = 0; ++ if (chan->curzone) { ++ memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence)); ++ /* Looking for negative ringing time indicating where to loop back into ringcadence */ ++ for (i=0; iringcadence[i]<0) { ++ chan->ringcadence[i] *= -1; ++ chan->firstcadencepos = i; ++ break; ++ } ++ } ++ } else { ++ memset(chan->ringcadence, 0, sizeof(chan->ringcadence)); ++ chan->ringcadence[0] = chan->starttime; ++ chan->ringcadence[1] = DAHDI_RINGOFFTIME; ++ } ++ } ++ break; ++ default: ++ /* Check for common ioctl's and private ones */ ++ rv = dahdi_common_ioctl(file, cmd, data); ++ /* if no span, just return with value */ ++ if (!chan->span) return rv; ++ if ((rv == -ENOTTY) && chan->span->ops->ioctl) ++ rv = chan->span->ops->ioctl(chan, cmd, data); ++ return rv; ++ ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_DAHDI_PPP ++/* ++ * This is called at softirq (BH) level when there are calls ++ * we need to make to the ppp_generic layer. We do it this ++ * way because the ppp_generic layer functions may not be called ++ * at interrupt level. ++ */ ++static void do_ppp_calls(unsigned long data) ++{ ++ struct dahdi_chan *chan = (struct dahdi_chan *) data; ++ struct sk_buff *skb; ++ ++ if (!chan->ppp) ++ return; ++ if (chan->do_ppp_wakeup) { ++ chan->do_ppp_wakeup = 0; ++ ppp_output_wakeup(chan->ppp); ++ } ++ while ((skb = skb_dequeue(&chan->ppp_rq)) != NULL) ++ ppp_input(chan->ppp, skb); ++ if (chan->do_ppp_error) { ++ chan->do_ppp_error = 0; ++ ppp_input_error(chan->ppp, 0); ++ } ++} ++#endif ++ ++static int ++ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ const void __user *data) ++{ ++ struct dahdi_echocan_state *ec = NULL, *ec_state; ++ const struct dahdi_echocan_factory *ec_current; ++ struct dahdi_echocanparam *params; ++ int ret = 0; ++ unsigned long flags; ++ ++ if (ecp->param_count > DAHDI_MAX_ECHOCANPARAMS) ++ return -E2BIG; ++ ++ if (ecp->tap_length == 0) { ++ /* disable mode, don't need to inspect params */ ++ mutex_lock(&chan->mutex); ++ spin_lock_irqsave(&chan->lock, flags); ++ ec_state = chan->ec_state; ++ chan->ec_state = NULL; ++ ec_current = chan->ec_current; ++ chan->ec_current = NULL; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (ec_state) { ++ ec_state->ops->echocan_free(chan, ec_state); ++ release_echocan(ec_current); ++ } ++ mutex_unlock(&chan->mutex); ++ return 0; ++ } ++ ++ params = kmalloc(sizeof(params[0]) * DAHDI_MAX_ECHOCANPARAMS, GFP_KERNEL); ++ ++ if (!params) ++ return -ENOMEM; ++ ++ /* enable mode, need the params */ ++ ++ if (copy_from_user(params, data, ++ sizeof(params[0]) * ecp->param_count)) { ++ ret = -EFAULT; ++ goto exit_with_free; ++ } ++ ++ mutex_lock(&chan->mutex); ++ /* free any echocan that may be on the channel already */ ++ spin_lock_irqsave(&chan->lock, flags); ++ ec_state = chan->ec_state; ++ chan->ec_state = NULL; ++ ec_current = chan->ec_current; ++ chan->ec_current = NULL; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (ec_state) { ++ ec_state->ops->echocan_free(chan, ec_state); ++ release_echocan(ec_current); ++ } ++ ++ switch (ecp->tap_length) { ++ case 32: ++ case 64: ++ case 128: ++ case 256: ++ case 512: ++ case 1024: ++ break; ++ default: ++ ecp->tap_length = deftaps; ++ } ++ ++ ec_current = NULL; ++ ++ if (chan->ec_factory) { ++ /* try to get another reference to the module providing ++ this channel's echo canceler */ ++ if (!try_module_get(chan->ec_factory->owner)) { ++ module_printk(KERN_ERR, "Cannot get a reference to the" ++ " '%s' echo canceler\n", ++ chan->ec_factory->get_name(chan)); ++ goto exit_with_free; ++ } ++ ++ /* got the reference, copy the pointer and use it for making ++ an echo canceler instance if possible */ ++ ec_current = chan->ec_factory; ++ ++ ret = ec_current->echocan_create(chan, ecp, params, &ec); ++ if (ret) { ++ release_echocan(ec_current); ++ ++ goto exit_with_free; ++ } ++ if (!ec) { ++ module_printk(KERN_ERR, "%s failed to allocate an " \ ++ "dahdi_echocan_state instance.\n", ++ ec_current->get_name(chan)); ++ ret = -EFAULT; ++ goto exit_with_free; ++ } ++ } ++ ++ if (ec) { ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->ec_current = ec_current; ++ chan->ec_state = ec; ++ ec->status.mode = ECHO_MODE_ACTIVE; ++ if (!ec->features.CED_tx_detect) { ++ echo_can_disable_detector_init(&chan->ec_state->txecdis); ++ } ++ if (!ec->features.CED_rx_detect) { ++ echo_can_disable_detector_init(&chan->ec_state->rxecdis); ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ } ++ ++exit_with_free: ++ mutex_unlock(&chan->mutex); ++ kfree(params); ++ ++ return ret; ++} ++ ++static void set_echocan_fax_mode(struct dahdi_chan *chan, unsigned int channo, const char *reason, unsigned int enable) ++{ ++ if (enable) { ++ if (!chan->ec_state) ++ module_printk(KERN_NOTICE, "Ignoring FAX mode request because of %s for channel %d with no echo canceller\n", reason, channo); ++ else if (chan->ec_state->status.mode == ECHO_MODE_FAX) ++ module_printk(KERN_NOTICE, "Ignoring FAX mode request because of %s for echo canceller already in FAX mode on channel %d\n", reason, channo); ++ else if (chan->ec_state->status.mode != ECHO_MODE_ACTIVE) ++ module_printk(KERN_NOTICE, "Ignoring FAX mode request because of %s for echo canceller not in active mode on channel %d\n", reason, channo); ++ else if (chan->ec_state->features.NLP_automatic) { ++ /* for echocans that automatically do the right thing, just ++ * mark it as being in FAX mode without making any ++ * changes, as none are necessary. ++ */ ++ chan->ec_state->status.mode = ECHO_MODE_FAX; ++ } else if (chan->ec_state->features.NLP_toggle) { ++ module_printk(KERN_NOTICE, "Disabled echo canceller NLP because of %s on channel %d\n", reason, channo); ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_EC_NLP_DISABLED); ++ chan->ec_state->ops->echocan_NLP_toggle(chan->ec_state, 0); ++ chan->ec_state->status.mode = ECHO_MODE_FAX; ++ } else { ++ module_printk(KERN_NOTICE, "Idled echo canceller because of %s on channel %d\n", reason, channo); ++ chan->ec_state->status.mode = ECHO_MODE_IDLE; ++ } ++ } else { ++ if (!chan->ec_state) ++ module_printk(KERN_NOTICE, "Ignoring voice mode request because of %s for channel %d with no echo canceller\n", reason, channo); ++ else if (chan->ec_state->status.mode == ECHO_MODE_ACTIVE) ++ module_printk(KERN_NOTICE, "Ignoring voice mode request because of %s for echo canceller already in voice mode on channel %d\n", reason, channo); ++ else if ((chan->ec_state->status.mode != ECHO_MODE_FAX) && ++ (chan->ec_state->status.mode != ECHO_MODE_IDLE)) ++ module_printk(KERN_NOTICE, "Ignoring voice mode request because of %s for echo canceller not in FAX or idle mode on channel %d\n", reason, channo); ++ else if (chan->ec_state->features.NLP_automatic) { ++ /* for echocans that automatically do the right thing, just ++ * mark it as being in active mode without making any ++ * changes, as none are necessary. ++ */ ++ chan->ec_state->status.mode = ECHO_MODE_ACTIVE; ++ } else if (chan->ec_state->features.NLP_toggle) { ++ module_printk(KERN_NOTICE, "Enabled echo canceller NLP because of %s on channel %d\n", reason, channo); ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_EC_NLP_ENABLED); ++ chan->ec_state->ops->echocan_NLP_toggle(chan->ec_state, 1); ++ chan->ec_state->status.mode = ECHO_MODE_ACTIVE; ++ } else { ++ module_printk(KERN_NOTICE, "Activated echo canceller because of %s on channel %d\n", reason, channo); ++ chan->ec_state->status.mode = ECHO_MODE_ACTIVE; ++ } ++ } ++} ++ ++static inline bool ++is_txstate(struct dahdi_chan *const chan, const int txstate) ++{ ++ bool ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ ret = (txstate == chan->txstate); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return ret; ++} ++ ++static int dahdi_chan_ioctl(struct file *file, unsigned int cmd, unsigned long data) ++{ ++ struct dahdi_chan *const chan = chan_from_file(file); ++ unsigned long flags; ++ int j; ++ int ret; ++ int oldconf; ++ const void *rxgain = NULL; ++ ++ if (!chan) ++ return -ENOSYS; ++ ++ WARN_ON(!chan->master); ++ ++ switch(cmd) { ++ case DAHDI_SETSIGFREEZE: ++ get_user(j, (int __user *)data); ++ spin_lock_irqsave(&chan->lock, flags); ++ if (j) { ++ chan->flags |= DAHDI_FLAG_SIGFREEZE; ++ } else { ++ chan->flags &= ~DAHDI_FLAG_SIGFREEZE; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ break; ++ case DAHDI_GETSIGFREEZE: ++ spin_lock_irqsave(&chan->lock, flags); ++ if (chan->flags & DAHDI_FLAG_SIGFREEZE) ++ j = 1; ++ else ++ j = 0; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ put_user(j, (int __user *)data); ++ break; ++ case DAHDI_AUDIOMODE: ++ /* Only literal clear channels can be put in */ ++ if (chan->sig != DAHDI_SIG_CLEAR) return (-EINVAL); ++ get_user(j, (int __user *)data); ++ if (j) { ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->flags |= DAHDI_FLAG_AUDIO; ++ chan->flags &= ~(DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ } else { ++ /* Coming out of audio mode, also clear all ++ conferencing and gain related info as well ++ as echo canceller */ ++ struct dahdi_echocan_state *ec_state; ++ const struct dahdi_echocan_factory *ec_current; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->flags &= ~DAHDI_FLAG_AUDIO; ++ /* save old conf number, if any */ ++ oldconf = chan->confna; ++ /* initialize conference variables */ ++ chan->_confn = 0; ++ chan->confna = 0; ++ chan->conf_chan = NULL; ++ dahdi_disable_dacs(chan); ++ chan->confmode = 0; ++ chan->confmute = 0; ++ memset(chan->conflast, 0, sizeof(chan->conflast)); ++ memset(chan->conflast1, 0, sizeof(chan->conflast1)); ++ memset(chan->conflast2, 0, sizeof(chan->conflast2)); ++ ec_state = chan->ec_state; ++ chan->ec_state = NULL; ++ ec_current = chan->ec_current; ++ chan->ec_current = NULL; ++ /* release conference resource, if any to release */ ++ reset_conf(chan); ++ if (is_gain_allocated(chan)) ++ rxgain = chan->rxgain; ++ else ++ rxgain = NULL; ++ ++ chan->rxgain = defgain; ++ chan->txgain = defgain; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ if (ec_state) { ++ ec_state->ops->echocan_free(chan, ec_state); ++ release_echocan(ec_current); ++ } ++ ++ if (rxgain) ++ kfree(rxgain); ++ if (oldconf) dahdi_check_conf(oldconf); ++ } ++#ifdef DAHDI_AUDIO_NOTIFY ++ if (chan->span->ops->audio_notify) ++ chan->span->ops->audio_notify(chan, j); ++#endif ++ break; ++ case DAHDI_HDLCPPP: ++#ifdef CONFIG_DAHDI_PPP ++ if (chan->sig != DAHDI_SIG_CLEAR) return (-EINVAL); ++ get_user(j, (int __user *)data); ++ if (j) { ++ if (!chan->ppp) { ++ chan->ppp = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); ++ if (chan->ppp) { ++ struct dahdi_echocan_state *tec; ++ const struct dahdi_echocan_factory *ec_current; ++ ++ chan->ppp->private = chan; ++ chan->ppp->ops = &ztppp_ops; ++ chan->ppp->mtu = DAHDI_DEFAULT_MTU_MRU; ++ chan->ppp->hdrlen = 0; ++ skb_queue_head_init(&chan->ppp_rq); ++ chan->do_ppp_wakeup = 0; ++ tasklet_init(&chan->ppp_calls, do_ppp_calls, ++ (unsigned long)chan); ++ if ((ret = dahdi_reallocbufs(chan, DAHDI_DEFAULT_MTU_MRU, DAHDI_DEFAULT_NUM_BUFS))) { ++ kfree(chan->ppp); ++ chan->ppp = NULL; ++ return ret; ++ } ++ ++ if ((ret = ppp_register_channel(chan->ppp))) { ++ kfree(chan->ppp); ++ chan->ppp = NULL; ++ return ret; ++ } ++ tec = chan->ec_state; ++ chan->ec_state = NULL; ++ ec_current = chan->ec_current; ++ chan->ec_current = NULL; ++ /* Make sure there's no gain */ ++ if (is_gain_allocated(chan)) ++ kfree(chan->rxgain); ++ chan->rxgain = defgain; ++ chan->txgain = defgain; ++ chan->flags &= ~DAHDI_FLAG_AUDIO; ++ chan->flags |= (DAHDI_FLAG_PPP | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS); ++ ++ if (tec) { ++ tec->ops->echocan_free(chan, tec); ++ release_echocan(ec_current); ++ } ++ } else ++ return -ENOMEM; ++ } ++ } else { ++ chan->flags &= ~(DAHDI_FLAG_PPP | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS); ++ if (chan->ppp) { ++ struct ppp_channel *ppp = chan->ppp; ++ chan->ppp = NULL; ++ tasklet_kill(&chan->ppp_calls); ++ skb_queue_purge(&chan->ppp_rq); ++ ppp_unregister_channel(ppp); ++ kfree(ppp); ++ } ++ } ++#else ++ module_printk(KERN_NOTICE, "PPP support not compiled in\n"); ++ return -ENOSYS; ++#endif ++ break; ++ case DAHDI_HDLCRAWMODE: ++ if (chan->sig != DAHDI_SIG_CLEAR) return (-EINVAL); ++ get_user(j, (int __user *)data); ++ chan->flags &= ~(DAHDI_FLAG_AUDIO | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS); ++ if (j) { ++ chan->flags |= DAHDI_FLAG_HDLC; ++ fasthdlc_init(&chan->rxhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ fasthdlc_init(&chan->txhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ } ++ break; ++ case DAHDI_HDLCFCSMODE: ++ if (chan->sig != DAHDI_SIG_CLEAR) return (-EINVAL); ++ get_user(j, (int __user *)data); ++ chan->flags &= ~(DAHDI_FLAG_AUDIO | DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS); ++ if (j) { ++ chan->flags |= DAHDI_FLAG_HDLC | DAHDI_FLAG_FCS; ++ fasthdlc_init(&chan->rxhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ fasthdlc_init(&chan->txhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ } ++ break; ++ case DAHDI_HDLC_RATE: ++ get_user(j, (int __user *)data); ++ if (j == 56) { ++ chan->flags |= DAHDI_FLAG_HDLC56; ++ } else { ++ chan->flags &= ~DAHDI_FLAG_HDLC56; ++ } ++ ++ fasthdlc_init(&chan->rxhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ fasthdlc_init(&chan->txhdlc, (chan->flags & DAHDI_FLAG_HDLC56) ? FASTHDLC_MODE_56 : FASTHDLC_MODE_64); ++ break; ++ case DAHDI_ECHOCANCEL_PARAMS: ++ { ++ struct dahdi_echocanparams ecp; ++ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) ++ return -EINVAL; ++ ret = copy_from_user(&ecp, ++ (struct dahdi_echocanparams __user *)data, ++ sizeof(ecp)); ++ if (ret) ++ return -EFAULT; ++ data += sizeof(ecp); ++ ret = ioctl_echocancel(chan, &ecp, (void __user *)data); ++ if (ret) ++ return ret; ++ break; ++ } ++ case DAHDI_ECHOCANCEL: ++ { ++ struct dahdi_echocanparams ecp; ++ ++ if (!(chan->flags & DAHDI_FLAG_AUDIO)) ++ return -EINVAL; ++ get_user(j, (int __user *) data); ++ ecp.tap_length = j; ++ ecp.param_count = 0; ++ if ((ret = ioctl_echocancel(chan, &ecp, NULL))) ++ return ret; ++ break; ++ } ++ case DAHDI_ECHOTRAIN: ++ /* get pre-training time from user */ ++ get_user(j, (int __user *)data); ++ if ((j < 0) || (j >= DAHDI_MAX_PRETRAINING)) ++ return -EINVAL; ++ j <<= 3; ++ spin_lock_irqsave(&chan->lock, flags); ++ if (chan->ec_state) { ++ /* Start pretraining stage */ ++ if (chan->ec_state->ops->echocan_traintap) { ++ chan->ec_state->status.mode = ECHO_MODE_PRETRAINING; ++ chan->ec_state->status.pretrain_timer = j; ++ } ++ spin_unlock_irqrestore(&chan->lock, flags); ++ } else { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -EINVAL; ++ } ++ break; ++ case DAHDI_ECHOCANCEL_FAX_MODE: ++ if (!chan->ec_state) { ++ return -EINVAL; ++ } else { ++ get_user(j, (int __user *) data); ++ spin_lock_irqsave(&chan->lock, flags); ++ set_echocan_fax_mode(chan, chan->channo, "ioctl", j ? 1 : 0); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ } ++ break; ++ case DAHDI_SETTXBITS: ++ if (chan->sig != DAHDI_SIG_CAS) ++ return -EINVAL; ++ get_user(j, (int __user *)data); ++ dahdi_cas_setbits(chan, j); ++ break; ++ case DAHDI_GETRXBITS: ++ put_user(chan->rxsig, (int __user *)data); ++ break; ++ case DAHDI_LOOPBACK: ++ get_user(j, (int __user *)data); ++ spin_lock_irqsave(&chan->lock, flags); ++ if (j) ++ chan->flags |= DAHDI_FLAG_LOOPED; ++ else ++ chan->flags &= ~DAHDI_FLAG_LOOPED; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ break; ++ case DAHDI_HOOK: ++ get_user(j, (int __user *)data); ++ if (chan->flags & DAHDI_FLAG_CLEAR) ++ return -EINVAL; ++ if (chan->sig == DAHDI_SIG_CAS) ++ return -EINVAL; ++ /* if no span, just do nothing */ ++ if (!chan->span) return(0); ++ spin_lock_irqsave(&chan->lock, flags); ++ /* if dialing, stop it */ ++ chan->curtone = NULL; ++ chan->dialing = 0; ++ chan->txdialbuf[0] = '\0'; ++ chan->tonep = 0; ++ chan->pdialcount = 0; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (chan->span->flags & DAHDI_FLAG_RBS) { ++ switch (j) { ++ case DAHDI_ONHOOK: ++ spin_lock_irqsave(&chan->lock, flags); ++ dahdi_hangup(chan); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ break; ++ case DAHDI_OFFHOOK: ++ spin_lock_irqsave(&chan->lock, flags); ++ if ((chan->txstate == DAHDI_TXSTATE_KEWL) || ++ (chan->txstate == DAHDI_TXSTATE_AFTERKEWL)) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -EBUSY; ++ } ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_DEBOUNCE, chan->debouncetime); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ break; ++ case DAHDI_RING: ++ case DAHDI_START: ++ spin_lock_irqsave(&chan->lock, flags); ++ if (!chan->curzone) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ module_printk(KERN_WARNING, "Cannot start tone until a tone zone is loaded.\n"); ++ return -ENODATA; ++ } ++ if (chan->txstate != DAHDI_TXSTATE_ONHOOK) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -EBUSY; ++ } ++ if (chan->sig & __DAHDI_SIG_FXO) { ++ ret = 0; ++ chan->cadencepos = 0; ++ ret = chan->ringcadence[0]; ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_START, DAHDI_TXSTATE_RINGON, ret); ++ } else ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_START, DAHDI_TXSTATE_START, chan->starttime); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (file->f_flags & O_NONBLOCK) ++ return -EINPROGRESS; ++ break; ++ case DAHDI_WINK: ++ spin_lock_irqsave(&chan->lock, flags); ++ if (chan->txstate != DAHDI_TXSTATE_ONHOOK) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -EBUSY; ++ } ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_PREWINK, chan->prewinktime); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (file->f_flags & O_NONBLOCK) ++ return -EINPROGRESS; ++ wait_event_interruptible(chan->waitq, ++ !chan->file->private_data || is_txstate(chan, DAHDI_TXSIG_ONHOOK)); ++ if (unlikely(!chan->file->private_data)) ++ return -ENODEV; ++ if (signal_pending(current)) ++ return -ERESTARTSYS; ++ break; ++ case DAHDI_FLASH: ++ spin_lock_irqsave(&chan->lock, flags); ++ if (chan->txstate != DAHDI_TXSTATE_OFFHOOK) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -EBUSY; ++ } ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_PREFLASH, chan->preflashtime); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ if (file->f_flags & O_NONBLOCK) ++ return -EINPROGRESS; ++ wait_event_interruptible(chan->waitq, ++ !chan->file->private_data || is_txstate(chan, DAHDI_TXSIG_OFFHOOK)); ++ if (unlikely(!chan->file->private_data)) ++ return -ENODEV; ++ if (signal_pending(current)) ++ return -ERESTARTSYS; ++ break; ++ case DAHDI_RINGOFF: ++ spin_lock_irqsave(&chan->lock, flags); ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_ONHOOK, 0); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ break; ++ default: ++ return -EINVAL; ++ } ++ } else if (chan->span->ops->sethook) { ++ if (chan->txhooksig != j) { ++ chan->txhooksig = j; ++ chan->span->ops->sethook(chan, j); ++ } ++ } else ++ return -ENOSYS; ++ break; ++#ifdef CONFIG_DAHDI_PPP ++ case PPPIOCGCHAN: ++ if (chan->flags & DAHDI_FLAG_PPP) { ++ return put_user(ppp_channel_index(chan->ppp), ++ (int __user *)data) ? -EFAULT : 0; ++ } else { ++ return -EINVAL; ++ } ++ break; ++ case PPPIOCGUNIT: ++ if (chan->flags & DAHDI_FLAG_PPP) { ++ return put_user(ppp_unit_number(chan->ppp), ++ (int __user *)data) ? -EFAULT : 0; ++ } else { ++ return -EINVAL; ++ } ++ break; ++#endif ++ case DAHDI_BUFFER_EVENTS: ++ if (get_user(j, (int __user *)data)) ++ return -EFAULT; ++ if (j) ++ set_bit(DAHDI_FLAGBIT_BUFEVENTS, &chan->flags); ++ else ++ clear_bit(DAHDI_FLAGBIT_BUFEVENTS, &chan->flags); ++ ++ break; ++ default: ++ return dahdi_chanandpseudo_ioctl(file, cmd, data); ++ } ++ return 0; ++} ++ ++static int dahdi_prechan_ioctl(struct file *file, unsigned int cmd, unsigned long data) ++{ ++ int channo; ++ int res; ++ ++ if (file->private_data) { ++ module_printk(KERN_NOTICE, "Huh? Prechan already has private data??\n"); ++ } ++ switch(cmd) { ++ case DAHDI_SPECIFY: ++ get_user(channo, (int __user *)data); ++ file->private_data = chan_from_num(channo); ++ if (!file->private_data) ++ return -EINVAL; ++ res = dahdi_specchan_open(file); ++ if (res) ++ file->private_data = NULL; ++ return res; ++ default: ++ return -ENOSYS; ++ } ++ return 0; ++} ++ ++static long ++dahdi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data) ++{ ++ int unit = UNIT(file); ++ int ret; ++ ++ if (unit == DAHDI_CTL) { ++ ret = dahdi_ctl_ioctl(file, cmd, data); ++ goto exit; ++ } ++ ++ if (unit == DAHDI_TRANSCODE) { ++ /* dahdi_transcode should have updated the file_operations on ++ * this file object on open, so we shouldn't be here. */ ++ WARN_ON(1); ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ if (unit == DAHDI_TIMER) { ++ /* The file operations for a timer device should have been ++ * updated. */ ++ WARN_ON(1); ++ ret = -EFAULT; ++ goto exit; ++ } ++ if (unit == DAHDI_CHANNEL) { ++ if (file->private_data) ++ ret = dahdi_chan_ioctl(file, cmd, data); ++ else ++ ret = dahdi_prechan_ioctl(file, cmd, data); ++ goto exit; ++ } ++ if (unit == DAHDI_PSEUDO) { ++ if (!file->private_data) { ++ module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); ++ ret = -EINVAL; ++ goto exit; ++ } ++ ret = dahdi_chanandpseudo_ioctl(file, cmd, data); ++ goto exit; ++ } ++ ++ if (!file->private_data) { ++ ret = -ENXIO; ++ goto exit; ++ } ++ ++ ret = dahdi_chan_ioctl(file, cmd, data); ++ ++exit: ++ return ret; ++} ++ ++#ifndef HAVE_UNLOCKED_IOCTL ++static int dahdi_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long data) ++{ ++ return dahdi_unlocked_ioctl(file, cmd, data); ++} ++#endif ++ ++#ifdef HAVE_COMPAT_IOCTL ++static long dahdi_ioctl_compat(struct file *file, unsigned int cmd, ++ unsigned long data) ++{ ++ if (cmd == DAHDI_SFCONFIG) ++ return -ENOTTY; /* Not supported yet */ ++ ++ return dahdi_unlocked_ioctl(file, cmd, data); ++} ++#endif ++ ++/** ++ * _get_next_channo - Return the next taken channel number from the span list. ++ * @span: The span with which to start the search. ++ * ++ * Returns -1 if there aren't any channels on span or any of the following ++ * spans, otherwise, returns the channel number of the first channel. ++ * ++ * Must be callled with registration_mutex held. ++ * ++ */ ++static unsigned int _get_next_channo(const struct dahdi_span *span) ++{ ++ const struct list_head *pos = &span->spans_node; ++ while (pos != &span_list) { ++ span = list_entry(pos, struct dahdi_span, spans_node); ++ if (span->channels) ++ return span->chans[0]->channo; ++ pos = pos->next; ++ } ++ return -1; ++} ++ ++static void ++set_spanno_and_basechan(struct dahdi_span *span, u32 spanno, u32 basechan) ++{ ++ int i; ++ dahdi_dev_dbg(ASSIGN, span_device(span), ++ "set: spanno=%d, basechan=%d (span->channels=%d)\n", ++ spanno, basechan, span->channels); ++ span->spanno = spanno; ++ for (i = 0; i < span->channels; ++i) ++ span->chans[i]->channo = basechan + i; ++} ++ ++/** ++ * _assign_spanno_and_basechan - Assign next available span and channel numbers. ++ * ++ * This function will set span->spanno and channo for all the member channels. ++ * It will assign the first available location. ++ * ++ * Must be called with registration_mutex held. ++ * ++ */ ++static int _assign_spanno_and_basechan(struct dahdi_span *span) ++{ ++ struct dahdi_span *pos; ++ unsigned int next_channo; ++ unsigned int spanno = 1; ++ unsigned int basechan = 1; ++ ++ dahdi_dev_dbg(ASSIGN, span_device(span), ++ "assign: channels=%d\n", span->channels); ++ list_for_each_entry(pos, &span_list, spans_node) { ++ ++ if (pos->spanno <= spanno) { ++ spanno = pos->spanno + 1; ++ basechan = pos->chans[0]->channo + pos->channels; ++ continue; ++ } ++ ++ next_channo = _get_next_channo(pos); ++ if ((basechan + span->channels) <= next_channo) ++ break; ++ ++ /* We can't fit here, let's look at the next location. */ ++ spanno = pos->spanno + 1; ++ if (pos->channels) ++ basechan = pos->chans[0]->channo + pos->channels; ++ } ++ ++ dahdi_dev_dbg(ASSIGN, span_device(span), ++ "good: spanno=%d, basechan=%d (span->channels=%d)\n", ++ spanno, basechan, span->channels); ++ set_spanno_and_basechan(span, spanno, basechan); ++ return 0; ++} ++ ++static inline struct dahdi_span *span_from_node(struct list_head *node) ++{ ++ return container_of(node, struct dahdi_span, spans_node); ++} ++ ++/* ++ * Call with registration_mutex held. Make sure all the spans are on the list ++ * ordered by span. ++ * ++ */ ++static void _dahdi_add_span_to_span_list(struct dahdi_span *span) ++{ ++ unsigned long flags; ++ struct dahdi_span *pos; ++ ++ if (list_empty(&span_list)) { ++ list_add_tail(&span->spans_node, &span_list); ++ return; ++ } ++ ++ list_for_each_entry(pos, &span_list, spans_node) { ++ WARN_ON(0 == pos->spanno); ++ if (pos->spanno > span->spanno) ++ break; ++ } ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ list_add(&span->spans_node, pos->spans_node.prev); ++ spin_unlock_irqrestore(&chan_lock, flags); ++} ++ ++/** ++ * _check_spanno_and_basechan - Check if we can fit the new span in the requested location. ++ * ++ * Must be called with registration_mutex held. ++ * ++ */ ++static int ++_check_spanno_and_basechan(struct dahdi_span *span, u32 spanno, u32 basechan) ++{ ++ struct dahdi_span *pos; ++ unsigned int next_channo; ++ ++ dahdi_dev_dbg(ASSIGN, span_device(span), ++ "check: spanno=%d, basechan=%d (span->channels=%d)\n", ++ spanno, basechan, span->channels); ++ list_for_each_entry(pos, &span_list, spans_node) { ++ ++ next_channo = _get_next_channo(pos); ++ dahdi_dev_dbg(ASSIGN, span_device(span), ++ "pos: spanno=%d channels=%d (next_channo=%d)\n", ++ pos->spanno, pos->channels, next_channo); ++ ++ if (pos->spanno <= spanno) { ++ if (basechan < next_channo + pos->channels) { ++ /* Requested basechan breaks channel sorting */ ++ dev_notice(span_device(span), ++ "[%d] basechan (%d) is too low for wanted span %d\n", ++ local_spanno(span), basechan, spanno); ++ return -EINVAL; ++ } ++ continue; ++ } ++ ++ if (next_channo == -1) ++ break; ++ ++ if ((basechan + span->channels) <= next_channo) ++ break; ++ ++ /* Cannot fit the span into the requested location. Abort. */ ++ dev_notice(span_device(span), ++ "cannot fit span %d (basechan=%d) into requested location\n", ++ spanno, basechan); ++ return -EINVAL; ++ } ++ ++ dahdi_dev_dbg(ASSIGN, span_device(span), ++ "good: spanno=%d, basechan=%d (span->channels=%d)\n", ++ spanno, basechan, span->channels); ++ set_spanno_and_basechan(span, spanno, basechan); ++ return 0; ++} ++ ++ ++struct dahdi_device *dahdi_create_device(void) ++{ ++ struct dahdi_device *ddev; ++ ddev = kzalloc(sizeof(*ddev), GFP_KERNEL); ++ if (!ddev) ++ return NULL; ++ INIT_LIST_HEAD(&ddev->spans); ++ dahdi_sysfs_init_device(ddev); ++ return ddev; ++} ++EXPORT_SYMBOL(dahdi_create_device); ++ ++void dahdi_free_device(struct dahdi_device *ddev) ++{ ++ put_device(&ddev->dev); ++} ++EXPORT_SYMBOL(dahdi_free_device); ++ ++/** ++ * __dahdi_init_span - Setup all the data structures for the span. ++ * @span: The span of interest. ++ * ++ */ ++static void __dahdi_init_span(struct dahdi_span *span) ++{ ++ int x; ++ ++ INIT_LIST_HEAD(&span->spans_node); ++ spin_lock_init(&span->lock); ++ clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags); ++ ++ if (!span->deflaw) { ++ module_printk(KERN_NOTICE, "Span %s didn't specify default " ++ "law. Assuming mulaw, please fix driver!\n", ++ span->name); ++ span->deflaw = DAHDI_LAW_MULAW; ++ } ++ if (span->spantype == SPANTYPE_INVALID) { ++ module_printk(KERN_NOTICE, ++ "Warning: Span %s didn't specify a spantype. " ++ "Please fix driver!\n", span->name); ++ } ++ ++ for (x = 0; x < span->channels; ++x) { ++ span->chans[x]->span = span; ++ __dahdi_init_chan(span->chans[x]); ++ } ++} ++ ++/** ++ * dahdi_init_span - (Re)Initializes a dahdi span. ++ * @span: The span to initialize. ++ * ++ * Reinitializing a device span might be necessary if a span has been changed ++ * (channels added / removed) between when the dahdi_device it is on was first ++ * registered and when the spans are actually assigned. ++ * ++ */ ++void dahdi_init_span(struct dahdi_span *span) ++{ ++ mutex_lock(®istration_mutex); ++ __dahdi_init_span(span); ++ mutex_unlock(®istration_mutex); ++} ++EXPORT_SYMBOL(dahdi_init_span); ++ ++/** ++ * _dahdi_assign_span() - Assign a new DAHDI span ++ * @span: the DAHDI span ++ * @spanno: The span number we would like assigned. If 0, the first ++ * available spanno/basechan will be used. ++ * @basechan: The base channel number we would like. Ignored if spanno is 0. ++ * @prefmaster: will the new span be preferred as a master_span? ++ * ++ * Assigns a span for usage with DAHDI. All the channel numbers in it will ++ * have their numbering started at basechan. ++ * ++ * If prefmaster is set to anything > 0, span will attempt to become the ++ * master DAHDI span at registration time. If 0: it will only become ++ * master if no other span is currently the master (i.e.: it is the ++ * first one). ++ * ++ * Must be called with registration_mutex held, and the span must have already ++ * been initialized ith the __dahdi_init_span call. ++ * ++ */ ++static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno, ++ unsigned int basechan, int prefmaster) ++{ ++ int res = 0; ++ unsigned int x; ++ unsigned long flags; ++ ++ if (!span || !span->ops || !span->ops->owner) ++ return -EFAULT; ++ ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) { ++ dev_notice(span_device(span), ++ "local span %d is already assigned span %d\n", ++ local_spanno(span), span->spanno); ++ return -EINVAL; ++ } ++ ++ /* DAHDI_ALARM_NOTOPEN can be set when a span is disabled, i.e. via ++ * sysfs, so when the span is being reassigned we should make sure it's ++ * cleared. This eliminates the need for board drivers to re-report ++ * their alarm states on span reassignment. */ ++ ++ spin_lock_irqsave(&span->lock, flags); ++ span->alarms &= ~DAHDI_ALARM_NOTOPEN; ++ dahdi_alarm_notify(span); ++ spin_unlock_irqrestore(&span->lock, flags); ++ ++ if (span->ops->enable_hw_preechocan || ++ span->ops->disable_hw_preechocan) { ++ if ((NULL == span->ops->enable_hw_preechocan) || ++ (NULL == span->ops->disable_hw_preechocan)) { ++ dev_notice(span_device(span), ++ "span with inconsistent enable/disable hw_preechocan"); ++ return -EFAULT; ++ } ++ } ++ ++ if (!span->deflaw) { ++ module_printk(KERN_NOTICE, "Span %s didn't specify default law. " ++ "Assuming mulaw, please fix driver!\n", span->name); ++ span->deflaw = DAHDI_LAW_MULAW; ++ } ++ ++ /* Look through the span list to find the first available span number. ++ * The spans are kept on this list in sorted order. We'll also save ++ * off the next available channel number to use. */ ++ ++ if (0 == spanno) ++ res = _assign_spanno_and_basechan(span); ++ else ++ res = _check_spanno_and_basechan(span, spanno, basechan); ++ ++ if (res) ++ return res; ++ ++ for (x = 0; x < span->channels; x++) ++ dahdi_chan_reg(span->chans[x]); ++ ++#ifdef CONFIG_PROC_FS ++ { ++ char tempfile[17]; ++ snprintf(tempfile, sizeof(tempfile), "%d", span->spanno); ++ span->proc_entry = proc_create_data(tempfile, 0444, ++ root_proc_entry, &dahdi_proc_ops, ++ (void *)((unsigned long)span->spanno)); ++ if (!span->proc_entry) { ++ res = -EFAULT; ++ span_err(span, "Error creating procfs entry\n"); ++ goto cleanup; ++ } ++ } ++#endif ++ ++ res = span_sysfs_create(span); ++ if (res) ++ goto cleanup; ++ ++ if (debug & DEBUG_MAIN) { ++ module_printk(KERN_NOTICE, "Registered Span %d ('%s') with " ++ "%d channels\n", span->spanno, span->name, span->channels); ++ } ++ ++ _dahdi_add_span_to_span_list(span); ++ ++ set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags); ++ if (span->ops->assigned) ++ span->ops->assigned(span); ++ ++ __dahdi_find_master_span(); ++ ++ return 0; ++ ++cleanup: ++#ifdef CONFIG_PROC_FS ++ if (span->proc_entry) { ++ char tempfile[17]; ++ ++ snprintf(tempfile, sizeof(tempfile), "dahdi/%d", span->spanno); ++ remove_proc_entry(tempfile, NULL); ++ span->proc_entry = NULL; ++ } ++#endif ++ for (x = 0; x < span->channels; x++) { ++ struct dahdi_chan *chan = span->chans[x]; ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)) ++ dahdi_chan_unreg(chan); ++ } ++ return res; ++} ++ ++int dahdi_assign_span(struct dahdi_span *span, unsigned int spanno, ++ unsigned int basechan, int prefmaster) ++{ ++ int ret; ++ mutex_lock(®istration_mutex); ++ ret = _dahdi_assign_span(span, spanno, basechan, prefmaster); ++ mutex_unlock(®istration_mutex); ++ return ret; ++} ++ ++int dahdi_assign_device_spans(struct dahdi_device *ddev) ++{ ++ struct dahdi_span *span; ++ mutex_lock(®istration_mutex); ++ list_for_each_entry(span, &ddev->spans, device_node) ++ _dahdi_assign_span(span, 0, 0, 1); ++ mutex_unlock(®istration_mutex); ++ return 0; ++} ++ ++static int auto_assign_spans = 1; ++static const char *UNKNOWN = ""; ++ ++/** ++ * dahdi_auto_assign_spans - is the parameter auto_assign_spans set? ++ */ ++int dahdi_get_auto_assign_spans(void) ++{ ++ return auto_assign_spans; ++} ++EXPORT_SYMBOL(dahdi_get_auto_assign_spans); ++ ++/** ++ * _dahdi_register_device - Registers a DAHDI device and assign its spans. ++ * @ddev: the DAHDI device ++ * ++ * If auto_assign_spans is 0, add the device to the device list and wait for ++ * userspace to finish registration. Otherwise, go ahead and register the ++ * spans in order as was done historically. ++ * ++ * Must hold registration_mutex when this function is called. ++ * ++ */ ++static int _dahdi_register_device(struct dahdi_device *ddev, ++ struct device *parent) ++{ ++ struct dahdi_span *s; ++ int ret; ++ ++ ddev->manufacturer = (ddev->manufacturer) ?: UNKNOWN; ++ ddev->location = (ddev->location) ?: UNKNOWN; ++ ddev->devicetype = (ddev->devicetype) ?: UNKNOWN; ++ ++ list_for_each_entry(s, &ddev->spans, device_node) { ++ s->parent = ddev; ++ s->spanno = 0; ++ __dahdi_init_span(s); ++ } ++ ++ ddev->registration_time = ktime_get(); ++ ret = dahdi_sysfs_add_device(ddev, parent); ++ if (ret) ++ return ret; ++ ++ if (!auto_assign_spans) ++ return 0; ++ ++ list_for_each_entry(s, &ddev->spans, device_node) ++ ret = _dahdi_assign_span(s, 0, 0, 1); ++ ++ if (ret) ++ dahdi_sysfs_unregister_device(ddev); ++ ++ return ret; ++} ++ ++/** ++ * dahdi_register_device() - unregister a new DAHDI device ++ * @ddev: the DAHDI device ++ * ++ * Registers a device for usage with DAHDI. ++ * ++ */ ++int dahdi_register_device(struct dahdi_device *ddev, struct device *parent) ++{ ++ int ret; ++ ++ if (!ddev) ++ return -EINVAL; ++ ++ mutex_lock(®istration_mutex); ++ ret = _dahdi_register_device(ddev, parent); ++ mutex_unlock(®istration_mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL(dahdi_register_device); ++ ++static void disable_span(struct dahdi_span *span) ++{ ++ int x; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&span->lock, flags); ++ span->alarms = DAHDI_ALARM_NOTOPEN; ++ for (x = 0; x < span->channels; x++) { ++ /* ++ * This event may not make it to user space before the channel ++ * is gone, but let's try. ++ */ ++ dahdi_qevent_lock(span->chans[x], DAHDI_EVENT_REMOVED); ++ } ++ dahdi_alarm_notify(span); ++ spin_unlock_irqrestore(&span->lock, flags); ++ module_printk(KERN_INFO, "%s: span %d\n", __func__, span->spanno); ++} ++ ++#ifdef CONFIG_PROC_FS ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) ++static inline void proc_remove(struct proc_dir_entry *proc_entry) ++{ ++ remove_proc_entry(proc_entry->name, root_proc_entry); ++} ++#endif ++#endif ++ ++/** ++ * _dahdi_unassign_span() - unassign a DAHDI span ++ * @span: the DAHDI span ++ * ++ * Unassigns a span that has been previously assigned with ++ * dahdi_assign_span(). ++ * ++ * Must be called with the registration_mutex held. ++ * ++ */ ++static int _dahdi_unassign_span(struct dahdi_span *span) ++{ ++ int res; ++ int x; ++ struct dahdi_span *new_master, *s; ++ unsigned long flags; ++ ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) { ++ dev_info(span_device(span), ++ "local span %d is already unassigned\n", ++ local_spanno(span)); ++ return -EINVAL; ++ } ++ spin_lock_irqsave(&chan_lock, flags); ++ list_del_init(&span->spans_node); ++ spin_unlock_irqrestore(&chan_lock, flags); ++ span->spanno = 0; ++ clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags); ++ ++ res = dahdi_shutdown_span(span); ++ if (res) { ++ dev_err(span_device(span), ++ "Failed to shutdown when unassigning.\n"); ++ } ++ ++ if (debug & DEBUG_MAIN) ++ module_printk(KERN_NOTICE, "Unassigning Span '%s' with %d channels\n", span->name, span->channels); ++#ifdef CONFIG_PROC_FS ++ if (span->proc_entry) { ++ proc_remove(span->proc_entry); ++ span->proc_entry = NULL; ++ } ++#endif /* CONFIG_PROC_FS */ ++ ++ span_sysfs_remove(span); ++ ++ for (x=0;xchannels;x++) ++ dahdi_chan_unreg(span->chans[x]); ++ ++ new_master = master_span; /* FIXME: locking */ ++ if (master_span == span) ++ new_master = NULL; ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ list_for_each_entry(s, &span_list, spans_node) { ++ if ((s == new_master) || !can_provide_timing(s)) ++ continue; ++ new_master = s; ++ break; ++ } ++ spin_unlock_irqrestore(&chan_lock, flags); ++ if (master_span != new_master) { ++ if (debug & DEBUG_MAIN) { ++ module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__, ++ (new_master)? new_master->name: "no master"); ++ } ++ } ++ master_span = new_master; ++ return 0; ++} ++ ++static int open_channel_count(const struct dahdi_span *span) ++{ ++ int i; ++ int open_channels = 0; ++ struct dahdi_chan *chan; ++ ++ for (i = 0; i < span->channels; ++i) { ++ chan = span->chans[i]; ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) ++ ++open_channels; ++ } ++ return open_channels; ++} ++ ++int dahdi_unassign_span(struct dahdi_span *span) ++{ ++ int ret; ++ ++ module_printk(KERN_NOTICE, "%s: %s\n", __func__, span->name); ++ disable_span(span); ++ if (open_channel_count(span) > 0) ++ msleep(1000); /* Give user space a chance to read this */ ++ mutex_lock(®istration_mutex); ++ ret = _dahdi_unassign_span(span); ++ mutex_unlock(®istration_mutex); ++ return ret; ++} ++ ++/** ++ * dahdi_unregister_device() - unregister a DAHDI device ++ * @span: the DAHDI span ++ * ++ * Unregisters a device that has been previously registered with ++ * dahdi_register_device(). ++ * ++ */ ++void dahdi_unregister_device(struct dahdi_device *ddev) ++{ ++ struct dahdi_span *s; ++ struct dahdi_span *next; ++ unsigned int spans_with_open_channels = 0; ++ ++ WARN_ON(!ddev); ++ might_sleep(); ++ if (unlikely(!ddev)) ++ return; ++ ++ list_for_each_entry_safe(s, next, &ddev->spans, device_node) { ++ disable_span(s); ++ if (open_channel_count(s) > 0) ++ ++spans_with_open_channels; ++ } ++ ++ if (spans_with_open_channels > 0) ++ msleep(1000); /* give user space a chance to read this */ ++ ++ mutex_lock(®istration_mutex); ++ list_for_each_entry_safe(s, next, &ddev->spans, device_node) { ++ _dahdi_unassign_span(s); ++ list_del_init(&s->device_node); ++ } ++ mutex_unlock(®istration_mutex); ++ ++ dahdi_sysfs_unregister_device(ddev); ++ ++ if (UNKNOWN == ddev->location) ++ ddev->location = NULL; ++ if (UNKNOWN == ddev->manufacturer) ++ ddev->manufacturer = NULL; ++ if (UNKNOWN == ddev->devicetype) ++ ddev->devicetype = NULL; ++ ++} ++EXPORT_SYMBOL(dahdi_unregister_device); ++ ++/* ++** This routine converts from linear to ulaw ++** ++** Craig Reese: IDA/Supercomputing Research Center ++** Joe Campbell: Department of Defense ++** 29 September 1989 ++** ++** References: ++** 1) CCITT Recommendation G.711 (very difficult to follow) ++** 2) "A New Digital Technique for Implementation of Any ++** Continuous PCM Companding Law," Villeret, Michel, ++** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, ++** 1973, pg. 11.12-11.17 ++** 3) MIL-STD-188-113,"Interoperability and Performance Standards ++** for Analog-to_Digital Conversion Techniques," ++** 17 February 1987 ++** ++** Input: Signed 16 bit linear sample ++** Output: 8 bit ulaw sample ++*/ ++ ++#define ZEROTRAP /* turn on the trap as per the MIL-STD */ ++#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ ++#define CLIP 32635 ++ ++#ifdef CONFIG_CALC_XLAW ++unsigned char ++#else ++static unsigned char __init ++#endif ++__dahdi_lineartoulaw(short sample) ++{ ++ static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, ++ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, ++ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, ++ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, ++ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, ++ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, ++ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, ++ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; ++ int sign, exponent, mantissa; ++ unsigned char ulawbyte; ++ ++ /* Get the sample into sign-magnitude. */ ++ sign = (sample >> 8) & 0x80; /* set aside the sign */ ++ if (sign != 0) sample = -sample; /* get magnitude */ ++ if (sample > CLIP) sample = CLIP; /* clip the magnitude */ ++ ++ /* Convert from 16 bit linear to ulaw. */ ++ sample = sample + BIAS; ++ exponent = exp_lut[(sample >> 7) & 0xFF]; ++ mantissa = (sample >> (exponent + 3)) & 0x0F; ++ ulawbyte = ~(sign | (exponent << 4) | mantissa); ++#ifdef ZEROTRAP ++ if (ulawbyte == 0) ulawbyte = 0x02; /* optional CCITT trap */ ++#endif ++ if (ulawbyte == 0xff) ulawbyte = 0x7f; /* never return 0xff */ ++ return(ulawbyte); ++} ++ ++#define AMI_MASK 0x55 ++ ++#ifdef CONFIG_CALC_XLAW ++unsigned char ++#else ++static inline unsigned char __init ++#endif ++__dahdi_lineartoalaw (short linear) ++{ ++ int mask; ++ int seg; ++ int pcm_val; ++ static int seg_end[8] = ++ { ++ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF ++ }; ++ ++ pcm_val = linear; ++ if (pcm_val >= 0) ++ { ++ /* Sign (7th) bit = 1 */ ++ mask = AMI_MASK | 0x80; ++ } ++ else ++ { ++ /* Sign bit = 0 */ ++ mask = AMI_MASK; ++ pcm_val = -pcm_val; ++ } ++ ++ /* Convert the scaled magnitude to segment number. */ ++ for (seg = 0; seg < 8; seg++) ++ { ++ if (pcm_val <= seg_end[seg]) ++ break; ++ } ++ /* Combine the sign, segment, and quantization bits. */ ++ return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask; ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline short int __init alaw2linear (uint8_t alaw) ++{ ++ int i; ++ int seg; ++ ++ alaw ^= AMI_MASK; ++ i = ((alaw & 0x0F) << 4); ++ seg = (((int) alaw & 0x70) >> 4); ++ if (seg) ++ i = (i + 0x100) << (seg - 1); ++ return (short int) ((alaw & 0x80) ? i : -i); ++} ++/*- End of function --------------------------------------------------------*/ ++static void __init dahdi_conv_init(void) ++{ ++ int i; ++ ++ /* ++ * Set up mu-law conversion table ++ */ ++ for(i = 0;i < 256;i++) ++ { ++ short mu,e,f,y; ++ static short etab[]={0,132,396,924,1980,4092,8316,16764}; ++ ++ mu = 255-i; ++ e = (mu & 0x70)/16; ++ f = mu & 0x0f; ++ y = f * (1 << (e + 3)); ++ y += etab[e]; ++ if (mu & 0x80) y = -y; ++ __dahdi_mulaw[i] = y; ++ __dahdi_alaw[i] = alaw2linear(i); ++ /* Default (0.0 db) gain table */ ++ defgain[i] = i; ++ } ++#ifndef CONFIG_CALC_XLAW ++ /* set up the reverse (mu-law) conversion table */ ++ for(i = -32768; i < 32768; i += 4) ++ { ++ __dahdi_lin2mu[((unsigned short)(short)i) >> 2] = __dahdi_lineartoulaw(i); ++ __dahdi_lin2a[((unsigned short)(short)i) >> 2] = __dahdi_lineartoalaw(i); ++ } ++#endif ++} ++ ++static inline void __dahdi_process_getaudio_chunk(struct dahdi_chan *ss, unsigned char *txb) ++{ ++ /* We transmit data from our master channel */ ++ /* Called with ss->lock held */ ++ struct dahdi_chan *ms = ss->master; ++ /* Linear representation */ ++ short getlin[DAHDI_CHUNKSIZE], k[DAHDI_CHUNKSIZE]; ++ int x; ++ ++ /* Okay, now we've got something to transmit */ ++ for (x=0;xec_state && (ms->ec_state->status.mode == ECHO_MODE_ACTIVE) && !ms->ec_state->features.CED_tx_detect) { ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) { ++ if (echo_can_disable_detector_update(&ms->ec_state->txecdis, getlin[x])) { ++ set_echocan_fax_mode(ms, ss->channo, "CED tx detected", 1); ++ dahdi_qevent_nolock(ms, DAHDI_EVENT_TX_CED_DETECTED); ++ break; ++ } ++ } ++ } ++#endif ++ ++ if ((!ms->confmute && !ms->dialing) || (is_pseudo_chan(ms))) { ++ struct dahdi_chan *const conf_chan = ms->conf_chan; ++ /* Handle conferencing on non-clear channel and non-HDLC channels */ ++ switch(ms->confmode & DAHDI_CONF_MODE_MASK) { ++ case DAHDI_CONF_NORMAL: ++ /* Do nuffin */ ++ break; ++ case DAHDI_CONF_MONITOR: /* Monitor a channel's rx mode */ ++ /* if a pseudo-channel, ignore */ ++ if (is_pseudo_chan(ms)) ++ break; ++ /* Add monitored channel */ ++ if (is_pseudo_chan(conf_chan)) ++ ACSS(getlin, conf_chan->getlin); ++ else ++ ACSS(getlin, conf_chan->putlin); ++ ++ for (x=0;xputlin); ++ else ++ ACSS(getlin, conf_chan->getlin); ++ ++ for (x=0;xputlin); ++ ACSS(getlin, conf_chan->getlin); ++ for (x=0;xreadchunkpreec) ++ break; ++ ++ /* Add monitored channel */ ++ ACSS(getlin, is_pseudo_chan(conf_chan) ? ++ conf_chan->readchunkpreec : conf_chan->putlin); ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ txb[x] = DAHDI_LIN2X(getlin[x], ms); ++ ++ break; ++ case DAHDI_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */ ++ /* if a pseudo-channel, ignore */ ++ if (is_pseudo_chan(ms)) ++ break; ++ ++ if (!conf_chan->readchunkpreec) ++ break; ++ ++ /* Add monitored channel */ ++ ACSS(getlin, is_pseudo_chan(conf_chan) ? ++ conf_chan->putlin : conf_chan->readchunkpreec); ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ txb[x] = DAHDI_LIN2X(getlin[x], ms); ++ ++ break; ++ case DAHDI_CONF_MONITORBOTH_PREECHO: /* monitor a channel's rx and tx mode */ ++ /* if a pseudo-channel, ignore */ ++ if (is_pseudo_chan(ms)) ++ break; ++ ++ if (!conf_chan->readchunkpreec) ++ break; ++ ++ ACSS(getlin, conf_chan->putlin); ++ ACSS(getlin, conf_chan->readchunkpreec); ++ ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ txb[x] = DAHDI_LIN2X(getlin[x], ms); ++ ++ break; ++ case DAHDI_CONF_REALANDPSEUDO: ++ /* This strange mode takes the transmit buffer and ++ puts it on the conference, minus its last sample, ++ then outputs from the conference minus the ++ real channel's last sample. */ ++ /* if to talk on conf */ ++ if (ms->confmode & DAHDI_CONF_PSEUDO_TALKER) { ++ /* Store temp value */ ++ memcpy(k, getlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* Add conf value */ ++ ACSS(k, conf_sums_next[ms->_confn]); ++ /* save last one */ ++ memcpy(ms->conflast2, ms->conflast1, DAHDI_CHUNKSIZE * sizeof(short)); ++ memcpy(ms->conflast1, k, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* get amount actually added */ ++ SCSS(ms->conflast1, conf_sums_next[ms->_confn]); ++ /* Really add in new value */ ++ ACSS(conf_sums_next[ms->_confn], ms->conflast1); ++ } else { ++ memset(ms->conflast1, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ memset(ms->conflast2, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ } ++ memset(getlin, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ txb[0] = DAHDI_LIN2X(0, ms); ++ memset(txb + 1, txb[0], DAHDI_CHUNKSIZE - 1); ++ /* fall through to normal conf mode */ ++ case DAHDI_CONF_CONF: /* Normal conference mode */ ++ if (is_pseudo_chan(ms)) /* if pseudo-channel */ ++ { ++ /* if to talk on conf */ ++ if (ms->confmode & DAHDI_CONF_TALKER) { ++ /* Store temp value */ ++ memcpy(k, getlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* Add conf value */ ++ ACSS(k, conf_sums[ms->_confn]); ++ /* get amount actually added */ ++ memcpy(ms->conflast, k, DAHDI_CHUNKSIZE * sizeof(short)); ++ SCSS(ms->conflast, conf_sums[ms->_confn]); ++ /* Really add in new value */ ++ ACSS(conf_sums[ms->_confn], ms->conflast); ++ memcpy(ms->getlin, getlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ } else { ++ memset(ms->conflast, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ memcpy(getlin, ms->getlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ } ++ txb[0] = DAHDI_LIN2X(0, ms); ++ memset(txb + 1, txb[0], DAHDI_CHUNKSIZE - 1); ++ break; ++ } ++ /* fall through */ ++ case DAHDI_CONF_CONFMON: /* Conference monitor mode */ ++ if (ms->confmode & DAHDI_CONF_LISTENER) { ++ /* Subtract out last sample written to conf */ ++ SCSS(getlin, ms->conflast); ++ /* Add in conference */ ++ ACSS(getlin, conf_sums[ms->_confn]); ++ } ++ for (x=0;x_confn], getlin); ++ /* Start with silence */ ++ memset(getlin, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* If a listener on the conf... */ ++ if (ms->confmode & DAHDI_CONF_LISTENER) { ++ /* Subtract last value written */ ++ SCSS(getlin, ms->conflast); ++ /* Add in conf */ ++ ACSS(getlin, conf_sums[ms->_confn]); ++ } ++ for (x=0;xec_state) { ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ txb[x] = DAHDI_LIN2X(conf_chan->getlin[x], ms); ++ } else { ++ memcpy(txb, conf_chan->getraw, DAHDI_CHUNKSIZE); ++ } ++ } else { ++ if (ms->ec_state) { ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ txb[x] = DAHDI_LIN2X(conf_chan->putlin[x], ms); ++ } else { ++ memcpy(txb, conf_chan->putraw, ++ DAHDI_CHUNKSIZE); ++ } ++ } ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ getlin[x] = DAHDI_XLAW(txb[x], ms); ++ break; ++ } ++ } ++ if (ms->confmute || (ms->ec_state && (ms->ec_state->status.mode) & __ECHO_MODE_MUTE)) { ++ txb[0] = DAHDI_LIN2X(0, ms); ++ memset(txb + 1, txb[0], DAHDI_CHUNKSIZE - 1); ++ if (ms->ec_state && (ms->ec_state->status.mode == ECHO_MODE_STARTTRAINING)) { ++ /* Transmit impulse now */ ++ txb[0] = DAHDI_LIN2X(16384, ms); ++ ms->ec_state->status.mode = ECHO_MODE_AWAITINGECHO; ++ } ++ } ++ /* save value from current */ ++ memcpy(ms->getlin, getlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* save value from current */ ++ memcpy(ms->getraw, txb, DAHDI_CHUNKSIZE); ++ /* if to make tx tone */ ++ if (ms->v1_1 || ms->v2_1 || ms->v3_1) ++ { ++ for (x=0;xtxgain[txb[x]]; ++} ++ ++static void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, ++ int bytes); ++ ++static inline void __dahdi_getbuf_chunk(struct dahdi_chan *ss, unsigned char *txb) ++{ ++ ++ ++#ifdef CONFIG_DAHDI_MIRROR ++ unsigned char *orig_txb = txb; ++#endif /* CONFIG_DAHDI_MIRROR */ ++ ++ /* Called with ss->lock held */ ++ /* We transmit data from our master channel */ ++ struct dahdi_chan *ms = ss->master; ++ /* Buffer we're using */ ++ unsigned char *buf; ++ /* Old buffer number */ ++ int oldbuf; ++ /* Linear representation */ ++ int getlin; ++ /* How many bytes we need to process */ ++ int bytes = DAHDI_CHUNKSIZE, left; ++ bool needtxunderrun = false; ++ int x; ++ ++ /* Let's pick something to transmit. First source to ++ try is our write-out buffer. Always check it first because ++ its our 'fast path' for whatever that's worth. */ ++ while(bytes) { ++ if ((ms->outwritebuf > -1) && !ms->txdisable) { ++ buf= ms->writebuf[ms->outwritebuf]; ++ left = ms->writen[ms->outwritebuf] - ms->writeidx[ms->outwritebuf]; ++ if (left > bytes) ++ left = bytes; ++ if (ms->flags & DAHDI_FLAG_HDLC) { ++ /* If this is an HDLC channel we only send a byte of ++ HDLC. */ ++ for(x=0;xtxhdlc)) ++ /* Load a byte of data only if needed */ ++ fasthdlc_tx_load_nocheck(&ms->txhdlc, buf[ms->writeidx[ms->outwritebuf]++]); ++ *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); ++ } ++ bytes -= left; ++ } else { ++ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left); ++ ms->writeidx[ms->outwritebuf]+=left; ++ txb += left; ++ bytes -= left; ++ } ++ /* Check buffer status */ ++ if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) { ++ /* We've reached the end of our buffer. Go to the next. */ ++ oldbuf = ms->outwritebuf; ++ /* Clear out write index and such */ ++ ms->writeidx[oldbuf] = 0; ++ ms->outwritebuf = (ms->outwritebuf + 1) % ms->numbufs; ++ ++ if (!(ms->flags & DAHDI_FLAG_MTP2)) { ++ ms->writen[oldbuf] = 0; ++ if (ms->outwritebuf == ms->inwritebuf) { ++ /* Whoopsies, we're run out of buffers. Mark ours ++ as -1 and wait for the filler to notify us that ++ there is something to write */ ++ ms->outwritebuf = -1; ++ if (ms->iomask & (DAHDI_IOMUX_WRITE | DAHDI_IOMUX_WRITEEMPTY)) ++ wake_up_interruptible(&ms->waitq); ++ /* If we're only supposed to start when full, disable the transmitter */ ++ if ((ms->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || ++ (ms->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ++ ms->txdisable = 1; ++ } ++ } else { ++ if (ms->outwritebuf == ms->inwritebuf) { ++ ms->outwritebuf = oldbuf; ++ if (ms->iomask & (DAHDI_IOMUX_WRITE | DAHDI_IOMUX_WRITEEMPTY)) ++ wake_up_interruptible(&ms->waitq); ++ /* If we're only supposed to start when full, disable the transmitter */ ++ if ((ms->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || ++ (ms->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ++ ms->txdisable = 1; ++ } ++ } ++ if (ms->inwritebuf < 0) { ++ /* The filler doesn't have a place to put data. Now ++ that we're done with this buffer, notify them. */ ++ ms->inwritebuf = oldbuf; ++ } ++/* In the very orignal driver, it was quite well known to me (Jim) that there ++was a possibility that a channel sleeping on a write block needed to ++be potentially woken up EVERY time a buffer was emptied, not just on the first ++one, because if only done on the first one there is a slight timing potential ++of missing the wakeup (between where it senses the (lack of) active condition ++(with interrupts disabled) and where it does the sleep (interrupts enabled) ++in the read or iomux call, etc). That is why the write and iomux calls start ++with an infinite loop that gets broken out of upon an active condition, ++otherwise keeps sleeping and looking. The part in this code got "optimized" ++out in the later versions, and is put back now. */ ++ if (!(ms->flags & DAHDI_FLAG_PPP) || ++ !dahdi_have_netdev(ms)) { ++ wake_up_interruptible(&ms->waitq); ++ } ++ /* Transmit a flag if this is an HDLC channel */ ++ if (ms->flags & DAHDI_FLAG_HDLC) ++ fasthdlc_tx_frame_nocheck(&ms->txhdlc); ++#ifdef CONFIG_DAHDI_NET ++ if (dahdi_have_netdev(ms)) ++ netif_wake_queue(chan_to_netdev(ms)); ++#endif ++#ifdef CONFIG_DAHDI_PPP ++ if (ms->flags & DAHDI_FLAG_PPP) { ++ ms->do_ppp_wakeup = 1; ++ tasklet_schedule(&ms->ppp_calls); ++ } ++#endif ++ } ++ } else if (ms->curtone && !is_pseudo_chan(ms)) { ++ left = ms->curtone->tonesamples - ms->tonep; ++ if (left > bytes) ++ left = bytes; ++ for (x=0;xts, ms->curtone); ++ *(txb++) = DAHDI_LIN2X(getlin, ms); ++ } ++ ms->tonep+=left; ++ bytes -= left; ++ if (ms->tonep >= ms->curtone->tonesamples) { ++ struct dahdi_tone *last; ++ /* Go to the next sample of the tone */ ++ ms->tonep = 0; ++ last = ms->curtone; ++ ms->curtone = ms->curtone->next; ++ if (!ms->curtone) { ++ /* No more tones... Is this dtmf or mf? If so, go to the next digit */ ++ if (ms->dialing) ++ __do_dtmf(ms); ++ } else { ++ if (last != ms->curtone) ++ dahdi_init_tone_state(&ms->ts, ms->curtone); ++ } ++ } ++ } else if (ms->flags & DAHDI_FLAG_LOOPED) { ++ for (x = 0; x < bytes; x++) ++ txb[x] = ms->readchunk[x]; ++ bytes = 0; ++ } else if (ms->flags & DAHDI_FLAG_HDLC) { ++ for (x=0;xtxhdlc)) ++ fasthdlc_tx_frame_nocheck(&ms->txhdlc); ++ *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); ++ } ++ bytes = 0; ++ } else if (ms->flags & DAHDI_FLAG_CLEAR) { ++ /* Clear channels that are idle in audio mode need ++ to send silence; in non-audio mode, always send 0xff ++ so stupid switches won't consider the channel active ++ */ ++ if (ms->flags & DAHDI_FLAG_AUDIO) { ++ memset(txb, DAHDI_LIN2X(0, ms), bytes); ++ } else { ++ memset(txb, 0xFF, bytes); ++ } ++ needtxunderrun += bytes; ++ bytes = 0; ++ } else { ++ memset(txb, DAHDI_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */ ++ needtxunderrun += bytes; ++ bytes = 0; ++ } ++ } ++ ++ if (needtxunderrun) { ++ if (!test_bit(DAHDI_FLAGBIT_TXUNDERRUN, &ms->flags)) { ++ if (test_bit(DAHDI_FLAGBIT_BUFEVENTS, &ms->flags)) ++ __qevent(ms, DAHDI_EVENT_WRITE_UNDERRUN); ++ set_bit(DAHDI_FLAGBIT_TXUNDERRUN, &ms->flags); ++ } ++ } else { ++ clear_bit(DAHDI_FLAGBIT_TXUNDERRUN, &ms->flags); ++ } ++ ++#ifdef CONFIG_DAHDI_MIRROR ++ if (ss->txmirror) { ++ spin_lock(&ss->txmirror->lock); ++ __putbuf_chunk(ss->txmirror, orig_txb, DAHDI_CHUNKSIZE); ++ spin_unlock(&ss->txmirror->lock); ++ } ++#endif /* CONFIG_DAHDI_MIRROR */ ++} ++ ++static inline void rbs_itimer_expire(struct dahdi_chan *chan) ++{ ++ /* the only way this could have gotten here, is if a channel ++ went onf hook longer then the wink or flash detect timeout */ ++ /* Called with chan->lock held */ ++ switch(chan->sig) ++ { ++ case DAHDI_SIG_FXOLS: /* if FXO, its definitely on hook */ ++ case DAHDI_SIG_FXOGS: ++ case DAHDI_SIG_FXOKS: ++ __qevent(chan,DAHDI_EVENT_ONHOOK); ++ chan->gotgs = 0; ++ break; ++#if defined(EMFLASH) || defined(EMPULSE) ++ case DAHDI_SIG_EM: ++ case DAHDI_SIG_EM_E1: ++ if (chan->rxhooksig == DAHDI_RXSIG_ONHOOK) { ++ __qevent(chan,DAHDI_EVENT_ONHOOK); ++ break; ++ } ++ __qevent(chan,DAHDI_EVENT_RINGOFFHOOK); ++ break; ++#endif ++#ifdef FXSFLASH ++ case DAHDI_SIG_FXSKS: ++ if (chan->rxhooksig == DAHDI_RXSIG_ONHOOK) { ++ __qevent(chan, DAHDI_EVENT_ONHOOK); ++ break; ++ } ++#endif ++ /* fall thru intentionally */ ++ default: /* otherwise, its definitely off hook */ ++ __qevent(chan,DAHDI_EVENT_RINGOFFHOOK); ++ break; ++ } ++} ++ ++static inline void __rbs_otimer_expire(struct dahdi_chan *chan) ++{ ++ int len = 0; ++ /* Called with chan->lock held */ ++ ++ chan->otimer = 0; ++ /* Move to the next timer state */ ++ switch(chan->txstate) { ++ case DAHDI_TXSTATE_RINGOFF: ++ /* Turn on the ringer now that the silent time has passed */ ++ ++chan->cadencepos; ++ if (chan->cadencepos >= DAHDI_MAX_CADENCE) ++ chan->cadencepos = chan->firstcadencepos; ++ len = chan->ringcadence[chan->cadencepos]; ++ ++ if (!len) { ++ chan->cadencepos = chan->firstcadencepos; ++ len = chan->ringcadence[chan->cadencepos]; ++ } ++ ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_START, DAHDI_TXSTATE_RINGON, len); ++ __qevent(chan, DAHDI_EVENT_RINGERON); ++ break; ++ ++ case DAHDI_TXSTATE_RINGON: ++ /* Turn off the ringer now that the loud time has passed */ ++ ++chan->cadencepos; ++ if (chan->cadencepos >= DAHDI_MAX_CADENCE) ++ chan->cadencepos = 0; ++ len = chan->ringcadence[chan->cadencepos]; ++ ++ if (!len) { ++ chan->cadencepos = 0; ++ len = chan->curzone->ringcadence[chan->cadencepos]; ++ } ++ ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_RINGOFF, len); ++ __qevent(chan, DAHDI_EVENT_RINGEROFF); ++ break; ++ ++ case DAHDI_TXSTATE_START: ++ /* If we were starting, go off hook now ready to debounce */ ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_AFTERSTART, DAHDI_AFTERSTART_TIME); ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_PREWINK: ++ /* Actually wink */ ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_WINK, chan->winktime); ++ break; ++ ++ case DAHDI_TXSTATE_WINK: ++ /* Wink complete, go on hook and stabalize */ ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_ONHOOK, 0); ++ if (chan->file && (chan->file->f_flags & O_NONBLOCK)) ++ __qevent(chan, DAHDI_EVENT_HOOKCOMPLETE); ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_PREFLASH: ++ /* Actually flash */ ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_FLASH, chan->flashtime); ++ break; ++ ++ case DAHDI_TXSTATE_FLASH: ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_OFFHOOK, 0); ++ if (chan->file && (chan->file->f_flags & O_NONBLOCK)) ++ __qevent(chan, DAHDI_EVENT_HOOKCOMPLETE); ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_DEBOUNCE: ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_OFFHOOK, 0); ++ /* See if we've gone back on hook */ ++ if ((chan->rxhooksig == DAHDI_RXSIG_ONHOOK) && (chan->rxflashtime > 2)) ++ chan->itimerset = chan->itimer = chan->rxflashtime * DAHDI_CHUNKSIZE; ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_AFTERSTART: ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_OFFHOOK, 0); ++ if (chan->file && (chan->file->f_flags & O_NONBLOCK)) ++ __qevent(chan, DAHDI_EVENT_HOOKCOMPLETE); ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_KEWL: ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, DAHDI_TXSTATE_AFTERKEWL, DAHDI_AFTERKEWLTIME); ++ if (chan->file && (chan->file->f_flags & O_NONBLOCK)) ++ __qevent(chan, DAHDI_EVENT_HOOKCOMPLETE); ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_AFTERKEWL: ++ if (chan->kewlonhook) { ++ __qevent(chan,DAHDI_EVENT_ONHOOK); ++ } ++ chan->txstate = DAHDI_TXSTATE_ONHOOK; ++ chan->gotgs = 0; ++ break; ++ ++ case DAHDI_TXSTATE_PULSEBREAK: ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_PULSEMAKE, ++ chan->pulsemaketime); ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_PULSEMAKE: ++ if (chan->pdialcount) ++ chan->pdialcount--; ++ if (chan->pdialcount) ++ { ++ dahdi_rbs_sethook(chan, DAHDI_TXSIG_ONHOOK, ++ DAHDI_TXSTATE_PULSEBREAK, chan->pulsebreaktime); ++ break; ++ } ++ chan->txstate = DAHDI_TXSTATE_PULSEAFTER; ++ chan->otimer = chan->pulseaftertime * DAHDI_CHUNKSIZE; ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ case DAHDI_TXSTATE_PULSEAFTER: ++ chan->txstate = DAHDI_TXSTATE_OFFHOOK; ++ __do_dtmf(chan); ++ wake_up_interruptible(&chan->waitq); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void __dahdi_hooksig_pvt(struct dahdi_chan *chan, enum dahdi_rxsig rxsig) ++{ ++ ++ /* State machines for receive hookstate transitions ++ called with chan->lock held */ ++ ++ if ((chan->rxhooksig) == rxsig) return; ++ ++ if ((chan->flags & DAHDI_FLAG_SIGFREEZE)) return; ++ ++ chan->rxhooksig = rxsig; ++#ifdef RINGBEGIN ++ if ((chan->sig & __DAHDI_SIG_FXS) && (rxsig == DAHDI_RXSIG_RING) && ++ (!chan->ringdebtimer)) ++ __qevent(chan,DAHDI_EVENT_RINGBEGIN); ++#endif ++ switch(chan->sig) { ++ case DAHDI_SIG_EM: /* E and M */ ++ case DAHDI_SIG_EM_E1: ++ switch(rxsig) { ++ case DAHDI_RXSIG_OFFHOOK: /* went off hook */ ++ /* The interface is going off hook */ ++#ifdef EMFLASH ++ if (chan->itimer) ++ { ++ __qevent(chan,DAHDI_EVENT_WINKFLASH); ++ chan->itimerset = chan->itimer = 0; ++ break; ++ } ++#endif ++#ifdef EMPULSE ++ if (chan->itimer) /* if timer still running */ ++ { ++ int plen = chan->itimerset - chan->itimer; ++ if (plen <= DAHDI_MAXPULSETIME) ++ { ++ if (plen >= DAHDI_MINPULSETIME) ++ { ++ chan->pulsecount++; ++ ++ chan->pulsetimer = DAHDI_PULSETIMEOUT; ++ chan->itimerset = chan->itimer = 0; ++ if (chan->pulsecount == 1) ++ __qevent(chan,DAHDI_EVENT_PULSE_START); ++ } ++ } ++ break; ++ } ++#endif ++ /* set wink timer */ ++ chan->itimerset = chan->itimer = chan->rxwinktime * DAHDI_CHUNKSIZE; ++ break; ++ case DAHDI_RXSIG_ONHOOK: /* went on hook */ ++ /* This interface is now going on hook. ++ Check for WINK, etc */ ++ if (chan->itimer) ++ __qevent(chan,DAHDI_EVENT_WINKFLASH); ++#if defined(EMFLASH) || defined(EMPULSE) ++ else { ++#ifdef EMFLASH ++ chan->itimerset = chan->itimer = chan->rxflashtime * DAHDI_CHUNKSIZE; ++ ++#else /* EMFLASH */ ++ chan->itimerset = chan->itimer = chan->rxwinktime * DAHDI_CHUNKSIZE; ++ ++#endif /* EMFLASH */ ++ chan->gotgs = 0; ++ break; ++ } ++#else /* EMFLASH || EMPULSE */ ++ else { ++ __qevent(chan,DAHDI_EVENT_ONHOOK); ++ chan->gotgs = 0; ++ } ++#endif ++ chan->itimerset = chan->itimer = 0; ++ break; ++ default: ++ break; ++ } ++ break; ++ case DAHDI_SIG_FXSKS: /* FXS Kewlstart */ ++ /* ignore a bit error if loop not closed and stable */ ++ if (chan->txstate != DAHDI_TXSTATE_OFFHOOK) break; ++#ifdef FXSFLASH ++ if (rxsig == DAHDI_RXSIG_ONHOOK) { ++ chan->itimer = DAHDI_FXSFLASHMAXTIME * DAHDI_CHUNKSIZE; ++ break; ++ } else if (rxsig == DAHDI_RXSIG_OFFHOOK) { ++ if (chan->itimer) { ++ /* did the offhook occur in the window? if not, ignore both events */ ++ if (chan->itimer <= ((DAHDI_FXSFLASHMAXTIME - DAHDI_FXSFLASHMINTIME) * DAHDI_CHUNKSIZE)) ++ __qevent(chan, DAHDI_EVENT_WINKFLASH); ++ } ++ chan->itimer = 0; ++ break; ++ } ++#endif ++ /* fall through intentionally */ ++ case DAHDI_SIG_FXSGS: /* FXS Groundstart */ ++ if (rxsig == DAHDI_RXSIG_ONHOOK) { ++ chan->ringdebtimer = RING_DEBOUNCE_TIME; ++ chan->ringtrailer = 0; ++ if (chan->txstate != DAHDI_TXSTATE_DEBOUNCE) { ++ chan->gotgs = 0; ++ __qevent(chan,DAHDI_EVENT_ONHOOK); ++ } ++ } ++ break; ++ case DAHDI_SIG_FXOGS: /* FXO Groundstart */ ++ if (rxsig == DAHDI_RXSIG_START) { ++ /* if havent got gs, report it */ ++ if (!chan->gotgs) { ++ __qevent(chan,DAHDI_EVENT_RINGOFFHOOK); ++ chan->gotgs = 1; ++ } ++ } ++ /* fall through intentionally */ ++ case DAHDI_SIG_FXOLS: /* FXO Loopstart */ ++ case DAHDI_SIG_FXOKS: /* FXO Kewlstart */ ++ switch(rxsig) { ++ case DAHDI_RXSIG_OFFHOOK: /* went off hook */ ++ /* if asserti ng ring, stop it */ ++ if (chan->txstate == DAHDI_TXSTATE_START) { ++ dahdi_rbs_sethook(chan,DAHDI_TXSIG_OFFHOOK, DAHDI_TXSTATE_AFTERSTART, DAHDI_AFTERSTART_TIME); ++ } ++ chan->kewlonhook = 0; ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Off hook on channel %d, itimer = %d, gotgs = %d\n", chan->channo, chan->itimer, chan->gotgs); ++#endif ++ if (chan->itimer) /* if timer still running */ ++ { ++ int plen = chan->itimerset - chan->itimer; ++ if (plen <= DAHDI_MAXPULSETIME) ++ { ++ if (plen >= DAHDI_MINPULSETIME) ++ { ++ chan->pulsecount++; ++ chan->pulsetimer = DAHDI_PULSETIMEOUT; ++ chan->itimer = chan->itimerset; ++ if (chan->pulsecount == 1) ++ __qevent(chan,DAHDI_EVENT_PULSE_START); ++ } ++ } else ++ __qevent(chan,DAHDI_EVENT_WINKFLASH); ++ } else { ++ /* if havent got GS detect */ ++ if (!chan->gotgs) { ++ __qevent(chan,DAHDI_EVENT_RINGOFFHOOK); ++ chan->gotgs = 1; ++ chan->itimerset = chan->itimer = 0; ++ } ++ } ++ chan->itimerset = chan->itimer = 0; ++ break; ++ case DAHDI_RXSIG_ONHOOK: /* went on hook */ ++ /* if not during offhook debounce time */ ++ if ((chan->txstate != DAHDI_TXSTATE_DEBOUNCE) && ++ (chan->txstate != DAHDI_TXSTATE_KEWL) && ++ (chan->txstate != DAHDI_TXSTATE_AFTERKEWL)) { ++ chan->itimerset = chan->itimer = chan->rxflashtime * DAHDI_CHUNKSIZE; ++ } ++ if (chan->txstate == DAHDI_TXSTATE_KEWL) ++ chan->kewlonhook = 1; ++ break; ++ default: ++ break; ++ } ++ default: ++ break; ++ } ++} ++ ++/** ++ * dahdi_hooksig() - send a signal on a channel to userspace ++ * @chan: the DAHDI channel ++ * @rxsig: signal (number) to send ++ * ++ * Called from a channel driver to send a DAHDI signal to userspace. ++ * The signal will be queued for delivery to userspace. ++ * ++ * If the signal is the same as previous one sent, it won't be re-sent. ++ */ ++void dahdi_hooksig(struct dahdi_chan *chan, enum dahdi_rxsig rxsig) ++{ ++ /* skip if no change */ ++ unsigned long flags; ++ spin_lock_irqsave(&chan->lock, flags); ++ __dahdi_hooksig_pvt(chan,rxsig); ++ spin_unlock_irqrestore(&chan->lock, flags); ++} ++ ++ ++/** ++ * dahdi_rbsbits() - set Rx RBS bits on the channel ++ * @chan: the DAHDI channel ++ * @cursig: the bits to set ++ * ++ * Set the channel's rxsig (received: from device to userspace) and act ++ * accordingly. ++ */ ++void dahdi_rbsbits(struct dahdi_chan *chan, int cursig) ++{ ++ unsigned long flags; ++ if (cursig == chan->rxsig) ++ return; ++ ++ if ((chan->flags & DAHDI_FLAG_SIGFREEZE)) return; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ switch(chan->sig) { ++ case DAHDI_SIG_FXOGS: /* FXO Groundstart */ ++ /* B-bit only matters for FXO GS */ ++ if (!(cursig & DAHDI_BBIT)) { ++ __dahdi_hooksig_pvt(chan, DAHDI_RXSIG_START); ++ break; ++ } ++ /* Fall through */ ++ case DAHDI_SIG_EM_E1: ++ case DAHDI_SIG_FXOLS: /* FXO Loopstart */ ++ case DAHDI_SIG_FXOKS: /* FXO Kewlstart */ ++ if (cursig & DAHDI_ABIT) /* off hook */ ++ __dahdi_hooksig_pvt(chan,DAHDI_RXSIG_OFFHOOK); ++ else /* on hook */ ++ __dahdi_hooksig_pvt(chan,DAHDI_RXSIG_ONHOOK); ++ break; ++ case DAHDI_SIG_EM: /* E and M */ ++ /* Watch only the ABIT for changes. */ ++ if ((cursig & DAHDI_ABIT) == (chan->rxsig & DAHDI_ABIT)) ++ break; ++ __dahdi_hooksig_pvt(chan, (cursig & DAHDI_ABIT) ? ++ DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK); ++ break; ++ case DAHDI_SIG_FXSKS: /* FXS Kewlstart */ ++ case DAHDI_SIG_FXSGS: /* FXS Groundstart */ ++ /* Fall through */ ++ case DAHDI_SIG_FXSLS: ++ if (!(cursig & DAHDI_BBIT)) { ++ /* Check for ringing first */ ++ __dahdi_hooksig_pvt(chan, DAHDI_RXSIG_RING); ++ break; ++ } ++ if ((chan->sig != DAHDI_SIG_FXSLS) && (cursig & DAHDI_ABIT)) { ++ /* if went on hook */ ++ __dahdi_hooksig_pvt(chan, DAHDI_RXSIG_ONHOOK); ++ } else { ++ __dahdi_hooksig_pvt(chan, DAHDI_RXSIG_OFFHOOK); ++ } ++ break; ++ case DAHDI_SIG_CAS: ++ /* send event that something changed */ ++ __qevent(chan, DAHDI_EVENT_BITSCHANGED); ++ break; ++ ++ default: ++ break; ++ } ++ /* Keep track of signalling for next time */ ++ chan->rxsig = cursig; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ if ((debug & DEBUG_RBS) && printk_ratelimit()) { ++ chan_notice(chan, "Detected sigbits change to %04x\n", cursig); ++ } ++} ++ ++static void process_echocan_events(struct dahdi_chan *chan) ++{ ++ union dahdi_echocan_events events = chan->ec_state->events; ++ ++ if (events.bit.CED_tx_detected) { ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_TX_CED_DETECTED); ++ if (chan->ec_state) { ++ if (chan->ec_state->status.mode == ECHO_MODE_ACTIVE) ++ set_echocan_fax_mode(chan, chan->channo, "CED tx detected", 1); ++ else ++ module_printk(KERN_NOTICE, "Detected CED tone (tx) on channel %d\n", chan->channo); ++ } ++ } ++ ++ if (events.bit.CED_rx_detected) { ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_RX_CED_DETECTED); ++ if (chan->ec_state) { ++ if (chan->ec_state->status.mode == ECHO_MODE_ACTIVE) ++ set_echocan_fax_mode(chan, chan->channo, "CED rx detected", 1); ++ else ++ module_printk(KERN_NOTICE, "Detected CED tone (rx) on channel %d\n", chan->channo); ++ } ++ } ++ ++ if (events.bit.CNG_tx_detected) ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_TX_CNG_DETECTED); ++ ++ if (events.bit.CNG_rx_detected) ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_RX_CNG_DETECTED); ++ ++ if (events.bit.NLP_auto_disabled) { ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_EC_NLP_DISABLED); ++ chan->ec_state->status.mode = ECHO_MODE_FAX; ++ } ++ ++ if (events.bit.NLP_auto_enabled) { ++ dahdi_qevent_nolock(chan, DAHDI_EVENT_EC_NLP_ENABLED); ++ chan->ec_state->status.mode = ECHO_MODE_ACTIVE; ++ } ++} ++ ++/** ++ * __dahdi_ec_chunk() - process echo for a single channel ++ * @ss: DAHDI channel ++ * @rxchunk: buffer to store audio with cancelled audio ++ * @preecchunk: chunk of audio on which to cancel echo ++ * @txchunk: reference chunk from the other direction ++ * ++ * The echo canceller function fixes received (from device to userspace) ++ * audio. In order to fix it it uses the transmitted audio as a ++ * reference. This call updates the echo canceller for a single chunk (8 ++ * bytes). ++ * ++ * Call with local interrupts disabled. ++ */ ++void __dahdi_ec_chunk(struct dahdi_chan *ss, u8 *rxchunk, ++ const u8 *preecchunk, const u8 *txchunk) ++{ ++ short rxlin; ++ int x; ++ ++ spin_lock(&ss->lock); ++ ++ if (ss->readchunkpreec) { ++ /* Save a copy of the audio before the echo can has its way with it */ ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ /* We only ever really need to deal with signed linear - let's just convert it now */ ++ ss->readchunkpreec[x] = DAHDI_XLAW(preecchunk[x], ss); ++ } ++ ++ /* Perform echo cancellation on a chunk if necessary */ ++ if (ss->ec_state) { ++#if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP) ++ dahdi_kernel_fpu_begin(); ++#endif ++ if (ss->ec_state->status.mode & __ECHO_MODE_MUTE) { ++ /* Special stuff for training the echo can */ ++ for (x=0;xec_state->status.mode == ECHO_MODE_PRETRAINING) { ++ if (--ss->ec_state->status.pretrain_timer <= 0) { ++ ss->ec_state->status.pretrain_timer = 0; ++ ss->ec_state->status.mode = ECHO_MODE_STARTTRAINING; ++ } ++ } ++ if (ss->ec_state->status.mode == ECHO_MODE_AWAITINGECHO) { ++ ss->ec_state->status.last_train_tap = 0; ++ ss->ec_state->status.mode = ECHO_MODE_TRAINING; ++ } ++ if ((ss->ec_state->status.mode == ECHO_MODE_TRAINING) && ++ (ss->ec_state->ops->echocan_traintap)) { ++ if (ss->ec_state->ops->echocan_traintap(ss->ec_state, ss->ec_state->status.last_train_tap++, rxlin)) { ++ ss->ec_state->status.mode = ECHO_MODE_ACTIVE; ++ } ++ } ++ rxlin = 0; ++ rxchunk[x] = DAHDI_LIN2X((int)rxlin, ss); ++ } ++ } else if (ss->ec_state->status.mode != ECHO_MODE_IDLE) { ++ ss->ec_state->events.all = 0; ++ ++ if (ss->ec_state->ops->echocan_process) { ++ short rxlins[DAHDI_CHUNKSIZE], txlins[DAHDI_CHUNKSIZE]; ++ ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) { ++ rxlins[x] = DAHDI_XLAW(preecchunk[x], ++ ss); ++ txlins[x] = DAHDI_XLAW(txchunk[x], ss); ++ } ++ ss->ec_state->ops->echocan_process(ss->ec_state, rxlins, txlins, DAHDI_CHUNKSIZE); ++ ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ rxchunk[x] = DAHDI_LIN2X((int) rxlins[x], ss); ++ } else if (ss->ec_state->ops->echocan_events) ++ ss->ec_state->ops->echocan_events(ss->ec_state); ++ ++ if (ss->ec_state->events.all) ++ process_echocan_events(ss); ++ ++ } ++#if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP) ++ dahdi_kernel_fpu_end(); ++#endif ++ } ++ ++ spin_unlock(&ss->lock); ++} ++EXPORT_SYMBOL(__dahdi_ec_chunk); ++ ++/** ++ * dahdi_ec_span() - process echo for all channels in a span. ++ * @span: DAHDI span ++ * ++ * Similar to calling dahdi_ec_chunk() for each of the channels in the ++ * span. Uses dahdi_chunk.write_chunk for the rxchunk (the chunk to fix) ++ * and dahdi_chan.readchunk as the txchunk (the reference chunk). ++ */ ++void _dahdi_ec_span(struct dahdi_span *span) ++{ ++ int x; ++ for (x = 0; x < span->channels; x++) { ++ struct dahdi_chan *const chan = span->chans[x]; ++ if (!chan->ec_current) ++ continue; ++ _dahdi_ec_chunk(chan, chan->readchunk, chan->writechunk); ++ } ++} ++EXPORT_SYMBOL(_dahdi_ec_span); ++ ++/* return 0 if nothing detected, 1 if lack of tone, 2 if presence of tone */ ++/* modifies buffer pointed to by 'amp' with notched-out values */ ++static inline int sf_detect(struct sf_detect_state *s, ++ short *amp, ++ int samples,long p1, long p2, long p3) ++{ ++int i,rv = 0; ++long x,y; ++ ++#define SF_DETECT_SAMPLES (DAHDI_CHUNKSIZE * 5) ++#define SF_DETECT_MIN_ENERGY 500 ++#define NB 14 /* number of bits to shift left */ ++ ++ /* determine energy level before filtering */ ++ for(i = 0; i < samples; i++) ++ { ++ if (amp[i] < 0) s->e1 -= amp[i]; ++ else s->e1 += amp[i]; ++ } ++ /* do 2nd order IIR notch filter at given freq. and calculate ++ energy */ ++ for(i = 0; i < samples; i++) ++ { ++ x = amp[i] << NB; ++ y = s->x2 + (p1 * (s->x1 >> NB)) + x; ++ y += (p2 * (s->y2 >> NB)) + ++ (p3 * (s->y1 >> NB)); ++ s->x2 = s->x1; ++ s->x1 = x; ++ s->y2 = s->y1; ++ s->y1 = y; ++ amp[i] = y >> NB; ++ if (amp[i] < 0) s->e2 -= amp[i]; ++ else s->e2 += amp[i]; ++ } ++ s->samps += i; ++ /* if time to do determination */ ++ if ((s->samps) >= SF_DETECT_SAMPLES) ++ { ++ rv = 1; /* default to no tone */ ++ /* if enough energy, it is determined to be a tone */ ++ if (((s->e1 - s->e2) / s->samps) > SF_DETECT_MIN_ENERGY) rv = 2; ++ /* reset energy processing variables */ ++ s->samps = 0; ++ s->e1 = s->e2 = 0; ++ } ++ return(rv); ++} ++ ++static inline void __dahdi_process_putaudio_chunk(struct dahdi_chan *ss, unsigned char *rxb) ++{ ++ /* We transmit data from our master channel */ ++ /* Called with ss->lock held */ ++ struct dahdi_chan *ms = ss->master; ++ /* Linear version of received data */ ++ short putlin[DAHDI_CHUNKSIZE],k[DAHDI_CHUNKSIZE]; ++ int x,r; ++ ++ if (ms->dialing) ms->afterdialingtimer = 50; ++ else if (ms->afterdialingtimer) ms->afterdialingtimer--; ++ if (ms->afterdialingtimer && !is_pseudo_chan(ms)) { ++ /* Be careful since memset is likely a macro */ ++ rxb[0] = DAHDI_LIN2X(0, ms); ++ memset(&rxb[1], rxb[0], DAHDI_CHUNKSIZE - 1); /* receive as silence if dialing */ ++ } ++ for (x=0;xrxgain[rxb[x]]; ++ putlin[x] = DAHDI_XLAW(rxb[x], ms); ++ } ++ ++#ifndef CONFIG_DAHDI_NO_ECHOCAN_DISABLE ++ if (ms->ec_state && (ms->ec_state->status.mode == ECHO_MODE_ACTIVE) && !ms->ec_state->features.CED_rx_detect) { ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) { ++ if (echo_can_disable_detector_update(&ms->ec_state->rxecdis, putlin[x])) { ++ set_echocan_fax_mode(ms, ss->channo, "CED rx detected", 1); ++ dahdi_qevent_nolock(ms, DAHDI_EVENT_RX_CED_DETECTED); ++ break; ++ } ++ } ++ } ++#endif ++ ++ /* if doing rx tone decoding */ ++ if (ms->rxp1 && ms->rxp2 && ms->rxp3) ++ { ++ r = sf_detect(&ms->rd,putlin,DAHDI_CHUNKSIZE,ms->rxp1, ++ ms->rxp2,ms->rxp3); ++ /* Convert back */ ++ for(x=0;xrd.lastdetect) ++ { ++ if (((r == 2) && !(ms->toneflags & DAHDI_REVERSE_RXTONE)) || ++ ((r == 1) && (ms->toneflags & DAHDI_REVERSE_RXTONE))) ++ { ++ __qevent(ms,DAHDI_EVENT_RINGOFFHOOK); ++ } ++ else ++ { ++ __qevent(ms,DAHDI_EVENT_ONHOOK); ++ } ++ ms->rd.lastdetect = r; ++ } ++ } ++ } ++ ++ if (!is_pseudo_chan(ms)) { ++ memcpy(ms->putlin, putlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ memcpy(ms->putraw, rxb, DAHDI_CHUNKSIZE); ++ } ++ ++ /* Take the rxc, twiddle it for conferencing if appropriate and put it ++ back */ ++ if ((!ms->confmute && !ms->afterdialingtimer) || is_pseudo_chan(ms)) { ++ struct dahdi_chan *const conf_chan = ms->conf_chan; ++ switch(ms->confmode & DAHDI_CONF_MODE_MASK) { ++ case DAHDI_CONF_NORMAL: /* Normal mode */ ++ /* Do nothing. rx goes output */ ++ break; ++ case DAHDI_CONF_MONITOR: /* Monitor a channel's rx mode */ ++ /* if not a pseudo-channel, ignore */ ++ if (!is_pseudo_chan(ms)) ++ break; ++ /* Add monitored channel */ ++ if (is_pseudo_chan(conf_chan)) ++ ACSS(putlin, conf_chan->getlin); ++ else ++ ACSS(putlin, conf_chan->putlin); ++ /* Convert back */ ++ for(x=0;xputlin); ++ else ++ ACSS(putlin, conf_chan->getlin); ++ /* Convert back */ ++ for(x=0;xgetlin); ++ ACSS(putlin, conf_chan->putlin); ++ /* Convert back */ ++ for(x=0;xreadchunkpreec) ++ break; ++ ++ /* Add monitored channel */ ++ ACSS(putlin, is_pseudo_chan(conf_chan) ? ++ conf_chan->getlin : conf_chan->readchunkpreec); ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ rxb[x] = DAHDI_LIN2X(putlin[x], ms); ++ ++ break; ++ case DAHDI_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */ ++ /* if not a pseudo-channel, ignore */ ++ if (!is_pseudo_chan(ms)) ++ break; ++ ++ if (!conf_chan->readchunkpreec) ++ break; ++ ++ /* Add monitored channel */ ++ ACSS(putlin, is_pseudo_chan(conf_chan) ? ++ conf_chan->readchunkpreec : conf_chan->getlin); ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ rxb[x] = DAHDI_LIN2X(putlin[x], ms); ++ ++ break; ++ case DAHDI_CONF_MONITORBOTH_PREECHO: /* Monitor a channel's tx and rx mode */ ++ /* if not a pseudo-channel, ignore */ ++ if (!is_pseudo_chan(ms)) ++ break; ++ ++ if (!conf_chan->readchunkpreec) ++ break; ++ ++ /* Note: Technically, saturation should be done at ++ the end of the whole addition, but for performance ++ reasons, we don't do that. Besides, it only matters ++ when you're so loud you're clipping anyway */ ++ ACSS(putlin, conf_chan->getlin); ++ ACSS(putlin, conf_chan->readchunkpreec); ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) ++ rxb[x] = DAHDI_LIN2X(putlin[x], ms); ++ ++ break; ++ case DAHDI_CONF_REALANDPSEUDO: ++ /* do normal conf mode processing */ ++ if (ms->confmode & DAHDI_CONF_TALKER) { ++ /* Store temp value */ ++ memcpy(k, putlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* Add conf value */ ++ ACSS(k, conf_sums_next[ms->_confn]); ++ /* get amount actually added */ ++ memcpy(ms->conflast, k, DAHDI_CHUNKSIZE * sizeof(short)); ++ SCSS(ms->conflast, conf_sums_next[ms->_confn]); ++ /* Really add in new value */ ++ ACSS(conf_sums_next[ms->_confn], ms->conflast); ++ } else memset(ms->conflast, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* do the pseudo-channel part processing */ ++ memset(putlin, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ if (ms->confmode & DAHDI_CONF_PSEUDO_LISTENER) { ++ /* Subtract out previous last sample written to conf */ ++ SCSS(putlin, ms->conflast2); ++ /* Add in conference */ ++ ACSS(putlin, conf_sums[ms->_confn]); ++ } ++ /* Convert back */ ++ for(x=0;xconfmode & DAHDI_CONF_LISTENER) { ++ /* Subtract out last sample written to conf */ ++ SCSS(putlin, ms->conflast); ++ /* Add in conference */ ++ ACSS(putlin, conf_sums[ms->_confn]); ++ } ++ /* Convert back */ ++ for(x=0;xputlin, putlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ break; ++ } ++ /* fall through */ ++ case DAHDI_CONF_CONFANN: /* Conference with announce */ ++ if (ms->confmode & DAHDI_CONF_TALKER) { ++ /* Store temp value */ ++ memcpy(k, putlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* Add conf value */ ++ ACSS(k, conf_sums_next[ms->_confn]); ++ /* get amount actually added */ ++ memcpy(ms->conflast, k, DAHDI_CHUNKSIZE * sizeof(short)); ++ SCSS(ms->conflast, conf_sums_next[ms->_confn]); ++ /* Really add in new value */ ++ ACSS(conf_sums_next[ms->_confn], ms->conflast); ++ } else ++ memset(ms->conflast, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* rxc unmodified */ ++ break; ++ case DAHDI_CONF_CONFMON: ++ case DAHDI_CONF_CONFANNMON: ++ if (ms->confmode & DAHDI_CONF_TALKER) { ++ /* Store temp value */ ++ memcpy(k, putlin, DAHDI_CHUNKSIZE * sizeof(short)); ++ /* Subtract last value */ ++ SCSS(conf_sums[ms->_confn], ms->conflast); ++ /* Add conf value */ ++ ACSS(k, conf_sums[ms->_confn]); ++ /* get amount actually added */ ++ memcpy(ms->conflast, k, DAHDI_CHUNKSIZE * sizeof(short)); ++ SCSS(ms->conflast, conf_sums[ms->_confn]); ++ /* Really add in new value */ ++ ACSS(conf_sums[ms->_confn], ms->conflast); ++ } else ++ memset(ms->conflast, 0, DAHDI_CHUNKSIZE * sizeof(short)); ++ for (x=0;x_confn][x], ms); ++ break; ++ case DAHDI_CONF_DIGITALMON: ++ /* if not a pseudo-channel, ignore */ ++ if (!is_pseudo_chan(ms)) ++ break; ++ /* Add monitored channel */ ++ if (is_pseudo_chan(conf_chan)) ++ memcpy(rxb, conf_chan->getraw, DAHDI_CHUNKSIZE); ++ else ++ memcpy(rxb, conf_chan->putraw, DAHDI_CHUNKSIZE); ++ break; ++ } ++ } ++} ++ ++/* HDLC (or other) receiver buffer functions for read side */ ++static void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int bytes) ++{ ++ /* We transmit data from our master channel */ ++ /* Called with ss->lock held */ ++ struct dahdi_chan *ms = ss->master; ++ /* Our receive buffer */ ++ unsigned char *buf; ++#if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP) ++ /* SKB for receiving network stuff */ ++ struct sk_buff *skb=NULL; ++#endif ++ int oldbuf; ++ int eof=0; ++ int abort=0; ++ int res; ++ int left, x; ++ ++ while(bytes) { ++#if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP) ++ skb = NULL; ++#endif ++ abort = 0; ++ eof = 0; ++ /* Next, figure out if we've got a buffer to receive into */ ++ if (ms->inreadbuf > -1) { ++ /* Read into the current buffer */ ++ buf = ms->readbuf[ms->inreadbuf]; ++ left = ms->blocksize - ms->readidx[ms->inreadbuf]; ++ if (left > bytes) ++ left = bytes; ++ if (ms->flags & DAHDI_FLAG_HDLC) { ++ for (x=0;xrxhdlc, *(rxb++)); ++ bytes--; ++ res = fasthdlc_rx_run(&ms->rxhdlc); ++ /* If there is nothing there, continue */ ++ if (res & RETURN_EMPTY_FLAG) ++ continue; ++ else if (res & RETURN_COMPLETE_FLAG) { ++ /* Only count this if it's a non-empty frame */ ++ if (ms->readidx[ms->inreadbuf]) { ++ if ((ms->flags & DAHDI_FLAG_FCS) && (ms->infcs != PPP_GOODFCS)) { ++ abort = DAHDI_EVENT_BADFCS; ++ } else ++ eof=1; ++ break; ++ } ++ continue; ++ } else if (res & RETURN_DISCARD_FLAG) { ++ /* This could be someone idling with ++ "idle" instead of "flag" */ ++ if (!ms->readidx[ms->inreadbuf]) ++ continue; ++ abort = DAHDI_EVENT_ABORT; ++ break; ++ } else { ++ unsigned char rxc; ++ rxc = res; ++ ms->infcs = PPP_FCS(ms->infcs, rxc); ++ buf[ms->readidx[ms->inreadbuf]++] = rxc; ++ /* Pay attention to the possibility of an overrun */ ++ if (ms->readidx[ms->inreadbuf] >= ms->blocksize) { ++ if (!ss->span->alarms) ++ module_printk(KERN_WARNING, "HDLC Receiver overrun on channel %s (master=%s)\n", ss->name, ss->master->name); ++ abort=DAHDI_EVENT_OVERRUN; ++ /* Force the HDLC state back to frame-search mode */ ++ ms->rxhdlc.state = 0; ++ ms->rxhdlc.bits = 0; ++ ms->readidx[ms->inreadbuf]=0; ++ break; ++ } ++ } ++ } ++ } else { ++ /* Not HDLC */ ++ memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left); ++ rxb += left; ++ ms->readidx[ms->inreadbuf] += left; ++ bytes -= left; ++ /* End of frame is decided by block size of 'N' */ ++ eof = (ms->readidx[ms->inreadbuf] >= ms->blocksize); ++ if (eof && (ss->flags & DAHDI_FLAG_NOSTDTXRX)) { ++ eof = 0; ++ abort = DAHDI_EVENT_OVERRUN; ++ } ++ } ++ if (eof) { ++ /* Finished with this buffer, try another. */ ++ oldbuf = ms->inreadbuf; ++ ms->infcs = PPP_INITFCS; ++ ms->readn[ms->inreadbuf] = ms->readidx[ms->inreadbuf]; ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "EOF, len is %d\n", ms->readn[ms->inreadbuf]); ++#endif ++#if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP) ++ if ((ms->flags & DAHDI_FLAG_PPP) || ++ dahdi_have_netdev(ms)) { ++#ifdef CONFIG_DAHDI_NET ++#endif /* CONFIG_DAHDI_NET */ ++ /* Our network receiver logic is MUCH ++ different. We actually only use a single ++ buffer */ ++ if (ms->readn[ms->inreadbuf] > 1) { ++ /* Drop the FCS */ ++ ms->readn[ms->inreadbuf] -= 2; ++ /* Allocate an SKB */ ++#ifdef CONFIG_DAHDI_PPP ++ if (!ms->do_ppp_error) ++#endif ++ skb = dev_alloc_skb(ms->readn[ms->inreadbuf] + 2); ++ if (skb) { ++ unsigned char cisco_addr = *(ms->readbuf[ms->inreadbuf]); ++ if (cisco_addr != 0x0f && cisco_addr != 0x8f) ++ skb_reserve(skb, 2); ++ /* XXX Get rid of this memcpy XXX */ ++ memcpy(skb->data, ms->readbuf[ms->inreadbuf], ms->readn[ms->inreadbuf]); ++ skb_put(skb, ms->readn[ms->inreadbuf]); ++#ifdef CONFIG_DAHDI_NET ++ if (dahdi_have_netdev(ms)) { ++ struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); ++ stats->rx_packets++; ++ stats->rx_bytes += ms->readn[ms->inreadbuf]; ++ } ++#endif ++ ++ } else { ++#ifdef CONFIG_DAHDI_NET ++ if (dahdi_have_netdev(ms)) { ++ struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); ++ stats->rx_dropped++; ++ } ++#endif ++#ifdef CONFIG_DAHDI_PPP ++ if (ms->flags & DAHDI_FLAG_PPP) { ++ abort = DAHDI_EVENT_OVERRUN; ++ } ++#endif ++#if 1 ++#ifdef CONFIG_DAHDI_PPP ++ if (!ms->do_ppp_error) ++#endif ++ module_printk(KERN_NOTICE, "Memory squeeze, dropped one\n"); ++#endif ++ } ++ } ++ /* We don't cycle through buffers, just ++ reuse the same one */ ++ ms->readn[ms->inreadbuf] = 0; ++ ms->readidx[ms->inreadbuf] = 0; ++ } else ++#endif ++ { ++ /* This logic might confuse and astound. Basically we need to find ++ * the previous buffer index. It should be safe because, regardless ++ * of whether or not it has been copied to user space, nothing should ++ * have messed around with it since then */ ++ ++ int comparemessage; ++ /* Shut compiler up */ ++ int myres = 0; ++ ++ if (ms->flags & DAHDI_FLAG_MTP2) { ++ comparemessage = (ms->inreadbuf - 1) & (ms->numbufs - 1); ++ ++ myres = memcmp(ms->readbuf[comparemessage], ms->readbuf[ms->inreadbuf], ms->readn[ms->inreadbuf]); ++ } ++ ++ if ((ms->flags & DAHDI_FLAG_MTP2) && !myres) { ++ /* Our messages are the same, so discard - ++ * Don't advance buffers, reset indexes and buffer sizes. */ ++ ms->readn[ms->inreadbuf] = 0; ++ ms->readidx[ms->inreadbuf] = 0; ++ } else { ++ ms->inreadbuf = (ms->inreadbuf + 1) % ms->numbufs; ++ if (ms->inreadbuf == ms->outreadbuf) { ++ /* Whoops, we're full, and have no where else ++ to store into at the moment. We'll drop it ++ until there's a buffer available */ ++#ifdef BUFFER_DEBUG ++ module_printk(KERN_NOTICE, "Out of storage space\n"); ++#endif ++ ms->inreadbuf = -1; ++ } ++ if (ms->outreadbuf < 0) { /* start out buffer if not already */ ++ ms->outreadbuf = oldbuf; ++ /* if there are processes waiting in poll() on this channel, ++ wake them up */ ++ wake_up_interruptible(&ms->waitq); ++ } ++/* In the very orignal driver, it was quite well known to me (Jim) that there ++was a possibility that a channel sleeping on a receive block needed to ++be potentially woken up EVERY time a buffer was filled, not just on the first ++one, because if only done on the first one there is a slight timing potential ++of missing the wakeup (between where it senses the (lack of) active condition ++(with interrupts disabled) and where it does the sleep (interrupts enabled) ++in the read or iomux call, etc). That is why the read and iomux calls start ++with an infinite loop that gets broken out of upon an active condition, ++otherwise keeps sleeping and looking. The part in this code got "optimized" ++out in the later versions, and is put back now. Note that this is *NOT* ++needed for poll() waiters, because the poll_wait() function that is used there ++is atomic enough for this purpose; it will not go to sleep before ensuring ++that the waitqueue is empty. */ ++ /* Notify a blocked reader that there is data available ++ to be read, unless we're waiting for it to be full */ ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Notifying reader data in block %d\n", oldbuf); ++#endif ++ wake_up_interruptible(&ms->waitq); ++ } ++ } ++ } ++ if (abort) { ++ /* Start over reading frame */ ++ ms->readidx[ms->inreadbuf] = 0; ++ ms->infcs = PPP_INITFCS; ++ ++#ifdef CONFIG_DAHDI_NET ++ if (dahdi_have_netdev(ms)) { ++ struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); ++ stats->rx_errors++; ++ if (abort == DAHDI_EVENT_OVERRUN) ++ stats->rx_over_errors++; ++ if (abort == DAHDI_EVENT_BADFCS) ++ stats->rx_crc_errors++; ++ if (abort == DAHDI_EVENT_ABORT) ++ stats->rx_frame_errors++; ++ } else ++#endif ++#ifdef CONFIG_DAHDI_PPP ++ if (ms->flags & DAHDI_FLAG_PPP) { ++ ms->do_ppp_error = 1; ++ tasklet_schedule(&ms->ppp_calls); ++ } else ++#endif ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &ms->flags) && !ss->span->alarms) { ++ /* Notify the receiver... */ ++ __qevent(ss->master, abort); ++ } ++ } ++ } else /* No place to receive -- drop on the floor */ ++ break; ++#ifdef CONFIG_DAHDI_NET ++ if (skb && dahdi_have_netdev(ms)) ++ { ++ skb_reset_mac_header(skb); ++ skb->dev = chan_to_netdev(ms); ++#ifdef DAHDI_HDLC_TYPE_TRANS ++ skb->protocol = hdlc_type_trans(skb, ++ chan_to_netdev(ms)); ++#else ++ skb->protocol = htons (ETH_P_HDLC); ++#endif ++ netif_rx(skb); ++ } ++#endif ++#ifdef CONFIG_DAHDI_PPP ++ if (skb && (ms->flags & DAHDI_FLAG_PPP)) { ++ unsigned char *tmp; ++ tmp = skb->data; ++ skb_pull(skb, 2); ++ /* Make sure that it's addressed to ALL STATIONS and UNNUMBERED */ ++ if (!tmp || (tmp[0] != 0xff) || (tmp[1] != 0x03)) { ++ /* Invalid SKB -- drop */ ++ if (tmp) ++ module_printk(KERN_NOTICE, "Received invalid SKB (%02x, %02x)\n", tmp[0], tmp[1]); ++ dev_kfree_skb_irq(skb); ++ } else { ++ skb_queue_tail(&ms->ppp_rq, skb); ++ tasklet_schedule(&ms->ppp_calls); ++ } ++ } ++#endif ++ } ++ ++ if (bytes) { ++ if (!test_bit(DAHDI_FLAGBIT_RXOVERRUN, &ms->flags)) { ++ if (test_bit(DAHDI_FLAGBIT_BUFEVENTS, &ms->flags)) ++ __qevent(ms, DAHDI_EVENT_READ_OVERRUN); ++ set_bit(DAHDI_FLAGBIT_RXOVERRUN, &ms->flags); ++ } ++ } else { ++ clear_bit(DAHDI_FLAGBIT_RXOVERRUN, &ms->flags); ++ } ++} ++ ++static inline void __dahdi_putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb) ++{ ++ __putbuf_chunk(ss, rxb, DAHDI_CHUNKSIZE); ++ ++#ifdef CONFIG_DAHDI_MIRROR ++ if (ss->rxmirror) { ++ spin_lock(&ss->rxmirror->lock); ++ __putbuf_chunk(ss->rxmirror, rxb, DAHDI_CHUNKSIZE); ++ spin_unlock(&ss->rxmirror->lock); ++ } ++#endif /* CONFIG_DAHDI_MIRROR */ ++} ++ ++static void __dahdi_hdlc_abort(struct dahdi_chan *ss, int event) ++{ ++ if (ss->inreadbuf >= 0) ++ ss->readidx[ss->inreadbuf] = 0; ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &ss->flags) && !ss->span->alarms) ++ __qevent(ss->master, event); ++} ++ ++void dahdi_hdlc_abort(struct dahdi_chan *ss, int event) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&ss->lock, flags); ++ __dahdi_hdlc_abort(ss, event); ++ spin_unlock_irqrestore(&ss->lock, flags); ++} ++ ++void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int bytes) ++{ ++ unsigned long flags; ++ int left; ++ ++ spin_lock_irqsave(&ss->lock, flags); ++ if (ss->inreadbuf < 0) { ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "No place to receive HDLC frame\n"); ++#endif ++ spin_unlock_irqrestore(&ss->lock, flags); ++ return; ++ } ++ /* Read into the current buffer */ ++ left = ss->blocksize - ss->readidx[ss->inreadbuf]; ++ if (left > bytes) ++ left = bytes; ++ if (left > 0) { ++ memcpy(ss->readbuf[ss->inreadbuf] + ss->readidx[ss->inreadbuf], rxb, left); ++ rxb += left; ++ ss->readidx[ss->inreadbuf] += left; ++ bytes -= left; ++ } ++ /* Something isn't fit into buffer */ ++ if (bytes) { ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "HDLC frame isn't fit into buffer space\n"); ++#endif ++ __dahdi_hdlc_abort(ss, DAHDI_EVENT_OVERRUN); ++ } ++ spin_unlock_irqrestore(&ss->lock, flags); ++} ++ ++void dahdi_hdlc_finish(struct dahdi_chan *ss) ++{ ++ int oldreadbuf; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ss->lock, flags); ++ ++ if ((oldreadbuf = ss->inreadbuf) < 0) { ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "No buffers to finish\n"); ++#endif ++ spin_unlock_irqrestore(&ss->lock, flags); ++ return; ++ } ++ ++ if (!ss->readidx[ss->inreadbuf]) { ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Empty HDLC frame received\n"); ++#endif ++ spin_unlock_irqrestore(&ss->lock, flags); ++ return; ++ } ++ ++ ss->readn[ss->inreadbuf] = ss->readidx[ss->inreadbuf]; ++ ss->inreadbuf = (ss->inreadbuf + 1) % ss->numbufs; ++ if (ss->inreadbuf == ss->outreadbuf) { ++ ss->inreadbuf = -1; ++#ifdef CONFIG_DAHDI_DEBUG ++ module_printk(KERN_NOTICE, "Notifying reader data in block %d\n", oldreadbuf); ++#endif ++ } ++ if (ss->outreadbuf < 0) { ++ ss->outreadbuf = oldreadbuf; ++ } ++ ++ wake_up_interruptible(&ss->waitq); ++ spin_unlock_irqrestore(&ss->lock, flags); ++} ++ ++/* Returns 1 if EOF, 0 if data is still in frame, -1 if EOF and no buffers left */ ++int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size) ++{ ++ unsigned char *buf; ++ unsigned long flags; ++ int left = 0; ++ int res; ++ int oldbuf; ++ ++ spin_lock_irqsave(&ss->lock, flags); ++ if (ss->outwritebuf > -1) { ++ buf = ss->writebuf[ss->outwritebuf]; ++ left = ss->writen[ss->outwritebuf] - ss->writeidx[ss->outwritebuf]; ++ /* Strip off the empty HDLC CRC end */ ++ left -= 2; ++ if (left <= *size) { ++ *size = left; ++ res = 1; ++ } else ++ res = 0; ++ ++ memcpy(bufptr, &buf[ss->writeidx[ss->outwritebuf]], *size); ++ ss->writeidx[ss->outwritebuf] += *size; ++ ++ if (res) { ++ /* Rotate buffers */ ++ oldbuf = ss->outwritebuf; ++ ss->writeidx[oldbuf] = 0; ++ ss->writen[oldbuf] = 0; ++ ss->outwritebuf = (ss->outwritebuf + 1) % ss->numbufs; ++ if (ss->outwritebuf == ss->inwritebuf) { ++ ss->outwritebuf = -1; ++ if (ss->iomask & (DAHDI_IOMUX_WRITE | DAHDI_IOMUX_WRITEEMPTY)) ++ wake_up_interruptible(&ss->waitq); ++ /* If we're only supposed to start when full, disable the transmitter */ ++ if ((ss->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || (ss->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ++ ss->txdisable = 1; ++ res = -1; ++ } ++ ++ if (ss->inwritebuf < 0) ++ ss->inwritebuf = oldbuf; ++ ++ if (!(ss->flags & DAHDI_FLAG_PPP) || ++ !dahdi_have_netdev(ss)) { ++ wake_up_interruptible(&ss->waitq); ++ } ++ } ++ } else { ++ res = -1; ++ *size = 0; ++ } ++ spin_unlock_irqrestore(&ss->lock, flags); ++ ++ return res; ++} ++ ++ ++static void process_timers(void) ++{ ++ struct dahdi_timer *cur; ++ ++ if (list_empty(&dahdi_timers)) ++ return; ++ ++ spin_lock(&dahdi_timer_lock); ++ list_for_each_entry(cur, &dahdi_timers, list) { ++ spin_lock(&cur->lock); ++ cur->pos -= DAHDI_CHUNKSIZE; ++ if (cur->pos <= 0) { ++ cur->tripped++; ++ cur->pos = cur->ms; ++ wake_up_interruptible(&cur->sel); ++ } ++ spin_unlock(&cur->lock); ++ } ++ spin_unlock(&dahdi_timer_lock); ++} ++ ++static unsigned int dahdi_timer_poll(struct file *file, struct poll_table_struct *wait_table) ++{ ++ struct dahdi_timer *timer = file->private_data; ++ unsigned long flags; ++ int ret = 0; ++ if (timer) { ++ poll_wait(file, &timer->sel, wait_table); ++ spin_lock_irqsave(&timer->lock, flags); ++ if (timer->tripped || timer->ping) ++ ret |= POLLPRI; ++ spin_unlock_irqrestore(&timer->lock, flags); ++ } else { ++ /* ++ * This should never happen. Surprise device removal ++ * should lead us to the nodev_* file_operations ++ */ ++ msleep(5); ++ module_printk(KERN_ERR, "%s: NODEV\n", __func__); ++ return POLLERR | POLLHUP | POLLRDHUP | POLLNVAL | POLLPRI; ++ } ++ return ret; ++} ++ ++/* device poll routine */ ++static unsigned int ++dahdi_chan_poll(struct file *file, struct poll_table_struct *wait_table) ++{ ++ struct dahdi_chan *const c = file->private_data; ++ int ret = 0; ++ unsigned long flags; ++ ++ if (unlikely(!c)) { ++ /* ++ * This should never happen. Surprise device removal ++ * should lead us to the nodev_* file_operations ++ */ ++ msleep(5); ++ module_printk(KERN_ERR, "%s: NODEV\n", __func__); ++ return POLLERR | POLLHUP | POLLRDHUP | POLLNVAL | POLLPRI; ++ } ++ ++ poll_wait(file, &c->waitq, wait_table); ++ ++ spin_lock_irqsave(&c->lock, flags); ++ ret |= (c->inwritebuf > -1) ? POLLOUT|POLLWRNORM : 0; ++ ret |= (c->outreadbuf > -1) ? POLLIN|POLLRDNORM : 0; ++ ret |= (c->eventoutidx != c->eventinidx) ? POLLPRI : 0; ++ spin_unlock_irqrestore(&c->lock, flags); ++ ++ return ret; ++} ++ ++static unsigned int dahdi_poll(struct file *file, struct poll_table_struct *wait_table) ++{ ++ const int unit = UNIT(file); ++ ++ if (likely(unit == DAHDI_TIMER)) ++ return dahdi_timer_poll(file, wait_table); ++ ++ /* transcoders and channels should have updated their file_operations ++ * before poll is ever called. */ ++ return -EINVAL; ++} ++ ++static void __dahdi_transmit_chunk(struct dahdi_chan *chan, unsigned char *buf) ++{ ++ unsigned char silly[DAHDI_CHUNKSIZE]; ++ /* Called with chan->lock locked */ ++#ifdef OPTIMIZE_CHANMUTE ++ if(likely(chan->chanmute)) ++ return; ++#endif ++ if (!buf) ++ buf = silly; ++ __dahdi_getbuf_chunk(chan, buf); ++ ++ if ((chan->flags & DAHDI_FLAG_AUDIO) || (chan->confmode)) { ++#ifdef CONFIG_DAHDI_MMX ++ dahdi_kernel_fpu_begin(); ++#endif ++ __dahdi_process_getaudio_chunk(chan, buf); ++#ifdef CONFIG_DAHDI_MMX ++ dahdi_kernel_fpu_end(); ++#endif ++ } ++} ++ ++static inline void __dahdi_real_transmit(struct dahdi_chan *chan) ++{ ++ /* Called with chan->lock held */ ++#ifdef OPTIMIZE_CHANMUTE ++ if(likely(chan->chanmute)) ++ return; ++#endif ++ if (chan->confmode) { ++ /* Pull queued data off the conference */ ++ __buf_pull(&chan->confout, chan->writechunk, chan); ++ } else { ++ __dahdi_transmit_chunk(chan, chan->writechunk); ++ } ++} ++ ++static void __dahdi_getempty(struct dahdi_chan *ms, unsigned char *buf) ++{ ++ int bytes = DAHDI_CHUNKSIZE; ++ int left; ++ unsigned char *txb = buf; ++ int x; ++ short getlin; ++ /* Called with ms->lock held */ ++ ++ while(bytes) { ++ /* Receive silence, or tone */ ++ if (ms->curtone) { ++ left = ms->curtone->tonesamples - ms->tonep; ++ if (left > bytes) ++ left = bytes; ++ for (x=0;xts, ms->curtone); ++ *(txb++) = DAHDI_LIN2X(getlin, ms); ++ } ++ ms->tonep+=left; ++ bytes -= left; ++ if (ms->tonep >= ms->curtone->tonesamples) { ++ struct dahdi_tone *last; ++ /* Go to the next sample of the tone */ ++ ms->tonep = 0; ++ last = ms->curtone; ++ ms->curtone = ms->curtone->next; ++ if (!ms->curtone) { ++ /* No more tones... Is this dtmf or mf? If so, go to the next digit */ ++ if (ms->dialing) ++ __do_dtmf(ms); ++ } else { ++ if (last != ms->curtone) ++ dahdi_init_tone_state(&ms->ts, ms->curtone); ++ } ++ } ++ } else { ++ /* Use silence */ ++ memset(txb, DAHDI_LIN2X(0, ms), bytes); ++ bytes = 0; ++ } ++ } ++ ++} ++ ++static void __dahdi_receive_chunk(struct dahdi_chan *chan, unsigned char *buf) ++{ ++ /* Receive chunk of audio -- called with chan->lock held */ ++ unsigned char waste[DAHDI_CHUNKSIZE]; ++ ++#ifdef OPTIMIZE_CHANMUTE ++ if(likely(chan->chanmute)) ++ return; ++#endif ++ if (!buf) { ++ memset(waste, DAHDI_LIN2X(0, chan), sizeof(waste)); ++ buf = waste; ++ } ++ if ((chan->flags & DAHDI_FLAG_AUDIO) || (chan->confmode)) { ++#ifdef CONFIG_DAHDI_MMX ++ dahdi_kernel_fpu_begin(); ++#endif ++ __dahdi_process_putaudio_chunk(chan, buf); ++#ifdef CONFIG_DAHDI_MMX ++ dahdi_kernel_fpu_end(); ++#endif ++ } ++ __dahdi_putbuf_chunk(chan, buf); ++} ++ ++static inline void __dahdi_real_receive(struct dahdi_chan *chan) ++{ ++ /* Called with chan->lock held */ ++#ifdef OPTIMIZE_CHANMUTE ++ if(likely(chan->chanmute)) ++ return; ++#endif ++ if (chan->confmode) { ++ /* Load into queue if we have space */ ++ __buf_push(&chan->confin, chan->readchunk); ++ } else { ++ __dahdi_receive_chunk(chan, chan->readchunk); ++ } ++} ++ ++/** ++ * __transmit_to_slaves() - Distribute the tx data to all the slave channels. ++ * ++ */ ++static void __transmit_to_slaves(struct dahdi_chan *const chan) ++{ ++ u_char data[DAHDI_CHUNKSIZE]; ++ int i; ++ int pos = DAHDI_CHUNKSIZE; ++ struct dahdi_chan *slave; ++ for (i = 0; i < DAHDI_CHUNKSIZE; i++) { ++ for (slave = chan; (NULL != slave); slave = slave->nextslave) { ++ if (pos == DAHDI_CHUNKSIZE) { ++ __dahdi_transmit_chunk(chan, data); ++ pos = 0; ++ } ++ slave->writechunk[i] = data[pos++]; ++ } ++ } ++} ++ ++int _dahdi_transmit(struct dahdi_span *span) ++{ ++ unsigned int x; ++ ++ for (x=0;xchannels;x++) { ++ struct dahdi_chan *const chan = span->chans[x]; ++ spin_lock(&chan->lock); ++ if (unlikely(chan->flags & DAHDI_FLAG_NOSTDTXRX)) { ++ spin_unlock(&chan->lock); ++ continue; ++ } ++ if (chan == chan->master) { ++ if (is_chan_dacsed(chan)) { ++ struct dahdi_chan *const src = chan->dacs_chan; ++ memcpy(chan->writechunk, src->readchunk, ++ DAHDI_CHUNKSIZE); ++ if (chan->sig == DAHDI_SIG_DACS_RBS) { ++ /* Just set bits for our destination */ ++ if (chan->txsig != src->rxsig) { ++ chan->txsig = src->rxsig; ++ span->ops->rbsbits(chan, src->rxsig); ++ } ++ } ++ /* there is no further processing to do for ++ * DACS channels, so jump to the next channel ++ * in the span */ ++ spin_unlock(&chan->lock); ++ continue; ++ } else if (chan->nextslave) { ++ __transmit_to_slaves(chan); ++ } else { ++ /* Process a normal channel */ ++ __dahdi_real_transmit(chan); ++ } ++ if (chan->otimer) { ++ chan->otimer -= DAHDI_CHUNKSIZE; ++ if (chan->otimer <= 0) ++ __rbs_otimer_expire(chan); ++ } ++ } ++ spin_unlock(&chan->lock); ++ } ++ ++ if (span->mainttimer) { ++ span->mainttimer -= DAHDI_CHUNKSIZE; ++ if (span->mainttimer <= 0) { ++ span->mainttimer = 0; ++ span->maintstat = 0; ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(_dahdi_transmit); ++ ++static inline void __pseudo_rx_audio(struct dahdi_chan *chan) ++{ ++ unsigned char tmp[DAHDI_CHUNKSIZE]; ++ spin_lock(&chan->lock); ++ __dahdi_getempty(chan, tmp); ++ __dahdi_receive_chunk(chan, tmp); ++ spin_unlock(&chan->lock); ++} ++ ++#ifdef CONFIG_DAHDI_MIRROR ++static inline void pseudo_rx_audio(struct dahdi_chan *chan) ++{ ++ if (!chan->srcmirror) ++ __pseudo_rx_audio(chan); ++} ++#else ++static inline void pseudo_rx_audio(struct dahdi_chan *chan) ++{ ++ __pseudo_rx_audio(chan); ++} ++#endif /* CONFIG_DAHDI_MIRROR */ ++ ++#ifdef DAHDI_SYNC_TICK ++static inline void dahdi_sync_tick(struct dahdi_span *const s) ++{ ++ if (s->ops->sync_tick) ++ s->ops->sync_tick(s, dahdi_is_sync_master(s)); ++} ++#else ++#define dahdi_sync_tick(x) do { ; } while (0) ++#endif ++ ++/** ++ * _process_masterspan - Handle conferencing and timers. ++ * ++ * There are three sets of conference sum accumulators. One for the current ++ * sample chunk (conf_sums), one for the next sample chunk (conf_sums_next), and ++ * one for the previous sample chunk (conf_sums_prev). The following routine ++ * (rotate_sums) "rotates" the pointers to these accululator arrays as part ++ * of the events of sample chink processing as follows: ++ * ++ * 1. All (real span) receive chunks are processed (with putbuf). The last one ++ * to be processed is the master span. The data received is loaded into the ++ * accumulators for the next chunk (conf_sums_next), to be in alignment with ++ * current data after rotate_sums() is called (which immediately follows). ++ * Keep in mind that putbuf is *also* a transmit routine for the pseudo parts ++ * of channels that are in the REALANDPSEUDO conference mode. These channels ++ * are processed from data in the current sample chunk (conf_sums), being ++ * that this is a "transmit" function (for the pseudo part). ++ * ++ * 2. rotate_sums() is called. ++ * ++ * 3. All pseudo channel receive chunks are processed. This data is loaded into ++ * the current sample chunk accumulators (conf_sums). ++ * ++ * 4. All conference links are processed (being that all receive data for this ++ * chunk has already been processed by now). ++ * ++ * 5. All pseudo channel transmit chunks are processed. This data is loaded from ++ * the current sample chunk accumulators (conf_sums). ++ * ++ * 6. All (real span) transmit chunks are processed (with getbuf). This data is ++ * loaded from the current sample chunk accumulators (conf_sums). Keep in mind ++ * that getbuf is *also* a receive routine for the pseudo part of channels that ++ * are in the REALANDPSEUDO conference mode. These samples are loaded into ++ * the next sample chunk accumulators (conf_sums_next) to be processed as part ++ * of the next sample chunk's data (next time around the world). ++ * ++ */ ++static void _process_masterspan(void) ++{ ++ int x; ++ struct pseudo_chan *pseudo; ++ struct dahdi_span *s; ++ u_char *data; ++ ++#ifdef CONFIG_DAHDI_CORE_TIMER ++ /* We increment the calls since start here, so that if we switch over ++ * to the core timer, we know how many times we need to call ++ * process_masterspan in order to catch up since this function needs ++ * to be called (1000 / (DAHDI_CHUNKSIZE / 8)) times per second. */ ++ atomic_inc(&core_timer.count); ++#endif ++ /* Hold the chan_lock for the duration of major ++ activities which touch all sorts of channels */ ++ spin_lock(&chan_lock); ++ ++ /* Process any timers */ ++ process_timers(); ++ ++ list_for_each_entry(s, &span_list, spans_node) { ++ for (x = 0; x < s->channels; ++x) { ++ struct dahdi_chan *const chan = s->chans[x]; ++ if (!chan->confmode) ++ continue; ++ spin_lock(&chan->lock); ++ data = __buf_peek(&chan->confin); ++ __dahdi_receive_chunk(chan, data); ++ if (data) ++ __buf_pull(&chan->confin, NULL, chan); ++ spin_unlock(&chan->lock); ++ } ++ } ++ ++ /* This is the master channel, so make things switch over */ ++ rotate_sums(); ++ ++ /* do all the pseudo and/or conferenced channel receives (getbuf's) */ ++ list_for_each_entry(pseudo, &pseudo_chans, node) { ++ spin_lock(&pseudo->chan.lock); ++ __dahdi_transmit_chunk(&pseudo->chan, NULL); ++ spin_unlock(&pseudo->chan.lock); ++ } ++ ++#ifdef CONFIG_DAHDI_CONFLINK ++ if (maxlinks) { ++ int z; ++ int y; ++#ifdef CONFIG_DAHDI_MMX ++ dahdi_kernel_fpu_begin(); ++#endif ++ /* process all the conf links */ ++ for (x = 1; x <= maxlinks; x++) { ++ /* if we have a destination conf */ ++ z = confalias[conf_links[x].dst]; ++ if (z) { ++ y = confalias[conf_links[x].src]; ++ if (y) ++ ACSS(conf_sums[z], conf_sums[y]); ++ } ++ } ++#ifdef CONFIG_DAHDI_MMX ++ dahdi_kernel_fpu_end(); ++#endif ++ } ++#endif /* CONFIG_DAHDI_CONFLINK */ ++ ++ /* do all the pseudo/conferenced channel transmits (putbuf's) */ ++ list_for_each_entry(pseudo, &pseudo_chans, node) { ++ pseudo_rx_audio(&pseudo->chan); ++ } ++ ++ list_for_each_entry(s, &span_list, spans_node) { ++ for (x = 0; x < s->channels; x++) { ++ struct dahdi_chan *const chan = s->chans[x]; ++ if (!chan->confmode) ++ continue; ++ spin_lock(&chan->lock); ++ data = __buf_pushpeek(&chan->confout); ++ __dahdi_transmit_chunk(chan, data); ++ if (data) ++ __buf_push(&chan->confout, NULL); ++ spin_unlock(&chan->lock); ++ } ++ ++ dahdi_sync_tick(s); ++ } ++ spin_unlock(&chan_lock); ++} ++ ++#ifndef CONFIG_DAHDI_CORE_TIMER ++ ++static void coretimer_init(void) ++{ ++ return; ++} ++ ++static void coretimer_cleanup(void) ++{ ++ return; ++} ++ ++#else ++ ++static inline unsigned long msecs_processed(const struct core_timer *const ct) ++{ ++ return atomic_read(&ct->count) * DAHDI_MSECS_PER_CHUNK; ++} ++ ++static void coretimer_func(TIMER_DATA_TYPE unused) ++{ ++ unsigned long flags; ++ long ms_since_start; ++ ktime_t now; ++ const unsigned long MAX_INTERVAL = 100000L; ++ const unsigned long ONESEC_INTERVAL = HZ; ++ const long MS_LIMIT = 3000; ++ long difference; ++ ++ now = ktime_get(); ++ ++ if (atomic_read(&core_timer.count) == ++ atomic_read(&core_timer.last_count)) { ++ ++ /* This is the code path if a board driver is not calling ++ * dahdi_receive, and therefore the core of dahdi needs to ++ * perform the master span processing itself. */ ++ if (core_timer.dahdi_receive_used) { ++ core_timer.dahdi_receive_used = 0; ++ dahdi_dbg(GENERAL, "Master changed to core_timer\n"); ++ } ++ ++ if (!atomic_read(&core_timer.shutdown)) { ++ mod_timer(&core_timer.timer, jiffies + ++ core_timer.interval); ++ } ++ ++ ms_since_start = ktime_ms_delta(now, core_timer.start_interval); ++ ++ /* ++ * If the system time has changed, it is possible for us to be ++ * far behind. If we are more than MS_LIMIT milliseconds ++ * behind (or ahead in time), just reset our time base and ++ * continue so that we do not hang the system here. ++ * ++ */ ++ difference = ms_since_start - msecs_processed(&core_timer); ++ if (unlikely((difference > MS_LIMIT) || (difference < 0))) { ++ if (printk_ratelimit()) { ++ module_printk(KERN_INFO, ++ "Detected time shift.\n"); ++ } ++ atomic_set(&core_timer.count, 0); ++ atomic_set(&core_timer.last_count, 0); ++ core_timer.start_interval = now; ++ return; ++ } ++ ++ local_irq_save(flags); ++ while (ms_since_start > msecs_processed(&core_timer)) ++ _process_masterspan(); ++ local_irq_restore(flags); ++ ++ if (ms_since_start > MAX_INTERVAL) { ++ atomic_set(&core_timer.count, 0); ++ atomic_set(&core_timer.last_count, 0); ++ core_timer.start_interval = now; ++ } else { ++ atomic_set(&core_timer.last_count, ++ atomic_read(&core_timer.count)); ++ } ++ ++ } else { ++ ++ /* It looks like a board driver is calling dahdi_receive. We ++ * will just check again in a second. */ ++ if (!core_timer.dahdi_receive_used) { ++ core_timer.dahdi_receive_used = 1; ++ dahdi_dbg(GENERAL, "Master is no longer core_timer\n"); ++ } ++ atomic_set(&core_timer.count, 0); ++ atomic_set(&core_timer.last_count, 0); ++ core_timer.start_interval = now; ++ if (!atomic_read(&core_timer.shutdown)) ++ mod_timer(&core_timer.timer, jiffies + ONESEC_INTERVAL); ++ } ++} ++ ++static void coretimer_init(void) ++{ ++ timer_setup(&core_timer.timer, coretimer_func, 0); ++ core_timer.start_interval = ktime_get(); ++ atomic_set(&core_timer.count, 0); ++ atomic_set(&core_timer.shutdown, 0); ++ core_timer.interval = max(msecs_to_jiffies(DAHDI_MSECS_PER_CHUNK), 1UL); ++ if (core_timer.interval < (HZ/250)) ++ core_timer.interval = (HZ/250); ++ mod_timer(&core_timer.timer, jiffies + core_timer.interval); ++} ++ ++static void coretimer_cleanup(void) ++{ ++ atomic_set(&core_timer.shutdown, 1); ++ del_timer_sync(&core_timer.timer); ++} ++ ++#endif /* CONFIG_DAHDI_CORE_TIMER */ ++ ++/** ++ * __receive_from_slaves() - Collect the rx data from all the slave channels. ++ * ++ */ ++static void __receive_from_slaves(struct dahdi_chan *const chan) ++{ ++ u_char data[DAHDI_CHUNKSIZE]; ++ int i; ++ int pos = 0; ++ struct dahdi_chan *slave; ++ ++ for (i = 0; i < DAHDI_CHUNKSIZE; ++i) { ++ for (slave = chan; (NULL != slave); slave = slave->nextslave) { ++ data[pos++] = slave->readchunk[i]; ++ if (pos == DAHDI_CHUNKSIZE) { ++ __dahdi_receive_chunk(chan, data); ++ pos = 0; ++ } ++ } ++ } ++} ++ ++static inline bool should_skip_receive(const struct dahdi_chan *const chan) ++{ ++ return (unlikely(chan->flags & DAHDI_FLAG_NOSTDTXRX) || ++ (chan->master != chan) || ++ is_chan_dacsed(chan)); ++} ++ ++int _dahdi_receive(struct dahdi_span *span) ++{ ++ unsigned int x; ++ ++#ifdef CONFIG_DAHDI_WATCHDOG ++ span->watchcounter--; ++#endif ++ for (x = 0; x < span->channels; x++) { ++ struct dahdi_chan *const chan = span->chans[x]; ++ spin_lock(&chan->lock); ++ if (should_skip_receive(chan)) { ++ spin_unlock(&chan->lock); ++ continue; ++ } ++ ++ if (chan->nextslave) { ++ __receive_from_slaves(chan); ++ } else { ++ /* Process a normal channel */ ++ __dahdi_real_receive(chan); ++ } ++ if (chan->itimer) { ++ chan->itimer -= DAHDI_CHUNKSIZE; ++ if (chan->itimer <= 0) ++ rbs_itimer_expire(chan); ++ } ++ if (chan->ringdebtimer) ++ chan->ringdebtimer--; ++ if (chan->sig & __DAHDI_SIG_FXS) { ++ if (chan->rxhooksig == DAHDI_RXSIG_RING) ++ chan->ringtrailer = DAHDI_RINGTRAILER; ++ else if (chan->ringtrailer) { ++ chan->ringtrailer -= DAHDI_CHUNKSIZE; ++ /* See if RING trailer is expired */ ++ if (!chan->ringtrailer && !chan->ringdebtimer) ++ __qevent(chan, DAHDI_EVENT_RINGOFFHOOK); ++ } ++ } ++ if (chan->pulsetimer) { ++ chan->pulsetimer--; ++ if (chan->pulsetimer <= 0) { ++ if (chan->pulsecount) { ++ if (chan->pulsecount > 12) { ++ ++ module_printk(KERN_NOTICE, "Got pulse digit %d on %s???\n", ++ chan->pulsecount, ++ chan->name); ++ } else if (chan->pulsecount > 11) { ++ __qevent(chan, DAHDI_EVENT_PULSEDIGIT | '#'); ++ } else if (chan->pulsecount > 10) { ++ __qevent(chan, DAHDI_EVENT_PULSEDIGIT | '*'); ++ } else if (chan->pulsecount > 9) { ++ __qevent(chan, DAHDI_EVENT_PULSEDIGIT | '0'); ++ } else { ++ __qevent(chan, DAHDI_EVENT_PULSEDIGIT | ('0' + ++ chan->pulsecount)); ++ } ++ chan->pulsecount = 0; ++ } ++ } ++ } ++#ifdef BUFFER_DEBUG ++ chan->statcount -= DAHDI_CHUNKSIZE; ++#endif ++ spin_unlock(&chan->lock); ++ } ++ ++ if (dahdi_is_sync_master(span)) ++ _process_masterspan(); ++ ++ return 0; ++} ++EXPORT_SYMBOL(_dahdi_receive); ++ ++MODULE_AUTHOR("Mark Spencer "); ++MODULE_DESCRIPTION("DAHDI Telephony Interface"); ++MODULE_LICENSE("GPL v2"); ++/* DAHDI now provides timing. If anybody wants dahdi_dummy it's probably ++ * for that. So make dahdi provide it for now. This alias may be removed ++ * in the future, and users are encouraged not to rely on it. */ ++MODULE_ALIAS("dahdi_dummy"); ++ ++module_param(debug, int, 0644); ++MODULE_PARM_DESC(debug, "Sets debugging verbosity as a bitfield, to see"\ ++ " general debugging set this to 1. To see RBS debugging set"\ ++ " this to 32"); ++module_param(deftaps, int, 0644); ++ ++module_param(max_pseudo_channels, int, 0644); ++MODULE_PARM_DESC(max_pseudo_channels, "Maximum number of pseudo channels."); ++ ++module_param(hwec_overrides_swec, int, 0644); ++MODULE_PARM_DESC(hwec_overrides_swec, "When true, a hardware echo canceller is used instead of configured SWEC."); ++ ++module_param(auto_assign_spans, int, 0644); ++MODULE_PARM_DESC(auto_assign_spans, ++ "If 1 spans will automatically have their children span and " ++ "channel numbers assigned by the driver. If 0, user space " ++ "will need to assign them via /sys/bus/dahdi_devices."); ++ ++ ++static ssize_t dahdi_no_read(struct file *file, char __user *usrbuf, ++ size_t count, loff_t *ppos) ++{ ++ return -ENOSYS; ++} ++static ssize_t dahdi_no_write(struct file *file, const char __user *usrbuf, ++ size_t count, loff_t *ppos) ++{ ++ return -ENOSYS; ++} ++ ++static const struct file_operations dahdi_fops = { ++ .owner = THIS_MODULE, ++ .open = dahdi_open, ++ .release = dahdi_release, ++#ifdef HAVE_UNLOCKED_IOCTL ++ .unlocked_ioctl = dahdi_unlocked_ioctl, ++#ifdef HAVE_COMPAT_IOCTL ++ .compat_ioctl = dahdi_ioctl_compat, ++#endif ++#else ++ .ioctl = dahdi_ioctl, ++#endif ++ .poll = dahdi_poll, ++ .read = dahdi_no_read, ++ .write = dahdi_no_write, ++}; ++ ++static const struct file_operations dahdi_timer_fops = { ++ .owner = THIS_MODULE, ++ .release = dahdi_timer_release, ++#ifdef HAVE_UNLOCKED_IOCTL ++ .unlocked_ioctl = dahdi_timer_unlocked_ioctl, ++#ifdef HAVE_COMPAT_IOCTL ++ .compat_ioctl = dahdi_timer_unlocked_ioctl, ++#endif ++#else ++ .ioctl = dahdi_timer_ioctl, ++#endif ++ .poll = dahdi_timer_poll, ++ .read = dahdi_no_read, ++ .write = dahdi_no_write, ++}; ++ ++/* ++ * DAHDI stability should not depend on the calling process behaviour. ++ * In case of suprise device removal, we should be able to return ++ * sane results (-ENODEV) even after the underlying device was released. ++ * ++ * This should be OK even if the calling process (hint, hint Asterisk) ++ * ignores the system calls return value. ++ * ++ * We simply use dummy file_operations to implement this. ++ */ ++ ++/* ++ * Common behaviour called from all other nodev_*() file_operations ++ */ ++static int nodev_common(const char msg[]) ++{ ++ if (printk_ratelimit()) { ++ module_printk(KERN_NOTICE, ++ "nodev: %s: process %d still calling\n", ++ msg, current->tgid); ++ } ++ msleep(5); ++ return -ENODEV; ++} ++ ++static ssize_t nodev_chan_read(struct file *file, char __user *usrbuf, ++ size_t count, loff_t *ppos) ++{ ++ return nodev_common("read"); ++} ++ ++static ssize_t nodev_chan_write(struct file *file, const char __user *usrbuf, ++ size_t count, loff_t *ppos) ++{ ++ return nodev_common("write"); ++} ++ ++static unsigned int ++nodev_chan_poll(struct file *file, struct poll_table_struct *wait_table) ++{ ++ return nodev_common("poll"); ++} ++ ++static long ++nodev_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data) ++{ ++ switch (cmd) { ++ case DAHDI_GETEVENT: /* Get event on queue */ ++ /* ++ * Hint the bugger that the channel is gone for good ++ */ ++ put_user(DAHDI_EVENT_REMOVED, (int __user *)data); ++ break; ++ } ++ return nodev_common("ioctl"); ++} ++ ++#ifndef HAVE_UNLOCKED_IOCTL ++static int nodev_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long data) ++{ ++ return nodev_unlocked_ioctl(file, cmd, data); ++} ++#endif ++ ++#ifdef HAVE_COMPAT_IOCTL ++static long nodev_ioctl_compat(struct file *file, unsigned int cmd, ++ unsigned long data) ++{ ++ if (cmd == DAHDI_SFCONFIG) ++ return -ENOTTY; /* Not supported yet */ ++ ++ return nodev_unlocked_ioctl(file, cmd, data); ++} ++#endif ++ ++static const struct file_operations nodev_fops = { ++ .owner = THIS_MODULE, ++#ifdef HAVE_UNLOCKED_IOCTL ++ .unlocked_ioctl = nodev_unlocked_ioctl, ++#ifdef HAVE_COMPAT_IOCTL ++ .compat_ioctl = nodev_ioctl_compat, ++#endif ++#else ++ .ioctl = nodev_ioctl, ++#endif ++ .read = nodev_chan_read, ++ .write = nodev_chan_write, ++ .poll = nodev_chan_poll, ++}; ++ ++static const struct file_operations dahdi_chan_fops = { ++ .owner = THIS_MODULE, ++ .open = dahdi_open, ++ .release = dahdi_release, ++#ifdef HAVE_UNLOCKED_IOCTL ++ .unlocked_ioctl = dahdi_unlocked_ioctl, ++#ifdef HAVE_COMPAT_IOCTL ++ .compat_ioctl = dahdi_ioctl_compat, ++#endif ++#else ++ .ioctl = dahdi_ioctl, ++#endif ++ .read = dahdi_chan_read, ++ .write = dahdi_chan_write, ++ .poll = dahdi_chan_poll, ++}; ++ ++#ifdef CONFIG_DAHDI_WATCHDOG ++static struct timer_list watchdogtimer; ++ ++static void watchdog_check(TIMER_DATA_TYPE ignored) ++{ ++ unsigned long flags; ++ static int wdcheck=0; ++ struct dahdi_span *s; ++ ++ spin_lock_irqsave(&chan_lock, flags); ++ list_for_each_entry(s, &span_list, spans_node) { ++ if (s->flags & DAHDI_FLAG_RUNNING) { ++ if (s->watchcounter == DAHDI_WATCHDOG_INIT) { ++ /* Whoops, dead card */ ++ if ((s->watchstate == DAHDI_WATCHSTATE_OK) || ++ (s->watchstate == DAHDI_WATCHSTATE_UNKNOWN)) { ++ s->watchstate = DAHDI_WATCHSTATE_RECOVERING; ++ if (s->ops->watchdog) { ++ module_printk(KERN_NOTICE, "Kicking span %s\n", s->name); ++ s->ops->watchdog(s, DAHDI_WATCHDOG_NOINTS); ++ } else { ++ module_printk(KERN_NOTICE, "Span %s is dead with no revival\n", s->name); ++ s->watchstate = DAHDI_WATCHSTATE_FAILED; ++ } ++ } ++ } else { ++ if ((s->watchstate != DAHDI_WATCHSTATE_OK) && ++ (s->watchstate != DAHDI_WATCHSTATE_UNKNOWN)) ++ module_printk(KERN_NOTICE, "Span %s is alive!\n", s->name); ++ s->watchstate = DAHDI_WATCHSTATE_OK; ++ } ++ s->watchcounter = DAHDI_WATCHDOG_INIT; ++ } ++ } ++ spin_unlock_irqrestore(&chan_lock, flags); ++ if (!wdcheck) { ++ module_printk(KERN_NOTICE, "watchdog on duty!\n"); ++ wdcheck=1; ++ } ++ mod_timer(&watchdogtimer, jiffies + 2); ++} ++ ++static int __init watchdog_init(void) ++{ ++ timer_setup(&watchdogtimer, watchdog_check, 0); ++ /* Run every couple of jiffy or so */ ++ mod_timer(&watchdogtimer, jiffies + 2); ++ return 0; ++} ++ ++static void __exit watchdog_cleanup(void) ++{ ++ del_timer(&watchdogtimer); ++} ++ ++#endif ++ ++static int __init dahdi_init(void) ++{ ++ int res = 0; ++ ++ module_printk(KERN_INFO, "Version: %s\n", dahdi_version); ++#ifdef CONFIG_PROC_FS ++ root_proc_entry = proc_mkdir("dahdi", NULL); ++ if (!root_proc_entry) { ++ dahdi_err("dahdi init: Failed creating /proc/dahdi\n"); ++ return -EEXIST; ++ } ++#endif ++ res = dahdi_sysfs_init(&dahdi_fops); ++ if (res) ++ goto failed_driver_init; ++ ++ dahdi_conv_init(); ++ fasthdlc_precalc(); ++ rotate_sums(); ++#ifdef CONFIG_DAHDI_WATCHDOG ++ watchdog_init(); ++#endif ++ coretimer_init(); ++ ++ res = dahdi_register_echocan_factory(&hwec_factory); ++ if (res) { ++ WARN_ON(1); ++ goto failed_register_ec_factory; ++ } ++ ++ return 0; ++ ++failed_register_ec_factory: ++ coretimer_cleanup(); ++ dahdi_sysfs_exit(); ++failed_driver_init: ++ if (root_proc_entry) { ++ remove_proc_entry("dahdi", NULL); ++ root_proc_entry = NULL; ++ } ++ return res; ++} ++ ++static inline void flush_find_master_work(void) ++{ ++ cancel_work_sync(&find_master_work); ++} ++ ++static void __exit dahdi_cleanup(void) ++{ ++ struct dahdi_zone *z; ++ ++ dahdi_unregister_echocan_factory(&hwec_factory); ++ coretimer_cleanup(); ++ dahdi_sysfs_exit(); ++ ++#ifdef CONFIG_PROC_FS ++ if (root_proc_entry) { ++ remove_proc_entry("dahdi", NULL); ++ root_proc_entry = NULL; ++ } ++#endif ++ ++ module_printk(KERN_INFO, "Telephony Interface Unloaded\n"); ++ ++ spin_lock(&zone_lock); ++ while (!list_empty(&tone_zones)) { ++ z = list_entry(tone_zones.next, struct dahdi_zone, node); ++ list_del(&z->node); ++ if (!tone_zone_put(z)) { ++ module_printk(KERN_WARNING, ++ "Potential memory leak detected in %s\n", ++ __func__); ++ } ++ } ++ spin_unlock(&zone_lock); ++ ++#ifdef CONFIG_DAHDI_WATCHDOG ++ watchdog_cleanup(); ++#endif ++ flush_find_master_work(); ++} ++ ++module_init(dahdi_init); ++module_exit(dahdi_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi-sysfs-chan.c linux-source-4.19-dahdi/drivers/dahdi/dahdi-sysfs-chan.c +--- linux-source-4.19/drivers/dahdi/dahdi-sysfs-chan.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi-sysfs-chan.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,523 @@ ++/* dahdi-sysfs-chan.c ++ * ++ * Copyright (C) 2011-2012, Xorcom ++ * Copyright (C) 2011-2012, 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 ++ ++#define DAHDI_PRINK_MACROS_USE_debug ++#include ++#include ++#include ++#include ++#include ++#include "dahdi.h" ++#include "dahdi-sysfs.h" ++ ++/* shortcuts, for code readability */ ++#define MAKE_DAHDI_DEV(num, name) \ ++ device_create(dahdi_class, NULL, MKDEV(DAHDI_MAJOR, num), \ ++ NULL, "%s", name) ++ ++#define DEL_DAHDI_DEV(num) \ ++ device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, num)) ++ ++static struct class *dahdi_class; ++ ++static dev_t dahdi_channels_devt; /*!< Device number of first channel */ ++static struct cdev dahdi_channels_cdev; /*!< Channels chardev's */ ++ ++/* ++ * Flags to remember what initializations already ++ * succeeded. ++ */ ++static struct { ++ u32 channel_driver:1; ++ u32 channels_bus:1; ++ u32 cdev:1; ++} should_cleanup; ++ ++#define chan_attr(field, format_string) \ ++static BUS_ATTR_READER(field##_show, dev, buf) \ ++{ \ ++ struct dahdi_chan *chan; \ ++ \ ++ chan = dev_to_chan(dev); \ ++ return sprintf(buf, format_string, chan->field); \ ++} ++ ++chan_attr(name, "%s\n"); ++chan_attr(channo, "%d\n"); ++chan_attr(chanpos, "%d\n"); ++chan_attr(blocksize, "%d\n"); ++#ifdef OPTIMIZE_CHANMUTE ++chan_attr(chanmute, "%d\n"); ++#endif ++ ++static BUS_ATTR_READER(sigcap_show, dev, buf) ++{ ++ struct dahdi_chan *chan; ++ int len = 0; ++ int i; ++ uint sigtypes[] = { ++ DAHDI_SIG_FXSLS, ++ DAHDI_SIG_FXSGS, ++ DAHDI_SIG_FXSKS, ++ DAHDI_SIG_FXOLS, ++ DAHDI_SIG_FXOGS, ++ DAHDI_SIG_FXOKS, ++ DAHDI_SIG_EM, ++ DAHDI_SIG_CLEAR, ++ DAHDI_SIG_HDLCRAW, ++ DAHDI_SIG_HDLCFCS, ++ DAHDI_SIG_HDLCNET, ++ DAHDI_SIG_SLAVE, ++ DAHDI_SIG_SF, ++ DAHDI_SIG_CAS, ++ DAHDI_SIG_EM_E1, ++ DAHDI_SIG_DACS_RBS, ++ DAHDI_SIG_HARDHDLC, ++ DAHDI_SIG_MTP2, ++ }; ++ chan = dev_to_chan(dev); ++ ++ for (i = 0; i < ARRAY_SIZE(sigtypes); i++) { ++ uint x = chan->sigcap & sigtypes[i]; ++ if (x == sigtypes[i]) ++ len += sprintf(buf + len, "%s ", sigstr(x)); ++ } ++ while (len > 0 && isspace(buf[len - 1])) /* trim */ ++ len--; ++ len += sprintf(buf + len, "\n"); ++ return len; ++} ++ ++static BUS_ATTR_READER(sig_show, dev, buf) ++{ ++ struct dahdi_chan *chan; ++ ++ chan = dev_to_chan(dev); ++ return sprintf(buf, "%s\n", sigstr(chan->sig)); ++} ++ ++static BUS_ATTR_READER(in_use_show, dev, buf) ++{ ++ struct dahdi_chan *chan; ++ ++ chan = dev_to_chan(dev); ++ return sprintf(buf, "%d\n", test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)); ++} ++ ++static BUS_ATTR_READER(alarms_show, dev, buf) ++{ ++ struct dahdi_chan *chan; ++ int len; ++ ++ chan = dev_to_chan(dev); ++ len = fill_alarm_string(buf, PAGE_SIZE, chan->chan_alarms); ++ buf[len++] = '\n'; ++ return len; ++} ++ ++static BUS_ATTR_READER(ec_factory_show, dev, buf) ++{ ++ struct dahdi_chan *chan; ++ int len = 0; ++ ++ chan = dev_to_chan(dev); ++ if (chan->ec_factory) ++ len += sprintf(buf, "%s", chan->ec_factory->get_name(chan)); ++ buf[len++] = '\n'; ++ return len; ++} ++ ++static BUS_ATTR_READER(ec_state_show, dev, buf) ++{ ++ struct dahdi_chan *chan; ++ int len = 0; ++ ++ chan = dev_to_chan(dev); ++ if (chan->ec_factory) ++ len += sprintf(buf, "%sACTIVE", (chan->ec_state) ? "" : "IN"); ++ buf[len++] = '\n'; ++ return len; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++static struct device_attribute chan_dev_attrs[] = { ++ __ATTR_RO(name), ++ __ATTR_RO(channo), ++ __ATTR_RO(chanpos), ++ __ATTR_RO(sig), ++ __ATTR_RO(sigcap), ++ __ATTR_RO(alarms), ++ __ATTR_RO(ec_factory), ++ __ATTR_RO(ec_state), ++ __ATTR_RO(blocksize), ++#ifdef OPTIMIZE_CHANMUTE ++ __ATTR_RO(chanmute), ++#endif ++ __ATTR_RO(in_use), ++ __ATTR_NULL, ++}; ++#else ++static DEVICE_ATTR_RO(name); ++static DEVICE_ATTR_RO(channo); ++static DEVICE_ATTR_RO(chanpos); ++static DEVICE_ATTR_RO(sig); ++static DEVICE_ATTR_RO(sigcap); ++static DEVICE_ATTR_RO(alarms); ++static DEVICE_ATTR_RO(ec_factory); ++static DEVICE_ATTR_RO(ec_state); ++static DEVICE_ATTR_RO(blocksize); ++#ifdef OPTIMIZE_CHANMUTE ++static DEVICE_ATTR_RO(chanmute); ++#endif ++static DEVICE_ATTR_RO(in_use); ++ ++static struct attribute *chan_dev_attrs[] = { ++ &dev_attr_name.attr, ++ &dev_attr_channo.attr, ++ &dev_attr_chanpos.attr, ++ &dev_attr_sig.attr, ++ &dev_attr_sigcap.attr, ++ &dev_attr_alarms.attr, ++ &dev_attr_ec_factory.attr, ++ &dev_attr_ec_state.attr, ++ &dev_attr_blocksize.attr, ++#ifdef OPTIMIZE_CHANMUTE ++ &dev_attr_chanmute.attr, ++#endif ++ &dev_attr_in_use.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(chan_dev); ++#endif ++ ++static void chan_release(struct device *dev) ++{ ++ struct dahdi_chan *chan; ++ ++ BUG_ON(!dev); ++ chan = dev_to_chan(dev); ++ chan_dbg(DEVICES, chan, "SYSFS\n"); ++} ++ ++static int chan_match(struct device *dev, struct device_driver *driver) ++{ ++ struct dahdi_chan *chan; ++ ++ chan = dev_to_chan(dev); ++ chan_dbg(DEVICES, chan, "SYSFS\n"); ++ return 1; ++} ++ ++static struct bus_type chan_bus_type = { ++ .name = "dahdi_channels", ++ .match = chan_match, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++ .dev_attrs = chan_dev_attrs, ++#else ++ .dev_groups = chan_dev_groups, ++#endif ++}; ++ ++static int chan_probe(struct device *dev) ++{ ++ struct dahdi_chan *chan; ++ ++ chan = dev_to_chan(dev); ++ chan_dbg(DEVICES, chan, "SYSFS\n"); ++ return 0; ++} ++ ++static int chan_remove(struct device *dev) ++{ ++ struct dahdi_chan *chan; ++ ++ chan = dev_to_chan(dev); ++ chan_dbg(DEVICES, chan, "SYSFS\n"); ++ return 0; ++} ++ ++static struct device_driver chan_driver = { ++ .name = "dahdi", ++ .bus = &chan_bus_type, ++#ifndef OLD_HOTPLUG_SUPPORT ++ .owner = THIS_MODULE, ++#endif ++ .probe = chan_probe, ++ .remove = chan_remove ++}; ++ ++int chan_sysfs_create(struct dahdi_chan *chan) ++{ ++ struct device *dev; ++ struct dahdi_span *span; ++ int res; ++ dev_t devt; ++ ++ chan_dbg(DEVICES, chan, "Creating channel %d\n", chan->channo); ++ if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags)) ++ return 0; ++ span = chan->span; ++ devt = MKDEV(MAJOR(dahdi_channels_devt), chan->channo); ++ dev = &chan->chan_device; ++ memset(dev, 0, sizeof(*dev)); ++ dev->devt = devt; ++ dev->bus = &chan_bus_type; ++ dev->parent = span->span_device; ++ /* ++ * FIXME: the name cannot be longer than KOBJ_NAME_LEN ++ */ ++ dev_set_name(dev, "dahdi!chan!%03d!%03d", span->spanno, chan->chanpos); ++ dev_set_drvdata(dev, chan); ++ dev->release = chan_release; ++ res = device_register(dev); ++ if (res) { ++ chan_err(chan, "%s: device_register failed: %d\n", ++ __func__, res); ++ put_device(dev); ++ return res; ++ } ++ set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags); ++ return 0; ++} ++ ++void chan_sysfs_remove(struct dahdi_chan *chan) ++{ ++ struct device *dev = &chan->chan_device; ++ ++ chan_dbg(DEVICES, chan, "Destroying channel %d\n", chan->channo); ++ if (!dev_get_drvdata(dev)) ++ return; ++ if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags)) ++ return; ++ dev = &chan->chan_device; ++ BUG_ON(dev_get_drvdata(dev) != chan); ++ device_unregister(dev); ++ /* FIXME: should have been done earlier in dahdi_chan_unreg */ ++ chan->channo = -1; ++ clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags); ++} ++ ++/* ++ * Used by dahdi_transcode.c ++ */ ++int dahdi_register_chardev(struct dahdi_chardev *dev) ++{ ++ static const char *DAHDI_STRING = "dahdi!"; ++ char *udevname; ++ ++ udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1, ++ GFP_KERNEL); ++ if (!udevname) ++ return -ENOMEM; ++ ++ strcpy(udevname, DAHDI_STRING); ++ strcat(udevname, dev->name); ++ MAKE_DAHDI_DEV(dev->minor, udevname); ++ kfree(udevname); ++ return 0; ++} ++EXPORT_SYMBOL(dahdi_register_chardev); ++ ++/* ++ * Used by dahdi_transcode.c ++ */ ++int dahdi_unregister_chardev(struct dahdi_chardev *dev) ++{ ++ DEL_DAHDI_DEV(dev->minor); ++ return 0; ++} ++EXPORT_SYMBOL(dahdi_unregister_chardev); ++ ++/*--------- Sysfs Device handling ----*/ ++ ++/* ++ * Describe fixed device files and maintain their ++ * pointer so fixed_devfiles_remove() can always be called ++ * and work cleanly ++ */ ++static struct { ++ int minor; ++ char *name; ++ void *dev; /* FIXME: wrong type because of old kernels */ ++} fixed_minors[] = { ++ { DAHDI_CTL, "dahdi!ctl", }, ++ { DAHDI_TIMER, "dahdi!timer", }, ++ { DAHDI_CHANNEL, "dahdi!channel",}, ++ { DAHDI_PSEUDO, "dahdi!pseudo", }, ++}; ++ ++/* ++ * Removes /dev/dahdi/{ctl,timer,channel,pseudo} ++ * ++ * It is safe to call it during initialization error handling, ++ * as it skips non existing objects. ++ */ ++static void fixed_devfiles_remove(void) ++{ ++ int i; ++ ++ if (!dahdi_class) ++ return; ++ for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) { ++ void *d = fixed_minors[i].dev; ++ if (d && !IS_ERR(d)) ++ dahdi_dbg(DEVICES, "Removing fixed device file %s\n", ++ fixed_minors[i].name); ++ DEL_DAHDI_DEV(fixed_minors[i].minor); ++ } ++} ++ ++/* ++ * Creates /dev/dahdi/{ctl,timer,channel,pseudo} ++ */ ++static int fixed_devfiles_create(void) ++{ ++ int i; ++ int res = 0; ++ ++ if (!dahdi_class) { ++ dahdi_err("%s: dahdi_class is not initialized yet!\n", ++ __func__); ++ res = -ENODEV; ++ goto cleanup; ++ } ++ for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) { ++ char *name = fixed_minors[i].name; ++ int minor = fixed_minors[i].minor; ++ void *dummy; ++ ++ dahdi_dbg(DEVICES, "Making fixed device file %s\n", name); ++ dummy = (void *)MAKE_DAHDI_DEV(minor, name); ++ if (IS_ERR(dummy)) { ++ int res = PTR_ERR(dummy); ++ ++ dahdi_err("%s: failed (%d: %s). Error: %d\n", ++ __func__, minor, name, res); ++ goto cleanup; ++ } ++ fixed_minors[i].dev = dummy; ++ } ++ return 0; ++cleanup: ++ fixed_devfiles_remove(); ++ return res; ++} ++ ++/* ++ * Called during driver unload and while handling any error during ++ * driver load. ++ * Always clean any (and only) objects that were initialized (invariant) ++ */ ++static void sysfs_channels_cleanup(void) ++{ ++ if (should_cleanup.cdev) { ++ dahdi_dbg(DEVICES, "removing channels cdev\n"); ++ cdev_del(&dahdi_channels_cdev); ++ should_cleanup.cdev = 0; ++ } ++ if (dahdi_channels_devt) { ++ dahdi_dbg(DEVICES, "unregistering chrdev_region\n"); ++ unregister_chrdev_region(dahdi_channels_devt, ++ DAHDI_MAX_CHANNELS); ++ } ++ ++ fixed_devfiles_remove(); ++ if (dahdi_class) { ++ dahdi_dbg(DEVICES, "Destroying DAHDI class:\n"); ++ class_destroy(dahdi_class); ++ dahdi_class = NULL; ++ } ++ if (should_cleanup.channel_driver) { ++ dahdi_dbg(DEVICES, "Removing channel driver\n"); ++ driver_unregister(&chan_driver); ++ should_cleanup.channel_driver = 0; ++ } ++ if (should_cleanup.channels_bus) { ++ dahdi_dbg(DEVICES, "Removing channels bus\n"); ++ bus_unregister(&chan_bus_type); ++ should_cleanup.channels_bus = 0; ++ } ++} ++ ++int __init dahdi_sysfs_chan_init(const struct file_operations *fops) ++{ ++ int res = 0; ++ ++ dahdi_dbg(DEVICES, "Registering channels bus\n"); ++ res = bus_register(&chan_bus_type); ++ if (res) { ++ dahdi_err("%s: bus_register(%s) failed. Error number %d\n", ++ __func__, chan_bus_type.name, res); ++ goto cleanup; ++ } ++ should_cleanup.channels_bus = 1; ++ ++ dahdi_dbg(DEVICES, "Registering channel driver\n"); ++ res = driver_register(&chan_driver); ++ if (res) { ++ dahdi_err("%s: driver_register(%s) failed. Error number %d", ++ __func__, chan_driver.name, res); ++ goto cleanup; ++ } ++ should_cleanup.channel_driver = 1; ++ ++ dahdi_class = class_create(THIS_MODULE, "dahdi"); ++ if (IS_ERR(dahdi_class)) { ++ res = PTR_ERR(dahdi_class); ++ dahdi_err("%s: class_create(dahi_chan) failed. Error: %d\n", ++ __func__, res); ++ goto cleanup; ++ } ++ res = fixed_devfiles_create(); ++ if (res) ++ goto cleanup; ++ dahdi_dbg(DEVICES, "allocating chrdev_region\n"); ++ res = alloc_chrdev_region(&dahdi_channels_devt, ++ 0, ++ DAHDI_MAX_CHANNELS, ++ "dahdi_channels"); ++ if (res) { ++ dahdi_err("%s: Failed allocating chrdev for %d channels (%d)", ++ __func__, DAHDI_MAX_CHANNELS, res); ++ goto cleanup; ++ } ++ dahdi_dbg(DEVICES, "adding channels cdev\n"); ++ cdev_init(&dahdi_channels_cdev, fops); ++ res = cdev_add(&dahdi_channels_cdev, dahdi_channels_devt, ++ DAHDI_MAX_CHANNELS); ++ if (res) { ++ dahdi_err("%s: cdev_add() failed (%d)", __func__, res); ++ goto cleanup; ++ } ++ should_cleanup.cdev = 1; ++ return 0; ++cleanup: ++ sysfs_channels_cleanup(); ++ return res; ++} ++ ++void dahdi_sysfs_chan_exit(void) ++{ ++ sysfs_channels_cleanup(); ++} +diff -Nru linux-source-4.19/drivers/dahdi/dahdi-sysfs.c linux-source-4.19-dahdi/drivers/dahdi/dahdi-sysfs.c +--- linux-source-4.19/drivers/dahdi/dahdi-sysfs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi-sysfs.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,855 @@ ++/* dahdi-sysfs.c ++ * ++ * Copyright (C) 2011-2012, Xorcom ++ * Copyright (C) 2011-2012, 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 ++#define DAHDI_PRINK_MACROS_USE_debug ++#include ++#include ++#include ++#include ++ ++#include "dahdi.h" ++#include "dahdi-sysfs.h" ++ ++ ++static char *initdir; ++module_param(initdir, charp, 0444); ++MODULE_PARM_DESC(initdir, ++ "deprecated, should use /usr/share/dahdi"); ++ ++static char *tools_rootdir; ++module_param(tools_rootdir, charp, 0444); ++MODULE_PARM_DESC(tools_rootdir, ++ "root directory of all tools paths (default /)"); ++ ++static int span_match(struct device *dev, struct device_driver *driver) ++{ ++ return 1; ++} ++ ++static inline struct dahdi_span *dev_to_span(struct device *dev) ++{ ++ return dev_get_drvdata(dev); ++} ++ ++#define SPAN_VAR_BLOCK \ ++ do { \ ++ DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \ ++ DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \ ++ initdir); \ ++ DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \ ++ DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \ ++ } while (0) ++ ++#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \ ++ do { \ ++ int err = add_uevent_var(kenv, fmt, val); \ ++ if (err) \ ++ return err; \ ++ } while (0) ++ ++static int span_uevent(struct device *dev, struct kobj_uevent_env *kenv) ++{ ++ struct dahdi_span *span; ++ ++ if (!dev) ++ return -ENODEV; ++ span = dev_to_span(dev); ++ if (!span) ++ return -ENODEV; ++ dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n", ++ dev_name(dev), span->name); ++ SPAN_VAR_BLOCK; ++ return 0; ++} ++ ++#define span_attr(field, format_string) \ ++static BUS_ATTR_READER(field##_show, dev, buf) \ ++{ \ ++ struct dahdi_span *span; \ ++ \ ++ span = dev_to_span(dev); \ ++ return sprintf(buf, format_string, span->field); \ ++} ++ ++span_attr(name, "%s\n"); ++span_attr(desc, "%s\n"); ++span_attr(alarms, "0x%x\n"); ++span_attr(lbo, "%d\n"); ++span_attr(syncsrc, "%d\n"); ++ ++static BUS_ATTR_READER(spantype_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ return sprintf(buf, "%s\n", dahdi_spantype2str(span->spantype)); ++} ++ ++static BUS_ATTR_READER(local_spanno_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ return sprintf(buf, "%d\n", local_spanno(span)); ++} ++ ++static BUS_ATTR_READER(is_digital_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ return sprintf(buf, "%d\n", dahdi_is_digital_span(span)); ++} ++ ++static BUS_ATTR_READER(is_sync_master_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ return sprintf(buf, "%d\n", dahdi_is_sync_master(span)); ++} ++ ++static BUS_ATTR_READER(basechan_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ if (!span->channels) ++ return -ENODEV; ++ return sprintf(buf, "%d\n", span->chans[0]->channo); ++} ++ ++static BUS_ATTR_READER(channels_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ return sprintf(buf, "%d\n", span->channels); ++} ++ ++static BUS_ATTR_READER(lineconfig_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ int len = 0; ++ ++ span = dev_to_span(dev); ++ len += lineconfig_str(span->lineconfig, buf, 20); ++ len += sprintf(buf + len, "\n"); ++ return len; ++} ++ ++static BUS_ATTR_READER(linecompat_show, dev, buf) ++{ ++ struct dahdi_span *span; ++ int bit; ++ int len = 0; ++ ++ span = dev_to_span(dev); ++ for (bit = 4; bit <= 12; bit++) { ++ if (span->linecompat & (1 << bit)) { ++ const char *name = dahdi_lineconfig_bit_name(bit); ++ if (name) ++ len += sprintf(buf + len, "%s ", name); ++ } ++ } ++ /* chomp */ ++ while (len > 0 && isspace(buf[len - 1])) ++ buf[--len] = '\0'; ++ len += sprintf(buf + len, "\n"); ++ return len; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++static struct device_attribute span_dev_attrs[] = { ++ __ATTR_RO(name), ++ __ATTR_RO(desc), ++ __ATTR_RO(spantype), ++ __ATTR_RO(local_spanno), ++ __ATTR_RO(alarms), ++ __ATTR_RO(lbo), ++ __ATTR_RO(syncsrc), ++ __ATTR_RO(is_digital), ++ __ATTR_RO(is_sync_master), ++ __ATTR_RO(basechan), ++ __ATTR_RO(channels), ++ __ATTR_RO(lineconfig), ++ __ATTR_RO(linecompat), ++ __ATTR_NULL, ++}; ++#else ++static DEVICE_ATTR_RO(name); ++static DEVICE_ATTR_RO(desc); ++static DEVICE_ATTR_RO(spantype); ++static DEVICE_ATTR_RO(local_spanno); ++static DEVICE_ATTR_RO(alarms); ++static DEVICE_ATTR_RO(lbo); ++static DEVICE_ATTR_RO(syncsrc); ++static DEVICE_ATTR_RO(is_digital); ++static DEVICE_ATTR_RO(is_sync_master); ++static DEVICE_ATTR_RO(basechan); ++static DEVICE_ATTR_RO(channels); ++static DEVICE_ATTR_RO(lineconfig); ++static DEVICE_ATTR_RO(linecompat); ++ ++static struct attribute *span_dev_attrs[] = { ++ &dev_attr_name.attr, ++ &dev_attr_desc.attr, ++ &dev_attr_spantype.attr, ++ &dev_attr_local_spanno.attr, ++ &dev_attr_lbo.attr, ++ &dev_attr_alarms.attr, ++ &dev_attr_syncsrc.attr, ++ &dev_attr_is_digital.attr, ++ &dev_attr_is_sync_master.attr, ++ &dev_attr_basechan.attr, ++ &dev_attr_channels.attr, ++ &dev_attr_lineconfig.attr, ++ &dev_attr_linecompat.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(span_dev); ++#endif ++ ++static ssize_t master_span_show(struct device_driver *driver, char *buf) ++{ ++ struct dahdi_span *s = get_master_span(); ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", (s) ? s->spanno : 0); ++} ++ ++static ssize_t master_span_store(struct device_driver *driver, const char *buf, ++ size_t count) ++{ ++ int spanno; ++ ++ if (sscanf(buf, "%d", &spanno) != 1) { ++ module_printk(KERN_ERR, "non-numeric input '%s'\n", buf); ++ return -EINVAL; ++ } ++ set_master_span(spanno); ++ return count; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) ++static struct driver_attribute dahdi_attrs[] = { ++ __ATTR(master_span, S_IRUGO | S_IWUSR, master_span_show, ++ master_span_store), ++ __ATTR_NULL, ++}; ++#else ++static DRIVER_ATTR_RW(master_span); ++static struct attribute *dahdi_attrs[] = { ++ &driver_attr_master_span.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(dahdi); ++#endif ++ ++static struct bus_type spans_bus_type = { ++ .name = "dahdi_spans", ++ .match = span_match, ++ .uevent = span_uevent, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++ .dev_attrs = span_dev_attrs, ++#else ++ .dev_groups = span_dev_groups, ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) ++ .drv_attrs = dahdi_attrs, ++#else ++ .drv_groups = dahdi_groups, ++#endif ++}; ++ ++static int span_probe(struct device *dev) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ span_dbg(DEVICES, span, "\n"); ++ return 0; ++} ++ ++static int span_remove(struct device *dev) ++{ ++ struct dahdi_span *span; ++ ++ span = dev_to_span(dev); ++ span_dbg(DEVICES, span, "\n"); ++ return 0; ++} ++ ++static struct device_driver dahdi_driver = { ++ .name = "generic_lowlevel", ++ .bus = &spans_bus_type, ++ .probe = span_probe, ++ .remove = span_remove, ++ .owner = THIS_MODULE ++}; ++ ++static void span_uevent_send(struct dahdi_span *span, enum kobject_action act) ++{ ++ struct kobject *kobj; ++ ++ kobj = &span->span_device->kobj; ++ span_dbg(DEVICES, span, "SYFS dev_name=%s action=%d\n", ++ dev_name(span->span_device), act); ++ kobject_uevent(kobj, act); ++} ++ ++static void span_release(struct device *dev) ++{ ++ dahdi_dbg(DEVICES, "%s: %s\n", __func__, dev_name(dev)); ++} ++ ++void span_sysfs_remove(struct dahdi_span *span) ++{ ++ struct device *span_device; ++ int x; ++ ++ span_dbg(DEVICES, span, "\n"); ++ span_device = span->span_device; ++ ++ if (!span_device) ++ return; ++ ++ for (x = 0; x < span->channels; x++) ++ chan_sysfs_remove(span->chans[x]); ++ if (!dev_get_drvdata(span_device)) ++ return; ++ ++ /* Grab an extra reference to the device since we'll still want it ++ * after we've unregistered it */ ++ ++ get_device(span_device); ++ span_uevent_send(span, KOBJ_OFFLINE); ++ sysfs_remove_link(&span_device->kobj, "ddev"); ++ device_unregister(span->span_device); ++ dev_set_drvdata(span_device, NULL); ++ span_device->parent = NULL; ++ put_device(span_device); ++ memset(&span->span_device, 0, sizeof(span->span_device)); ++ kfree(span->span_device); ++ span->span_device = NULL; ++} ++ ++int span_sysfs_create(struct dahdi_span *span) ++{ ++ struct device *span_device; ++ int res = 0; ++ int x; ++ ++ if (span->span_device) { ++ WARN_ON(1); ++ return -EEXIST; ++ } ++ ++ span->span_device = kzalloc(sizeof(*span->span_device), GFP_KERNEL); ++ if (!span->span_device) ++ return -ENOMEM; ++ ++ span_device = span->span_device; ++ span_dbg(DEVICES, span, "\n"); ++ ++ span_device->bus = &spans_bus_type; ++ span_device->parent = &span->parent->dev; ++ dev_set_name(span_device, "span-%d", span->spanno); ++ dev_set_drvdata(span_device, span); ++ span_device->release = span_release; ++ res = device_register(span_device); ++ if (res) { ++ span_err(span, "%s: device_register failed: %d\n", __func__, ++ res); ++ kfree(span->span_device); ++ span->span_device = NULL; ++ goto cleanup; ++ } ++ res = sysfs_create_link(&span_device->kobj, &span_device->parent->kobj, ++ "ddev"); ++ if (res) { ++ span_err(span, "%s: sysfs_create_link failed: %d\n", __func__, ++ res); ++ kfree(span->span_device); ++ span->span_device = NULL; ++ goto cleanup; ++ } ++ ++ for (x = 0; x < span->channels; x++) { ++ res = chan_sysfs_create(span->chans[x]); ++ if (res) ++ goto cleanup; ++ } ++ return 0; ++ ++cleanup: ++ span_sysfs_remove(span); ++ return res; ++} ++ ++/* Only used to flag that the device exists: */ ++static struct { ++ unsigned int clean_dahdi_driver:1; ++ unsigned int clean_span_bus_type:1; ++ unsigned int clean_device_bus:1; ++ unsigned int clean_chardev:1; ++} should_cleanup; ++ ++static inline struct dahdi_device *to_ddev(struct device *dev) ++{ ++ return container_of(dev, struct dahdi_device, dev); ++} ++ ++#define DEVICE_VAR_BLOCK \ ++ do { \ ++ DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \ ++ DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \ ++ initdir); \ ++ DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_HWID=%s", \ ++ ddev->hardware_id); \ ++ DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_LOCATION=%s", \ ++ ddev->location); \ ++ } while (0) ++ ++#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \ ++ do { \ ++ int err = add_uevent_var(kenv, fmt, val); \ ++ if (err) \ ++ return err; \ ++ } while (0) ++ ++static int device_uevent(struct device *dev, struct kobj_uevent_env *kenv) ++{ ++ struct dahdi_device *ddev; ++ ++ if (!dev) ++ return -ENODEV; ++ ddev = to_ddev(dev); ++ if (!ddev) ++ return -ENODEV; ++ dahdi_dbg(GENERAL, "SYFS dev_name=%s\n", dev_name(dev)); ++ DEVICE_VAR_BLOCK; ++ return 0; ++} ++ ++static ssize_t ++manufacturer_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ return sprintf(buf, "%s\n", ddev->manufacturer); ++} ++ ++static ssize_t ++type_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ return sprintf(buf, "%s\n", ddev->devicetype); ++} ++ ++static ssize_t ++span_count_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ unsigned int count = 0; ++ struct list_head *pos; ++ ++ list_for_each(pos, &ddev->spans) ++ ++count; ++ ++ return sprintf(buf, "%d\n", count); ++} ++ ++static ssize_t ++hardware_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ ++ return sprintf(buf, "%s\n", ++ (ddev->hardware_id) ? ddev->hardware_id : ""); ++} ++ ++static ssize_t ++location_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ ++ return sprintf(buf, "%s\n", ++ (ddev->location) ? ddev->location : ""); ++} ++ ++static ssize_t ++auto_assign_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ dahdi_assign_device_spans(ddev); ++ return count; ++} ++ ++static ssize_t ++assign_span_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int ret; ++ struct dahdi_span *span; ++ unsigned int local_span_number; ++ unsigned int desired_spanno; ++ unsigned int desired_basechanno; ++ struct dahdi_device *const ddev = to_ddev(dev); ++ ++ ret = sscanf(buf, "%u:%u:%u", &local_span_number, &desired_spanno, ++ &desired_basechanno); ++ if (ret != 3) { ++ dev_notice(dev, "bad input (should be ::)\n"); ++ return -EINVAL; ++ } ++ ++ if (desired_spanno && !desired_basechanno) { ++ dev_notice(dev, "Must set span number AND base chan number\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(span, &ddev->spans, device_node) { ++ if (local_span_number == local_spanno(span)) { ++ ret = dahdi_assign_span(span, desired_spanno, ++ desired_basechanno, 1); ++ return (ret) ? ret : count; ++ } ++ } ++ dev_notice(dev, "no match for local span number %d\n", ++ local_span_number); ++ return -EINVAL; ++} ++ ++static ssize_t ++unassign_span_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned int local_span_number; ++ struct dahdi_span *span; ++ struct dahdi_device *const ddev = to_ddev(dev); ++ ++ ret = sscanf(buf, "%u", &local_span_number); ++ if (ret != 1) ++ return -EINVAL; ++ ++ ret = -ENODEV; ++ list_for_each_entry(span, &ddev->spans, device_node) { ++ if (local_span_number == local_spanno(span)) ++ ret = dahdi_unassign_span(span); ++ } ++ if (-ENODEV == ret) { ++ if (printk_ratelimit()) { ++ dev_info(dev, "'%d' is an invalid local span number.\n", ++ local_span_number); ++ } ++ return -EINVAL; ++ } ++ return (ret < 0) ? ret : count; ++} ++ ++static ssize_t ++dahdi_spantype_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ int count = 0; ++ ssize_t total = 0; ++ struct dahdi_span *span; ++ ++ /* TODO: Make sure this doesn't overflow the page. */ ++ list_for_each_entry(span, &ddev->spans, device_node) { ++ count = sprintf(buf, "%d:%s\n", ++ local_spanno(span), dahdi_spantype2str(span->spantype)); ++ buf += count; ++ total += count; ++ } ++ ++ return total; ++} ++ ++static ssize_t ++dahdi_spantype_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct dahdi_device *const ddev = to_ddev(dev); ++ int ret; ++ struct dahdi_span *span = NULL; ++ struct dahdi_span *cur; ++ unsigned int local_span_number; ++ char spantype_name[80]; ++ enum spantypes spantype; ++ ++ ret = sscanf(buf, "%u:%70s", &local_span_number, spantype_name); ++ if (ret != 2) { ++ dev_err(&ddev->dev, "Wrong input format: '%s'\n", buf); ++ return -EINVAL; ++ } ++ spantype = dahdi_str2spantype(spantype_name); ++ if (spantype == SPANTYPE_INVALID) { ++ dev_err(&ddev->dev, "Invalid spantype: '%s'\n", buf); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(cur, &ddev->spans, device_node) { ++ if (local_spanno(cur) == local_span_number) { ++ span = cur; ++ break; ++ } ++ } ++ ++ if (!span || (local_spanno(span) != local_span_number)) { ++ module_printk(KERN_WARNING, ++ "%d is not a valid local span number " ++ "for this device.\n", local_span_number); ++ return -EINVAL; ++ } ++ ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) { ++ module_printk(KERN_WARNING, "Span %s is already assigned.\n", ++ span->name); ++ return -EINVAL; ++ } ++ ++ ++ if (!span->ops->set_spantype) { ++ module_printk(KERN_WARNING, "Span %s does not support " ++ "setting type.\n", span->name); ++ return -EINVAL; ++ } ++ ++ ret = span->ops->set_spantype(span, spantype); ++ return (ret < 0) ? ret : count; ++} ++ ++static ssize_t ++dahdi_registration_time_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dahdi_device *ddev = to_ddev(dev); ++ int count = 0; ++ struct timespec64 ts = ktime_to_timespec64(ddev->registration_time); ++ ++ count += sprintf(buf, "%010lld.%09ld\n", ++ (s64)ts.tv_sec, ++ ts.tv_nsec); ++ return count; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++static struct device_attribute dahdi_device_attrs[] = { ++ __ATTR(manufacturer, S_IRUGO, manufacturer_show, NULL), ++ __ATTR(type, S_IRUGO, type_show, NULL), ++ __ATTR(span_count, S_IRUGO, span_count_show, NULL), ++ __ATTR(hardware_id, S_IRUGO, hardware_id_show, NULL), ++ __ATTR(location, S_IRUGO, location_show, NULL), ++ __ATTR(auto_assign, S_IWUSR, NULL, auto_assign_store), ++ __ATTR(assign_span, S_IWUSR, NULL, assign_span_store), ++ __ATTR(unassign_span, S_IWUSR, NULL, unassign_span_store), ++ __ATTR(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show, ++ dahdi_spantype_store), ++ __ATTR(registration_time, S_IRUGO, dahdi_registration_time_show, NULL), ++ __ATTR_NULL, ++}; ++#else ++static DEVICE_ATTR_RO(manufacturer); ++static DEVICE_ATTR_RO(type); ++static DEVICE_ATTR_RO(span_count); ++static DEVICE_ATTR_RO(hardware_id); ++static DEVICE_ATTR_RO(location); ++static DEVICE_ATTR_WO(auto_assign); ++static DEVICE_ATTR_WO(assign_span); ++static DEVICE_ATTR_WO(unassign_span); ++static DEVICE_ATTR_RW(dahdi_spantype); ++static DEVICE_ATTR_RO(dahdi_registration_time); ++static struct attribute *dahdi_device_attrs[] = { ++ &dev_attr_manufacturer.attr, ++ &dev_attr_type.attr, ++ &dev_attr_span_count.attr, ++ &dev_attr_hardware_id.attr, ++ &dev_attr_location.attr, ++ &dev_attr_auto_assign.attr, ++ &dev_attr_assign_span.attr, ++ &dev_attr_unassign_span.attr, ++ &dev_attr_dahdi_spantype.attr, ++ &dev_attr_dahdi_registration_time.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(dahdi_device); ++#endif ++ ++static struct bus_type dahdi_device_bus = { ++ .name = "dahdi_devices", ++ .uevent = device_uevent, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++ .dev_attrs = dahdi_device_attrs, ++#else ++ .dev_groups = dahdi_device_groups, ++#endif ++}; ++ ++static void dahdi_sysfs_cleanup(void) ++{ ++ dahdi_dbg(DEVICES, "SYSFS\n"); ++ if (should_cleanup.clean_dahdi_driver) { ++ dahdi_dbg(DEVICES, "Unregister driver\n"); ++ driver_unregister(&dahdi_driver); ++ should_cleanup.clean_dahdi_driver = 0; ++ } ++ if (should_cleanup.clean_span_bus_type) { ++ dahdi_dbg(DEVICES, "Unregister span bus type\n"); ++ bus_unregister(&spans_bus_type); ++ should_cleanup.clean_span_bus_type = 0; ++ } ++ dahdi_sysfs_chan_exit(); ++ if (should_cleanup.clean_chardev) { ++ dahdi_dbg(DEVICES, "Unregister character device\n"); ++ unregister_chrdev(DAHDI_MAJOR, "dahdi"); ++ should_cleanup.clean_chardev = 0; ++ } ++ ++ if (should_cleanup.clean_device_bus) { ++ dahdi_dbg(DEVICES, "Unregister DAHDI device bus\n"); ++ bus_unregister(&dahdi_device_bus); ++ should_cleanup.clean_device_bus = 0; ++ } ++} ++ ++static void dahdi_device_release(struct device *dev) ++{ ++ struct dahdi_device *ddev = container_of(dev, struct dahdi_device, dev); ++ kfree(ddev); ++} ++ ++/** ++ * dahdi_sysfs_add_device - Add the dahdi_device into the sysfs hierarchy. ++ * @ddev: The device to add. ++ * @parent: The physical device that is implementing this device. ++ * ++ * By adding the dahdi_device to the sysfs hierarchy user space can control ++ * how spans are numbered. ++ * ++ */ ++int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent) ++{ ++ int ret; ++ struct device *const dev = &ddev->dev; ++ const char *dn; ++ ++ dev->parent = parent; ++ dev->bus = &dahdi_device_bus; ++ dn = dev_name(dev); ++ if (!dn || !*dn) { ++ /* Invent default name based on parent */ ++ if (!parent) ++ return -EINVAL; ++ dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent)); ++ } ++ ret = device_add(dev); ++ return ret; ++} ++ ++void dahdi_sysfs_init_device(struct dahdi_device *ddev) ++{ ++ device_initialize(&ddev->dev); ++ ddev->dev.release = dahdi_device_release; ++} ++ ++void dahdi_sysfs_unregister_device(struct dahdi_device *ddev) ++{ ++ device_del(&ddev->dev); ++} ++ ++int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops) ++{ ++ int res = 0; ++ ++ dahdi_dbg(DEVICES, "Registering DAHDI device bus\n"); ++ ++ /* Handle dahdi-tools paths (for udev environment) */ ++ if (tools_rootdir && initdir) { ++ dahdi_err("Cannot use tools-rootdir and initdir parameters simultaneously\n"); ++ return -EINVAL; ++ } ++ if (initdir) ++ pr_notice("dahdi: initdir is depracated -- prefer using \"tools_rootdir\" parameter\n"); ++ else ++ initdir = "/usr/share/dahdi"; ++ if (!tools_rootdir) ++ tools_rootdir = ""; ++ ++ res = bus_register(&dahdi_device_bus); ++ if (res) ++ return res; ++ should_cleanup.clean_device_bus = 1; ++ ++ dahdi_dbg(DEVICES, ++ "Registering character device (major=%d)\n", DAHDI_MAJOR); ++ res = register_chrdev(DAHDI_MAJOR, "dahdi", dahdi_fops); ++ if (res) { ++ module_printk(KERN_ERR, ++ "Unable to register DAHDI character device " ++ "handler on %d\n", DAHDI_MAJOR); ++ return res; ++ } ++ should_cleanup.clean_chardev = 1; ++ ++ res = dahdi_sysfs_chan_init(dahdi_fops); ++ if (res) ++ goto cleanup; ++ ++ res = bus_register(&spans_bus_type); ++ if (res) { ++ dahdi_err("%s: bus_register(%s) failed. Error number %d", ++ __func__, spans_bus_type.name, res); ++ goto cleanup; ++ } ++ should_cleanup.clean_span_bus_type = 1; ++ ++ res = driver_register(&dahdi_driver); ++ if (res) { ++ dahdi_err("%s: driver_register(%s) failed. Error number %d", ++ __func__, dahdi_driver.name, res); ++ goto cleanup; ++ } ++ should_cleanup.clean_dahdi_driver = 1; ++ ++ module_printk(KERN_INFO, "Telephony Interface Registered on major %d\n", ++ DAHDI_MAJOR); ++ return 0; ++ ++cleanup: ++ dahdi_sysfs_cleanup(); ++ return res; ++} ++ ++void dahdi_sysfs_exit(void) ++{ ++ dahdi_sysfs_cleanup(); ++} +diff -Nru linux-source-4.19/drivers/dahdi/dahdi-sysfs.h linux-source-4.19-dahdi/drivers/dahdi/dahdi-sysfs.h +--- linux-source-4.19/drivers/dahdi/dahdi-sysfs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi-sysfs.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,32 @@ ++#ifndef DAHDI_SYSFS_H ++#define DAHDI_SYSFS_H ++ ++#define DEVICE_ATTR_READER(name, dev, buf) \ ++ ssize_t name(struct device *dev, \ ++ struct device_attribute *attr, \ ++ char *buf) ++#define DEVICE_ATTR_WRITER(name, dev, buf, count) \ ++ ssize_t name(struct device *dev, \ ++ struct device_attribute *attr, \ ++ const char *buf, size_t count) ++#define BUS_ATTR_READER(name, dev, buf) \ ++ ssize_t name(struct device *dev, \ ++ struct device_attribute *attr, \ ++ char *buf) ++#define BUS_ATTR_WRITER(name, dev, buf, count) \ ++ ssize_t name(struct device *dev, \ ++ struct device_attribute *attr, \ ++ const char *buf, size_t count) ++ ++#define DRIVER_ATTR_READER(name, drv, buf) \ ++ ssize_t name(struct device_driver *drv, char * buf) ++ ++/* Global */ ++int __init dahdi_sysfs_chan_init(const struct file_operations *fops); ++void dahdi_sysfs_chan_exit(void); ++ ++/* Channel Handling */ ++int chan_sysfs_create(struct dahdi_chan *chan); ++void chan_sysfs_remove(struct dahdi_chan *chan); ++ ++#endif /* DAHDI_SYSFS_H */ +diff -Nru linux-source-4.19/drivers/dahdi/dahdi-version.c linux-source-4.19-dahdi/drivers/dahdi/dahdi-version.c +--- linux-source-4.19/drivers/dahdi/dahdi-version.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi-version.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,33 @@ ++/* ++ * Dahdi Version ++ * ++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony. ++ * Copyright (C) 2011 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 "dahdi.h" ++ ++const char *const dahdi_version = DAHDI_VERSION; ++ ++MODULE_VERSION(DAHDI_VERSION); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi.h linux-source-4.19-dahdi/drivers/dahdi/dahdi.h +--- linux-source-4.19/drivers/dahdi/dahdi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,62 @@ ++#ifndef _DAHDI_H ++#define _DAHDI_H ++ ++/* dahdi.h: headers intended only for the dahdi.ko module. ++ * Not to be included elsewhere ++ * ++ * Written by Tzafrir Cohen ++ * Copyright (C) 2011, Xorcom ++ * Copyright (C) 2011, 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. ++ */ ++ ++extern int debug; ++extern const char *const dahdi_version; ++ ++int dahdi_register_chardev(struct dahdi_chardev *dev); ++int dahdi_unregister_chardev(struct dahdi_chardev *dev); ++int span_sysfs_create(struct dahdi_span *span); ++void span_sysfs_remove(struct dahdi_span *span); ++int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops); ++void dahdi_sysfs_exit(void); ++ ++void dahdi_sysfs_init_device(struct dahdi_device *ddev); ++int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent); ++void dahdi_sysfs_unregister_device(struct dahdi_device *ddev); ++ ++int dahdi_assign_span(struct dahdi_span *span, unsigned int spanno, ++ unsigned int basechan, int prefmaster); ++int dahdi_unassign_span(struct dahdi_span *span); ++int dahdi_assign_device_spans(struct dahdi_device *ddev); ++ ++static inline int get_span(struct dahdi_span *span) ++{ ++ return try_module_get(span->ops->owner); ++} ++ ++static inline void put_span(struct dahdi_span *span) ++{ ++ module_put(span->ops->owner); ++} ++ ++static inline int local_spanno(struct dahdi_span *span) ++{ ++ return span->offset + 1; ++} ++ ++#endif /* _DAHDI_H */ +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_dummy.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_dummy.c +--- linux-source-4.19/drivers/dahdi/dahdi_dummy.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_dummy.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,274 @@ ++/* ++ * Dummy DAHDI Driver for DAHDI Telephony interface ++ * ++ * Required: kernel > 2.6.0 ++ * ++ * Written by Robert Pleh ++ * 2.6 version by Tony Hoyle ++ * Unified by Mark Spencer ++ * ++ * Converted to use HighResTimers on i386 by Jeffery Palmer ++ * ++ * Copyright (C) 2002, Hermes Softlab ++ * Copyright (C) 2004-2012, 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. ++ */ ++ ++/* ++ * To use the high resolution timers, in your kernel CONFIG_HIGH_RES_TIMERS ++ * needs to be enabled (Processor type and features -> High Resolution ++ * Timer Support), and optionally HPET (Processor type and features -> ++ * HPET Timer Support) provides a better clock source. ++ */ ++ ++#include ++ ++#if defined(CONFIG_HIGH_RES_TIMERS) ++#define USE_HIGHRESTIMER ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#if !defined(USE_HIGHRESTIMER) ++#include ++#endif ++ ++#include ++ ++#ifndef HAVE_HRTIMER_ACCESSORS ++#if defined(USE_HIGHRESTIMER) && \ ++ (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)) ++/* Compatibility with new hrtimer interface */ ++static inline ktime_t hrtimer_get_expires(const struct hrtimer *timer) ++{ ++ return timer->expires; ++} ++ ++static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time) ++{ ++ timer->expires = time; ++} ++#endif ++#endif ++ ++struct dahdi_dummy { ++ struct dahdi_device *ddev; ++ struct dahdi_span span; ++ struct dahdi_chan _chan; ++ struct dahdi_chan *chan; ++#if !defined(USE_HIGHRESTIMER) ++ unsigned long calls_since_start; ++ ktime_t start_interval; ++#endif ++}; ++ ++static struct dahdi_dummy *ztd; ++ ++static int debug = 0; ++ ++#ifdef USE_HIGHRESTIMER ++#define CLOCK_SRC "HRtimer" ++static struct hrtimer zaptimer; ++#define DAHDI_RATE 1000 /* DAHDI ticks per second */ ++#define DAHDI_TIME (1000000 / DAHDI_RATE) /* DAHDI tick time in us */ ++#define DAHDI_TIME_NS (DAHDI_TIME * 1000) /* DAHDI tick time in ns */ ++#else ++#define CLOCK_SRC "Linux26" ++static struct timer_list timer; ++static atomic_t shutdown; ++#define JIFFIES_INTERVAL max(HZ/250, 1) /* 4ms is fine for dahdi_dummy */ ++#endif ++ ++/* Different bits of the debug variable: */ ++#define DEBUG_GENERAL (1 << 0) ++#define DEBUG_TICKS (1 << 1) ++ ++#if defined(USE_HIGHRESTIMER) ++static enum hrtimer_restart dahdi_dummy_hr_int(struct hrtimer *htmr) ++{ ++ unsigned long overrun; ++ ++ /* Trigger DAHDI */ ++ dahdi_receive(&ztd->span); ++ dahdi_transmit(&ztd->span); ++ ++ /* Overrun should always return 1, since we are in the timer that ++ * expired. ++ * We should worry if overrun is 2 or more; then we really missed ++ * a tick */ ++ overrun = hrtimer_forward(&zaptimer, hrtimer_get_expires(htmr), ++ ktime_set(0, DAHDI_TIME_NS)); ++ if(overrun > 1) { ++ if(printk_ratelimit()) ++ printk(KERN_NOTICE "dahdi_dummy: HRTimer missed %lu ticks\n", ++ overrun - 1); ++ } ++ ++ if(debug && DEBUG_TICKS) { ++ static int count = 0; ++ /* Printk every 5 seconds, good test to see if timer is ++ * running properly */ ++ if (count++ % 5000 == 0) ++ printk(KERN_DEBUG "dahdi_dummy: 5000 ticks from hrtimer\n"); ++ } ++ ++ /* Always restart the timer */ ++ return HRTIMER_RESTART; ++} ++#else ++ ++static void dahdi_dummy_timer(TIMER_DATA_TYPE unused) ++{ ++ long ms_since_start; ++ ktime_t now; ++ const long MAX_INTERVAL = 100000L; ++ const long MS_LIMIT = 3000; ++ ++ if (!atomic_read(&shutdown)) ++ mod_timer(&timer, jiffies + JIFFIES_INTERVAL); ++ ++ now = ktime_get(); ++ ms_since_start = ktime_ms_delta(now, ztd->start_interval); ++ ++ /* ++ * If the system time has changed, it is possible for us to be far ++ * behind. If we are more than MS_LIMIT milliseconds behind, just ++ * reset our time base and continue so that we do not hang the system ++ * here. ++ * ++ */ ++ if (unlikely((ms_since_start - ztd->calls_since_start) > MS_LIMIT)) { ++ if (printk_ratelimit()) { ++ printk(KERN_INFO ++ "dahdi_dummy: Detected time shift.\n"); ++ } ++ ztd->calls_since_start = 0; ++ ztd->start_interval = now; ++ return; ++ } ++ ++ while (ms_since_start > ztd->calls_since_start) { ++ ztd->calls_since_start++; ++ dahdi_receive(&ztd->span); ++ dahdi_transmit(&ztd->span); ++ } ++ ++ if (ms_since_start > MAX_INTERVAL) { ++ ztd->calls_since_start = 0; ++ ztd->start_interval = now; ++ } ++} ++#endif ++ ++static const struct dahdi_span_ops dummy_ops = { ++ .owner = THIS_MODULE, ++}; ++ ++static int dahdi_dummy_initialize(struct dahdi_dummy *ztd) ++{ ++ int res = 0; ++ /* DAHDI stuff */ ++ ztd->ddev = dahdi_create_device(); ++ if (!ztd->ddev) ++ return -ENOMEM; ++ dev_set_name(&ztd->ddev->dev, "dahdi_dummy"); ++ ztd->chan = &ztd->_chan; ++ sprintf(ztd->span.name, "DAHDI_DUMMY/1"); ++ snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1); ++ sprintf(ztd->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0); ++ ztd->ddev->devicetype = "DAHDI Dummy Timing"; ++ ztd->chan->chanpos = 1; ++ ztd->span.chans = &ztd->chan; ++ ztd->span.channels = 0; /* no channels on our span */ ++ ztd->span.deflaw = DAHDI_LAW_MULAW; ++ ztd->chan->pvt = ztd; ++ ztd->span.ops = &dummy_ops; ++ list_add_tail(&ztd->span.device_node, &ztd->ddev->spans); ++ res = dahdi_register_device(ztd->ddev, NULL); ++ return res; ++} ++ ++int init_module(void) ++{ ++ int res; ++ ztd = kzalloc(sizeof(*ztd), GFP_KERNEL); ++ if (ztd == NULL) { ++ printk(KERN_ERR "dahdi_dummy: Unable to allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ res = dahdi_dummy_initialize(ztd); ++ if (res) { ++ printk(KERN_ERR ++ "dahdi_dummy: Unable to intialize DAHDI driver (%d)\n", ++ res); ++ kfree(ztd); ++ return res; ++ } ++ ++#if defined(USE_HIGHRESTIMER) ++ printk(KERN_DEBUG "dahdi_dummy: Trying to load High Resolution Timer\n"); ++ hrtimer_init(&zaptimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ printk(KERN_DEBUG "dahdi_dummy: Initialized High Resolution Timer\n"); ++ ++ /* Set timer callback function */ ++ zaptimer.function = dahdi_dummy_hr_int; ++ ++ printk(KERN_DEBUG "dahdi_dummy: Starting High Resolution Timer\n"); ++ hrtimer_start(&zaptimer, ktime_set(0, DAHDI_TIME_NS), HRTIMER_MODE_REL); ++ printk(KERN_INFO "dahdi_dummy: High Resolution Timer started, good to go\n"); ++#else ++ timer_setup(&timer, dahdi_dummy_timer, 0); ++ ztd->start_interval = ktime_get(); ++ atomic_set(&shutdown, 0); ++ mod_timer(&timer, jiffies + JIFFIES_INTERVAL); ++#endif ++ ++ if (debug) ++ printk(KERN_DEBUG "dahdi_dummy: init() finished\n"); ++ return 0; ++} ++ ++ ++void cleanup_module(void) ++{ ++#if defined(USE_HIGHRESTIMER) ++ /* Stop high resolution timer */ ++ hrtimer_cancel(&zaptimer); ++#else ++ atomic_set(&shutdown, 1); ++ del_timer_sync(&timer); ++#endif ++ dahdi_unregister_device(ztd->ddev); ++ dahdi_free_device(ztd->ddev); ++ kfree(ztd); ++ if (debug) ++ printk(KERN_DEBUG "dahdi_dummy: cleanup() finished\n"); ++} ++ ++module_param(debug, int, 0600); ++ ++MODULE_DESCRIPTION("Timing-Only Driver"); ++MODULE_AUTHOR("Robert Pleh "); ++MODULE_LICENSE("GPL v2"); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_dynamic.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic.c +--- linux-source-4.19/drivers/dahdi/dahdi_dynamic.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,911 @@ ++/* ++ * Dynamic Span Interface for DAHDI ++ * ++ * Written by Mark Spencer ++ * ++ * Copyright (C) 2001-2012, 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifndef DAHDI_SYNC_TICK ++#error "Dynamic support depends on DAHDI_SYNC_TICK being enabled." ++#endif ++ ++/* ++ * Tasklets provide better system interactive response at the cost of the ++ * possibility of losing a frame of data at very infrequent intervals. If ++ * you are more concerned with the performance of your machine, enable the ++ * tasklets. If you are strict about absolutely no drops, then do not enable ++ * tasklets. ++ */ ++ ++#undef ENABLE_TASKLETS ++ ++/* ++ * Dynamic spans implemented using TDM over X with standard message ++ * types. Message format is as follows: ++ * ++ * Byte #: Meaning ++ * 0 Number of samples per channel ++ * 1 Current flags on span ++ * Bit 0: Yellow Alarm ++ * Bit 1: Sig bits present ++ * Bits 2-7: reserved for future use ++ * 2-3 16-bit counter value for detecting drops, network byte order. ++ * 4-5 Number of channels in the message, network byte order ++ * 6... 16-bit words, containing sig bits for each ++ * four channels, least significant 4 bits being ++ * the least significant channel, network byte order. ++ * the rest data for each channel, all samples per channel ++ before moving to the next. ++ */ ++ ++#define DAHDI_DYNAMIC_FLAG_YELLOW_ALARM (1 << 0) ++#define DAHDI_DYNAMIC_FLAG_SIGBITS_PRESENT (1 << 1) ++#define DAHDI_DYNAMIC_FLAG_LOOPBACK (1 << 2) ++ ++#define ERR_NSAMP (1 << 16) ++#define ERR_NCHAN (1 << 17) ++#define ERR_LEN (1 << 18) ++ ++static int dahdi_dynamic_init(void); ++static void dahdi_dynamic_cleanup(void); ++ ++#ifdef ENABLE_TASKLETS ++static int taskletrun; ++static int taskletsched; ++static int taskletpending; ++static int taskletexec; ++static int txerrors; ++static struct tasklet_struct dahdi_dynamic_tlet; ++ ++static void dahdi_dynamic_tasklet(unsigned long data); ++#else ++static struct tasklet_struct dahdi_dynamic_flush_tlet; ++#endif ++ ++static DEFINE_MUTEX(dspan_mutex); ++static DEFINE_SPINLOCK(dspan_lock); ++static DEFINE_SPINLOCK(driver_lock); ++ ++static LIST_HEAD(dspan_list); ++static LIST_HEAD(driver_list); ++ ++static int debug = 0; ++ ++static int hasmaster = 0; ++ ++static void checkmaster(void) ++{ ++ int newhasmaster=0; ++ int best = 9999999; ++ struct dahdi_dynamic *d, *master = NULL; ++ ++ rcu_read_lock(); ++ ++ list_for_each_entry_rcu(d, &dspan_list, list) { ++ if (d->timing) { ++ d->master = 0; ++ if (!(d->span.alarms & DAHDI_ALARM_RED) && ++ (d->timing < best)) { ++ /* If not in alarm and they're ++ a better timing source, use them */ ++ master = d; ++ best = d->timing; ++ newhasmaster = 1; ++ } ++ } ++ } ++ ++ hasmaster = newhasmaster; ++ /* Mark the new master if there is one */ ++ if (master) ++ master->master = 1; ++ ++ rcu_read_unlock(); ++ ++ if (master) ++ printk(KERN_INFO "TDMoX: New master: %s\n", master->span.name); ++ else ++ printk(KERN_INFO "TDMoX: No master.\n"); ++} ++ ++static void dahdi_dynamic_sendmessage(struct dahdi_dynamic *d) ++{ ++ unsigned char *buf = d->msgbuf; ++ unsigned short bits; ++ int msglen = 0; ++ int x; ++ int offset; ++ ++ /* Byte 0: Number of samples per channel */ ++ *buf = DAHDI_CHUNKSIZE; ++ buf++; msglen++; ++ ++ /* Byte 1: Flags */ ++ *buf = 0; ++ if (d->span.alarms & DAHDI_ALARM_RED) ++ *buf |= DAHDI_DYNAMIC_FLAG_YELLOW_ALARM; ++ *buf |= DAHDI_DYNAMIC_FLAG_SIGBITS_PRESENT; ++ buf++; msglen++; ++ ++ /* Bytes 2-3: Transmit counter */ ++ *((unsigned short *)buf) = htons((unsigned short)d->txcnt); ++ d->txcnt++; ++ buf++; msglen++; ++ buf++; msglen++; ++ ++ /* Bytes 4-5: Number of channels */ ++ *((unsigned short *)buf) = htons((unsigned short)d->span.channels); ++ buf++; msglen++; ++ buf++; msglen++; ++ bits = 0; ++ offset = 0; ++ for (x = 0; x < d->span.channels; x++) { ++ offset = x % 4; ++ bits |= (d->chans[x]->txsig & 0xf) << (offset << 2); ++ if (offset == 3) { ++ /* Write the bits when we have four channels */ ++ *((unsigned short *)buf) = htons(bits); ++ buf++; msglen++; ++ buf++; msglen++; ++ bits = 0; ++ } ++ } ++ ++ if (offset != 3) { ++ /* Finish it off if it's not done already */ ++ *((unsigned short *)buf) = htons(bits); ++ buf++; msglen++; ++ buf++; msglen++; ++ } ++ ++ for (x = 0; x < d->span.channels; x++) { ++ memcpy(buf, d->chans[x]->writechunk, DAHDI_CHUNKSIZE); ++ buf += DAHDI_CHUNKSIZE; ++ msglen += DAHDI_CHUNKSIZE; ++ } ++ ++ d->driver->transmit(d, d->msgbuf, msglen); ++ ++} ++ ++static void __dahdi_dynamic_run(void) ++{ ++ struct dahdi_dynamic *d; ++#ifdef ENABLE_TASKLETS ++ struct dahdi_dynamic_driver *drv; ++#endif ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(d, &dspan_list, list) { ++ dahdi_transmit(&d->span); ++ /* Handle all transmissions now */ ++ dahdi_dynamic_sendmessage(d); ++ } ++ ++#ifdef ENABLE_TASKLETS ++ list_for_each_entry_rcu(drv, &driver_list, list) { ++ /* Flush any traffic still pending in the driver */ ++ if (drv->flush) { ++ drv->flush(); ++ } ++ } ++#else ++ /* If tasklets are not enabled, the above section will be called in ++ * interrupt context and the flushing of each driver will be called in a ++ * separate tasklet that only handles that. This is necessary since some ++ * of the dynamic spans need to call functions that require interrupts ++ * to be enabled but dahdi_transmit / ...sendmessage needs to be called ++ * each time the masterspan is processed which happens with interrupts ++ * disabled. ++ * ++ */ ++ tasklet_hi_schedule(&dahdi_dynamic_flush_tlet); ++#endif ++ rcu_read_unlock(); ++} ++ ++#ifdef ENABLE_TASKLETS ++static void dahdi_dynamic_run(void) ++{ ++ if (likely(!taskletpending)) { ++ taskletpending = 1; ++ taskletsched++; ++ tasklet_hi_schedule(&dahdi_dynamic_tlet); ++ } else { ++ txerrors++; ++ } ++} ++#else ++#define dahdi_dynamic_run __dahdi_dynamic_run ++#endif ++ ++static inline struct dahdi_dynamic *dynamic_from_span(struct dahdi_span *span) ++{ ++ return container_of(span, struct dahdi_dynamic, span); ++} ++ ++void dahdi_dynamic_receive(struct dahdi_span *span, unsigned char *msg, int msglen) ++{ ++ struct dahdi_dynamic *dtd = dynamic_from_span(span); ++ int newerr=0; ++ int sflags; ++ int xlen; ++ int x, bits, sig; ++ int nchans, master; ++ int newalarm; ++ unsigned short rxpos, rxcnt; ++ ++ rcu_read_lock(); ++ ++ if (unlikely(msglen < 6)) { ++ rcu_read_unlock(); ++ newerr = ERR_LEN; ++ if (newerr != dtd->err) ++ printk(KERN_NOTICE "Span %s: Insufficient samples for header (only %d)\n", span->name, msglen); ++ dtd->err = newerr; ++ return; ++ } ++ ++ /* First, check the chunksize */ ++ if (unlikely(*msg != DAHDI_CHUNKSIZE)) { ++ rcu_read_unlock(); ++ newerr = ERR_NSAMP | msg[0]; ++ if (newerr != dtd->err) ++ printk(KERN_NOTICE "Span %s: Expected %d samples, but receiving %d\n", span->name, DAHDI_CHUNKSIZE, msg[0]); ++ dtd->err = newerr; ++ return; ++ } ++ msg++; ++ sflags = *msg; ++ msg++; ++ ++ rxpos = ntohs(*((unsigned short *)msg)); ++ msg++; ++ msg++; ++ ++ nchans = ntohs(*((unsigned short *)msg)); ++ if (unlikely(nchans != span->channels)) { ++ rcu_read_unlock(); ++ newerr = ERR_NCHAN | nchans; ++ if (newerr != dtd->err) ++ printk(KERN_NOTICE "Span %s: Expected %d channels, but receiving %d\n", span->name, span->channels, nchans); ++ dtd->err = newerr; ++ return; ++ } ++ msg++; ++ msg++; ++ ++ /* Okay now we've accepted the header, lets check our message ++ length... */ ++ ++ /* Start with header */ ++ xlen = 6; ++ /* Add samples of audio */ ++ xlen += nchans * DAHDI_CHUNKSIZE; ++ /* If RBS info is there, add that */ ++ if (sflags & DAHDI_DYNAMIC_FLAG_SIGBITS_PRESENT) { ++ /* Account for sigbits -- one short per 4 channels*/ ++ xlen += ((nchans + 3) / 4) * 2; ++ } ++ ++ if (unlikely(xlen != msglen)) { ++ rcu_read_unlock(); ++ newerr = ERR_LEN | xlen; ++ if (newerr != dtd->err) ++ printk(KERN_NOTICE "Span %s: Expected message size %d, but was %d instead\n", span->name, xlen, msglen); ++ dtd->err = newerr; ++ return; ++ } ++ ++ bits = 0; ++ ++ /* Record sigbits if present */ ++ if (sflags & DAHDI_DYNAMIC_FLAG_SIGBITS_PRESENT) { ++ for (x=0;x> ((x % 4) << 2)) & 0xff; ++ ++ /* Update signalling if appropriate */ ++ if (sig != span->chans[x]->rxsig) ++ dahdi_rbsbits(span->chans[x], sig); ++ ++ } ++ } ++ ++ /* Record data for channels */ ++ for (x=0;xchans[x]->readchunk, msg, DAHDI_CHUNKSIZE); ++ msg += DAHDI_CHUNKSIZE; ++ } ++ ++ master = dtd->master; ++ ++ rxcnt = dtd->rxcnt; ++ dtd->rxcnt = rxpos+1; ++ ++ /* Keep track of last received packet */ ++ dtd->rxjif = jiffies; ++ ++ rcu_read_unlock(); ++ ++ /* Check for Yellow alarm */ ++ newalarm = span->alarms & ~(DAHDI_ALARM_YELLOW | DAHDI_ALARM_RED); ++ if (sflags & DAHDI_DYNAMIC_FLAG_YELLOW_ALARM) ++ newalarm |= DAHDI_ALARM_YELLOW; ++ ++ if (newalarm != span->alarms) { ++ span->alarms = newalarm; ++ dahdi_alarm_notify(span); ++ checkmaster(); ++ } ++ ++ /* note if we had a missing packet */ ++ if (unlikely(rxpos != rxcnt)) ++ printk(KERN_NOTICE "Span %s: Expected seq no %d, but received %d instead\n", span->name, rxcnt, rxpos); ++ ++ dahdi_ec_span(span); ++ dahdi_receive(span); ++ ++ /* If this is our master span, then run everything */ ++ if (master) ++ dahdi_dynamic_run(); ++} ++EXPORT_SYMBOL(dahdi_dynamic_receive); ++ ++/** ++ * dahdi_dynamic_release() - Free the memory associated with the dahdi_dynamic. ++ * @kref: Pointer to kref embedded in dahdi_dynamic structure. ++ * ++ */ ++static void dahdi_dynamic_release(struct kref *kref) ++{ ++ struct dahdi_dynamic *d = container_of(kref, struct dahdi_dynamic, ++ kref); ++ unsigned int x; ++ ++ WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags)); ++ ++ kfree(d->msgbuf); ++ ++ for (x = 0; x < d->span.channels; x++) ++ kfree(d->chans[x]); ++ ++ dahdi_free_device(d->ddev); ++ kfree(d); ++} ++ ++static inline int dynamic_put(struct dahdi_dynamic *d) ++{ ++ return kref_put(&d->kref, dahdi_dynamic_release); ++} ++ ++static inline void dynamic_get(struct dahdi_dynamic *d) ++{ ++ kref_get(&d->kref); ++} ++ ++static struct dahdi_dynamic *find_dynamic(struct dahdi_dynamic_span *dds) ++{ ++ struct dahdi_dynamic *d = NULL, *found = NULL; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(d, &dspan_list, list) { ++ if (!strcmp(d->dname, dds->driver) && ++ !strcmp(d->addr, dds->addr)) { ++ dynamic_get(d); ++ found = d; ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ ++ return found; ++} ++ ++static struct dahdi_dynamic_driver *find_driver(const char *name) ++{ ++ struct dahdi_dynamic_driver *dtd, *found = NULL; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(dtd, &driver_list, list) { ++ /* here's our driver */ ++ if (!strcmp(name, dtd->name)) { ++ found = dtd; ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ ++ return found; ++} ++ ++static int _destroy_dynamic(struct dahdi_dynamic_span *dds) ++{ ++ unsigned long flags; ++ struct dahdi_dynamic *d; ++ ++ d = find_dynamic(dds); ++ if (unlikely(!d)) ++ return -EINVAL; ++ ++ /* We shouldn't have more than the two references at this point. If ++ * we do, there are probably channels that are still opened. */ ++ if (refcount_read(&d->kref.refcount) > 2) { ++ dynamic_put(d); ++ return -EBUSY; ++ } ++ ++ if (d->pvt) { ++ if (d->driver && d->driver->destroy) { ++ if (!try_module_get(d->driver->owner)) { ++ /* The driver for this device is in the ++ * process of unloading. Leave this dynamic on ++ * the list so it's cleaned up when the driver ++ * unregisters. */ ++ dynamic_put(d); ++ return -ENXIO; ++ } ++ d->driver->destroy(d); ++ module_put(d->driver->owner); ++ } else { ++ WARN_ON(1); ++ } ++ d->pvt = NULL; ++ } ++ ++ dahdi_unregister_device(d->ddev); ++ ++ spin_lock_irqsave(&dspan_lock, flags); ++ list_del_rcu(&d->list); ++ spin_unlock_irqrestore(&dspan_lock, flags); ++ synchronize_rcu(); ++ ++ /* One since we've removed the item from the list... */ ++ dynamic_put(d); ++ /* ...and one for find_dynamic. */ ++ dynamic_put(d); ++ return 0; ++} ++ ++static int destroy_dynamic(struct dahdi_dynamic_span *dds) ++{ ++ int ret; ++ mutex_lock(&dspan_mutex); ++ ret = _destroy_dynamic(dds); ++ mutex_unlock(&dspan_mutex); ++ return ret; ++} ++ ++static int dahdi_dynamic_rbsbits(struct dahdi_chan *chan, int bits) ++{ ++ /* Don't have to do anything */ ++ return 0; ++} ++ ++static int dahdi_dynamic_open(struct dahdi_chan *chan) ++{ ++ struct dahdi_dynamic *d = dynamic_from_span(chan->span); ++ if (!try_module_get(d->driver->owner)) ++ return -ENODEV; ++ dynamic_get(d); ++ return 0; ++} ++ ++static int dahdi_dynamic_chanconfig(struct file *file, ++ struct dahdi_chan *chan, int sigtype) ++{ ++ return 0; ++} ++ ++static int dahdi_dynamic_close(struct dahdi_chan *chan) ++{ ++ struct dahdi_dynamic *d = dynamic_from_span(chan->span); ++ struct module *owner = d->driver->owner; ++ dynamic_put(d); ++ module_put(owner); ++ return 0; ++} ++ ++static void dahdi_dynamic_sync_tick(struct dahdi_span *span, int is_master) ++{ ++ struct dahdi_dynamic *head; ++ struct dahdi_dynamic *d = dynamic_from_span(span); ++ ++ if (hasmaster) ++ return; ++ ++ rcu_read_lock(); ++ head = list_entry(dspan_list.next, struct dahdi_dynamic, list); ++ rcu_read_unlock(); ++ ++ if (d == head) ++ dahdi_dynamic_run(); ++ return; ++} ++ ++static const struct dahdi_span_ops dynamic_ops = { ++ .owner = THIS_MODULE, ++ .rbsbits = dahdi_dynamic_rbsbits, ++ .open = dahdi_dynamic_open, ++ .close = dahdi_dynamic_close, ++ .chanconfig = dahdi_dynamic_chanconfig, ++ .sync_tick = dahdi_dynamic_sync_tick, ++}; ++ ++static int _create_dynamic(struct dahdi_dynamic_span *dds) ++{ ++ int res = 0; ++ struct dahdi_dynamic *d; ++ struct dahdi_dynamic_driver *dtd; ++ unsigned long flags; ++ int x; ++ int bufsize; ++ ++ if (dds->numchans < 1) { ++ printk(KERN_NOTICE "Can't be less than 1 channel (%d)!\n", ++ dds->numchans); ++ return -EINVAL; ++ } ++ if (dds->numchans >= ARRAY_SIZE(d->chans)) { ++ printk(KERN_NOTICE "Can't create dynamic span with greater " ++ "than %d channels. See dahdi_dynamic.c and increase " ++ "DAHDI_DYNAMIC_MAX_CHANS\n", dds->numchans); ++ return -EINVAL; ++ } ++ ++ d = find_dynamic(dds); ++ if (d) { ++ dynamic_put(d); ++ return -EEXIST; ++ } ++ ++ d = kzalloc(sizeof(*d), GFP_KERNEL); ++ if (!d) ++ return -ENOMEM; ++ kref_init(&d->kref); ++ d->ddev = dahdi_create_device(); ++ ++ for (x = 0; x < dds->numchans; x++) { ++ d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL); ++ if (!d->chans[x]) { ++ dynamic_put(d); ++ return -ENOMEM; ++ } ++ d->span.channels++; ++ } ++ ++ /* Allocate message buffer with sample space and header space */ ++ bufsize = dds->numchans * DAHDI_CHUNKSIZE + dds->numchans / 4 + 48; ++ ++ d->msgbuf = kzalloc(bufsize, GFP_KERNEL); ++ ++ if (!d->msgbuf) { ++ dynamic_put(d); ++ return -ENOMEM; ++ } ++ ++ /* Setup parameters properly assuming we're going to be okay. */ ++ strlcpy(d->dname, dds->driver, sizeof(d->dname)); ++ strlcpy(d->addr, dds->addr, sizeof(d->addr)); ++ d->timing = dds->timing; ++ snprintf(d->span.name, sizeof(d->span.name), "DYN/%s/%s", ++ dds->driver, dds->addr); ++ snprintf(d->span.desc, sizeof(d->span.desc), ++ "Dynamic '%s' span at '%s'", dds->driver, dds->addr); ++ d->span.deflaw = DAHDI_LAW_MULAW; ++ d->span.flags |= DAHDI_FLAG_RBS; ++ d->span.chans = d->chans; ++ d->span.spantype = SPANTYPE_DIGITAL_DYNAMIC; ++ d->span.linecompat = DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF | ++ DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_CCS | ++ DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_NOTOPEN; ++ d->span.ops = &dynamic_ops; ++ for (x = 0; x < d->span.channels; x++) { ++ snprintf(d->chans[x]->name, sizeof(d->chans[x]->name), ++ "DYN/%s/%s/%d", dds->driver, dds->addr, x+1); ++ d->chans[x]->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | ++ DAHDI_SIG_FXSLS | DAHDI_SIG_FXSKS | ++ DAHDI_SIG_FXSGS | DAHDI_SIG_FXOLS | ++ DAHDI_SIG_FXOKS | DAHDI_SIG_FXOGS | ++ DAHDI_SIG_SF | DAHDI_SIG_DACS_RBS | ++ DAHDI_SIG_CAS; ++ d->chans[x]->chanpos = x + 1; ++ d->chans[x]->pvt = d; ++ } ++ ++ dtd = find_driver(dds->driver); ++ if (!dtd) { ++ request_module("dahdi_dynamic_%s", dds->driver); ++ dtd = find_driver(dds->driver); ++ } ++ ++ ++ if (!dtd) { ++ printk(KERN_NOTICE "No such driver '%s' for dynamic span\n", ++ dds->driver); ++ dynamic_put(d); ++ return -EINVAL; ++ } ++ ++ if (!try_module_get(dtd->owner)) { ++ dynamic_put(d); ++ return -ENODEV; ++ } ++ ++ /* Remember the driver. We also give our reference to the driver to ++ * the dahdi_dyanmic here. Do not access dtd directly now. */ ++ d->driver = dtd; ++ ++ /* Create the stuff */ ++ res = dtd->create(d, d->addr); ++ if (res) { ++ printk(KERN_NOTICE "Driver '%s' (%s) rejected address '%s'\n", ++ dtd->name, dtd->desc, d->addr); ++ dynamic_put(d); ++ module_put(dtd->owner); ++ return res; ++ } ++ ++ d->ddev->devicetype = d->span.name; ++ d->ddev->hardware_id = d->span.name; ++ dev_set_name(&d->ddev->dev, "dynamic:%s:%d", dds->driver, dtd->id++); ++ list_add_tail(&d->span.device_node, &d->ddev->spans); ++ /* Whee! We're created. Now register the span */ ++ if (dahdi_register_device(d->ddev, d->dev)) { ++ printk(KERN_NOTICE "Unable to register span '%s'\n", ++ d->span.name); ++ dynamic_put(d); ++ module_put(dtd->owner); ++ return -EINVAL; ++ } ++ ++ x = d->span.spanno; ++ ++ /* Transfer our reference to the dspan_list. Do not touch d after ++ * this point. It also must remain on the list while registered. */ ++ spin_lock_irqsave(&dspan_lock, flags); ++ list_add_rcu(&d->list, &dspan_list); ++ spin_unlock_irqrestore(&dspan_lock, flags); ++ ++ checkmaster(); ++ ++ module_put(dtd->owner); ++ return x; ++} ++ ++static int create_dynamic(struct dahdi_dynamic_span *dds) ++{ ++ int ret; ++ mutex_lock(&dspan_mutex); ++ ret = _create_dynamic(dds); ++ mutex_unlock(&dspan_mutex); ++ return ret; ++} ++ ++#ifdef ENABLE_TASKLETS ++static void dahdi_dynamic_tasklet(unsigned long data) ++{ ++ taskletrun++; ++ if (taskletpending) { ++ taskletexec++; ++ __dahdi_dynamic_run(); ++ } ++ taskletpending = 0; ++} ++#else ++static void dahdi_dynamic_flush_tasklet(unsigned long data) ++{ ++ struct dahdi_dynamic_driver *drv; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(drv, &driver_list, list) { ++ /* Flush any traffic still pending in the driver */ ++ if (drv->flush) { ++ drv->flush(); ++ } ++ } ++ rcu_read_unlock(); ++} ++#endif ++ ++static int dahdi_dynamic_ioctl(unsigned int cmd, unsigned long data) ++{ ++ struct dahdi_dynamic_span dds; ++ int res; ++ switch(cmd) { ++ case DAHDI_DYNAMIC_CREATE: ++ if (copy_from_user(&dds, (__user const void *)data, ++ sizeof(dds))) ++ return -EFAULT; ++ if (debug) ++ printk(KERN_DEBUG "Dynamic Create\n"); ++ res = create_dynamic(&dds); ++ if (res < 0) ++ return res; ++ dds.spanno = res; ++ /* Let them know the new span number */ ++ if (copy_to_user((__user void *) data, &dds, sizeof(dds))) ++ return -EFAULT; ++ return 0; ++ case DAHDI_DYNAMIC_DESTROY: ++ if (copy_from_user(&dds, (__user const void *)data, ++ sizeof(dds))) ++ return -EFAULT; ++ if (debug) ++ printk(KERN_DEBUG "Dynamic Destroy\n"); ++ return destroy_dynamic(&dds); ++ } ++ ++ return -ENOTTY; ++} ++ ++int dahdi_dynamic_register_driver(struct dahdi_dynamic_driver *dri) ++{ ++ unsigned long flags; ++ int res = 0; ++ ++ if (!dri->owner) ++ return -EINVAL; ++ ++ if (find_driver(dri->name)) { ++ res = -1; ++ } else { ++ spin_lock_irqsave(&driver_lock, flags); ++ list_add_rcu(&dri->list, &driver_list); ++ spin_unlock_irqrestore(&driver_lock, flags); ++ } ++ return res; ++} ++EXPORT_SYMBOL(dahdi_dynamic_register_driver); ++ ++void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri) ++{ ++ struct dahdi_dynamic *d, *n; ++ unsigned long flags; ++ ++ mutex_lock(&dspan_mutex); ++ ++ list_for_each_entry_safe(d, n, &dspan_list, list) { ++ if (d->driver == dri) { ++ if (d->pvt) { ++ if (d->driver && d->driver->destroy) ++ d->driver->destroy(d); ++ else ++ WARN_ON(1); ++ } ++ dahdi_unregister_device(d->ddev); ++ spin_lock_irqsave(&dspan_lock, flags); ++ list_del_rcu(&d->list); ++ spin_unlock_irqrestore(&dspan_lock, flags); ++ synchronize_rcu(); ++ d->driver = NULL; ++ dynamic_put(d); ++ } ++ } ++ ++ spin_lock_irqsave(&driver_lock, flags); ++ list_del_rcu(&dri->list); ++ spin_unlock_irqrestore(&driver_lock, flags); ++ synchronize_rcu(); ++ ++ mutex_unlock(&dspan_mutex); ++} ++EXPORT_SYMBOL(dahdi_dynamic_unregister_driver); ++ ++static struct timer_list alarmcheck; ++ ++static void check_for_red_alarm(TIMER_DATA_TYPE unused) ++{ ++ int newalarm; ++ int alarmchanged = 0; ++ struct dahdi_dynamic *d; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(d, &dspan_list, list) { ++ newalarm = d->span.alarms & ~DAHDI_ALARM_RED; ++ /* If nothing received for a second, consider that RED ALARM */ ++ if ((jiffies - d->rxjif) > 1 * HZ) { ++ newalarm |= DAHDI_ALARM_RED; ++ if (d->span.alarms != newalarm) { ++ d->span.alarms = newalarm; ++ dahdi_alarm_notify(&d->span); ++ alarmchanged++; ++ } ++ } ++ } ++ rcu_read_unlock(); ++ ++ if (alarmchanged) ++ checkmaster(); ++ ++ /* Do the next one */ ++ mod_timer(&alarmcheck, jiffies + 1 * HZ); ++} ++ ++static const struct dahdi_dynamic_ops dahdi_dynamic_ops = { ++ .owner = THIS_MODULE, ++ .ioctl = dahdi_dynamic_ioctl, ++}; ++ ++static int dahdi_dynamic_init(void) ++{ ++ /* Start process to check for RED ALARM */ ++ timer_setup(&alarmcheck, check_for_red_alarm, 0); ++ /* Check once per second */ ++ mod_timer(&alarmcheck, jiffies + 1 * HZ); ++#ifdef ENABLE_TASKLETS ++ tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0); ++#else ++ tasklet_init(&dahdi_dynamic_flush_tlet, dahdi_dynamic_flush_tasklet, 0); ++#endif ++ dahdi_set_dynamic_ops(&dahdi_dynamic_ops); ++ ++ printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n"); ++ return 0; ++} ++ ++static void dahdi_dynamic_cleanup(void) ++{ ++ dahdi_set_dynamic_ops(NULL); ++ ++#ifdef ENABLE_TASKLETS ++ if (taskletpending) { ++ tasklet_disable(&dahdi_dynamic_tlet); ++ tasklet_kill(&dahdi_dynamic_tlet); ++ } ++#else ++ tasklet_disable(&dahdi_dynamic_flush_tlet); ++ tasklet_kill(&dahdi_dynamic_flush_tlet); ++#endif ++ del_timer_sync(&alarmcheck); ++ /* Must call again in case it was running before and rescheduled ++ * itself. */ ++ del_timer(&alarmcheck); ++ printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n"); ++} ++ ++module_param(debug, int, 0600); ++ ++MODULE_DESCRIPTION("DAHDI Dynamic Span Support"); ++MODULE_AUTHOR("Mark Spencer "); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(dahdi_dynamic_init); ++module_exit(dahdi_dynamic_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_dynamic_eth.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic_eth.c +--- linux-source-4.19/drivers/dahdi/dahdi_dynamic_eth.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic_eth.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,419 @@ ++/* ++ * Dynamic Span Interface for DAHDI (Ethernet Interface) ++ * ++ * Written by Mark Spencer ++ * ++ * Copyright (C) 2001-2012, 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define ETH_P_DAHDI_DETH 0xd00d ++ ++struct ztdeth_header { ++ unsigned short subaddr; ++}; ++ ++/* We take the raw message, put it in an ethernet frame, and add a ++ two byte addressing header at the top for future use */ ++static DEFINE_SPINLOCK(zlock); ++ ++static struct sk_buff_head skbs; ++ ++static struct ztdeth { ++ unsigned char addr[ETH_ALEN]; ++ unsigned short subaddr; /* Network byte order */ ++ struct dahdi_span *span; ++ char ethdev[IFNAMSIZ]; ++ struct net_device *dev; ++ struct ztdeth *next; ++} *zdevs = NULL; ++ ++static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short subaddr) ++{ ++ unsigned long flags; ++ struct ztdeth *z; ++ struct dahdi_span *span = NULL; ++ spin_lock_irqsave(&zlock, flags); ++ z = zdevs; ++ while(z) { ++ if (!memcmp(addr, z->addr, ETH_ALEN) && ++ z->subaddr == subaddr) ++ break; ++ z = z->next; ++ } ++ if (z) ++ span = z->span; ++ spin_unlock_irqrestore(&zlock, flags); ++ if (!span || !test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) ++ return NULL; ++ return span; ++} ++ ++static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) ++{ ++ struct dahdi_span *span; ++ struct ztdeth_header *zh; ++ zh = (struct ztdeth_header *)skb_network_header(skb); ++ span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr); ++ if (span) { ++ skb_pull(skb, sizeof(struct ztdeth_header)); ++#ifdef NEW_SKB_LINEARIZE ++ if (skb_is_nonlinear(skb)) ++ skb_linearize(skb); ++#else ++ if (skb_is_nonlinear(skb)) ++ skb_linearize(skb, GFP_KERNEL); ++#endif ++ dahdi_dynamic_receive(span, (unsigned char *)skb->data, skb->len); ++ } ++ kfree_skb(skb); ++ return 0; ++} ++ ++static int ztdeth_notifier(struct notifier_block *block, unsigned long event, void *ptr) ++{ ++ struct net_device *dev = ptr; ++ struct ztdeth *z; ++ unsigned long flags; ++ switch(event) { ++ case NETDEV_GOING_DOWN: ++ case NETDEV_DOWN: ++ spin_lock_irqsave(&zlock, flags); ++ z = zdevs; ++ while(z) { ++ /* Note that the device no longer exists */ ++ if (z->dev == dev) ++ z->dev = NULL; ++ z = z->next; ++ } ++ spin_unlock_irqrestore(&zlock, flags); ++ break; ++ case NETDEV_UP: ++ spin_lock_irqsave(&zlock, flags); ++ z = zdevs; ++ while(z) { ++ /* Now that the device exists again, use it */ ++ if (!strcmp(z->ethdev, dev->name)) ++ z->dev = dev; ++ z = z->next; ++ } ++ spin_unlock_irqrestore(&zlock, flags); ++ break; ++ } ++ return 0; ++} ++ ++static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen) ++{ ++ struct ztdeth *z; ++ struct sk_buff *skb; ++ struct ztdeth_header *zh; ++ unsigned long flags; ++ struct net_device *dev; ++ unsigned char addr[ETH_ALEN]; ++ unsigned short subaddr; /* Network byte order */ ++ ++ spin_lock_irqsave(&zlock, flags); ++ z = dyn->pvt; ++ if (z && z->dev) { ++ /* Copy fields to local variables to remove spinlock ASAP */ ++ dev = z->dev; ++ memcpy(addr, z->addr, sizeof(z->addr)); ++ subaddr = z->subaddr; ++ spin_unlock_irqrestore(&zlock, flags); ++ skb = dev_alloc_skb(msglen + dev->hard_header_len + sizeof(struct ztdeth_header) + 32); ++ if (skb) { ++ /* Reserve header space */ ++ skb_reserve(skb, dev->hard_header_len + sizeof(struct ztdeth_header)); ++ ++ /* Copy message body */ ++ memcpy(skb_put(skb, msglen), msg, msglen); ++ ++ /* Throw on header */ ++ zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header)); ++ zh->subaddr = subaddr; ++ ++ /* Setup protocol and such */ ++ skb->protocol = __constant_htons(ETH_P_DAHDI_DETH); ++ skb_set_network_header(skb, 0); ++ skb->dev = dev; ++ dev_hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len); ++ skb_queue_tail(&skbs, skb); ++ } ++ } ++ else ++ spin_unlock_irqrestore(&zlock, flags); ++} ++ ++/** ++ * ztdeth_flush - Flush all pending transactions. ++ * ++ * This function is always called in softirq context. ++ */ ++static int ztdeth_flush(void) ++{ ++ struct sk_buff *skb; ++ while ((skb = skb_dequeue(&skbs))) ++ dev_queue_xmit(skb); ++ return 0; ++} ++ ++static struct packet_type ztdeth_ptype = { ++ .type = __constant_htons(ETH_P_DAHDI_DETH), /* Protocol */ ++ .dev = NULL, /* Device (NULL = wildcard) */ ++ .func = ztdeth_rcv, /* Receiver */ ++}; ++ ++static int digit2int(char d) ++{ ++ switch(d) { ++ case 'F': ++ case 'E': ++ case 'D': ++ case 'C': ++ case 'B': ++ case 'A': ++ return d - 'A' + 10; ++ case 'f': ++ case 'e': ++ case 'd': ++ case 'c': ++ case 'b': ++ case 'a': ++ return d - 'a' + 10; ++ case '9': ++ case '8': ++ case '7': ++ case '6': ++ case '5': ++ case '4': ++ case '3': ++ case '2': ++ case '1': ++ case '0': ++ return d - '0'; ++ } ++ return -1; ++} ++ ++static int hex2int(char *s) ++{ ++ int res; ++ int tmp; ++ /* Gotta be at least one digit */ ++ if (strlen(s) < 1) ++ return -1; ++ /* Can't be more than two */ ++ if (strlen(s) > 2) ++ return -1; ++ /* Grab the first digit */ ++ res = digit2int(s[0]); ++ if (res < 0) ++ return -1; ++ tmp = res; ++ /* Grab the next */ ++ if (strlen(s) > 1) { ++ res = digit2int(s[1]); ++ if (res < 0) ++ return -1; ++ tmp = tmp * 16 + res; ++ } ++ return tmp; ++} ++ ++static void ztdeth_destroy(struct dahdi_dynamic *dyn) ++{ ++ struct ztdeth *z = dyn->pvt; ++ unsigned long flags; ++ struct ztdeth *prev=NULL, *cur; ++ ++ spin_lock_irqsave(&zlock, flags); ++ cur = zdevs; ++ while(cur) { ++ if (cur == z) { ++ if (prev) ++ prev->next = cur->next; ++ else ++ zdevs = cur->next; ++ break; ++ } ++ prev = cur; ++ cur = cur->next; ++ } ++ spin_unlock_irqrestore(&zlock, flags); ++ ++ if (cur == z) { /* Successfully removed */ ++ dyn->pvt = NULL; ++ dev_put(z->dev); ++ printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name); ++ kfree(z); ++ } ++} ++ ++static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr) ++{ ++ struct ztdeth *z; ++ char src[256]; ++ char tmp[256], *tmp2, *tmp3, *tmp4 = NULL; ++ int res,x; ++ unsigned long flags; ++ struct dahdi_span *const span = &dyn->span; ++ ++ z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL); ++ if (z) { ++ /* Zero it out */ ++ memset(z, 0, sizeof(struct ztdeth)); ++ ++ /* Address should be /[/subaddr] */ ++ strlcpy(tmp, addr, sizeof(tmp)); ++ tmp2 = strchr(tmp, '/'); ++ if (tmp2) { ++ *tmp2 = '\0'; ++ tmp2++; ++ strlcpy(z->ethdev, tmp, sizeof(z->ethdev)); ++ } else { ++ printk(KERN_NOTICE "Invalid TDMoE address (no device) '%s'\n", addr); ++ kfree(z); ++ return -EINVAL; ++ } ++ if (tmp2) { ++ tmp4 = strchr(tmp2+1, '/'); ++ if (tmp4) { ++ *tmp4 = '\0'; ++ tmp4++; ++ } ++ /* We don't have SSCANF :( Gotta do this the hard way */ ++ tmp3 = strchr(tmp2, ':'); ++ for (x=0;x<6;x++) { ++ if (tmp2) { ++ if (tmp3) { ++ *tmp3 = '\0'; ++ tmp3++; ++ } ++ res = hex2int(tmp2); ++ if (res < 0) ++ break; ++ z->addr[x] = res & 0xff; ++ } else ++ break; ++ if ((tmp2 = tmp3)) ++ tmp3 = strchr(tmp2, ':'); ++ } ++ if (x != 6) { ++ printk(KERN_NOTICE "TDMoE: Invalid MAC address in: %s\n", addr); ++ kfree(z); ++ return -EINVAL; ++ } ++ } else { ++ printk(KERN_NOTICE "TDMoE: Missing MAC address\n"); ++ kfree(z); ++ return -EINVAL; ++ } ++ if (tmp4) { ++ int sub = 0; ++ int mul = 1; ++ ++ /* We have a subaddr */ ++ tmp3 = tmp4 + strlen (tmp4) - 1; ++ while (tmp3 >= tmp4) { ++ if (*tmp3 >= '0' && *tmp3 <= '9') { ++ sub += (*tmp3 - '0') * mul; ++ } else { ++ printk(KERN_NOTICE "TDMoE: Invalid subaddress\n"); ++ kfree(z); ++ return -EINVAL; ++ } ++ mul *= 10; ++ tmp3--; ++ } ++ z->subaddr = htons(sub); ++ } ++ z->dev = dev_get_by_name(&init_net, z->ethdev); ++ if (!z->dev) { ++ printk(KERN_NOTICE "TDMoE: Invalid device '%s'\n", z->ethdev); ++ kfree(z); ++ return -EINVAL; ++ } ++ z->span = span; ++ src[0] ='\0'; ++ for (x=0;x<5;x++) ++ sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]); ++ sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]); ++ printk(KERN_INFO "TDMoE: Added new interface for %s at %s (addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name, addr, src, ntohs(z->subaddr)); ++ ++ spin_lock_irqsave(&zlock, flags); ++ z->next = zdevs; ++ zdevs = z; ++ dyn->pvt = z; ++ spin_unlock_irqrestore(&zlock, flags); ++ } ++ return (z) ? 0 : -ENOMEM; ++} ++ ++static struct dahdi_dynamic_driver ztd_eth = { ++ .owner = THIS_MODULE, ++ .name = "eth", ++ .desc = "Ethernet", ++ .create = ztdeth_create, ++ .destroy = ztdeth_destroy, ++ .transmit = ztdeth_transmit, ++ .flush = ztdeth_flush, ++}; ++ ++static struct notifier_block ztdeth_nblock = { ++ .notifier_call = ztdeth_notifier, ++}; ++ ++static int __init ztdeth_init(void) ++{ ++ skb_queue_head_init(&skbs); ++ ++ dev_add_pack(&ztdeth_ptype); ++ register_netdevice_notifier(&ztdeth_nblock); ++ dahdi_dynamic_register_driver(&ztd_eth); ++ ++ return 0; ++} ++ ++static void __exit ztdeth_exit(void) ++{ ++ dahdi_dynamic_unregister_driver(&ztd_eth); ++ unregister_netdevice_notifier(&ztdeth_nblock); ++ dev_remove_pack(&ztdeth_ptype); ++ ++ skb_queue_purge(&skbs); ++} ++ ++MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support"); ++MODULE_AUTHOR("Mark Spencer "); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(ztdeth_init); ++module_exit(ztdeth_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_dynamic_ethmf.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic_ethmf.c +--- linux-source-4.19/drivers/dahdi/dahdi_dynamic_ethmf.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic_ethmf.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,797 @@ ++/* ++ * Dynamic Span Interface for DAHDI (Multi-Span Ethernet Interface) ++ * ++ * Written by Joseph Benden ++ * ++ * Copyright (C) 2007-2010, Thralling Penguin LLC. ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * Undefine USE_PROC_FS, if you do not want the /proc/dahdi/dynamic-ethmf ++ * support. Undefining this would give a slight performance increase. ++ */ ++#define USE_PROC_FS ++ ++#ifdef USE_PROC_FS ++# include ++# include ++#endif ++ ++#ifdef CONFIG_DEVFS_FS ++# include ++#endif ++ ++#include ++#include ++ ++#define ETH_P_ZTDETH 0xd00d ++#define ETHMF_MAX_PER_SPAN_GROUP 8 ++#define ETHMF_MAX_GROUPS 16 ++#define ETHMF_FLAG_IGNORE_CHAN0 (1 << 3) ++#define ETHMF_MAX_SPANS 4 ++ ++struct ztdeth_header { ++ unsigned short subaddr; ++}; ++ ++/* Timer for enabling spans - used to combat a lock problem */ ++static struct timer_list timer; ++ ++/* Whether or not the timer has been deleted */ ++static atomic_t timer_deleted = ATOMIC_INIT(0); ++ ++/* Global error counter */ ++static atomic_t errcount = ATOMIC_INIT(0); ++ ++/* Whether or not we are in shutdown */ ++static atomic_t shutdown = ATOMIC_INIT(0); ++ ++static struct sk_buff_head skbs; ++ ++#ifdef USE_PROC_FS ++struct ethmf_group { ++ unsigned int hash_addr; ++ atomic_t spans; ++ atomic_t rxframecount; ++ atomic_t txframecount; ++ atomic_t rxbytecount; ++ atomic_t txbytecount; ++ atomic_t devupcount; ++ atomic_t devdowncount; ++}; ++static struct ethmf_group ethmf_groups[ETHMF_MAX_GROUPS]; ++#endif ++ ++struct ztdeth { ++ /* Destination MAC address */ ++ unsigned char addr[ETH_ALEN]; ++ /* Destination MAC address hash value */ ++ unsigned int addr_hash; ++ /* span sub-address, in network byte order */ ++ unsigned short subaddr; ++ /* DAHDI span associated with this TDMoE-mf span */ ++ struct dahdi_span *span; ++ /* Ethernet interface name */ ++ char ethdev[IFNAMSIZ]; ++ /* Ethernet device reference */ ++ struct net_device *dev; ++ /* trx buffer */ ++ unsigned char *msgbuf; ++ /* trx buffer length */ ++ int msgbuf_len; ++ /* wether or not this frame is ready for trx */ ++ atomic_t ready; ++ /* delay counter, to ensure all spans are added, prior to usage */ ++ atomic_t delay; ++ /* rvc buffer */ ++ unsigned char *rcvbuf; ++ /* the number of channels in this span */ ++ int real_channels; ++ /* use padding if 1, else no padding */ ++ atomic_t no_front_padding; ++ /* counter to pseudo lock the rcvbuf */ ++ atomic_t refcnt; ++ ++ struct list_head list; ++}; ++ ++/** ++ * Lock for adding and removing items in ethmf_list ++ */ ++static DEFINE_SPINLOCK(ethmf_lock); ++ ++/** ++ * The active list of all running spans ++ */ ++static LIST_HEAD(ethmf_list); ++ ++static inline void ethmf_errors_inc(void) ++{ ++#ifdef USE_PROC_FS ++ atomic_inc(&errcount); ++#endif ++} ++ ++#ifdef USE_PROC_FS ++static inline int hashaddr_to_index(unsigned int hash_addr) ++{ ++ int i, z = -1; ++ for (i = 0; i < ETHMF_MAX_GROUPS; ++i) { ++ if (z == -1 && ethmf_groups[i].hash_addr == 0) ++ z = i; ++ if (ethmf_groups[i].hash_addr == hash_addr) ++ return i; ++ } ++ if (z != -1) { ++ ethmf_groups[z].hash_addr = hash_addr; ++ } ++ return z; ++} ++#endif ++ ++/** ++ * Find the Ztdeth Struct and DAHDI span for a given MAC address and subaddr. ++ * ++ * NOTE: RCU read lock must already be held. ++ */ ++static inline void find_ethmf(const unsigned char *addr, ++ const unsigned short subaddr, struct ztdeth **ze, ++ struct dahdi_span **span) ++{ ++ struct ztdeth *z; ++ ++ list_for_each_entry_rcu(z, ðmf_list, list) { ++ if (!atomic_read(&z->delay)) { ++ if (!memcmp(addr, z->addr, ETH_ALEN) ++ && z->subaddr == subaddr) { ++ *ze = z; ++ *span = z->span; ++ return; ++ } ++ } ++ } ++ ++ /* no results */ ++ *ze = NULL; ++ *span = NULL; ++} ++ ++/** ++ * Determines if all spans are ready for transmit. If all spans are ready, ++ * we return the number of spans which indeed are ready and populate the ++ * array of pointers to those spans.. ++ * ++ * NOTE: RCU read lock must already be held. ++ */ ++static inline int ethmf_trx_spans_ready(unsigned int addr_hash, struct ztdeth *(*ready_spans)[ETHMF_MAX_PER_SPAN_GROUP]) ++{ ++ struct ztdeth *t; ++ int span_count = 0, spans_ready = 0; ++ ++ list_for_each_entry_rcu(t, ðmf_list, list) { ++ if (!atomic_read(&t->delay) && t->addr_hash == addr_hash) { ++ ++span_count; ++ if (atomic_read(&t->ready)) { ++ short subaddr = ntohs(t->subaddr); ++ if (subaddr < ETHMF_MAX_PER_SPAN_GROUP) { ++ (*ready_spans)[subaddr] = t; ++ ++spans_ready; ++ } else { ++ printk(KERN_ERR "More than %d spans per multi-frame group are not currently supported.", ++ ETHMF_MAX_PER_SPAN_GROUP); ++ } ++ } ++ } ++ } ++ ++ if (span_count && spans_ready && span_count == spans_ready) { ++ return spans_ready; ++ } ++ return 0; ++} ++ ++/** ++ * Ethernet receiving side processing function. ++ */ ++static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev, ++ struct packet_type *pt, struct net_device *orig_dev) ++{ ++ int num_spans = 0, span_index = 0; ++ unsigned char *data; ++ struct dahdi_span *span; ++ struct ztdeth *z = NULL; ++ struct ztdeth_header *zh; ++ unsigned int samples, channels, rbslen, flags; ++ unsigned int skip = 0; ++ ++ zh = (struct ztdeth_header *) skb_network_header(skb); ++ if (ntohs(zh->subaddr) & 0x8000) { ++ /* got a multi-span frame */ ++ num_spans = ntohs(zh->subaddr) & 0xFF; ++ ++ /* Currently max of 4 spans supported */ ++ if (unlikely(num_spans > ETHMF_MAX_SPANS)) { ++ kfree_skb(skb); ++ return 0; ++ } ++ ++ skb_pull(skb, sizeof(struct ztdeth_header)); ++#ifdef NEW_SKB_LINEARIZE ++ if (skb_is_nonlinear(skb)) ++ skb_linearize(skb); ++#else ++ if (skb_is_nonlinear(skb)) ++ skb_linearize(skb, GFP_KERNEL); ++#endif ++ data = (unsigned char *) skb->data; ++ ++ rcu_read_lock(); ++ do { ++ find_ethmf(eth_hdr(skb)->h_source, ++ htons(span_index), &z, &span); ++ if (unlikely(!z || !span)) { ++ /* The recv'd span does not belong to us */ ++ /* ethmf_errors_inc(); */ ++ ++span_index; ++ continue; ++ } ++ ++ samples = data[(span_index * 6)] & 0xFF; ++ flags = data[((span_index * 6) + 1)] & 0xFF; ++ channels = data[((span_index * 6) + 5)] & 0xFF; ++ ++ /* Precomputed defaults for most typical values */ ++ if (channels == 24) ++ rbslen = 12; ++ else if (channels == 31) ++ rbslen = 16; ++ else ++ rbslen = ((channels + 3) / 4) * 2; ++ ++ if (unlikely(samples != 8 || channels >= 32 || channels == 0)) { ++ ethmf_errors_inc(); ++ ++span_index; ++ continue; ++ } ++ ++ if (atomic_dec_and_test(&z->refcnt) == 0) { ++ memcpy(z->rcvbuf, data + 6*span_index, 6); /* TDM Header */ ++ /* ++ * If we ignore channel zero we must skip the first eight bytes and ++ * ensure that ztdynamic doesn't get confused by this new flag ++ */ ++ if (flags & ETHMF_FLAG_IGNORE_CHAN0) { ++ skip = 8; ++ ++ /* Remove this flag since ztdynamic may not understand it */ ++ z->rcvbuf[1] = flags & ~(ETHMF_FLAG_IGNORE_CHAN0); ++ ++ /* Additionally, now we will transmit with front padding */ ++ atomic_set(&z->no_front_padding, 0); ++ } else { ++ /* Disable front padding if we recv'd a packet without it */ ++ atomic_set(&z->no_front_padding, 1); ++ } ++ memcpy(z->rcvbuf + 6, data + 6*num_spans + 16 ++ *span_index, rbslen); /* RBS Header */ ++ ++ /* 256 == 32*8; if padding lengths change, this must be modified */ ++ memcpy(z->rcvbuf + 6 + rbslen, data + 6*num_spans + 16 ++ *num_spans + (256)*span_index + skip, channels ++ * 8); /* Payload */ ++ ++ dahdi_dynamic_receive(span, z->rcvbuf, 6 + rbslen ++ + channels*8); ++ } else { ++ ethmf_errors_inc(); ++ printk(KERN_INFO "TDMoE span overflow detected. Span %d was dropped.", span_index); ++ } ++ atomic_inc(&z->refcnt); ++ ++#ifdef USE_PROC_FS ++ if (span_index == 0) { ++ atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].rxframecount)); ++ atomic_add(skb->len + z->dev->hard_header_len + ++ sizeof(struct ztdeth_header), ++ &(ethmf_groups[hashaddr_to_index(z->addr_hash)].rxbytecount)); ++ } ++#endif ++ ++span_index; ++ } while (!atomic_read(&shutdown) && span_index < num_spans); ++ rcu_read_unlock(); ++ } ++ ++ kfree_skb(skb); ++ return 0; ++} ++ ++static int ztdethmf_notifier(struct notifier_block *block, unsigned long event, ++ void *ptr) ++{ ++ struct net_device *dev = ptr; ++ struct ztdeth *z; ++ ++ switch (event) { ++ case NETDEV_GOING_DOWN: ++ case NETDEV_DOWN: ++ rcu_read_lock(); ++ list_for_each_entry_rcu(z, ðmf_list, list) { ++ /* Note that the device no longer exists */ ++ if (z->dev == dev) { ++ z->dev = NULL; ++#ifdef USE_PROC_FS ++ atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].devdowncount)); ++#endif ++ } ++ } ++ rcu_read_unlock(); ++ break; ++ case NETDEV_UP: ++ rcu_read_lock(); ++ list_for_each_entry_rcu(z, ðmf_list, list) { ++ /* Now that the device exists again, use it */ ++ if (!strcmp(z->ethdev, dev->name)) { ++ z->dev = dev; ++#ifdef USE_PROC_FS ++ atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].devupcount)); ++#endif ++ } ++ } ++ rcu_read_unlock(); ++ break; ++ } ++ return 0; ++} ++ ++static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen) ++{ ++ struct ztdeth *z = dyn->pvt, *ready_spans[ETHMF_MAX_PER_SPAN_GROUP]; ++ struct sk_buff *skb; ++ struct ztdeth_header *zh; ++ struct net_device *dev; ++ unsigned char addr[ETH_ALEN]; ++ int spans_ready = 0, index = 0; ++ ++ if (atomic_read(&shutdown)) ++ return; ++ ++ rcu_read_lock(); ++ ++ if (unlikely(!z || !z->dev)) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ if (!atomic_read(&z->ready)) { ++ if (atomic_inc_return(&z->ready) == 1) { ++ memcpy(z->msgbuf, msg, msglen); ++ z->msgbuf_len = msglen; ++ } ++ } ++ ++ spans_ready = ethmf_trx_spans_ready(z->addr_hash, &ready_spans); ++ if (spans_ready) { ++ int pad[ETHMF_MAX_SPANS], rbs[ETHMF_MAX_SPANS]; ++ ++ dev = z->dev; ++ memcpy(addr, z->addr, sizeof(z->addr)); ++ ++ for (index = 0; index < spans_ready; index++) { ++ int chan = ready_spans[index]->real_channels; ++ /* By default we pad to 32 channels, but if ++ * no_front_padding is false then we have a pad ++ * in the front of 8 bytes, so this implies one ++ * less channel ++ */ ++ if (atomic_read(&(ready_spans[index]->no_front_padding))) ++ pad[index] = (32 - chan)*8; ++ else ++ pad[index] = (31 - chan)*8; ++ ++ if (chan == 24) ++ rbs[index] = 12; ++ else if (chan == 31) ++ rbs[index] = 16; ++ else ++ /* Shouldn't this be index, not spans_ready? */ ++ rbs[spans_ready] = ((chan + 3) / 4) * 2; ++ } ++ ++ /* Allocate the standard size for a 32-chan frame */ ++ skb = dev_alloc_skb(1112 + dev->hard_header_len ++ + sizeof(struct ztdeth_header) + 32); ++ if (unlikely(!skb)) { ++ rcu_read_unlock(); ++ ethmf_errors_inc(); ++ return; ++ } ++ ++ /* Reserve header space */ ++ skb_reserve(skb, dev->hard_header_len ++ + sizeof(struct ztdeth_header)); ++ /* copy each spans header */ ++ for (index = 0; index < spans_ready; index++) { ++ if (!atomic_read(&(ready_spans[index]->no_front_padding))) ++ ready_spans[index]->msgbuf[1] ++ |= ETHMF_FLAG_IGNORE_CHAN0; ++ ++ memcpy(skb_put(skb, 6), ready_spans[index]->msgbuf, 6); ++ } ++ ++ /* copy each spans RBS payload */ ++ for (index = 0; index < spans_ready; index++) { ++ memcpy(skb_put(skb, 16), ready_spans[index]->msgbuf + 6, ++ rbs[index]); ++ } ++ ++ /* copy each spans data/voice payload */ ++ for (index = 0; index < spans_ready; index++) { ++ int chan = ready_spans[index]->real_channels; ++ if (!atomic_read(&(ready_spans[index]->no_front_padding))) { ++ /* This adds an additional (padded) channel to our total */ ++ memset(skb_put(skb, 8), 0xA5, 8); /* ETHMF_IGNORE_CHAN0 */ ++ } ++ memcpy(skb_put(skb, chan*8), ready_spans[index]->msgbuf ++ + (6 + rbs[index]), chan*8); ++ if (pad[index] > 0) { ++ memset(skb_put(skb, pad[index]), 0xDD, pad[index]); ++ } ++ ++ /* mark span as ready for new data/voice */ ++ atomic_set(&(ready_spans[index]->ready), 0); ++ } ++ ++ /* Throw on header */ ++ zh = (struct ztdeth_header *)skb_push(skb, ++ sizeof(struct ztdeth_header)); ++ zh->subaddr = htons((unsigned short)(0x8000 | (unsigned char)(spans_ready & 0xFF))); ++ ++ /* Setup protocol type */ ++ skb->protocol = __constant_htons(ETH_P_ZTDETH); ++ skb_set_network_header(skb, 0); ++ skb->dev = dev; ++ dev_hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len); ++ /* queue frame for delivery */ ++ if (dev) { ++ skb_queue_tail(&skbs, skb); ++ } ++#ifdef USE_PROC_FS ++ atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].txframecount)); ++ atomic_add(skb->len, &(ethmf_groups[hashaddr_to_index(z->addr_hash)].txbytecount)); ++#endif ++ } ++ ++ rcu_read_unlock(); ++ ++ return; ++} ++ ++static int ztdethmf_flush(void) ++{ ++ struct sk_buff *skb; ++ ++ /* Handle all transmissions now */ ++ while ((skb = skb_dequeue(&skbs))) { ++ dev_queue_xmit(skb); ++ } ++ return 0; ++} ++ ++static struct packet_type ztdethmf_ptype = { ++ .type = __constant_htons(ETH_P_ZTDETH), /* Protocol */ ++ .dev = NULL, /* Device (NULL = wildcard) */ ++ .func = ztdethmf_rcv, /* Receiver */ ++}; ++ ++static void ztdethmf_destroy(struct dahdi_dynamic *dyn) ++{ ++ struct ztdeth *z = dyn->pvt; ++ unsigned long flags; ++ ++ atomic_set(&shutdown, 1); ++ synchronize_rcu(); ++ ++ spin_lock_irqsave(ðmf_lock, flags); ++ list_del_rcu(&z->list); ++ spin_unlock_irqrestore(ðmf_lock, flags); ++ synchronize_rcu(); ++ atomic_dec(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].spans)); ++ ++ if (z) { /* Successfully removed */ ++ printk(KERN_INFO "Removed interface for %s\n", ++ z->span->name); ++ kfree(z->msgbuf); ++ kfree(z); ++ } else { ++ if (z && z->span && z->span->name) { ++ printk(KERN_ERR "Cannot find interface for %s\n", ++ z->span->name); ++ } ++ } ++} ++ ++static int ztdethmf_create(struct dahdi_dynamic *dyn, const char *addr) ++{ ++ struct ztdeth *z; ++ char src[256]; ++ char *src_ptr; ++ int x, bufsize, num_matched; ++ unsigned long flags; ++ struct dahdi_span *const span = &dyn->span; ++ ++ BUG_ON(!span); ++ BUG_ON(!addr); ++ ++ z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL); ++ if (!z) ++ return -ENOMEM; ++ ++ /* Zero it out */ ++ memset(z, 0, sizeof(struct ztdeth)); ++ ++ /* set a delay for xmit/recv to workaround Zaptel problems */ ++ atomic_set(&z->delay, 4); ++ ++ /* create a msg buffer. MAX OF 31 CHANNELS!!!! */ ++ bufsize = 31 * DAHDI_CHUNKSIZE + 31 / 4 + 48; ++ z->msgbuf = kmalloc(bufsize, GFP_KERNEL); ++ z->rcvbuf = kmalloc(bufsize, GFP_KERNEL); ++ ++ /* Address should be //subaddr */ ++ strlcpy(src, addr, sizeof(src)); ++ /* replace all / with space; otherwise kernel sscanf does not work */ ++ src_ptr = src; ++ while (*src_ptr) { ++ if (*src_ptr == '/') ++ *src_ptr = ' '; ++ ++src_ptr; ++ } ++ num_matched = sscanf(src, ++ "%16s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hu", ++ z->ethdev, &z->addr[0], &z->addr[1], ++ &z->addr[2], &z->addr[3], &z->addr[4], ++ &z->addr[5], &z->subaddr); ++ if (8 != num_matched) { ++ printk(KERN_ERR "Only matched %d entries in '%s'\n", num_matched, src); ++ printk(KERN_ERR "Invalid TDMoE Multiframe address: %s\n", addr); ++ kfree(z); ++ return -EINVAL; ++ } ++ z->dev = dev_get_by_name(&init_net, z->ethdev); ++ if (!z->dev) { ++ printk(KERN_ERR "TDMoE Multiframe: Invalid device '%s'\n", z->ethdev); ++ kfree(z); ++ return -EINVAL; ++ } ++ z->span = span; ++ z->subaddr = htons(z->subaddr); ++ z->addr_hash = crc32_le(0, z->addr, ETH_ALEN); ++ z->real_channels = span->channels; ++ ++ src[0] = '\0'; ++ for (x = 0; x < 5; x++) ++ sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]); ++ sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]); ++ ++ printk(KERN_INFO "TDMoEmf: Added new interface for %s at %s " ++ "(addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name, ++ addr, src, ntohs(z->subaddr)); ++ ++ atomic_set(&z->ready, 0); ++ atomic_set(&z->refcnt, 0); ++ ++ spin_lock_irqsave(ðmf_lock, flags); ++ list_add_rcu(&z->list, ðmf_list); ++ spin_unlock_irqrestore(ðmf_lock, flags); ++ atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].spans)); ++ ++ /* enable the timer for enabling the spans */ ++ mod_timer(&timer, jiffies + HZ); ++ atomic_set(&shutdown, 0); ++ dyn->pvt = z; ++ return 0; ++} ++ ++static struct dahdi_dynamic_driver ztd_ethmf = { ++ .owner = THIS_MODULE, ++ .name = "ethmf", ++ .desc = "Ethernet", ++ .create = ztdethmf_create, ++ .destroy = ztdethmf_destroy, ++ .transmit = ztdethmf_transmit, ++ .flush = ztdethmf_flush, ++}; ++ ++static struct notifier_block ztdethmf_nblock = { ++ .notifier_call = ztdethmf_notifier, ++}; ++ ++/** ++ * Decrements each delay counter in the ethmf_list and returns the number of ++ * delay counters that are not equal to zero. ++ */ ++static int ethmf_delay_dec(void) ++{ ++ struct ztdeth *z; ++ int count_nonzero = 0; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(z, ðmf_list, list) { ++ if (atomic_read(&z->delay)) { ++ atomic_dec(&z->delay); ++ ++count_nonzero; ++ } else ++ atomic_set(&z->delay, 0); ++ } ++ rcu_read_unlock(); ++ return count_nonzero; ++} ++ ++/** ++ * Timer callback function to allow all spans to be added, prior to any of ++ * them being used. ++ */ ++static void timer_callback(TIMER_DATA_TYPE unused) ++{ ++ if (ethmf_delay_dec()) { ++ if (!atomic_read(&timer_deleted)) ++ mod_timer(&timer, jiffies + HZ); ++ } else { ++ printk(KERN_INFO "All TDMoE multiframe span groups are active.\n"); ++ } ++} ++ ++#ifdef USE_PROC_FS ++static struct proc_dir_entry *proc_entry; ++static const char *ztdethmf_procname = "dahdi/dynamic-ethmf"; ++ ++static int ztdethmf_proc_show(struct seq_file *sfile, void *not_used) ++{ ++ struct ztdeth *z = NULL; ++ int i = 0; ++ unsigned int group = 0, c = 0; ++ ++ rcu_read_lock(); ++ ++ seq_printf(sfile, "Errors: %d\n\n", atomic_read(&errcount)); ++ ++ for (group = 0; group < ETHMF_MAX_GROUPS; ++group) { ++ if (atomic_read(&(ethmf_groups[group].spans))) { ++ seq_printf(sfile, "Group #%d (0x%x)\n", i++, ++ ethmf_groups[group].hash_addr); ++ seq_printf(sfile, "Spans: %d\n", ++ atomic_read(&(ethmf_groups[group].spans))); ++ ++ c = 1; ++ list_for_each_entry_rcu(z, ðmf_list, list) { ++ if (z->addr_hash == ethmf_groups[group].hash_addr) { ++ if (c == 1) { ++ seq_printf(sfile, ++ " Device: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x)\n", ++ z->ethdev, ++ z->addr[0], z->addr[1], z->addr[2], ++ z->addr[3], z->addr[4], z->addr[5]); ++ } ++ seq_printf(sfile, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n", ++ c++, ntohs(z->subaddr), ++ atomic_read(&z->ready), atomic_read(&z->delay), ++ z->real_channels, atomic_read(&z->no_front_padding)); ++ } ++ } ++ seq_printf(sfile, " Device UPs: %u\n", ++ atomic_read(&(ethmf_groups[group].devupcount))); ++ seq_printf(sfile, " Device DOWNs: %u\n", ++ atomic_read(&(ethmf_groups[group].devdowncount))); ++ seq_printf(sfile, " Rx Frames: %u\n", ++ atomic_read(&(ethmf_groups[group].rxframecount))); ++ seq_printf(sfile, " Tx Frames: %u\n", ++ atomic_read(&(ethmf_groups[group].txframecount))); ++ seq_printf(sfile, " Rx Bytes: %u\n", ++ atomic_read(&(ethmf_groups[group].rxbytecount))); ++ seq_printf(sfile, " Tx Bytes: %u\n", ++ atomic_read(&(ethmf_groups[group].txbytecount))); ++ } ++ } ++ rcu_read_unlock(); ++ return 0; ++} ++ ++static int ztdethmf_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ztdethmf_proc_show, NULL); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops ztdethmf_proc_fops = { ++ .proc_open = ztdethmf_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = seq_release, ++}; ++#else ++static const struct file_operations ztdethmf_proc_fops = { ++ .open = ztdethmf_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++}; ++#endif ++#endif ++ ++static int __init ztdethmf_init(void) ++{ ++ timer_setup(&timer, timer_callback, 0); ++ mod_timer(&timer, jiffies + HZ); ++ ++ dev_add_pack(&ztdethmf_ptype); ++ register_netdevice_notifier(&ztdethmf_nblock); ++ dahdi_dynamic_register_driver(&ztd_ethmf); ++ ++ skb_queue_head_init(&skbs); ++ ++#ifdef USE_PROC_FS ++ proc_entry = proc_create_data(ztdethmf_procname, 0444, NULL, ++ &ztdethmf_proc_fops, NULL); ++ if (!proc_entry) { ++ printk(KERN_ALERT "create_proc_read_entry failed.\n"); ++ } ++#endif ++ ++ return 0; ++} ++ ++static void __exit ztdethmf_exit(void) ++{ ++ atomic_set(&timer_deleted, 1); ++ del_timer_sync(&timer); ++ ++ dev_remove_pack(&ztdethmf_ptype); ++ unregister_netdevice_notifier(&ztdethmf_nblock); ++ dahdi_dynamic_unregister_driver(&ztd_ethmf); ++ ++#ifdef USE_PROC_FS ++ if (proc_entry) ++ remove_proc_entry(ztdethmf_procname, NULL); ++#endif ++} ++ ++MODULE_DESCRIPTION("DAHDI Dynamic TDMoEmf Support"); ++MODULE_AUTHOR("Joseph Benden "); ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif ++ ++module_init(ztdethmf_init); ++module_exit(ztdethmf_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_dynamic_loc.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic_loc.c +--- linux-source-4.19/drivers/dahdi/dahdi_dynamic_loc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_dynamic_loc.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,269 @@ ++/* ++ * Dynamic Span Interface for DAHDI (Local Interface) ++ * ++ * Written by Nicolas Bougues ++ * ++ * Copyright (C) 2004, Axialys Interactive ++ * ++ * All rights reserved. ++ * ++ * Note : a DAHDI timing source must exist prior to loading this driver ++ * ++ * Address syntax : ++ * :[:] ++ * ++ * As of now, keys and ids are single digit only ++ * ++ * One span may have up to one "normal" peer, and one "monitor" peer ++ * ++ * Example : ++ * ++ * Say you have two spans cross connected, a third one monitoring RX on the ++ * first one, a fourth one monitoring RX on the second one ++ * ++ * 1:0 ++ * 1:1 ++ * 1:2:0 ++ * 1:3:1 ++ * ++ * Contrary to TDMoE, no frame loss can occur. ++ * ++ * See bug #2021 for more details ++ * ++ */ ++ ++/* ++ * 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 ++ ++/** ++ * struct dahdi_dynamic_loc - For local dynamic spans ++ * @monitor_rx_peer: Indicates the peer span that monitors this span. ++ * @peer: Indicates the rw peer for this span. ++ * ++ */ ++struct dahdi_dynamic_local { ++ unsigned short key; ++ unsigned short id; ++ struct dahdi_dynamic_local *monitor_rx_peer; ++ struct dahdi_dynamic_local *peer; ++ struct dahdi_span *span; ++ struct list_head node; ++}; ++ ++static DEFINE_SPINLOCK(local_lock); ++static LIST_HEAD(dynamic_local_list); ++ ++static void ++dahdi_dynamic_local_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen) ++{ ++ struct dahdi_dynamic_local *d; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&local_lock, flags); ++ d = dyn->pvt; ++ if (d && d->peer && d->peer->span) { ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->peer->span->flags)) ++ dahdi_dynamic_receive(d->peer->span, msg, msglen); ++ } ++ if (d && d->monitor_rx_peer && d->monitor_rx_peer->span) { ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, ++ &d->monitor_rx_peer->span->flags)) { ++ dahdi_dynamic_receive(d->monitor_rx_peer->span, ++ msg, msglen); ++ } ++ } ++ spin_unlock_irqrestore(&local_lock, flags); ++} ++ ++static int digit2int(char d) ++{ ++ switch(d) { ++ case 'F': ++ case 'E': ++ case 'D': ++ case 'C': ++ case 'B': ++ case 'A': ++ return d - 'A' + 10; ++ case 'f': ++ case 'e': ++ case 'd': ++ case 'c': ++ case 'b': ++ case 'a': ++ return d - 'a' + 10; ++ case '9': ++ case '8': ++ case '7': ++ case '6': ++ case '5': ++ case '4': ++ case '3': ++ case '2': ++ case '1': ++ case '0': ++ return d - '0'; ++ } ++ return -1; ++} ++ ++static void dahdi_dynamic_local_destroy(struct dahdi_dynamic *dyn) ++{ ++ struct dahdi_dynamic_local *d; ++ unsigned long flags; ++ struct dahdi_dynamic_local *cur; ++ ++ spin_lock_irqsave(&local_lock, flags); ++ d = dyn->pvt; ++ list_for_each_entry(cur, &dynamic_local_list, node) { ++ if (cur->peer == d) ++ cur->peer = NULL; ++ if (cur->monitor_rx_peer == d) ++ cur->monitor_rx_peer = NULL; ++ } ++ list_del(&d->node); ++ dyn->pvt = NULL; ++ spin_unlock_irqrestore(&local_lock, flags); ++ ++ printk(KERN_INFO "TDMoL: Removed interface for %s, key %d " ++ "id %d\n", d->span->name, d->key, d->id); ++ kfree(d); ++} ++ ++static int dahdi_dynamic_local_create(struct dahdi_dynamic *dyn, ++ const char *address) ++{ ++ struct dahdi_dynamic_local *d, *l; ++ unsigned long flags; ++ int key = -1, id = -1, monitor = -1; ++ struct dahdi_span *const span = &dyn->span; ++ ++ if (strlen(address) >= 3) { ++ if (address[1] != ':') ++ goto INVALID_ADDRESS; ++ key = digit2int(address[0]); ++ id = digit2int(address[2]); ++ } ++ if (strlen (address) == 5) { ++ if (address[3] != ':') ++ goto INVALID_ADDRESS; ++ monitor = digit2int(address[4]); ++ } ++ ++ if (key == -1 || id == -1) ++ goto INVALID_ADDRESS; ++ ++ d = kzalloc(sizeof(*d), GFP_KERNEL); ++ if (!d) ++ return -ENOMEM; ++ ++ d->key = key; ++ d->id = id; ++ d->span = span; ++ ++ spin_lock_irqsave(&local_lock, flags); ++ /* Add this peer to any existing spans with same key ++ And add them as peers to this one */ ++ list_for_each_entry(l, &dynamic_local_list, node) { ++ if (l->key != d->key) ++ continue; ++ ++ if (l->id == d->id) { ++ printk(KERN_DEBUG "TDMoL: Duplicate id (%d) for key " ++ "%d\n", d->id, d->key); ++ goto CLEAR_AND_DEL_FROM_PEERS; ++ } ++ if (monitor == -1) { ++ if (l->peer) { ++ printk(KERN_DEBUG "TDMoL: Span with key %d and " ++ "id %d already has a R/W peer\n", ++ d->key, d->id); ++ goto CLEAR_AND_DEL_FROM_PEERS; ++ } else { ++ l->peer = d; ++ d->peer = l; ++ } ++ } ++ if (monitor == l->id) { ++ if (l->monitor_rx_peer) { ++ printk(KERN_DEBUG "TDMoL: Span with key %d and " ++ "id %d already has a monitoring peer\n", ++ d->key, d->id); ++ goto CLEAR_AND_DEL_FROM_PEERS; ++ } else { ++ l->monitor_rx_peer = d; ++ } ++ } ++ } ++ list_add(&d->node, &dynamic_local_list); ++ dyn->pvt = d; ++ spin_unlock_irqrestore(&local_lock, flags); ++ ++ printk(KERN_INFO "TDMoL: Added new interface for %s, " ++ "key %d id %d\n", span->name, d->key, d->id); ++ ++ span->cannot_provide_timing = 1; ++ return 0; ++ ++CLEAR_AND_DEL_FROM_PEERS: ++ list_for_each_entry(l, &dynamic_local_list, node) { ++ if (l->peer == d) ++ l->peer = NULL; ++ if (l->monitor_rx_peer == d) ++ l->monitor_rx_peer = NULL; ++ } ++ kfree(d); ++ spin_unlock_irqrestore(&local_lock, flags); ++ return -EINVAL; ++ ++INVALID_ADDRESS: ++ printk (KERN_NOTICE "TDMoL: Invalid address %s\n", address); ++ return -EINVAL; ++} ++ ++static struct dahdi_dynamic_driver dahdi_dynamic_local = { ++ .owner = THIS_MODULE, ++ .name = "loc", ++ .desc = "Local", ++ .create = dahdi_dynamic_local_create, ++ .destroy = dahdi_dynamic_local_destroy, ++ .transmit = dahdi_dynamic_local_transmit, ++}; ++ ++static int __init dahdi_dynamic_local_init(void) ++{ ++ dahdi_dynamic_register_driver(&dahdi_dynamic_local); ++ return 0; ++} ++ ++static void __exit dahdi_dynamic_local_exit(void) ++{ ++ dahdi_dynamic_unregister_driver(&dahdi_dynamic_local); ++} ++ ++module_init(dahdi_dynamic_local_init); ++module_exit(dahdi_dynamic_local_exit); ++ ++MODULE_LICENSE("GPL v2"); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_echocan_jpah.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_jpah.c +--- linux-source-4.19/drivers/dahdi/dahdi_echocan_jpah.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_jpah.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,144 @@ ++/* ++ * ECHO_CAN_JPAH ++ * ++ * by Jason Parker ++ * ++ * Based upon mg2ec.h - sort of. ++ * This "echo can" will completely hose your audio. ++ * Don't use it unless you're absolutely sure you know what you're doing. ++ * ++ * Copyright (C) 2007-2012, 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 ++#include ++#include ++#include ++ ++#include ++ ++static int debug; ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); ++static const char *name = "JPAH"; ++static const char *ec_name(const struct dahdi_chan *chan) { return name; } ++ ++static const struct dahdi_echocan_factory my_factory = { ++ .get_name = ec_name, ++ .owner = THIS_MODULE, ++ .echocan_create = echo_can_create, ++}; ++ ++static const struct dahdi_echocan_ops my_ops = { ++ .echocan_free = echo_can_free, ++ .echocan_process = echo_can_process, ++ .echocan_traintap = echo_can_traintap, ++}; ++ ++struct ec_pvt { ++ struct dahdi_echocan_state dahdi; ++ int blah; ++}; ++ ++#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) ++{ ++ struct ec_pvt *pvt; ++ ++ if (ecp->param_count > 0) { ++ printk(KERN_WARNING "JPAH does not support parameters; failing request\n"); ++ return -EINVAL; ++ } ++ ++ pvt = kzalloc(sizeof(*pvt), GFP_KERNEL); ++ if (!pvt) ++ return -ENOMEM; ++ ++ pvt->dahdi.ops = &my_ops; ++ ++ *ec = &pvt->dahdi; ++ return 0; ++} ++ ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ kfree(pvt); ++} ++ ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ u32 x; ++ ++ for (x = 0; x < size; x++) { ++ if (pvt->blah < 2) { ++ pvt->blah++; ++ ++ *isig++ = 0; ++ } else { ++ pvt->blah = 0; ++ ++ isig++; ++ } ++ } ++} ++ ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) ++{ ++ return 0; ++} ++ ++static int __init mod_init(void) ++{ ++ if (dahdi_register_echocan_factory(&my_factory)) { ++ module_printk(KERN_ERR, "could not register with DAHDI core\n"); ++ ++ return -EPERM; ++ } ++ ++ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", ++ my_factory.get_name(NULL)); ++ ++ return 0; ++} ++ ++static void __exit mod_exit(void) ++{ ++ dahdi_unregister_echocan_factory(&my_factory); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++ ++MODULE_DESCRIPTION("DAHDI Jason Parker Audio Hoser"); ++MODULE_AUTHOR("Jason Parker "); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(mod_init); ++module_exit(mod_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_echocan_kb1.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_kb1.c +--- linux-source-4.19/drivers/dahdi/dahdi_echocan_kb1.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_kb1.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,743 @@ ++/* ++ * ECHO_CAN_KB1 ++ * ++ * by Kris Boutilier ++ * ++ * Based upon mec2.h ++ * ++ * Copyright (C) 2002-2012, Digium, Inc. ++ * ++ * Additional background on the techniques used in this code can be found in: ++ * ++ * Messerschmitt, David; Hedberg, David; Cole, Christopher; Haoui, Amine; ++ * Winship, Peter; "Digital Voice Echo Canceller with a TMS32020," ++ * in Digital Signal Processing Applications with the TMS320 Family, ++ * pp. 415-437, Texas Instruments, Inc., 1986. ++ * ++ * A pdf of which is available by searching on the document title at http://www.ti.com/ ++ * ++ */ ++ ++/* ++ * 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 ++ ++static int debug; ++static int aggressive; ++ ++/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ ++/* #define MEC2_STATS 4000 */ ++ ++/* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */ ++/* #define MEC2_STATS_DETAILED */ ++ ++/* Get optimized routines for math */ ++#include "arith.h" ++ ++/* ++ Important constants for tuning kb1 echo can ++ */ ++ ++/* Convergence (aka. adaptation) speed -- higher means slower */ ++#define DEFAULT_BETA1_I 2048 ++ ++/* Constants for various power computations */ ++#define DEFAULT_SIGMA_LY_I 7 ++#define DEFAULT_SIGMA_LU_I 7 ++#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ ++#define DEFAULT_ALPHA_YT_I 5 ++ ++#define DEFAULT_CUTOFF_I 128 ++ ++/* Define the near-end speech hangover counter: if near-end speech ++ * is declared, hcntr is set equal to hangt (see pg. 432) ++ */ ++#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ ++ ++/* define the residual error suppression threshold */ ++#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ ++ ++/* This is the minimum reference signal power estimate level ++ * that will result in filter adaptation. ++ * If this is too low then background noise will cause the filter ++ * coefficients to constantly be updated. ++ */ ++#define MIN_UPDATE_THRESH_I 4096 ++ ++/* The number of samples used to update coefficients using the ++ * the block update method (M). It should be related back to the ++ * length of the echo can. ++ * ie. it only updates coefficients when (sample number MOD default_m) = 0 ++ * ++ * Getting this wrong may cause an oops. Consider yourself warned! ++ */ ++#define DEFAULT_M 16 /* every 16th sample */ ++ ++/* If AGGRESSIVE supression is enabled, then we start cancelling residual ++ * echos again even while there is potentially the very end of a near-side ++ * signal present. ++ * This defines how many samples of DEFAULT_HANGT can remain before we ++ * kick back in ++ */ ++#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ ++ ++ ++/***************************************************************/ ++/* The following knobs are not implemented in the current code */ ++ ++/* we need a dynamic level of suppression varying with the ratio of the ++ power of the echo to the power of the reference signal this is ++ done so that we have a smoother background. ++ we have a higher suppression when the power ratio is closer to ++ suppr_ceil and reduces logarithmically as we approach suppr_floor. ++ */ ++#define SUPPR_FLOOR -64 ++#define SUPPR_CEIL -24 ++ ++/* in a second departure, we calculate the residual error suppression ++ * as a percentage of the reference signal energy level. The threshold ++ * is defined in terms of dB below the reference signal. ++ */ ++#define RES_SUPR_FACTOR -20 ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++#ifndef FALSE ++#define FALSE 0 ++#endif ++#ifndef TRUE ++#define TRUE (!FALSE) ++#endif ++ ++/* Generic circular buffer definition */ ++typedef struct { ++ /* Pointer to the relative 'start' of the buffer */ ++ int idx_d; ++ /* The absolute size of the buffer */ ++ int size_d; ++ /* The actual sample - twice as large as we need, however we do store values at idx_d and idx_d+size_d */ ++ short *buf_d; ++} echo_can_cb_s; ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); ++static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable); ++static const char *name = "KB1"; ++static const char *ec_name(const struct dahdi_chan *chan) { return name; } ++ ++static const struct dahdi_echocan_factory my_factory = { ++ .get_name = ec_name, ++ .owner = THIS_MODULE, ++ .echocan_create = echo_can_create, ++}; ++ ++static const struct dahdi_echocan_features my_features = { ++ .NLP_toggle = 1, ++}; ++ ++static const struct dahdi_echocan_ops my_ops = { ++ .echocan_free = echo_can_free, ++ .echocan_process = echo_can_process, ++ .echocan_traintap = echo_can_traintap, ++ .echocan_NLP_toggle = echocan_NLP_toggle, ++}; ++ ++struct ec_pvt { ++ struct dahdi_echocan_state dahdi; ++ /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ ++ int id; ++ ++ /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ ++ int i_d; ++ ++ /* Pre-computed constants */ ++ /* ---------------------- */ ++ /* Number of filter coefficents */ ++ int N_d; ++ /* Rate of adaptation of filter */ ++ int beta2_i; ++ ++ /* Accumulators for power computations */ ++ /* ----------------------------------- */ ++ /* reference signal power estimate - aka. Average absolute value of y(k) */ ++ int Ly_i; ++ /* ... */ ++ int Lu_i; ++ ++ /* Accumulators for signal detectors */ ++ /* --------------------------------- */ ++ /* Power estimate of the recent past of the near-end hybrid signal - aka. Short-time average of: 2 x |s(i)| */ ++ int s_tilde_i; ++ /* Power estimate of the recent past of the far-end receive signal - aka. Short-time average of: |y(i)| */ ++ int y_tilde_i; ++ ++ /* Near end speech detection counter - stores Hangover counter time remaining, in samples */ ++ int HCNTR_d; ++ ++ /* Circular buffers and coefficients */ ++ /* --------------------------------- */ ++ /* ... */ ++ int *a_i; ++ /* ... */ ++ short *a_s; ++ /* Reference samples of far-end receive signal */ ++ echo_can_cb_s y_s; ++ /* Reference samples of near-end signal */ ++ echo_can_cb_s s_s; ++ /* Reference samples of near-end signal minus echo estimate */ ++ echo_can_cb_s u_s; ++ /* Reference samples of far-end receive signal used to calculate short-time average */ ++ echo_can_cb_s y_tilde_s; ++ ++ /* Peak far-end receive signal */ ++ /* --------------------------- */ ++ /* Highest y_tilde value in the sample buffer */ ++ short max_y_tilde; ++ /* Index of the sample containing the max_y_tilde value */ ++ int max_y_tilde_pos; ++ ++#ifdef MEC2_STATS ++ /* Storage for performance statistics */ ++ int cntr_nearend_speech_frames; ++ int cntr_residualcorrected_frames; ++ int cntr_residualcorrected_framesskipped; ++ int cntr_coeff_updates; ++ int cntr_coeff_missedupdates; ++ ++ int avg_Lu_i_toolow; ++ int avg_Lu_i_ok; ++#endif ++ unsigned int aggressive:1; ++ int use_nlp; ++}; ++ ++#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) ++ ++static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) ++{ ++ cb->buf_d = (short *)where; ++ cb->idx_d = 0; ++ cb->size_d = len; ++} ++ ++static inline void add_cc_s(echo_can_cb_s *cb, short newval) ++{ ++ /* Can't use modulus because N+M isn't a power of two (generally) */ ++ cb->idx_d--; ++ if (cb->idx_d < (int)0) ++ /* Whoops - the pointer to the 'start' wrapped around so reset it to the top of the buffer */ ++ cb->idx_d += cb->size_d; ++ ++ /* Load two copies into memory */ ++ cb->buf_d[cb->idx_d] = newval; ++ cb->buf_d[cb->idx_d + cb->size_d] = newval; ++} ++ ++static inline short get_cc_s(echo_can_cb_s *cb, int pos) ++{ ++ /* Load two copies into memory */ ++ return cb->buf_d[cb->idx_d + pos]; ++} ++ ++static inline void init_cc(struct ec_pvt *pvt, int N, int maxy, int maxu) ++{ ++ char *ptr = (char *) pvt; ++ unsigned long tmp; ++ ++ /* Double-word align past end of state */ ++ ptr += sizeof(*pvt); ++ tmp = (unsigned long)ptr; ++ tmp += 3; ++ tmp &= ~3L; ++ ptr = (void *)tmp; ++ ++ /* Reset parameters */ ++ pvt->N_d = N; ++ pvt->beta2_i = DEFAULT_BETA1_I; ++ ++ /* Allocate coefficient memory */ ++ pvt->a_i = (int *) ptr; ++ ptr += (sizeof(int) * pvt->N_d); ++ pvt->a_s = (short *) ptr; ++ ptr += (sizeof(short) * pvt->N_d); ++ ++ /* Reset Y circular buffer (short version) */ ++ init_cb_s(&pvt->y_s, maxy, ptr); ++ ptr += (sizeof(short) * (maxy) * 2); ++ ++ /* Reset Sigma circular buffer (short version for FIR filter) */ ++ init_cb_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); ++ ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); ++ ++ init_cb_s(&pvt->u_s, maxu, ptr); ++ ptr += (sizeof(short) * maxu * 2); ++ ++ /* Allocate a buffer for the reference signal power computation */ ++ init_cb_s(&pvt->y_tilde_s, pvt->N_d, ptr); ++ ++ /* Reset the absolute time index */ ++ pvt->i_d = (int)0; ++ ++ /* Reset the power computations (for y and u) */ ++ pvt->Ly_i = DEFAULT_CUTOFF_I; ++ pvt->Lu_i = DEFAULT_CUTOFF_I; ++ ++#ifdef MEC2_STATS ++ /* set the identity */ ++ pvt->id = (int)&ptr; ++ ++ /* Reset performance stats */ ++ pvt->cntr_nearend_speech_frames = (int)0; ++ pvt->cntr_residualcorrected_frames = (int)0; ++ pvt->cntr_residualcorrected_framesskipped = (int)0; ++ pvt->cntr_coeff_updates = (int)0; ++ pvt->cntr_coeff_missedupdates = (int)0; ++ ++ pvt->avg_Lu_i_toolow = (int)0; ++ pvt->avg_Lu_i_ok = (int)0; ++#endif ++ ++ /* Reset the near-end speech detector */ ++ pvt->s_tilde_i = (int)0; ++ pvt->y_tilde_i = (int)0; ++ pvt->HCNTR_d = (int)0; ++ ++} ++ ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ kfree(pvt); ++} ++ ++static inline short sample_update(struct ec_pvt *pvt, short iref, short isig) ++{ ++ /* Declare local variables that are used more than once */ ++ /* ... */ ++ int k; ++ /* ... */ ++ int rs; ++ /* ... */ ++ short u; ++ /* ... */ ++ int Py_i; ++ /* ... */ ++ int two_beta_i; ++ ++ /* flow A on pg. 428 */ ++ /* eq. (16): high-pass filter the input to generate the next value; ++ * push the current value into the circular buffer ++ * ++ * sdc_im1_d = sdc_d; ++ * sdc_d = sig; ++ * s_i_d = sdc_d; ++ * s_d = s_i_d; ++ * s_i_d = (float)(1.0 - gamma_d) * s_i_d ++ * + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); ++ */ ++ ++ /* Update the Far-end receive signal circular buffers and accumulators */ ++ /* ------------------------------------------------------------------- */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->y_tilde_i -= abs(get_cc_s(&pvt->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1)) >> DEFAULT_ALPHA_YT_I; ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_ST_I; ++ /* Push a copy of the new sample into its circular buffer */ ++ add_cc_s(&pvt->y_s, iref); ++ ++ ++ /* eq. (2): compute r in fixed-point */ ++ rs = CONVOLVE2(pvt->a_s, ++ pvt->y_s.buf_d + pvt->y_s.idx_d, ++ pvt->N_d); ++ rs >>= 15; ++ ++ /* eq. (3): compute the output value (see figure 3) and the error ++ * note: the error is the same as the output signal when near-end ++ * speech is not present ++ */ ++ u = isig - rs; ++ ++ /* Push a copy of the output value sample into its circular buffer */ ++ add_cc_s(&pvt->u_s, u); ++ ++ ++ /* Update the Near-end hybrid signal circular buffers and accumulators */ ++ /* ------------------------------------------------------------------- */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->s_tilde_i -= abs(get_cc_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1)); ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->s_tilde_i += abs(isig); ++ /* Push a copy of the new sample into it's circular buffer */ ++ add_cc_s(&pvt->s_s, isig); ++ ++ ++ /* Push a copy of the current short-time average of the far-end receive signal into it's circular buffer */ ++ add_cc_s(&pvt->y_tilde_s, pvt->y_tilde_i); ++ ++ /* flow B on pg. 428 */ ++ ++ /* If the hangover timer isn't running then compute the new convergence factor, otherwise set Py_i to 32768 */ ++ if (!pvt->HCNTR_d) { ++ Py_i = (pvt->Ly_i >> DEFAULT_SIGMA_LY_I) * (pvt->Ly_i >> DEFAULT_SIGMA_LY_I); ++ Py_i >>= 15; ++ } else { ++ Py_i = (1 << 15); ++ } ++ ++#if 0 ++ /* Vary rate of adaptation depending on position in the file ++ * Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech ++ * has begun of the file to allow the echo cancellor to estimate the ++ * channel accurately ++ * Still needs conversion! ++ */ ++ ++ if (pvt->start_speech_d != 0) { ++ if (pvt->i_d > (DEFAULT_T0 + pvt->start_speech_d)*(SAMPLE_FREQ)) { ++ pvt->beta2_d = max_cc_float(MIN_BETA, DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((pvt->i_d/(float)SAMPLE_FREQ) - DEFAULT_T0 - pvt->start_speech_d))); ++ } ++ } else { ++ pvt->beta2_d = DEFAULT_BETA1; ++ } ++#endif ++ ++ /* Fixed point, inverted */ ++ pvt->beta2_i = DEFAULT_BETA1_I; ++ ++ /* Fixed point version, inverted */ ++ two_beta_i = (pvt->beta2_i * Py_i) >> 15; ++ if (!two_beta_i) ++ two_beta_i++; ++ ++ /* Update the Suppressed signal power estimate accumulator */ ++ /* ------------------------------------------------------- */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->Lu_i -= abs(get_cc_s(&pvt->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1)); ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->Lu_i += abs(u); ++ ++ /* Update the Far-end reference signal power estimate accumulator */ ++ /* -------------------------------------------------------------- */ ++ /* eq. (10): update power estimate of the reference */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->Ly_i -= abs(get_cc_s(&pvt->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->Ly_i += abs(iref); ++ ++ if (pvt->Ly_i < DEFAULT_CUTOFF_I) ++ pvt->Ly_i = DEFAULT_CUTOFF_I; ++ ++ ++ /* Update the Peak far-end receive signal detected */ ++ /* ----------------------------------------------- */ ++ if (pvt->y_tilde_i > pvt->max_y_tilde) { ++ /* New highest y_tilde with full life */ ++ pvt->max_y_tilde = pvt->y_tilde_i; ++ pvt->max_y_tilde_pos = pvt->N_d - 1; ++ } else if (--pvt->max_y_tilde_pos < 0) { ++ /* Time to find new max y tilde... */ ++ pvt->max_y_tilde = MAX16(pvt->y_tilde_s.buf_d + pvt->y_tilde_s.idx_d, pvt->N_d, &pvt->max_y_tilde_pos); ++ } ++ ++ /* Determine if near end speech was detected in this sample */ ++ /* -------------------------------------------------------- */ ++ if (((pvt->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > pvt->max_y_tilde) ++ && (pvt->max_y_tilde > 0)) { ++ /* Then start the Hangover counter */ ++ pvt->HCNTR_d = DEFAULT_HANGT; ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", pvt->s_tilde_i, (pvt->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), pvt->max_y_tilde); ++#endif ++#ifdef MEC2_STATS ++ ++pvt->cntr_nearend_speech_frames; ++#endif ++ } else if (pvt->HCNTR_d > (int)0) { ++ /* otherwise, if it's still non-zero, decrement the Hangover counter by one sample */ ++#ifdef MEC2_STATS ++ ++pvt->cntr_nearend_speech_frames; ++#endif ++ pvt->HCNTR_d--; ++ } ++ ++ /* Update coefficients if no near-end speech in this sample (ie. HCNTR_d = 0) ++ * and we have enough signal to bother trying to update. ++ * -------------------------------------------------------------------------- ++ */ ++ if (!pvt->HCNTR_d && /* no near-end speech present */ ++ !(pvt->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */ ++ if (pvt->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */ ++ /* so loop over all the filter coefficients */ ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "updating coefficients with: pvt->Lu_i %9d\n", pvt->Lu_i); ++#endif ++#ifdef MEC2_STATS ++ pvt->avg_Lu_i_ok = pvt->avg_Lu_i_ok + pvt->Lu_i; ++ ++pvt->cntr_coeff_updates; ++#endif ++ for (k = 0; k < pvt->N_d; k++) { ++ /* eq. (7): compute an expectation over M_d samples */ ++ int grad2; ++ grad2 = CONVOLVE2(pvt->u_s.buf_d + pvt->u_s.idx_d, ++ pvt->y_s.buf_d + pvt->y_s.idx_d + k, ++ DEFAULT_M); ++ /* eq. (7): update the coefficient */ ++ pvt->a_i[k] += grad2 / two_beta_i; ++ pvt->a_s[k] = pvt->a_i[k] >> 16; ++ } ++ } else { ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "insufficient signal to update coefficients pvt->Lu_i %5d < %5d\n", pvt->Lu_i, MIN_UPDATE_THRESH_I); ++#endif ++#ifdef MEC2_STATS ++ pvt->avg_Lu_i_toolow = pvt->avg_Lu_i_toolow + pvt->Lu_i; ++ ++pvt->cntr_coeff_missedupdates; ++#endif ++ } ++ } ++ ++ /* paragraph below eq. (15): if no near-end speech in the sample and ++ * the reference signal power estimate > cutoff threshold ++ * then perform residual error suppression ++ */ ++#ifdef MEC2_STATS_DETAILED ++ if (pvt->HCNTR_d == 0) ++ printk(KERN_INFO "possibly correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d and expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); ++#endif ++ ++#ifndef NO_ECHO_SUPPRESSOR ++ if (pvt->use_nlp) { ++ if (pvt->aggressive) { ++ if ((pvt->HCNTR_d < AGGRESSIVE_HCNTR) && (pvt->Ly_i > (pvt->Lu_i << 1))) { ++ for (k = 0; k < 2; k++) { ++ u = u * (pvt->Lu_i >> DEFAULT_SIGMA_LU_I) / ((pvt->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); ++ } ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "aggresively correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); ++#endif ++#ifdef MEC2_STATS ++ ++pvt->cntr_residualcorrected_frames; ++#endif ++ } ++ } else { ++ if (pvt->HCNTR_d == 0) { ++ if ((pvt->Ly_i/(pvt->Lu_i + 1)) > DEFAULT_SUPPR_I) { ++ for (k = 0; k < 1; k++) { ++ u = u * (pvt->Lu_i >> DEFAULT_SIGMA_LU_I) / ((pvt->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); ++ } ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); ++#endif ++#ifdef MEC2_STATS ++ ++pvt->cntr_residualcorrected_frames; ++#endif ++ } ++#ifdef MEC2_STATS ++ else { ++ ++pvt->cntr_residualcorrected_framesskipped; ++ } ++#endif ++ } ++ } ++ } ++#endif ++ ++#if 0 ++ /* This will generate a non-linear supression factor, once converted */ ++ if ((pvt->HCNTR_d == 0) && ++ ((pvt->Lu_d/pvt->Ly_d) < DEFAULT_SUPPR) && ++ (pvt->Lu_d/pvt->Ly_d > EC_MIN_DB_VALUE)) { ++ suppr_factor = (10 / (float)(SUPPR_FLOOR - SUPPR_CEIL)) * log(pvt->Lu_d/pvt->Ly_d) ++ - SUPPR_CEIL / (float)(SUPPR_FLOOR - SUPPR_CEIL); ++ u_suppr = pow(10.0, (suppr_factor) * RES_SUPR_FACTOR / 10.0) * u_suppr; ++ } ++#endif ++ ++#ifdef MEC2_STATS ++ /* Periodically dump performance stats */ ++ if ((pvt->i_d % MEC2_STATS) == 0) { ++ /* make sure to avoid div0's! */ ++ if (pvt->cntr_coeff_missedupdates > 0) ++ pvt->avg_Lu_i_toolow = (int)(pvt->avg_Lu_i_toolow / pvt->cntr_coeff_missedupdates); ++ else ++ pvt->avg_Lu_i_toolow = -1; ++ ++ if (pvt->cntr_coeff_updates > 0) ++ pvt->avg_Lu_i_ok = (pvt->avg_Lu_i_ok / pvt->cntr_coeff_updates); ++ else ++ pvt->avg_Lu_i_ok = -1; ++ ++ printk( KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n", ++ pvt->id, ++ pvt->cntr_nearend_speech_frames, ++ pvt->cntr_residualcorrected_frames, pvt->cntr_residualcorrected_framesskipped, ++ pvt->cntr_coeff_updates, pvt->cntr_coeff_missedupdates, ++ pvt->avg_Lu_i_ok, pvt->avg_Lu_i_toolow); ++ ++ pvt->cntr_nearend_speech_frames = 0; ++ pvt->cntr_residualcorrected_frames = 0; ++ pvt->cntr_residualcorrected_framesskipped = 0; ++ pvt->cntr_coeff_updates = 0; ++ pvt->cntr_coeff_missedupdates = 0; ++ pvt->avg_Lu_i_ok = 0; ++ pvt->avg_Lu_i_toolow = 0; ++ } ++#endif ++ ++ /* Increment the sample index and return the corrected sample */ ++ pvt->i_d++; ++ return u; ++} ++ ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ u32 x; ++ short result; ++ ++ for (x = 0; x < size; x++) { ++ result = sample_update(pvt, *iref, *isig); ++ *isig++ = result; ++ ++iref; ++ } ++} ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) ++{ ++ int maxy; ++ int maxu; ++ size_t size; ++ unsigned int x; ++ char *c; ++ struct ec_pvt *pvt; ++ ++ maxy = ecp->tap_length + DEFAULT_M; ++ maxu = DEFAULT_M; ++ if (maxy < (1 << DEFAULT_ALPHA_YT_I)) ++ maxy = (1 << DEFAULT_ALPHA_YT_I); ++ if (maxy < (1 << DEFAULT_SIGMA_LY_I)) ++ maxy = (1 << DEFAULT_SIGMA_LY_I); ++ if (maxu < (1 << DEFAULT_SIGMA_LU_I)) ++ maxu = (1 << DEFAULT_SIGMA_LU_I); ++ ++ size = sizeof(*ec) + ++ 4 + /* align */ ++ sizeof(int) * ecp->tap_length + /* a_i */ ++ sizeof(short) * ecp->tap_length + /* a_s */ ++ 2 * sizeof(short) * (maxy) + /* y_s */ ++ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ ++ 2 * sizeof(short) * (maxu) + /* u_s */ ++ 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ ++ ++ pvt = kzalloc(size, GFP_KERNEL); ++ if (!pvt) ++ return -ENOMEM; ++ ++ pvt->dahdi.ops = &my_ops; ++ ++ pvt->aggressive = aggressive; ++ pvt->dahdi.features = my_features; ++ ++ for (x = 0; x < ecp->param_count; x++) { ++ for (c = p[x].name; *c; c++) ++ *c = tolower(*c); ++ if (!strcmp(p[x].name, "aggressive")) { ++ pvt->aggressive = p[x].value ? 1 : 0; ++ } else { ++ printk(KERN_WARNING "Unknown parameter supplied to KB1 echo canceler: '%s'\n", p[x].name); ++ kfree(pvt); ++ ++ return -EINVAL; ++ } ++ } ++ ++ init_cc(pvt, ecp->tap_length, maxy, maxu); ++ /* Non-linear processor - a fancy way to say "zap small signals, to avoid ++ accumulating noise". */ ++ pvt->use_nlp = TRUE; ++ ++ *ec = &pvt->dahdi; ++ return 0; ++} ++ ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ /* Set the hangover counter to the length of the can to ++ * avoid adjustments occuring immediately after initial forced training ++ */ ++ pvt->HCNTR_d = pvt->N_d << 1; ++ ++ if (pos >= pvt->N_d) ++ return 1; ++ ++ pvt->a_i[pos] = val << 17; ++ pvt->a_s[pos] = val << 1; ++ ++ if (++pos >= pvt->N_d) ++ return 1; ++ ++ return 0; ++} ++ ++static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ pvt->use_nlp = enable ? 1 : 0; ++} ++ ++static int __init mod_init(void) ++{ ++ if (dahdi_register_echocan_factory(&my_factory)) { ++ module_printk(KERN_ERR, "could not register with DAHDI core\n"); ++ ++ return -EPERM; ++ } ++ ++ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", ++ my_factory.get_name(NULL)); ++ ++ return 0; ++} ++ ++static void __exit mod_exit(void) ++{ ++ dahdi_unregister_echocan_factory(&my_factory); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++module_param(aggressive, int, S_IRUGO | S_IWUSR); ++ ++MODULE_DESCRIPTION("DAHDI 'KB1' Echo Canceler"); ++MODULE_AUTHOR("Kris Boutilier"); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(mod_init); ++module_exit(mod_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_echocan_mg2.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_mg2.c +--- linux-source-4.19/drivers/dahdi/dahdi_echocan_mg2.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_mg2.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,890 @@ ++/* ++ * ECHO_CAN_MG2 ++ * ++ * by Michael Gernoth ++ * ++ * Based upon kb1ec.h and mec2.h ++ * ++ * Copyright (C) 2002-2012, Digium, Inc. ++ * ++ * Additional background on the techniques used in this code can be found in: ++ * ++ * Messerschmitt, David; Hedberg, David; Cole, Christopher; Haoui, Amine; ++ * Winship, Peter; "Digital Voice Echo Canceller with a TMS32020," ++ * in Digital Signal Processing Applications with the TMS320 Family, ++ * pp. 415-437, Texas Instruments, Inc., 1986. ++ * ++ * A pdf of which is available by searching on the document title at http://www.ti.com/ ++ * ++ */ ++ ++/* ++ * 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 ++ ++static int debug; ++static int aggressive; ++ ++#define ABS(a) abs(a!=-32768?a:-32767) ++ ++#define RESTORE_COEFFS {\ ++ int x;\ ++ memcpy(pvt->a_i, pvt->c_i, pvt->N_d*sizeof(int));\ ++ for (x = 0; x < pvt->N_d; x++) {\ ++ pvt->a_s[x] = pvt->a_i[x] >> 16;\ ++ }\ ++ pvt->backup = BACKUP;\ ++ } ++ ++/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ ++/* #define MEC2_STATS 4000 */ ++ ++/* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */ ++/* #define MEC2_STATS_DETAILED */ ++ ++/* Uncomment to generate per-call DC bias offset messages */ ++/* #define MEC2_DCBIAS_MESSAGE */ ++ ++/* Get optimized routines for math */ ++#include "arith.h" ++ ++/* ++ Important constants for tuning mg2 echo can ++ */ ++ ++/* Convergence (aka. adaptation) speed -- higher means slower */ ++#define DEFAULT_BETA1_I 2048 ++ ++/* Constants for various power computations */ ++#define DEFAULT_SIGMA_LY_I 7 ++#define DEFAULT_SIGMA_LU_I 7 ++#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ ++#define DEFAULT_ALPHA_YT_I 5 ++ ++#define DEFAULT_CUTOFF_I 128 ++ ++/* Define the near-end speech hangover counter: if near-end speech ++ * is declared, hcntr is set equal to hangt (see pg. 432) ++ */ ++#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ ++ ++/* define the residual error suppression threshold */ ++#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ ++ ++/* This is the minimum reference signal power estimate level ++ * that will result in filter adaptation. ++ * If this is too low then background noise will cause the filter ++ * coefficients to constantly be updated. ++ */ ++#define MIN_UPDATE_THRESH_I 2048 ++ ++/* The number of samples used to update coefficients using the ++ * the block update method (M). It should be related back to the ++ * length of the echo can. ++ * ie. it only updates coefficients when (sample number MOD default_m) = 0 ++ * ++ * Getting this wrong may cause an oops. Consider yourself warned! ++ */ ++#define DEFAULT_M 16 /* every 16th sample */ ++ ++/* If AGGRESSIVE supression is enabled, then we start cancelling residual ++ * echos again even while there is potentially the very end of a near-side ++ * signal present. ++ * This defines how many samples of DEFAULT_HANGT can remain before we ++ * kick back in ++ */ ++#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ ++ ++/* Treat sample as error if it has a different sign as the ++ * input signal and is this number larger in ABS() as ++ * the input-signal */ ++#define MAX_SIGN_ERROR 3000 ++ ++/* Number of coefficients really used for calculating the ++ * simulated echo. The value specifies how many of the ++ * biggest coefficients are used for calculating rs. ++ * This helps on long echo-tails by artificially limiting ++ * the number of coefficients for the calculation and ++ * preventing overflows. ++ * Comment this to deactivate the code */ ++#define USED_COEFFS 64 ++ ++/* Backup coefficients every this number of samples */ ++#define BACKUP 256 ++ ++/***************************************************************/ ++/* The following knobs are not implemented in the current code */ ++ ++/* we need a dynamic level of suppression varying with the ratio of the ++ power of the echo to the power of the reference signal this is ++ done so that we have a smoother background. ++ we have a higher suppression when the power ratio is closer to ++ suppr_ceil and reduces logarithmically as we approach suppr_floor. ++ */ ++#define SUPPR_FLOOR -64 ++#define SUPPR_CEIL -24 ++ ++/* in a second departure, we calculate the residual error suppression ++ * as a percentage of the reference signal energy level. The threshold ++ * is defined in terms of dB below the reference signal. ++ */ ++#define RES_SUPR_FACTOR -20 ++ ++#define DC_NORMALIZE ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++#ifndef FALSE ++#define FALSE 0 ++#endif ++#ifndef TRUE ++#define TRUE (!FALSE) ++#endif ++ ++/* Generic circular buffer definition */ ++typedef struct { ++ /* Pointer to the relative 'start' of the buffer */ ++ int idx_d; ++ /* The absolute size of the buffer */ ++ int size_d; ++ /* The actual sample - twice as large as we need, however we do store values at idx_d and idx_d+size_d */ ++ short *buf_d; ++} echo_can_cb_s; ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); ++static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable); ++static const char *name = "MG2"; ++static const char *ec_name(const struct dahdi_chan *chan) { return name; } ++ ++static const struct dahdi_echocan_factory my_factory = { ++ .get_name = ec_name, ++ .owner = THIS_MODULE, ++ .echocan_create = echo_can_create, ++}; ++ ++static const struct dahdi_echocan_features my_features = { ++ .NLP_toggle = 1, ++}; ++ ++static const struct dahdi_echocan_ops my_ops = { ++ .echocan_free = echo_can_free, ++ .echocan_process = echo_can_process, ++ .echocan_traintap = echo_can_traintap, ++ .echocan_NLP_toggle = echocan_NLP_toggle, ++}; ++ ++struct ec_pvt { ++ struct dahdi_echocan_state dahdi; ++ /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ ++ int id; ++ ++ /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ ++ int i_d; ++ ++ /* Pre-computed constants */ ++ /* ---------------------- */ ++ /* Number of filter coefficents */ ++ int N_d; ++ /* Rate of adaptation of filter */ ++ int beta2_i; ++ ++ /* Accumulators for power computations */ ++ /* ----------------------------------- */ ++ /* reference signal power estimate - aka. Average absolute value of y(k) */ ++ int Ly_i; ++ /* ... */ ++ int Lu_i; ++ ++ /* Accumulators for signal detectors */ ++ /* --------------------------------- */ ++ /* Power estimate of the recent past of the near-end hybrid signal - aka. Short-time average of: 2 x |s(i)| */ ++ int s_tilde_i; ++ /* Power estimate of the recent past of the far-end receive signal - aka. Short-time average of: |y(i)| */ ++ int y_tilde_i; ++ ++ /* Near end speech detection counter - stores Hangover counter time remaining, in samples */ ++ int HCNTR_d; ++ ++ /* Circular buffers and coefficients */ ++ /* --------------------------------- */ ++ /* ... */ ++ int *a_i; ++ /* ... */ ++ short *a_s; ++ /* Backups */ ++ int *b_i; ++ int *c_i; ++ /* Reference samples of far-end receive signal */ ++ echo_can_cb_s y_s; ++ /* Reference samples of near-end signal */ ++ echo_can_cb_s s_s; ++ /* Reference samples of near-end signal minus echo estimate */ ++ echo_can_cb_s u_s; ++ /* Reference samples of far-end receive signal used to calculate short-time average */ ++ echo_can_cb_s y_tilde_s; ++ ++ /* Peak far-end receive signal */ ++ /* --------------------------- */ ++ /* Highest y_tilde value in the sample buffer */ ++ short max_y_tilde; ++ /* Index of the sample containing the max_y_tilde value */ ++ int max_y_tilde_pos; ++ ++#ifdef MEC2_STATS ++ /* Storage for performance statistics */ ++ int cntr_nearend_speech_frames; ++ int cntr_residualcorrected_frames; ++ int cntr_residualcorrected_framesskipped; ++ int cntr_coeff_updates; ++ int cntr_coeff_missedupdates; ++ ++ int avg_Lu_i_toolow; ++ int avg_Lu_i_ok; ++#endif ++ unsigned int aggressive:1; ++ short lastsig; ++ int lastcount; ++ int backup; ++#ifdef DC_NORMALIZE ++ int dc_estimate; ++#endif ++ int use_nlp; ++}; ++ ++#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) ++ ++static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) ++{ ++ cb->buf_d = (short *)where; ++ cb->idx_d = 0; ++ cb->size_d = len; ++} ++ ++static inline void add_cc_s(echo_can_cb_s *cb, short newval) ++{ ++ /* Can't use modulus because N+M isn't a power of two (generally) */ ++ cb->idx_d--; ++ if (cb->idx_d < (int)0) ++ /* Whoops - the pointer to the 'start' wrapped around so reset it to the top of the buffer */ ++ cb->idx_d += cb->size_d; ++ ++ /* Load two copies into memory */ ++ cb->buf_d[cb->idx_d] = newval; ++ cb->buf_d[cb->idx_d + cb->size_d] = newval; ++} ++ ++static inline short get_cc_s(echo_can_cb_s *cb, int pos) ++{ ++ /* Load two copies into memory */ ++ return cb->buf_d[cb->idx_d + pos]; ++} ++ ++static inline void init_cc(struct ec_pvt *pvt, int N, int maxy, int maxu) ++{ ++ char *ptr = (char *) pvt; ++ unsigned long tmp; ++ ++ /* Double-word align past end of state */ ++ ptr += sizeof(*pvt); ++ tmp = (unsigned long)ptr; ++ tmp += 3; ++ tmp &= ~3L; ++ ptr = (void *)tmp; ++ ++ /* Reset parameters */ ++ pvt->N_d = N; ++ pvt->beta2_i = DEFAULT_BETA1_I; ++ ++ /* Allocate coefficient memory */ ++ pvt->a_i = (int *) ptr; ++ ptr += (sizeof(int) * pvt->N_d); ++ pvt->a_s = (short *) ptr; ++ ptr += (sizeof(short) * pvt->N_d); ++ ++ /* Allocate backup memory */ ++ pvt->b_i = (int *) ptr; ++ ptr += (sizeof(int) * pvt->N_d); ++ pvt->c_i = (int *) ptr; ++ ptr += (sizeof(int) * pvt->N_d); ++ ++ /* Reset Y circular buffer (short version) */ ++ init_cb_s(&pvt->y_s, maxy, ptr); ++ ptr += (sizeof(short) * (maxy) * 2); ++ ++ /* Reset Sigma circular buffer (short version for FIR filter) */ ++ init_cb_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); ++ ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); ++ ++ init_cb_s(&pvt->u_s, maxu, ptr); ++ ptr += (sizeof(short) * maxu * 2); ++ ++ /* Allocate a buffer for the reference signal power computation */ ++ init_cb_s(&pvt->y_tilde_s, pvt->N_d, ptr); ++ ++ /* Reset the absolute time index */ ++ pvt->i_d = (int)0; ++ ++ /* Reset the power computations (for y and u) */ ++ pvt->Ly_i = DEFAULT_CUTOFF_I; ++ pvt->Lu_i = DEFAULT_CUTOFF_I; ++ ++#ifdef MEC2_STATS ++ /* set the identity */ ++ pvt->id = (int)&ptr; ++ ++ /* Reset performance stats */ ++ pvt->cntr_nearend_speech_frames = (int)0; ++ pvt->cntr_residualcorrected_frames = (int)0; ++ pvt->cntr_residualcorrected_framesskipped = (int)0; ++ pvt->cntr_coeff_updates = (int)0; ++ pvt->cntr_coeff_missedupdates = (int)0; ++ ++ pvt->avg_Lu_i_toolow = (int)0; ++ pvt->avg_Lu_i_ok = (int)0; ++#endif ++ ++ /* Reset the near-end speech detector */ ++ pvt->s_tilde_i = (int)0; ++ pvt->y_tilde_i = (int)0; ++ pvt->HCNTR_d = (int)0; ++ ++} ++ ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++#if defined(DC_NORMALIZE) && defined(MEC2_DCBIAS_MESSAGE) ++ printk(KERN_INFO "EC: DC bias calculated: %d V\n", pvt->dc_estimate >> 15); ++#endif ++ kfree(pvt); ++} ++ ++#ifdef DC_NORMALIZE ++static inline short dc_removal(int *dc_estimate, short samp) ++{ ++ *dc_estimate += ((((int)samp << 15) - *dc_estimate) >> 9); ++ return samp - (*dc_estimate >> 15); ++} ++#endif ++ ++static inline short sample_update(struct ec_pvt *pvt, short iref, short isig) ++{ ++ /* Declare local variables that are used more than once */ ++ /* ... */ ++ int k; ++ /* ... */ ++ int rs; ++ /* ... */ ++ short u; ++ /* ... */ ++ int Py_i; ++ /* ... */ ++ int two_beta_i; ++ ++#ifdef DC_NORMALIZE ++ isig = dc_removal(&pvt->dc_estimate, isig); ++#endif ++ ++ /* flow A on pg. 428 */ ++ /* eq. (16): high-pass filter the input to generate the next value; ++ * push the current value into the circular buffer ++ * ++ * sdc_im1_d = sdc_d; ++ * sdc_d = sig; ++ * s_i_d = sdc_d; ++ * s_d = s_i_d; ++ * s_i_d = (float)(1.0 - gamma_d) * s_i_d ++ * + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); ++ */ ++ ++ /* Update the Far-end receive signal circular buffers and accumulators */ ++ /* ------------------------------------------------------------------- */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->y_tilde_i -= abs(get_cc_s(&pvt->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1)) >> DEFAULT_ALPHA_YT_I; ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_ST_I; ++ /* Push a copy of the new sample into its circular buffer */ ++ add_cc_s(&pvt->y_s, iref); ++ ++ ++ /* eq. (2): compute r in fixed-point */ ++ rs = CONVOLVE2(pvt->a_s, ++ pvt->y_s.buf_d + pvt->y_s.idx_d, ++ pvt->N_d); ++ rs >>= 15; ++ ++ if (pvt->lastsig == isig) { ++ pvt->lastcount++; ++ } else { ++ pvt->lastcount = 0; ++ pvt->lastsig = isig; ++ } ++ ++ if (isig == 0) { ++ u = 0; ++ } else if (pvt->lastcount > 255) { ++ /* We have seen the same input-signal more than 255 times, ++ * we should pass it through uncancelled, as we are likely on hold */ ++ u = isig; ++ } else { ++ int sign_error; ++ ++ if (rs < -32768) { ++ rs = -32768; ++ pvt->HCNTR_d = DEFAULT_HANGT; ++ RESTORE_COEFFS; ++ } else if (rs > 32767) { ++ rs = 32767; ++ pvt->HCNTR_d = DEFAULT_HANGT; ++ RESTORE_COEFFS; ++ } ++ ++ sign_error = ABS(rs) - ABS(isig); ++ ++ if (ABS(sign_error) > MAX_SIGN_ERROR) ++ { ++ rs = 0; ++ RESTORE_COEFFS; ++ } ++ ++ /* eq. (3): compute the output value (see figure 3) and the error ++ * note: the error is the same as the output signal when near-end ++ * speech is not present ++ */ ++ u = isig - rs; ++ ++ if (u / isig < 0) ++ u = isig - (rs >> 1); ++ } ++ ++ /* Push a copy of the output value sample into its circular buffer */ ++ add_cc_s(&pvt->u_s, u); ++ ++ if (!pvt->backup) { ++ /* Backup coefficients periodically */ ++ pvt->backup = BACKUP; ++ memcpy(pvt->c_i, pvt->b_i, pvt->N_d*sizeof(int)); ++ memcpy(pvt->b_i, pvt->a_i, pvt->N_d*sizeof(int)); ++ } else ++ pvt->backup--; ++ ++ ++ /* Update the Near-end hybrid signal circular buffers and accumulators */ ++ /* ------------------------------------------------------------------- */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->s_tilde_i -= abs(get_cc_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1)); ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->s_tilde_i += abs(isig); ++ /* Push a copy of the new sample into it's circular buffer */ ++ add_cc_s(&pvt->s_s, isig); ++ ++ ++ /* Push a copy of the current short-time average of the far-end receive signal into it's circular buffer */ ++ add_cc_s(&pvt->y_tilde_s, pvt->y_tilde_i); ++ ++ /* flow B on pg. 428 */ ++ ++ /* If the hangover timer isn't running then compute the new convergence factor, otherwise set Py_i to 32768 */ ++ if (!pvt->HCNTR_d) { ++ Py_i = (pvt->Ly_i >> DEFAULT_SIGMA_LY_I) * (pvt->Ly_i >> DEFAULT_SIGMA_LY_I); ++ Py_i >>= 15; ++ } else { ++ Py_i = (1 << 15); ++ } ++ ++#if 0 ++ /* Vary rate of adaptation depending on position in the file ++ * Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech ++ * has begun of the file to allow the echo cancellor to estimate the ++ * channel accurately ++ * Still needs conversion! ++ */ ++ ++ if (pvt->start_speech_d != 0) { ++ if (pvt->i_d > (DEFAULT_T0 + pvt->start_speech_d)*(SAMPLE_FREQ)) { ++ pvt->beta2_d = max_cc_float(MIN_BETA, DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((pvt->i_d/(float)SAMPLE_FREQ) - DEFAULT_T0 - pvt->start_speech_d))); ++ } ++ } else { ++ pvt->beta2_d = DEFAULT_BETA1; ++ } ++#endif ++ ++ /* Fixed point, inverted */ ++ pvt->beta2_i = DEFAULT_BETA1_I; ++ ++ /* Fixed point version, inverted */ ++ two_beta_i = (pvt->beta2_i * Py_i) >> 15; ++ if (!two_beta_i) ++ two_beta_i++; ++ ++ /* Update the Suppressed signal power estimate accumulator */ ++ /* ------------------------------------------------------- */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->Lu_i -= abs(get_cc_s(&pvt->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1)); ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->Lu_i += abs(u); ++ ++ /* Update the Far-end reference signal power estimate accumulator */ ++ /* -------------------------------------------------------------- */ ++ /* eq. (10): update power estimate of the reference */ ++ /* Delete the oldest sample from the power estimate accumulator */ ++ pvt->Ly_i -= abs(get_cc_s(&pvt->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; ++ /* Add the new sample to the power estimate accumulator */ ++ pvt->Ly_i += abs(iref); ++ ++ if (pvt->Ly_i < DEFAULT_CUTOFF_I) ++ pvt->Ly_i = DEFAULT_CUTOFF_I; ++ ++ ++ /* Update the Peak far-end receive signal detected */ ++ /* ----------------------------------------------- */ ++ if (pvt->y_tilde_i > pvt->max_y_tilde) { ++ /* New highest y_tilde with full life */ ++ pvt->max_y_tilde = pvt->y_tilde_i; ++ pvt->max_y_tilde_pos = pvt->N_d - 1; ++ } else if (--pvt->max_y_tilde_pos < 0) { ++ /* Time to find new max y tilde... */ ++ pvt->max_y_tilde = MAX16(pvt->y_tilde_s.buf_d + pvt->y_tilde_s.idx_d, pvt->N_d, &pvt->max_y_tilde_pos); ++ } ++ ++ /* Determine if near end speech was detected in this sample */ ++ /* -------------------------------------------------------- */ ++ if (((pvt->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > pvt->max_y_tilde) ++ && (pvt->max_y_tilde > 0)) { ++ /* Then start the Hangover counter */ ++ pvt->HCNTR_d = DEFAULT_HANGT; ++ RESTORE_COEFFS; ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", pvt->s_tilde_i, (pvt->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), pvt->max_y_tilde); ++#endif ++#ifdef MEC2_STATS ++ ++pvt->cntr_nearend_speech_frames; ++#endif ++ } else if (pvt->HCNTR_d > (int)0) { ++ /* otherwise, if it's still non-zero, decrement the Hangover counter by one sample */ ++#ifdef MEC2_STATS ++ ++pvt->cntr_nearend_speech_frames; ++#endif ++ pvt->HCNTR_d--; ++ } ++ ++ /* Update coefficients if no near-end speech in this sample (ie. HCNTR_d = 0) ++ * and we have enough signal to bother trying to update. ++ * -------------------------------------------------------------------------- ++ */ ++ if (!pvt->HCNTR_d && /* no near-end speech present */ ++ !(pvt->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */ ++ if (pvt->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */ ++ /* so loop over all the filter coefficients */ ++#ifdef USED_COEFFS ++ int max_coeffs[USED_COEFFS]; ++ int *pos; ++ ++ if (pvt->N_d > USED_COEFFS) ++ memset(max_coeffs, 0, USED_COEFFS*sizeof(int)); ++#endif ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "updating coefficients with: pvt->Lu_i %9d\n", pvt->Lu_i); ++#endif ++#ifdef MEC2_STATS ++ pvt->avg_Lu_i_ok = pvt->avg_Lu_i_ok + pvt->Lu_i; ++ ++pvt->cntr_coeff_updates; ++#endif ++ for (k = 0; k < pvt->N_d; k++) { ++ /* eq. (7): compute an expectation over M_d samples */ ++ int grad2; ++ grad2 = CONVOLVE2(pvt->u_s.buf_d + pvt->u_s.idx_d, ++ pvt->y_s.buf_d + pvt->y_s.idx_d + k, ++ DEFAULT_M); ++ /* eq. (7): update the coefficient */ ++ pvt->a_i[k] += grad2 / two_beta_i; ++ pvt->a_s[k] = pvt->a_i[k] >> 16; ++ ++#ifdef USED_COEFFS ++ if (pvt->N_d > USED_COEFFS) { ++ if (abs(pvt->a_i[k]) > max_coeffs[USED_COEFFS-1]) { ++ /* More or less insertion-sort... */ ++ pos = max_coeffs; ++ while (*pos > abs(pvt->a_i[k])) ++ pos++; ++ ++ if (*pos > max_coeffs[USED_COEFFS-1]) ++ memmove(pos+1, pos, (USED_COEFFS-(pos-max_coeffs)-1)*sizeof(int)); ++ ++ *pos = abs(pvt->a_i[k]); ++ } ++ } ++#endif ++ } ++ ++#ifdef USED_COEFFS ++ /* Filter out irrelevant coefficients */ ++ if (pvt->N_d > USED_COEFFS) ++ for (k = 0; k < pvt->N_d; k++) ++ if (abs(pvt->a_i[k]) < max_coeffs[USED_COEFFS-1]) ++ pvt->a_i[k] = pvt->a_s[k] = 0; ++#endif ++ } else { ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "insufficient signal to update coefficients pvt->Lu_i %5d < %5d\n", pvt->Lu_i, MIN_UPDATE_THRESH_I); ++#endif ++#ifdef MEC2_STATS ++ pvt->avg_Lu_i_toolow = pvt->avg_Lu_i_toolow + pvt->Lu_i; ++ ++pvt->cntr_coeff_missedupdates; ++#endif ++ } ++ } ++ ++ /* paragraph below eq. (15): if no near-end speech in the sample and ++ * the reference signal power estimate > cutoff threshold ++ * then perform residual error suppression ++ */ ++#ifdef MEC2_STATS_DETAILED ++ if (pvt->HCNTR_d == 0) ++ printk(KERN_INFO "possibly correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d and expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); ++#endif ++ ++#ifndef NO_ECHO_SUPPRESSOR ++ if (pvt->use_nlp) { ++ if (pvt->aggressive) { ++ if ((pvt->HCNTR_d < AGGRESSIVE_HCNTR) && (pvt->Ly_i > (pvt->Lu_i << 1))) { ++ for (k = 0; k < 2; k++) { ++ u = u * (pvt->Lu_i >> DEFAULT_SIGMA_LU_I) / ((pvt->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); ++ } ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "aggresively correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); ++#endif ++#ifdef MEC2_STATS ++ ++pvt->cntr_residualcorrected_frames; ++#endif ++ } ++ } else { ++ if (pvt->HCNTR_d == 0) { ++ if ((pvt->Ly_i/(pvt->Lu_i + 1)) > DEFAULT_SUPPR_I) { ++ for (k = 0; k < 1; k++) { ++ u = u * (pvt->Lu_i >> DEFAULT_SIGMA_LU_I) / ((pvt->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); ++ } ++#ifdef MEC2_STATS_DETAILED ++ printk(KERN_INFO "correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); ++#endif ++#ifdef MEC2_STATS ++ ++pvt->cntr_residualcorrected_frames; ++#endif ++ } ++#ifdef MEC2_STATS ++ else { ++ ++pvt->cntr_residualcorrected_framesskipped; ++ } ++#endif ++ } ++ } ++ } ++#endif ++ ++#if 0 ++ /* This will generate a non-linear supression factor, once converted */ ++ if ((pvt->HCNTR_d == 0) && ++ ((pvt->Lu_d/pvt->Ly_d) < DEFAULT_SUPPR) && ++ (pvt->Lu_d/pvt->Ly_d > EC_MIN_DB_VALUE)) { ++ suppr_factor = (10 / (float)(SUPPR_FLOOR - SUPPR_CEIL)) * log(pvt->Lu_d/pvt->Ly_d) ++ - SUPPR_CEIL / (float)(SUPPR_FLOOR - SUPPR_CEIL); ++ u_suppr = pow(10.0, (suppr_factor) * RES_SUPR_FACTOR / 10.0) * u_suppr; ++ } ++#endif ++ ++#ifdef MEC2_STATS ++ /* Periodically dump performance stats */ ++ if ((pvt->i_d % MEC2_STATS) == 0) { ++ /* make sure to avoid div0's! */ ++ if (pvt->cntr_coeff_missedupdates > 0) ++ pvt->avg_Lu_i_toolow = (int)(pvt->avg_Lu_i_toolow / pvt->cntr_coeff_missedupdates); ++ else ++ pvt->avg_Lu_i_toolow = -1; ++ ++ if (pvt->cntr_coeff_updates > 0) ++ pvt->avg_Lu_i_ok = (pvt->avg_Lu_i_ok / pvt->cntr_coeff_updates); ++ else ++ pvt->avg_Lu_i_ok = -1; ++ ++ printk(KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n", ++ pvt->id, ++ pvt->cntr_nearend_speech_frames, ++ pvt->cntr_residualcorrected_frames, pvt->cntr_residualcorrected_framesskipped, ++ pvt->cntr_coeff_updates, pvt->cntr_coeff_missedupdates, ++ pvt->avg_Lu_i_ok, pvt->avg_Lu_i_toolow); ++ ++ pvt->cntr_nearend_speech_frames = 0; ++ pvt->cntr_residualcorrected_frames = 0; ++ pvt->cntr_residualcorrected_framesskipped = 0; ++ pvt->cntr_coeff_updates = 0; ++ pvt->cntr_coeff_missedupdates = 0; ++ pvt->avg_Lu_i_ok = 0; ++ pvt->avg_Lu_i_toolow = 0; ++ } ++#endif ++ ++ /* Increment the sample index and return the corrected sample */ ++ pvt->i_d++; ++ return u; ++} ++ ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ u32 x; ++ short result; ++ ++ for (x = 0; x < size; x++) { ++ result = sample_update(pvt, *iref, *isig); ++ *isig++ = result; ++ ++iref; ++ } ++} ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) ++{ ++ int maxy; ++ int maxu; ++ size_t size; ++ unsigned int x; ++ char *c; ++ struct ec_pvt *pvt; ++ ++ maxy = ecp->tap_length + DEFAULT_M; ++ maxu = DEFAULT_M; ++ if (maxy < (1 << DEFAULT_ALPHA_YT_I)) ++ maxy = (1 << DEFAULT_ALPHA_YT_I); ++ if (maxy < (1 << DEFAULT_SIGMA_LY_I)) ++ maxy = (1 << DEFAULT_SIGMA_LY_I); ++ if (maxu < (1 << DEFAULT_SIGMA_LU_I)) ++ maxu = (1 << DEFAULT_SIGMA_LU_I); ++ size = sizeof(**ec) + ++ 4 + /* align */ ++ sizeof(int) * ecp->tap_length + /* a_i */ ++ sizeof(short) * ecp->tap_length + /* a_s */ ++ sizeof(int) * ecp->tap_length + /* b_i */ ++ sizeof(int) * ecp->tap_length + /* c_i */ ++ 2 * sizeof(short) * (maxy) + /* y_s */ ++ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ ++ 2 * sizeof(short) * (maxu) + /* u_s */ ++ 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ ++ ++ pvt = kzalloc(size, GFP_KERNEL); ++ if (!pvt) ++ return -ENOMEM; ++ ++ pvt->dahdi.ops = &my_ops; ++ ++ pvt->aggressive = aggressive; ++ pvt->dahdi.features = my_features; ++ ++ for (x = 0; x < ecp->param_count; x++) { ++ for (c = p[x].name; *c; c++) ++ *c = tolower(*c); ++ if (!strcmp(p[x].name, "aggressive")) { ++ pvt->aggressive = p[x].value ? 1 : 0; ++ } else { ++ printk(KERN_WARNING "Unknown parameter supplied to MG2 echo canceler: '%s'\n", p[x].name); ++ kfree(pvt); ++ ++ return -EINVAL; ++ } ++ } ++ ++ init_cc(pvt, ecp->tap_length, maxy, maxu); ++ /* Non-linear processor - a fancy way to say "zap small signals, to avoid ++ accumulating noise". */ ++ pvt->use_nlp = TRUE; ++ ++ *ec = &pvt->dahdi; ++ return 0; ++} ++ ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ /* Set the hangover counter to the length of the can to ++ * avoid adjustments occuring immediately after initial forced training ++ */ ++ pvt->HCNTR_d = pvt->N_d << 1; ++ ++ if (pos >= pvt->N_d) { ++ memcpy(pvt->b_i, pvt->a_i, pvt->N_d*sizeof(int)); ++ memcpy(pvt->c_i, pvt->a_i, pvt->N_d*sizeof(int)); ++ return 1; ++ } ++ ++ pvt->a_i[pos] = val << 17; ++ pvt->a_s[pos] = val << 1; ++ ++ if (++pos >= pvt->N_d) { ++ memcpy(pvt->b_i, pvt->a_i, pvt->N_d*sizeof(int)); ++ memcpy(pvt->c_i, pvt->a_i, pvt->N_d*sizeof(int)); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ pvt->use_nlp = enable ? 1 : 0; ++} ++ ++static int __init mod_init(void) ++{ ++ if (dahdi_register_echocan_factory(&my_factory)) { ++ module_printk(KERN_ERR, "could not register with DAHDI core\n"); ++ ++ return -EPERM; ++ } ++ ++ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", ++ my_factory.get_name(NULL)); ++ ++ return 0; ++} ++ ++static void __exit mod_exit(void) ++{ ++ dahdi_unregister_echocan_factory(&my_factory); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++module_param(aggressive, int, S_IRUGO | S_IWUSR); ++ ++MODULE_DESCRIPTION("DAHDI 'MG2' Echo Canceler"); ++MODULE_AUTHOR("Michael Gernoth"); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(mod_init); ++module_exit(mod_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_echocan_oslec.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_oslec.c +--- linux-source-4.19/drivers/dahdi/dahdi_echocan_oslec.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_oslec.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,166 @@ ++/* ++ * DAHDI Telephony Interface to the Open Source Line Echo Canceller (OSLEC) ++ * ++ * Written by Tzafrir Cohen ++ * Copyright (C) 2008 Xorcom, Inc. ++ * ++ * All rights reserved. ++ * ++ * Based on dahdi_echocan_hpec.c, Copyright (C) 2006-2008 Digium, Inc. ++ * ++ * 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 ++ ++/* Fix this if OSLEC is elsewhere */ ++#include "../staging/echo/oslec.h" ++//#include ++ ++#include ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); ++#ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX ++static void echo_can_hpf_tx(struct dahdi_echocan_state *ec, ++ short *tx, u32 size); ++#endif ++static const char *name = "OSLEC"; ++static const char *ec_name(const struct dahdi_chan *chan) { return name; } ++ ++static const struct dahdi_echocan_factory my_factory = { ++ .get_name = ec_name, ++ .owner = THIS_MODULE, ++ .echocan_create = echo_can_create, ++}; ++ ++static const struct dahdi_echocan_ops my_ops = { ++ .echocan_free = echo_can_free, ++ .echocan_process = echo_can_process, ++ .echocan_traintap = echo_can_traintap, ++#ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX ++ .echocan_process_tx = echo_can_hpf_tx, ++#endif ++}; ++ ++struct ec_pvt { ++ struct oslec_state *oslec; ++ struct dahdi_echocan_state dahdi; ++}; ++ ++#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) ++ ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ oslec_free(pvt->oslec); ++ kfree(pvt); ++} ++ ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ u32 SampleNum; ++ ++ for (SampleNum = 0; SampleNum < size; SampleNum++, iref++) { ++ short iCleanSample; ++ ++ iCleanSample = oslec_update(pvt->oslec, *iref, *isig); ++ *isig++ = iCleanSample; ++ } ++} ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) ++{ ++ struct ec_pvt *pvt; ++ ++ if (ecp->param_count > 0) { ++ printk(KERN_WARNING "OSLEC does not support parameters; failing request\n"); ++ return -EINVAL; ++ } ++ ++ pvt = kzalloc(sizeof(*pvt), GFP_KERNEL); ++ if (!pvt) ++ return -ENOMEM; ++ ++ pvt->dahdi.ops = &my_ops; ++ ++ pvt->oslec = oslec_create(ecp->tap_length, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CLIP | ECHO_CAN_USE_TX_HPF | ECHO_CAN_USE_RX_HPF); ++ ++ if (!pvt->oslec) { ++ kfree(pvt); ++ *ec = NULL; ++ return -ENOTTY; ++ } else { ++ *ec = &pvt->dahdi; ++ return 0; ++ } ++} ++ ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) ++{ ++ return 1; ++} ++ ++#ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX ++static void echo_can_hpf_tx(struct dahdi_echocan_state *ec, short *tx, u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ u32 SampleNum; ++ ++ for (SampleNum = 0; SampleNum < size; SampleNum++, tx++) { ++ short iCleanSample; ++ ++ iCleanSample = oslec_hpf_tx(pvt->oslec, *tx); ++ *tx = iCleanSample; ++ } ++} ++#endif ++ ++static int __init mod_init(void) ++{ ++ if (dahdi_register_echocan_factory(&my_factory)) { ++ module_printk(KERN_ERR, "could not register with DAHDI core\n"); ++ ++ return -EPERM; ++ } ++ ++ module_printk(KERN_INFO, "Registered echo canceler '%s'\n", ++ my_factory.get_name(NULL)); ++ ++ return 0; ++} ++ ++static void __exit mod_exit(void) ++{ ++ dahdi_unregister_echocan_factory(&my_factory); ++} ++ ++MODULE_DESCRIPTION("DAHDI OSLEC wrapper"); ++MODULE_AUTHOR("Tzafrir Cohen "); ++MODULE_LICENSE("GPL"); ++ ++module_init(mod_init); ++module_exit(mod_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_echocan_sec.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_sec.c +--- linux-source-4.19/drivers/dahdi/dahdi_echocan_sec.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_sec.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,355 @@ ++/* ++ * SpanDSP - a series of DSP components for telephony ++ * ++ * echo.c - An echo cancellor, suitable for electrical and acoustic ++ * cancellation. This code does not currently comply with ++ * any relevant standards (e.g. G.164/5/7/8). One day.... ++ * ++ * Written by Steve Underwood ++ * Various optimizations and improvements by Mark Spencer ++ * ++ * Copyright (C) 2001 Steve Underwood ++ * ++ * Based on a bit from here, a bit from there, eye of toad, ++ * ear of bat, etc - plus, of course, my own 2 cents. ++ * ++ * 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. ++ */ ++ ++/* TODO: ++ Finish the echo suppressor option, however nasty suppression may be ++ Add an option to reintroduce side tone at -24dB under appropriate conditions. ++ Improve double talk detector (iterative!) ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static int debug; ++ ++#include "arith.h" ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++#ifndef FALSE ++#define FALSE 0 ++#endif ++#ifndef TRUE ++#define TRUE (!FALSE) ++#endif ++ ++#define USE_SHORTS ++ ++#define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ ++ ++/* Original parameters : ++#define MIN_TX_POWER_FOR_ADAPTION 256 ++#define MIN_RX_POWER_FOR_ADAPTION 128 ++*/ ++ ++#define MIN_TX_POWER_FOR_ADAPTION 256 ++#define MIN_RX_POWER_FOR_ADAPTION 64 ++ ++/* Better ones found by Jim ++#define MIN_TX_POWER_FOR_ADAPTION 128 ++#define MIN_RX_POWER_FOR_ADAPTION 64 ++*/ ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); ++static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable); ++static const char *name = "SEC"; ++static const char *ec_name(const struct dahdi_chan *chan) { return name; } ++ ++static const struct dahdi_echocan_factory my_factory = { ++ .get_name = ec_name, ++ .owner = THIS_MODULE, ++ .echocan_create = echo_can_create, ++}; ++ ++static const struct dahdi_echocan_features my_features = { ++ .NLP_toggle = 1, ++}; ++ ++static const struct dahdi_echocan_ops my_ops = { ++ .echocan_free = echo_can_free, ++ .echocan_process = echo_can_process, ++ .echocan_traintap = echo_can_traintap, ++ .echocan_NLP_toggle = echocan_NLP_toggle, ++}; ++ ++struct ec_pvt { ++ struct dahdi_echocan_state dahdi; ++ int tx_power; ++ int rx_power; ++ int clean_rx_power; ++ ++ int rx_power_threshold; ++ int nonupdate_dwell; ++ ++ int16_t *tx_history; /* Last N tx samples */ ++ int32_t *fir_taps; /* Echo FIR taps */ ++ int16_t *fir_taps_short; /* Echo FIR taps, shorts instead of ints */ ++ ++ int curr_pos; ++ ++ int taps; ++ int tap_mask; ++ int use_nlp; ++ int use_suppressor; ++ ++ int32_t supp_test1; ++ int32_t supp_test2; ++ int32_t supp1; ++ int32_t supp2; ++ ++ int32_t latest_correction; /* Indication of the magnitude of the latest ++ adaption, or a code to indicate why adaption ++ was skipped, for test purposes */ ++}; ++ ++#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) ++{ ++ struct ec_pvt *pvt; ++ size_t size; ++ ++ if (ecp->param_count > 0) { ++ printk(KERN_WARNING "SEC does not support parameters; failing request\n"); ++ return -EINVAL; ++ } ++ ++ size = sizeof(*pvt) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); ++ ++ pvt = kzalloc(size, GFP_KERNEL); ++ if (!pvt) ++ return -ENOMEM; ++ ++ pvt->dahdi.ops = &my_ops; ++ pvt->dahdi.features = my_features; ++ ++ pvt->taps = ecp->tap_length; ++ pvt->tap_mask = ecp->tap_length - 1; ++ pvt->tx_history = (int16_t *) (pvt + sizeof(*pvt)); ++ pvt->fir_taps = (int32_t *) (pvt + sizeof(*pvt) + ++ ecp->tap_length * 2 * sizeof(int16_t)); ++ pvt->fir_taps_short = (int16_t *) (pvt + sizeof(*pvt) + ++ ecp->tap_length * sizeof(int32_t) + ++ ecp->tap_length * 2 * sizeof(int16_t)); ++ pvt->rx_power_threshold = 10000000; ++ pvt->use_suppressor = FALSE; ++ /* Non-linear processor - a fancy way to say "zap small signals, to avoid ++ accumulating noise". */ ++ pvt->use_nlp = TRUE; ++ ++ *ec = &pvt->dahdi; ++ return 0; ++} ++ ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ kfree(pvt); ++} ++ ++static inline int16_t sample_update(struct ec_pvt *pvt, int16_t tx, int16_t rx) ++{ ++ int32_t echo_value; ++ int clean_rx; ++ int nsuppr; ++ ++ pvt->tx_history[pvt->curr_pos] = tx; ++ pvt->tx_history[pvt->curr_pos + pvt->taps] = tx; ++ ++ /* Evaluate the echo - i.e. apply the FIR filter */ ++ /* Assume the gain of the FIR does not exceed unity. Exceeding unity ++ would seem like a rather poor thing for an echo cancellor to do :) ++ This means we can compute the result with a total disregard for ++ overflows. 16bits x 16bits -> 31bits, so no overflow can occur in ++ any multiply. While accumulating we may overflow and underflow the ++ 32 bit scale often. However, if the gain does not exceed unity, ++ everything should work itself out, and the final result will be ++ OK, without any saturation logic. */ ++ /* Overflow is very much possible here, and we do nothing about it because ++ of the compute costs */ ++ /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound ++ bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems ++ best */ ++#ifdef USE_SHORTS ++ echo_value = CONVOLVE2(pvt->fir_taps_short, pvt->tx_history + pvt->curr_pos, pvt->taps); ++#else ++ echo_value = CONVOLVE(pvt->fir_taps, pvt->tx_history + pvt->curr_pos, pvt->taps); ++#endif ++ echo_value >>= 16; ++ ++ /* And the answer is..... */ ++ clean_rx = rx - echo_value; ++ ++ /* That was the easy part. Now we need to adapt! */ ++ if (pvt->nonupdate_dwell > 0) ++ pvt->nonupdate_dwell--; ++ ++ /* If there is very little being transmitted, any attempt to train is ++ futile. We would either be training on the far end's noise or signal, ++ the channel's own noise, or our noise. Either way, this is hardly good ++ training, so don't do it (avoid trouble). */ ++ /* If the received power is very low, either we are sending very little or ++ we are already well adapted. There is little point in trying to improve ++ the adaption under these circumstanceson, so don't do it (reduce the ++ compute load). */ ++ if (pvt->tx_power > MIN_TX_POWER_FOR_ADAPTION && pvt->rx_power > MIN_RX_POWER_FOR_ADAPTION) { ++ /* This is a really crude piece of decision logic, but it does OK ++ for now. */ ++ if (pvt->tx_power > pvt->rx_power << 1) { ++ /* There is no far-end speech detected */ ++ if (pvt->nonupdate_dwell == 0) { ++ /* ... and we are not in the dwell time from previous speech. */ ++ /* nsuppr = saturate((clean_rx << 16)/pvt->tx_power); */ ++ nsuppr = (clean_rx << 16) / pvt->tx_power; ++ nsuppr >>= 4; ++ if (nsuppr > 512) ++ nsuppr = 512; ++ if (nsuppr < -512) ++ nsuppr = -512; ++ ++ /* Update the FIR taps */ ++ pvt->latest_correction = 0; ++#ifdef USE_SHORTS ++ UPDATE2(pvt->fir_taps, pvt->fir_taps_short, pvt->tx_history + pvt->curr_pos, nsuppr, pvt->taps); ++#else ++ UPDATE(pvt->fir_taps, pvt->fir_taps_short, pvt->tx_history + pvt->curr_pos, nsuppr, pvt->taps); ++#endif ++ } else { ++ pvt->latest_correction = -3; ++ } ++ } else { ++ pvt->nonupdate_dwell = NONUPDATE_DWELL_TIME; ++ pvt->latest_correction = -2; ++ } ++ } else { ++ pvt->nonupdate_dwell = 0; ++ pvt->latest_correction = -1; ++ } ++ /* Calculate short term power levels using very simple single pole IIRs */ ++ /* TODO: Is the nasty modulus approach the fastest, or would a real ++ tx*tx power calculation actually be faster? */ ++ pvt->tx_power += ((abs(tx) - pvt->tx_power) >> 5); ++ pvt->rx_power += ((abs(rx) - pvt->rx_power) >> 5); ++ pvt->clean_rx_power += ((abs(clean_rx) - pvt->clean_rx_power) >> 5); ++ ++#if defined(XYZZY) ++ if (pvt->use_suppressor) { ++ pvt->supp_test1 += (pvt->tx_history[pvt->curr_pos] - pvt->tx_history[(pvt->curr_pos - 7) & pvt->tap_mask]); ++ pvt->supp_test2 += (pvt->tx_history[(pvt->curr_pos - 24) & pvt->tap_mask] - pvt->tx_history[(pvt->curr_pos - 31) & pvt->tap_mask]); ++ if (pvt->supp_test1 > 42 && pvt->supp_test2 > 42) ++ supp_change = 25; ++ else ++ supp_change = 50; ++ supp = supp_change + k1*pvt->supp1 + k2*pvt->supp2; ++ pvt->supp2 = pvt->supp1; ++ pvt->supp1 = supp; ++ clean_rx *= (1 - supp); ++ } ++#endif ++ ++ if (pvt->use_nlp && pvt->rx_power < 32) ++ clean_rx = 0; ++ ++ /* Roll around the rolling buffer */ ++ pvt->curr_pos = (pvt->curr_pos - 1) & pvt->tap_mask; ++ ++ return clean_rx; ++} ++ ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ u32 x; ++ short result; ++ ++ for (x = 0; x < size; x++) { ++ result = sample_update(pvt, *iref, *isig); ++ *isig++ = result; ++ ++iref; ++ } ++} ++ ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ /* Reset hang counter to avoid adjustments after ++ initial forced training */ ++ pvt->nonupdate_dwell = pvt->taps << 1; ++ if (pos >= pvt->taps) ++ return 1; ++ pvt->fir_taps[pos] = val << 17; ++ pvt->fir_taps_short[pos] = val << 1; ++ if (++pos >= pvt->taps) ++ return 1; ++ else ++ return 0; ++} ++ ++static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ pvt->use_nlp = enable ? 1 : 0; ++} ++ ++static int __init mod_init(void) ++{ ++ if (dahdi_register_echocan_factory(&my_factory)) { ++ module_printk(KERN_ERR, "could not register with DAHDI core\n"); ++ ++ return -EPERM; ++ } ++ ++ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", ++ my_factory.get_name(NULL)); ++ ++ return 0; ++} ++ ++static void __exit mod_exit(void) ++{ ++ dahdi_unregister_echocan_factory(&my_factory); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++ ++MODULE_DESCRIPTION("DAHDI 'SEC' Echo Canceler"); ++MODULE_AUTHOR("Steve Underwood "); ++MODULE_LICENSE("GPL"); ++ ++module_init(mod_init); ++module_exit(mod_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_echocan_sec2.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_sec2.c +--- linux-source-4.19/drivers/dahdi/dahdi_echocan_sec2.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_echocan_sec2.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,350 @@ ++/* ++ * SpanDSP - a series of DSP components for telephony ++ * ++ * echo.c - An echo cancellor, suitable for electrical and acoustic ++ * cancellation. This code does not currently comply with ++ * any relevant standards (e.g. G.164/5/7/8). One day.... ++ * ++ * Written by Steve Underwood ++ * ++ * Copyright (C) 2001 Steve Underwood ++ * ++ * Based on a bit from here, a bit from there, eye of toad, ++ * ear of bat, etc - plus, of course, my own 2 cents. ++ * ++ * 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. ++ */ ++ ++/* TODO: ++ Finish the echo suppressor option, however nasty suppression may be ++ Add an option to reintroduce side tone at -24dB under appropriate conditions. ++ Improve double talk detector (iterative!) ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static int debug; ++ ++#include "fir.h" ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++#ifndef FALSE ++#define FALSE 0 ++#endif ++#ifndef TRUE ++#define TRUE (!FALSE) ++#endif ++ ++#define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ ++ ++/* ++ * According to Jim... ++ */ ++#define MIN_TX_POWER_FOR_ADAPTION 512 ++#define MIN_RX_POWER_FOR_ADAPTION 64 ++ ++/* ++ * According to Steve... ++ */ ++/* #define MIN_TX_POWER_FOR_ADAPTION 4096 ++#define MIN_RX_POWER_FOR_ADAPTION 64 */ ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); ++static const char *name = "SEC2"; ++static const char *ec_name(const struct dahdi_chan *chan) { return name; } ++ ++static const struct dahdi_echocan_factory my_factory = { ++ .get_name = ec_name, ++ .owner = THIS_MODULE, ++ .echocan_create = echo_can_create, ++}; ++ ++static const struct dahdi_echocan_ops my_ops = { ++ .echocan_free = echo_can_free, ++ .echocan_process = echo_can_process, ++ .echocan_traintap = echo_can_traintap, ++}; ++ ++struct ec_pvt { ++ struct dahdi_echocan_state dahdi; ++ int tx_power; ++ int rx_power; ++ int clean_rx_power; ++ ++ int rx_power_threshold; ++ int nonupdate_dwell; ++ ++ fir16_state_t fir_state; ++ int16_t *fir_taps16; /* 16-bit version of FIR taps */ ++ int32_t *fir_taps32; /* 32-bit version of FIR taps */ ++ ++ int curr_pos; ++ ++ int taps; ++ int tap_mask; ++ int use_nlp; ++ int use_suppressor; ++ ++ int32_t supp_test1; ++ int32_t supp_test2; ++ int32_t supp1; ++ int32_t supp2; ++ ++ int32_t latest_correction; /* Indication of the magnitude of the latest ++ adaption, or a code to indicate why adaption ++ was skipped, for test purposes */ ++}; ++ ++#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) ++{ ++ struct ec_pvt *pvt; ++ size_t size; ++ ++ if (ecp->param_count > 0) { ++ printk(KERN_WARNING "SEC2 does not support parameters; failing request\n"); ++ return -EINVAL; ++ } ++ ++ size = sizeof(*pvt) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); ++ ++ pvt = kzalloc(size, GFP_KERNEL); ++ if (!pvt) ++ return -ENOMEM; ++ ++ pvt->dahdi.ops = &my_ops; ++ ++ if (ecp->param_count > 0) { ++ printk(KERN_WARNING "SEC-2 echo canceler does not support parameters; failing request\n"); ++ return -EINVAL; ++ } ++ ++ pvt->taps = ecp->tap_length; ++ pvt->curr_pos = ecp->tap_length - 1; ++ pvt->tap_mask = ecp->tap_length - 1; ++ pvt->fir_taps32 = (int32_t *) (pvt + sizeof(*pvt)); ++ pvt->fir_taps16 = (int16_t *) (pvt + sizeof(*pvt) + ecp->tap_length * sizeof(int32_t)); ++ /* Create FIR filter */ ++ fir16_create(&pvt->fir_state, pvt->fir_taps16, pvt->taps); ++ pvt->rx_power_threshold = 10000000; ++ pvt->use_suppressor = FALSE; ++ /* Non-linear processor - a fancy way to say "zap small signals, to avoid ++ accumulating noise". */ ++ pvt->use_nlp = FALSE; ++ ++ *ec = &pvt->dahdi; ++ return 0; ++} ++ ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ fir16_free(&pvt->fir_state); ++ kfree(pvt); ++} ++ ++static inline int16_t sample_update(struct ec_pvt *pvt, int16_t tx, int16_t rx) ++{ ++ int offset1; ++ int offset2; ++ int32_t echo_value; ++ int clean_rx; ++ int nsuppr; ++ int i; ++ int correction; ++ ++ /* Evaluate the echo - i.e. apply the FIR filter */ ++ /* Assume the gain of the FIR does not exceed unity. Exceeding unity ++ would seem like a rather poor thing for an echo cancellor to do :) ++ This means we can compute the result with a total disregard for ++ overflows. 16bits x 16bits -> 31bits, so no overflow can occur in ++ any multiply. While accumulating we may overflow and underflow the ++ 32 bit scale often. However, if the gain does not exceed unity, ++ everything should work itself out, and the final result will be ++ OK, without any saturation logic. */ ++ /* Overflow is very much possible here, and we do nothing about it because ++ of the compute costs */ ++ /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound ++ bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems ++ best */ ++ echo_value = fir16 (&pvt->fir_state, tx); ++ ++ /* And the answer is..... */ ++ clean_rx = rx - echo_value; ++ ++ /* That was the easy part. Now we need to adapt! */ ++ if (pvt->nonupdate_dwell > 0) ++ pvt->nonupdate_dwell--; ++ ++ /* If there is very little being transmitted, any attempt to train is ++ futile. We would either be training on the far end's noise or signal, ++ the channel's own noise, or our noise. Either way, this is hardly good ++ training, so don't do it (avoid trouble). */ ++ /* If the received power is very low, either we are sending very little or ++ we are already well adapted. There is little point in trying to improve ++ the adaption under these circumstanceson, so don't do it (reduce the ++ compute load). */ ++ if (pvt->tx_power > MIN_TX_POWER_FOR_ADAPTION && pvt->rx_power > MIN_RX_POWER_FOR_ADAPTION) { ++ /* This is a really crude piece of decision logic, but it does OK ++ for now. */ ++ if (pvt->tx_power > 2*pvt->rx_power) { ++ /* There is no far-end speech detected */ ++ if (pvt->nonupdate_dwell == 0) { ++ /* ... and we are not in the dwell time from previous speech. */ ++ /* nsuppr = saturate((clean_rx << 16)/pvt->tx_power); */ ++ nsuppr = clean_rx >> 3; ++ ++ /* Update the FIR taps */ ++ offset2 = pvt->curr_pos + 1; ++ offset1 = pvt->taps - offset2; ++ pvt->latest_correction = 0; ++ for (i = pvt->taps - 1; i >= offset1; i--) { ++ correction = pvt->fir_state.history[i - offset1]*nsuppr; ++ /* Leak to avoid false training on signals with multiple ++ strong correlations. */ ++ pvt->fir_taps32[i] -= (pvt->fir_taps32[i] >> 12); ++ pvt->fir_taps32[i] += correction; ++ pvt->fir_state.coeffs[i] = pvt->fir_taps32[i] >> 15; ++ pvt->latest_correction += abs(correction); ++ } ++ for ( ; i >= 0; i--) { ++ correction = pvt->fir_state.history[i + offset2]*nsuppr; ++ /* Leak to avoid false training on signals with multiple ++ strong correlations. */ ++ pvt->fir_taps32[i] -= (pvt->fir_taps32[i] >> 12); ++ pvt->fir_taps32[i] += correction; ++ pvt->fir_state.coeffs[i] = pvt->fir_taps32[i] >> 15; ++ pvt->latest_correction += abs(correction); ++ } ++ } else { ++ pvt->latest_correction = -1; ++ } ++ } else { ++ pvt->nonupdate_dwell = NONUPDATE_DWELL_TIME; ++ pvt->latest_correction = -2; ++ } ++ } else { ++ pvt->nonupdate_dwell = 0; ++ pvt->latest_correction = -3; ++ } ++ /* Calculate short term power levels using very simple single pole IIRs */ ++ /* TODO: Is the nasty modulus approach the fastest, or would a real ++ tx*tx power calculation actually be faster? */ ++ pvt->tx_power += ((abs(tx) - pvt->tx_power) >> 5); ++ pvt->rx_power += ((abs(rx) - pvt->rx_power) >> 5); ++ pvt->clean_rx_power += ((abs(clean_rx) - pvt->clean_rx_power) >> 5); ++ ++#if defined(XYZZY) ++ if (pvt->use_suppressor) { ++ pvt->supp_test1 += (pvt->fir_state.history[pvt->curr_pos] - pvt->fir_state.history[(pvt->curr_pos - 7) & pvt->tap_mask]); ++ pvt->supp_test2 += (pvt->fir_state.history[(pvt->curr_pos - 24) & pvt->tap_mask] - pvt->fir_state.history[(pvt->curr_pos - 31) & pvt->tap_mask]); ++ if (pvt->supp_test1 > 42 && pvt->supp_test2 > 42) ++ supp_change = 25; ++ else ++ supp_change = 50; ++ supp = supp_change + k1*pvt->supp1 + k2*pvt->supp2; ++ pvt->supp2 = pvt->supp1; ++ pvt->supp1 = supp; ++ clean_rx *= (1 - supp); ++ } ++#endif ++ ++ if (pvt->use_nlp && pvt->rx_power < 32) ++ clean_rx = 0; ++ ++ /* Roll around the rolling buffer */ ++ if (pvt->curr_pos <= 0) ++ pvt->curr_pos = pvt->taps; ++ pvt->curr_pos--; ++ ++ return clean_rx; ++} ++ ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ u32 x; ++ short result; ++ ++ for (x = 0; x < size; x++) { ++ result = sample_update(pvt, *iref, *isig); ++ *isig++ = result; ++ ++iref; ++ } ++} ++ ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ /* Reset hang counter to avoid adjustments after ++ initial forced training */ ++ pvt->nonupdate_dwell = pvt->taps << 1; ++ if (pos >= pvt->taps) ++ return 1; ++ pvt->fir_taps32[pos] = val << 17; ++ pvt->fir_taps16[pos] = val << 1; ++ if (++pos >= pvt->taps) ++ return 1; ++ else ++ return 0; ++} ++ ++static int __init mod_init(void) ++{ ++ if (dahdi_register_echocan_factory(&my_factory)) { ++ module_printk(KERN_ERR, "could not register with DAHDI core\n"); ++ ++ return -EPERM; ++ } ++ ++ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", ++ my_factory.get_name(NULL)); ++ ++ return 0; ++} ++ ++static void __exit mod_exit(void) ++{ ++ dahdi_unregister_echocan_factory(&my_factory); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++ ++MODULE_DESCRIPTION("DAHDI 'SEC2' Echo Canceler"); ++MODULE_AUTHOR("Steve Underwood "); ++MODULE_LICENSE("GPL"); ++ ++module_init(mod_init); ++module_exit(mod_exit); +diff -Nru linux-source-4.19/drivers/dahdi/dahdi_transcode.c linux-source-4.19-dahdi/drivers/dahdi/dahdi_transcode.c +--- linux-source-4.19/drivers/dahdi/dahdi_transcode.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/dahdi_transcode.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,480 @@ ++/* ++ * Transcoder Interface for DAHDI ++ * ++ * Written by Mark Spencer ++ * ++ * Copyright (C) 2006-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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static int debug; ++/* The registration list contains transcoders in the order in which they were ++ * registered. */ ++static LIST_HEAD(registration_list); ++/* The active list is sorted by the most recently used transcoder is last. This ++ * is used as a simplistic way to spread the load amongst the different hardware ++ * transcoders in the system. */ ++static LIST_HEAD(active_list); ++static DEFINE_SPINLOCK(translock); ++ ++EXPORT_SYMBOL(dahdi_transcoder_register); ++EXPORT_SYMBOL(dahdi_transcoder_unregister); ++EXPORT_SYMBOL(dahdi_transcoder_alert); ++EXPORT_SYMBOL(dahdi_transcoder_alloc); ++EXPORT_SYMBOL(dahdi_transcoder_free); ++ ++struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans) ++{ ++ struct dahdi_transcoder *tc; ++ unsigned int x; ++ size_t size = sizeof(*tc) + (sizeof(tc->channels[0]) * numchans); ++ ++ if (!(tc = kmalloc(size, GFP_KERNEL))) ++ return NULL; ++ ++ memset(tc, 0, size); ++ strcpy(tc->name, ""); ++ INIT_LIST_HEAD(&tc->registration_list_node); ++ INIT_LIST_HEAD(&tc->active_list_node); ++ tc->numchannels = numchans; ++ for (x=0; x < tc->numchannels; x++) { ++ init_waitqueue_head(&tc->channels[x].ready); ++ tc->channels[x].parent = tc; ++ } ++ ++ WARN_ON(!dahdi_transcode_fops); ++ /* Individual transcoders should supply their own file_operations for ++ * write and read. But they will by default use the file_operations ++ * provided by the dahdi_transcode layer. */ ++ memcpy(&tc->fops, dahdi_transcode_fops, sizeof(*dahdi_transcode_fops)); ++ return tc; ++} ++ ++void dahdi_transcoder_free(struct dahdi_transcoder *tc) ++{ ++ kfree(tc); ++} ++ ++/* Returns 1 if the item is on the list pointed to by head, otherwise, returns ++ * 0 */ ++static int is_on_list(struct list_head *entry, struct list_head *head) ++{ ++ struct list_head *cur; ++ list_for_each(cur, head) { ++ if (cur == entry) return 1; ++ } ++ return 0; ++} ++ ++/* Register a transcoder */ ++int dahdi_transcoder_register(struct dahdi_transcoder *tc) ++{ ++ spin_lock(&translock); ++ BUG_ON(is_on_list(&tc->registration_list_node, ®istration_list)); ++ list_add_tail(&tc->registration_list_node, ®istration_list); ++ list_add_tail(&tc->active_list_node, &active_list); ++ spin_unlock(&translock); ++ ++ printk(KERN_INFO "%s: Registered codec translator '%s' " \ ++ "with %d transcoders (srcs=%08x, dsts=%08x)\n", ++ THIS_MODULE->name, tc->name, tc->numchannels, ++ tc->srcfmts, tc->dstfmts); ++ ++ return 0; ++} ++ ++/* Unregister a transcoder */ ++int dahdi_transcoder_unregister(struct dahdi_transcoder *tc) ++{ ++ int res = -EINVAL; ++ ++ /* \todo Perhaps we should check to make sure there isn't a channel ++ * that is still in use? */ ++ ++ spin_lock(&translock); ++ if (!is_on_list(&tc->registration_list_node, ®istration_list)) { ++ spin_unlock(&translock); ++ printk(KERN_WARNING "%s: Failed to unregister %s, which is " \ ++ "not currently registered.\n", THIS_MODULE->name, tc->name); ++ return -EINVAL; ++ } ++ list_del_init(&tc->registration_list_node); ++ list_del_init(&tc->active_list_node); ++ spin_unlock(&translock); ++ ++ printk(KERN_INFO "Unregistered codec translator '%s' with %d " \ ++ "transcoders (srcs=%08x, dsts=%08x)\n", ++ tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts); ++ res = 0; ++ ++ return res; ++} ++ ++/* Alert a transcoder */ ++int dahdi_transcoder_alert(struct dahdi_transcoder_channel *chan) ++{ ++ wake_up_interruptible(&chan->ready); ++ return 0; ++} ++ ++static int dahdi_tc_open(struct inode *inode, struct file *file) ++{ ++ const struct file_operations *original_fops; ++ BUG_ON(!dahdi_transcode_fops); ++ original_fops = file->f_op; ++ file->f_op = dahdi_transcode_fops; ++ file->private_data = NULL; ++ /* Under normal operation, this releases the reference on the DAHDI ++ * module that was created when the file was opened. dahdi_open is ++ * responsible for taking a reference out on this module before ++ * calling this function. */ ++ module_put(original_fops->owner); ++ return 0; ++} ++ ++static void dtc_release(struct dahdi_transcoder_channel *chan) ++{ ++ BUG_ON(!chan); ++ if (chan->parent && chan->parent->release) { ++ chan->parent->release(chan); ++ } else { ++ dahdi_tc_clear_busy(chan); ++ } ++} ++ ++static int dahdi_tc_release(struct inode *inode, struct file *file) ++{ ++ struct dahdi_transcoder_channel *chan = file->private_data; ++ /* There will not be a transcoder channel associated with this file if ++ * the ALLOCATE ioctl never succeeded. ++ */ ++ if (chan) { ++ dtc_release(chan); ++ } ++ return 0; ++} ++ ++/* Find a free channel on the transcoder and mark it busy. */ ++static inline struct dahdi_transcoder_channel * ++get_free_channel(struct dahdi_transcoder *tc, ++ const struct dahdi_transcoder_formats *fmts) ++{ ++ struct dahdi_transcoder_channel *chan; ++ int i; ++ /* Should be called with the translock held. */ ++#ifdef CONFIG_SMP ++ WARN_ON(!spin_is_locked(&translock)); ++#endif ++ ++ for (i = 0; i < tc->numchannels; i++) { ++ chan = &tc->channels[i]; ++ if (!dahdi_tc_is_busy(chan)) { ++ if (!dahdi_tc_is_built(chan)) { ++ dahdi_tc_set_busy(chan); ++ return chan; ++ } else { ++ /* If the channel is already built, we must ++ * make sure that it can support the formats ++ * that we're interested in. */ ++ if ((fmts->srcfmt|fmts->dstfmt) == chan->built_fmts) { ++ dahdi_tc_set_busy(chan); ++ return chan; ++ } ++ } ++ } ++ } ++ return NULL; ++} ++ ++/* Search the list for a transcoder that supports the specified format, and ++ * allocate and return an available channel on it. ++ * ++ * Returns either a pointer to the allocated channel, -EBUSY if the format is ++ * supported but all the channels are busy, or -ENODEV if there are not any ++ * transcoders that support the formats. ++ */ ++static struct dahdi_transcoder_channel * ++__find_free_channel(struct list_head *list, const struct dahdi_transcoder_formats *fmts) ++{ ++ struct dahdi_transcoder *tc; ++ struct dahdi_transcoder_channel *chan = NULL; ++ unsigned int match = 0; ++ ++ list_for_each_entry(tc, list, active_list_node) { ++ if ((tc->dstfmts & fmts->dstfmt) && (tc->srcfmts & fmts->srcfmt)) { ++ /* We found a transcoder that can handle our formats. ++ * Now look for an available channel. */ ++ match = 1; ++ if ((chan = get_free_channel(tc, fmts))) { ++ /* transcoder tc has a free channel. In order ++ * to spread the load among available ++ * transcoders (when there are more than one ++ * transcoder in the system) we'll move tc ++ * to the end of the list. */ ++ list_move_tail(&tc->active_list_node, list); ++ return chan; ++ } ++ } ++ } ++ return (void*)((long)((match) ? -EBUSY : -ENODEV)); ++} ++ ++static long dahdi_tc_allocate(struct file *file, unsigned long data) ++{ ++ struct dahdi_transcoder_channel *chan = NULL; ++ struct dahdi_transcoder_formats fmts; ++ ++ if (copy_from_user(&fmts, (__user const void *) data, sizeof(fmts))) { ++ return -EFAULT; ++ } ++ ++ spin_lock(&translock); ++ chan = __find_free_channel(&active_list, &fmts); ++ spin_unlock(&translock); ++ ++ if (IS_ERR(chan)) { ++ return PTR_ERR(chan); ++ } ++ ++ /* Every transcoder channel must be associated with a parent ++ * transcoder. */ ++ BUG_ON(!chan->parent); ++ ++ chan->srcfmt = fmts.srcfmt; ++ chan->dstfmt = fmts.dstfmt; ++ ++ if (file->private_data) { ++ /* This open file is moving to a new channel. Cleanup and ++ * close the old channel here. */ ++ dtc_release(file->private_data); ++ } ++ ++ file->private_data = chan; ++ if (chan->parent->fops.owner != file->f_op->owner) { ++ if (!try_module_get(chan->parent->fops.owner)) { ++ /* Failed to get a reference on the driver for the ++ * actual transcoding hardware. */ ++ return -EINVAL; ++ } ++ /* Release the reference on the existing driver. */ ++ module_put(file->f_op->owner); ++ file->f_op = &chan->parent->fops; ++ } ++ ++ if (file->f_flags & O_NONBLOCK) { ++ dahdi_tc_set_nonblock(chan); ++ } else { ++ dahdi_tc_clear_nonblock(chan); ++ } ++ ++ /* Actually reset the transcoder channel */ ++ if (chan->parent->allocate) ++ return chan->parent->allocate(chan); ++ ++ return -EINVAL; ++} ++ ++static long dahdi_tc_getinfo(unsigned long data) ++{ ++ struct dahdi_transcoder_info info; ++ struct dahdi_transcoder *cur; ++ struct dahdi_transcoder *tc = NULL; ++ unsigned int count = 0; ++ ++ if (copy_from_user(&info, (__user const void *) data, sizeof(info))) { ++ return -EFAULT; ++ } ++ ++ spin_lock(&translock); ++ list_for_each_entry(cur, ®istration_list, registration_list_node) { ++ if (info.tcnum == count++) { ++ tc = cur; ++ break; ++ } ++ } ++ spin_unlock(&translock); ++ ++ if (!tc) { ++ return -ENOSYS; ++ } ++ ++ strlcpy(info.name, tc->name, sizeof(info.name)); ++ info.numchannels = tc->numchannels; ++ info.srcfmts = tc->srcfmts; ++ info.dstfmts = tc->dstfmts; ++ ++ return copy_to_user((__user void *) data, &info, sizeof(info)) ? -EFAULT : 0; ++} ++ ++static ssize_t dahdi_tc_write(struct file *file, __user const char *usrbuf, size_t count, loff_t *ppos) ++{ ++ if (file->private_data) { ++ /* file->private_data will not be NULL if DAHDI_TC_ALLOCATE was ++ * called, and therefore indicates that the transcoder driver ++ * did not export a read function. */ ++ WARN_ON(1); ++ return -ENOSYS; ++ } else { ++ printk(KERN_INFO "%s: Attempt to write to unallocated " \ ++ "channel.\n", THIS_MODULE->name); ++ return -EINVAL; ++ } ++} ++ ++static ssize_t dahdi_tc_read(struct file *file, __user char *usrbuf, size_t count, loff_t *ppos) ++{ ++ if (file->private_data) { ++ /* file->private_data will not be NULL if DAHDI_TC_ALLOCATE was ++ * called, and therefore indicates that the transcoder driver ++ * did not export a write function. */ ++ WARN_ON(1); ++ return -ENOSYS; ++ } else { ++ printk(KERN_INFO "%s: Attempt to read from unallocated " \ ++ "channel.\n", THIS_MODULE->name); ++ return -EINVAL; ++ } ++} ++ ++static long dahdi_tc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data) ++{ ++ switch (cmd) { ++ case DAHDI_TC_ALLOCATE: ++ return dahdi_tc_allocate(file, data); ++ case DAHDI_TC_GETINFO: ++ return dahdi_tc_getinfo(data); ++ case DAHDI_TRANSCODE_OP: ++ /* This is a deprecated call from the previous transcoder ++ * interface, which was all routed through the dahdi_ioctl in ++ * dahdi-base.c, and this ioctl request was used to indicate ++ * that the call should be forwarded to this function. Now ++ * when the file is opened, the f_ops pointer is updated to ++ * point directly to this function, and we don't need a ++ * general indication that the ioctl is destined for the ++ * transcoder. ++ * ++ * I'm keeping this ioctl here in order to explain why there ++ * might be a hole in the ioctl numbering scheme in the header ++ * files. ++ */ ++ printk(KERN_WARNING "%s: DAHDI_TRANSCODE_OP is no longer " \ ++ "supported. Please call DAHDI_TC ioctls directly.\n", ++ THIS_MODULE->name); ++ return -EINVAL; ++ default: ++ return -EINVAL; ++ }; ++} ++ ++#ifndef HAVE_UNLOCKED_IOCTL ++static int dahdi_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) ++{ ++ return (int)dahdi_tc_unlocked_ioctl(file, cmd, data); ++} ++#endif ++ ++static unsigned int dahdi_tc_poll(struct file *file, struct poll_table_struct *wait_table) ++{ ++ int ret; ++ struct dahdi_transcoder_channel *chan = file->private_data; ++ ++ if (!chan) { ++ /* This is because the DAHDI_TC_ALLOCATE ioctl was not called ++ * before calling poll, which is invalid. */ ++ return -EINVAL; ++ } ++ ++ poll_wait(file, &chan->ready, wait_table); ++ ++ ret = dahdi_tc_is_busy(chan) ? 0 : POLLPRI; ++ ret |= dahdi_tc_is_built(chan) ? POLLOUT : 0; ++ ret |= dahdi_tc_is_data_waiting(chan) ? POLLIN : 0; ++ return ret; ++} ++ ++static struct file_operations __dahdi_transcode_fops = { ++ .owner = THIS_MODULE, ++ .open = dahdi_tc_open, ++ .release = dahdi_tc_release, ++#ifdef HAVE_UNLOCKED_IOCTL ++ .unlocked_ioctl = dahdi_tc_unlocked_ioctl, ++#else ++ .ioctl = dahdi_tc_ioctl, ++#endif ++ .read = dahdi_tc_read, ++ .write = dahdi_tc_write, ++ .poll = dahdi_tc_poll, ++}; ++ ++static struct dahdi_chardev transcode_chardev = { ++ .name = "transcode", ++ .minor = DAHDI_TRANSCODE, ++}; ++ ++static int dahdi_transcode_init(void) ++{ ++ int res; ++ ++ if (dahdi_transcode_fops) { ++ printk(KERN_WARNING "dahdi_transcode_fops already set.\n"); ++ return -EBUSY; ++ } ++ ++ dahdi_transcode_fops = &__dahdi_transcode_fops; ++ ++ if ((res = dahdi_register_chardev(&transcode_chardev))) ++ return res; ++ ++ printk(KERN_INFO "%s: Loaded.\n", THIS_MODULE->name); ++ return 0; ++} ++ ++static void dahdi_transcode_cleanup(void) ++{ ++ dahdi_unregister_chardev(&transcode_chardev); ++ ++ dahdi_transcode_fops = NULL; ++ ++ printk(KERN_DEBUG "%s: Unloaded.\n", THIS_MODULE->name); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++MODULE_DESCRIPTION("DAHDI Transcoder Support"); ++MODULE_AUTHOR("Mark Spencer "); ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif ++ ++module_init(dahdi_transcode_init); ++module_exit(dahdi_transcode_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/datamods/Makefile linux-source-4.19-dahdi/drivers/dahdi/datamods/Makefile +--- linux-source-4.19/drivers/dahdi/datamods/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/Makefile 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,32 @@ ++.EXPORT_ALL_VARIABLES: ++MODULES= \ ++ hdlc_cisco hdlc_generic hdlc_raw syncppp \ ++ hdlc_fr hdlc_ppp hdlc_raw_eth ++ ++ ++PWD=$(shell pwd) ++ ++MODULESO:=$(MODULES:%=%.o) ++MODULESKO:=$(MODULES:%=%.ko) ++KMAKE = $(MAKE) -C $(KSRC) KBUILD_EXTMOD=$(PWD) ++KMAKE_INST = $(KMAKE) \ ++ INSTALL_MOD_PATH=$(INSTALL_PREFIX) INSTALL_MOD_DIR=misc modules_install ++ ++obj-m := $(MODULESO) ++#obj-m:=hdlc_raw.o hdlc_cisco.o ++#obj-m := hdlc_cisco.o hdlc_cisco.mod.o hdlc_fr.o hdlc_generic.o hdlc_ppp.o hdlc_raw.o hdlc_raw_eth.o hdlc_raw.mod.o hdlc_x25.o ++ ++all: ++ @echo "You don't want to do make here. Do it from up above" ++ ++clean: ++ $(KMAKE) clean ++ ++install: $(MODULESKO) ++ $(KMAKE_INST) ++ ++datamods: ++ @echo "To build: $(obj-m)" ++ @echo $(KSRC) ++ @if [ -z "$(KSRC)" -o ! -d "$(KSRC)" ]; then echo "You do not appear to have the sources for the $(KVERS) kernel installed."; exit 1 ; fi ++ $(KMAKE) modules +diff -Nru linux-source-4.19/drivers/dahdi/datamods/hdlc_cisco.c linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_cisco.c +--- linux-source-4.19/drivers/dahdi/datamods/hdlc_cisco.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_cisco.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,335 @@ ++/* ++ * Generic HDLC support routines for Linux ++ * Cisco HDLC support ++ * ++ * Copyright (C) 2000 - 2003 Krzysztof Halasa ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License ++ * as published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#undef DEBUG_HARD_HEADER ++ ++#define CISCO_MULTICAST 0x8F /* Cisco multicast address */ ++#define CISCO_UNICAST 0x0F /* Cisco unicast address */ ++#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ ++#define CISCO_SYS_INFO 0x2000 /* Cisco interface/system info */ ++#define CISCO_ADDR_REQ 0 /* Cisco address request */ ++#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ ++#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ ++ ++ ++static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev, ++ u16 type, void *daddr, void *saddr, ++ unsigned int len) ++{ ++ hdlc_header *data; ++#ifdef DEBUG_HARD_HEADER ++ printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name); ++#endif ++ ++ skb_push(skb, sizeof(hdlc_header)); ++ data = (hdlc_header*)skb->data; ++ if (type == CISCO_KEEPALIVE) ++ data->address = CISCO_MULTICAST; ++ else ++ data->address = CISCO_UNICAST; ++ data->control = 0; ++ data->protocol = htons(type); ++ ++ return sizeof(hdlc_header); ++} ++ ++ ++ ++static void cisco_keepalive_send(struct net_device *dev, u32 type, ++ u32 par1, u32 par2) ++{ ++ struct sk_buff *skb; ++ cisco_packet *data; ++ ++ skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet)); ++ if (!skb) { ++ printk(KERN_WARNING ++ "%s: Memory squeeze on cisco_keepalive_send()\n", ++ dev->name); ++ return; ++ } ++ skb_reserve(skb, 4); ++ cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); ++ data = (cisco_packet*)(skb->data + 4); ++ ++ data->type = htonl(type); ++ data->par1 = htonl(par1); ++ data->par2 = htonl(par2); ++ data->rel = 0xFFFF; ++ /* we will need do_div here if 1000 % HZ != 0 */ ++ data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ)); ++ ++ skb_put(skb, sizeof(cisco_packet)); ++ skb->priority = TC_PRIO_CONTROL; ++ skb->dev = dev; ++ skb->nh.raw = skb->data; ++ ++ dev_queue_xmit(skb); ++} ++ ++ ++ ++static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) ++{ ++ hdlc_header *data = (hdlc_header*)skb->data; ++ ++ if (skb->len < sizeof(hdlc_header)) ++ return __constant_htons(ETH_P_HDLC); ++ ++ if (data->address != CISCO_MULTICAST && ++ data->address != CISCO_UNICAST) ++ return __constant_htons(ETH_P_HDLC); ++ ++ switch(data->protocol) { ++ case __constant_htons(ETH_P_IP): ++ case __constant_htons(ETH_P_IPX): ++ case __constant_htons(ETH_P_IPV6): ++ skb_pull(skb, sizeof(hdlc_header)); ++ return data->protocol; ++ default: ++ return __constant_htons(ETH_P_HDLC); ++ } ++} ++ ++ ++static int cisco_rx(struct sk_buff *skb) ++{ ++ struct net_device *dev = skb->dev; ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ hdlc_header *data = (hdlc_header*)skb->data; ++ cisco_packet *cisco_data; ++ struct in_device *in_dev; ++ u32 addr, mask; ++ ++ if (skb->len < sizeof(hdlc_header)) ++ goto rx_error; ++ ++ if (data->address != CISCO_MULTICAST && ++ data->address != CISCO_UNICAST) ++ goto rx_error; ++ ++ switch(ntohs(data->protocol)) { ++ case CISCO_SYS_INFO: ++ /* Packet is not needed, drop it. */ ++ dev_kfree_skb_any(skb); ++ return NET_RX_SUCCESS; ++ ++ case CISCO_KEEPALIVE: ++ if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN && ++ skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) { ++ printk(KERN_INFO "%s: Invalid length of Cisco " ++ "control packet (%d bytes)\n", ++ dev->name, skb->len); ++ goto rx_error; ++ } ++ ++ cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header)); ++ ++ switch(ntohl (cisco_data->type)) { ++ case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ ++ in_dev = dev->ip_ptr; ++ addr = 0; ++ mask = ~0; /* is the mask correct? */ ++ ++ if (in_dev != NULL) { ++ struct in_ifaddr **ifap = &in_dev->ifa_list; ++ ++ while (*ifap != NULL) { ++ if (strcmp(dev->name, ++ (*ifap)->ifa_label) == 0) { ++ addr = (*ifap)->ifa_local; ++ mask = (*ifap)->ifa_mask; ++ break; ++ } ++ ifap = &(*ifap)->ifa_next; ++ } ++ ++ cisco_keepalive_send(dev, CISCO_ADDR_REPLY, ++ addr, mask); ++ } ++ dev_kfree_skb_any(skb); ++ return NET_RX_SUCCESS; ++ ++ case CISCO_ADDR_REPLY: ++ printk(KERN_INFO "%s: Unexpected Cisco IP address " ++ "reply\n", dev->name); ++ goto rx_error; ++ ++ case CISCO_KEEPALIVE_REQ: ++ hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); ++ if (hdlc->state.cisco.request_sent && ++ ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { ++ hdlc->state.cisco.last_poll = jiffies; ++ if (!hdlc->state.cisco.up) { ++ u32 sec, min, hrs, days; ++ sec = ntohl(cisco_data->time) / 1000; ++ min = sec / 60; sec -= min * 60; ++ hrs = min / 60; min -= hrs * 60; ++ days = hrs / 24; hrs -= days * 24; ++ printk(KERN_INFO "%s: Link up (peer " ++ "uptime %ud%uh%um%us)\n", ++ dev->name, days, hrs, ++ min, sec); ++#if 0 ++ netif_carrier_on(dev); ++#endif ++ hdlc->state.cisco.up = 1; ++ } ++ } ++ ++ dev_kfree_skb_any(skb); ++ return NET_RX_SUCCESS; ++ } /* switch(keepalive type) */ ++ } /* switch(protocol) */ ++ ++ printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, ++ data->protocol); ++ dev_kfree_skb_any(skb); ++ return NET_RX_DROP; ++ ++ rx_error: ++ hdlc->stats.rx_errors++; /* Mark error */ ++ dev_kfree_skb_any(skb); ++ return NET_RX_DROP; ++} ++ ++ ++ ++static void cisco_timer(unsigned long arg) ++{ ++ struct net_device *dev = (struct net_device *)arg; ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ ++ if (hdlc->state.cisco.up && ++ time_after(jiffies, hdlc->state.cisco.last_poll + ++ hdlc->state.cisco.settings.timeout * HZ)) { ++ hdlc->state.cisco.up = 0; ++ printk(KERN_INFO "%s: Link down\n", dev->name); ++#if 0 ++ netif_carrier_off(dev); ++#endif ++ } ++ ++ cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, ++ ++hdlc->state.cisco.txseq, ++ hdlc->state.cisco.rxseq); ++ hdlc->state.cisco.request_sent = 1; ++ hdlc->state.cisco.timer.expires = jiffies + ++ hdlc->state.cisco.settings.interval * HZ; ++ hdlc->state.cisco.timer.function = cisco_timer; ++ hdlc->state.cisco.timer.data = arg; ++ add_timer(&hdlc->state.cisco.timer); ++} ++ ++ ++ ++static void cisco_start(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ hdlc->state.cisco.up = 0; ++ hdlc->state.cisco.request_sent = 0; ++ hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0; ++ ++ init_timer(&hdlc->state.cisco.timer); ++ hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/ ++ hdlc->state.cisco.timer.function = cisco_timer; ++ hdlc->state.cisco.timer.data = (unsigned long)dev; ++ add_timer(&hdlc->state.cisco.timer); ++} ++ ++ ++ ++static void cisco_stop(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ del_timer_sync(&hdlc->state.cisco.timer); ++#if 0 ++ if (netif_carrier_ok(dev)) ++ netif_carrier_off(dev); ++#endif ++ hdlc->state.cisco.up = 0; ++ hdlc->state.cisco.request_sent = 0; ++} ++ ++ ++ ++int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) ++{ ++ cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; ++ const size_t size = sizeof(cisco_proto); ++ cisco_proto new_settings; ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ int result; ++ ++ switch (ifr->ifr_settings.type) { ++ case IF_GET_PROTO: ++ ifr->ifr_settings.type = IF_PROTO_CISCO; ++ if (ifr->ifr_settings.size < size) { ++ ifr->ifr_settings.size = size; /* data size wanted */ ++ return -ENOBUFS; ++ } ++ if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size)) ++ return -EFAULT; ++ return 0; ++ ++ case IF_PROTO_CISCO: ++ if(!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if(dev->flags & IFF_UP) ++ return -EBUSY; ++ ++ if (copy_from_user(&new_settings, cisco_s, size)) ++ return -EFAULT; ++ ++ if (new_settings.interval < 1 || ++ new_settings.timeout < 2) ++ return -EINVAL; ++ ++ result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); ++ ++ if (result) ++ return result; ++ ++ hdlc_proto_detach(hdlc); ++ memcpy(&hdlc->state.cisco.settings, &new_settings, size); ++ memset(&hdlc->proto, 0, sizeof(hdlc->proto)); ++ ++ hdlc->proto.start = cisco_start; ++ hdlc->proto.stop = cisco_stop; ++ hdlc->proto.netif_rx = cisco_rx; ++ hdlc->proto.type_trans = cisco_type_trans; ++ hdlc->proto.id = IF_PROTO_CISCO; ++ dev->hard_start_xmit = hdlc->xmit; ++ dev->hard_header = cisco_hard_header; ++ dev->hard_header_cache = NULL; ++ dev->type = ARPHRD_CISCO; ++ dev->flags = IFF_POINTOPOINT | IFF_NOARP; ++ dev->addr_len = 0; ++ return 0; ++ } ++ ++ return -EINVAL; ++} +diff -Nru linux-source-4.19/drivers/dahdi/datamods/hdlc_fr.c linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_fr.c +--- linux-source-4.19/drivers/dahdi/datamods/hdlc_fr.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_fr.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,1284 @@ ++/* ++ * Generic HDLC support routines for Linux ++ * Frame Relay support ++ * ++ * Copyright (C) 1999 - 2005 Krzysztof Halasa ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License ++ * as published by the Free Software Foundation. ++ * ++ ++ Theory of PVC state ++ ++ DCE mode: ++ ++ (exist,new) -> 0,0 when "PVC create" or if "link unreliable" ++ 0,x -> 1,1 if "link reliable" when sending FULL STATUS ++ 1,1 -> 1,0 if received FULL STATUS ACK ++ ++ (active) -> 0 when "ifconfig PVC down" or "link unreliable" or "PVC create" ++ -> 1 when "PVC up" and (exist,new) = 1,0 ++ ++ DTE mode: ++ (exist,new,active) = FULL STATUS if "link reliable" ++ = 0, 0, 0 if "link unreliable" ++ No LMI: ++ active = open and "link reliable" ++ exist = new = not used ++ ++ CCITT LMI: ITU-T Q.933 Annex A ++ ANSI LMI: ANSI T1.617 Annex D ++ CISCO LMI: the original, aka "Gang of Four" LMI ++ ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#undef DEBUG_PKT ++#undef DEBUG_ECN ++#undef DEBUG_LINK ++ ++#define FR_UI 0x03 ++#define FR_PAD 0x00 ++ ++#define NLPID_IP 0xCC ++#define NLPID_IPV6 0x8E ++#define NLPID_SNAP 0x80 ++#define NLPID_PAD 0x00 ++#define NLPID_CCITT_ANSI_LMI 0x08 ++#define NLPID_CISCO_LMI 0x09 ++ ++ ++#define LMI_CCITT_ANSI_DLCI 0 /* LMI DLCI */ ++#define LMI_CISCO_DLCI 1023 ++ ++#define LMI_CALLREF 0x00 /* Call Reference */ ++#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI locking shift */ ++#define LMI_ANSI_CISCO_REPTYPE 0x01 /* report type */ ++#define LMI_CCITT_REPTYPE 0x51 ++#define LMI_ANSI_CISCO_ALIVE 0x03 /* keep alive */ ++#define LMI_CCITT_ALIVE 0x53 ++#define LMI_ANSI_CISCO_PVCSTAT 0x07 /* PVC status */ ++#define LMI_CCITT_PVCSTAT 0x57 ++ ++#define LMI_FULLREP 0x00 /* full report */ ++#define LMI_INTEGRITY 0x01 /* link integrity report */ ++#define LMI_SINGLE 0x02 /* single PVC report */ ++ ++#define LMI_STATUS_ENQUIRY 0x75 ++#define LMI_STATUS 0x7D /* reply */ ++ ++#define LMI_REPT_LEN 1 /* report type element length */ ++#define LMI_INTEG_LEN 2 /* link integrity element length */ ++ ++#define LMI_CCITT_CISCO_LENGTH 13 /* LMI frame lengths */ ++#define LMI_ANSI_LENGTH 14 ++ ++ ++typedef struct { ++#if defined(__LITTLE_ENDIAN_BITFIELD) ++ unsigned ea1: 1; ++ unsigned cr: 1; ++ unsigned dlcih: 6; ++ ++ unsigned ea2: 1; ++ unsigned de: 1; ++ unsigned becn: 1; ++ unsigned fecn: 1; ++ unsigned dlcil: 4; ++#else ++ unsigned dlcih: 6; ++ unsigned cr: 1; ++ unsigned ea1: 1; ++ ++ unsigned dlcil: 4; ++ unsigned fecn: 1; ++ unsigned becn: 1; ++ unsigned de: 1; ++ unsigned ea2: 1; ++#endif ++}__attribute__ ((packed)) fr_hdr; ++ ++ ++static inline u16 q922_to_dlci(u8 *hdr) ++{ ++ return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4); ++} ++ ++ ++ ++static inline void dlci_to_q922(u8 *hdr, u16 dlci) ++{ ++ hdr[0] = (dlci >> 2) & 0xFC; ++ hdr[1] = ((dlci << 4) & 0xF0) | 0x01; ++} ++ ++ ++ ++static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) ++{ ++ pvc_device *pvc = hdlc->state.fr.first_pvc; ++ ++ while (pvc) { ++ if (pvc->dlci == dlci) ++ return pvc; ++ if (pvc->dlci > dlci) ++ return NULL; /* the listed is sorted */ ++ pvc = pvc->next; ++ } ++ ++ return NULL; ++} ++ ++ ++static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc; ++ ++ while (*pvc_p) { ++ if ((*pvc_p)->dlci == dlci) ++ return *pvc_p; ++ if ((*pvc_p)->dlci > dlci) ++ break; /* the list is sorted */ ++ pvc_p = &(*pvc_p)->next; ++ } ++ ++ pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); ++ if (!pvc) ++ return NULL; ++ ++ memset(pvc, 0, sizeof(pvc_device)); ++ pvc->dlci = dlci; ++ pvc->master = dev; ++ pvc->next = *pvc_p; /* Put it in the chain */ ++ *pvc_p = pvc; ++ return pvc; ++} ++ ++ ++static inline int pvc_is_used(pvc_device *pvc) ++{ ++ return pvc->main != NULL || pvc->ether != NULL; ++} ++ ++ ++static inline void pvc_carrier(int on, pvc_device *pvc) ++{ ++ if (on) { ++ if (pvc->main) ++ if (!netif_carrier_ok(pvc->main)) ++ netif_carrier_on(pvc->main); ++ if (pvc->ether) ++ if (!netif_carrier_ok(pvc->ether)) ++ netif_carrier_on(pvc->ether); ++ } else { ++ if (pvc->main) ++ if (netif_carrier_ok(pvc->main)) ++ netif_carrier_off(pvc->main); ++ if (pvc->ether) ++ if (netif_carrier_ok(pvc->ether)) ++ netif_carrier_off(pvc->ether); ++ } ++} ++ ++ ++static inline void delete_unused_pvcs(hdlc_device *hdlc) ++{ ++ pvc_device **pvc_p = &hdlc->state.fr.first_pvc; ++ ++ while (*pvc_p) { ++ if (!pvc_is_used(*pvc_p)) { ++ pvc_device *pvc = *pvc_p; ++ *pvc_p = pvc->next; ++ kfree(pvc); ++ continue; ++ } ++ pvc_p = &(*pvc_p)->next; ++ } ++} ++ ++ ++static inline struct net_device** get_dev_p(pvc_device *pvc, int type) ++{ ++ if (type == ARPHRD_ETHER) ++ return &pvc->ether; ++ else ++ return &pvc->main; ++} ++ ++ ++static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) ++{ ++ u16 head_len; ++ struct sk_buff *skb = *skb_p; ++ ++ switch (skb->protocol) { ++ case __constant_ntohs(NLPID_CCITT_ANSI_LMI): ++ head_len = 4; ++ skb_push(skb, head_len); ++ skb->data[3] = NLPID_CCITT_ANSI_LMI; ++ break; ++ ++ case __constant_ntohs(NLPID_CISCO_LMI): ++ head_len = 4; ++ skb_push(skb, head_len); ++ skb->data[3] = NLPID_CISCO_LMI; ++ break; ++ ++ case __constant_ntohs(ETH_P_IP): ++ head_len = 4; ++ skb_push(skb, head_len); ++ skb->data[3] = NLPID_IP; ++ break; ++ ++ case __constant_ntohs(ETH_P_IPV6): ++ head_len = 4; ++ skb_push(skb, head_len); ++ skb->data[3] = NLPID_IPV6; ++ break; ++ ++ case __constant_ntohs(ETH_P_802_3): ++ head_len = 10; ++ if (skb_headroom(skb) < head_len) { ++ struct sk_buff *skb2 = skb_realloc_headroom(skb, ++ head_len); ++ if (!skb2) ++ return -ENOBUFS; ++ dev_kfree_skb(skb); ++ skb = *skb_p = skb2; ++ } ++ skb_push(skb, head_len); ++ skb->data[3] = FR_PAD; ++ skb->data[4] = NLPID_SNAP; ++ skb->data[5] = FR_PAD; ++ skb->data[6] = 0x80; ++ skb->data[7] = 0xC2; ++ skb->data[8] = 0x00; ++ skb->data[9] = 0x07; /* bridged Ethernet frame w/out FCS */ ++ break; ++ ++ default: ++ head_len = 10; ++ skb_push(skb, head_len); ++ skb->data[3] = FR_PAD; ++ skb->data[4] = NLPID_SNAP; ++ skb->data[5] = FR_PAD; ++ skb->data[6] = FR_PAD; ++ skb->data[7] = FR_PAD; ++ *(u16*)(skb->data + 8) = skb->protocol; ++ } ++ ++ dlci_to_q922(skb->data, dlci); ++ skb->data[2] = FR_UI; ++ return 0; ++} ++ ++ ++ ++static int pvc_open(struct net_device *dev) ++{ ++ pvc_device *pvc = dev_to_pvc(dev); ++ ++ if ((pvc->master->flags & IFF_UP) == 0) ++ return -EIO; /* Master must be UP in order to activate PVC */ ++ ++ if (pvc->open_count++ == 0) { ++ hdlc_device *hdlc = dev_to_hdlc(pvc->master); ++ if (hdlc->state.fr.settings.lmi == LMI_NONE) ++ pvc->state.active = hdlc->carrier; ++ ++ pvc_carrier(pvc->state.active, pvc); ++ hdlc->state.fr.dce_changed = 1; ++ } ++ return 0; ++} ++ ++ ++ ++static int pvc_close(struct net_device *dev) ++{ ++ pvc_device *pvc = dev_to_pvc(dev); ++ ++ if (--pvc->open_count == 0) { ++ hdlc_device *hdlc = dev_to_hdlc(pvc->master); ++ if (hdlc->state.fr.settings.lmi == LMI_NONE) ++ pvc->state.active = 0; ++ ++ if (hdlc->state.fr.settings.dce) { ++ hdlc->state.fr.dce_changed = 1; ++ pvc->state.active = 0; ++ } ++ } ++ return 0; ++} ++ ++ ++ ++static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ pvc_device *pvc = dev_to_pvc(dev); ++ fr_proto_pvc_info info; ++ ++ if (ifr->ifr_settings.type == IF_GET_PROTO) { ++ if (dev->type == ARPHRD_ETHER) ++ ifr->ifr_settings.type = IF_PROTO_FR_ETH_PVC; ++ else ++ ifr->ifr_settings.type = IF_PROTO_FR_PVC; ++ ++ if (ifr->ifr_settings.size < sizeof(info)) { ++ /* data size wanted */ ++ ifr->ifr_settings.size = sizeof(info); ++ return -ENOBUFS; ++ } ++ ++ info.dlci = pvc->dlci; ++ memcpy(info.master, pvc->master->name, IFNAMSIZ); ++ if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, ++ &info, sizeof(info))) ++ return -EFAULT; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++ ++static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) ++{ ++ return netdev_priv(dev); ++} ++ ++ ++ ++static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ pvc_device *pvc = dev_to_pvc(dev); ++ struct net_device_stats *stats = pvc_get_stats(dev); ++ ++ if (pvc->state.active) { ++ if (dev->type == ARPHRD_ETHER) { ++ int pad = ETH_ZLEN - skb->len; ++ if (pad > 0) { /* Pad the frame with zeros */ ++ int len = skb->len; ++ if (skb_tailroom(skb) < pad) ++ if (pskb_expand_head(skb, 0, pad, ++ GFP_ATOMIC)) { ++ stats->tx_dropped++; ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ skb_put(skb, pad); ++ memset(skb->data + len, 0, pad); ++ } ++ skb->protocol = __constant_htons(ETH_P_802_3); ++ } ++ if (!fr_hard_header(&skb, pvc->dlci)) { ++ stats->tx_bytes += skb->len; ++ stats->tx_packets++; ++ if (pvc->state.fecn) /* TX Congestion counter */ ++ stats->tx_compressed++; ++ skb->dev = pvc->master; ++ dev_queue_xmit(skb); ++ return 0; ++ } ++ } ++ ++ stats->tx_dropped++; ++ dev_kfree_skb(skb); ++ return 0; ++} ++ ++ ++ ++static int pvc_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) ++ return -EINVAL; ++ dev->mtu = new_mtu; ++ return 0; ++} ++ ++ ++ ++static inline void fr_log_dlci_active(pvc_device *pvc) ++{ ++ printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", ++ pvc->master->name, ++ pvc->dlci, ++ pvc->main ? pvc->main->name : "", ++ pvc->main && pvc->ether ? " " : "", ++ pvc->ether ? pvc->ether->name : "", ++ pvc->state.new ? " new" : "", ++ !pvc->state.exist ? "deleted" : ++ pvc->state.active ? "active" : "inactive"); ++} ++ ++ ++ ++static inline u8 fr_lmi_nextseq(u8 x) ++{ ++ x++; ++ return x ? x : 1; ++} ++ ++ ++ ++static void fr_lmi_send(struct net_device *dev, int fullrep) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ struct sk_buff *skb; ++ pvc_device *pvc = hdlc->state.fr.first_pvc; ++ int lmi = hdlc->state.fr.settings.lmi; ++ int dce = hdlc->state.fr.settings.dce; ++ int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH; ++ int stat_len = (lmi == LMI_CISCO) ? 6 : 3; ++ u8 *data; ++ int i = 0; ++ ++ if (dce && fullrep) { ++ len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); ++ if (len > HDLC_MAX_MRU) { ++ printk(KERN_WARNING "%s: Too many PVCs while sending " ++ "LMI full report\n", dev->name); ++ return; ++ } ++ } ++ ++ skb = dev_alloc_skb(len); ++ if (!skb) { ++ printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n", ++ dev->name); ++ return; ++ } ++ memset(skb->data, 0, len); ++ skb_reserve(skb, 4); ++ if (lmi == LMI_CISCO) { ++ skb->protocol = __constant_htons(NLPID_CISCO_LMI); ++ fr_hard_header(&skb, LMI_CISCO_DLCI); ++ } else { ++ skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI); ++ fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); ++ } ++ data = skb->tail; ++ data[i++] = LMI_CALLREF; ++ data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY; ++ if (lmi == LMI_ANSI) ++ data[i++] = LMI_ANSI_LOCKSHIFT; ++ data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : ++ LMI_ANSI_CISCO_REPTYPE; ++ data[i++] = LMI_REPT_LEN; ++ data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY; ++ data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE; ++ data[i++] = LMI_INTEG_LEN; ++ data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq); ++ data[i++] = hdlc->state.fr.rxseq; ++ ++ if (dce && fullrep) { ++ while (pvc) { ++ data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : ++ LMI_ANSI_CISCO_PVCSTAT; ++ data[i++] = stat_len; ++ ++ /* LMI start/restart */ ++ if (hdlc->state.fr.reliable && !pvc->state.exist) { ++ pvc->state.exist = pvc->state.new = 1; ++ fr_log_dlci_active(pvc); ++ } ++ ++ /* ifconfig PVC up */ ++ if (pvc->open_count && !pvc->state.active && ++ pvc->state.exist && !pvc->state.new) { ++ pvc_carrier(1, pvc); ++ pvc->state.active = 1; ++ fr_log_dlci_active(pvc); ++ } ++ ++ if (lmi == LMI_CISCO) { ++ data[i] = pvc->dlci >> 8; ++ data[i + 1] = pvc->dlci & 0xFF; ++ } else { ++ data[i] = (pvc->dlci >> 4) & 0x3F; ++ data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80; ++ data[i + 2] = 0x80; ++ } ++ ++ if (pvc->state.new) ++ data[i + 2] |= 0x08; ++ else if (pvc->state.active) ++ data[i + 2] |= 0x02; ++ ++ i += stat_len; ++ pvc = pvc->next; ++ } ++ } ++ ++ skb_put(skb, i); ++ skb->priority = TC_PRIO_CONTROL; ++ skb->dev = dev; ++ skb->nh.raw = skb->data; ++ ++ dev_queue_xmit(skb); ++} ++ ++ ++ ++static void fr_set_link_state(int reliable, struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ pvc_device *pvc = hdlc->state.fr.first_pvc; ++ ++ hdlc->state.fr.reliable = reliable; ++ if (reliable) { ++#if 0 ++ if (!netif_carrier_ok(dev)) ++ netif_carrier_on(dev); ++#endif ++ ++ hdlc->state.fr.n391cnt = 0; /* Request full status */ ++ hdlc->state.fr.dce_changed = 1; ++ ++ if (hdlc->state.fr.settings.lmi == LMI_NONE) { ++ while (pvc) { /* Activate all PVCs */ ++ pvc_carrier(1, pvc); ++ pvc->state.exist = pvc->state.active = 1; ++ pvc->state.new = 0; ++ pvc = pvc->next; ++ } ++ } ++ } else { ++#if 0 ++ if (netif_carrier_ok(dev)) ++ netif_carrier_off(dev); ++#endif ++ ++ while (pvc) { /* Deactivate all PVCs */ ++ pvc_carrier(0, pvc); ++ pvc->state.exist = pvc->state.active = 0; ++ pvc->state.new = 0; ++ if (!hdlc->state.fr.settings.dce) ++ pvc->state.bandwidth = 0; ++ pvc = pvc->next; ++ } ++ } ++} ++ ++ ++ ++static void fr_timer(unsigned long arg) ++{ ++ struct net_device *dev = (struct net_device *)arg; ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ int i, cnt = 0, reliable; ++ u32 list; ++ ++ if (hdlc->state.fr.settings.dce) { ++ reliable = hdlc->state.fr.request && ++ time_before(jiffies, hdlc->state.fr.last_poll + ++ hdlc->state.fr.settings.t392 * HZ); ++ hdlc->state.fr.request = 0; ++ } else { ++ hdlc->state.fr.last_errors <<= 1; /* Shift the list */ ++ if (hdlc->state.fr.request) { ++ if (hdlc->state.fr.reliable) ++ printk(KERN_INFO "%s: No LMI status reply " ++ "received\n", dev->name); ++ hdlc->state.fr.last_errors |= 1; ++ } ++ ++ list = hdlc->state.fr.last_errors; ++ for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1) ++ cnt += (list & 1); /* errors count */ ++ ++ reliable = (cnt < hdlc->state.fr.settings.n392); ++ } ++ ++ if (hdlc->state.fr.reliable != reliable) { ++ printk(KERN_INFO "%s: Link %sreliable\n", dev->name, ++ reliable ? "" : "un"); ++ fr_set_link_state(reliable, dev); ++ } ++ ++ if (hdlc->state.fr.settings.dce) ++ hdlc->state.fr.timer.expires = jiffies + ++ hdlc->state.fr.settings.t392 * HZ; ++ else { ++ if (hdlc->state.fr.n391cnt) ++ hdlc->state.fr.n391cnt--; ++ ++ fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0); ++ ++ hdlc->state.fr.last_poll = jiffies; ++ hdlc->state.fr.request = 1; ++ hdlc->state.fr.timer.expires = jiffies + ++ hdlc->state.fr.settings.t391 * HZ; ++ } ++ ++ hdlc->state.fr.timer.function = fr_timer; ++ hdlc->state.fr.timer.data = arg; ++ add_timer(&hdlc->state.fr.timer); ++} ++ ++ ++ ++static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ pvc_device *pvc; ++ u8 rxseq, txseq; ++ int lmi = hdlc->state.fr.settings.lmi; ++ int dce = hdlc->state.fr.settings.dce; ++ int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i; ++ ++ if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : ++ LMI_CCITT_CISCO_LENGTH)) { ++ printk(KERN_INFO "%s: Short LMI frame\n", dev->name); ++ return 1; ++ } ++ ++ if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : ++ NLPID_CCITT_ANSI_LMI)) { ++ printk(KERN_INFO "%s: Received non-LMI frame with LMI" ++ " DLCI\n", dev->name); ++ return 1; ++ } ++ ++ if (skb->data[4] != LMI_CALLREF) { ++ printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n", ++ dev->name, skb->data[4]); ++ return 1; ++ } ++ ++ if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) { ++ printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n", ++ dev->name, skb->data[5]); ++ return 1; ++ } ++ ++ if (lmi == LMI_ANSI) { ++ if (skb->data[6] != LMI_ANSI_LOCKSHIFT) { ++ printk(KERN_INFO "%s: Not ANSI locking shift in LMI" ++ " message (0x%02X)\n", dev->name, skb->data[6]); ++ return 1; ++ } ++ i = 7; ++ } else ++ i = 6; ++ ++ if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : ++ LMI_ANSI_CISCO_REPTYPE)) { ++ printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n", ++ dev->name, skb->data[i]); ++ return 1; ++ } ++ ++ if (skb->data[++i] != LMI_REPT_LEN) { ++ printk(KERN_INFO "%s: Invalid LMI Report type IE length" ++ " (%u)\n", dev->name, skb->data[i]); ++ return 1; ++ } ++ ++ reptype = skb->data[++i]; ++ if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) { ++ printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n", ++ dev->name, reptype); ++ return 1; ++ } ++ ++ if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE : ++ LMI_ANSI_CISCO_ALIVE)) { ++ printk(KERN_INFO "%s: Not an LMI Link integrity verification" ++ " IE (0x%02X)\n", dev->name, skb->data[i]); ++ return 1; ++ } ++ ++ if (skb->data[++i] != LMI_INTEG_LEN) { ++ printk(KERN_INFO "%s: Invalid LMI Link integrity verification" ++ " IE length (%u)\n", dev->name, skb->data[i]); ++ return 1; ++ } ++ i++; ++ ++ hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */ ++ rxseq = skb->data[i++]; /* Should confirm our sequence */ ++ ++ txseq = hdlc->state.fr.txseq; ++ ++ if (dce) ++ hdlc->state.fr.last_poll = jiffies; ++ ++ error = 0; ++ if (!hdlc->state.fr.reliable) ++ error = 1; ++ ++ if (rxseq == 0 || rxseq != txseq) { ++ hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */ ++ error = 1; ++ } ++ ++ if (dce) { ++ if (hdlc->state.fr.fullrep_sent && !error) { ++/* Stop sending full report - the last one has been confirmed by DTE */ ++ hdlc->state.fr.fullrep_sent = 0; ++ pvc = hdlc->state.fr.first_pvc; ++ while (pvc) { ++ if (pvc->state.new) { ++ pvc->state.new = 0; ++ ++/* Tell DTE that new PVC is now active */ ++ hdlc->state.fr.dce_changed = 1; ++ } ++ pvc = pvc->next; ++ } ++ } ++ ++ if (hdlc->state.fr.dce_changed) { ++ reptype = LMI_FULLREP; ++ hdlc->state.fr.fullrep_sent = 1; ++ hdlc->state.fr.dce_changed = 0; ++ } ++ ++ hdlc->state.fr.request = 1; /* got request */ ++ fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); ++ return 0; ++ } ++ ++ /* DTE */ ++ ++ hdlc->state.fr.request = 0; /* got response, no request pending */ ++ ++ if (error) ++ return 0; ++ ++ if (reptype != LMI_FULLREP) ++ return 0; ++ ++ pvc = hdlc->state.fr.first_pvc; ++ ++ while (pvc) { ++ pvc->state.deleted = 1; ++ pvc = pvc->next; ++ } ++ ++ no_ram = 0; ++ while (skb->len >= i + 2 + stat_len) { ++ u16 dlci; ++ u32 bw; ++ unsigned int active, new; ++ ++ if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : ++ LMI_ANSI_CISCO_PVCSTAT)) { ++ printk(KERN_INFO "%s: Not an LMI PVC status IE" ++ " (0x%02X)\n", dev->name, skb->data[i]); ++ return 1; ++ } ++ ++ if (skb->data[++i] != stat_len) { ++ printk(KERN_INFO "%s: Invalid LMI PVC status IE length" ++ " (%u)\n", dev->name, skb->data[i]); ++ return 1; ++ } ++ i++; ++ ++ new = !! (skb->data[i + 2] & 0x08); ++ active = !! (skb->data[i + 2] & 0x02); ++ if (lmi == LMI_CISCO) { ++ dlci = (skb->data[i] << 8) | skb->data[i + 1]; ++ bw = (skb->data[i + 3] << 16) | ++ (skb->data[i + 4] << 8) | ++ (skb->data[i + 5]); ++ } else { ++ dlci = ((skb->data[i] & 0x3F) << 4) | ++ ((skb->data[i + 1] & 0x78) >> 3); ++ bw = 0; ++ } ++ ++ pvc = add_pvc(dev, dlci); ++ ++ if (!pvc && !no_ram) { ++ printk(KERN_WARNING ++ "%s: Memory squeeze on fr_lmi_recv()\n", ++ dev->name); ++ no_ram = 1; ++ } ++ ++ if (pvc) { ++ pvc->state.exist = 1; ++ pvc->state.deleted = 0; ++ if (active != pvc->state.active || ++ new != pvc->state.new || ++ bw != pvc->state.bandwidth || ++ !pvc->state.exist) { ++ pvc->state.new = new; ++ pvc->state.active = active; ++ pvc->state.bandwidth = bw; ++ pvc_carrier(active, pvc); ++ fr_log_dlci_active(pvc); ++ } ++ } ++ ++ i += stat_len; ++ } ++ ++ pvc = hdlc->state.fr.first_pvc; ++ ++ while (pvc) { ++ if (pvc->state.deleted && pvc->state.exist) { ++ pvc_carrier(0, pvc); ++ pvc->state.active = pvc->state.new = 0; ++ pvc->state.exist = 0; ++ pvc->state.bandwidth = 0; ++ fr_log_dlci_active(pvc); ++ } ++ pvc = pvc->next; ++ } ++ ++ /* Next full report after N391 polls */ ++ hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391; ++ ++ return 0; ++} ++ ++ ++ ++static int fr_rx(struct sk_buff *skb) ++{ ++ struct net_device *ndev = skb->dev; ++ hdlc_device *hdlc = dev_to_hdlc(ndev); ++ fr_hdr *fh = (fr_hdr*)skb->data; ++ u8 *data = skb->data; ++ u16 dlci; ++ pvc_device *pvc; ++ struct net_device *dev = NULL; ++ ++ if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI) ++ goto rx_error; ++ ++ dlci = q922_to_dlci(skb->data); ++ ++ if ((dlci == LMI_CCITT_ANSI_DLCI && ++ (hdlc->state.fr.settings.lmi == LMI_ANSI || ++ hdlc->state.fr.settings.lmi == LMI_CCITT)) || ++ (dlci == LMI_CISCO_DLCI && ++ hdlc->state.fr.settings.lmi == LMI_CISCO)) { ++ if (fr_lmi_recv(ndev, skb)) ++ goto rx_error; ++ dev_kfree_skb_any(skb); ++ return NET_RX_SUCCESS; ++ } ++ ++ pvc = find_pvc(hdlc, dlci); ++ if (!pvc) { ++#ifdef DEBUG_PKT ++ printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", ++ ndev->name, dlci); ++#endif ++ dev_kfree_skb_any(skb); ++ return NET_RX_DROP; ++ } ++ ++ if (pvc->state.fecn != fh->fecn) { ++#ifdef DEBUG_ECN ++ printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name, ++ dlci, fh->fecn ? "N" : "FF"); ++#endif ++ pvc->state.fecn ^= 1; ++ } ++ ++ if (pvc->state.becn != fh->becn) { ++#ifdef DEBUG_ECN ++ printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name, ++ dlci, fh->becn ? "N" : "FF"); ++#endif ++ pvc->state.becn ^= 1; ++ } ++ ++ ++ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { ++ hdlc->stats.rx_dropped++; ++ return NET_RX_DROP; ++ } ++ ++ if (data[3] == NLPID_IP) { ++ skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ ++ dev = pvc->main; ++ skb->protocol = htons(ETH_P_IP); ++ ++ } else if (data[3] == NLPID_IPV6) { ++ skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ ++ dev = pvc->main; ++ skb->protocol = htons(ETH_P_IPV6); ++ ++ } else if (skb->len > 10 && data[3] == FR_PAD && ++ data[4] == NLPID_SNAP && data[5] == FR_PAD) { ++ u16 oui = ntohs(*(u16*)(data + 6)); ++ u16 pid = ntohs(*(u16*)(data + 8)); ++ skb_pull(skb, 10); ++ ++ switch ((((u32)oui) << 16) | pid) { ++ case ETH_P_ARP: /* routed frame with SNAP */ ++ case ETH_P_IPX: ++ case ETH_P_IP: /* a long variant */ ++ case ETH_P_IPV6: ++ dev = pvc->main; ++ skb->protocol = htons(pid); ++ break; ++ ++ case 0x80C20007: /* bridged Ethernet frame */ ++ if ((dev = pvc->ether) != NULL) ++ skb->protocol = eth_type_trans(skb, dev); ++ break; ++ ++ default: ++ printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " ++ "PID=%x\n", ndev->name, oui, pid); ++ dev_kfree_skb_any(skb); ++ return NET_RX_DROP; ++ } ++ } else { ++ printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " ++ "length = %i\n", ndev->name, data[3], skb->len); ++ dev_kfree_skb_any(skb); ++ return NET_RX_DROP; ++ } ++ ++ if (dev) { ++ struct net_device_stats *stats = pvc_get_stats(dev); ++ stats->rx_packets++; /* PVC traffic */ ++ stats->rx_bytes += skb->len; ++ if (pvc->state.becn) ++ stats->rx_compressed++; ++ skb->dev = dev; ++ netif_rx(skb); ++ return NET_RX_SUCCESS; ++ } else { ++ dev_kfree_skb_any(skb); ++ return NET_RX_DROP; ++ } ++ ++ rx_error: ++ hdlc->stats.rx_errors++; /* Mark error */ ++ dev_kfree_skb_any(skb); ++ return NET_RX_DROP; ++} ++ ++ ++ ++static void fr_start(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++#ifdef DEBUG_LINK ++ printk(KERN_DEBUG "fr_start\n"); ++#endif ++ if (hdlc->state.fr.settings.lmi != LMI_NONE) { ++ hdlc->state.fr.reliable = 0; ++ hdlc->state.fr.dce_changed = 1; ++ hdlc->state.fr.request = 0; ++ hdlc->state.fr.fullrep_sent = 0; ++ hdlc->state.fr.last_errors = 0xFFFFFFFF; ++ hdlc->state.fr.n391cnt = 0; ++ hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0; ++ ++ init_timer(&hdlc->state.fr.timer); ++ /* First poll after 1 s */ ++ hdlc->state.fr.timer.expires = jiffies + HZ; ++ hdlc->state.fr.timer.function = fr_timer; ++ hdlc->state.fr.timer.data = (unsigned long)dev; ++ add_timer(&hdlc->state.fr.timer); ++ } else ++ fr_set_link_state(1, dev); ++} ++ ++ ++ ++static void fr_stop(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++#ifdef DEBUG_LINK ++ printk(KERN_DEBUG "fr_stop\n"); ++#endif ++ if (hdlc->state.fr.settings.lmi != LMI_NONE) ++ del_timer_sync(&hdlc->state.fr.timer); ++ fr_set_link_state(0, dev); ++} ++ ++ ++ ++static void fr_close(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ pvc_device *pvc = hdlc->state.fr.first_pvc; ++ ++ while (pvc) { /* Shutdown all PVCs for this FRAD */ ++ if (pvc->main) ++ dev_close(pvc->main); ++ if (pvc->ether) ++ dev_close(pvc->ether); ++ pvc = pvc->next; ++ } ++} ++ ++static void dlci_setup(struct net_device *dev) ++{ ++ dev->type = ARPHRD_DLCI; ++ dev->flags = IFF_POINTOPOINT; ++ dev->hard_header_len = 10; ++ dev->addr_len = 2; ++} ++ ++static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(master); ++ pvc_device *pvc = NULL; ++ struct net_device *dev; ++ int result, used; ++ char * prefix = "pvc%d"; ++ ++ if (type == ARPHRD_ETHER) ++ prefix = "pvceth%d"; ++ ++ if ((pvc = add_pvc(master, dlci)) == NULL) { ++ printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", ++ master->name); ++ return -ENOBUFS; ++ } ++ ++ if (*get_dev_p(pvc, type)) ++ return -EEXIST; ++ ++ used = pvc_is_used(pvc); ++ ++ if (type == ARPHRD_ETHER) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ dev = alloc_netdev(sizeof(struct net_device_stats), ++ "pvceth%d", NET_NAME_UNKNOWN, ether_setup); ++#else ++ dev = alloc_netdev(sizeof(struct net_device_stats), ++ "pvceth%d", ether_setup); ++#endif ++ } else { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ dev = alloc_netdev(sizeof(struct net_device_stats), ++ "pvc%d", NET_NAME_UNKNOWN, dlci_setup); ++#else ++ dev = alloc_netdev(sizeof(struct net_device_stats), ++ "pvc%d", dlci_setup); ++#endif ++ } ++ ++ if (!dev) { ++ printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", ++ master->name); ++ delete_unused_pvcs(hdlc); ++ return -ENOBUFS; ++ } ++ ++ if (type == ARPHRD_ETHER) { ++ memcpy(dev->dev_addr, "\x00\x01", 2); ++ get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); ++ } else { ++ *(u16*)dev->dev_addr = htons(dlci); ++ dlci_to_q922(dev->broadcast, dlci); ++ } ++ dev->hard_start_xmit = pvc_xmit; ++ dev->get_stats = pvc_get_stats; ++ dev->open = pvc_open; ++ dev->stop = pvc_close; ++ dev->do_ioctl = pvc_ioctl; ++ dev->change_mtu = pvc_change_mtu; ++ dev->mtu = HDLC_MAX_MTU; ++ dev->tx_queue_len = 0; ++ dev->priv = pvc; ++ ++ result = dev_alloc_name(dev, dev->name); ++ if (result < 0) { ++ free_netdev(dev); ++ delete_unused_pvcs(hdlc); ++ return result; ++ } ++ ++ if (register_netdevice(dev) != 0) { ++ free_netdev(dev); ++ delete_unused_pvcs(hdlc); ++ return -EIO; ++ } ++ ++ dev->destructor = free_netdev; ++ *get_dev_p(pvc, type) = dev; ++ if (!used) { ++ hdlc->state.fr.dce_changed = 1; ++ hdlc->state.fr.dce_pvc_count++; ++ } ++ return 0; ++} ++ ++ ++ ++static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type) ++{ ++ pvc_device *pvc; ++ struct net_device *dev; ++ ++ if ((pvc = find_pvc(hdlc, dlci)) == NULL) ++ return -ENOENT; ++ ++ if ((dev = *get_dev_p(pvc, type)) == NULL) ++ return -ENOENT; ++ ++ if (dev->flags & IFF_UP) ++ return -EBUSY; /* PVC in use */ ++ ++ unregister_netdevice(dev); /* the destructor will free_netdev(dev) */ ++ *get_dev_p(pvc, type) = NULL; ++ ++ if (!pvc_is_used(pvc)) { ++ hdlc->state.fr.dce_pvc_count--; ++ hdlc->state.fr.dce_changed = 1; ++ } ++ delete_unused_pvcs(hdlc); ++ return 0; ++} ++ ++ ++ ++static void fr_destroy(hdlc_device *hdlc) ++{ ++ pvc_device *pvc; ++ ++ pvc = hdlc->state.fr.first_pvc; ++ hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */ ++ hdlc->state.fr.dce_pvc_count = 0; ++ hdlc->state.fr.dce_changed = 1; ++ ++ while (pvc) { ++ pvc_device *next = pvc->next; ++ /* destructors will free_netdev() main and ether */ ++ if (pvc->main) ++ unregister_netdevice(pvc->main); ++ ++ if (pvc->ether) ++ unregister_netdevice(pvc->ether); ++ ++ kfree(pvc); ++ pvc = next; ++ } ++} ++ ++ ++ ++int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) ++{ ++ fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr; ++ const size_t size = sizeof(fr_proto); ++ fr_proto new_settings; ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ fr_proto_pvc pvc; ++ int result; ++ ++ switch (ifr->ifr_settings.type) { ++ case IF_GET_PROTO: ++ ifr->ifr_settings.type = IF_PROTO_FR; ++ if (ifr->ifr_settings.size < size) { ++ ifr->ifr_settings.size = size; /* data size wanted */ ++ return -ENOBUFS; ++ } ++ if (copy_to_user(fr_s, &hdlc->state.fr.settings, size)) ++ return -EFAULT; ++ return 0; ++ ++ case IF_PROTO_FR: ++ if(!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if(dev->flags & IFF_UP) ++ return -EBUSY; ++ ++ if (copy_from_user(&new_settings, fr_s, size)) ++ return -EFAULT; ++ ++ if (new_settings.lmi == LMI_DEFAULT) ++ new_settings.lmi = LMI_ANSI; ++ ++ if ((new_settings.lmi != LMI_NONE && ++ new_settings.lmi != LMI_ANSI && ++ new_settings.lmi != LMI_CCITT && ++ new_settings.lmi != LMI_CISCO) || ++ new_settings.t391 < 1 || ++ new_settings.t392 < 2 || ++ new_settings.n391 < 1 || ++ new_settings.n392 < 1 || ++ new_settings.n393 < new_settings.n392 || ++ new_settings.n393 > 32 || ++ (new_settings.dce != 0 && ++ new_settings.dce != 1)) ++ return -EINVAL; ++ ++ result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); ++ if (result) ++ return result; ++ ++ if (hdlc->proto.id != IF_PROTO_FR) { ++ hdlc_proto_detach(hdlc); ++ hdlc->state.fr.first_pvc = NULL; ++ hdlc->state.fr.dce_pvc_count = 0; ++ } ++ memcpy(&hdlc->state.fr.settings, &new_settings, size); ++ memset(&hdlc->proto, 0, sizeof(hdlc->proto)); ++ ++ hdlc->proto.close = fr_close; ++ hdlc->proto.start = fr_start; ++ hdlc->proto.stop = fr_stop; ++ hdlc->proto.detach = fr_destroy; ++ hdlc->proto.netif_rx = fr_rx; ++ hdlc->proto.id = IF_PROTO_FR; ++ dev->hard_start_xmit = hdlc->xmit; ++ dev->hard_header = NULL; ++ dev->type = ARPHRD_FRAD; ++ dev->flags = IFF_POINTOPOINT | IFF_NOARP; ++ dev->addr_len = 0; ++ return 0; ++ ++ case IF_PROTO_FR_ADD_PVC: ++ case IF_PROTO_FR_DEL_PVC: ++ case IF_PROTO_FR_ADD_ETH_PVC: ++ case IF_PROTO_FR_DEL_ETH_PVC: ++ if(!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (copy_from_user(&pvc, ifr->ifr_settings.ifs_ifsu.fr_pvc, ++ sizeof(fr_proto_pvc))) ++ return -EFAULT; ++ ++ if (pvc.dlci <= 0 || pvc.dlci >= 1024) ++ return -EINVAL; /* Only 10 bits, DLCI 0 reserved */ ++ ++ if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC || ++ ifr->ifr_settings.type == IF_PROTO_FR_DEL_ETH_PVC) ++ result = ARPHRD_ETHER; /* bridged Ethernet device */ ++ else ++ result = ARPHRD_DLCI; ++ ++ if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC || ++ ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC) ++ return fr_add_pvc(dev, pvc.dlci, result); ++ else ++ return fr_del_pvc(hdlc, pvc.dlci, result); ++ } ++ ++ return -EINVAL; ++} +diff -Nru linux-source-4.19/drivers/dahdi/datamods/hdlc_generic.c linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_generic.c +--- linux-source-4.19/drivers/dahdi/datamods/hdlc_generic.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_generic.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,360 @@ ++/* ++ * Generic HDLC support routines for Linux ++ * ++ * Copyright (C) 1999 - 2005 Krzysztof Halasa ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License ++ * as published by the Free Software Foundation. ++ * ++ * Currently supported: ++ * * raw IP-in-HDLC ++ * * Cisco HDLC ++ * * Frame Relay with ANSI or CCITT LMI (both user and network side) ++ * * PPP ++ * * X.25 ++ * ++ * Use sethdlc utility to set line parameters, protocol and PVCs ++ * ++ * How does it work: ++ * - proto.open(), close(), start(), stop() calls are serialized. ++ * The order is: open, [ start, stop ... ] close ... ++ * - proto.start() and stop() are called with spin_lock_irq held. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static const char* version = "HDLC support module revision 1.18"; ++ ++#undef DEBUG_LINK ++ ++ ++static int hdlc_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) ++ return -EINVAL; ++ dev->mtu = new_mtu; ++ return 0; ++} ++ ++ ++ ++static struct net_device_stats *hdlc_get_stats(struct net_device *dev) ++{ ++ return hdlc_stats(dev); ++} ++ ++ ++ ++static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, ++ struct packet_type *p, struct net_device *orig_dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ if (hdlc->proto.netif_rx) ++ return hdlc->proto.netif_rx(skb); ++ ++ hdlc->stats.rx_dropped++; /* Shouldn't happen */ ++ dev_kfree_skb(skb); ++ return NET_RX_DROP; ++} ++ ++ ++ ++static void __hdlc_set_carrier_on(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ if (hdlc->proto.start) ++ return hdlc->proto.start(dev); ++#if 0 ++#ifdef DEBUG_LINK ++ if (netif_carrier_ok(dev)) ++ printk(KERN_ERR "hdlc_set_carrier_on(): already on\n"); ++#endif ++ netif_carrier_on(dev); ++#endif ++} ++ ++ ++ ++static void __hdlc_set_carrier_off(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ if (hdlc->proto.stop) ++ return hdlc->proto.stop(dev); ++ ++#if 0 ++#ifdef DEBUG_LINK ++ if (!netif_carrier_ok(dev)) ++ printk(KERN_ERR "hdlc_set_carrier_off(): already off\n"); ++#endif ++ netif_carrier_off(dev); ++#endif ++} ++ ++ ++ ++void hdlc_set_carrier(int on, struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ unsigned long flags; ++ on = on ? 1 : 0; ++ ++#ifdef DEBUG_LINK ++ printk(KERN_DEBUG "hdlc_set_carrier %i\n", on); ++#endif ++ ++ spin_lock_irqsave(&hdlc->state_lock, flags); ++ ++ if (hdlc->carrier == on) ++ goto carrier_exit; /* no change in DCD line level */ ++ ++#ifdef DEBUG_LINK ++ printk(KERN_INFO "%s: carrier %s\n", dev->name, on ? "ON" : "off"); ++#endif ++ hdlc->carrier = on; ++ ++ if (!hdlc->open) ++ goto carrier_exit; ++ ++ if (hdlc->carrier) { ++ printk(KERN_INFO "%s: Carrier detected\n", dev->name); ++ __hdlc_set_carrier_on(dev); ++ } else { ++ printk(KERN_INFO "%s: Carrier lost\n", dev->name); ++ __hdlc_set_carrier_off(dev); ++ } ++ ++carrier_exit: ++ spin_unlock_irqrestore(&hdlc->state_lock, flags); ++} ++ ++ ++ ++/* Must be called by hardware driver when HDLC device is being opened */ ++int hdlc_open(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++#ifdef DEBUG_LINK ++ printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n", ++ hdlc->carrier, hdlc->open); ++#endif ++ ++ if (hdlc->proto.id == -1) ++ return -ENOSYS; /* no protocol attached */ ++ ++ if (hdlc->proto.open) { ++ int result = hdlc->proto.open(dev); ++ if (result) ++ return result; ++ } ++ ++ spin_lock_irq(&hdlc->state_lock); ++ ++ if (hdlc->carrier) { ++ printk(KERN_INFO "%s: Carrier detected\n", dev->name); ++ __hdlc_set_carrier_on(dev); ++ } else ++ printk(KERN_INFO "%s: No carrier\n", dev->name); ++ ++ hdlc->open = 1; ++ ++ spin_unlock_irq(&hdlc->state_lock); ++ return 0; ++} ++ ++ ++ ++/* Must be called by hardware driver when HDLC device is being closed */ ++void hdlc_close(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++#ifdef DEBUG_LINK ++ printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n", ++ hdlc->carrier, hdlc->open); ++#endif ++ ++ spin_lock_irq(&hdlc->state_lock); ++ ++ hdlc->open = 0; ++ if (hdlc->carrier) ++ __hdlc_set_carrier_off(dev); ++ ++ spin_unlock_irq(&hdlc->state_lock); ++ ++ if (hdlc->proto.close) ++ hdlc->proto.close(dev); ++} ++ ++ ++ ++#ifndef CONFIG_HDLC_RAW ++#define hdlc_raw_ioctl(dev, ifr) -ENOSYS ++#endif ++ ++#ifndef CONFIG_HDLC_RAW_ETH ++#define hdlc_raw_eth_ioctl(dev, ifr) -ENOSYS ++#endif ++ ++#ifndef CONFIG_HDLC_PPP ++#define hdlc_ppp_ioctl(dev, ifr) -ENOSYS ++#endif ++ ++#ifndef CONFIG_HDLC_CISCO ++#define hdlc_cisco_ioctl(dev, ifr) -ENOSYS ++#endif ++ ++#ifndef CONFIG_HDLC_FR ++#define hdlc_fr_ioctl(dev, ifr) -ENOSYS ++#endif ++ ++#ifndef CONFIG_HDLC_X25 ++#define hdlc_x25_ioctl(dev, ifr) -ENOSYS ++#endif ++ ++ ++int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ unsigned int proto; ++ ++ if (cmd != SIOCWANDEV) ++ return -EINVAL; ++ ++ switch(ifr->ifr_settings.type) { ++ case IF_PROTO_HDLC: ++ case IF_PROTO_HDLC_ETH: ++ case IF_PROTO_PPP: ++ case IF_PROTO_CISCO: ++ case IF_PROTO_FR: ++ case IF_PROTO_X25: ++ proto = ifr->ifr_settings.type; ++ break; ++ ++ default: ++ proto = hdlc->proto.id; ++ } ++ ++ switch(proto) { ++ case IF_PROTO_HDLC: return hdlc_raw_ioctl(dev, ifr); ++ case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr); ++ case IF_PROTO_PPP: return hdlc_ppp_ioctl(dev, ifr); ++ case IF_PROTO_CISCO: return hdlc_cisco_ioctl(dev, ifr); ++ case IF_PROTO_FR: return hdlc_fr_ioctl(dev, ifr); ++ case IF_PROTO_X25: return hdlc_x25_ioctl(dev, ifr); ++ default: return -EINVAL; ++ } ++} ++ ++static void hdlc_setup(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ ++ dev->get_stats = hdlc_get_stats; ++ dev->change_mtu = hdlc_change_mtu; ++ dev->mtu = HDLC_MAX_MTU; ++ ++ dev->type = ARPHRD_RAWHDLC; ++ dev->hard_header_len = 16; ++ ++ dev->flags = IFF_POINTOPOINT | IFF_NOARP; ++ ++ hdlc->proto.id = -1; ++ hdlc->proto.detach = NULL; ++ hdlc->carrier = 1; ++ hdlc->open = 0; ++ spin_lock_init(&hdlc->state_lock); ++} ++ ++struct net_device *alloc_hdlcdev(void *priv) ++{ ++ struct net_device *dev; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", ++ NET_NAME_UNKNOWN, hdlc_setup); ++#else ++ dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup); ++#endif ++ if (dev) ++ dev_to_hdlc(dev)->priv = priv; ++ return dev; ++} ++ ++int register_hdlc_device(struct net_device *dev) ++{ ++ int result = dev_alloc_name(dev, "hdlc%d"); ++ if (result < 0) ++ return result; ++ ++ result = register_netdev(dev); ++ if (result != 0) ++ return -EIO; ++ ++#if 0 ++ if (netif_carrier_ok(dev)) ++ netif_carrier_off(dev); /* no carrier until DCD goes up */ ++#endif ++ ++ return 0; ++} ++ ++ ++ ++void unregister_hdlc_device(struct net_device *dev) ++{ ++ rtnl_lock(); ++ hdlc_proto_detach(dev_to_hdlc(dev)); ++ unregister_netdevice(dev); ++ rtnl_unlock(); ++} ++ ++ ++ ++MODULE_AUTHOR("Krzysztof Halasa "); ++MODULE_DESCRIPTION("HDLC support module"); ++MODULE_LICENSE("GPL v2"); ++ ++EXPORT_SYMBOL(hdlc_open); ++EXPORT_SYMBOL(hdlc_close); ++EXPORT_SYMBOL(hdlc_set_carrier); ++EXPORT_SYMBOL(hdlc_ioctl); ++EXPORT_SYMBOL(alloc_hdlcdev); ++EXPORT_SYMBOL(register_hdlc_device); ++EXPORT_SYMBOL(unregister_hdlc_device); ++ ++static struct packet_type hdlc_packet_type = { ++ .type = __constant_htons(ETH_P_HDLC), ++ .func = hdlc_rcv, ++}; ++ ++ ++static int __init hdlc_module_init(void) ++{ ++ printk(KERN_INFO "%s\n", version); ++ dev_add_pack(&hdlc_packet_type); ++ return 0; ++} ++ ++ ++ ++static void __exit hdlc_module_exit(void) ++{ ++ dev_remove_pack(&hdlc_packet_type); ++} ++ ++ ++module_init(hdlc_module_init); ++module_exit(hdlc_module_exit); +diff -Nru linux-source-4.19/drivers/dahdi/datamods/hdlc_ppp.c linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_ppp.c +--- linux-source-4.19/drivers/dahdi/datamods/hdlc_ppp.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_ppp.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,114 @@ ++/* ++ * Generic HDLC support routines for Linux ++ * Point-to-point protocol support ++ * ++ * Copyright (C) 1999 - 2003 Krzysztof Halasa ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License ++ * as published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static int ppp_open(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ void *old_ioctl; ++ int result; ++ ++ dev->priv = &hdlc->state.ppp.syncppp_ptr; ++ hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev; ++ hdlc->state.ppp.pppdev.dev = dev; ++ ++ old_ioctl = dev->do_ioctl; ++ hdlc->state.ppp.old_change_mtu = dev->change_mtu; ++ sppp_attach(&hdlc->state.ppp.pppdev); ++ /* sppp_attach nukes them. We don't need syncppp's ioctl */ ++ dev->do_ioctl = old_ioctl; ++ hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO; ++ dev->type = ARPHRD_PPP; ++ result = sppp_open(dev); ++ if (result) { ++ sppp_detach(dev); ++ return result; ++ } ++ ++ return 0; ++} ++ ++ ++ ++static void ppp_close(struct net_device *dev) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ ++ sppp_close(dev); ++ sppp_detach(dev); ++ dev->rebuild_header = NULL; ++ dev->change_mtu = hdlc->state.ppp.old_change_mtu; ++ dev->mtu = HDLC_MAX_MTU; ++ dev->hard_header_len = 16; ++} ++ ++ ++ ++static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) ++{ ++ return __constant_htons(ETH_P_WAN_PPP); ++} ++ ++ ++ ++int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) ++{ ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ int result; ++ ++ switch (ifr->ifr_settings.type) { ++ case IF_GET_PROTO: ++ ifr->ifr_settings.type = IF_PROTO_PPP; ++ return 0; /* return protocol only, no settable parameters */ ++ ++ case IF_PROTO_PPP: ++ if(!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if(dev->flags & IFF_UP) ++ return -EBUSY; ++ ++ /* no settable parameters */ ++ ++ result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); ++ if (result) ++ return result; ++ ++ hdlc_proto_detach(hdlc); ++ memset(&hdlc->proto, 0, sizeof(hdlc->proto)); ++ ++ hdlc->proto.open = ppp_open; ++ hdlc->proto.close = ppp_close; ++ hdlc->proto.type_trans = ppp_type_trans; ++ hdlc->proto.id = IF_PROTO_PPP; ++ dev->hard_start_xmit = hdlc->xmit; ++ dev->hard_header = NULL; ++ dev->type = ARPHRD_PPP; ++ dev->addr_len = 0; ++ return 0; ++ } ++ ++ return -EINVAL; ++} +diff -Nru linux-source-4.19/drivers/dahdi/datamods/hdlc_raw.c linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_raw.c +--- linux-source-4.19/drivers/dahdi/datamods/hdlc_raw.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_raw.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,89 @@ ++/* ++ * Generic HDLC support routines for Linux ++ * HDLC support ++ * ++ * Copyright (C) 1999 - 2003 Krzysztof Halasa ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License ++ * as published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) ++{ ++ return __constant_htons(ETH_P_IP); ++} ++ ++ ++ ++int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) ++{ ++ raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; ++ const size_t size = sizeof(raw_hdlc_proto); ++ raw_hdlc_proto new_settings; ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ int result; ++ ++ switch (ifr->ifr_settings.type) { ++ case IF_GET_PROTO: ++ ifr->ifr_settings.type = IF_PROTO_HDLC; ++ if (ifr->ifr_settings.size < size) { ++ ifr->ifr_settings.size = size; /* data size wanted */ ++ return -ENOBUFS; ++ } ++ if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) ++ return -EFAULT; ++ return 0; ++ ++ case IF_PROTO_HDLC: ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (dev->flags & IFF_UP) ++ return -EBUSY; ++ ++ if (copy_from_user(&new_settings, raw_s, size)) ++ return -EFAULT; ++ ++ if (new_settings.encoding == ENCODING_DEFAULT) ++ new_settings.encoding = ENCODING_NRZ; ++ ++ if (new_settings.parity == PARITY_DEFAULT) ++ new_settings.parity = PARITY_CRC16_PR1_CCITT; ++ ++ result = hdlc->attach(dev, new_settings.encoding, ++ new_settings.parity); ++ if (result) ++ return result; ++ ++ hdlc_proto_detach(hdlc); ++ memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); ++ memset(&hdlc->proto, 0, sizeof(hdlc->proto)); ++ ++ hdlc->proto.type_trans = raw_type_trans; ++ hdlc->proto.id = IF_PROTO_HDLC; ++ dev->hard_start_xmit = hdlc->xmit; ++ dev->hard_header = NULL; ++ dev->type = ARPHRD_RAWHDLC; ++ dev->flags = IFF_POINTOPOINT | IFF_NOARP; ++ dev->addr_len = 0; ++ return 0; ++ } ++ ++ return -EINVAL; ++} +diff -Nru linux-source-4.19/drivers/dahdi/datamods/hdlc_raw_eth.c linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_raw_eth.c +--- linux-source-4.19/drivers/dahdi/datamods/hdlc_raw_eth.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/hdlc_raw_eth.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,107 @@ ++/* ++ * Generic HDLC support routines for Linux ++ * HDLC Ethernet emulation support ++ * ++ * Copyright (C) 2002-2003 Krzysztof Halasa ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License ++ * as published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static int eth_tx(struct sk_buff *skb, struct net_device *dev) ++{ ++ int pad = ETH_ZLEN - skb->len; ++ if (pad > 0) { /* Pad the frame with zeros */ ++ int len = skb->len; ++ if (skb_tailroom(skb) < pad) ++ if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { ++ hdlc_stats(dev)->tx_dropped++; ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ skb_put(skb, pad); ++ memset(skb->data + len, 0, pad); ++ } ++ return dev_to_hdlc(dev)->xmit(skb, dev); ++} ++ ++ ++int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) ++{ ++ raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; ++ const size_t size = sizeof(raw_hdlc_proto); ++ raw_hdlc_proto new_settings; ++ hdlc_device *hdlc = dev_to_hdlc(dev); ++ int result; ++ void *old_ch_mtu; ++ int old_qlen; ++ ++ switch (ifr->ifr_settings.type) { ++ case IF_GET_PROTO: ++ ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; ++ if (ifr->ifr_settings.size < size) { ++ ifr->ifr_settings.size = size; /* data size wanted */ ++ return -ENOBUFS; ++ } ++ if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) ++ return -EFAULT; ++ return 0; ++ ++ case IF_PROTO_HDLC_ETH: ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (dev->flags & IFF_UP) ++ return -EBUSY; ++ ++ if (copy_from_user(&new_settings, raw_s, size)) ++ return -EFAULT; ++ ++ if (new_settings.encoding == ENCODING_DEFAULT) ++ new_settings.encoding = ENCODING_NRZ; ++ ++ if (new_settings.parity == PARITY_DEFAULT) ++ new_settings.parity = PARITY_CRC16_PR1_CCITT; ++ ++ result = hdlc->attach(dev, new_settings.encoding, ++ new_settings.parity); ++ if (result) ++ return result; ++ ++ hdlc_proto_detach(hdlc); ++ memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); ++ memset(&hdlc->proto, 0, sizeof(hdlc->proto)); ++ ++ hdlc->proto.type_trans = eth_type_trans; ++ hdlc->proto.id = IF_PROTO_HDLC_ETH; ++ dev->hard_start_xmit = eth_tx; ++ old_ch_mtu = dev->change_mtu; ++ old_qlen = dev->tx_queue_len; ++ ether_setup(dev); ++ dev->change_mtu = old_ch_mtu; ++ dev->tx_queue_len = old_qlen; ++ memcpy(dev->dev_addr, "\x00\x01", 2); ++ get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); ++ return 0; ++ } ++ ++ return -EINVAL; ++} +diff -Nru linux-source-4.19/drivers/dahdi/datamods/syncppp.c linux-source-4.19-dahdi/drivers/dahdi/datamods/syncppp.c +--- linux-source-4.19/drivers/dahdi/datamods/syncppp.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/datamods/syncppp.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,1482 @@ ++/* ++ * NET3: A (fairly minimal) implementation of synchronous PPP for Linux ++ * as well as a CISCO HDLC implementation. See the copyright ++ * message below for the original source. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the license, or (at your option) any later version. ++ * ++ * Note however. This code is also used in a different form by FreeBSD. ++ * Therefore when making any non OS specific change please consider ++ * contributing it back to the original author under the terms ++ * below in addition. ++ * -- Alan ++ * ++ * Port for Linux-2.1 by Jan "Yenya" Kasprzak ++ */ ++ ++/* ++ * Synchronous PPP/Cisco link level subroutines. ++ * Keepalive protocol implemented in both Cisco and PPP modes. ++ * ++ * Copyright (C) 1994 Cronyx Ltd. ++ * Author: Serge Vakulenko, ++ * ++ * This software is distributed with NO WARRANTIES, not even the implied ++ * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ * ++ * Authors grant any other persons or organisations permission to use ++ * or modify this software as long as this message is kept with the software, ++ * all derivative works or modified versions. ++ * ++ * Version 1.9, Wed Oct 4 18:58:15 MSK 1995 ++ * ++ * $Id$ ++ */ ++#undef DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#define MAXALIVECNT 6 /* max. alive packets */ ++ ++#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ ++#define PPP_UI 0x03 /* Unnumbered Information */ ++#define PPP_IP 0x0021 /* Internet Protocol */ ++#define PPP_ISO 0x0023 /* ISO OSI Protocol */ ++#define PPP_XNS 0x0025 /* Xerox NS Protocol */ ++#define PPP_IPX 0x002b /* Novell IPX Protocol */ ++#define PPP_LCP 0xc021 /* Link Control Protocol */ ++#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ ++ ++#define LCP_CONF_REQ 1 /* PPP LCP configure request */ ++#define LCP_CONF_ACK 2 /* PPP LCP configure acknowledge */ ++#define LCP_CONF_NAK 3 /* PPP LCP configure negative ack */ ++#define LCP_CONF_REJ 4 /* PPP LCP configure reject */ ++#define LCP_TERM_REQ 5 /* PPP LCP terminate request */ ++#define LCP_TERM_ACK 6 /* PPP LCP terminate acknowledge */ ++#define LCP_CODE_REJ 7 /* PPP LCP code reject */ ++#define LCP_PROTO_REJ 8 /* PPP LCP protocol reject */ ++#define LCP_ECHO_REQ 9 /* PPP LCP echo request */ ++#define LCP_ECHO_REPLY 10 /* PPP LCP echo reply */ ++#define LCP_DISC_REQ 11 /* PPP LCP discard request */ ++ ++#define LCP_OPT_MRU 1 /* maximum receive unit */ ++#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ ++#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ ++#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ ++#define LCP_OPT_MAGIC 5 /* magic number */ ++#define LCP_OPT_RESERVED 6 /* reserved */ ++#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ ++#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ ++ ++#define IPCP_CONF_REQ LCP_CONF_REQ /* PPP IPCP configure request */ ++#define IPCP_CONF_ACK LCP_CONF_ACK /* PPP IPCP configure acknowledge */ ++#define IPCP_CONF_NAK LCP_CONF_NAK /* PPP IPCP configure negative ack */ ++#define IPCP_CONF_REJ LCP_CONF_REJ /* PPP IPCP configure reject */ ++#define IPCP_TERM_REQ LCP_TERM_REQ /* PPP IPCP terminate request */ ++#define IPCP_TERM_ACK LCP_TERM_ACK /* PPP IPCP terminate acknowledge */ ++#define IPCP_CODE_REJ LCP_CODE_REJ /* PPP IPCP code reject */ ++ ++#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ ++#define CISCO_UNICAST 0x0f /* Cisco unicast address */ ++#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ ++#define CISCO_ADDR_REQ 0 /* Cisco address request */ ++#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ ++#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ ++ ++struct ppp_header { ++ u8 address; ++ u8 control; ++ u16 protocol; ++}; ++#define PPP_HEADER_LEN sizeof (struct ppp_header) ++ ++struct lcp_header { ++ u8 type; ++ u8 ident; ++ u16 len; ++}; ++#define LCP_HEADER_LEN sizeof (struct lcp_header) ++ ++struct cisco_packet { ++ u32 type; ++ u32 par1; ++ u32 par2; ++ u16 rel; ++ u16 time0; ++ u16 time1; ++}; ++#define CISCO_PACKET_LEN 18 ++#define CISCO_BIG_PACKET_LEN 20 ++ ++static struct sppp *spppq; ++static struct timer_list sppp_keepalive_timer; ++static DEFINE_SPINLOCK(spppq_lock); ++ ++/* global xmit queue for sending packets while spinlock is held */ ++static struct sk_buff_head tx_queue; ++ ++static void sppp_keepalive (unsigned long dummy); ++static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, ++ u8 ident, u16 len, void *data); ++static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2); ++static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m); ++static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m); ++static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m); ++static void sppp_lcp_open (struct sppp *sp); ++static void sppp_ipcp_open (struct sppp *sp); ++static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, ++ int len, u32 *magic); ++static void sppp_cp_timeout (TIMER_DATA_TYPE timer); ++static char *sppp_lcp_type_name (u8 type); ++static char *sppp_ipcp_type_name (u8 type); ++static void sppp_print_bytes (u8 *p, u16 len); ++ ++static int debug; ++ ++/* Flush global outgoing packet queue to dev_queue_xmit(). ++ * ++ * dev_queue_xmit() must be called with interrupts enabled ++ * which means it can't be called with spinlocks held. ++ * If a packet needs to be sent while a spinlock is held, ++ * then put the packet into tx_queue, and call sppp_flush_xmit() ++ * after spinlock is released. ++ */ ++static void sppp_flush_xmit(void) ++{ ++ struct sk_buff *skb; ++ while ((skb = skb_dequeue(&tx_queue)) != NULL) ++ dev_queue_xmit(skb); ++} ++ ++/* ++ * Interface down stub ++ */ ++ ++static void if_down(struct net_device *dev) ++{ ++ struct sppp *sp = (struct sppp *)sppp_of(dev); ++ ++ sp->pp_link_state=SPPP_LINK_DOWN; ++} ++ ++/* ++ * Timeout routine activations. ++ */ ++ ++static void sppp_set_timeout(struct sppp *p,int s) ++{ ++ if (! (p->pp_flags & PP_TIMO)) ++ { ++ p->pp_flags |= PP_TIMO; ++ timer_setup(&p->pp_timer, sppp_cp_timeout, 0); ++ mod_timer(&p->pp_timer, jiffies + s*HZ); ++ } ++} ++ ++static void sppp_clear_timeout(struct sppp *p) ++{ ++ if (p->pp_flags & PP_TIMO) ++ { ++ del_timer(&p->pp_timer); ++ p->pp_flags &= ~PP_TIMO; ++ } ++} ++ ++/** ++ * sppp_input - receive and process a WAN PPP frame ++ * @skb: The buffer to process ++ * @dev: The device it arrived on ++ * ++ * This can be called directly by cards that do not have ++ * timing constraints but is normally called from the network layer ++ * after interrupt servicing to process frames queued via netif_rx(). ++ * ++ * We process the options in the card. If the frame is destined for ++ * the protocol stacks then it requeues the frame for the upper level ++ * protocol. If it is a control from it is processed and discarded ++ * here. ++ */ ++ ++static void sppp_input (struct net_device *dev, struct sk_buff *skb) ++{ ++ struct ppp_header *h; ++ struct sppp *sp = (struct sppp *)sppp_of(dev); ++ unsigned long flags; ++ ++ skb->dev=dev; ++ skb->mac.raw=skb->data; ++ ++ if (dev->flags & IFF_RUNNING) ++ { ++ /* Count received bytes, add FCS and one flag */ ++ sp->ibytes+= skb->len + 3; ++ sp->ipkts++; ++ } ++ ++ if (!pskb_may_pull(skb, PPP_HEADER_LEN)) { ++ /* Too small packet, drop it. */ ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n", ++ dev->name, skb->len); ++ kfree_skb(skb); ++ return; ++ } ++ ++ /* Get PPP header. */ ++ h = (struct ppp_header *)skb->data; ++ skb_pull(skb,sizeof(struct ppp_header)); ++ ++ spin_lock_irqsave(&sp->lock, flags); ++ ++ switch (h->address) { ++ default: /* Invalid PPP packet. */ ++ goto invalid; ++ case PPP_ALLSTATIONS: ++ if (h->control != PPP_UI) ++ goto invalid; ++ if (sp->pp_flags & PP_CISCO) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: PPP packet in Cisco mode <0x%x 0x%x 0x%x>\n", ++ dev->name, ++ h->address, h->control, ntohs (h->protocol)); ++ goto drop; ++ } ++ switch (ntohs (h->protocol)) { ++ default: ++ if (sp->lcp.state == LCP_STATE_OPENED) ++ sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ, ++ ++sp->pp_seq, skb->len + 2, ++ &h->protocol); ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid input protocol <0x%x 0x%x 0x%x>\n", ++ dev->name, ++ h->address, h->control, ntohs (h->protocol)); ++ goto drop; ++ case PPP_LCP: ++ sppp_lcp_input (sp, skb); ++ goto drop; ++ case PPP_IPCP: ++ if (sp->lcp.state == LCP_STATE_OPENED) ++ sppp_ipcp_input (sp, skb); ++ else ++ printk(KERN_DEBUG "IPCP when still waiting LCP finish.\n"); ++ goto drop; ++ case PPP_IP: ++ if (sp->ipcp.state == IPCP_STATE_OPENED) { ++ if(sp->pp_flags&PP_DEBUG) ++ printk(KERN_DEBUG "Yow an IP frame.\n"); ++ skb->protocol=htons(ETH_P_IP); ++ netif_rx(skb); ++ dev->last_rx = jiffies; ++ goto done; ++ } ++ break; ++#ifdef IPX ++ case PPP_IPX: ++ /* IPX IPXCP not implemented yet */ ++ if (sp->lcp.state == LCP_STATE_OPENED) { ++ skb->protocol=htons(ETH_P_IPX); ++ netif_rx(skb); ++ dev->last_rx = jiffies; ++ goto done; ++ } ++ break; ++#endif ++ } ++ break; ++ case CISCO_MULTICAST: ++ case CISCO_UNICAST: ++ /* Don't check the control field here (RFC 1547). */ ++ if (! (sp->pp_flags & PP_CISCO)) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: Cisco packet in PPP mode <0x%x 0x%x 0x%x>\n", ++ dev->name, ++ h->address, h->control, ntohs (h->protocol)); ++ goto drop; ++ } ++ switch (ntohs (h->protocol)) { ++ default: ++ goto invalid; ++ case CISCO_KEEPALIVE: ++ sppp_cisco_input (sp, skb); ++ goto drop; ++#ifdef CONFIG_INET ++ case ETH_P_IP: ++ skb->protocol=htons(ETH_P_IP); ++ netif_rx(skb); ++ dev->last_rx = jiffies; ++ goto done; ++#endif ++#ifdef CONFIG_IPX ++ case ETH_P_IPX: ++ skb->protocol=htons(ETH_P_IPX); ++ netif_rx(skb); ++ dev->last_rx = jiffies; ++ goto done; ++#endif ++ } ++ break; ++ } ++ goto drop; ++ ++invalid: ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid input packet <0x%x 0x%x 0x%x>\n", ++ dev->name, h->address, h->control, ntohs (h->protocol)); ++drop: ++ kfree_skb(skb); ++done: ++ spin_unlock_irqrestore(&sp->lock, flags); ++ sppp_flush_xmit(); ++ return; ++} ++ ++/* ++ * Handle transmit packets. ++ */ ++ ++static int sppp_hard_header(struct sk_buff *skb, struct net_device *dev, __u16 type, ++ void *daddr, void *saddr, unsigned int len) ++{ ++ struct sppp *sp = (struct sppp *)sppp_of(dev); ++ struct ppp_header *h; ++ skb_push(skb,sizeof(struct ppp_header)); ++ h=(struct ppp_header *)skb->data; ++ if(sp->pp_flags&PP_CISCO) ++ { ++ h->address = CISCO_UNICAST; ++ h->control = 0; ++ } ++ else ++ { ++ h->address = PPP_ALLSTATIONS; ++ h->control = PPP_UI; ++ } ++ if(sp->pp_flags & PP_CISCO) ++ { ++ h->protocol = htons(type); ++ } ++ else switch(type) ++ { ++ case ETH_P_IP: ++ h->protocol = htons(PPP_IP); ++ break; ++ case ETH_P_IPX: ++ h->protocol = htons(PPP_IPX); ++ break; ++ } ++ return sizeof(struct ppp_header); ++} ++ ++static int sppp_rebuild_header(struct sk_buff *skb) ++{ ++ return 0; ++} ++ ++/* ++ * Send keepalive packets, every 10 seconds. ++ */ ++ ++static void sppp_keepalive (unsigned long dummy) ++{ ++ struct sppp *sp; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&spppq_lock, flags); ++ ++ for (sp=spppq; sp; sp=sp->pp_next) ++ { ++ struct net_device *dev = sp->pp_if; ++ ++ /* Keepalive mode disabled or channel down? */ ++ if (! (sp->pp_flags & PP_KEEPALIVE) || ++ ! (dev->flags & IFF_UP)) ++ continue; ++ ++ spin_lock(&sp->lock); ++ ++ /* No keepalive in PPP mode if LCP not opened yet. */ ++ if (! (sp->pp_flags & PP_CISCO) && ++ sp->lcp.state != LCP_STATE_OPENED) { ++ spin_unlock(&sp->lock); ++ continue; ++ } ++ ++ if (sp->pp_alivecnt == MAXALIVECNT) { ++ /* No keepalive packets got. Stop the interface. */ ++ printk (KERN_WARNING "%s: protocol down\n", dev->name); ++ if_down (dev); ++ if (! (sp->pp_flags & PP_CISCO)) { ++ /* Shut down the PPP link. */ ++ sp->lcp.magic = jiffies; ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ sppp_clear_timeout (sp); ++ /* Initiate negotiation. */ ++ sppp_lcp_open (sp); ++ } ++ } ++ if (sp->pp_alivecnt <= MAXALIVECNT) ++ ++sp->pp_alivecnt; ++ if (sp->pp_flags & PP_CISCO) ++ sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, ++ sp->pp_rseq); ++ else if (sp->lcp.state == LCP_STATE_OPENED) { ++ long nmagic = htonl (sp->lcp.magic); ++ sp->lcp.echoid = ++sp->pp_seq; ++ sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, ++ sp->lcp.echoid, 4, &nmagic); ++ } ++ ++ spin_unlock(&sp->lock); ++ } ++ spin_unlock_irqrestore(&spppq_lock, flags); ++ sppp_flush_xmit(); ++ sppp_keepalive_timer.expires=jiffies+10*HZ; ++ add_timer(&sppp_keepalive_timer); ++} ++ ++/* ++ * Handle incoming PPP Link Control Protocol packets. ++ */ ++ ++static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb) ++{ ++ struct lcp_header *h; ++ struct net_device *dev = sp->pp_if; ++ int len = skb->len; ++ u8 *p, opt[6]; ++ u32 rmagic; ++ ++ if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n", ++ dev->name, len); ++ return; ++ } ++ h = (struct lcp_header *)skb->data; ++ skb_pull(skb,sizeof(struct lcp_header *)); ++ ++ if (sp->pp_flags & PP_DEBUG) ++ { ++ char state = '?'; ++ switch (sp->lcp.state) { ++ case LCP_STATE_CLOSED: state = 'C'; break; ++ case LCP_STATE_ACK_RCVD: state = 'R'; break; ++ case LCP_STATE_ACK_SENT: state = 'S'; break; ++ case LCP_STATE_OPENED: state = 'O'; break; ++ } ++ printk (KERN_WARNING "%s: lcp input(%c): %d bytes <%s id=%xh len=%xh", ++ dev->name, state, len, ++ sppp_lcp_type_name (h->type), h->ident, ntohs (h->len)); ++ if (len > 4) ++ sppp_print_bytes ((u8*) (h+1), len-4); ++ printk (">\n"); ++ } ++ if (len > ntohs (h->len)) ++ len = ntohs (h->len); ++ switch (h->type) { ++ default: ++ /* Unknown packet type -- send Code-Reject packet. */ ++ sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq, ++ skb->len, h); ++ break; ++ case LCP_CONF_REQ: ++ if (len < 4) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_DEBUG"%s: invalid lcp configure request packet length: %d bytes\n", ++ dev->name, len); ++ break; ++ } ++ if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic)) ++ goto badreq; ++ if (rmagic == sp->lcp.magic) { ++ /* Local and remote magics equal -- loopback? */ ++ if (sp->pp_loopcnt >= MAXALIVECNT*5) { ++ printk (KERN_WARNING "%s: loopback\n", ++ dev->name); ++ sp->pp_loopcnt = 0; ++ if (dev->flags & IFF_UP) { ++ if_down (dev); ++ } ++ } else if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_DEBUG "%s: conf req: magic glitch\n", ++ dev->name); ++ ++sp->pp_loopcnt; ++ ++ /* MUST send Conf-Nack packet. */ ++ rmagic = ~sp->lcp.magic; ++ opt[0] = LCP_OPT_MAGIC; ++ opt[1] = sizeof (opt); ++ opt[2] = rmagic >> 24; ++ opt[3] = rmagic >> 16; ++ opt[4] = rmagic >> 8; ++ opt[5] = rmagic; ++ sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK, ++ h->ident, sizeof (opt), &opt); ++badreq: ++ switch (sp->lcp.state) { ++ case LCP_STATE_OPENED: ++ /* Initiate renegotiation. */ ++ sppp_lcp_open (sp); ++ /* fall through... */ ++ case LCP_STATE_ACK_SENT: ++ /* Go to closed state. */ ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ } ++ break; ++ } ++ /* Send Configure-Ack packet. */ ++ sp->pp_loopcnt = 0; ++ if (sp->lcp.state != LCP_STATE_OPENED) { ++ sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, ++ h->ident, len-4, h+1); ++ } ++ /* Change the state. */ ++ switch (sp->lcp.state) { ++ case LCP_STATE_CLOSED: ++ sp->lcp.state = LCP_STATE_ACK_SENT; ++ break; ++ case LCP_STATE_ACK_RCVD: ++ sp->lcp.state = LCP_STATE_OPENED; ++ sppp_ipcp_open (sp); ++ break; ++ case LCP_STATE_OPENED: ++ /* Remote magic changed -- close session. */ ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ /* Initiate renegotiation. */ ++ sppp_lcp_open (sp); ++ /* Send ACK after our REQ in attempt to break loop */ ++ sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, ++ h->ident, len-4, h+1); ++ sp->lcp.state = LCP_STATE_ACK_SENT; ++ break; ++ } ++ break; ++ case LCP_CONF_ACK: ++ if (h->ident != sp->lcp.confid) ++ break; ++ sppp_clear_timeout (sp); ++ if ((sp->pp_link_state != SPPP_LINK_UP) && ++ (dev->flags & IFF_UP)) { ++ /* Coming out of loopback mode. */ ++ sp->pp_link_state=SPPP_LINK_UP; ++ printk (KERN_INFO "%s: protocol up\n", dev->name); ++ } ++ switch (sp->lcp.state) { ++ case LCP_STATE_CLOSED: ++ sp->lcp.state = LCP_STATE_ACK_RCVD; ++ sppp_set_timeout (sp, 5); ++ break; ++ case LCP_STATE_ACK_SENT: ++ sp->lcp.state = LCP_STATE_OPENED; ++ sppp_ipcp_open (sp); ++ break; ++ } ++ break; ++ case LCP_CONF_NAK: ++ if (h->ident != sp->lcp.confid) ++ break; ++ p = (u8*) (h+1); ++ if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) { ++ rmagic = (u32)p[2] << 24 | ++ (u32)p[3] << 16 | p[4] << 8 | p[5]; ++ if (rmagic == ~sp->lcp.magic) { ++ int newmagic; ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_DEBUG "%s: conf nak: magic glitch\n", ++ dev->name); ++ get_random_bytes(&newmagic, sizeof(newmagic)); ++ sp->lcp.magic += newmagic; ++ } else ++ sp->lcp.magic = rmagic; ++ } ++ if (sp->lcp.state != LCP_STATE_ACK_SENT) { ++ /* Go to closed state. */ ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ } ++ /* The link will be renegotiated after timeout, ++ * to avoid endless req-nack loop. */ ++ sppp_clear_timeout (sp); ++ sppp_set_timeout (sp, 2); ++ break; ++ case LCP_CONF_REJ: ++ if (h->ident != sp->lcp.confid) ++ break; ++ sppp_clear_timeout (sp); ++ /* Initiate renegotiation. */ ++ sppp_lcp_open (sp); ++ if (sp->lcp.state != LCP_STATE_ACK_SENT) { ++ /* Go to closed state. */ ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ } ++ break; ++ case LCP_TERM_REQ: ++ sppp_clear_timeout (sp); ++ /* Send Terminate-Ack packet. */ ++ sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, NULL); ++ /* Go to closed state. */ ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ /* Initiate renegotiation. */ ++ sppp_lcp_open (sp); ++ break; ++ case LCP_TERM_ACK: ++ case LCP_CODE_REJ: ++ case LCP_PROTO_REJ: ++ /* Ignore for now. */ ++ break; ++ case LCP_DISC_REQ: ++ /* Discard the packet. */ ++ break; ++ case LCP_ECHO_REQ: ++ if (sp->lcp.state != LCP_STATE_OPENED) ++ break; ++ if (len < 8) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid lcp echo request packet length: %d bytes\n", ++ dev->name, len); ++ break; ++ } ++ if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { ++ /* Line loopback mode detected. */ ++ printk (KERN_WARNING "%s: loopback\n", dev->name); ++ if_down (dev); ++ ++ /* Shut down the PPP link. */ ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ sppp_clear_timeout (sp); ++ /* Initiate negotiation. */ ++ sppp_lcp_open (sp); ++ break; ++ } ++ *(long*)(h+1) = htonl (sp->lcp.magic); ++ sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1); ++ break; ++ case LCP_ECHO_REPLY: ++ if (h->ident != sp->lcp.echoid) ++ break; ++ if (len < 8) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid lcp echo reply packet length: %d bytes\n", ++ dev->name, len); ++ break; ++ } ++ if (ntohl (*(long*)(h+1)) != sp->lcp.magic) ++ sp->pp_alivecnt = 0; ++ break; ++ } ++} ++ ++/* ++ * Handle incoming Cisco keepalive protocol packets. ++ */ ++ ++static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) ++{ ++ struct cisco_packet *h; ++ struct net_device *dev = sp->pp_if; ++ ++ if (!pskb_may_pull(skb, sizeof(struct cisco_packet)) ++ || (skb->len != CISCO_PACKET_LEN ++ && skb->len != CISCO_BIG_PACKET_LEN)) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n", ++ dev->name, skb->len); ++ return; ++ } ++ h = (struct cisco_packet *)skb->data; ++ skb_pull(skb, sizeof(struct cisco_packet*)); ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: cisco input: %d bytes <%xh %xh %xh %xh %xh-%xh>\n", ++ dev->name, skb->len, ++ ntohl (h->type), h->par1, h->par2, h->rel, ++ h->time0, h->time1); ++ switch (ntohl (h->type)) { ++ default: ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: unknown cisco packet type: 0x%x\n", ++ dev->name, ntohl (h->type)); ++ break; ++ case CISCO_ADDR_REPLY: ++ /* Reply on address request, ignore */ ++ break; ++ case CISCO_KEEPALIVE_REQ: ++ sp->pp_alivecnt = 0; ++ sp->pp_rseq = ntohl (h->par1); ++ if (sp->pp_seq == sp->pp_rseq) { ++ /* Local and remote sequence numbers are equal. ++ * Probably, the line is in loopback mode. */ ++ int newseq; ++ if (sp->pp_loopcnt >= MAXALIVECNT) { ++ printk (KERN_WARNING "%s: loopback\n", ++ dev->name); ++ sp->pp_loopcnt = 0; ++ if (dev->flags & IFF_UP) { ++ if_down (dev); ++ } ++ } ++ ++sp->pp_loopcnt; ++ ++ /* Generate new local sequence number */ ++ get_random_bytes(&newseq, sizeof(newseq)); ++ sp->pp_seq ^= newseq; ++ break; ++ } ++ sp->pp_loopcnt = 0; ++ if (sp->pp_link_state==SPPP_LINK_DOWN && ++ (dev->flags & IFF_UP)) { ++ sp->pp_link_state=SPPP_LINK_UP; ++ printk (KERN_INFO "%s: protocol up\n", dev->name); ++ } ++ break; ++ case CISCO_ADDR_REQ: ++ /* Stolen from net/ipv4/devinet.c -- SIOCGIFADDR ioctl */ ++ { ++ struct in_device *in_dev; ++ struct in_ifaddr *ifa; ++ u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ ++#ifdef CONFIG_INET ++ rcu_read_lock(); ++ if ((in_dev = __in_dev_get_rcu(dev)) != NULL) ++ { ++ for (ifa=in_dev->ifa_list; ifa != NULL; ++ ifa=ifa->ifa_next) { ++ if (strcmp(dev->name, ifa->ifa_label) == 0) ++ { ++ addr = ifa->ifa_local; ++ mask = ifa->ifa_mask; ++ break; ++ } ++ } ++ } ++ rcu_read_unlock(); ++#endif ++ /* I hope both addr and mask are in the net order */ ++ sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); ++ break; ++ } ++ } ++} ++ ++ ++/* ++ * Send PPP LCP packet. ++ */ ++ ++static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, ++ u8 ident, u16 len, void *data) ++{ ++ struct ppp_header *h; ++ struct lcp_header *lh; ++ struct sk_buff *skb; ++ struct net_device *dev = sp->pp_if; ++ ++ skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+LCP_HEADER_LEN+len, ++ GFP_ATOMIC); ++ if (skb==NULL) ++ return; ++ ++ skb_reserve(skb,dev->hard_header_len); ++ ++ h = (struct ppp_header *)skb_put(skb, sizeof(struct ppp_header)); ++ h->address = PPP_ALLSTATIONS; /* broadcast address */ ++ h->control = PPP_UI; /* Unnumbered Info */ ++ h->protocol = htons (proto); /* Link Control Protocol */ ++ ++ lh = (struct lcp_header *)skb_put(skb, sizeof(struct lcp_header)); ++ lh->type = type; ++ lh->ident = ident; ++ lh->len = htons (LCP_HEADER_LEN + len); ++ ++ if (len) ++ memcpy(skb_put(skb,len),data, len); ++ ++ if (sp->pp_flags & PP_DEBUG) { ++ printk (KERN_WARNING "%s: %s output <%s id=%xh len=%xh", ++ dev->name, ++ proto==PPP_LCP ? "lcp" : "ipcp", ++ proto==PPP_LCP ? sppp_lcp_type_name (lh->type) : ++ sppp_ipcp_type_name (lh->type), lh->ident, ++ ntohs (lh->len)); ++ if (len) ++ sppp_print_bytes ((u8*) (lh+1), len); ++ printk (">\n"); ++ } ++ sp->obytes += skb->len; ++ /* Control is high priority so it doesn't get queued behind data */ ++ skb->priority=TC_PRIO_CONTROL; ++ skb->dev = dev; ++ skb_queue_tail(&tx_queue, skb); ++} ++ ++/* ++ * Send Cisco keepalive packet. ++ */ ++ ++static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2) ++{ ++ struct ppp_header *h; ++ struct cisco_packet *ch; ++ struct sk_buff *skb; ++ struct net_device *dev = sp->pp_if; ++ u32 t = jiffies * 1000/HZ; ++ ++ skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+CISCO_PACKET_LEN, ++ GFP_ATOMIC); ++ ++ if(skb==NULL) ++ return; ++ ++ skb_reserve(skb, dev->hard_header_len); ++ h = (struct ppp_header *)skb_put (skb, sizeof(struct ppp_header)); ++ h->address = CISCO_MULTICAST; ++ h->control = 0; ++ h->protocol = htons (CISCO_KEEPALIVE); ++ ++ ch = (struct cisco_packet*)skb_put(skb, CISCO_PACKET_LEN); ++ ch->type = htonl (type); ++ ch->par1 = htonl (par1); ++ ch->par2 = htonl (par2); ++ ch->rel = -1; ++ ch->time0 = htons ((u16) (t >> 16)); ++ ch->time1 = htons ((u16) t); ++ ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: cisco output: <%xh %xh %xh %xh %xh-%xh>\n", ++ dev->name, ntohl (ch->type), ch->par1, ++ ch->par2, ch->rel, ch->time0, ch->time1); ++ sp->obytes += skb->len; ++ skb->priority=TC_PRIO_CONTROL; ++ skb->dev = dev; ++ skb_queue_tail(&tx_queue, skb); ++} ++ ++/** ++ * sppp_close - close down a synchronous PPP or Cisco HDLC link ++ * @dev: The network device to drop the link of ++ * ++ * This drops the logical interface to the channel. It is not ++ * done politely as we assume we will also be dropping DTR. Any ++ * timeouts are killed. ++ */ ++ ++int sppp_close (struct net_device *dev) ++{ ++ struct sppp *sp = (struct sppp *)sppp_of(dev); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&sp->lock, flags); ++ sp->pp_link_state = SPPP_LINK_DOWN; ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ sppp_clear_timeout (sp); ++ spin_unlock_irqrestore(&sp->lock, flags); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(sppp_close); ++ ++/** ++ * sppp_open - open a synchronous PPP or Cisco HDLC link ++ * @dev: Network device to activate ++ * ++ * Close down any existing synchronous session and commence ++ * from scratch. In the PPP case this means negotiating LCP/IPCP ++ * and friends, while for Cisco HDLC we simply need to start sending ++ * keepalives ++ */ ++ ++int sppp_open (struct net_device *dev) ++{ ++ struct sppp *sp = (struct sppp *)sppp_of(dev); ++ unsigned long flags; ++ ++ sppp_close(dev); ++ ++ spin_lock_irqsave(&sp->lock, flags); ++ if (!(sp->pp_flags & PP_CISCO)) { ++ sppp_lcp_open (sp); ++ } ++ sp->pp_link_state = SPPP_LINK_DOWN; ++ spin_unlock_irqrestore(&sp->lock, flags); ++ sppp_flush_xmit(); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(sppp_open); ++ ++/** ++ * sppp_reopen - notify of physical link loss ++ * @dev: Device that lost the link ++ * ++ * This function informs the synchronous protocol code that ++ * the underlying link died (for example a carrier drop on X.21) ++ * ++ * We increment the magic numbers to ensure that if the other end ++ * failed to notice we will correctly start a new session. It happens ++ * do to the nature of telco circuits is that you can lose carrier on ++ * one endonly. ++ * ++ * Having done this we go back to negotiating. This function may ++ * be called from an interrupt context. ++ */ ++ ++int sppp_reopen (struct net_device *dev) ++{ ++ struct sppp *sp = (struct sppp *)sppp_of(dev); ++ unsigned long flags; ++ ++ sppp_close(dev); ++ ++ spin_lock_irqsave(&sp->lock, flags); ++ if (!(sp->pp_flags & PP_CISCO)) ++ { ++ sp->lcp.magic = jiffies; ++ ++sp->pp_seq; ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ /* Give it a moment for the line to settle then go */ ++ sppp_set_timeout (sp, 1); ++ } ++ sp->pp_link_state=SPPP_LINK_DOWN; ++ spin_unlock_irqrestore(&sp->lock, flags); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(sppp_reopen); ++ ++/** ++ * sppp_change_mtu - Change the link MTU ++ * @dev: Device to change MTU on ++ * @new_mtu: New MTU ++ * ++ * Change the MTU on the link. This can only be called with ++ * the link down. It returns an error if the link is up or ++ * the mtu is out of range. ++ */ ++ ++static int sppp_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP)) ++ return -EINVAL; ++ dev->mtu=new_mtu; ++ return 0; ++} ++ ++/** ++ * sppp_do_ioctl - Ioctl handler for ppp/hdlc ++ * @dev: Device subject to ioctl ++ * @ifr: Interface request block from the user ++ * @cmd: Command that is being issued ++ * ++ * This function handles the ioctls that may be issued by the user ++ * to control the settings of a PPP/HDLC link. It does both busy ++ * and security checks. This function is intended to be wrapped by ++ * callers who wish to add additional ioctl calls of their own. ++ */ ++ ++int sppp_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct sppp *sp = (struct sppp *)sppp_of(dev); ++ ++ if(dev->flags&IFF_UP) ++ return -EBUSY; ++ ++ if(!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ switch(cmd) ++ { ++ case SPPPIOCCISCO: ++ sp->pp_flags|=PP_CISCO; ++ dev->type = ARPHRD_HDLC; ++ break; ++ case SPPPIOCPPP: ++ sp->pp_flags&=~PP_CISCO; ++ dev->type = ARPHRD_PPP; ++ break; ++ case SPPPIOCDEBUG: ++ sp->pp_flags&=~PP_DEBUG; ++ if(ifr->ifr_flags) ++ sp->pp_flags|=PP_DEBUG; ++ break; ++ case SPPPIOCGFLAGS: ++ if(copy_to_user(ifr->ifr_data, &sp->pp_flags, sizeof(sp->pp_flags))) ++ return -EFAULT; ++ break; ++ case SPPPIOCSFLAGS: ++ if(copy_from_user(&sp->pp_flags, ifr->ifr_data, sizeof(sp->pp_flags))) ++ return -EFAULT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++EXPORT_SYMBOL(sppp_do_ioctl); ++ ++/** ++ * sppp_attach - attach synchronous PPP/HDLC to a device ++ * @pd: PPP device to initialise ++ * ++ * This initialises the PPP/HDLC support on an interface. At the ++ * time of calling the dev element must point to the network device ++ * that this interface is attached to. The interface should not yet ++ * be registered. ++ */ ++ ++void sppp_attach(struct ppp_device *pd) ++{ ++ struct net_device *dev = pd->dev; ++ struct sppp *sp = &pd->sppp; ++ unsigned long flags; ++ ++ /* Make sure embedding is safe for sppp_of */ ++ BUG_ON(sppp_of(dev) != sp); ++ ++ spin_lock_irqsave(&spppq_lock, flags); ++ /* Initialize keepalive handler. */ ++ if (! spppq) ++ { ++ init_timer(&sppp_keepalive_timer); ++ sppp_keepalive_timer.expires=jiffies+10*HZ; ++ sppp_keepalive_timer.function=sppp_keepalive; ++ add_timer(&sppp_keepalive_timer); ++ } ++ /* Insert new entry into the keepalive list. */ ++ sp->pp_next = spppq; ++ spppq = sp; ++ spin_unlock_irqrestore(&spppq_lock, flags); ++ ++ sp->pp_loopcnt = 0; ++ sp->pp_alivecnt = 0; ++ sp->pp_seq = 0; ++ sp->pp_rseq = 0; ++ sp->pp_flags = PP_KEEPALIVE|PP_CISCO|debug;/*PP_DEBUG;*/ ++ sp->lcp.magic = 0; ++ sp->lcp.state = LCP_STATE_CLOSED; ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ sp->pp_if = dev; ++ spin_lock_init(&sp->lock); ++ ++ /* ++ * Device specific setup. All but interrupt handler and ++ * hard_start_xmit. ++ */ ++ ++ dev->hard_header = sppp_hard_header; ++ dev->rebuild_header = sppp_rebuild_header; ++ dev->tx_queue_len = 10; ++ dev->type = ARPHRD_HDLC; ++ dev->addr_len = 0; ++ dev->hard_header_len = sizeof(struct ppp_header); ++ dev->mtu = PPP_MTU; ++ /* ++ * These 4 are callers but MUST also call sppp_ functions ++ */ ++ dev->do_ioctl = sppp_do_ioctl; ++#if 0 ++ dev->get_stats = NULL; /* Let the driver override these */ ++ dev->open = sppp_open; ++ dev->stop = sppp_close; ++#endif ++ dev->change_mtu = sppp_change_mtu; ++ dev->hard_header_cache = NULL; ++ dev->header_cache_update = NULL; ++ dev->flags = IFF_MULTICAST|IFF_POINTOPOINT|IFF_NOARP; ++} ++ ++EXPORT_SYMBOL(sppp_attach); ++ ++/** ++ * sppp_detach - release PPP resources from a device ++ * @dev: Network device to release ++ * ++ * Stop and free up any PPP/HDLC resources used by this ++ * interface. This must be called before the device is ++ * freed. ++ */ ++ ++void sppp_detach (struct net_device *dev) ++{ ++ struct sppp **q, *p, *sp = (struct sppp *)sppp_of(dev); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&spppq_lock, flags); ++ /* Remove the entry from the keepalive list. */ ++ for (q = &spppq; (p = *q); q = &p->pp_next) ++ if (p == sp) { ++ *q = p->pp_next; ++ break; ++ } ++ ++ /* Stop keepalive handler. */ ++ if (! spppq) ++ del_timer(&sppp_keepalive_timer); ++ sppp_clear_timeout (sp); ++ spin_unlock_irqrestore(&spppq_lock, flags); ++} ++ ++EXPORT_SYMBOL(sppp_detach); ++ ++/* ++ * Analyze the LCP Configure-Request options list ++ * for the presence of unknown options. ++ * If the request contains unknown options, build and ++ * send Configure-reject packet, containing only unknown options. ++ */ ++static int ++sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, ++ int len, u32 *magic) ++{ ++ u8 *buf, *r, *p; ++ int rlen; ++ ++ len -= 4; ++ buf = r = kmalloc (len, GFP_ATOMIC); ++ if (! buf) ++ return (0); ++ ++ p = (void*) (h+1); ++ for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { ++ switch (*p) { ++ case LCP_OPT_MAGIC: ++ /* Magic number -- extract. */ ++ if (len >= 6 && p[1] == 6) { ++ *magic = (u32)p[2] << 24 | ++ (u32)p[3] << 16 | p[4] << 8 | p[5]; ++ continue; ++ } ++ break; ++ case LCP_OPT_ASYNC_MAP: ++ /* Async control character map -- check to be zero. */ ++ if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] && ++ ! p[4] && ! p[5]) ++ continue; ++ break; ++ case LCP_OPT_MRU: ++ /* Maximum receive unit -- always OK. */ ++ continue; ++ default: ++ /* Others not supported. */ ++ break; ++ } ++ /* Add the option to rejected list. */ ++ memcpy(r, p, p[1]); ++ r += p[1]; ++ rlen += p[1]; ++ } ++ if (rlen) ++ sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf); ++ kfree(buf); ++ return (rlen == 0); ++} ++ ++static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb) ++{ ++ struct lcp_header *h; ++ struct net_device *dev = sp->pp_if; ++ int len = skb->len; ++ ++ if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n", ++ dev->name, len); ++ return; ++ } ++ h = (struct lcp_header *)skb->data; ++ skb_pull(skb,sizeof(struct lcp_header)); ++ if (sp->pp_flags & PP_DEBUG) { ++ printk (KERN_WARNING "%s: ipcp input: %d bytes <%s id=%xh len=%xh", ++ dev->name, len, ++ sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len)); ++ if (len > 4) ++ sppp_print_bytes ((u8*) (h+1), len-4); ++ printk (">\n"); ++ } ++ if (len > ntohs (h->len)) ++ len = ntohs (h->len); ++ switch (h->type) { ++ default: ++ /* Unknown packet type -- send Code-Reject packet. */ ++ sppp_cp_send (sp, PPP_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h); ++ break; ++ case IPCP_CONF_REQ: ++ if (len < 4) { ++ if (sp->pp_flags & PP_DEBUG) ++ printk (KERN_WARNING "%s: invalid ipcp configure request packet length: %d bytes\n", ++ dev->name, len); ++ return; ++ } ++ if (len > 4) { ++ sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident, ++ len-4, h+1); ++ ++ switch (sp->ipcp.state) { ++ case IPCP_STATE_OPENED: ++ /* Initiate renegotiation. */ ++ sppp_ipcp_open (sp); ++ /* fall through... */ ++ case IPCP_STATE_ACK_SENT: ++ /* Go to closed state. */ ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ } ++ } else { ++ /* Send Configure-Ack packet. */ ++ sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident, ++ 0, NULL); ++ /* Change the state. */ ++ if (sp->ipcp.state == IPCP_STATE_ACK_RCVD) ++ sp->ipcp.state = IPCP_STATE_OPENED; ++ else ++ sp->ipcp.state = IPCP_STATE_ACK_SENT; ++ } ++ break; ++ case IPCP_CONF_ACK: ++ if (h->ident != sp->ipcp.confid) ++ break; ++ sppp_clear_timeout (sp); ++ switch (sp->ipcp.state) { ++ case IPCP_STATE_CLOSED: ++ sp->ipcp.state = IPCP_STATE_ACK_RCVD; ++ sppp_set_timeout (sp, 5); ++ break; ++ case IPCP_STATE_ACK_SENT: ++ sp->ipcp.state = IPCP_STATE_OPENED; ++ break; ++ } ++ break; ++ case IPCP_CONF_NAK: ++ case IPCP_CONF_REJ: ++ if (h->ident != sp->ipcp.confid) ++ break; ++ sppp_clear_timeout (sp); ++ /* Initiate renegotiation. */ ++ sppp_ipcp_open (sp); ++ if (sp->ipcp.state != IPCP_STATE_ACK_SENT) ++ /* Go to closed state. */ ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ break; ++ case IPCP_TERM_REQ: ++ /* Send Terminate-Ack packet. */ ++ sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, NULL); ++ /* Go to closed state. */ ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ /* Initiate renegotiation. */ ++ sppp_ipcp_open (sp); ++ break; ++ case IPCP_TERM_ACK: ++ /* Ignore for now. */ ++ case IPCP_CODE_REJ: ++ /* Ignore for now. */ ++ break; ++ } ++} ++ ++static void sppp_lcp_open (struct sppp *sp) ++{ ++ char opt[6]; ++ ++ if (! sp->lcp.magic) ++ sp->lcp.magic = jiffies; ++ opt[0] = LCP_OPT_MAGIC; ++ opt[1] = sizeof (opt); ++ opt[2] = sp->lcp.magic >> 24; ++ opt[3] = sp->lcp.magic >> 16; ++ opt[4] = sp->lcp.magic >> 8; ++ opt[5] = sp->lcp.magic; ++ sp->lcp.confid = ++sp->pp_seq; ++ sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid, ++ sizeof (opt), &opt); ++ sppp_set_timeout (sp, 2); ++} ++ ++static void sppp_ipcp_open (struct sppp *sp) ++{ ++ sp->ipcp.confid = ++sp->pp_seq; ++ sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, NULL); ++ sppp_set_timeout (sp, 2); ++} ++ ++/* ++ * Process PPP control protocol timeouts. ++ */ ++ ++static void sppp_cp_timeout (unsigned long arg) ++{ ++ struct sppp *sp = (struct sppp*) arg; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&sp->lock, flags); ++ ++ sp->pp_flags &= ~PP_TIMO; ++ if (! (sp->pp_if->flags & IFF_UP) || (sp->pp_flags & PP_CISCO)) { ++ spin_unlock_irqrestore(&sp->lock, flags); ++ return; ++ } ++ switch (sp->lcp.state) { ++ case LCP_STATE_CLOSED: ++ /* No ACK for Configure-Request, retry. */ ++ sppp_lcp_open (sp); ++ break; ++ case LCP_STATE_ACK_RCVD: ++ /* ACK got, but no Configure-Request for peer, retry. */ ++ sppp_lcp_open (sp); ++ sp->lcp.state = LCP_STATE_CLOSED; ++ break; ++ case LCP_STATE_ACK_SENT: ++ /* ACK sent but no ACK for Configure-Request, retry. */ ++ sppp_lcp_open (sp); ++ break; ++ case LCP_STATE_OPENED: ++ /* LCP is already OK, try IPCP. */ ++ switch (sp->ipcp.state) { ++ case IPCP_STATE_CLOSED: ++ /* No ACK for Configure-Request, retry. */ ++ sppp_ipcp_open (sp); ++ break; ++ case IPCP_STATE_ACK_RCVD: ++ /* ACK got, but no Configure-Request for peer, retry. */ ++ sppp_ipcp_open (sp); ++ sp->ipcp.state = IPCP_STATE_CLOSED; ++ break; ++ case IPCP_STATE_ACK_SENT: ++ /* ACK sent but no ACK for Configure-Request, retry. */ ++ sppp_ipcp_open (sp); ++ break; ++ case IPCP_STATE_OPENED: ++ /* IPCP is OK. */ ++ break; ++ } ++ break; ++ } ++ spin_unlock_irqrestore(&sp->lock, flags); ++ sppp_flush_xmit(); ++} ++ ++static char *sppp_lcp_type_name (u8 type) ++{ ++ static char buf [8]; ++ switch (type) { ++ case LCP_CONF_REQ: return ("conf-req"); ++ case LCP_CONF_ACK: return ("conf-ack"); ++ case LCP_CONF_NAK: return ("conf-nack"); ++ case LCP_CONF_REJ: return ("conf-rej"); ++ case LCP_TERM_REQ: return ("term-req"); ++ case LCP_TERM_ACK: return ("term-ack"); ++ case LCP_CODE_REJ: return ("code-rej"); ++ case LCP_PROTO_REJ: return ("proto-rej"); ++ case LCP_ECHO_REQ: return ("echo-req"); ++ case LCP_ECHO_REPLY: return ("echo-reply"); ++ case LCP_DISC_REQ: return ("discard-req"); ++ } ++ sprintf (buf, "%xh", type); ++ return (buf); ++} ++ ++static char *sppp_ipcp_type_name (u8 type) ++{ ++ static char buf [8]; ++ switch (type) { ++ case IPCP_CONF_REQ: return ("conf-req"); ++ case IPCP_CONF_ACK: return ("conf-ack"); ++ case IPCP_CONF_NAK: return ("conf-nack"); ++ case IPCP_CONF_REJ: return ("conf-rej"); ++ case IPCP_TERM_REQ: return ("term-req"); ++ case IPCP_TERM_ACK: return ("term-ack"); ++ case IPCP_CODE_REJ: return ("code-rej"); ++ } ++ sprintf (buf, "%xh", type); ++ return (buf); ++} ++ ++static void sppp_print_bytes (u_char *p, u16 len) ++{ ++ printk (" %x", *p++); ++ while (--len > 0) ++ printk ("-%x", *p++); ++} ++ ++/** ++ * sppp_rcv - receive and process a WAN PPP frame ++ * @skb: The buffer to process ++ * @dev: The device it arrived on ++ * @p: Unused ++ * @orig_dev: Unused ++ * ++ * Protocol glue. This drives the deferred processing mode the poorer ++ * cards use. This can be called directly by cards that do not have ++ * timing constraints but is normally called from the network layer ++ * after interrupt servicing to process frames queued via netif_rx. ++ */ ++ ++static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) ++{ ++ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) ++ return NET_RX_DROP; ++ sppp_input(dev,skb); ++ return 0; ++} ++ ++static struct packet_type sppp_packet_type = { ++ .type = __constant_htons(ETH_P_WAN_PPP), ++ .func = sppp_rcv, ++}; ++ ++static char banner[] __initdata = ++ KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n" ++ KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & " ++ "Jan \"Yenya\" Kasprzak.\n"; ++ ++static int __init sync_ppp_init(void) ++{ ++ if(debug) ++ debug=PP_DEBUG; ++ printk(banner); ++ skb_queue_head_init(&tx_queue); ++ dev_add_pack(&sppp_packet_type); ++ return 0; ++} ++ ++ ++static void __exit sync_ppp_cleanup(void) ++{ ++ dev_remove_pack(&sppp_packet_type); ++} ++ ++module_init(sync_ppp_init); ++module_exit(sync_ppp_cleanup); ++module_param(debug, int, 0); ++MODULE_LICENSE("GPL v2"); +diff -Nru linux-source-4.19/drivers/dahdi/ecdis.h linux-source-4.19-dahdi/drivers/dahdi/ecdis.h +--- linux-source-4.19/drivers/dahdi/ecdis.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/ecdis.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,103 @@ ++/* ++ * SpanDSP - a series of DSP components for telephony ++ * ++ * ec_disable_detector.h - A detector which should eventually meet the ++ * G.164/G.165 requirements for detecting the ++ * 2100Hz echo cancellor disable tone. ++ * ++ * Written by Steve Underwood ++ * ++ * Copyright (C) 2001 Steve Underwood ++ * ++ * 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 "biquad.h" ++ ++#define FALSE 0 ++#define TRUE (!FALSE) ++ ++static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det) ++{ ++ /* Elliptic notch */ ++ /* This is actually centred at 2095Hz, but gets the balance we want, due ++ to the asymmetric walls of the notch */ ++ biquad2_init (&det->notch, ++ (int32_t) (-0.7600000*32768.0), ++ (int32_t) (-0.1183852*32768.0), ++ (int32_t) (-0.5104039*32768.0), ++ (int32_t) ( 0.1567596*32768.0), ++ (int32_t) ( 1.0000000*32768.0)); ++ ++ det->channel_level = 0; ++ det->notch_level = 0; ++ det->tone_present = FALSE; ++ det->tone_cycle_duration = 0; ++ det->good_cycles = 0; ++ det->hit = 0; ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline int echo_can_disable_detector_update (echo_can_disable_detector_state_t *det, ++ int16_t amp) ++{ ++ int16_t notched; ++ ++ notched = biquad2 (&det->notch, amp); ++ /* Estimate the overall energy in the channel, and the energy in ++ the notch (i.e. overall channel energy - tone energy => noise). ++ Use abs instead of multiply for speed (is it really faster?). ++ Damp the overall energy a little more for a stable result. ++ Damp the notch energy a little less, so we don't damp out the ++ blip every time the phase reverses */ ++ det->channel_level += ((abs(amp) - det->channel_level) >> 5); ++ det->notch_level += ((abs(notched) - det->notch_level) >> 4); ++ if (det->channel_level >= 70) { ++ /* There is adequate energy in the channel. Is it mostly at 2100Hz? */ ++ if (det->notch_level*6 < det->channel_level) { ++ det->tone_cycle_duration++; ++ /* The notch says yes, so we have the tone. */ ++ if (!det->tone_present) { ++ /* Do we get a kick every 450+-25ms? */ ++ if ((det->tone_cycle_duration >= (425 * 8)) && ++ (det->tone_cycle_duration <= (475 * 8))) { ++ /* It's ANS/PR (CED with polarity reversals), so wait ++ for at least three cycles before returning a hit. */ ++ det->good_cycles++; ++ if (det->good_cycles > 2) ++ det->hit = TRUE; ++ } ++ det->tone_cycle_duration = 0; ++ det->tone_present = TRUE; ++ } else if (det->tone_cycle_duration >= 600 * 8) { ++ /* It's ANS (CED without polarity reversals) ++ so return a hit. */ ++ det->hit = TRUE; ++ } ++ } else { ++ det->tone_present = FALSE; ++ } ++ } else { ++ det->tone_present = FALSE; ++ det->tone_cycle_duration = 0; ++ det->good_cycles = 0; ++ } ++ ++ return det->hit; ++} ++/*- End of function --------------------------------------------------------*/ ++/*- End of file ------------------------------------------------------------*/ +diff -Nru linux-source-4.19/drivers/dahdi/fir.h linux-source-4.19-dahdi/drivers/dahdi/fir.h +--- linux-source-4.19/drivers/dahdi/fir.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/fir.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,129 @@ ++/* ++ * SpanDSP - a series of DSP components for telephony ++ * ++ * fir.h - General telephony FIR routines ++ * ++ * Written by Steve Underwood ++ * ++ * Copyright (C) 2002 Steve Underwood ++ * ++ * 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. ++ */ ++ ++#if !defined(_FIR_H_) ++#define _FIR_H_ ++ ++typedef struct ++{ ++ int taps; ++ int curr_pos; ++ int16_t *coeffs; ++ int16_t *history; ++} fir16_state_t; ++ ++typedef struct ++{ ++ int taps; ++ int curr_pos; ++ int32_t *coeffs; ++ int16_t *history; ++} fir32_state_t; ++ ++static inline void fir16_create (fir16_state_t *fir, ++ int16_t *coeffs, ++ int taps) ++{ ++ fir->taps = taps; ++ fir->curr_pos = taps - 1; ++ fir->coeffs = coeffs; ++ fir->history = kmalloc(taps*sizeof (int16_t), GFP_KERNEL); ++ if (fir->history) ++ memset (fir->history, '\0', taps*sizeof (int16_t)); ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline void fir16_free (fir16_state_t *fir) ++{ ++ kfree(fir->history); ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline int16_t fir16 (fir16_state_t *fir, int16_t sample) ++{ ++ int i; ++ int offset1; ++ int offset2; ++ int32_t y; ++ ++ fir->history[fir->curr_pos] = sample; ++ offset2 = fir->curr_pos + 1; ++ offset1 = fir->taps - offset2; ++ y = 0; ++ for (i = fir->taps - 1; i >= offset1; i--) ++ y += fir->coeffs[i]*fir->history[i - offset1]; ++ for ( ; i >= 0; i--) ++ y += fir->coeffs[i]*fir->history[i + offset2]; ++ if (fir->curr_pos <= 0) ++ fir->curr_pos = fir->taps; ++ fir->curr_pos--; ++ return y >> 15; ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline void fir32_create (fir32_state_t *fir, ++ int32_t *coeffs, ++ int taps) ++{ ++ fir->taps = taps; ++ fir->curr_pos = taps - 1; ++ fir->coeffs = coeffs; ++ fir->history = kmalloc(taps*sizeof (int16_t), GFP_KERNEL); ++ if (fir->history) ++ memset (fir->history, '\0', taps*sizeof (int16_t)); ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline void fir32_free (fir32_state_t *fir) ++{ ++ kfree(fir->history); ++} ++/*- End of function --------------------------------------------------------*/ ++ ++static inline int16_t fir32 (fir32_state_t *fir, int16_t sample) ++{ ++ int i; ++ int offset1; ++ int offset2; ++ int32_t y; ++ ++ fir->history[fir->curr_pos] = sample; ++ offset2 = fir->curr_pos + 1; ++ offset1 = fir->taps - offset2; ++ y = 0; ++ for (i = fir->taps - 1; i >= offset1; i--) ++ y += fir->coeffs[i]*fir->history[i - offset1]; ++ for ( ; i >= 0; i--) ++ y += fir->coeffs[i]*fir->history[i + offset2]; ++ if (fir->curr_pos <= 0) ++ fir->curr_pos = fir->taps; ++ fir->curr_pos--; ++ return y >> 15; ++} ++/*- End of function --------------------------------------------------------*/ ++ ++#endif ++/*- End of file ------------------------------------------------------------*/ +diff -Nru linux-source-4.19/drivers/dahdi/firmware/Makefile linux-source-4.19-dahdi/drivers/dahdi/firmware/Makefile +--- linux-source-4.19/drivers/dahdi/firmware/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/firmware/Makefile 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,194 @@ ++# ++# DAHDI ++# ++# Makefile for firmware downloading/installation ++# ++# Copyright (C) 2007-2013, Digium, Inc. ++# ++# Joshua Colp ++# ++# ++# 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. ++# ++ ++.PHONY: dist-clean clean all uninstall have_download install object-build hotplug-install hotplug-dirs hotplug-uninstall make_firmware_object firmware-loaders ++ ++OCT6114_032_VERSION:=1.05.01 ++OCT6114_064_VERSION:=1.05.01 ++OCT6114_128_VERSION:=1.05.01 ++OCT6114_256_VERSION:=1.05.01 ++TC400M_VERSION:=MR6.12 ++VPMADT032_VERSION:=1.25.0 ++HX8_VERSION:=2.06 ++VPMOCT032_VERSION:=1.12.0 ++WCT820_VERSION:=1.76 ++TE133_VERSION:=7a001e ++TE134_VERSION:=780017 ++TE435_VERSION:=13001e ++TE436_VERSION:=10017 ++A8A_VERSION:=1d0017 ++A8B_VERSION:=1f001e ++A4A_VERSION:=a0017 ++A4B_VERSION:=d001e ++ ++FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases ++ ++ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 ++ALL_FIRMWARE+=FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134 ++ALL_FIRMWARE+=FIRMWARE-A8A FIRMWARE-A8B FIRMWARE-A4A FIRMWARE-A4B FIRMWARE-TE435 FIRMWARE-TE436 ++ ++# Firmware files should use the naming convention: dahdi-fw--- or dahdi-fw-- ++# First example: dahdi-fw-oct6114-064-1.05.01 ++# This means this is version 1.05.01 of the oct6114-064 firmware ++# Second example: dahdi-fw-tc400m-MR5.6 ++# This means this is version MR5.6 of the tc400m firmware ++ ++# Build a list of firmware package filenames we need ++FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-032=dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz) ++FIRMWARE:=$(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-OCT6114-256=dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-HX8=dahdi-fw-hx8-$(HX8_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-TE133=dahdi-fw-te133-$(TE133_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-TE134=dahdi-fw-te134-$(TE134_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-TE435=dahdi-fw-te435-$(TE435_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-TE436=dahdi-fw-te436-$(TE436_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-A8A=dahdi-fw-a8b-$(A8B_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-A8B=dahdi-fw-a8a-$(A8A_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-A4A=dahdi-fw-a4b-$(A4B_VERSION).tar.gz) ++FIRMWARE:=$(FIRMWARE:FIRMWARE-A4B=dahdi-fw-a4a-$(A4A_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-032=dahdi-fw-oct6114-032.o) ++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-OCT6114-256=dahdi-fw-oct6114-256.o) ++OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o) ++OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-HX8=dahdi-fw-hx8.o) ++OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o) ++ ++# Force usage of wget, for now ++DOWNLOAD=wget ++WGET=wget ++INSTALL_FIRMWARE=../../../build_tools/install_firmware ++RUN_INST=$(INSTALL_FIRMWARE) $(1) $(2) $(DESTDIR) ++ ++# If "fetch" is used, --continue is not a valid option. ++ifeq ($(WGET),wget) ++WGET_ARGS:=--continue ++endif ++ ++all: $(FIRMWARE) ++ ++# Clean up any downloaded/extracted firmware packages ++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 ++clean: ++ rm -f dahdi-fw-*.o ++ ++# Download and extract firmware tarballs ++dahdi-fw-%.tar.gz: ++ @if ( [ "$(HOTPLUG_FIRMWARE)" = "no" ] ) || ( [ -d $(DESTDIR)/usr/lib/hotplug/firmware ] && ! [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.$(subst .tar.gz,,$*) ] ) || ( [ -d $(DESTDIR)/lib/firmware ] && ! [ -f $(DESTDIR)/lib/firmware/.$(subst .tar.gz,,$*) ] ); then \ ++ echo "Attempting to download $@"; \ ++ if test ! -f $@; then $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL)/$@; fi; \ ++ if test ! -f $@; then exit 1; fi; \ ++ 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 --no-same-owner -xf -) ++ ++# Create object files suitable for linking against ++object-build: $(FIRMWARE) $(OBJECT_FILES) ++ ++$(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware: ++ mkdir -p $@ ++ ++# Install all downloaded firmware images for hotplug usage ++hotplug-install: $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware $(FIRMWARE) ++ @$(call RUN_INST,dahdi-fw-oct6114-032,$(OCT6114_032_VERSION)) ++ @$(call RUN_INST,dahdi-fw-oct6114-064,$(OCT6114_064_VERSION)) ++ @$(call RUN_INST,dahdi-fw-oct6114-128,$(OCT6114_128_VERSION)) ++ @$(call RUN_INST,dahdi-fw-oct6114-256,$(OCT6114_256_VERSION)) ++ @$(call RUN_INST,dahdi-fw-tc400m,$(TC400M_VERSION)) ++ @$(call RUN_INST,dahdi-fw-hx8,$(HX8_VERSION)) ++ @$(call RUN_INST,dahdi-fw-vpmoct032,$(VPMOCT032_VERSION)) ++ @$(call RUN_INST,dahdi-fw-te820,$(WCT820_VERSION)) ++ @$(call RUN_INST,dahdi-fw-te133,$(TE133_VERSION)) ++ @$(call RUN_INST,dahdi-fw-te134,$(TE134_VERSION)) ++ @$(call RUN_INST,dahdi-fw-te435,$(TE435_VERSION)) ++ @$(call RUN_INST,dahdi-fw-te436,$(TE436_VERSION)) ++ @$(call RUN_INST,dahdi-fw-a8a,$(A8A_VERSION)) ++ @$(call RUN_INST,dahdi-fw-a8b,$(A8B_VERSION)) ++ @$(call RUN_INST,dahdi-fw-a4a,$(A4A_VERSION)) ++ @$(call RUN_INST,dahdi-fw-a4b,$(A4B_VERSION)) ++ ++# Uninstall any installed dahdi firmware images from hotplug firmware directories ++hotplug-uninstall: ++ if [ -d $(DESTDIR)/usr/lib/hotplug/firmware ]; then \ ++ rm -f $(DESTDIR)/usr/lib/hotplug/firmware/dahdi-fw-*.bin; \ ++ rm -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw*; \ ++ fi ++ if [ -d $(DESTDIR)/lib/firmware ]; then \ ++ rm -f $(DESTDIR)/lib/firmware/dahdi-fw-*.bin; \ ++ rm -f $(DESTDIR)/lib/firmware/.dahdi-fw*; \ ++ fi ++ ++make_firmware_object: make_firmware_object.in ../dahdi-base.o ++ @export BFDNAME=`LANG=C objdump -f ../dahdi-base.o | grep -e "dahdi-base.o:" | sed "s/.*file format \(.*\)/\1/"`; \ ++ export BFDARCH=`LANG=C objdump -f ../dahdi-base.o | grep -e "architecture:" | sed "s/.*ture: \(.*\),.*/\1/"`; \ ++ sed -e s/BFDNAME/$${BFDNAME}/ -e s/BFDARCH/$${BFDARCH}/ $< > $@ ++ @chmod +x $@ ++ ++# Build object file of an oct6114 032 firmware image for linking ++dahdi-fw-oct6114-032.o: dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz dahdi-fw-oct6114-032.bin make_firmware_object ++ @echo Making firmware object file for dahdi-fw-oct6114-032.bin ++ ./make_firmware_object dahdi-fw-oct6114-032.bin $@ ++ ++# Build object file of an oct6114 064 firmware image for linking ++dahdi-fw-oct6114-064.o: dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz dahdi-fw-oct6114-064.bin make_firmware_object ++ @echo Making firmware object file for dahdi-fw-oct6114-064.bin ++ ./make_firmware_object dahdi-fw-oct6114-064.bin $@ ++ ++# Build object file of an oct6114 128 firmware image for linking ++dahdi-fw-oct6114-128.o: dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz dahdi-fw-oct6114-128.bin make_firmware_object ++ @echo Making firmware object file for dahdi-fw-oct6114-128.bin ++ ./make_firmware_object dahdi-fw-oct6114-128.bin $@ ++ ++# Build object file of an oct6114 256 firmware image for linking ++dahdi-fw-oct6114-256.o: dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz dahdi-fw-oct6114-256.bin make_firmware_object ++ @echo Making firmware object file for dahdi-fw-oct6114-256.bin ++ ./make_firmware_object dahdi-fw-oct6114-256.bin $@ ++ ++# Build object file of a TC400M firmware image for linking ++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 VPMOCT032 firmware image for linking ++dahdi-fw-vpmoct032.o: dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz dahdi-fw-vpmoct032.bin make_firmware_object ++ @echo Making firmware object file for dahdi-fw-vpmoct032.bin ++ ./make_firmware_object dahdi-fw-vpmoct032.bin $@ +diff -Nru linux-source-4.19/drivers/dahdi/firmware/make_firmware_object.in linux-source-4.19-dahdi/drivers/dahdi/firmware/make_firmware_object.in +--- linux-source-4.19/drivers/dahdi/firmware/make_firmware_object.in 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/firmware/make_firmware_object.in 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,8 @@ ++#!/bin/sh -e ++ ++# make an object file from a raw binary firmware file ++# arguments: ++# 1 - firmware file ++# 2 - output file ++ ++objcopy -I binary ${1} -B BFDARCH -O BFDNAME ${2} --rename-section .data=.rodata,alloc,load,data,contents,readonly +diff -Nru linux-source-4.19/drivers/dahdi/fxo_modes.h linux-source-4.19-dahdi/drivers/dahdi/fxo_modes.h +--- linux-source-4.19/drivers/dahdi/fxo_modes.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/fxo_modes.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,587 @@ ++/* ++ * FXO port mode settings for various regions ++ * ++ * Copyright (C) 2008 Digium, Inc. ++ * ++ * extracted from wctdm.c by ++ * Kevin P. Fleming ++ * ++ * 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 _FXO_MODES_H ++#define _FXO_MODES_H ++ ++static const struct fxo_mode { ++ const char *name; ++ unsigned char ohs:1; ++ unsigned char ohs2:1; ++ unsigned char rz:1; ++ unsigned char rt:1; ++ unsigned char ilim:1; ++ unsigned char dcv:2; ++ unsigned char mini:2; ++ unsigned char acim:4; ++ unsigned short int ring_osc; ++ unsigned short int ring_x; ++ unsigned short int battdebounce; /* in milliseconds */ ++ unsigned short int battalarm; /* in milliseconds */ ++ unsigned short int battthresh; /* unknown units */ ++} fxo_modes[] = ++{ ++ /* US, Canada */ ++ { .name = "FCC", ++ .rt = 1, ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ /* Austria, Belgium, Denmark, Finland, France, Germany, ++ Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, ++ Norway, Portugal, Spain, Sweden, Switzerland, and UK */ ++ { .name = "TBR21", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .ring_osc = 0x7e6c, ++ .ring_x = 0x023a, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "ARGENTINA", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "AUSTRALIA", ++ .ohs = 1, ++ .mini = 0x3, ++ .acim = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "AUSTRIA", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "BAHRAIN", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "BELGIUM", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "BRAZIL", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "BULGARIA", ++ .ilim = 1, ++ .dcv = 0x3, ++ .mini = 0x0, ++ .acim = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "CANADA", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "CHILE", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "CHINA", ++ .mini = 0x3, ++ .acim = 0xf, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "COLOMBIA", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "CROATIA", ++ .ilim = 1, ++ .dcv = 0x3, ++ .mini = 0, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "CYPRUS", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "CZECH", ++ .ilim = 1, ++ .dcv = 0x3, ++ .mini = 0, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "DENMARK", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "ECUADOR", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "EGYPT", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "ELSALVADOR", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "FINLAND", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "FRANCE", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .mini = 0, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "GERMANY", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "GREECE", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "GUAM", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "HONGKONG", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "HUNGARY", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "ICELAND", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "INDIA", ++ .dcv = 0x3, ++ .acim = 0x4, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "INDONESIA", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "IRELAND", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "ISRAEL", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "ITALY", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "JAPAN", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "JORDAN", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "KAZAKHSTAN", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "KUWAIT", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "LATVIA", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "LEBANON", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "LUXEMBOURG", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "MACAO", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ /* Current loop >= 20ma */ ++ { .name = "MALAYSIA", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "MALTA", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "MEXICO", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "MOROCCO", ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "NETHERLANDS", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "NEWZEALAND", ++ .dcv = 0x3, ++ .acim = 0x4, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "NIGERIA", ++ .ilim = 0x1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "NORWAY", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "OMAN", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "PAKISTAN", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "PERU", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "PHILIPPINES", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "POLAND", ++ .rz = 1, ++ .rt = 1, ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "PORTUGAL", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "ROMANIA", ++ .dcv = 3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "RUSSIA", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SAUDIARABIA", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SINGAPORE", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SLOVAKIA", ++ .dcv = 0x3, ++ .acim = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SLOVENIA", ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SOUTHAFRICA", ++ .ohs = 1, ++ .rz = 1, ++ .dcv = 0x3, ++ .acim = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SOUTHKOREA", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SPAIN", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SWEDEN", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SWITZERLAND", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x2, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "SYRIA", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "TAIWAN", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "THAILAND", ++ .mini = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "UAE", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "UK", ++ .ohs2 = 1, ++ .ilim = 1, ++ .dcv = 0x3, ++ .acim = 0x5, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "USA", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++ { .name = "YEMEN", ++ .dcv = 0x3, ++ .battdebounce = 64, ++ .battalarm = 1000, ++ .battthresh = 3, ++ }, ++}; ++ ++#endif /* _FXO_MODES_H */ +diff -Nru linux-source-4.19/drivers/dahdi/hpec/dahdi_echocan_hpec.c linux-source-4.19-dahdi/drivers/dahdi/hpec/dahdi_echocan_hpec.c +--- linux-source-4.19/drivers/dahdi/hpec/dahdi_echocan_hpec.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/hpec/dahdi_echocan_hpec.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,213 @@ ++/* ++ * DAHDI Telephony Interface to Digium High-Performance Echo Canceller ++ * ++ * Copyright (C) 2006-2012 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; ++ ++#include "hpec_user.h" ++#include "hpec.h" ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, __u32 size); ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); ++static const char *name = "HPEC"; ++static const char *ec_name(const struct dahdi_chan *chan) { return name; } ++ ++static const struct dahdi_echocan_factory my_factory = { ++ .get_name = ec_name, ++ .owner = THIS_MODULE, ++ .echocan_create = echo_can_create, ++}; ++ ++static const struct dahdi_echocan_features my_features = { ++ .NLP_automatic = 1, ++ .CED_tx_detect = 1, ++ .CED_rx_detect = 1, ++}; ++ ++static const struct dahdi_echocan_ops my_ops = { ++ .echocan_free = echo_can_free, ++ .echocan_process = echo_can_process, ++ .echocan_traintap = echo_can_traintap, ++}; ++ ++struct ec_pvt { ++ struct hpec_state *hpec; ++ struct dahdi_echocan_state dahdi; ++}; ++ ++#define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) ++ ++static int __attribute__((regparm(0), format(printf, 1, 2))) logger(const char *format, ...) ++{ ++ int res; ++ va_list args; ++ ++ va_start(args, format); ++ res = vprintk(format, args); ++ va_end(args); ++ ++ return res; ++} ++ ++static void *memalloc(size_t len) ++{ ++ return kmalloc(len, GFP_KERNEL); ++} ++ ++static void memfree(void *ptr) ++{ ++ kfree(ptr); ++} ++ ++static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ hpec_channel_free(pvt->hpec); ++ kfree(pvt); ++} ++ ++static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, __u32 size) ++{ ++ struct ec_pvt *pvt = dahdi_to_pvt(ec); ++ ++ hpec_channel_update(pvt->hpec, isig, iref); ++} ++ ++DEFINE_SEMAPHORE(license_lock); ++ ++static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) ++{ ++ struct ec_pvt *pvt; ++ ++ if (ecp->param_count > 0) { ++ printk(KERN_WARNING "HPEC does not support parameters; failing request\n"); ++ return -EINVAL; ++ } ++ ++ pvt = kzalloc(sizeof(*pvt), GFP_KERNEL); ++ if (!pvt) ++ return -ENOMEM; ++ ++ pvt->dahdi.ops = &my_ops; ++ pvt->dahdi.features = my_features; ++ ++ if (down_interruptible(&license_lock)) ++ return -ENOTTY; ++ ++ pvt->hpec = hpec_channel_alloc(ecp->tap_length); ++ ++ up(&license_lock); ++ ++ if (!pvt->hpec) { ++ kfree(pvt); ++ *ec = NULL; ++ return -ENOTTY; ++ } else { ++ *ec = &pvt->dahdi; ++ return 0; ++ } ++} ++ ++static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) ++{ ++ return 1; ++} ++ ++static int hpec_license_ioctl(unsigned int cmd, unsigned long data) ++{ ++ struct hpec_challenge challenge; ++ struct hpec_license license; ++ int result = 0; ++ ++ switch (cmd) { ++ case DAHDI_EC_LICENSE_CHALLENGE: ++ if (down_interruptible(&license_lock)) ++ return -EINTR; ++ memset(&challenge, 0, sizeof(challenge)); ++ if (hpec_license_challenge(&challenge)) ++ result = -ENODEV; ++ if (!result && copy_to_user((unsigned char *) data, &challenge, sizeof(challenge))) ++ result = -EFAULT; ++ up(&license_lock); ++ return result; ++ case DAHDI_EC_LICENSE_RESPONSE: ++ if (down_interruptible(&license_lock)) ++ return -EINTR; ++ if (copy_from_user(&license, (unsigned char *) data, sizeof(license))) ++ result = -EFAULT; ++ if (!result && hpec_license_check(&license)) ++ result = -EACCES; ++ up(&license_lock); ++ return result; ++ default: ++ return -ENOSYS; ++ } ++} ++ ++static int __init mod_init(void) ++{ ++ if (dahdi_register_echocan_factory(&my_factory)) { ++ module_printk(KERN_ERR, "could not register with DAHDI core\n"); ++ ++ return -EPERM; ++ } ++ ++ module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", ++ my_factory.get_name(NULL)); ++ ++ hpec_init(logger, debug, DAHDI_CHUNKSIZE, memalloc, memfree); ++ ++ dahdi_set_hpec_ioctl(hpec_license_ioctl); ++ ++ return 0; ++} ++ ++static void __exit mod_exit(void) ++{ ++ dahdi_unregister_echocan_factory(&my_factory); ++ ++ dahdi_set_hpec_ioctl(NULL); ++ ++ hpec_shutdown(); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++ ++MODULE_DESCRIPTION("DAHDI High Performance Echo Canceller"); ++MODULE_AUTHOR("Kevin P. Fleming "); ++MODULE_LICENSE("Digium Commercial"); ++ ++module_init(mod_init); ++module_exit(mod_exit); +diff -Nru linux-source-4.19/drivers/dahdi/hpec/hpec.h linux-source-4.19-dahdi/drivers/dahdi/hpec/hpec.h +--- linux-source-4.19/drivers/dahdi/hpec/hpec.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/hpec/hpec.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,46 @@ ++/* ++ * DAHDI Telephony Interface to Digium High-Performance Echo Canceller ++ * ++ * Copyright (C) 2006 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. ++ */ ++ ++#if !defined(_HPEC_H) ++#define _HPEC_H ++ ++struct hpec_state; ++ ++void __attribute__((regparm(0))) hpec_init(int __attribute__((regparm(0), format(printf, 1, 2))) (*logger)(const char *format, ...), ++ unsigned int debug, ++ unsigned int chunk_size, ++ void * (*memalloc)(size_t len), ++ void (*memfree)(void *ptr)); ++ ++void __attribute__((regparm(0))) hpec_shutdown(void); ++ ++int __attribute__((regparm(0))) hpec_license_challenge(struct hpec_challenge *challenge); ++ ++int __attribute__((regparm(0))) hpec_license_check(struct hpec_license *license); ++ ++struct hpec_state __attribute__((regparm(0))) *hpec_channel_alloc(unsigned int len); ++ ++void __attribute__((regparm(0))) hpec_channel_free(struct hpec_state *channel); ++ ++void __attribute__((regparm(0))) hpec_channel_update(struct hpec_state *channel, short *isig, const short *iref); ++ ++#endif /* !defined(_HPEC_H) */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/hpec/hpec_user.h linux-source-4.19-dahdi/drivers/dahdi/hpec/hpec_user.h +--- linux-source-4.19/drivers/dahdi/hpec/hpec_user.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/hpec/hpec_user.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,39 @@ ++/* ++ * DAHDI Telephony Interface to Digium High-Performance Echo Canceller ++ * ++ * Copyright (C) 2006 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. ++ */ ++ ++#if !defined(_HPEC_USER_H) ++#define _HPEC_USER_H ++ ++struct hpec_challenge { ++ __u8 challenge[16]; ++}; ++ ++struct hpec_license { ++ __u32 numchannels; ++ __u8 userinfo[256]; ++ __u8 response[16]; ++}; ++ ++#define DAHDI_EC_LICENSE_CHALLENGE _IOR(DAHDI_CODE, 60, struct hpec_challenge) ++#define DAHDI_EC_LICENSE_RESPONSE _IOW(DAHDI_CODE, 61, struct hpec_license) ++ ++#endif /* !defined(_HPEC_USER_H) */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/makefw.c linux-source-4.19-dahdi/drivers/dahdi/makefw.c +--- linux-source-4.19/drivers/dahdi/makefw.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/makefw.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,84 @@ ++/* Xilinx firmware convertor program. ++ * ++ * Written by Jim Dixon . ++ * ++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony. ++ * Copyright (C) 2001-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. ++ */ ++ ++#include ++#include ++#include ++ ++#define SWATH 12 ++ ++int main(int argc, char *argv[]) ++{ ++FILE *fp; ++int i,j,nbytes; ++unsigned char c; ++char buf[300]; ++ ++ if (argc < 3) ++ { ++ puts("Usage... makefw filename.rbt array_name"); ++ exit(1); ++ } ++ ++ fp = fopen(argv[1],"r"); ++ if (!fp) ++ { ++ perror("bit file open"); ++ exit(1); ++ } ++ nbytes = 0; ++ printf("static unsigned char %s[] = {\n",argv[2]); ++ i = 0; ++ while(fgets(buf,sizeof(buf) - 1,fp)) ++ { ++ if (!buf[0]) continue; ++ if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; ++ if (!buf[0]) continue; ++ if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; ++ if (!buf[0]) continue; ++ if (strlen(buf) < 32) continue; ++ if ((buf[0] != '0') && (buf[0] != '1')) continue; ++ c = 0; ++ for(j = 0; buf[j]; j++) ++ { ++ if (buf[j] > '0') c |= 1 << (j & 7); ++ if ((j & 7) == 7) ++ { ++ nbytes++; ++ if (i) printf(","); ++ printf("0x%02x",c); ++ if (i++ == SWATH) { ++ printf(",\n"); ++ i = 0; ++ } ++ c = 0; ++ } ++ } ++ } ++ printf("\n};\n\n"); ++ fprintf(stderr,"Loaded %d bytes from file\n",nbytes); ++ fclose(fp); ++ exit(0); ++} ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/Kbuild linux-source-4.19-dahdi/drivers/dahdi/oct612x/Kbuild +--- linux-source-4.19/drivers/dahdi/oct612x/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/Kbuild 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,32 @@ ++# ++# Produces the oct612x library ++# ++octapi_files = octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_channel.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_debug.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_events.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_memory.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.o \ ++ apilib/bt/octapi_bt0.o \ ++ apilib/largmath/octapi_largmath.o \ ++ apilib/llman/octapi_llman.o \ ++ oct612x-user.o ++ ++# TODO: ccflags was added in 2.6.24 in commit f77bf01425b11947eeb3b5b54. This ++# should be changed to a conditional compilation based on the Kernel Version. ++# ccflags-y := -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api ++EXTRA_CFLAGS = -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) := oct612x.o ++oct612x-objs := $(octapi_files) +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/Makefile linux-source-4.19-dahdi/drivers/dahdi/oct612x/Makefile +--- linux-source-4.19/drivers/dahdi/oct612x/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/Makefile 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,30 @@ ++# ++# Produces the oct612x library ++# ++octapi_files = octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_channel.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_debug.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_events.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_memory.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.o \ ++ octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.o \ ++ apilib/bt/octapi_bt0.o \ ++ apilib/largmath/octapi_largmath.o \ ++ apilib/llman/octapi_llman.o ++ ++# TODO: ccflags was added in 2.6.24 in commit f77bf01425b11947eeb3b5b54. This ++# should be changed to a conditional compilation based on the Kernel Version. ++# ccflags-y := -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api ++EXTRA_CFLAGS = -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api ++lib-y := $(octapi_files) +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/apilib/bt/octapi_bt0.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/bt/octapi_bt0.c +--- linux-source-4.19/drivers/dahdi/oct612x/apilib/bt/octapi_bt0.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/bt/octapi_bt0.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,1217 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_bt0.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Library used to manage a binary tree of variable max size. Library is ++ made to use one block of contiguous memory to manage the tree. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 18 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#include "apilib/octapi_bt0.h" ++#include "octapi_bt0_private.h" ++ ++ ++ ++#if !SKIP_OctApiBt0GetSize ++UINT32 OctApiBt0GetSize(UINT32 number_of_items,UINT32 key_size, UINT32 data_size, UINT32 * b_size) ++{ ++ if ((key_size % 4) != 0) return(OCTAPI_BT0_KEY_SIZE_NOT_MUTLIPLE_OF_UINT32); ++ if ((data_size % 4) != 0) return(OCTAPI_BT0_DATA_SIZE_NOT_MUTLIPLE_OF_UINT32); ++ ++ *b_size = 0; ++ *b_size += sizeof(OCTAPI_BT0); ++ *b_size += sizeof(OCTAPI_BT0_NODE) * number_of_items; ++ *b_size += key_size * number_of_items; ++ *b_size += data_size * number_of_items; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiBt0Init ++UINT32 OctApiBt0Init(void ** b,UINT32 number_of_items,UINT32 key_size, UINT32 data_size) ++{ ++ UINT32 i; ++ OCTAPI_BT0 * bb; ++ ++ /* Check input parameters.*/ ++ if ((key_size % 4) != 0) return(OCTAPI_BT0_KEY_SIZE_NOT_MUTLIPLE_OF_UINT32); ++ if ((data_size % 4) != 0) return(OCTAPI_BT0_DATA_SIZE_NOT_MUTLIPLE_OF_UINT32); ++ ++ /* If b is not already allocated.*/ ++ if (*b == NULL) return(OCTAPI_BT0_MALLOC_FAILED); ++ ++ bb = (OCTAPI_BT0 *)(*b); ++ ++ /* Initialize the tree to an empty one!*/ ++ bb->root_link.node_number = 0xFFFFFFFF; ++ bb->root_link.depth = 0; ++ ++ /* Initialize tree parameters.*/ ++ bb->number_of_items = number_of_items; ++ bb->key_size = key_size / 4; ++ bb->data_size = data_size / 4; ++ ++ /* Initialize the next free node pointer.*/ ++ if (number_of_items != 0) ++ bb->next_free_node = 0; ++ else ++ bb->next_free_node = 0xFFFFFFFF; ++ ++ /* Setup the arrays.*/ ++ OctApiBt0CorrectPointers(bb); ++ ++ /* Initialize the Nodes to unused!*/ ++ for(i=0;inode[i].next_free_node = i + 1; ++ } ++ ++ /* Last empty node points to invalid node.*/ ++ bb->node[number_of_items-1].next_free_node = 0xFFFFFFFF; ++ ++ bb->invalid_value = 0xFFFFFFFF; ++ bb->no_smaller_key = OCTAPI_BT0_NO_SMALLER_KEY; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++#if !SKIP_OctApiBt0CorrectPointers ++void OctApiBt0CorrectPointers(OCTAPI_BT0 * bb) ++{ ++ bb->node = (OCTAPI_BT0_NODE *)(((BYTE *)bb) + sizeof(OCTAPI_BT0)); ++ bb->key = (UINT32 *)(((BYTE *)bb->node) + (sizeof(OCTAPI_BT0_NODE) * bb->number_of_items)); ++ bb->data = (UINT32 *)(((BYTE *)bb->key) + (sizeof(UINT32) * bb->number_of_items * bb->key_size)); ++} ++#endif ++ ++ ++#if !SKIP_OctApiBt0AddNode ++UINT32 OctApiBt0AddNode(void * b,void * key,void ** data) ++{ ++ OCTAPI_BT0 * bb; ++ OCTAPI_BT0_NODE * new_node; ++ UINT32 * lkey; ++ UINT32 * nkey; ++ UINT32 i; ++ UINT32 new_node_number; ++ UINT32 result; ++ ++ /* Load all!*/ ++ bb = (OCTAPI_BT0 *)(b); ++ OctApiBt0CorrectPointers(bb); ++ ++ /* Check that there is at least one block left.*/ ++ if (bb->next_free_node == 0xFFFFFFFF) return(OCTAPI_BT0_NO_NODES_AVAILABLE); ++ ++ /* Seize the node!*/ ++ new_node_number = bb->next_free_node; ++ new_node = &(bb->node[new_node_number]); ++ bb->next_free_node = new_node->next_free_node; ++ ++ /* Register in the key and the data.*/ ++ lkey = ((UINT32 *)key); ++ ++ /* Find the first UINT32 of the key.*/ ++ nkey = &(bb->key[bb->key_size * new_node_number]); ++ ++ /* Copy the key.*/ ++ for(i=0;ikey_size;i++) ++ nkey[i] = lkey[i]; ++ ++ /* Attempt to place the node. Only a "multiple hit" will cause an error.*/ ++ result = OctApiBt0AddNode2(bb,&(bb->root_link), lkey, new_node_number); ++ if (result != GENERIC_OK) ++ { ++ /* This attempt failed. Refree the node!*/ ++ bb->next_free_node = new_node_number; ++ ++ /* Return the error code.*/ ++ return(result); ++ } ++ ++ /* Return the address of the data to the user.*/ ++ if ( bb->data_size > 0 ) ++ *data = (void *)(&(bb->data[bb->data_size * new_node_number])); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiBt0AddNode2 ++UINT32 OctApiBt0AddNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 new_node_number) ++{ ++ UINT32 result; ++ ++ if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/ ++ { ++ bb->node[new_node_number].l[0].node_number = 0xFFFFFFFF; ++ bb->node[new_node_number].l[0].depth = 0; ++ bb->node[new_node_number].l[1].node_number = 0xFFFFFFFF; ++ bb->node[new_node_number].l[1].depth = 0; ++ ++ /* OCTAPI_BT0_LINK to parent!*/ ++ link->node_number = new_node_number; ++ link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/ ++ ++ return(GENERIC_OK); ++ } ++ else /* Current node is used, check for a match and a direction.*/ ++ { ++ OCTAPI_BT0_NODE * this_node; ++ UINT32 compare; ++ ++ /* Get a pointer to this node.*/ ++ this_node = &(bb->node[link->node_number]); ++ ++ /* Compare this node to the lkey.*/ ++ compare = OctApiBt0KeyCompare(bb,link,lkey); ++ ++ if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ ++ { ++ result = OctApiBt0AddNode2(bb,&(this_node->l[0]), lkey, new_node_number); ++ if (result != GENERIC_OK) return(result); ++ } ++ else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ ++ { ++ result = OctApiBt0AddNode2(bb,&(this_node->l[1]), lkey, new_node_number); ++ if (result != GENERIC_OK) return(result); ++ } ++ else ++ { ++ return(OCTAPI_BT0_KEY_ALREADY_IN_TREE); ++ } ++ ++ /* Check if this node is unbalanced by 2. If so, rebalance it:*/ ++ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || ++ this_node->l[1].depth > (this_node->l[0].depth + 1)) ++ { ++ OctApiBt0Rebalance(bb,link); ++ } ++ ++ /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ ++ OctApiBt0UpdateLinkDepth(bb,link); ++ ++ return(GENERIC_OK); ++ } ++} ++#endif ++ ++ ++#if !SKIP_OctApiBt0AddNode3 ++UINT32 OctApiBt0AddNode3(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 *p_new_node_number) ++{ ++ UINT32 result; ++ ++ if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/ ++ { ++ if ( *p_new_node_number == 0xFFFFFFFF ) ++ return(OCTAPI_BT0_NO_NODES_AVAILABLE); ++ ++ bb->node[*p_new_node_number].l[0].node_number = 0xFFFFFFFF; ++ bb->node[*p_new_node_number].l[0].depth = 0; ++ bb->node[*p_new_node_number].l[1].node_number = 0xFFFFFFFF; ++ bb->node[*p_new_node_number].l[1].depth = 0; ++ ++ /* OCTAPI_BT0_LINK to parent!*/ ++ link->node_number = *p_new_node_number; ++ link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/ ++ ++ return(GENERIC_OK); ++ } ++ else /* Current node is used, check for a match and a direction.*/ ++ { ++ OCTAPI_BT0_NODE * this_node; ++ UINT32 compare; ++ ++ /* Get a pointer to this node.*/ ++ this_node = &(bb->node[link->node_number]); ++ ++ /* Compare this node to the lkey.*/ ++ compare = OctApiBt0KeyCompare(bb,link,lkey); ++ ++ if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ ++ { ++ result = OctApiBt0AddNode3(bb,&(this_node->l[0]), lkey, p_new_node_number); ++ if (result != GENERIC_OK) return(result); ++ } ++ else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ ++ { ++ result = OctApiBt0AddNode3(bb,&(this_node->l[1]), lkey, p_new_node_number); ++ if (result != GENERIC_OK) return(result); ++ } ++ else ++ { ++ *p_new_node_number = link->node_number; ++ return(OCTAPI_BT0_KEY_ALREADY_IN_TREE); ++ } ++ ++ /* Check if this node is unbalanced by 2. If so, rebalance it:*/ ++ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || ++ this_node->l[1].depth > (this_node->l[0].depth + 1)) ++ { ++ OctApiBt0Rebalance(bb,link); ++ } ++ ++ /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ ++ OctApiBt0UpdateLinkDepth(bb,link); ++ ++ return(GENERIC_OK); ++ } ++} ++#endif ++ ++/* state ++0 -> first call to the function. ++1 -> recursive call.*/ ++#if !SKIP_OctApiBt0AddNode4 ++UINT32 OctApiBt0AddNode4(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 *p_new_node_number, UINT32 *p_prev_node_number, UINT32 state ) ++{ ++ UINT32 result; ++ UINT32 *nkey; ++ UINT32 *okey; ++ ++ if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/ ++ { ++ bb->node[*p_new_node_number].l[0].node_number = 0xFFFFFFFF; ++ bb->node[*p_new_node_number].l[0].depth = 0; ++ bb->node[*p_new_node_number].l[1].node_number = 0xFFFFFFFF; ++ bb->node[*p_new_node_number].l[1].depth = 0; ++ ++ /* OCTAPI_BT0_LINK to parent!*/ ++ link->node_number = *p_new_node_number; ++ link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/ ++ ++ if ( state == 0 ) ++ *p_prev_node_number = 0xFFFFFFFF; ++ ++ return(GENERIC_OK); ++ } ++ else /* Current node is used, check for a match and a direction.*/ ++ { ++ OCTAPI_BT0_NODE * this_node; ++ UINT32 compare; ++ ++ /* Get a pointer to this node.*/ ++ this_node = &(bb->node[link->node_number]); ++ ++ /* Compare this node to the lkey.*/ ++ compare = OctApiBt0KeyCompare(bb,link,lkey); ++ ++ if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ ++ { ++ if ( state == 0 ) ++ *p_prev_node_number = OCTAPI_BT0_NO_SMALLER_KEY; ++ ++ if ( *p_prev_node_number != OCTAPI_BT0_NO_SMALLER_KEY ) ++ { ++ /* Check if the key is the smallest one encountered yet.*/ ++ okey = &(bb->key[bb->key_size * (*p_prev_node_number)]); ++ nkey = &(bb->key[bb->key_size * link->node_number]); ++ /* If the node is key smaller then the old small one, change the value.*/ ++ if ( *nkey > *okey ) ++ { ++ if ( *nkey < *lkey ) ++ *p_prev_node_number = link->node_number; ++ } ++ } ++ ++ result = OctApiBt0AddNode4(bb,&(this_node->l[0]), lkey, p_new_node_number, p_prev_node_number, 1); ++ if (result != GENERIC_OK) return(result); ++ } ++ else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ ++ { ++ if ( state == 0 ) ++ *p_prev_node_number = link->node_number; ++ else ++ { ++ if ( *p_prev_node_number == OCTAPI_BT0_NO_SMALLER_KEY ) ++ *p_prev_node_number = link->node_number; ++ else ++ { ++ /* Check if the key is the smallest one encountered yet.*/ ++ okey = &(bb->key[bb->key_size * (*p_prev_node_number)]); ++ nkey = &(bb->key[bb->key_size * link->node_number]); ++ /* If the node is key smaller then the old small one, change the value.*/ ++ if ( *nkey > *okey ) ++ { ++ if ( *nkey < *lkey ) ++ *p_prev_node_number = link->node_number; ++ } ++ } ++ } ++ ++ result = OctApiBt0AddNode4(bb,&(this_node->l[1]), lkey, p_new_node_number, p_prev_node_number, 1); ++ if (result != GENERIC_OK) return(result); ++ } ++ else ++ { ++ *p_new_node_number = link->node_number; ++ return(OCTAPI_BT0_KEY_ALREADY_IN_TREE); ++ } ++ ++ /* Check if this node is unbalanced by 2. If so, rebalance it:*/ ++ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || ++ this_node->l[1].depth > (this_node->l[0].depth + 1)) ++ { ++ OctApiBt0Rebalance(bb,link); ++ } ++ ++ /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ ++ OctApiBt0UpdateLinkDepth(bb,link); ++ ++ return(GENERIC_OK); ++ } ++} ++#endif ++ ++#if !SKIP_OctApiBt0KeyCompare ++UINT32 OctApiBt0KeyCompare(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey) ++{ ++ UINT32 * nkey; ++ UINT32 i; ++ ++ /* Find the first UINT32 of the key.*/ ++ nkey = &(bb->key[bb->key_size * link->node_number]); ++ ++ for(i=0;ikey_size;i++) ++ { ++ if (lkey[i] < nkey[i]) ++ return(OCTAPI_BT0_LKEY_SMALLER); ++ else if (lkey[i] > nkey[i]) ++ return(OCTAPI_BT0_LKEY_LARGER); ++ } ++ ++ return(OCTAPI_BT0_LKEY_EQUAL); ++} ++#endif ++ ++ ++#if !SKIP_OctApiBt0UpdateLinkDepth ++void OctApiBt0UpdateLinkDepth(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link) ++{ ++ OCTAPI_BT0_NODE * this_node; ++ ++ /* Get a pointer to this node.*/ ++ this_node = &(bb->node[link->node_number]); ++ ++ if (this_node->l[0].depth > this_node->l[1].depth) ++ link->depth = this_node->l[0].depth + 1; ++ else ++ link->depth = this_node->l[1].depth + 1; ++} ++#endif ++ ++#if !SKIP_OctApiBt0Rebalance ++void OctApiBt0Rebalance(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * root_link) ++{ ++ if (bb->node[root_link->node_number].l[0].depth > (bb->node[root_link->node_number].l[1].depth + 1)) /* Heavy to the left.*/ ++ { ++ /* Check if the right child of the heavy child node is causing a problem.*/ ++ /* If so, do a left rotate in order to make the left most child the longer one.*/ ++ { ++ OCTAPI_BT0_LINK * heavy_link; ++ heavy_link = &(bb->node[root_link->node_number].l[0]); ++ ++ if (bb->node[heavy_link->node_number].l[1].depth > bb->node[heavy_link->node_number].l[0].depth) ++ { ++ OctApiBt0ExternalHeavy(bb,heavy_link); ++ } ++ } ++ ++ /* Ready to do super rotation!*/ ++ { ++ OCTAPI_BT0_LINK init_root_link; ++ OCTAPI_BT0_LINK init_heavy_link; ++ OCTAPI_BT0_LINK init_leaf_tree[3]; ++ ++ /* Save pertinent initial OCTAPI_BT0_LINK information.*/ ++ init_root_link = *root_link; ++ init_heavy_link = bb->node[root_link->node_number].l[0]; ++ init_leaf_tree[2] = bb->node[root_link->node_number].l[1]; ++ init_leaf_tree[0] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[0]; ++ init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[1]; ++ ++ /* Restructure the tree.*/ ++ *root_link = init_heavy_link; ++ bb->node[init_heavy_link.node_number].l[1] = init_root_link; ++ bb->node[init_root_link.node_number].l[0] = init_leaf_tree[1]; ++ ++ /* Reconstruct the depth of the branches.*/ ++ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[1])); ++ OctApiBt0UpdateLinkDepth(bb,root_link); ++ } ++ } ++ else if (bb->node[root_link->node_number].l[1].depth > (bb->node[root_link->node_number].l[0].depth + 1)) /* Heavy to the right.*/ ++ { ++ /* Check if the right child of the heavy child node is causing a problem.*/ ++ /* If so, do a left rotate in order to make the left most child the longer one.*/ ++ { ++ OCTAPI_BT0_LINK * heavy_link; ++ heavy_link = &(bb->node[root_link->node_number].l[1]); ++ ++ if (bb->node[heavy_link->node_number].l[0].depth > bb->node[heavy_link->node_number].l[1].depth) ++ { ++ OctApiBt0ExternalHeavy(bb,heavy_link); ++ } ++ } ++ ++ /* Ready to do super rotation!*/ ++ { ++ OCTAPI_BT0_LINK init_root_link; ++ OCTAPI_BT0_LINK init_heavy_link; ++ OCTAPI_BT0_LINK init_leaf_tree[3]; ++ ++ /* Save pertinent initial OCTAPI_BT0_LINK information.*/ ++ init_root_link = *root_link; ++ init_heavy_link = bb->node[root_link->node_number].l[1]; ++ init_leaf_tree[2] = bb->node[root_link->node_number].l[0]; ++ init_leaf_tree[0] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[1]; ++ init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[0]; ++ ++ /* Restructure the tree.*/ ++ *root_link = init_heavy_link; ++ bb->node[init_heavy_link.node_number].l[0] = init_root_link; ++ bb->node[init_root_link.node_number].l[1] = init_leaf_tree[1]; ++ ++ /* Reconstruct the depth of the branches.*/ ++ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[0])); ++ OctApiBt0UpdateLinkDepth(bb,root_link); ++ } ++ } ++} ++#endif ++ ++/* This function does a rotation towards the outside of the tree*/ ++/* in order to keep the heavy branches towards the outside.*/ ++#if !SKIP_OctApiBt0ExternalHeavy ++void OctApiBt0ExternalHeavy(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * root_link) ++{ ++ if (bb->node[root_link->node_number].l[1].depth > bb->node[root_link->node_number].l[0].depth) /* Exterior of tree is towards the left.*/ ++ { ++ OCTAPI_BT0_LINK init_root_link; ++ OCTAPI_BT0_LINK init_heavy_link; ++ OCTAPI_BT0_LINK init_leaf_tree[3]; ++ ++ /* Save pertinent initial OCTAPI_BT0_LINK information.*/ ++ init_root_link = *root_link; ++ init_leaf_tree[0] = bb->node[root_link->node_number].l[0]; ++ init_heavy_link = bb->node[root_link->node_number].l[1]; ++ init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[0]; ++ init_leaf_tree[2] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[1]; ++ ++ /* Restructure the tree.*/ ++ *root_link = init_heavy_link; ++ bb->node[init_heavy_link.node_number].l[0] = init_root_link; ++ bb->node[init_root_link.node_number].l[1] = init_leaf_tree[1]; ++ ++ /* Reconstruct the depth of the branches.*/ ++ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[0])); ++ OctApiBt0UpdateLinkDepth(bb,root_link); ++ } ++ else if (bb->node[root_link->node_number].l[0].depth > bb->node[root_link->node_number].l[1].depth) /* Exterior of tree is towards the right.*/ ++ { ++ OCTAPI_BT0_LINK init_root_link; ++ OCTAPI_BT0_LINK init_heavy_link; ++ OCTAPI_BT0_LINK init_leaf_tree[3]; ++ ++ /* Save pertinent initial OCTAPI_BT0_LINK information.*/ ++ init_root_link = *root_link; ++ init_leaf_tree[0] = bb->node[root_link->node_number].l[1]; ++ init_heavy_link = bb->node[root_link->node_number].l[0]; ++ init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[1]; ++ init_leaf_tree[2] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[0]; ++ ++ /* Restructure the tree.*/ ++ *root_link = init_heavy_link; ++ bb->node[init_heavy_link.node_number].l[1] = init_root_link; ++ bb->node[init_root_link.node_number].l[0] = init_leaf_tree[1]; ++ ++ /* Reconstruct the depth of the branches.*/ ++ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[1])); ++ OctApiBt0UpdateLinkDepth(bb,root_link); ++ } ++} ++#endif ++ ++ ++/* State:*/ ++/* 0 = seeking node to be removed.*/ ++/* 1 = node found, left branch taken.*/ ++/* 2 = node found, right branch taken.*/ ++#if !SKIP_OctApiBt0RemoveNode2 ++UINT32 OctApiBt0RemoveNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey, OCTAPI_BT0_LINK * link_to_removed_node, UINT32 state, OCTAPI_BT0_LINK * volatile_grandparent_link) ++{ ++ UINT32 result; ++ OCTAPI_BT0_NODE * this_node; ++ ++ /* Get a pointer to this node.*/ ++ this_node = &(bb->node[link->node_number]); ++ ++ if (state == 0) ++ { ++ if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/ ++ { ++ return(OCTAPI_BT0_KEY_NOT_IN_TREE); ++ } ++ else /* Current node is used, check for a match and a direction.*/ ++ { ++ UINT32 compare; ++ ++ /* Compare this node to the lkey.*/ ++ compare = OctApiBt0KeyCompare(bb,link,lkey); ++ ++ if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ ++ { ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, 0, NULL); ++ if (result != GENERIC_OK) return(result); ++ } ++ else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ ++ { ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, 0, NULL); ++ if (result != GENERIC_OK) return(result); ++ } ++ else ++ { ++ link_to_removed_node = link; ++ ++ /* Keep on going down to find a replacement node.*/ ++ if (bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) ++ { ++ /* Doe! No tree left! WHAT TO DO? */ ++ /* Just delete the current node. That's it.*/ ++ ++ /* Release the current node (restore free node link-list)*/ ++ bb->node[link->node_number].next_free_node = bb->next_free_node; ++ bb->next_free_node = link->node_number; ++ ++ link->node_number = 0xFFFFFFFF; ++ link->depth = 0; ++ ++ return(GENERIC_OK); ++ } ++ else if (bb->node[link->node_number].l[0].node_number != 0xFFFFFFFF) /* Left node is present. Go left, then permanently right.*/ ++ { ++ OCTAPI_BT0_NODE * removed_node_pnt; ++ removed_node_pnt = &(bb->node[link->node_number]); ++ ++ result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[0]), lkey, link_to_removed_node, 1, link); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/ ++ /* but is about to be discarded! Save it quickly!*/ ++ /* bb->node[link->node_number].l[0] = removed_node_pnt->l[0];*/ ++ } ++ else /* Right node is present. Go right, then permanently left.*/ ++ { ++ OCTAPI_BT0_NODE * removed_node_pnt; ++ removed_node_pnt = &(bb->node[link->node_number]); ++ ++ result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[1]), lkey, link_to_removed_node, 2, link); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/ ++ /* but is about to be discarded! Save it quickly!*/ ++ /* bb->node[link->node_number].l[1] = removed_node_pnt->l[1];*/ ++ } ++ } ++ } ++ } ++ else ++ { ++ /* Left side, Right-most node found! OR*/ ++ /* Right side, Left-most node found!*/ ++ if ((state == 1 && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) || ++ (state == 2 && bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF)) ++ { ++ OCTAPI_BT0_LINK init_chosen_link; ++ ++ /* Release the current node (restore free node link-list)*/ ++ bb->node[link_to_removed_node->node_number].next_free_node = bb->next_free_node; ++ bb->next_free_node = link_to_removed_node->node_number; ++ ++ /* Save the link to the chosen node, because it is about to be deleted.*/ ++ init_chosen_link = *link; ++ ++ /* Remove this node, and allow the tree to go on:*/ ++ { ++ OCTAPI_BT0_LINK init_child_link[2]; ++ ++ init_child_link[0] = bb->node[link->node_number].l[0]; ++ init_child_link[1] = bb->node[link->node_number].l[1]; ++ ++ if (state == 1) ++ *link = init_child_link[0]; ++ else ++ *link = init_child_link[1]; ++ } ++ ++ /* Replace the removed node by this node.*/ ++ { ++ OCTAPI_BT0_LINK init_removed_child_link[2]; ++ ++ init_removed_child_link[0] = bb->node[link_to_removed_node->node_number].l[0]; ++ init_removed_child_link[1] = bb->node[link_to_removed_node->node_number].l[1]; ++ ++ *link_to_removed_node = init_chosen_link; ++ bb->node[init_chosen_link.node_number].l[0] = init_removed_child_link[0]; ++ bb->node[init_chosen_link.node_number].l[1] = init_removed_child_link[1]; ++ } ++ ++ return(GENERIC_OK); ++ } ++ else ++ { ++ /* Keep on going, we have not found the center most node yet!*/ ++ if (state == 1) ++ { ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, state, NULL); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Refresh the link if our link is volatile.*/ ++ if (volatile_grandparent_link != NULL) ++ { ++ link = &(bb->node[volatile_grandparent_link->node_number].l[0]); ++ } ++ } ++ else ++ { ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, state, NULL); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Refresh the link if our link is volatile.*/ ++ if (volatile_grandparent_link != NULL) ++ { ++ link = &(bb->node[volatile_grandparent_link->node_number].l[1]); ++ } ++ } ++ } ++ } ++ ++ /* We may have messed up the tree. So patch it!*/ ++ /* Check if this node is unbalanced by 2. If so, rebalance it:*/ ++ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || ++ this_node->l[1].depth > (this_node->l[0].depth + 1)) ++ { ++ OctApiBt0Rebalance(bb,link); ++ } ++ ++ /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ ++ OctApiBt0UpdateLinkDepth(bb,link); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++/* State:*/ ++/* 0 = seeking node to be removed.*/ ++/* 1 = node found, left branch taken.*/ ++/* 2 = node found, right branch taken.*/ ++#if !SKIP_OctApiBt0RemoveNode3 ++UINT32 OctApiBt0RemoveNode3(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey, OCTAPI_BT0_LINK * link_to_removed_node, UINT32 state, OCTAPI_BT0_LINK * volatile_grandparent_link, UINT32 *p_prev_node_number ) ++{ ++ UINT32 result; ++ UINT32 *nkey; ++ UINT32 *okey; ++ OCTAPI_BT0_NODE * this_node; ++ ++ /* Get a pointer to this node.*/ ++ this_node = &(bb->node[link->node_number]); ++ ++ if (state == 0) ++ { ++ if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/ ++ { ++ return(OCTAPI_BT0_KEY_NOT_IN_TREE); ++ } ++ else /* Current node is used, check for a match and a direction.*/ ++ { ++ UINT32 compare; ++ ++ /* Compare this node to the lkey.*/ ++ compare = OctApiBt0KeyCompare(bb,link,lkey); ++ ++ if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ ++ { ++ /* Check if the key is the biggest one encountered yet.*/ ++ okey = &(bb->key[bb->key_size * (*p_prev_node_number)]); ++ nkey = &(bb->key[bb->key_size * link->node_number]); ++ /* If the node is key bigger then the old one, change the value.*/ ++ if ( *nkey > *okey ) ++ { ++ if ( *nkey < *lkey ) ++ *p_prev_node_number = link->node_number; ++ } ++ ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, 0, NULL); ++ if (result != GENERIC_OK) return(result); ++ } ++ else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ ++ { ++ /* Check if the key is the biggest one encountered yet.*/ ++ okey = &(bb->key[bb->key_size * (*p_prev_node_number)]); ++ nkey = &(bb->key[bb->key_size * link->node_number]); ++ /* If the node is key bigger then the old one, change the value.*/ ++ if ( *nkey > *okey ) ++ { ++ if ( *nkey < *lkey ) ++ *p_prev_node_number = link->node_number; ++ } ++ ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, 0, NULL); ++ if (result != GENERIC_OK) return(result); ++ } ++ else ++ { ++ link_to_removed_node = link; ++ ++ /* Keep on going down to find a replacement node.*/ ++ if (bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) ++ { ++ /* Doe! No tree left! WHAT TO DO? */ ++ /* Just delete the current node. That's it.*/ ++ ++ /* Release the current node (restore free node link-list)*/ ++ bb->node[link->node_number].next_free_node = bb->next_free_node; ++ bb->next_free_node = link->node_number; ++ ++ link->node_number = 0xFFFFFFFF; ++ link->depth = 0; ++ ++ return(GENERIC_OK); ++ } ++ else if (bb->node[link->node_number].l[0].node_number != 0xFFFFFFFF) /* Left node is present. Go left, then permanently right.*/ ++ { ++ OCTAPI_BT0_NODE * removed_node_pnt; ++ removed_node_pnt = &(bb->node[link->node_number]); ++ ++ result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[0]), lkey, link_to_removed_node, 1, link); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/ ++ /* but is about to be discarded! Save it quickly!*/ ++ /* bb->node[link->node_number].l[0] = removed_node_pnt->l[0];*/ ++ } ++ else /* Right node is present. Go right, then permanently left.*/ ++ { ++ OCTAPI_BT0_NODE * removed_node_pnt; ++ removed_node_pnt = &(bb->node[link->node_number]); ++ ++ result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[1]), lkey, link_to_removed_node, 2, link); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/ ++ /* but is about to be discarded! Save it quickly!*/ ++ /* bb->node[link->node_number].l[1] = removed_node_pnt->l[1];*/ ++ } ++ } ++ } ++ } ++ else ++ { ++ /* Check if the key is the biggest one encountered yet.*/ ++ okey = &(bb->key[bb->key_size * (*p_prev_node_number)]); ++ nkey = &(bb->key[bb->key_size * link->node_number]); ++ /* If the node is key bigger then the old one, change the value.*/ ++ if ( *nkey > *okey ) ++ { ++ if ( *nkey < *lkey ) ++ *p_prev_node_number = link->node_number; ++ } ++ ++ /* Left side, Right-most node found! OR*/ ++ /* Right side, Left-most node found!*/ ++ if ((state == 1 && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) || ++ (state == 2 && bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF)) ++ { ++ OCTAPI_BT0_LINK init_chosen_link; ++ ++ /* Release the current node (restore free node link-list)*/ ++ bb->node[link_to_removed_node->node_number].next_free_node = bb->next_free_node; ++ bb->next_free_node = link_to_removed_node->node_number; ++ ++ /* Save the link to the chosen node, because it is about to be deleted.*/ ++ init_chosen_link = *link; ++ ++ /* Remove this node, and allow the tree to go on:*/ ++ { ++ OCTAPI_BT0_LINK init_child_link[2]; ++ ++ init_child_link[0] = bb->node[link->node_number].l[0]; ++ init_child_link[1] = bb->node[link->node_number].l[1]; ++ ++ if (state == 1) ++ *link = init_child_link[0]; ++ else ++ *link = init_child_link[1]; ++ } ++ ++ /* Replace the removed node by this node.*/ ++ { ++ OCTAPI_BT0_LINK init_removed_child_link[2]; ++ ++ init_removed_child_link[0] = bb->node[link_to_removed_node->node_number].l[0]; ++ init_removed_child_link[1] = bb->node[link_to_removed_node->node_number].l[1]; ++ ++ *link_to_removed_node = init_chosen_link; ++ bb->node[init_chosen_link.node_number].l[0] = init_removed_child_link[0]; ++ bb->node[init_chosen_link.node_number].l[1] = init_removed_child_link[1]; ++ } ++ ++ return(GENERIC_OK); ++ } ++ else ++ { ++ /* Keep on going, we have not found the center most node yet!*/ ++ if (state == 1) ++ { ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, state, NULL); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Refresh the link if our link is volatile.*/ ++ if (volatile_grandparent_link != NULL) ++ { ++ link = &(bb->node[volatile_grandparent_link->node_number].l[0]); ++ } ++ } ++ else ++ { ++ result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, state, NULL); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Refresh the link if our link is volatile.*/ ++ if (volatile_grandparent_link != NULL) ++ { ++ link = &(bb->node[volatile_grandparent_link->node_number].l[1]); ++ } ++ } ++ } ++ } ++ ++ /* We may have messed up the tree. So patch it!*/ ++ /* Check if this node is unbalanced by 2. If so, rebalance it:*/ ++ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || ++ this_node->l[1].depth > (this_node->l[0].depth + 1)) ++ { ++ OctApiBt0Rebalance(bb,link); ++ } ++ ++ /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ ++ OctApiBt0UpdateLinkDepth(bb,link); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiBt0RemoveNode ++UINT32 OctApiBt0RemoveNode(void * b,void * key) ++{ ++ OCTAPI_BT0 * bb; ++ UINT32 result; ++ UINT32 * lkey; ++ ++ /* Load all!*/ ++ bb = (OCTAPI_BT0 *)(b); ++ OctApiBt0CorrectPointers(bb); ++ ++ /* Register in the key and the data.*/ ++ lkey = ((UINT32 *)key); ++ ++ /* Attempt to remove the node. Only a "no hit" will cause an error.*/ ++ result = OctApiBt0RemoveNode2(bb,&(bb->root_link), lkey, NULL, 0, NULL); ++ if (result != GENERIC_OK) return(result); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiBt0QueryNode2 ++UINT32 OctApiBt0QueryNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 * node_number) ++{ ++ UINT32 result; ++ ++ if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/ ++ { ++ return(OCTAPI_BT0_KEY_NOT_IN_TREE); ++ } ++ else /* Current node is used, check for a match and a direction.*/ ++ { ++ UINT32 compare; ++ ++ /* Compare this node to the lkey.*/ ++ compare = OctApiBt0KeyCompare(bb,link,lkey); ++ ++ if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ ++ { ++ result = OctApiBt0QueryNode2(bb,&(bb->node[link->node_number].l[0]), lkey, node_number); ++ if (result != GENERIC_OK) return(result); ++ } ++ else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ ++ { ++ result = OctApiBt0QueryNode2(bb,&(bb->node[link->node_number].l[1]), lkey, node_number); ++ if (result != GENERIC_OK) return(result); ++ } ++ else ++ { ++ /* A match!*/ ++ *node_number = link->node_number; ++ } ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++#if !SKIP_OctApiBt0QueryNode ++UINT32 OctApiBt0QueryNode(void * b,void * key,void ** data) ++{ ++ OCTAPI_BT0 * bb; ++ UINT32 node_number; ++ UINT32 result; ++ UINT32 * lkey; ++ ++ /* Load all!*/ ++ bb = (OCTAPI_BT0 *)(b); ++ OctApiBt0CorrectPointers(bb); ++ ++ /* Register in the key and the data.*/ ++ lkey = ((UINT32 *)key); ++ ++ /* Get the node number.*/ ++ result = OctApiBt0QueryNode2(bb,&(bb->root_link),lkey,&node_number); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Return the address of the data to the user.*/ ++ if ( bb->data_size > 0 ) ++ *data = (void *)(&(bb->data[bb->data_size * node_number])); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiBt0GetFirstNode ++UINT32 OctApiBt0GetFirstNode(void * b,void ** key, void ** data) ++{ ++ OCTAPI_BT0 * bb; ++ OCTAPI_BT0_NODE * node; ++ UINT32 node_number; ++ UINT32 * lkey; ++ ++ /* Load all!*/ ++ bb = (OCTAPI_BT0 *)(b); ++ OctApiBt0CorrectPointers(bb); ++ ++ /* Register in the key and the data.*/ ++ lkey = ((UINT32 *)key); ++ ++ /* Check if there are any keys present in the tree. */ ++ if (bb->root_link.node_number == 0xFFFFFFFF) return OCTAPI_BT0_NO_NODES_AVAILABLE; ++ ++ node_number = bb->root_link.node_number; ++ node = &bb->node[node_number]; ++ ++ /* Make our way down to the left-most node. */ ++ while (node->l[0].node_number != 0xFFFFFFFF) ++ { ++ node_number = node->l[0].node_number; ++ node = &bb->node[node_number]; ++ } ++ ++ /* Return the address of the data to the user.*/ ++ if ( bb->key_size > 0 ) ++ *key = (void *)(&(bb->key[bb->key_size * node_number])); ++ ++ if ( bb->data_size > 0 ) ++ *data = (void *)(&(bb->data[bb->data_size * node_number])); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiBt0FindOrAddNode ++UINT32 OctApiBt0FindOrAddNode(void * b,void * key,void ** data, UINT32 *fnct_result) ++{ ++ OCTAPI_BT0 * bb; ++ OCTAPI_BT0_NODE * new_node; ++ UINT32 * lkey; ++ UINT32 * nkey; ++ UINT32 i; ++ UINT32 new_node_number; ++ UINT32 temp_node_number = 0; ++ UINT32 result; ++ UINT32 tree_already_full = FALSE; ++ ++ /* Load all!*/ ++ bb = (OCTAPI_BT0 *)(b); ++ OctApiBt0CorrectPointers(bb); ++ ++ /* Seize the node!*/ ++ new_node_number = bb->next_free_node; ++ /* Register in the key and the data.*/ ++ lkey = ((UINT32 *)key); ++ ++ /* Check that there is at least one block left.*/ ++ if (bb->next_free_node != 0xFFFFFFFF) ++ { ++ ++ temp_node_number = new_node_number; ++ new_node = &(bb->node[new_node_number]); ++ bb->next_free_node = new_node->next_free_node; ++ ++ /* Find the first UINT32 of the key.*/ ++ nkey = &(bb->key[bb->key_size * new_node_number]); ++ ++ /* Copy the key.*/ ++ for(i=0;ikey_size;i++) ++ nkey[i] = lkey[i]; ++ } ++ else ++ tree_already_full = TRUE; /* Signal that the tree was already full when the function was called.*/ ++ ++ /* Attempt to place the node. Only a "multiple hit" will cause an error.*/ ++ result = OctApiBt0AddNode3(bb,&(bb->root_link), lkey, &new_node_number); ++ switch( result ) ++ { ++ case GENERIC_OK: ++ *fnct_result = OCTAPI0_BT0_NODE_ADDDED; ++ break; ++ case OCTAPI_BT0_KEY_ALREADY_IN_TREE: ++ *fnct_result = OCTAPI0_BT0_NODE_FOUND; ++ /* This attempt did not add a new node. Refree the node!*/ ++ if ( tree_already_full == FALSE ) ++ bb->next_free_node = temp_node_number; ++ result = GENERIC_OK; ++ break; ++ default: ++ break; ++ } ++ ++ if (result != GENERIC_OK) ++ { ++ /* This attempt failed. Refree the node!*/ ++ if ( tree_already_full == FALSE ) ++ bb->next_free_node = new_node_number; ++ ++ /* Return the error code.*/ ++ return(result); ++ } ++ ++ /* Return the address of the data to the user.*/ ++ if ( bb->data_size > 0 ) ++ *data = (void *)(&(bb->data[bb->data_size * new_node_number])); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++#if !SKIP_OctApiBt0AddNodeReportPrevNodeData ++UINT32 OctApiBt0AddNodeReportPrevNodeData(void * b,void * key,void ** data, void ** prev_data, PUINT32 fnct_result ) ++{ ++ OCTAPI_BT0 * bb; ++ OCTAPI_BT0_NODE * new_node; ++ UINT32 * lkey; ++ UINT32 * nkey; ++ UINT32 i; ++ UINT32 new_node_number; ++ UINT32 temp_node_number; ++ UINT32 prev_node_number; ++ UINT32 result; ++ ++ /* Load all!*/ ++ bb = (OCTAPI_BT0 *)(b); ++ OctApiBt0CorrectPointers(bb); ++ ++ /* Check that there is at least one block left.*/ ++ if (bb->next_free_node == 0xFFFFFFFF) return(OCTAPI_BT0_NO_NODES_AVAILABLE); ++ ++ /* Seize the node!*/ ++ new_node_number = bb->next_free_node; ++ temp_node_number = new_node_number; ++ new_node = &(bb->node[new_node_number]); ++ bb->next_free_node = new_node->next_free_node; ++ ++ /* Set the previous node value */ ++ prev_node_number = 0xFFFFFFFF; ++ ++ /* Register in the key and the data.*/ ++ lkey = ((UINT32 *)key); ++ ++ /* Find the first UINT32 of the key.*/ ++ nkey = &(bb->key[bb->key_size * new_node_number]); ++ ++ /* Copy the key.*/ ++ for(i=0;ikey_size;i++) ++ nkey[i] = lkey[i]; ++ ++ /* Attempt to place the node. Only a "multiple hit" will cause an error.*/ ++ result = OctApiBt0AddNode4(bb,&(bb->root_link), lkey, &new_node_number, &prev_node_number, 0); ++ switch( result ) ++ { ++ case GENERIC_OK: ++ *fnct_result = OCTAPI0_BT0_NODE_ADDDED; ++ break; ++ case OCTAPI_BT0_KEY_ALREADY_IN_TREE: ++ *fnct_result = OCTAPI0_BT0_NODE_FOUND; ++ /* This attempt did not add a new node. Refree the node!*/ ++ bb->next_free_node = temp_node_number; ++ result = GENERIC_OK; ++ break; ++ default: ++ break; ++ } ++ ++ if (result != GENERIC_OK) ++ { ++ /* This attempt failed. Refree the node!*/ ++ bb->next_free_node = new_node_number; ++ ++ /* Return the error code.*/ ++ return(result); ++ } ++ ++ /* Return the address of the data to the user.*/ ++ if ( bb->data_size > 0 ) ++ *data = (void *)(&(bb->data[bb->data_size * new_node_number])); ++ ++ if ( bb->data_size > 0 ) ++ { ++ if ( (prev_node_number != 0xFFFFFFFF) && ++ (prev_node_number != OCTAPI_BT0_NO_SMALLER_KEY) && ++ (*fnct_result == OCTAPI0_BT0_NODE_ADDDED)) ++ *prev_data = ( void* )(&(bb->data[bb->data_size * prev_node_number])); ++ else if ( prev_node_number == 0xFFFFFFFF ) ++ *prev_data = ( void* )(&bb->invalid_value); ++ else if ( prev_node_number == OCTAPI_BT0_NO_SMALLER_KEY ) ++ *prev_data = ( void* )(&bb->no_smaller_key); ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/apilib/bt/octapi_bt0_private.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/bt/octapi_bt0_private.h +--- linux-source-4.19/drivers/dahdi/oct612x/apilib/bt/octapi_bt0_private.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/bt/octapi_bt0_private.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,93 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_bt0_private.h ++ ++Copyright (c) 2001 Octasic Inc. All rights reserved. ++ ++Description: ++ ++ Library used to manage a binary tree of variable max size. Library is ++ made to use one block of contiguous memory to manage the tree. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 11 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#ifndef __OCTAPI_BT0_PRIVATE_H__ ++#define __OCTAPI_BT0_PRIVATE_H__ ++ ++ ++ ++#include "octdef.h" ++ ++#define OCTAPI_BT0_LKEY_LARGER 0x0 ++#define OCTAPI_BT0_LKEY_SMALLER 0x1 ++#define OCTAPI_BT0_LKEY_EQUAL 0x2 ++ ++typedef struct __OCTAPI_BT0_LINK__ ++{ ++ UINT32 node_number; ++ UINT32 depth; ++} OCTAPI_BT0_LINK; ++ ++typedef struct __OCTAPI_BT0_NODE__ ++{ ++ UINT32 next_free_node; /* Number of the next node in the free node link-list.*/ ++ OCTAPI_BT0_LINK l[2]; /* 0 = left link; 1 = right link.*/ ++} OCTAPI_BT0_NODE; ++ ++ ++typedef struct __OCTAPI_BT0__ ++{ ++ UINT32 number_of_items; /* Number of items on total that can be allocated in the tree.*/ ++ UINT32 key_size; /* Size is in UINT32s*/ ++ UINT32 data_size; /* Size is in UINT32s*/ ++ ++ /* Empty node linked-list:*/ ++ UINT32 next_free_node; /* 0xFFFFFFFF means that no nodes are free.*/ ++ ++ /* Tree as such:*/ ++ OCTAPI_BT0_NODE * node; /* Array of nodes (number_of_items in size).*/ ++ ++ /* Tree root:*/ ++ OCTAPI_BT0_LINK root_link; ++ ++ /* Associated key structure*/ ++ UINT32 * key; /* Array of keys associated to NODEs.*/ ++ ++ /* Associated data structure.*/ ++ UINT32 * data; /* Array of data associated to NODEs.*/ ++ ++ UINT32 invalid_value; ++ UINT32 no_smaller_key; ++ ++} OCTAPI_BT0; ++ ++void OctApiBt0CorrectPointers( OCTAPI_BT0 * bb ); ++UINT32 OctApiBt0AddNode2( OCTAPI_BT0 * bb, OCTAPI_BT0_LINK * link, UINT32 * lkey, UINT32 new_node_number ); ++UINT32 OctApiBt0AddNode3( OCTAPI_BT0 * bb, OCTAPI_BT0_LINK * link, UINT32 * lkey, UINT32 *p_new_node_number ); ++UINT32 OctApiBt0AddNode4(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 *p_new_node_number, UINT32 *p_prev_node_number, UINT32 state ); ++UINT32 OctApiBt0KeyCompare( OCTAPI_BT0 * bb, OCTAPI_BT0_LINK * link, UINT32 * lkey ); ++void OctApiBt0UpdateLinkDepth( OCTAPI_BT0 * bb, OCTAPI_BT0_LINK * link ); ++void OctApiBt0Rebalance( OCTAPI_BT0 * bb, OCTAPI_BT0_LINK * root_link ); ++void OctApiBt0ExternalHeavy( OCTAPI_BT0 * bb, OCTAPI_BT0_LINK * root_link ); ++UINT32 OctApiBt0RemoveNode2( OCTAPI_BT0 * bb, OCTAPI_BT0_LINK * link, UINT32 * lkey, OCTAPI_BT0_LINK * link_to_removed_node, UINT32 state, OCTAPI_BT0_LINK * volatile_grandparent_link ); ++ ++ ++ ++#endif /*__OCTAPI_BT0_PRIVATE_H__*/ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/apilib/largmath/octapi_largmath.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/largmath/octapi_largmath.c +--- linux-source-4.19/drivers/dahdi/oct612x/apilib/largmath/octapi_largmath.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/largmath/octapi_largmath.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,628 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_largmath.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Library used to perform arithmetic on integer values of an integer multiple ++ of 32-bits. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 10 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#include "apilib/octapi_largmath.h" ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLmAdd. ++| ++| Description: This function adds 2 numbers, a and b. Number a is ++| (alen + 1) * 32 bits long; b is (blen + 1) * 32 bits long. The ++| result is (zlen + 1) * 32 bits long. It the function succeeds it returns ++| GENERIC_OK, else GENERIC_ERROR. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *a UINT32 The array containing the first number. ++| alen USHORT The length of array a, minus 1 (0 - 99). ++| *b UINT32 The array containing the second number. ++| blen USHORT The length of array b, minus 1 (0 - 99). ++| *z UINT32 The array containing the resulting number. ++| zlen USHORT The length of array z, minus 1 (0 - 99). ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmAdd ++UINT32 OctApiLmAdd(UINT32 * a,USHORT alen,UINT32 * b,USHORT blen,UINT32 * z, USHORT zlen) ++{ ++ USHORT i; ++ UINT32 temp; ++ UINT32 carry=0; ++ UINT32 aprim; ++ UINT32 bprim; ++ ++ /* Check for array lengths.*/ ++ if (alen > zlen || blen > zlen) return(OCTAPI_LM_ARRAY_SIZE_MISMATCH); ++ ++ for(i=0;i<=zlen;i++) ++ { ++ if (i <= alen) aprim = *(a+i); else aprim = 0; ++ if (i <= blen) bprim = *(b+i); else bprim = 0; ++ temp = aprim + bprim + carry; ++ ++ /* Calculate carry for next time.*/ ++ if (carry == 0) ++ if (temp < aprim) carry = 1; else carry = 0; ++ else ++ if (temp <= aprim) carry = 1; else carry = 0; ++ ++ /* Write new value.*/ ++ *(z+i) = temp; ++ } ++ ++ /* Check for overflow.*/ ++ if (carry == 1) return(OCTAPI_LM_OVERFLOW); ++ ++ /* All is well.*/ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLmSubtract. ++| ++| Description: This function subtracts 2 numbers, a and b. Number a is ++| (alen + 1) * 32 bits long; b is (blen + 1) * 32 bits long. The result ++| is (zlen + 1) * 32 bits long. It the function succeeds it returns ++| GENERIC_OK, else GENERIC_ERROR. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *a UINT32 The array containing the first number. ++| alen USHORT The length of array a, minus 1 (0 - 99). ++| *bneg UINT32 The array containing the second number. ++| blen USHORT The length of array b, minus 1 (0 - 99). ++| *z UINT32 The array containing the resulting number. ++| zlen USHORT The length of array z, minus 1 (0 - 99). ++| *neg USHORT Indicates if the result is negative ++| (TRUE/FALSE). ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmSubtract ++UINT32 OctApiLmSubtract(UINT32 * a,USHORT alen,UINT32 * bneg,USHORT blen,UINT32 * z,USHORT zlen,USHORT * neg) ++{ ++ USHORT i; ++ UINT32 temp; ++ UINT32 carry=1; ++ UINT32 aprim; ++ UINT32 bprim; ++ ++ /* Check for array lengths.*/ ++ if (alen > zlen || blen > zlen) return(OCTAPI_LM_ARRAY_SIZE_MISMATCH); ++ ++ for(i=0;i<=zlen;i++) ++ { ++ if (i <= alen) aprim = *(a+i); else aprim = 0; ++ if (i <= blen) bprim = ~(*(bneg+i)); else bprim = 0xFFFFFFFF; ++ temp = aprim + bprim + carry; ++ ++ /* Calculate carry for next time.*/ ++ if (carry == 0) ++ if (temp < aprim) carry = 1; else carry = 0; ++ else ++ if (temp <= aprim) carry = 1; else carry = 0; ++ ++ /* Write new value.*/ ++ *(z+i) = temp; ++ } ++ ++ /* Check for overflow, which means negative number!*/ ++ if (carry == 0) ++ { ++ /* Number is not of right neg. Invert and add one to correct neg.*/ ++ for(i=0;i<=zlen;i++) ++ *(z+i) = ~(*(z+i)); ++ ++ temp = 1; ++ OctApiLmAdd(&temp,0,z,zlen,z,zlen); ++ ++ *neg = TRUE; ++ return(GENERIC_OK); ++ } ++ ++ /* Result is positive.*/ ++ *neg = FALSE; ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLmCompare. ++| ++| Description: This function compares two numbers (arrays) of equal lengths. ++| Number a is (alen + 1) * 32 bits long; b is (blen + 1) * 32 bits long. The result ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *a UINT32 The array containing the first number. ++| alen USHORT The length of array a, minus 1 (0 - 99). ++| *b UINT32 The array containing the second number. ++| blen USHORT The length of array b, minus 1 (0 - 99). ++| *neg USHORT Result of compare. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmCompare ++UINT32 OctApiLmCompare(UINT32 * a,USHORT alen,UINT32 * bneg,USHORT blen,USHORT * neg) ++{ ++ USHORT i; ++ UINT32 temp; ++ UINT32 carry=1; ++ UINT32 aprim; ++ UINT32 bprim; ++ UINT32 zlen; ++ ++ /* Set zlen to alen or blen (which ever is longer)*/ ++ if (alen < blen) ++ zlen = blen; ++ else ++ zlen = alen; ++ ++ for(i=0;i<=zlen;i++) ++ { ++ if (i <= alen) aprim = *(a+i); else aprim = 0; ++ if (i <= blen) bprim = ~(*(bneg+i)); else bprim = 0xFFFFFFFF; ++ temp = aprim + bprim + carry; ++ ++ /* Calculate carry for next time.*/ ++ if (carry == 0) ++ if (temp < aprim) carry = 1; else carry = 0; ++ else ++ if (temp <= aprim) carry = 1; else carry = 0; ++ } ++ ++ /* Check for overflow, which means negative number!*/ ++ if (carry == 0) ++ { ++ *neg = TRUE; ++ return(GENERIC_OK); ++ } ++ ++ /* Result is positive.*/ ++ *neg = FALSE; ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLmSubtract. ++| ++| Description: This function multiplies 2 numbers, a and b. Number a and ++| b are both (ablen + 1) * 32 bits long. The result is twice as ++| long. If the functions succeeds if returns GENERIC_OK, ++| else GENERIC_ERROR. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *a UINT32 The array containing the first number. ++| *b UINT32 The array containing the second number. ++| ablen USHORT The length of arrays a and b, minus 1 (0 - 99). ++| *z UINT32 The array containing the resulting number. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmMultiply ++UINT32 OctApiLmMultiply(UINT32 * a,UINT32 * b,USHORT ablen,UINT32 * z) ++{ ++ USHORT i,j,k; ++ USHORT nos; ++ UINT32 lownum; ++ UINT32 highnum; ++ USHORT longnumi; ++ USHORT longnumj; ++ USHORT indentw,indentl; ++ ++ ++ /* Caculate number of shorts in a and b.*/ ++ nos = (USHORT)((ablen+1) * 2); ++ ++ /* Clear answer word.*/ ++ for(i=0;i OCTAPI_LM_MAX_OPTIMIZE_MUL) ++ optimizea = FALSE; ++ if(*b > OCTAPI_LM_MAX_OPTIMIZE_MUL) ++ optimizeb = FALSE; ++ ++ if(optimizea == TRUE) ++ { ++ for(l = 0; l < *a; l++) ++ OctApiLmAdd(z, (USHORT)(nos-1), b, ablen, z, (USHORT)(nos-1)); ++ return(GENERIC_OK); ++ } ++ ++ if(optimizeb == TRUE) ++ { ++ for(l = 0; l < *b; l++) ++ OctApiLmAdd(z, (USHORT)(nos-1), a, ablen, z, (USHORT)(nos-1)); ++ return(GENERIC_OK); ++ } ++ } ++ ++ for(i=0;i>16; /* Odd word. Upper part of long.*/ ++ ++ for(j=0;j>16; /* Odd word. Upper part of long.*/ ++ ++ /* Find the word indent of the answer. 0 = no indent. 1 = one word indent.*/ ++ indentw = (USHORT)( j+i ); ++ indentl = (USHORT)( indentw / 2 ); ++ ++ /* Multiply both numbers.*/ ++ product = highnum * lownum; ++ ++ /* After multiplying both numbers, add result to end result.*/ ++ if ((indentw % 2) == 0) /* Even word boundary, addition in one shot!*/ ++ { ++ UINT32 carry=0; ++ UINT32 temp; ++ UINT32 addme; ++ ++ for(k=indentl;k>16; ++ else addme = 0; ++ ++ temp = *(z+k) + addme + carry; ++ ++ /* Calculate carry for next time.*/ ++ if (carry == 0) ++ if (temp < addme) carry = 1; else carry = 0; ++ else ++ if (temp <= addme) carry = 1; else carry = 0; ++ ++ /* Set value.*/ ++ *(z+k) = temp; ++ } ++ ++ /* Carry should always be 0.*/ ++ if (carry == 1) return(GENERIC_ERROR); ++ } ++ } ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLmDivide. ++| ++| Description: This function divides the number n by the number d. The ++| quotient is placed in q and the remainder in r. The arrays ++| n, d, q and r are all of the same length, namely (ndqrlen + 1). ++| If the functions succeeds if returns GENERIC_OK, else ++| GENERIC_ERROR. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *a UINT32 The array containing the first number. ++| *b UINT32 The array containing the second number. ++| ablen USHORT The length of arrays a and b, minus 1 (0 - 99). ++| *z UINT32 The array containing the resulting number. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmDivide ++UINT32 OctApiLmDivide(UINT32 * n,UINT32 * d,UINT32 * q,UINT32 * r,USHORT ndqrlen) ++{ ++ /* Proceedure for division:*/ ++ /* r = n*/ ++ /* q = 0*/ ++ /* shift = initial_denominator_shift (for upper '1's to be in same bit position).*/ ++ /* d <<= shift;*/ ++ /* Start loop:*/ ++ /* compare r and d*/ ++ /* if r > d then*/ ++ /* r -= d;*/ ++ /* write a '1' to bit "shift" of array q.*/ ++ /* end if;*/ ++ /* if shift == 0 then*/ ++ /* return;*/ ++ /* else*/ ++ /* shift--;*/ ++ /* d>>=1;*/ ++ /* goto "Start loop:"*/ ++ /* end if;*/ ++ ++ UINT32 i; ++ UINT32 result; ++ USHORT shift,n_msb,d_msb; ++ USHORT neg; ++ USHORT ConditionFlag = TRUE; ++ ++ /* r = n*/ ++ for(i=0;i<=ndqrlen;i++) ++ *(r+i) = *(n+i); ++ ++ /* q = 0*/ ++ for(i=0;i<=ndqrlen;i++) ++ *(q+i) = 0; ++ ++ /* shift = initial_denominator_shift (for upper '1's to be in same bit position).*/ ++ result = OctApiLmGetMsb(d,ndqrlen,&d_msb); ++ if (result != GENERIC_OK) return(result); ++ ++ result = OctApiLmGetMsb(n,ndqrlen,&n_msb); ++ if (result != GENERIC_OK) return(result); ++ ++ if (d_msb == 0xFFFF) /* Division by 0.*/ ++ return(OCTAPI_LM_DIVISION_BY_ZERO); ++ ++ if (n_msb == 0xFFFF) /* 0/n, returns 0 R 0.*/ ++ return(GENERIC_OK); ++ ++ if (n_msb < d_msb) /* x/y, where x is smaller than y, returns 0 R x.*/ ++ return(GENERIC_OK); ++ ++ shift = (USHORT)( n_msb - d_msb ); ++ ++ /* Shift d to match n highest bit position.*/ ++ result = OctApiLmShiftn(d,ndqrlen,TRUE,shift); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Start loop:*/ ++ while( ConditionFlag == TRUE ) ++ { ++ /* compare r and d*/ ++ result = OctApiLmCompare(r,ndqrlen,d,ndqrlen,&neg); ++ if (result != GENERIC_OK) return(result); ++ ++ if (neg == FALSE) /* Subtraction can be done(do it).*/ ++ { ++ /* r -= d;*/ ++ result = OctApiLmSubtract(r,ndqrlen,d,ndqrlen,r,ndqrlen,&neg); ++ if (result != GENERIC_OK) return(result); ++ ++ /* write a '1' to bit "shift" of array q.*/ ++ *(q+(shift/32)) |= (UINT32)0x1 << (shift%32); ++ } ++ ++ /* if shift == 0 then*/ ++ /* return;*/ ++ if (shift == 0) return(GENERIC_OK); ++ ++ /* shift--;*/ ++ /* d>>=1;*/ ++ /* goto "Start loop:"*/ ++ shift--; ++ OctApiLmShiftRight1(d,ndqrlen); ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: octapi_lm_shifright1. ++| ++| Description: The function is for internal use only. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| N/A. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmShiftRight1 ++UINT32 OctApiLmShiftRight1(UINT32 * a,USHORT alen) ++{ ++ UINT32 i; ++ ++ /* Start with lower long and move up by one long each time,*/ ++ /* shifting each long to the right by one bit. The upper bit*/ ++ /* of the next long will have to be concatenated each time a*/ ++ /* loop is executed. For the last long, leave the highest bit*/ ++ /* intact.*/ ++ for(i=0;i>=1; /* Shift long by one to the right.*/ ++ *(a+i)|=*(a+i+1)<<31; ++ } ++ *(a+alen)>>=1; /* Shift last long, leaving it's highest bit at 0.*/ ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLmShiftn. ++| ++| Description: The function is for internal use only. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| N/A. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmShiftn ++UINT32 OctApiLmShiftn(UINT32 * a,USHORT alen,USHORT shiftleft,USHORT shiftn) ++{ ++ UINT32 i; ++ USHORT long_offset; ++ USHORT bit_offset; ++ ++ long_offset = (USHORT)( shiftn / 32 ); ++ bit_offset = (USHORT)( shiftn % 32 ); ++ ++ if (shiftleft == TRUE) /* Shift left.*/ ++ { ++ for(i=alen;i<=alen;i--) ++ { ++ /* Fill upper bits of long.*/ ++ if (i >= long_offset) ++ *(a+i) = *(a+i-long_offset) << bit_offset; ++ else ++ *(a+i) = 0; ++ ++ /* Fill lower bits of long.*/ ++ if (i > long_offset && bit_offset != 0) ++ *(a+i) |= *(a+i-long_offset-1) >> (32-bit_offset); ++ } ++ } ++ else /* Shift right.*/ ++ { ++ for(i=0;i<=alen;i++) ++ { ++ /* Fill lower bits of long.*/ ++ if ((alen-i) >= long_offset) ++ *(a+i) = *(a+i+long_offset) >> bit_offset; ++ else ++ *(a+i) = 0; ++ ++ /* Fill upper bits of long.*/ ++ if ((alen-i) > long_offset && bit_offset != 0) ++ *(a+i) |= *(a+i+long_offset+1) << (32-bit_offset); ++ ++ } ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLmGetMsb. ++| ++| Description: The function is for internal use only. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| N/A. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLmGetMsb ++UINT32 OctApiLmGetMsb(UINT32 * a,USHORT alen,USHORT * msb_pos) ++{ ++ UINT32 i,j; ++ UINT32 x; ++ ++ for(i=alen;i<=alen;i--) ++ { ++ if (*(a+i) == 0) continue; ++ ++ x = *(a+i); ++ for(j=31;j<=31;j--) ++ { ++ /* Test for bit being '1'.*/ ++ if ((x & 0x80000000) != 0) ++ { ++ *msb_pos=(USHORT)(j+(32*i)); ++ return(GENERIC_OK); ++ } ++ ++ /* Shift bit one bit position, and try again.*/ ++ x<<=1; ++ } ++ } ++ ++ /* MSB not found.*/ ++ *msb_pos = 0xFFFF; ++ ++ return(GENERIC_OK); ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/apilib/llman/octapi_llman.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/llman/octapi_llman.c +--- linux-source-4.19/drivers/dahdi/oct612x/apilib/llman/octapi_llman.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/llman/octapi_llman.c 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,2787 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_llman.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Library used to manage allocation tables and linked lists. The library is ++ made such that only a block of contiguous memory is needed for the ++ management of the linked list/allocation table. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 22 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#include "octapi_llman_private.h" ++#include "apilib/octapi_llman.h" ++#include "apilib/octapi_largmath.h" ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctapiLlmAllocGetSize. ++| ++| Description: This function determines the amount of memory needed to ++| manage the allocation of a fixed amount of resources. ++| The memory is measured in bytes. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| number_of_items UINT32 The number of resources to be allocated. ++| *l_size UINT32 UINT32 The amount of memory needed, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctapiLlmAllocGetSize ++UINT32 OctapiLlmAllocGetSize(UINT32 number_of_items,UINT32 * l_size) ++{ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ ++ *l_size = (sizeof(LLM_ALLOC)) + (number_of_items * sizeof(UINT32)); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctapiLlmAllocInit. ++| ++| Description: This function intializes the LLM_ALLOC structure. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| **l void The memory used by the LLM_ALLOC structure. ++| number_of_items UINT32 The number of resources to be allocated. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctapiLlmAllocInit ++UINT32 OctapiLlmAllocInit(void ** l,UINT32 number_of_items) ++{ ++ LLM_ALLOC* ls; ++ UINT32 i; ++ ++ /* Check the number of items required.*/ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ ++ /* If no memory has been allocated yet:*/ ++ if (*l == NULL) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); ++ ++ /* Build the structure before starting.*/ ++ ls = (LLM_ALLOC *)(*l); ++ ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); ++ ++ ls->number_of_items = number_of_items; ++ ++ /* Linked list links all structures in ascending order.*/ ++ for(i=0;ilinked_list[i] = i+1; ++ } ++ ++ ls->linked_list[number_of_items - 1] = 0xFFFFFFFF; /* Invalid link.*/ ++ ++ /* Next avail is 0.*/ ++ ls->next_avail_num = 0; ++ ++ /* Number of allocated items is null.*/ ++ ls->allocated_items = 0; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctapiLlmAllocInfo. ++| ++| Description: This function returns the number of free and allocated ++| block in the LLMAN list. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_ALLOC structure. ++| *allocated_items UINT32 Number of allocated items. ++| *available_items UINT32 Number of available items. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctapiLlmAllocInfo ++UINT32 OctapiLlmAllocInfo(void * l,UINT32 * allocated_items,UINT32 * available_items) ++{ ++ LLM_ALLOC* ls; ++ ++ /* Build the structure before starting.*/ ++ ls = (LLM_ALLOC *)l; ++ ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); ++ ++ *allocated_items = ls->allocated_items; ++ *available_items = ls->number_of_items - ls->allocated_items; ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctapiLlmAllocInfo. ++| ++| Description: This function allocates the resource indicated by blocknum. ++| If the resource can be allocated then GENERIC_OK is returned. ++| Else an error. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_ALLOC structure. ++| *block_num UINT32 The resource to be allocated. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctapiLlmAllocAlloc ++UINT32 OctapiLlmAllocAlloc(void * l,UINT32 * blocknum) ++{ ++ LLM_ALLOC* ls; ++ UINT32 allocated_block; ++ UINT32* node; ++ ++ /* Build the structure before starting.*/ ++ ls = (LLM_ALLOC *)l; ++ ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); ++ ++ /* Get next available block number.*/ ++ allocated_block = ls->next_avail_num; ++ ++ /* Check if block is invalid.*/ ++ if (allocated_block == 0xFFFFFFFF) ++ { ++ /* Make blocknum NULL.*/ ++ *blocknum = 0xFFFFFFFF; ++ ++ return(OCTAPI_LLM_NO_STRUCTURES_LEFT); ++ } ++ ++ node = &ls->linked_list[allocated_block]; ++ ++ /* Copy next block number.*/ ++ ls->next_avail_num = *node; ++ ++ /* Tag as used the current block number.*/ ++ *node = 0xFFFFFFFE; ++ ++ /* Return proper block number.*/ ++ *blocknum = allocated_block; ++ ++ /* Update block usage number.*/ ++ ls->allocated_items++; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctapiLlmAllocDealloc. ++| ++| Description: This function deallocates the resource indicated by blocknum. ++| If the resource is not already allocated an error is returned. ++| Else GENERIC_OK is returned. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_ALLOC structure. ++| block_num UINT32 The resource to be deallocated. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctapiLlmAllocDealloc ++UINT32 OctapiLlmAllocDealloc(void * l,UINT32 blocknum) ++{ ++ LLM_ALLOC* ls; ++ UINT32* node; ++ ++ /* Build the structure before starting.*/ ++ ls = (LLM_ALLOC *)l; ++ ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); ++ ++ /* Check for null item pointer.*/ ++ if (blocknum == 0xFFFFFFFF) return(GENERIC_OK); ++ ++ /* Check if blocknum is within specified item range.*/ ++ if (blocknum >= ls->number_of_items) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ ++ node = &ls->linked_list[blocknum]; ++ ++ /* Check if block is really used as of now.*/ ++ if (*node != 0xFFFFFFFE) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); ++ ++ /* Add link to list.*/ ++ *node = ls->next_avail_num; ++ ++ /* Point to returned block.*/ ++ ls->next_avail_num = blocknum; ++ ++ /* Update block usage number.*/ ++ ls->allocated_items--; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiTllmAllocGetSize. ++| ++| Description: This function determines the amount of memory needed to ++| manage the allocation of a fixed amount of resources. ++| The memory is measured in bytes. ++| ++| This version is a time manage version of llman. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| number_of_items UINT32 The number of resources to be allocated. ++| *l_size UINT32 UINT32 The amount of memory needed, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiTllmAllocGetSize ++UINT32 OctApiTllmAllocGetSize(UINT32 number_of_items,UINT32 * l_size) ++{ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ ++ *l_size = (sizeof(TLLM_ALLOC)) + (number_of_items * sizeof(TLLM_ALLOC_NODE)); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiTllmAllocInit. ++| ++| Description: This function intializes the TLLM_ALLOC structure. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| **l void The memory used by the LLM_ALLOC structure. ++| number_of_items UINT32 The number of resources to be allocated. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiTllmAllocInit ++UINT32 OctApiTllmAllocInit(void ** l,UINT32 number_of_items) ++{ ++ TLLM_ALLOC* ls; ++ UINT32 i; ++ ++ /* Check the number of items required.*/ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ ++ /* If no memory has been allocated yet.*/ ++ if (*l == NULL) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); ++ ++ /* Build the structure before starting.*/ ++ ls = (TLLM_ALLOC *)(*l); ++ ls->linked_list = (TLLM_ALLOC_NODE *)((BYTE *)ls + sizeof(TLLM_ALLOC)); ++ ++ ls->number_of_items = number_of_items; ++ ++ /* Linked list links all structures in ascending order.*/ ++ for(i=0;ilinked_list[i].value = i+1; ++ } ++ ++ ls->linked_list[number_of_items - 1].value = 0xFFFFFFFF; /* Invalid link.*/ ++ ++ /* Next avail is 0.*/ ++ ls->next_avail_num = 0; ++ ++ /* Number of allocated items is null.*/ ++ ls->allocated_items = 0; ++ ++ /* Set the number of timeout entry.*/ ++ ls->number_of_timeout = 0; ++ ++ /* Next timeout is 0.*/ ++ ls->next_timeout_num = 0xFFFFFFFF; ++ ls->last_timeout_num = 0xFFFFFFFF; ++ ++ /* Set the known time to 0.*/ ++ ls->last_known_time[ 0 ] = 0; ++ ls->last_known_time[ 1 ] = 0; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiTllmAllocInfo. ++| ++| Description: This function returns the number of free and allocated ++| block in the TLLMAN list. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_ALLOC structure. ++| *allocated_items UINT32 Number of allocated items. ++| *available_items UINT32 Number of available items. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiTllmAllocInfo ++UINT32 OctApiTllmAllocInfo(void * l,UINT32 * allocated_items,UINT32 * available_items) ++{ ++ TLLM_ALLOC* ls; ++ ++ /* Build the structure before starting.*/ ++ ls = (TLLM_ALLOC *)l; ++ *allocated_items = ls->allocated_items; ++ *available_items = ls->number_of_items - ls->allocated_items; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiTllmAllocAlloc. ++| ++| Description: This function allocates the resource indicated by blocknum. ++| If the resource can be allocated then GENERIC_OK is returned. ++| Else an error. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_ALLOC structure. ++| *block_num UINT32 The resource to be allocated. ++| *current_time UINT32 ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiTllmAllocAlloc ++UINT32 OctApiTllmAllocAlloc(void * l,UINT32 * blocknum, UINT32 *current_time) ++{ ++ TLLM_ALLOC* ls; ++ UINT32 allocated_block; ++ TLLM_ALLOC_NODE* node; ++ ++ /* Build the structure before starting.*/ ++ ls = (TLLM_ALLOC *)l; ++ ls->linked_list = (TLLM_ALLOC_NODE *)((BYTE *)ls + sizeof(TLLM_ALLOC)); ++ ++ if ( ls->allocated_items == ls->number_of_items && ++ ls->next_timeout_num != 0xFFFFFFFF ) ++ { ++ UINT32 l_ulResult; ++ l_ulResult = OctApiTllmCheckTimeoutList( ls, current_time ); ++ if ( l_ulResult != GENERIC_OK ) ++ return l_ulResult; ++ } ++ ++ /* Get next available block number.*/ ++ allocated_block = ls->next_avail_num; ++ ++ /* Check if block is invalid.*/ ++ if (allocated_block == 0xFFFFFFFF) ++ { ++ /* Make blocknum NULL.*/ ++ *blocknum = 0xFFFFFFFF; ++ ++ return(OCTAPI_LLM_NO_STRUCTURES_LEFT); ++ } ++ ++ node = &ls->linked_list[allocated_block]; ++ ++ /* Copy next block number.*/ ++ ls->next_avail_num = node->value; ++ ++ /* Tag as used the current block number.*/ ++ node->value = 0xFFFFFFFE; ++ ++ /* Return proper block number.*/ ++ *blocknum = allocated_block; ++ ++ /* Update block usage number.*/ ++ ls->allocated_items++; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiTllmAllocDealloc. ++| ++| Description: This function deallocates the resource indicated by blocknum. ++| If the resource is not already allocated an error is returned. ++| Else GENERIC_OK is returned. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_ALLOC structure. ++| block_num UINT32 The resource to be deallocated. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiTllmAllocDealloc ++UINT32 OctApiTllmAllocDealloc(void * l,UINT32 blocknum, UINT32 timeout_value, UINT32 current_time[2]) ++{ ++ TLLM_ALLOC* ls; ++ TLLM_ALLOC_NODE* node; ++ UINT32 l_ulResult; ++ ++ /* Build the structure before starting.*/ ++ ls = (TLLM_ALLOC *)l; ++ ls->linked_list = (TLLM_ALLOC_NODE *)((BYTE *)ls + sizeof(TLLM_ALLOC)); ++ ++ /* Check for null item pointer.*/ ++ if (blocknum == 0xFFFFFFFF) return(GENERIC_OK); ++ ++ /* Check if blocknum is within specified item range.*/ ++ if (blocknum >= ls->number_of_items) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ ++ if ( ls->next_timeout_num != 0xFFFFFFFF ) ++ { ++ l_ulResult = OctApiTllmCheckTimeoutList( ls, current_time ); ++ if ( l_ulResult != GENERIC_OK ) ++ return l_ulResult; ++ } ++ ++ node = &ls->linked_list[blocknum]; ++ ++ /* Check if block is really used as of now.*/ ++ if (node->value != 0xFFFFFFFE) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); ++ ++ /* Add link to timeout list.*/ ++ if ( ls->last_timeout_num != 0xFFFFFFFF ) ++ { ++ TLLM_ALLOC_NODE* last_node; ++ ++ /* insert the node at the end of the list.*/ ++ node->value = 0xFFFFFFFF; ++ last_node = &ls->linked_list[ ls->last_timeout_num ]; ++ last_node->value = blocknum; ++ } ++ else ++ { ++ /* The node is alone in the list.*/ ++ node->value = 0xFFFFFFFF; ++ ls->next_timeout_num = blocknum; ++ } ++ ++ ls->last_timeout_num = blocknum; ++ ls->number_of_timeout++; ++ ++ /* Set the timeout time of the node.*/ ++ l_ulResult = OctApiLmAdd( current_time, 1, &timeout_value, 0, node->timeout, 1 ); ++ if (l_ulResult != GENERIC_OK) ++ return(l_ulResult); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiTllmCheckTimeoutList. ++| ++| Description: This function will verify if the timeout time ++| of all the node present in the timeout list are bigger ++| then the current time. If so the node will be returned ++| ot the free node list. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *ls TLLM_ALLOC The memory used by the TLLM_ALLOC structure. ++| current_time UINT32[2] The current time in msec. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiTllmCheckTimeoutList ++UINT32 OctApiTllmCheckTimeoutList(TLLM_ALLOC *ls, UINT32 current_time[2]) ++{ ++ UINT32 result; ++ UINT32 fConditionFlag = TRUE; ++ ++ /* Free-up any pending memory before trying the allocation:*/ ++ if ((ls->last_known_time[0] != current_time[0] || ++ ls->last_known_time[1] != current_time[1]) && ++ (current_time[1] != 0 || current_time[0] != 0)) /* Time has changed.*/ ++ { ++ TLLM_ALLOC_NODE *pcurrent_node; ++ UINT32 current_num; ++ USHORT neg; ++ ++ /* Remember time for next time!*/ ++ ls->last_known_time[0] = current_time[0]; ++ ls->last_known_time[1] = current_time[1]; ++ ++ ++ while ( fConditionFlag == TRUE ) ++ { ++ /* Get a node from the timeout list.*/ ++ pcurrent_node = &ls->linked_list[ ls->next_timeout_num ]; ++ current_num = ls->next_timeout_num; ++ ++ /* Check if first node has timeout.*/ ++ result = OctApiLmCompare(current_time,1,pcurrent_node->timeout ,1,&neg); ++ if (result != GENERIC_OK) return(result); ++ ++ /* if the timeout tiem was exceeded, set the block as free.*/ ++ if ( neg == FALSE ) ++ { ++ /* set the next node pointer.*/ ++ ls->next_timeout_num = pcurrent_node->value; ++ ls->number_of_timeout--; ++ ++ /* reset the last pointer of the timeout list.*/ ++ if ( ls->number_of_timeout == 0 ) ++ ls->last_timeout_num = 0xFFFFFFFF; ++ ++ /* return the node the free list.*/ ++ pcurrent_node->value = ls->next_avail_num; ++ ls->next_avail_num = current_num; ++ ls->allocated_items--; ++ } ++ else /* node not in timeout */ ++ { ++ fConditionFlag = FALSE; ++ break; ++ } ++ ++ if ( ls->next_timeout_num == 0xFFFFFFFF ) ++ { ++ fConditionFlag = FALSE; ++ break; /* end of timeout list.*/ ++ } ++ } ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++/**************************************** llm_alloc section **********************************************/ ++ ++ ++ ++ ++ ++ ++ ++/**************************************** llm_list section **********************************************/ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListGetSize ++| ++| Description: This function determines the amount of memory needed by ++| the LLM_LIST structure to manage the allocation of ++| number_of_items number of resources. The memory is ++| measured in bytes. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| number_of_items UINT32 The number of resources to be allocated ++| amongst all linked-lists. ++| number_of_lists UINT32 The maximum number of linked-lists that ++| can be allocated. ++| *l_size UINT32 UINT32 The amount of memory needed, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListGetSize ++UINT32 OctApiLlmListGetSize(UINT32 number_of_items,UINT32 number_of_lists,UINT32 user_info_size,UINT32 * l_size) ++{ ++ UINT32 head_alloc_size; ++ UINT32 result; ++ UINT32 user_info_size_roundup; ++ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ if (number_of_lists == 0) return(GENERIC_BAD_PARAM); ++ if (user_info_size == 0) return(GENERIC_BAD_PARAM); ++ ++ user_info_size_roundup = ((user_info_size + 3) / 4) * 4; ++ ++ result = OctapiLlmAllocGetSize(number_of_lists,&head_alloc_size); ++ if(result != GENERIC_OK) return(result); ++ ++ *l_size = sizeof(LLM_LIST) + (number_of_lists * sizeof(LLM_LIST_HEAD)) + head_alloc_size + (number_of_items * (sizeof(LLM_LIST_ITEM) + user_info_size_roundup - 4)); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiLlmListGetItemPointer ++LLM_LIST_ITEM * OctApiLlmListGetItemPointer(LLM_LIST * ls, UINT32 item_number) ++{ ++ return (LLM_LIST_ITEM *) (((BYTE *)ls->li) + (ls->item_size * item_number)) ; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListInit. ++| ++| Description: This function intializes the LLM_TALLOC structure. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| number_of_items UINT32 The number of resources to be allocated ++| amongst all linked-lists. ++| number_of_lists UINT32 The maximum number of linked-lists that ++| can be allocated. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListInit ++UINT32 OctApiLlmListInit(void ** l,UINT32 number_of_items,UINT32 number_of_lists,UINT32 user_info_size) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_ITEM* item; ++ UINT32 i; ++ UINT32 head_alloc_size; ++ UINT32 result; ++ UINT32 user_info_size_roundup; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ ++ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ if (number_of_lists == 0) return(GENERIC_BAD_PARAM); ++ if (user_info_size == 0) return(GENERIC_BAD_PARAM); ++ ++ user_info_size_roundup = ((user_info_size + 3) / 4) * 4; ++ ++ /* Get the size of the Alloc structure used to manage head of list structures.*/ ++ result = OctapiLlmAllocGetSize(number_of_lists,&head_alloc_size); ++ if(result != GENERIC_OK) return(result); ++ ++ if (*l == NULL) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)(*l); ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ /* Initialize parameters in the structure.*/ ++ ls->head_alloc_size = head_alloc_size; ++ ls->user_info_bytes = user_info_size; ++ ls->user_info_size = user_info_size_roundup; ++ ls->total_items = number_of_items; ++ ls->assigned_items = 0; ++ ls->total_lists = number_of_lists; ++ ls->assigned_lists = 0; ++ ls->next_empty_item = 0; ++ ls->item_size = sizeof(LLM_LIST_ITEM) + user_info_size_roundup - 4; ++ ++ /* Complete the build!*/ ++ ls = (LLM_LIST *)(*l); ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ /* Initialize the head of queue Alloc structure.*/ ++ result = OctapiLlmAllocInit(&(ls->list_head_alloc),number_of_lists); ++ if(result != GENERIC_OK) return(result); ++ ++ /* Initialize the linked list of the items:*/ ++ for(i=0; ili + ls->item_size * i); ++ ++ if (i == (number_of_items - 1)) ++ item->forward_link = 0xFFFFFFFF; ++ else ++ item->forward_link = i + 1; ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListInfo. ++| ++| Description: This function returns the status of the LLM_LIST structure. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| *allocated_lists UINT32 The number of linked_lists allocated. ++| *free_lists UINT32 The number of linked_lists still free. ++| *allocated_items UINT32 The number of items allocated to lists. ++| *free_items UINT32 The number of items still free. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListInfo ++UINT32 OctApiLlmListInfo(void * l,UINT32 * allocated_lists,UINT32 * allocated_items, ++ UINT32 * free_lists,UINT32 * free_items) ++{ ++ LLM_LIST* ls; ++ BYTE* lsbyte; ++ UINT32 total_lists; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ *allocated_items = ls->assigned_items; ++ *free_items = ls->total_items - ls->assigned_items; ++ ++ *allocated_lists = ls->assigned_lists; ++ *free_lists = ls->total_lists - ls->assigned_lists; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListCreate. ++| ++| Description: This function creates a linked list. The target which is ++| allocated the newly created list can request additions ++| or removals from the list later on. To target identifies ++| its list with the returned list handle. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| *list_handle UINT32 The handle to the new list, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListCreate ++UINT32 OctApiLlmListCreate(void * l,UINT32 * list_handle) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ UINT32 blocknum; ++ UINT32 total_lists; ++ UINT32 result; ++ BYTE* lsbyte; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ /* Get a list using the list head alloc structure.*/ ++ result = OctapiLlmAllocAlloc(ls->list_head_alloc, &blocknum); ++ if (result != GENERIC_OK) return(result); ++ ++ /* The handle is the block number.*/ ++ *list_handle = blocknum; ++ ++ /* Initialize the list head structure.*/ ++ lh = &ls->lh[blocknum]; ++ lh->list_length = 0; ++ lh->head_pointer = 0xFFFFFFFF; ++ lh->tail_pointer = 0xFFFFFFFF; ++ lh->cache_item_number = 0xFFFFFFFF; ++ lh->cache_item_pointer = 0xFFFFFFFF; ++ ++ ls->assigned_lists++; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListDelete. ++| ++| Description: This function deletes the linked list indicated by the ++| handle list_handle. Any items which are still allocated ++| to the list are first deallocated. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| *list_handle UINT32 The handle to the list. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListDelete ++UINT32 OctApiLlmListDelete(void * l,UINT32 list_handle) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ UINT32 total_lists; ++ UINT32 result; ++ BYTE* lsbyte; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ if (ls->lh[list_handle].list_length == 0xFFFFFFFF) return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ ++ /* Release internal list header handle...*/ ++ result = OctapiLlmAllocDealloc(ls->list_head_alloc,list_handle); ++ if (result != GENERIC_OK) return(result); ++ ++ lh = &ls->lh[list_handle]; ++ ++ /* Deallocate all items in the list!*/ ++ if (lh->list_length != 0) ++ { ++ LLM_LIST_ITEM * item; ++ ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * lh->tail_pointer); ++ ++ /* Release the items using only the links.*/ ++ item->forward_link = ls->next_empty_item; ++ ls->next_empty_item = lh->head_pointer; ++ ++ /* Remove items from item counter.*/ ++ ls->assigned_items -= lh->list_length; ++ } ++ ++ lh->list_length = 0xFFFFFFFF; ++ lh->head_pointer = 0xFFFFFFFF; ++ lh->tail_pointer = 0xFFFFFFFF; ++ lh->cache_item_number = 0xFFFFFFFF; ++ lh->cache_item_pointer = 0xFFFFFFFF; ++ ++ ls->assigned_lists--; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListLength. ++| ++| Description: This function returns the number of items allocated to the ++| list indicated by the handle list_handle. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| list_handle UINT32 The handle to the list. ++| *number_of_items UINT32 The number of items in the list, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListLength ++UINT32 OctApiLlmListLength(void * l,UINT32 list_handle, UINT32 * number_of_items_in_list) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ if (lh->list_length == 0xFFFFFFFF) return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ ++ *number_of_items_in_list = lh->list_length; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListItemData ++| ++| Description: This function returns a pointer to the user data associated ++| with an item. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| list_handle UINT32 The handle to the list. ++| item_number UINT32 The number of the list node in question. ++| **item_data_pnt void The pointer to the user data, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListItemData ++UINT32 OctApiLlmListItemData(void * l,UINT32 list_handle,UINT32 item_number,void ** item_data_pnt) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ LLM_LIST_ITEM* item; ++ UINT32 cur_list_pnt; ++ UINT32 cur_list_num; ++ UINT32 total_lists; ++ UINT32 list_length; ++ BYTE* lsbyte; ++ UINT32 fConditionFlag = TRUE; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ list_length = lh->list_length; ++ ++ *item_data_pnt = NULL; ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ if (list_length == 0xFFFFFFFF) return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ if (list_length <= item_number) return(OCTAPI_LLM_ELEMENT_NOT_FOUND); ++ ++ /* Determine where the search will start.*/ ++ if (list_length == (item_number + 1)) /* Last item in list:*/ ++ { ++ cur_list_pnt = lh->tail_pointer; ++ cur_list_num = item_number; ++ } ++ else if (lh->cache_item_number <= item_number) /* Start at cache:*/ ++ { ++ cur_list_pnt = lh->cache_item_pointer; ++ cur_list_num = lh->cache_item_number; ++ } ++ else /* Start at beginning:*/ ++ { ++ cur_list_pnt = lh->head_pointer; ++ cur_list_num = 0; ++ } ++ ++ /* Start search from cur_list_pnt and cur_list_num.*/ ++ while ( fConditionFlag == TRUE ) ++ { ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ ++ if (cur_list_num == item_number) /* Item number found.*/ ++ { ++ /* Write new cache entry.*/ ++ lh->cache_item_pointer = cur_list_pnt; ++ lh->cache_item_number = cur_list_num; ++ ++ /* Get item info.*/ ++ *item_data_pnt = (void *)item->user_info; ++ ++ return(GENERIC_OK); ++ } ++ else if(item->forward_link == 0xFFFFFFFF) /* End of list found?!?*/ ++ { ++ return(OCTAPI_LLM_INTERNAL_ERROR0); ++ } ++ else /* Item was not found, but continue searching.*/ ++ { ++ cur_list_pnt = item->forward_link; ++ } ++ ++ cur_list_num++; ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListInsertItem. ++| ++| Description: This function allocates a node to the linked list specified ++| by the handle list_handle. The position of the new item ++| can be specified. A position of 0xFFFFFFFF means append to the ++| list( use the OCTAPI_LLM_LIST_APPEND define for clarity); ++| a position of 0 mean insert at the begining of the list. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| *list_handle UINT32 The handle to the list. ++| **item_data void Address of the user data space for this item. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListInsertItem ++UINT32 OctApiLlmListInsertItem(void * l,UINT32 list_handle,UINT32 item_number,void ** item_data_pnt) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ LLM_LIST_ITEM* free_item; ++ UINT32 free_item_pnt; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ UINT32 fConditionFlag = TRUE; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ ++ *item_data_pnt = NULL; ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ if (lh->list_length == 0xFFFFFFFF) return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ if (lh->list_length < item_number && item_number != 0xFFFFFFFF) ++ return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ if (ls->next_empty_item == 0xFFFFFFFF) return(OCTAPI_LLM_NO_STRUCTURES_LEFT); ++ ++ /* Get a free item from the free item list!*/ ++ free_item_pnt = ls->next_empty_item; ++ free_item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * free_item_pnt); ++ ls->next_empty_item = free_item->forward_link; ++ ++ if (item_number == 0xFFFFFFFF) ++ item_number = lh->list_length; ++ ++ if (lh->list_length == 0) /* First item and only item:*/ ++ { ++ free_item->forward_link = 0xFFFFFFFF; ++ lh->tail_pointer = free_item_pnt; ++ lh->head_pointer = free_item_pnt; ++ } ++ else if (item_number == 0) /* First item and but list not empty:*/ ++ { ++ free_item->forward_link = lh->head_pointer; ++ lh->head_pointer = free_item_pnt; ++ } ++ else if (item_number == lh->list_length) /* Append:*/ ++ { ++ LLM_LIST_ITEM * last_item; ++ last_item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * lh->tail_pointer); ++ ++ last_item->forward_link = free_item_pnt; ++ free_item->forward_link = 0xFFFFFFFF; ++ lh->tail_pointer = free_item_pnt; ++ } ++ else /* Insert:*/ ++ { ++ LLM_LIST_ITEM * last_item = NULL; ++ LLM_LIST_ITEM * item; ++ UINT32 last_list_pnt; ++ UINT32 cur_list_pnt; ++ UINT32 cur_list_num; ++ ++ if (lh->cache_item_number < item_number) /* Start at cache:*/ ++ { ++ cur_list_pnt = lh->cache_item_pointer; ++ cur_list_num = lh->cache_item_number; ++ } ++ else /* Start at beginning:*/ ++ { ++ cur_list_pnt = lh->head_pointer; ++ cur_list_num = 0; ++ } ++ ++ last_list_pnt = 0xFFFFFFFF; ++ ++ /* Start search from cur_list_pnt and cur_list_num.*/ ++ while ( fConditionFlag == TRUE ) ++ { ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ ++ if (cur_list_num == item_number) /* Item number found.*/ ++ { ++ if (last_list_pnt == 0xFFFFFFFF) return(OCTAPI_LLM_INTERNAL_ERROR1); ++ ++ free_item->forward_link = cur_list_pnt; ++ last_item->forward_link = free_item_pnt; ++ ++ fConditionFlag = FALSE; ++ break; ++ } ++ else if (item->forward_link == 0xFFFFFFFF) /* End of list found?!?*/ ++ { ++ return(OCTAPI_LLM_INTERNAL_ERROR0); ++ } ++ else /* Item was not found, but continue searching.*/ ++ { ++ last_item = item; ++ last_list_pnt = cur_list_pnt; ++ cur_list_pnt = item->forward_link; ++ } ++ ++ cur_list_num++; ++ } ++ } ++ ++ /* Increase the list length.*/ ++ lh->list_length++; ++ ls->assigned_items++; ++ *item_data_pnt = (void *)free_item->user_info; ++ ++ /* Write new cache entry.*/ ++ lh->cache_item_pointer = free_item_pnt; ++ lh->cache_item_number = item_number; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListCreateFull. ++| ++| Description: This function allocates the desired number of nodes to ++| the linked list specified by the handle list_handle. ++| The position of the new item can be specified. A ++| position of 0xFFFFFFFF means append to the list (use the ++| OCTAPI_LLM_LIST_APPEND define for clarity); a position ++| of 0 means insert at the begining of the list. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| *list_handle UINT32 The handle to the list. ++| **item_data void Address of the user data space for this item. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListCreateFull ++UINT32 OctApiLlmListCreateFull(void* l, UINT32 list_length, UINT32* plist_handle) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ LLM_LIST_ITEM* free_item; ++ LLM_LIST_ITEM* last_item = NULL; ++ UINT32 free_item_pnt = 0xFFFFFFFF; ++ UINT32 total_lists; ++ UINT32 list_handle; ++ UINT32 list_length_m1; ++ UINT32 next_empty_item; ++ UINT32 result; ++ UINT32 i; ++ BYTE* lsbyte; ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Build the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Make sure another list can be created.*/ ++ if (ls->assigned_lists == ls->total_lists) ++ return(OCTAPI_LLM_ELEMENT_ALREADY_ASSIGNED); ++ ++ /* Make sure there are enough free nodes to fill the new list.*/ ++ if (list_length > (ls->total_items - ls->assigned_items)) ++ return(OCTAPI_LLM_ELEMENT_ALREADY_ASSIGNED); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Create list (i.e. get a list using the list head alloc structure.*/ ++ result = OctapiLlmAllocAlloc(ls->list_head_alloc, &list_handle); ++ if (result != GENERIC_OK) return(result); ++ ++ /* Initialize the list head structure.*/ ++ lh = &ls->lh[list_handle]; ++ lh->list_length = 0; ++ lh->head_pointer = 0xFFFFFFFF; ++ lh->tail_pointer = 0xFFFFFFFF; ++ lh->cache_item_number = 0xFFFFFFFF; ++ lh->cache_item_pointer = 0xFFFFFFFF; ++ ++ ls->assigned_lists++; ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Add the number of requested nodes to the list.*/ ++ lh = &ls->lh[list_handle]; ++ list_length_m1 = list_length - 1; ++ next_empty_item = ls->next_empty_item; ++ ++ for (i=0; ili + ls->item_size * free_item_pnt); ++ next_empty_item = free_item->forward_link; ++ ++ /* Branch according to whether the node is the first in list, last, or in ++ the middle.*/ ++ if (i == 0) ++ { ++ /* First item.*/ ++ free_item->forward_link = 0xFFFFFFFF; ++ lh->head_pointer = free_item_pnt; ++ lh->tail_pointer = free_item_pnt; ++ } ++ else if (i == list_length_m1) ++ { ++ /* Last item.*/ ++ last_item->forward_link = free_item_pnt; ++ free_item->forward_link = 0xFFFFFFFF; ++ lh->tail_pointer = free_item_pnt; ++ } ++ else ++ { ++ /* Node somewhere in the middle.*/ ++ last_item->forward_link = free_item_pnt; ++ } ++ ++ /* Store pointer to free item as pointer to last item (for next iteration).*/ ++ last_item = free_item; ++ } ++ ++ /* Store new value of next_empty_item.*/ ++ ls->next_empty_item = next_empty_item; ++ ++ /* Write new cache entry.*/ ++ lh->cache_item_pointer = free_item_pnt; ++ lh->cache_item_number = list_length_m1; ++ ++ /* Set the list length.*/ ++ lh->list_length = list_length; ++ ls->assigned_items += list_length; ++ ++ /* Return pointer to new list.*/ ++ *plist_handle = list_handle; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListAppendItems. ++| ++| Description: This function allocates the desired number of nodes to ++| the linked list specified by the handle list_handle. ++| The position of the new item can be specified. A ++| position of 0xFFFFFFFF means append to the list (use the ++| OCTAPI_LLM_LIST_APPEND define for clarity); a position ++| of 0 means insert at the begining of the list. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| *list_handle UINT32 The handle to the list. ++| **item_data void Address of the user data space for this item. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListAppendItems ++UINT32 OctApiLlmListAppendItems(void* l, UINT32 list_handle, UINT32 num_items) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ LLM_LIST_ITEM* item_list; ++ LLM_LIST_ITEM* curr_item = NULL; ++ LLM_LIST_ITEM* free_item; ++ UINT32 curr_item_pnt = 0xFFFFFFFF; ++ UINT32 total_lists; ++ UINT32 next_empty_item; ++ UINT32 item_size; ++ UINT32 i; ++ BYTE* lsbyte; ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Build the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Make sure list handle is valid.*/ ++ if (list_handle >= ls->total_lists) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ ++ /* Make sure there is at least one item.*/ ++ if (num_items == 0) ++ return(OCTAPI_LLM_INVALID_PARAMETER); ++ ++ /* Make sure there are enough free nodes.*/ ++ if (num_items > (ls->total_items - ls->assigned_items)) ++ return(OCTAPI_LLM_NO_STRUCTURES_LEFT); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Get pointer to list structure.*/ ++ lh = &ls->lh[list_handle]; ++ if (lh->list_length == 0xFFFFFFFF) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Add the number of requested nodes to the list.*/ ++ item_list = ls->li; ++ item_size = ls->item_size; ++ next_empty_item = ls->next_empty_item; ++ ++ for (i=0; ihead_pointer == 0xFFFFFFFF) ++ { ++ /* Current and next items are one and the same!*/ ++ curr_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * next_empty_item); ++ ++ /* Set new head and tail pointers.*/ ++ lh->head_pointer = next_empty_item; ++ lh->tail_pointer = next_empty_item; ++ ++ /* Update current item pnt.*/ ++ curr_item_pnt = next_empty_item; ++ ++ /* Update next item.*/ ++ next_empty_item = curr_item->forward_link; ++ ++ /* Set first item to be only item in list.*/ ++ curr_item->forward_link = 0xFFFFFFFF; ++ } ++ else ++ { ++ /* Get a free item from the free item list!*/ ++ curr_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * lh->tail_pointer); ++ free_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * next_empty_item); ++ ++ /* Have current item point to next empty item.*/ ++ curr_item->forward_link = next_empty_item; ++ ++ /* Update current item pnt.*/ ++ curr_item_pnt = next_empty_item; ++ ++ /* Update next_empty_item.*/ ++ next_empty_item = free_item->forward_link; ++ ++ /* Update pointers to current item and free item.*/ ++ curr_item = free_item; ++ } ++ } ++ else ++ { ++ /* Update pointers to current item and free item.*/ ++ free_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * next_empty_item); ++ ++ /* Have current item point to next empty item.*/ ++ curr_item->forward_link = next_empty_item; ++ ++ /* Update current item pnt.*/ ++ curr_item_pnt = next_empty_item; ++ ++ /* Update next_empty_item.*/ ++ next_empty_item = free_item->forward_link; ++ ++ /* Update pointers to current item and free item.*/ ++ curr_item = free_item; ++ } ++ } ++ ++ /* Terminate list.*/ ++ if ( curr_item != NULL ) ++ curr_item->forward_link = 0xFFFFFFFF; ++ ++ /* Update llman structure variables.*/ ++ ls->next_empty_item = next_empty_item; ++ ls->assigned_items += num_items; ++ ++ /* Update list variables.*/ ++ lh->list_length += num_items; ++ lh->cache_item_pointer = curr_item_pnt; ++ lh->cache_item_number = lh->list_length - 1; ++ lh->tail_pointer = curr_item_pnt; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListAppendAndSetItems. ++| ++| Description: ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListAppendAndSetItems ++UINT32 OctApiLlmListAppendAndSetItems(void* l, UINT32 list_handle, UINT32 num_items, void* data_list) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ LLM_LIST_ITEM* item_list; ++ LLM_LIST_ITEM* curr_item = NULL; ++ LLM_LIST_ITEM* free_item; ++ UINT32 curr_item_pnt = 0xFFFFFFFF; ++ UINT32 total_lists; ++ UINT32 next_empty_item; ++ UINT32 user_info_bytes; ++ UINT32 item_size; ++ UINT32 i; ++ BYTE* lsbyte; ++ void* data_item; ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Build the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Make sure list handle is valid.*/ ++ if (list_handle >= ls->total_lists) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ ++ /* Make sure there is at least one item.*/ ++ if (num_items == 0) ++ return(OCTAPI_LLM_INVALID_PARAMETER); ++ ++ /* Make sure there are enough free nodes.*/ ++ if (num_items > (ls->total_items - ls->assigned_items)) ++ return(OCTAPI_LLM_NO_STRUCTURES_LEFT); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Get pointer to list structure.*/ ++ lh = &ls->lh[list_handle]; ++ if (lh->list_length == 0xFFFFFFFF) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Add the number of requested nodes to the list.*/ ++ item_list = ls->li; ++ user_info_bytes = ls->user_info_bytes; ++ item_size = ls->item_size; ++ next_empty_item = ls->next_empty_item; ++ data_item = data_list; ++ ++ for (i=0; ihead_pointer == 0xFFFFFFFF) ++ { ++ /* Current and next items are one and the same!*/ ++ curr_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * next_empty_item); ++ ++ /* Set new head and tail pointers.*/ ++ lh->head_pointer = next_empty_item; ++ lh->tail_pointer = next_empty_item; ++ ++ /* Update current item pnt.*/ ++ curr_item_pnt = next_empty_item; ++ ++ /* Update next item.*/ ++ next_empty_item = curr_item->forward_link; ++ ++ /* Set first item to be only item in list.*/ ++ curr_item->forward_link = 0xFFFFFFFF; ++ } ++ else ++ { ++ /* Get a free item from the free item list!*/ ++ curr_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * lh->tail_pointer); ++ free_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * next_empty_item); ++ ++ /* Have current item point to next empty item.*/ ++ curr_item->forward_link = next_empty_item; ++ ++ /* Update current item pnt.*/ ++ curr_item_pnt = next_empty_item; ++ ++ /* Update next_empty_item.*/ ++ next_empty_item = free_item->forward_link; ++ ++ /* Update pointers to current item and free item.*/ ++ curr_item = free_item; ++ } ++ } ++ else ++ { ++ /* Update pointers to current item and free item.*/ ++ free_item = (LLM_LIST_ITEM *)((BYTE *)item_list + item_size * next_empty_item); ++ ++ /* Have current item point to next empty item.*/ ++ curr_item->forward_link = next_empty_item; ++ ++ /* Update current item pnt.*/ ++ curr_item_pnt = next_empty_item; ++ ++ /* Update next_empty_item.*/ ++ next_empty_item = free_item->forward_link; ++ ++ /* Update pointers to current item and free item.*/ ++ curr_item = free_item; ++ } ++ ++ /* Copy data to new item.*/ ++ OctApiLlmMemCpy(curr_item->user_info, data_item, user_info_bytes); ++ ++ /* Update data_item pointer for next iteration (item).*/ ++ data_item = (void *)((BYTE *)data_item + user_info_bytes); ++ } ++ ++ ++ /* Terminate list.*/ ++ if ( curr_item != NULL ) ++ curr_item->forward_link = 0xFFFFFFFF; ++ ++ /* Update llman structure variables.*/ ++ ls->next_empty_item = next_empty_item; ++ ls->assigned_items += num_items; ++ ++ /* Update list variables.*/ ++ lh->list_length += num_items; ++ lh->cache_item_pointer = curr_item_pnt; ++ lh->cache_item_number = lh->list_length - 1; ++ lh->tail_pointer = curr_item_pnt; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListSetItems. ++| ++| Description: This function takes a start entry (0 to length - 1), ++| a pointer to a list of data (each item of list is the ++| size of one data unit, specified at init), and the ++| length of the data list. From this, the data will be ++| copied from the data list to the linked list, from ++| entry start_entry to (start_entry + data_length - 1). ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListSetItems ++UINT32 OctApiLlmListSetItems(void* l, UINT32 list_handle, UINT32 start_item, UINT32 data_length, void* pdata_list) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ LLM_LIST_ITEM* item = NULL; ++ UINT32 total_lists; ++ UINT32 item_pnt = 0xFFFFFFFF; ++ UINT32 i, j; ++ BYTE* lsbyte; ++ void* pdata_item = NULL; ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Build the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Make sure list handle is valid.*/ ++ if (list_handle >= ls->total_lists) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ lh = &ls->lh[list_handle]; ++ if (lh->list_length == 0xFFFFFFFF) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ ++ /* Make sure the start_entry is within limits.*/ ++ if (start_item >= lh->list_length) ++ return(OCTAPI_LLM_INVALID_PARAMETER); ++ ++ /* Make sure the end_entry is within limits.*/ ++ lh = &ls->lh[list_handle]; ++ if ((start_item + data_length) > lh->list_length) ++ return(OCTAPI_LLM_INVALID_PARAMETER); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Set the data of each node.*/ ++ for (i=0; icache_item_number + 1)) ++ { ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * lh->cache_item_pointer); ++ item_pnt = item->forward_link; ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * item_pnt); ++ } ++ else ++ { ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * lh->head_pointer); ++ item_pnt = lh->head_pointer; ++ for (j=0; jforward_link; ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * item_pnt); ++ } ++ } ++ ++ pdata_item = (void *)((BYTE *)pdata_list + (i * ls->user_info_bytes)); ++ } ++ else ++ { ++ item_pnt = item->forward_link; ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * item_pnt); ++ ++ pdata_item = (void *)((BYTE *)pdata_item + ls->user_info_bytes); ++ } ++ ++ /* Set the value of the item's user data.*/ ++ OctApiLlmMemCpy(item->user_info, pdata_item, ls->user_info_bytes); ++ } ++ ++ /* Write new cache entry.*/ ++ lh->cache_item_pointer = item_pnt; ++ lh->cache_item_number = start_item + data_length - 1; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListCopyData. ++| ++| Description: This function takes a start entry (0 to length - 1), ++| a pointer to a list of data (each item of list is the ++| size of one data unit, specified at init), and the ++| length of the data list. From this, the data will be ++| copied from the linked list to the data list, from ++| entry start_entry of the linked list to ++| (start_entry + data_length - 1). ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListCopyData ++UINT32 OctApiLlmListCopyData(void* l, UINT32 list_handle, UINT32 start_item, UINT32 data_length, void* pdata_list) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_HEAD* lh; ++ LLM_LIST_ITEM* item = NULL; ++ UINT32 item_pnt = 0xFFFFFFFF; ++ UINT32 total_lists; ++ UINT32 i, j; ++ BYTE* lsbyte; ++ void* pdata_item = NULL; ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Build the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Make sure list handle is valid.*/ ++ if (list_handle >= ls->total_lists) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ lh = &ls->lh[list_handle]; ++ if (lh->list_length == 0xFFFFFFFF) ++ return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ ++ /* Make sure the start_entry is within limits.*/ ++ if (start_item >= lh->list_length) ++ return(OCTAPI_LLM_INVALID_PARAMETER); ++ ++ /* Make sure the end_entry is within limits.*/ ++ lh = &ls->lh[list_handle]; ++ if ((start_item + data_length) > lh->list_length) ++ return(OCTAPI_LLM_INVALID_PARAMETER); ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ ++ ++ ++ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ ++ /* Set the data of each node.*/ ++ for (i=0; icache_item_number + 1)) ++ { ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * lh->cache_item_pointer); ++ item_pnt = item->forward_link; ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * item_pnt); ++ } ++ else ++ { ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * lh->head_pointer); ++ for (j=0; jforward_link; ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * item_pnt); ++ } ++ } ++ ++ pdata_item = (void *)((BYTE *)pdata_list + (i * ls->user_info_bytes)); ++ } ++ else ++ { ++ item_pnt = item->forward_link; ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * item_pnt); ++ ++ pdata_item = (void *)((BYTE *)pdata_item + ls->user_info_bytes); ++ } ++ ++ /* Set the value of the item's user data.*/ ++ OctApiLlmMemCpy(pdata_item, item->user_info, ls->user_info_bytes); ++ } ++ ++ /* Write new cache entry.*/ ++ lh->cache_item_pointer = item_pnt; ++ lh->cache_item_number = start_item + data_length - 1; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListRemoveItem. ++| ++| Description: This function deallocates a node of the linked list specified ++| by the handle list_handle. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| list_handle UINT32 The handle to the list. ++| item_number UINT32 The number of the item to be removed. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmListRemoveItem ++UINT32 OctApiLlmListRemoveItem(void * l,UINT32 list_handle,UINT32 item_number) ++{ ++ LLM_LIST* ls; ++ LLM_LIST_ITEM* freed_item = NULL; ++ LLM_LIST_HEAD* lh; ++ UINT32 freed_item_pnt = 0xFFFFFFFF; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ UINT32 fConditionFlag = TRUE; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM_LIST_HEAD *)(lsbyte + sizeof(LLM_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD))); ++ ls->li = (LLM_LIST_ITEM *)(lsbyte + sizeof(LLM_LIST) + (total_lists * sizeof(LLM_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ if (lh->list_length == 0xFFFFFFFF) return(OCTAPI_LLM_INVALID_LIST_HANDLE); ++ if (lh->list_length <= item_number) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); ++ ++ if (item_number == 0 && lh->list_length == 1)/* First item and only item:*/ ++ { ++ freed_item_pnt = lh->head_pointer; ++ freed_item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * freed_item_pnt); ++ ++ lh->head_pointer = 0xFFFFFFFF; ++ lh->tail_pointer = 0xFFFFFFFF; ++ ++ lh->cache_item_number = 0xFFFFFFFF; ++ lh->cache_item_pointer = 0xFFFFFFFF; ++ } ++ else if (item_number == 0) /* First item and but list not empty:*/ ++ { ++ freed_item_pnt = ls->lh[list_handle].head_pointer; ++ freed_item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * freed_item_pnt); ++ ++ lh->head_pointer = freed_item->forward_link; ++ ++ lh->cache_item_number = 0; ++ lh->cache_item_pointer = freed_item->forward_link; ++ } ++ else /* Discard non-first item! (Caution: this could be the last item!)*/ ++ { ++ LLM_LIST_ITEM * last_item = NULL; ++ LLM_LIST_ITEM * item; ++ UINT32 last_list_pnt; ++ UINT32 cur_list_pnt; ++ UINT32 cur_list_num; ++ ++ if (lh->cache_item_number < item_number) /* Start at cache:*/ ++ { ++ cur_list_pnt = lh->cache_item_pointer; ++ cur_list_num = lh->cache_item_number; ++ } ++ else /* Start at beginning:*/ ++ { ++ cur_list_pnt = lh->head_pointer; ++ cur_list_num = 0; ++ } ++ ++ last_list_pnt = 0xFFFFFFFF; ++ ++ /* Start search from cur_list_pnt and cur_list_num.*/ ++ while( fConditionFlag == TRUE ) ++ { ++ item = (LLM_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ ++ if (cur_list_num == item_number) /* Item number found.*/ ++ { ++ if (last_list_pnt == 0xFFFFFFFF) return(OCTAPI_LLM_INTERNAL_ERROR1); ++ ++ if ((item_number + 1) == lh->list_length) ++ { ++ lh->tail_pointer = last_list_pnt; ++ last_item->forward_link = 0xFFFFFFFF; ++ } ++ else ++ { ++ last_item->forward_link = item->forward_link; ++ } ++ freed_item_pnt = cur_list_pnt; ++ freed_item = item; ++ ++ /* Reset cache entry.*/ ++ lh->cache_item_pointer = last_list_pnt; ++ lh->cache_item_number = cur_list_num - 1; ++ ++ fConditionFlag = FALSE; ++ break; ++ } ++ else if (item->forward_link == 0xFFFFFFFF) /* End of list found?!?*/ ++ { ++ return(OCTAPI_LLM_INTERNAL_ERROR0); ++ } ++ else /* Item was not found, but continue searching.*/ ++ { ++ last_item = item; ++ last_list_pnt = cur_list_pnt; ++ cur_list_pnt = item->forward_link; ++ } ++ ++ cur_list_num++; ++ } ++ } ++ ++ /* Decrease the list length.*/ ++ lh->list_length--; ++ ls->assigned_items--; ++ ++ /* Return free block to free block list:*/ ++ freed_item->forward_link = ls->next_empty_item; ++ ls->next_empty_item = freed_item_pnt; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/**************************************** llm2 function section *****************************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlm2ListGetSize ++| ++| Description: This function determines the amount of memory needed by ++| the LLM2_LIST structure to manage the allocation of ++| number_of_items number of resources. The memory is ++| measured in bytes. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| number_of_items UINT32 The number of resources to be allocated ++| amongst all linked-lists. ++| number_of_lists UINT32 The maximum number of linked-lists that ++| can be allocated. ++| *l_size UINT32 UINT32 The amount of memory needed, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListGetSize ++UINT32 OctApiLlm2ListGetSize(UINT32 number_of_items,UINT32 number_of_lists,UINT32 user_info_size,UINT32 * l_size) ++{ ++ UINT32 head_alloc_size; ++ UINT32 result; ++ UINT32 user_info_size_roundup; ++ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ if (number_of_lists == 0) return(GENERIC_BAD_PARAM); ++ if (user_info_size == 0) return(GENERIC_BAD_PARAM); ++ ++ user_info_size_roundup = ((user_info_size + 3) / 4) * 4; ++ ++ result = OctapiLlmAllocGetSize(number_of_lists,&head_alloc_size); ++ if(result != GENERIC_OK) return(result); ++ ++ *l_size = sizeof(LLM2_LIST) + (number_of_lists * sizeof(LLM2_LIST_HEAD)) + head_alloc_size + (number_of_items * (sizeof(LLM2_LIST_ITEM) + user_info_size_roundup - 4)); ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++#if !SKIP_OctApiLlm2ListGetItemPointer ++LLM2_LIST_ITEM * OctApiLlm2ListGetItemPointer(LLM2_LIST * ls, UINT32 item_number) ++{ ++ return (LLM2_LIST_ITEM *) (((BYTE *)ls->li) + (ls->item_size * item_number)) ; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlm2ListInit. ++| ++| Description: This function intializes the LLM2_TALLOC structure. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM2_LIST structure. ++| number_of_items UINT32 The number of resources to be allocated ++| amongst all linked-lists. ++| number_of_lists UINT32 The maximum number of linked-lists that ++| can be allocated. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListInit ++UINT32 OctApiLlm2ListInit(void ** l,UINT32 number_of_items,UINT32 number_of_lists,UINT32 user_info_size) ++{ ++ LLM2_LIST* ls; ++ LLM2_LIST_ITEM* item; ++ UINT32 i; ++ UINT32 head_alloc_size; ++ UINT32 result; ++ UINT32 user_info_size_roundup; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ ++ ++ if (number_of_items == 0) return(GENERIC_BAD_PARAM); ++ if (number_of_lists == 0) return(GENERIC_BAD_PARAM); ++ if (user_info_size == 0) return(GENERIC_BAD_PARAM); ++ ++ user_info_size_roundup = ((user_info_size + 3) / 4) * 4; ++ ++ /* Get the size of the Alloc structure used to manage head of list structures.*/ ++ result = OctapiLlmAllocGetSize(number_of_lists,&head_alloc_size); ++ if(result != GENERIC_OK) return(result); ++ ++ if (*l == NULL) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM2_LIST *)(*l); ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ /* Initialize parameters in the structure.*/ ++ ls->head_alloc_size = head_alloc_size; ++ ls->user_info_bytes = user_info_size; ++ ls->user_info_size = user_info_size_roundup; ++ ls->total_items = number_of_items; ++ ls->assigned_items = 0; ++ ls->total_lists = number_of_lists; ++ ls->assigned_lists = 0; ++ ls->next_empty_item = 0; ++ ls->item_size = sizeof(LLM2_LIST_ITEM) + user_info_size_roundup - 4; ++ ++ /* Complete the build!*/ ++ ls = (LLM2_LIST *)(*l); ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ /* Initialize the head of queue Alloc structure.*/ ++ result = OctapiLlmAllocInit(&(ls->list_head_alloc),number_of_lists); ++ if(result != GENERIC_OK) return(result); ++ ++ /* Initialize the linked list of the items:*/ ++ for(i=0; ili + ls->item_size * i); ++ ++ if (i == (number_of_items - 1)) ++ item->forward_link = 0xFFFFFFFF; ++ else ++ item->forward_link = i + 1; ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlm2ListCreate. ++| ++| Description: This function creates a linked list. The target which is ++| allocated the newly created list can request additions ++| or removals from the list later on. To target identifies ++| its list with the returned list handle. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM_LIST structure. ++| *list_handle UINT32 The handle to the new list, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListCreate ++UINT32 OctApiLlm2ListCreate(void * l,UINT32 * list_handle) ++{ ++ LLM2_LIST* ls; ++ LLM2_LIST_HEAD* lh; ++ UINT32 blocknum; ++ UINT32 total_lists; ++ UINT32 result; ++ BYTE* lsbyte; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM2_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ /* Get a list using the list head alloc structure.*/ ++ result = OctapiLlmAllocAlloc(ls->list_head_alloc, &blocknum); ++ if (result != GENERIC_OK) return(result); ++ ++ /* The handle is the block number.*/ ++ *list_handle = blocknum; ++ ++ /* Initialize the list head structure.*/ ++ lh = &ls->lh[blocknum]; ++ lh->list_length = 0; ++ lh->head_pointer = 0xFFFFFFFF; ++ lh->tail_pointer = 0xFFFFFFFF; ++ ++ ls->assigned_lists++; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListDelete. ++| ++| Description: This function deletes the linked list indicated by the ++| handle list_handle. Any items which are still allocated ++| to the list are first deallocated. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM2_LIST structure. ++| *list_handle UINT32 The handle to the list. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListDelete ++UINT32 OctApiLlm2ListDelete(void * l,UINT32 list_handle) ++{ ++ LLM2_LIST* ls; ++ LLM2_LIST_HEAD* lh; ++ UINT32 total_lists; ++ UINT32 result; ++ BYTE* lsbyte; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM2_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM2_BLOCKNUM_OUT_OF_RANGE); ++ if (ls->lh[list_handle].list_length == 0xFFFFFFFF) return(OCTAPI_LLM2_INVALID_LIST_HANDLE); ++ ++ /* Release internal list header handle...*/ ++ result = OctapiLlmAllocDealloc(ls->list_head_alloc,list_handle); ++ if (result != GENERIC_OK) return(result); ++ ++ lh = &ls->lh[list_handle]; ++ ++ /* Deallocate all items in the list!*/ ++ if (lh->list_length != 0) ++ { ++ LLM2_LIST_ITEM * item; ++ ++ item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * lh->tail_pointer); ++ ++ /* Release the items using only the links.*/ ++ item->forward_link = ls->next_empty_item; ++ ls->next_empty_item = lh->head_pointer; ++ ++ /* Remove items from item counter.*/ ++ ls->assigned_items -= lh->list_length; ++ } ++ ++ lh->list_length = 0xFFFFFFFF; ++ lh->head_pointer = 0xFFFFFFFF; ++ lh->tail_pointer = 0xFFFFFFFF; ++ ++ ls->assigned_lists--; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmListLength. ++| ++| Description: This function returns the number of items allocated to the ++| list indicated by the handle list_handle. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM2_LIST structure. ++| list_handle UINT32 The handle to the list. ++| *number_of_items UINT32 The number of items in the list, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListLength ++UINT32 OctApiLlm2ListLength(void * l,UINT32 list_handle, UINT32 * number_of_items_in_list) ++{ ++ LLM2_LIST* ls; ++ LLM2_LIST_HEAD* lh; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM2_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM2_BLOCKNUM_OUT_OF_RANGE); ++ if (lh->list_length == 0xFFFFFFFF) return(OCTAPI_LLM2_INVALID_LIST_HANDLE); ++ ++ *number_of_items_in_list = lh->list_length; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlm2ListItemData ++| ++| Description: This function returns a pointer to the user data associated ++| with an item. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM2_LIST structure. ++| list_handle UINT32 The handle to the list. ++| item_number UINT32 The number of the list node in question. ++| **item_data_pnt void The pointer to the user data, returned. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListItemData ++UINT32 OctApiLlm2ListItemData(void * l,UINT32 list_handle,UINT32 item_key,void ** item_data_pnt, PUINT32 item_number_pnt) ++{ ++ LLM2_LIST* ls; ++ LLM2_LIST_HEAD* lh; ++ LLM2_LIST_ITEM* item; ++ UINT32 cur_list_pnt; ++ UINT32 cur_list_key = 0xFFFFFFFF; ++ UINT32 total_lists; ++ UINT32 list_length; ++ BYTE* lsbyte; ++ UINT32 fConditionFlag = TRUE; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM2_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ list_length = lh->list_length; ++ ++ *item_data_pnt = NULL; ++ *item_number_pnt = 0; ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM2_BLOCKNUM_OUT_OF_RANGE); ++ if (list_length == 0xFFFFFFFF) return(OCTAPI_LLM2_INVALID_LIST_HANDLE); ++ ++ /* Determine where the search will start.*/ ++ /* Start at beginning:*/ ++ cur_list_pnt = lh->head_pointer; ++ item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ cur_list_key = item->key; ++ ++ /* Start search from cur_list_pnt and cur_list_num.*/ ++ while ( fConditionFlag == TRUE ) ++ { ++ if (cur_list_key == item_key) /* Item key found.*/ ++ { ++ /* Get item info.*/ ++ *item_data_pnt = (void *)item->user_info; ++ ++ return(GENERIC_OK); ++ } ++ else if(item->forward_link == 0xFFFFFFFF) /* End of list found?!?*/ ++ { ++ return(OCTAPI_LLM2_INTERNAL_ERROR0); ++ } ++ else /* Item was not found, but continue searching.*/ ++ { ++ cur_list_pnt = item->forward_link; ++ } ++ ++ item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ cur_list_key = item->key; ++ (*item_number_pnt)++; ++ } ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlm2ListInsertItem. ++| ++| Description: This function allocates a node to the linked list specified ++| by the handle list_handle. The position of the new item ++| will be defined based on the key value. All entry are inserted ++| in the list in incremental Key value. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM2_LIST structure. ++| *list_handle UINT32 The handle to the list. ++| **item_data void Address of the user data space for this item. ++| **prev_item_data void Address of the user data space for the previous item. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListInsertItem ++UINT32 OctApiLlm2ListInsertItem(void * l,UINT32 list_handle,UINT32 item_key,void ** item_data_pnt, void ** prev_item_data_pnt, void ** prev_prev_item_data_pnt, PUINT32 insert_status_pnt ) ++{ ++ LLM2_LIST* ls; ++ LLM2_LIST_HEAD* lh; ++ LLM2_LIST_ITEM* free_item; ++ UINT32 free_item_pnt; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ UINT32 ulPassCount = 0; ++ UINT32 fConditionFlag = TRUE; ++ ++ /* Set the status of the insertion.*/ ++ *insert_status_pnt = OCTAPI_LLM2_INSERT_ERROR; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM2_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ ++ *item_data_pnt = NULL; ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM2_BLOCKNUM_OUT_OF_RANGE); ++ if (lh->list_length == 0xFFFFFFFF) return(OCTAPI_LLM2_INVALID_LIST_HANDLE); ++ if (ls->next_empty_item == 0xFFFFFFFF) return(OCTAPI_LLM2_NO_STRUCTURES_LEFT); ++ ++ /* Get a free item from the free item list!*/ ++ free_item_pnt = ls->next_empty_item; ++ free_item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * free_item_pnt); ++ free_item->key = item_key; ++ ls->next_empty_item = free_item->forward_link; ++ ++ if (lh->list_length == 0) /* First item and only item:*/ ++ { ++ free_item->forward_link = 0xFFFFFFFF; ++ lh->tail_pointer = free_item_pnt; ++ lh->head_pointer = free_item_pnt; ++ *insert_status_pnt = OCTAPI_LLM2_INSERT_FIRST_NODE; ++ ++ /* There is no previous node information to return.*/ ++ *prev_item_data_pnt = NULL; ++ *prev_prev_item_data_pnt = NULL; ++ } ++ else /* Insert:*/ ++ { ++ LLM2_LIST_ITEM * last_last_item = NULL; ++ LLM2_LIST_ITEM * last_item = NULL; ++ LLM2_LIST_ITEM * item; ++ UINT32 last_list_pnt; ++ UINT32 cur_list_pnt; ++ UINT32 cur_list_key = 0xFFFFFFFF; ++ ++ /* Start at beginning:*/ ++ cur_list_pnt = lh->head_pointer; ++ item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ cur_list_key = item->key; ++ ++ last_list_pnt = 0xFFFFFFFF; ++ ++ /* Start search from cur_list_pnt and cur_list_num.*/ ++ while ( fConditionFlag == TRUE ) ++ { ++ /* Increment the pass count to determine if the addition will happen next to last.*/ ++ ulPassCount++; ++ ++ if (cur_list_key >= item_key) /* Item new node between the last and the curent. */ ++ { ++ if (last_list_pnt == 0xFFFFFFFF) /* Must insert at the head of the list.*/ ++ { ++ free_item->forward_link = cur_list_pnt; ++ lh->head_pointer = free_item_pnt; ++ } ++ else /* Standard insertion.*/ ++ { ++ free_item->forward_link = cur_list_pnt; ++ last_item->forward_link = free_item_pnt; ++ } ++ ++ /* Check if the entry was made before the last one.*/ ++ if ( ulPassCount == lh->list_length ) ++ *insert_status_pnt = OCTAPI_LLM2_INSERT_BEFORE_LAST_NODE; ++ else ++ *insert_status_pnt = OCTAPI_LLM2_INSERT_LIST_NODE; ++ ++ fConditionFlag = FALSE; ++ break; ++ } ++ else if (item->forward_link == 0xFFFFFFFF) /* End of list found, must insert at the end.*/ ++ { ++ free_item->forward_link = 0xFFFFFFFF; ++ item->forward_link = free_item_pnt; ++ lh->tail_pointer = free_item_pnt; ++ ++ *insert_status_pnt = OCTAPI_LLM2_INSERT_LAST_NODE; ++ ++ fConditionFlag = FALSE; ++ break; ++ } ++ else /* Item was not found, but continue searching.*/ ++ { ++ last_last_item = last_item; ++ last_item = item; ++ last_list_pnt = cur_list_pnt; ++ cur_list_pnt = item->forward_link; ++ } ++ ++ item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ cur_list_key = item->key; ++ ++ } ++ ++ /* Return the previous node if possible.*/ ++ if ( *insert_status_pnt == OCTAPI_LLM2_INSERT_LIST_NODE || ++ *insert_status_pnt == OCTAPI_LLM2_INSERT_BEFORE_LAST_NODE ) ++ { ++ if ( last_item != NULL ) ++ *prev_item_data_pnt = (void *)last_item->user_info; ++ ++ if ( last_last_item != NULL ) ++ *prev_prev_item_data_pnt = (void *)last_last_item->user_info; ++ else ++ *prev_prev_item_data_pnt = NULL; ++ } ++ else ++ { ++ *prev_item_data_pnt = (void *)item->user_info; ++ ++ if ( ( last_last_item != NULL ) && ( last_item != NULL ) ) ++ *prev_prev_item_data_pnt = (void *)last_item->user_info; ++ else ++ *prev_prev_item_data_pnt = NULL; ++ } ++ } ++ ++ /* Increase the list length.*/ ++ lh->list_length++; ++ ls->assigned_items++; ++ *item_data_pnt = (void *)free_item->user_info; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlm2ListRemoveItem. ++| ++| Description: This function deallocates a node of the linked list specified ++| by the handle list_handle. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *l void The memory used by the LLM2_LIST structure. ++| list_handle UINT32 The handle to the list. ++| item_key UINT32 The key of the item to be removed. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlm2ListRemoveItem ++UINT32 OctApiLlm2ListRemoveItem(void * l,UINT32 list_handle,UINT32 item_key, PUINT32 prev_item_key_pnt, PUINT32 prev_prev_item_key_pnt, PUINT32 remove_status_pnt ) ++{ ++ LLM2_LIST* ls; ++ LLM2_LIST_ITEM* freed_item = NULL; ++ LLM2_LIST_HEAD* lh; ++ UINT32 freed_item_pnt = 0xFFFFFFFF; ++ UINT32 total_lists; ++ BYTE* lsbyte; ++ UINT32 fConditionFlag = TRUE; ++ UINT32 ulPassCount = 0; ++ ++ /* Built the structure based on the base address:*/ ++ ls = (LLM2_LIST *)l; ++ lsbyte = (BYTE *)ls; ++ total_lists = ls->total_lists; ++ ++ /* Set the status of the removal to error as a default value.*/ ++ *remove_status_pnt = OCTAPI_LLM2_REMOVE_ERROR; ++ ++ ls->lh = (LLM2_LIST_HEAD *)(lsbyte + sizeof(LLM2_LIST)); ++ ls->list_head_alloc = (void *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD))); ++ ls->li = (LLM2_LIST_ITEM *)(lsbyte + sizeof(LLM2_LIST) + (total_lists * sizeof(LLM2_LIST_HEAD)) + ls->head_alloc_size); ++ ++ lh = &ls->lh[list_handle]; ++ ++ if (list_handle >= ls->total_lists) return(OCTAPI_LLM2_BLOCKNUM_OUT_OF_RANGE); ++ if (lh->list_length == 0xFFFFFFFF) return(OCTAPI_LLM2_INVALID_LIST_HANDLE); ++ ++ if (lh->list_length == 1)/* First item and only item if he matches.*/ ++ { ++ freed_item_pnt = lh->head_pointer; ++ freed_item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * freed_item_pnt); ++ ++ if ( freed_item->key == item_key ) ++ { ++ lh->head_pointer = 0xFFFFFFFF; ++ lh->tail_pointer = 0xFFFFFFFF; ++ } ++ else ++ return(OCTAPI_LLM2_INTERNAL_ERROR1); ++ ++ /* Indicate that there was no node prior to the one removed.*/ ++ *prev_item_key_pnt = 0xFFFFFFFF; ++ *prev_prev_item_key_pnt = 0xFFFFFFFF; ++ *remove_status_pnt = OCTAPI_LLM2_REMOVE_FIRST_NODE; ++ } ++ else /* Discard non-first item! (Caution: this could be the last item!)*/ ++ { ++ LLM2_LIST_ITEM * last_last_item = NULL; ++ LLM2_LIST_ITEM * last_item = NULL; ++ LLM2_LIST_ITEM * item; ++ UINT32 last_list_pnt; ++ UINT32 cur_list_pnt; ++ UINT32 cur_list_key; ++ ++ /* Start at beginning:*/ ++ cur_list_pnt = lh->head_pointer; ++ item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ cur_list_key = item->key; ++ ++ last_list_pnt = 0xFFFFFFFF; ++ ++ /* Start search from cur_list_pnt and cur_list_num.*/ ++ while( fConditionFlag == TRUE ) ++ { ++ ulPassCount++; ++ if (cur_list_key == item_key) /* Item number found.*/ ++ { ++ if (last_list_pnt == 0xFFFFFFFF) /* First item in the list.*/ ++ { ++ lh->head_pointer = item->forward_link; ++ *remove_status_pnt = OCTAPI_LLM2_REMOVE_FIRST_NODE; ++ } ++ else if ( item->forward_link == 0xFFFFFFFF) /* Last item of the list.*/ ++ { ++ last_item->forward_link = 0xFFFFFFFF; ++ lh->tail_pointer = last_list_pnt; ++ *remove_status_pnt = OCTAPI_LLM2_REMOVE_LAST_NODE; ++ } ++ else ++ { ++ last_item->forward_link = item->forward_link; ++ ++ if ( ulPassCount == ( lh->list_length - 1 ) ) ++ *remove_status_pnt = OCTAPI_LLM2_REMOVE_BEFORE_LAST_NODE; ++ else ++ *remove_status_pnt = OCTAPI_LLM2_REMOVE_LIST_NODE; ++ } ++ ++ freed_item_pnt = cur_list_pnt; ++ freed_item = item; ++ ++ fConditionFlag = FALSE; ++ break; ++ } ++ else if (item->forward_link == 0xFFFFFFFF) /* End of list found?!?*/ ++ { ++ return(OCTAPI_LLM2_INTERNAL_ERROR0); ++ } ++ else /* Item was not found, but continue searching.*/ ++ { ++ last_last_item = last_item; ++ last_item = item; ++ last_list_pnt = cur_list_pnt; ++ cur_list_pnt = item->forward_link; ++ } ++ ++ item = (LLM2_LIST_ITEM *)((BYTE *)ls->li + ls->item_size * cur_list_pnt); ++ cur_list_key = item->key; ++ } ++ ++ /* Return the key of the node before the node removed if possible.*/ ++ if ( last_list_pnt == 0xFFFFFFFF ) ++ *prev_item_key_pnt = 0xFFFFFFFF; ++ else if ( last_item != NULL ) ++ *prev_item_key_pnt = last_item->key; ++ ++ /* Return the key of the node before before the node removed if possible.*/ ++ if ( last_last_item == NULL ) ++ *prev_prev_item_key_pnt = 0xFFFFFFFF; ++ else ++ *prev_prev_item_key_pnt = last_last_item->key; ++ ++ } ++ ++ /* Decrease the list length.*/ ++ lh->list_length--; ++ ls->assigned_items--; ++ ++ /* Return free block to free block list:*/ ++ freed_item->forward_link = ls->next_empty_item; ++ ls->next_empty_item = freed_item_pnt; ++ ++ return(GENERIC_OK); ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++| API UTILITIES ++| ++| Function: OctApiLlmMemCpy. ++| ++| Description: This function copies data from a source to a destination. ++| ++| ----------------------------------------------------------------------- ++| | Variable | Type | Description ++| ----------------------------------------------------------------------- ++| *f_pvDestination VOID The destination where to copy the data. ++| *f_pvSource VOID The source where to copy the data from. ++| f_ulSize UINT32 The number of bytes to copy. ++| ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OctApiLlmMemCpy ++VOID * OctApiLlmMemCpy( VOID *f_pvDestination, const VOID * f_pvSource, UINT32 f_ulSize ) ++{ ++ CHAR * pbyDst; ++ const CHAR * pbySrc; ++ UINT32 * f_pulAlignedDst; ++ const UINT32 * f_pulAlignedSrc; ++ ++ pbyDst = (CHAR *)f_pvDestination; ++ pbySrc = (const CHAR *)f_pvSource; ++ ++ /* ++ * If the size is small, or either SRC or DST is unaligned, ++ * then punt into the byte copy loop. This should be rare. ++ */ ++ if ( ( f_ulSize < sizeof(UINT32) ) ++ || ( ( (unsigned long)( pbySrc ) & ( sizeof(UINT32) - 1 ) ) | ( (unsigned long)( pbyDst ) & ( sizeof(UINT32) - 1 ) ) ) ) ++ { ++ while ( f_ulSize-- ) ++ *pbyDst++ = *pbySrc++; ++ return f_pvDestination; ++ } ++ ++ f_pulAlignedDst = (UINT32 *)pbyDst; ++ f_pulAlignedSrc = (const UINT32 *)pbySrc; ++ ++ /* Copy 4X long words at a time if possible. */ ++ while ( f_ulSize >= 4 * sizeof(UINT32) ) ++ { ++ *f_pulAlignedDst++ = *f_pulAlignedSrc++; ++ *f_pulAlignedDst++ = *f_pulAlignedSrc++; ++ *f_pulAlignedDst++ = *f_pulAlignedSrc++; ++ *f_pulAlignedDst++ = *f_pulAlignedSrc++; ++ f_ulSize -= 4 * sizeof(UINT32); ++ } ++ ++ /* Copy one long word at a time if possible. */ ++ while ( f_ulSize >= sizeof(UINT32) ) ++ { ++ *f_pulAlignedDst++ = *f_pulAlignedSrc++; ++ f_ulSize -= sizeof(UINT32); ++ } ++ ++ /* Pick up any residual with a byte copier. */ ++ pbyDst = (CHAR *)f_pulAlignedDst; ++ pbySrc = (const CHAR *)f_pulAlignedSrc; ++ while ( f_ulSize-- ) ++ *pbyDst++ = *pbySrc++; ++ ++ return f_pvDestination; ++} ++#endif ++ ++/**************************************** llm_list section **********************************************/ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/apilib/llman/octapi_llman_private.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/llman/octapi_llman_private.h +--- linux-source-4.19/drivers/dahdi/oct612x/apilib/llman/octapi_llman_private.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/apilib/llman/octapi_llman_private.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,206 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_llman_private.h ++ ++Copyright (c) 2001 Octasic Inc. All rights reserved. ++ ++Description: ++ ++ Library used to manage allocation tables and linked lists. The library is ++ made such that only a block of contiguous memory is needed for the ++ management of the linked list/allocation table. ++ ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 13 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#ifndef __OCTAPI_LLMAN_PRIVATE_H__ ++#define __OCTAPI_LLMAN_PRIVATE_H__ ++ ++#include "octdef.h" ++ ++ ++/**************************************** llm_alloc section **********************************************/ ++ ++ ++/* Most basic linked list model. ++ LLM_STR contains a list of "number_of_items" that ++ are each "unassigned" or "assigned". When requesting ++ a new element, llm_alloc must choose an "unassigned" ++ element. An element that is deallocated will be last ++ to be allocated. ++*/ ++ ++typedef struct _LLM_ALLOC ++{ ++ UINT32 *linked_list; /* Each item is either used (0xFFFFFFFE)*/ ++ /* or unused (pointer to next unused item, 0xFFFFFFFF means last item reached).*/ ++ UINT32 next_avail_num; /* Points to the next available item in linked list. (0xFFFFFFFF means none available)*/ ++ UINT32 number_of_items; /* Total number of items in linked list.*/ ++ UINT32 allocated_items; /* Allocated items in linked list.*/ ++ ++} LLM_ALLOC; ++ ++typedef struct _TLLM_ALLOC_NODE_ ++{ ++ UINT32 value; /* Each item is either used (0xFFFFFFFE)*/ ++ /* or unused (pointer to next unused item, 0xFFFFFFFF means last item reached).*/ ++ UINT32 timeout[2]; /* Timeout value that must be exceeded for the node to be considered free again.*/ ++ ++} TLLM_ALLOC_NODE; ++ ++ ++typedef struct _TLLM_ALLOC_ ++{ ++ TLLM_ALLOC_NODE *linked_list; /* List of nodes used by the link list.*/ ++ ++ UINT32 next_avail_num; /* Points to the next available item in linked list. (0xFFFFFFFF means none available)*/ ++ UINT32 number_of_items; /* Total number of items in linked list.*/ ++ UINT32 allocated_items; /* Allocated items in linked list.*/ ++ ++ UINT32 number_of_timeout; /* Number of block currently in timeout.*/ ++ UINT32 next_timeout_num; /* Points to the next block currently in timeout.*/ ++ UINT32 last_timeout_num; /* Last node of the timeout list.*/ ++ ++ UINT32 last_known_time[2]; /* last known time.*/ ++ ++} TLLM_ALLOC; ++ ++/* ++void octapi_llm_alloc_build_structure(void *l, LLM_ALLOC ** ls); ++*/ ++/**************************************** llm_alloc section **********************************************/ ++ ++ ++ ++/**************************************** llm_list section **********************************************/ ++/* This section contains memory structures and functions used ++ to maintain a variable number of lists (FIFOs) that each ++ have a variable amount of items. A total amount of items ++ can be assigned through-out all the lists. Each item in ++ each list contains a UINT32 specified by the software using ++ the lists. Each used item in the list is accessible through ++ it's position in the list. */ ++ ++typedef struct _LLM_LIST_HEAD ++{ ++ UINT32 list_length; /* Current number of items in the list.*/ ++ /* 0xFFFFFFFF means that the list is not used.*/ ++ UINT32 head_pointer; /* Number of the item in the item pool that is the first of this list.*/ ++ /* 0xFFFFFFFF indicates end-of-list link.*/ ++ UINT32 tail_pointer; /* Number of the item in the item pool that is the last of this list.*/ ++ ++ /* Item cache (pointer within the list of the last accessed item):*/ ++ UINT32 cache_item_number; /* Number of the last accessed item in the list. 0xFFFFFFFF indicates invalid cache.*/ ++ UINT32 cache_item_pointer; /* Number of the last accessed item in the item pool.*/ ++} LLM_LIST_HEAD; ++ ++typedef struct _LLM_LIST_ITEM ++{ ++ UINT32 forward_link; /* Number of the item in the item pool that is next in this list.*/ ++ /* 0xFFFFFFFF indicates end-of-list link.*/ ++ ++ /* User item info (variable size)*/ ++ UINT32 user_info[1]; ++} LLM_LIST_ITEM; ++ ++typedef struct _LLM_LIST ++{ ++ UINT32 user_info_bytes; /* In bytes, size of the user info in a single item.*/ ++ UINT32 user_info_size; /* In bytes, size of the user info in a single item.*/ ++ UINT32 item_size; ++ ++ UINT32 head_alloc_size; ++ UINT32 total_items; ++ UINT32 assigned_items; ++ ++ UINT32 total_lists; ++ UINT32 assigned_lists; ++ ++ UINT32 next_empty_item; /* Contains a pointer to the next empty item in the*/ ++ /* item pool.*/ ++ ++ /* Table of all the possible list heads:*/ ++ LLM_LIST_HEAD * lh; ++ void * list_head_alloc; /* LLM_ALLOC structure used for list head allocation!*/ ++ ++ /* Table of the list items:*/ ++ LLM_LIST_ITEM * li; ++} LLM_LIST; ++ ++ ++/**********************************************************************************/ ++/* These structures are are used by the Llm2 functions to creates lists of ordered ++ items based on a key given by the user when a new node is inserted in a list. */ ++typedef struct _LLM2_LIST_HEAD ++{ ++ UINT32 list_length; /* Current number of items in the list.*/ ++ /* 0xFFFFFFFF means that the list is not used.*/ ++ UINT32 head_pointer; /* Number of the item in the item pool that is the first of this list.*/ ++ /* 0xFFFFFFFF indicates end-of-list link.*/ ++ UINT32 tail_pointer; /* Number of the item in the item pool that is the last of this list.*/ ++ ++} LLM2_LIST_HEAD; ++ ++typedef struct _LLM2_LIST_ITEM ++{ ++ UINT32 forward_link; /* Number of the item in the item pool that is next in this list.*/ ++ /* 0xFFFFFFFF indicates end-of-list link.*/ ++ UINT32 key; /* Key used to order the entries.*/ ++ ++ /* User item info (variable size)*/ ++ UINT32 user_info[1]; ++} LLM2_LIST_ITEM; ++ ++typedef struct _LLM2_LIST ++{ ++ UINT32 user_info_bytes; /* In bytes, size of the user info in a single item.*/ ++ UINT32 user_info_size; /* In bytes, size of the user info in a single item.*/ ++ UINT32 item_size; ++ ++ UINT32 head_alloc_size; ++ UINT32 total_items; ++ UINT32 assigned_items; ++ ++ UINT32 total_lists; ++ UINT32 assigned_lists; ++ ++ UINT32 next_empty_item; /* Contains a pointer to the next empty item in the*/ ++ /* item pool.*/ ++ ++ /* Table of all the possible list heads:*/ ++ LLM2_LIST_HEAD * lh; ++ void * list_head_alloc; /* LLM_ALLOC structure used for list head allocation!*/ ++ ++ /* Table of the list items:*/ ++ LLM2_LIST_ITEM * li; ++} LLM2_LIST; ++ ++/*void octapi_llm_list_build_structure(void *l, LLM_LIST ** ls);*/ ++LLM_LIST_ITEM * OctApiLlmListGetItemPointer( LLM_LIST * ls, UINT32 item_number ); ++LLM2_LIST_ITEM * OctApiLlm2ListGetItemPointer( LLM2_LIST * ls, UINT32 item_number ); ++UINT32 OctApiTllmCheckTimeoutList( TLLM_ALLOC *ls, UINT32 current_time[2] ); ++VOID * OctApiLlmMemCpy( VOID *f_pvDestination, const VOID * f_pvSource, UINT32 f_ulSize ); ++/**************************************** llm_list section **********************************************/ ++ ++ ++ ++ ++ ++#endif /*__OCTAPI_LLMAN_PRIVATE_H__*/ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/get_discards linux-source-4.19-dahdi/drivers/dahdi/oct612x/get_discards +--- linux-source-4.19/drivers/dahdi/oct612x/get_discards 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/get_discards 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,51 @@ ++#!/usr/bin/php ++ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/apilib/octapi_bt0.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/apilib/octapi_bt0.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/apilib/octapi_bt0.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/apilib/octapi_bt0.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,75 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_bt0.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Library used to manage a binary tree of variable max size. Library is ++ made to use one block of contiguous memory to manage the tree. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 11 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#ifndef __OCTAPI_BT0_H__ ++#define __OCTAPI_BT0_H__ ++ ++#include "octdef.h" ++ ++#define OCTAPI_BT0_BASE 0xFFFF0000 ++#define OCTAPI_BT0_KEY_SIZE_NOT_MUTLIPLE_OF_UINT32 OCTAPI_BT0_BASE+0x0001 ++#define OCTAPI_BT0_DATA_SIZE_NOT_MUTLIPLE_OF_UINT32 OCTAPI_BT0_BASE+0x0002 ++#define OCTAPI_BT0_MALLOC_FAILED OCTAPI_BT0_BASE+0x0003 ++#define OCTAPI_BT0_NO_NODES_AVAILABLE OCTAPI_BT0_BASE+0x0004 ++#define OCTAPI_BT0_KEY_ALREADY_IN_TREE OCTAPI_BT0_BASE+0x0005 ++#define OCTAPI_BT0_KEY_NOT_IN_TREE OCTAPI_BT0_BASE+0x0006 ++ ++/* Possible result for Find Or Add function. */ ++#define OCTAPI0_BT0_NODE_FOUND 0 ++#define OCTAPI0_BT0_NODE_ADDDED 1 ++ ++#define OCTAPI_BT0_NO_SMALLER_KEY 0xAAAAAAAA ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++#define octapi_bt0_get_size( number_of_items, key_size, data_size, b_size ) OctApiBt0GetSize( (UINT32) number_of_items,(UINT32) key_size, (UINT32) data_size, (PUINT32) b_size ) ++#define octapi_bt0_init( b, number_of_items, key_size, data_size ) OctApiBt0Init( (void **) b,(UINT32) number_of_items,(UINT32) key_size, (UINT32) data_size ) ++#define octapi_bt0_add_node( b, key, data ) OctApiBt0AddNode( (void *) b,(void *) key,(void **) data ) ++#define octapi_bt0_remove_node( b, key ) OctApiBt0RemoveNode( (void *) b,(void *) key ) ++#define octapi_bt0_query_node( b, key, data ) OctApiBt0QueryNode( (void *) b,(void *) key,(void **) data ) ++#define octapi_bt0_get_first_node( b, key, data ) OctApiBt0GetFirstNode( (void *) b,(void **) key, (void **) data ) ++ ++UINT32 OctApiBt0GetSize( UINT32 number_of_items, UINT32 key_size, UINT32 data_size, UINT32 * b_size ); ++UINT32 OctApiBt0Init( void ** b, UINT32 number_of_items, UINT32 key_size, UINT32 data_size ); ++UINT32 OctApiBt0AddNode( void * b, void * key, void ** data ); ++UINT32 OctApiBt0RemoveNode( void * b, void * key ); ++UINT32 OctApiBt0QueryNode( void * b, void * key, void ** data ); ++UINT32 OctApiBt0GetFirstNode( void * b, void ** key, void ** data ); ++UINT32 OctApiBt0FindOrAddNode( void * b, void * key, void ** data, UINT32 *fnct_result ); ++ ++UINT32 OctApiBt0AddNodeReportPrevNodeData( void * b, void * key, void ** data, void ** prev_data, UINT32 *fnct_result ); ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /*__OCTAPI_BT0_H__*/ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/apilib/octapi_largmath.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/apilib/octapi_largmath.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/apilib/octapi_largmath.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/apilib/octapi_largmath.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,69 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_largmath.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Library used to perform arithmetic on integer values of an integer multiple ++ of 32-bits. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 6 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#ifndef __OCTAPI_LARGMATH_H__ ++#define __OCTAPI_LARGMATH_H__ ++ ++#include "octdef.h" ++ ++#define OCTAPI_LM_DIVISION_BY_ZERO 0xFFFF ++#define OCTAPI_LM_OVERFLOW 0xFFFE ++#define OCTAPI_LM_ARRAY_SIZE_MISMATCH 0xFFFD ++ ++#define OCTAPI_LM_MAX_OPTIMIZE_MUL 10 ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++#define octapi_lm_add( a, alen, b, blen, z, zlen ) OctApiLmAdd( (PUINT32) a, (USHORT) alen, (PUINT32) b, (USHORT) blen, (PUINT32) z, (USHORT) zlen ) ++#define octapi_lm_subtract( a, alen, bneg, blen, z, zlen, neg ) OctApiLmSubtract( (PUINT32) a, (USHORT) alen, (PUINT32) bneg, (USHORT) blen, (PUINT32) z, (USHORT) zlen, (USHORT*) neg ) ++#define octapi_lm_compare( a, alen, bneg, blen, neg ) OctApiLmCompare( (PUINT32) a, (USHORT) alen, (PUINT32) bneg, (USHORT) blen, (USHORT*) neg ) ++#define octapi_lm_multiply( a, b, ablen, z ) OctApiLmMultiply( (PUINT32) a, (PUINT32) b, (USHORT) ablen, (PUINT32) z ) ++#define octapi_lm_divide( n, d, q, r, ndqrlen ) OctApiLmDivide( (PUINT32) n, (PUINT32) d, (PUINT32) q, (PUINT32) r, (USHORT) ndqrlen ) ++#define octapi_lm_shiftright1( a, alen ) OctApiLmShiftRight1( (PUINT32) a, (USHORT) alen ) ++#define octapi_lm_shiftn( a, alen, shiftleft, shiftn ) OctApiLmShiftn( (PUINT32) a, (USHORT) alen, (USHORT) shiftleft, (USHORT) shiftn ) ++#define octapi_lm_getmsb( a, alen, msb_pos ) OctApiLmGetMsb( (PUINT32) a, (USHORT) alen, (USHORT*) msb_pos ) ++ ++ ++UINT32 OctApiLmAdd( PUINT32 a, USHORT alen, PUINT32 b, USHORT blen, PUINT32 z, USHORT zlen ); ++UINT32 OctApiLmSubtract( PUINT32 a, USHORT alen, PUINT32 bneg, USHORT blen, PUINT32 z, USHORT zlen, PUSHORT neg ); ++UINT32 OctApiLmCompare( PUINT32 a, USHORT alen, PUINT32 bneg, USHORT blen, PUSHORT neg ); ++UINT32 OctApiLmMultiply( PUINT32 a, PUINT32 b, USHORT ablen, PUINT32 z ); ++UINT32 OctApiLmDivide( PUINT32 n, PUINT32 d, PUINT32 q, PUINT32 r, USHORT ndqrlen ); ++UINT32 OctApiLmShiftRight1( PUINT32 a, USHORT alen ); ++UINT32 OctApiLmShiftn( PUINT32 a, USHORT alen, USHORT shiftleft, USHORT shiftn ); ++UINT32 OctApiLmGetMsb( PUINT32 a, USHORT alen, PUSHORT msb_pos ); ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* __OCTAPI_LARGMATH_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/apilib/octapi_llman.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/apilib/octapi_llman.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/apilib/octapi_llman.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/apilib/octapi_llman.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,142 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octapi_llman.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Library used to manage allocation tables and linked lists. The library is ++ made such that only a block of contiguous memory is needed for the ++ management of the linked list/allocation table. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 8 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#ifndef __OCTAPI_LLMAN_H__ ++#define __OCTAPI_LLMAN_H__ ++ ++#include "octdef.h" ++ ++/* Error defines. */ ++#define OCTAPI_LLM_MEMORY_NOT_ALLOCATED 0xFFFFFFFF ++#define OCTAPI_LLM_NO_STRUCTURES_LEFT 0xFFFFFFFE ++#define OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE 0xFFFFFFFD ++#define OCTAPI_LLM_ELEMENT_ALREADY_ASSIGNED 0xFFFFFFFC ++#define OCTAPI_LLM_ELEMENT_NOT_FOUND 0xFFFFFFFB ++#define OCTAPI_LLM_LIST_EMPTY 0xFFFFFFFA ++#define OCTAPI_LLM_INVALID_LIST_HANDLE 0xFFFFFFF9 ++#define OCTAPI_LLM_TREE_NODE_ABSENT 0xFFFFFFF8 ++#define OCTAPI_LLM_INTERNAL_ERROR0 0xFFFFFFF7 ++#define OCTAPI_LLM_INTERNAL_ERROR1 0xFFFFFFF6 ++#define OCTAPI_LLM_INVALID_PARAMETER 0xFFFFFFF5 ++ ++#define OCTAPI_LLM2_MEMORY_NOT_ALLOCATED 0xFEFFFFFF ++#define OCTAPI_LLM2_NO_STRUCTURES_LEFT 0xFEFFFFFE ++#define OCTAPI_LLM2_BLOCKNUM_OUT_OF_RANGE 0xFEFFFFFD ++#define OCTAPI_LLM2_ELEMENT_ALREADY_ASSIGNED 0xFEFFFFFC ++#define OCTAPI_LLM2_ELEMENT_NOT_FOUND 0xFEFFFFFB ++#define OCTAPI_LLM2_LIST_EMPTY 0xFEFFFFFA ++#define OCTAPI_LLM2_INVALID_LIST_HANDLE 0xFEFFFFF9 ++#define OCTAPI_LLM2_TREE_NODE_ABSENT 0xFEFFFFF8 ++#define OCTAPI_LLM2_INTERNAL_ERROR0 0xFEFFFFF7 ++#define OCTAPI_LLM2_INTERNAL_ERROR1 0xFEFFFFF6 ++#define OCTAPI_LLM2_INVALID_PARAMETER 0xFEFFFFF5 ++ ++/* Other defines. */ ++#define OCTAPI_LLM_LIST_APPEND 0xFFFFFFFF ++#define OCTAPI_LLM2_INSERT_ERROR 0xFFFFFFFF ++#define OCTAPI_LLM2_INSERT_FIRST_NODE 0xFFFF0000 ++#define OCTAPI_LLM2_INSERT_LIST_NODE 0xFFFF0001 ++#define OCTAPI_LLM2_INSERT_LAST_NODE 0xFFFF0002 ++#define OCTAPI_LLM2_INSERT_BEFORE_LAST_NODE 0xFFFF0003 ++#define OCTAPI_LLM2_REMOVE_ERROR 0xFFFFFFFF ++#define OCTAPI_LLM2_REMOVE_FIRST_NODE 0xFFFF0004 ++#define OCTAPI_LLM2_REMOVE_LIST_NODE 0xFFFF0005 ++#define OCTAPI_LLM2_REMOVE_LAST_NODE 0xFFFF0006 ++#define OCTAPI_LLM2_REMOVE_BEFORE_LAST_NODE 0xFFFF0007 ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++#define octapi_llm_alloc_get_size( number_of_items, l_size ) OctapiLlmAllocGetSize( (UINT32) number_of_items,(PUINT32) l_size ) ++#define octapi_llm_alloc_init( l, number_of_items ) OctapiLlmAllocInit( (PVOID*) l,(UINT32) number_of_items ) ++#define octapi_llm_alloc_info( l, allocated_items, available_items ) OctapiLlmAllocInfo( (PVOID) l, (PUINT32) allocated_items, (PUINT32) available_items ) ++#define octapi_llm_alloc_alloc( l, blocknum ) OctapiLlmAllocAlloc( (PVOID) l, (PUINT32) blocknum ) ++#define octapi_llm_alloc_dealloc( l, blocknum ) OctapiLlmAllocDealloc( (PVOID) l,(UINT32) blocknum ) ++#define octapi_llm_list_get_size( number_of_items, number_of_lists, user_info_size, l_size ) OctApiLlmListGetSize( (UINT32) number_of_items,(UINT32) number_of_lists,(UINT32) user_info_size,(PUINT32) l_size ) ++#define octapi_llm_list_init( l, number_of_items, number_of_lists, user_info_size ) OctApiLlmListInit( (PVOID*) l,(UINT32) number_of_items,(UINT32) number_of_lists,(UINT32) user_info_size ) ++#define octapi_llm_list_info( l, allocated_lists, allocated_items, free_lists, free_items ) OctApiLlmListInfo( (PVOID) l,(PUINT32) allocated_lists,(PUINT32) allocated_items,(PUINT32) free_lists,(PUINT32) free_items ) ++#define octapi_llm_list_create( l, list_handle ) OctApiLlmListCreate( (PVOID) l,(PUINT32) list_handle ) ++#define octapi_llm_list_create_full( l, list_length, plist_handle ) OctApiLlmListCreateFull( (PVOID) l, (UINT32) list_length, (PUINT32) plist_handle ) ++#define octapi_llm_list_append_items( l, list_handle, num_items ) OctApiLlmListAppendItems( (PVOID) l, (UINT32) list_handle, (UINT32) num_items ) ++#define octapi_llm_list_append_and_set_items( l, list_handle, num_items, data_list ) OctApiLlmListAppendAndSetItems( (PVOID) l, (UINT32) list_handle, (UINT32) num_items, (PVOID) data_list ) ++#define octapi_llm_list_delete( l, list_handle ) OctApiLlmListDelete( (PVOID) l,(UINT32) list_handle ) ++#define octapi_llm_list_length( l, list_handle, number_of_items_in_list ) OctApiLlmListLength( (PVOID) l,(UINT32) list_handle, (PUINT32) number_of_items_in_list ) ++#define octapi_llm_list_insert_item( l, list_handle, item_number, item_data_pnt ) OctApiLlmListInsertItem( (PVOID) l,(UINT32) list_handle,(UINT32) item_number,(PVOID*) item_data_pnt ) ++#define octapi_llm_list_remove_item( l, list_handle, item_number ) OctApiLlmListRemoveItem( (PVOID) l,(UINT32) list_handle,(UINT32) item_number ) ++#define octapi_llm_list_item_data( l, list_handle, item_number, item_data_pnt ) OctApiLlmListItemData( (PVOID) l,(UINT32) list_handle,(UINT32) item_number,(PVOID*) item_data_pnt ) ++#define octapi_llm_list_copy_data( l, list_handle, start_item, data_length, pdata_list ) OctApiLlmListCopyData( (PVOID) l, (UINT32) list_handle, (UINT32) start_item, (UINT32) data_length, (PVOID) pdata_list ) ++#define octapi_llm_list_set_items( l, list_handle, start_item, data_length, pdata_list ) OctApiLlmListSetItems( (PVOID) l, (UINT32) list_handle, (UINT32) start_item, (UINT32) data_length, (PVOID) pdata_list ) ++ ++/* Alloc man. */ ++UINT32 OctapiLlmAllocGetSize( UINT32 number_of_items,PUINT32 l_size ); ++UINT32 OctapiLlmAllocInit( PVOID* l,UINT32 number_of_items ); ++UINT32 OctapiLlmAllocInfo( PVOID l, PUINT32 allocated_items, PUINT32 available_items ); ++UINT32 OctapiLlmAllocAlloc( PVOID l, PUINT32 blocknum ); ++UINT32 OctapiLlmAllocDealloc( PVOID l,UINT32 blocknum ); ++ ++/* Time managed alloc man. */ ++UINT32 OctApiTllmAllocGetSize( UINT32 number_of_items, PUINT32 l_size ); ++UINT32 OctApiTllmAllocInit( PVOID* l, UINT32 number_of_items ); ++UINT32 OctApiTllmAllocInfo( PVOID l, PUINT32 allocated_items, PUINT32 available_items ); ++UINT32 OctApiTllmAllocAlloc( PVOID l, PUINT32 blocknum, UINT32 current_time[2] ); ++UINT32 OctApiTllmAllocDealloc( PVOID l, UINT32 blocknum, UINT32 timeout_value, UINT32 current_time[2] ); ++ ++/* List man. */ ++UINT32 OctApiLlmListGetSize( UINT32 number_of_items, UINT32 number_of_lists, UINT32 user_info_size, PUINT32 l_size ); ++UINT32 OctApiLlmListInit( PVOID* l, UINT32 number_of_items, UINT32 number_of_lists, UINT32 user_info_size ); ++UINT32 OctApiLlmListInfo( PVOID l, PUINT32 allocated_lists, PUINT32 allocated_items, PUINT32 free_lists, PUINT32 free_items ); ++UINT32 OctApiLlmListCreate( PVOID l, PUINT32 list_handle ); ++UINT32 OctApiLlmListCreateFull( PVOID l, UINT32 list_length, UINT32* plist_handle ); ++UINT32 OctApiLlmListAppendItems( PVOID l, UINT32 list_handle, UINT32 num_items ); ++UINT32 OctApiLlmListAppendAndSetItems( PVOID l, UINT32 list_handle, UINT32 num_items, PVOID data_list ); ++UINT32 OctApiLlmListDelete( PVOID l, UINT32 list_handle ); ++UINT32 OctApiLlmListLength( PVOID l, UINT32 list_handle, PUINT32 number_of_items_in_list ); ++UINT32 OctApiLlmListInsertItem( PVOID l, UINT32 list_handle, UINT32 item_number, PVOID* item_data_pnt ); ++UINT32 OctApiLlmListRemoveItem( PVOID l, UINT32 list_handle, UINT32 item_number ); ++UINT32 OctApiLlmListItemData( PVOID l, UINT32 list_handle, UINT32 item_number, PVOID* item_data_pnt ); ++UINT32 OctApiLlmListCopyData( PVOID l, UINT32 list_handle, UINT32 start_item, UINT32 data_length, PVOID pdata_list ); ++UINT32 OctApiLlmListSetItems( PVOID l, UINT32 list_handle, UINT32 start_item, UINT32 data_length, PVOID pdata_list ); ++ ++/* Second list manager using a key to order info in the list. */ ++UINT32 OctApiLlm2ListGetSize( UINT32 number_of_items, UINT32 number_of_lists, UINT32 user_info_size, PUINT32 l_size ); ++UINT32 OctApiLlm2ListInit( PVOID* l,UINT32 number_of_items, UINT32 number_of_lists, UINT32 user_info_size ); ++UINT32 OctApiLlm2ListCreate( PVOID l, PUINT32 list_handle ); ++UINT32 OctApiLlm2ListLength( PVOID l, UINT32 list_handle, PUINT32 number_of_items_in_list ); ++UINT32 OctApiLlm2ListInsertItem(void * l, UINT32 list_handle, UINT32 item_key, void ** item_data_pnt, void ** prev_item_data_pnt, void ** prev_prev_item_data_pnt, PUINT32 insert_status_pnt ); ++UINT32 OctApiLlm2ListRemoveItem(void * l, UINT32 list_handle, UINT32 item_key, PUINT32 prev_item_key_pnt, PUINT32 prev_prev_item_key_pnt, PUINT32 remove_status_pnt ); ++UINT32 OctApiLlm2ListItemData( PVOID l, UINT32 list_handle, UINT32 item_key, PVOID* item_data_pnt, PUINT32 item_number ); ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* __OCTAPI_LLMAN_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/digium_unused.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/digium_unused.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/digium_unused.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/digium_unused.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,297 @@ ++/* Define macros here to suppress functions from the API being built */ ++ ++#if 1 ++ ++#define SKIP_Oct6100AdpcmChanOpenDef 1 ++#define SKIP_Oct6100AdpcmChanOpen 1 ++#define SKIP_Oct6100AdpcmChanCloseDef 1 ++#define SKIP_Oct6100AdpcmChanClose 1 ++#define SKIP_Oct6100AdpcmChanOpenSer 1 ++#define SKIP_Oct6100ApiCheckAdpcmChanParams 1 ++#define SKIP_Oct6100ApiReserveAdpcmChanResources 1 ++#define SKIP_Oct6100ApiWriteAdpcmChanStructs 1 ++#define SKIP_Oct6100ApiUpdateAdpcmChanEntry 1 ++#define SKIP_Oct6100AdpcmChanCloseSer 1 ++#define SKIP_Oct6100ApiAssertAdpcmChanParams 1 ++#define SKIP_Oct6100ApiInvalidateAdpcmChanStructs 1 ++#define SKIP_Oct6100ApiReleaseAdpcmChanResources 1 ++#define SKIP_Oct6100ApiReserveAdpcmChanEntry 1 ++#define SKIP_Oct6100ApiReleaseAdpcmChanEntry 1 ++#define SKIP_Oct6100ChannelCloseDef 1 ++#define SKIP_Oct6100ChannelClose 1 ++#define SKIP_Oct6100ChannelCreateBiDirDef 1 ++#define SKIP_Oct6100ChannelCreateBiDir 1 ++#define SKIP_Oct6100ChannelDestroyBiDirDef 1 ++#define SKIP_Oct6100ChannelDestroyBiDir 1 ++#define SKIP_Oct6100ChannelBroadcastTsstAddDef 1 ++#define SKIP_Oct6100ChannelBroadcastTsstAdd 1 ++#define SKIP_Oct6100ChannelBroadcastTsstRemove 1 ++#define SKIP_Oct6100ChannelGetStatsDef 1 ++#define SKIP_Oct6100ChannelGetStats 1 ++#define SKIP_Oct6100ChannelMuteDef 1 ++#define SKIP_Oct6100ChannelMute 1 ++#define SKIP_Oct6100ChannelUnMuteDef 1 ++#define SKIP_Oct6100ChannelUnMute 1 ++#define SKIP_Oct6100ChannelCloseSer 1 ++#define SKIP_Oct6100ApiAssertChannelParams 1 ++#define SKIP_Oct6100ApiInvalidateChannelStructs 1 ++#define SKIP_Oct6100ApiReleaseChannelResources 1 ++#define SKIP_Oct6100ChannelBroadcastTsstAddSer 1 ++#define SKIP_Oct6100ApiCheckChanTsstAddParams 1 ++#define SKIP_Oct6100ApiReserveTsstAddResources 1 ++#define SKIP_Oct6100ApiWriteTsstAddStructs 1 ++#define SKIP_Oct6100ApiUpdateTsstAddChanEntry 1 ++#define SKIP_Oct6100ApiChannelGetStatsSer 1 ++#define SKIP_Oct6100ApiReserveBiDirChanEntry 1 ++#define SKIP_Oct6100ApiReleaseBiDirChanEntry 1 ++#define SKIP_Oct6100ApiRetrieveNlpConfDword 1 ++#define SKIP_Oct6100ApiSaveNlpConfDword 1 ++#define SKIP_Oct6100ChannelCreateBiDirSer 1 ++#define SKIP_Oct6100ApiCheckChannelCreateBiDirParams 1 ++#define SKIP_Oct6100ApiReserveChannelCreateBiDirResources 1 ++#define SKIP_Oct6100ApiWriteChannelCreateBiDirStructs 1 ++#define SKIP_Oct6100ApiUpdateBiDirChannelEntry 1 ++#define SKIP_Oct6100ChannelDestroyBiDirSer 1 ++#define SKIP_Oct6100ApiAssertDestroyBiDirChanParams 1 ++#define SKIP_Oct6100ApiInvalidateBiDirChannelStructs 1 ++#define SKIP_Oct6100ApiReleaseBiDirChannelResources 1 ++#define SKIP_Oct6100ApiOctFloatToDbEnergyByte 1 ++#define SKIP_Oct6100ApiOctFloatToDbEnergyHalf 1 ++#define SKIP_Oct6100ChannelMuteSer 1 ++#define SKIP_Oct6100ApiAssertChannelMuteParams 1 ++#define SKIP_Oct6100ChannelUnMuteSer 1 ++#define SKIP_Oct6100ApiAssertChannelUnMuteParams 1 ++#define SKIP_Oct6100ApiMuteSinWithFeatures 1 ++#define SKIP_Oct6100ApiMuteChannelPorts 1 ++#define SKIP_Oct6100CreateLocalInstanceDef 1 ++#define SKIP_Oct6100CreateLocalInstance 1 ++#define SKIP_Oct6100DestroyLocalInstanceDef 1 ++#define SKIP_Oct6100DestroyLocalInstance 1 ++#define SKIP_Oct6100GetHwRevisionDef 1 ++#define SKIP_Oct6100GetHwRevision 1 ++#define SKIP_Oct6100FreeResourcesDef 1 ++#define SKIP_Oct6100FreeResources 1 ++#define SKIP_Oct6100ProductionBistDef 1 ++#define SKIP_Oct6100ProductionBist 1 ++#define SKIP_Oct6100ApiGetVersionDef 1 ++#define SKIP_Oct6100ApiGetVersion 1 ++#define SKIP_Oct6100FreeResourcesSer 1 ++#define SKIP_Oct6100ProductionBistSer 1 ++#define SKIP_Oct6100ChipGetStatsDef 1 ++#define SKIP_Oct6100ChipGetStats 1 ++#define SKIP_Oct6100ChipGetImageInfoDef 1 ++#define SKIP_Oct6100ChipGetImageInfo 1 ++#define SKIP_Oct6100ChipGetStatsSer 1 ++#define SKIP_Oct6100ConfBridgeOpenDef 1 ++#define SKIP_Oct6100ConfBridgeOpen 1 ++#define SKIP_Oct6100ConfBridgeClose 1 ++#define SKIP_Oct6100ConfBridgeChanAddDef 1 ++#define SKIP_Oct6100ConfBridgeChanAdd 1 ++#define SKIP_Oct6100ConfBridgeChanRemove 1 ++#define SKIP_Oct6100ConfBridgeChanMuteDef 1 ++#define SKIP_Oct6100ConfBridgeChanMute 1 ++#define SKIP_Oct6100ConfBridgeChanUnMuteDef 1 ++#define SKIP_Oct6100ConfBridgeChanUnMute 1 ++#define SKIP_Oct6100ConfBridgeDominantSpeakerSetDef 1 ++#define SKIP_Oct6100ConfBridgeDominantSpeakerSet 1 ++#define SKIP_Oct6100ConfBridgeMaskChangeDef 1 ++#define SKIP_Oct6100ConfBridgeMaskChange 1 ++#define SKIP_Oct6100ConfBridgeGetStatsDef 1 ++#define SKIP_Oct6100ConfBridgeGetStats 1 ++#define SKIP_Oct6100ConfBridgeOpenSer 1 ++#define SKIP_Oct6100ApiCheckBridgeParams 1 ++#define SKIP_Oct6100ApiReserveBridgeResources 1 ++#define SKIP_Oct6100ApiUpdateBridgeEntry 1 ++#define SKIP_Oct6100ConfBridgeChanAddSer 1 ++#define SKIP_Oct6100ApiCheckBridgeAddParams 1 ++#define SKIP_Oct6100ApiReserveBridgeAddResources 1 ++#define SKIP_Oct6100ApiBridgeEventAdd 1 ++#define SKIP_Oct6100ApiBridgeAddParticipantToChannel 1 ++#define SKIP_Oct6100ConfBridgeChanMuteSer 1 ++#define SKIP_Oct6100ApiCheckBridgeMuteParams 1 ++#define SKIP_Oct6100ApiUpdateBridgeMuteResources 1 ++#define SKIP_Oct6100ConfBridgeChanUnMuteSer 1 ++#define SKIP_Oct6100ApiCheckBridgeUnMuteParams 1 ++#define SKIP_Oct6100ApiUpdateBridgeUnMuteResources 1 ++#define SKIP_Oct6100ConfBridgeDominantSpeakerSetSer 1 ++#define SKIP_Oct6100ApiCheckBridgeDominantSpeakerParams 1 ++#define SKIP_Oct6100ApiUpdateBridgeDominantSpeakerResources 1 ++#define SKIP_Oct6100ConfBridgeMaskChangeSer 1 ++#define SKIP_Oct6100ApiCheckBridgeMaskChangeParams 1 ++#define SKIP_Oct6100ApiUpdateMaskModifyResources 1 ++#define SKIP_Oct6100ApiBridgeUpdateMask 1 ++#define SKIP_Oct6100ConfBridgeGetStatsSer 1 ++#define SKIP_Oct6100ApiReserveBridgeEntry 1 ++#define SKIP_Oct6100ApiReserveFlexConfParticipantEntry 1 ++#define SKIP_Oct6100DebugSelectChannelDef 1 ++#define SKIP_Oct6100DebugSelectChannel 1 ++#define SKIP_Oct6100DebugGetDataDef 1 ++#define SKIP_Oct6100DebugGetData 1 ++#define SKIP_Oct6100DebugSelectChannelSer 1 ++#define SKIP_Oct6100DebugGetDataSer 1 ++#define SKIP_Oct6100BufferPlayoutGetEventDef 1 ++#define SKIP_Oct6100BufferPlayoutGetEvent 1 ++#define SKIP_Oct6100BufferPlayoutGetEventSer 1 ++#define SKIP_Oct6100InterruptConfigureDef 1 ++#define SKIP_Oct6100InterruptConfigure 1 ++#define SKIP_Oct6100ApiReserveBufferPlayoutMemoryNode 1 ++#define SKIP_Oct6100ApiReleaseBufferPlayoutMemoryNode 1 ++#define SKIP_Oct6100ApiReserveBufferPlayoutMemory 1 ++#define SKIP_Oct6100ApiReleaseBufferPlayoutMemory 1 ++#define SKIP_Oct6100ApiCreateFeatureMask 1 ++#define SKIP_Oct6100MixerCopyEventCreateDef 1 ++#define SKIP_Oct6100MixerCopyEventCreate 1 ++#define SKIP_Oct6100MixerCopyEventDestroyDef 1 ++#define SKIP_Oct6100MixerCopyEventDestroy 1 ++#define SKIP_Oct6100MixerCopyEventCreateSer 1 ++#define SKIP_Oct6100ApiCheckCopyEventCreateParams 1 ++#define SKIP_Oct6100ApiReserveCopyEventCreateResources 1 ++#define SKIP_Oct6100ApiWriteCopyEventCreateStructs 1 ++#define SKIP_Oct6100ApiUpdateCopyEventCreateEntry 1 ++#define SKIP_Oct6100MixerCopyEventDestroySer 1 ++#define SKIP_Oct6100ApiAssertCopyEventDestroyParams 1 ++#define SKIP_Oct6100ApiInvalidateCopyEventStructs 1 ++#define SKIP_Oct6100ApiReleaseCopyEventResources 1 ++#define SKIP_Oct6100ApiReserveCopyEventEntry 1 ++#define SKIP_Oct6100ApiReleaseCopyEventEntry 1 ++#define SKIP_Oct6100PhasingTsstOpenDef 1 ++#define SKIP_Oct6100PhasingTsstOpen 1 ++#define SKIP_Oct6100PhasingTsstCloseDef 1 ++#define SKIP_Oct6100PhasingTsstClose 1 ++#define SKIP_Oct6100PhasingTsstOpenSer 1 ++#define SKIP_Oct6100ApiCheckPhasingParams 1 ++#define SKIP_Oct6100ApiReservePhasingResources 1 ++#define SKIP_Oct6100ApiWritePhasingStructs 1 ++#define SKIP_Oct6100ApiUpdatePhasingEntry 1 ++#define SKIP_Oct6100PhasingTsstCloseSer 1 ++#define SKIP_Oct6100ApiAssertPhasingParams 1 ++#define SKIP_Oct6100ApiInvalidatePhasingStructs 1 ++#define SKIP_Oct6100ApiReleasePhasingResources 1 ++#define SKIP_Oct6100ApiReservePhasingEntry 1 ++#define SKIP_Oct6100ApiReleasePhasingEntry 1 ++#define SKIP_Oct6100BufferPlayoutLoadDef 1 ++#define SKIP_Oct6100BufferPlayoutLoad 1 ++#define SKIP_Oct6100BufferPlayoutLoadBlockInitDef 1 ++#define SKIP_Oct6100BufferPlayoutLoadBlockInit 1 ++#define SKIP_Oct6100BufferPlayoutLoadBlockDef 1 ++#define SKIP_Oct6100BufferPlayoutLoadBlock 1 ++#define SKIP_Oct6100BufferPlayoutUnloadDef 1 ++#define SKIP_Oct6100BufferPlayoutUnload 1 ++#define SKIP_Oct6100BufferPlayoutAddDef 1 ++#define SKIP_Oct6100BufferPlayoutAdd 1 ++#define SKIP_Oct6100BufferPlayoutStartDef 1 ++#define SKIP_Oct6100BufferPlayoutStart 1 ++#define SKIP_Oct6100BufferPlayoutStop 1 ++#define SKIP_Oct6100BufferLoadSer 1 ++#define SKIP_Oct6100BufferLoadBlockInitSer 1 ++#define SKIP_Oct6100BufferLoadBlockSer 1 ++#define SKIP_Oct6100ApiCheckBufferParams 1 ++#define SKIP_Oct6100ApiCheckBufferLoadBlockParams 1 ++#define SKIP_Oct6100ApiReserveBufferResources 1 ++#define SKIP_Oct6100ApiWriteBufferInMemory 1 ++#define SKIP_Oct6100ApiUpdateBufferEntry 1 ++#define SKIP_Oct6100BufferUnloadSer 1 ++#define SKIP_Oct6100ApiAssertBufferParams 1 ++#define SKIP_Oct6100ApiReleaseBufferResources 1 ++#define SKIP_Oct6100BufferPlayoutAddSer 1 ++#define SKIP_Oct6100ApiCheckPlayoutAddParams 1 ++#define SKIP_Oct6100ApiWriteBufferAddStructs 1 ++#define SKIP_Oct6100BufferPlayoutStartSer 1 ++#define SKIP_Oct6100ApiCheckPlayoutStartParams 1 ++#define SKIP_Oct6100ApiWriteChanPlayoutStructs 1 ++#define SKIP_Oct6100ApiReserveBufPlayoutListEntry 1 ++#define SKIP_Oct6100ApiReleaseBufPlayoutListEntry 1 ++#define SKIP_Oct6100RemoteDebugDef 1 ++#define SKIP_Oct6100RemoteDebug 1 ++#define SKIP_Oct6100ApiCheckEndianDetectField 1 ++#define SKIP_Oct6100ApiCalculateChecksum 1 ++#define SKIP_Oct6100ApiFormResponsePkt 1 ++#define SKIP_Oct6100ApiCheckPktCommands 1 ++#define SKIP_Oct6100ApiExecutePktCommands 1 ++#define SKIP_Oct6100ApiCheckSessionNum 1 ++#define SKIP_Oct6100ApiRpcReadWord 1 ++#define SKIP_Oct6100ApiRpcReadBurst 1 ++#define SKIP_Oct6100ApiRpcReadArray 1 ++#define SKIP_Oct6100ApiRpcWriteWord 1 ++#define SKIP_Oct6100ApiRpcWriteSmear 1 ++#define SKIP_Oct6100ApiRpcWriteBurst 1 ++#define SKIP_Oct6100ApiRpcSetHotChannel 1 ++#define SKIP_Oct6100ApiRpcGetDebugChanIndex 1 ++#define SKIP_Oct6100ApiRpcDisconnect 1 ++#define SKIP_Oct6100ToneDetectionDisable 1 ++#define SKIP_Oct6100TsiCnctOpenDef 1 ++#define SKIP_Oct6100TsiCnctOpen 1 ++#define SKIP_Oct6100TsiCnctCloseDef 1 ++#define SKIP_Oct6100TsiCnctClose 1 ++#define SKIP_Oct6100TsiCnctOpenSer 1 ++#define SKIP_Oct6100ApiCheckTsiParams 1 ++#define SKIP_Oct6100ApiReserveTsiResources 1 ++#define SKIP_Oct6100ApiWriteTsiStructs 1 ++#define SKIP_Oct6100ApiUpdateTsiEntry 1 ++#define SKIP_Oct6100TsiCnctCloseSer 1 ++#define SKIP_Oct6100ApiAssertTsiParams 1 ++#define SKIP_Oct6100ApiInvalidateTsiStructs 1 ++#define SKIP_Oct6100ApiReleaseTsiResources 1 ++#define SKIP_Oct6100ApiReserveTsiCnctEntry 1 ++#define SKIP_Oct6100ApiReleaseTsiCnctEntry 1 ++#define SKIP_Oct6100UserDriverWriteOs 1 ++#define SKIP_Oct6100UserDriverWriteSmearOs 1 ++#define SKIP_Oct6100UserDriverWriteBurstOs 1 ++#define SKIP_Oct6100UserDriverReadOs 1 ++#define SKIP_Oct6100UserDriverReadBurstOs 1 ++#define SKIP_OctApiBt0AddNode 1 ++#define SKIP_OctApiBt0AddNode2 1 ++#define SKIP_OctApiBt0AddNode3 1 ++#define SKIP_OctApiBt0AddNode4 1 ++#define SKIP_OctApiBt0KeyCompare 1 ++#define SKIP_OctApiBt0UpdateLinkDepth 1 ++#define SKIP_OctApiBt0Rebalance 1 ++#define SKIP_OctApiBt0ExternalHeavy 1 ++#define SKIP_OctApiBt0RemoveNode2 1 ++#define SKIP_OctApiBt0RemoveNode3 1 ++#define SKIP_OctApiBt0RemoveNode 1 ++#define SKIP_OctApiBt0QueryNode2 1 ++#define SKIP_OctApiBt0QueryNode 1 ++#define SKIP_OctApiBt0GetFirstNode 1 ++#define SKIP_OctApiBt0FindOrAddNode 1 ++#define SKIP_OctApiBt0AddNodeReportPrevNodeData 1 ++#define SKIP_OctApiLmCompare 1 ++#define SKIP_OctApiLmMultiply 1 ++#define SKIP_OctApiLmDivide 1 ++#define SKIP_OctApiLmShiftRight1 1 ++#define SKIP_OctApiLmShiftn 1 ++#define SKIP_OctApiLmGetMsb 1 ++#define SKIP_OctApiTllmAllocGetSize 1 ++#define SKIP_OctApiTllmAllocInit 1 ++#define SKIP_OctApiTllmAllocInfo 1 ++#define SKIP_OctApiTllmAllocAlloc 1 ++#define SKIP_OctApiTllmAllocDealloc 1 ++#define SKIP_OctApiTllmCheckTimeoutList 1 ++#define SKIP_OctApiLlmListGetSize 1 ++#define SKIP_OctApiLlmListGetItemPointer 1 ++#define SKIP_OctApiLlmListInit 1 ++#define SKIP_OctApiLlmListInfo 1 ++#define SKIP_OctApiLlmListCreate 1 ++#define SKIP_OctApiLlmListDelete 1 ++#define SKIP_OctApiLlmListLength 1 ++#define SKIP_OctApiLlmListItemData 1 ++#define SKIP_OctApiLlmListInsertItem 1 ++#define SKIP_OctApiLlmListCreateFull 1 ++#define SKIP_OctApiLlmListAppendItems 1 ++#define SKIP_OctApiLlmListAppendAndSetItems 1 ++#define SKIP_OctApiLlmListSetItems 1 ++#define SKIP_OctApiLlmListCopyData 1 ++#define SKIP_OctApiLlmListRemoveItem 1 ++#define SKIP_OctApiLlm2ListGetSize 1 ++#define SKIP_OctApiLlm2ListGetItemPointer 1 ++#define SKIP_OctApiLlm2ListInit 1 ++#define SKIP_OctApiLlm2ListCreate 1 ++#define SKIP_OctApiLlm2ListDelete 1 ++#define SKIP_OctApiLlm2ListLength 1 ++#define SKIP_OctApiLlm2ListItemData 1 ++#define SKIP_OctApiLlm2ListInsertItem 1 ++#define SKIP_OctApiLlm2ListRemoveItem 1 ++#define SKIP_OctApiLlmMemCpy 1 ++ ++#endif ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_inst.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,74 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_adpcm_chan_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_adpcm_chan.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_adpcm_chan_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 6 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_ADPCM_CHAN_INST_H__ ++#define __OCT6100_ADPCM_CHAN_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_ADPCM_CHAN_ ++{ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved; ++ ++ /* Count used to manage entry handles allocated to user. */ ++ UINT8 byEntryOpenCnt; ++ ++ /* TSI chariot memory entry. */ ++ UINT16 usTsiMemIndex; ++ ++ /* ADPCM memory entry. */ ++ UINT16 usAdpcmMemIndex; ++ ++ /* Input and output timeslot information. */ ++ UINT16 usInputTimeslot; ++ UINT16 usInputStream; ++ UINT8 byInputNumTssts; ++ UINT8 byInputPcmLaw; ++ ++ UINT16 usOutputTimeslot; ++ UINT16 usOutputStream; ++ UINT8 byOutputNumTssts; ++ UINT8 byOutputPcmLaw; ++ ++ /* Internal info for quick access to structures associated to this TSI cnct. */ ++ UINT16 usInputTsstIndex; ++ UINT16 usOutputTsstIndex; ++ ++} tOCT6100_API_ADPCM_CHAN, *tPOCT6100_API_ADPCM_CHAN; ++ ++#endif /* __OCT6100_ADPCM_CHAN_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_pub.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,90 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_adpcm_chan_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_adpcm_chan.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_adpcm_chan_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 5 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_ADPCM_CHAN_PUB_H__ ++#define __OCT6100_ADPCM_CHAN_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_ADPCM_CHAN_OPEN_ ++{ ++ PUINT32 pulChanHndl; ++ ++ UINT32 ulInputTimeslot; ++ UINT32 ulInputStream; ++ UINT32 ulInputNumTssts; ++ UINT32 ulInputPcmLaw; ++ ++ UINT32 ulOutputTimeslot; ++ UINT32 ulOutputStream; ++ UINT32 ulOutputNumTssts; ++ UINT32 ulOutputPcmLaw; ++ ++ UINT32 ulChanMode; /* Encoding or decoding. */ ++ ++ UINT32 ulEncodingRate; ++ UINT32 ulDecodingRate; ++ ++ UINT32 ulAdpcmNibblePosition; ++ ++} tOCT6100_ADPCM_CHAN_OPEN, *tPOCT6100_ADPCM_CHAN_OPEN; ++ ++typedef struct _OCT6100_ADPCM_CHAN_CLOSE_ ++{ ++ UINT32 ulChanHndl; ++ ++} tOCT6100_ADPCM_CHAN_CLOSE, *tPOCT6100_ADPCM_CHAN_CLOSE; ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++ ++UINT32 Oct6100AdpcmChanOpenDef( ++ OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ); ++UINT32 Oct6100AdpcmChanOpen( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ); ++ ++UINT32 Oct6100AdpcmChanCloseDef( ++ OUT tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose ); ++UINT32 Oct6100AdpcmChanClose( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose ); ++ ++#endif /* __OCT6100_ADPCM_CHAN_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_api.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_api.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_api.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_api.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,84 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_api.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Header file containing all definitions used throughout the API. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 23 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_API_H__ ++#define __OCT6100_API_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100_defines.h" ++#include "oct6100_errors.h" ++ ++#include "oct6100_apiud.h" ++#include "oct6100_tlv_inst.h" ++#include "oct6100_chip_stats_inst.h" ++#include "oct6100_tsi_cnct_inst.h" ++#include "oct6100_mixer_inst.h" ++#include "oct6100_events_inst.h" ++#include "oct6100_tone_detection_inst.h" ++#include "oct6100_conf_bridge_inst.h" ++#include "oct6100_playout_buf_inst.h" ++ ++#include "oct6100_adpcm_chan_inst.h" ++#include "oct6100_phasing_tsst_inst.h" ++#include "oct6100_channel_inst.h" ++#include "oct6100_interrupts_inst.h" ++#include "oct6100_remote_debug_inst.h" ++#include "oct6100_debug_inst.h" ++#include "oct6100_chip_open_inst.h" ++#include "oct6100_api_inst.h" ++ ++#include "oct6100_interrupts_pub.h" ++#include "oct6100_tsi_cnct_pub.h" ++#include "oct6100_events_pub.h" ++#include "oct6100_tone_detection_pub.h" ++#include "oct6100_mixer_pub.h" ++#include "oct6100_conf_bridge_pub.h" ++#include "oct6100_playout_buf_pub.h" ++ ++#include "oct6100_channel_pub.h" ++#include "oct6100_remote_debug_pub.h" ++#include "oct6100_debug_pub.h" ++#include "oct6100_chip_open_pub.h" ++#include "oct6100_chip_stats_pub.h" ++#include "oct6100_adpcm_chan_pub.h" ++#include "oct6100_phasing_tsst_pub.h" ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __OCT6100_API_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_api_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_api_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_api_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_api_inst.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,138 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_api_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing the definition of the API instance structure. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 40 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_API_INST_H__ ++#define __OCT6100_API_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_SHARED_INFO_ ++{ ++ /* Local copy of chip configuration structure. */ ++ tOCT6100_API_CHIP_CONFIG ChipConfig; ++ ++ /* Miscellaneous calculations and mapping of static structures in external memory. */ ++ tOCT6100_API_MISCELLANEOUS MiscVars; ++ tOCT6100_API_MEMORY_MAP MemoryMap; ++ ++ /* Error stats structure. */ ++ tOCT6100_API_CHIP_ERROR_STATS ErrorStats; ++ tOCT6100_API_CHIP_STATS ChipStats; ++ ++ /* Mixer information. */ ++ tOCT6100_API_MIXER MixerInfo; ++ ++ /* Image breakdown information. */ ++ tOCT6100_API_IMAGE_REGION ImageRegion[ cOCT6100_MAX_IMAGE_REGION ]; ++ tOCT6100_API_IMAGE_INFO ImageInfo; ++ ++ /* Configuration and management of interrupts. */ ++ tOCT6100_API_INTRPT_CONFIG IntrptConfig; ++ tOCT6100_API_INTRPT_MANAGE IntrptManage; ++ /* Remote debugging. */ ++ tOCT6100_API_REMOTE_DEBUG_INFO RemoteDebugInfo; ++ /* Chip debugging information. */ ++ tOCT6100_API_DEBUG DebugInfo; ++ ++ /* Management variables of software and hardware buffers. */ ++ tOCT6100_API_SOFT_BUFS SoftBufs; ++ ++ /* Caller buffer playout memory management structure. */ ++ tOCT6100_API_BUFFER_PLAYOUT_MALLOC_INFO PlayoutInfo; ++ ++ ++ ++ UINT32 ulChannelListOfst; ++ UINT32 ulChannelAllocOfst; ++ ++ UINT32 ulConversionMemoryAllocOfst; ++ ++ UINT32 ulTsiMemoryAllocOfst; ++ UINT32 ulExtraTsiMemoryAllocOfst; ++ UINT32 ulEchoMemoryAllocOfst; ++ ++ UINT32 ulTsstAllocOfst; ++ UINT32 ulTsstListOfst; ++ UINT32 ulTsstListAllocOfst; ++ ++ UINT32 ulTsiCnctListOfst; ++ UINT32 ulTsiCnctAllocOfst; ++ ++ UINT32 ulMixerEventListOfst; ++ UINT32 ulMixerEventAllocOfst; ++ ++ UINT32 ulCopyEventListOfst; ++ UINT32 ulCopyEventAllocOfst; ++ ++ UINT32 ulBiDirChannelListOfst; ++ UINT32 ulBiDirChannelAllocOfst; ++ ++ UINT32 ulConfBridgeListOfst; ++ UINT32 ulConfBridgeAllocOfst; ++ ++ UINT32 ulFlexConfParticipantListOfst; ++ UINT32 ulFlexConfParticipantAllocOfst; ++ ++ UINT32 ulPlayoutBufListOfst; ++ UINT32 ulPlayoutBufAllocOfst; ++ UINT32 ulPlayoutBufMemoryNodeListOfst; ++ ++ ++ ++ UINT32 ulAdpcmChanListOfst; ++ UINT32 ulAdpcmChanAllocOfst; ++ ++ UINT32 ulPhasingTsstListOfst; ++ UINT32 ulPhasingTsstAllocOfst; ++ ++} tOCT6100_SHARED_INFO, *tPOCT6100_SHARED_INFO; ++ ++typedef struct _OCT6100_INSTANCE_API_ ++{ ++ /* Pointer to portion of API instance structure shared amongst all processes. */ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ /* Pointer to user-supplied, process context structure. The structure is ++ a parameter to all user-supplied functions. */ ++ PVOID pProcessContext; ++ ++ /* Handles to all serialization objects used by the API. */ ++ tOCT6100_USER_SERIAL_OBJECT ulApiSerObj; ++ ++ ++} tOCT6100_INSTANCE_API, *tPOCT6100_INSTANCE_API; ++ ++#endif /* __OCT6100_API_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_apimi.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_apimi.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_apimi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_apimi.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,69 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_apimi.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the declaration of all functions exported from the ++ APIMI block. The APIMI block contains only one function: ++ Oct6100InterruptMask. ++ The function is used to mask out the interrupt pin of the chip. This ++ function is used when a deferred procedure call treats the interrupt (new ++ interrupts must not be generated until the signalled interrupt is treated). ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 6 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_APIMI_H__ ++#define __OCT6100_APIMI_H__ ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif /* __cplusplus */ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_INTERRUPT_MASK_ ++{ ++ UINT32 ulUserChipIndex; ++ PVOID pProcessContext; ++ ++ ++} tOCT6100_INTERRUPT_MASK, *tPOCT6100_INTERRUPT_MASK; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100InterruptMaskDef( ++ OUT tPOCT6100_INTERRUPT_MASK f_pInterruptMask ); ++UINT32 Oct6100InterruptMask( ++ IN tPOCT6100_INTERRUPT_MASK f_pInterruptMask ); ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* __OCT6100_APIMI_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_apiud.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_apiud.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_apiud.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_apiud.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,312 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_apiud.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Header file containing the definitions and prototypes that are to be ++ completed by the user. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 16 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_APIUD_H__ ++#define __OCT6100_APIUD_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/* Determines the maximum length of a burst of reads/writes. This value must ++ be in the range 8 - 1024. This value obtains best performance if set to ++ a power of 2 (i.e. 2^n). */ ++#define cOCT6100_MAX_RW_ACCESSES 32 ++ ++/* The define used to specify that the Oct6100SeizeSerializeObject function ++ is not to return until the specified serialization object has been seized. */ ++#define cOCT6100_WAIT_INFINITELY 0xFFFFFFFF ++ ++ ++/* Compile option: enabling this compile option inserts code to check every ++ call to a user provided function to make sure the function parameters ++ are not changed, as required by the API specification. */ ++#define cOCT6100_USER_FUNCTION_CHECK ++ ++ ++ ++#define cOCT6100_GET_TIME_FAILED_0 0xFFFF0000 ++#define cOCT6100_GET_TIME_FAILED_1 0xFFFF0001 ++#define cOCT6100_GET_TIME_FAILED_2 0xFFFF0002 ++#define cOCT6100_GET_TIME_FAILED_3 0xFFFF0003 ++#define cOCT6100_GET_TIME_FAILED_4 0xFFFF0004 ++ ++#define cOCT6100_CREATE_SERIAL_FAILED_0 0xFFFF0010 ++#define cOCT6100_CREATE_SERIAL_FAILED_1 0xFFFF0011 ++#define cOCT6100_CREATE_SERIAL_FAILED_2 0xFFFF0012 ++#define cOCT6100_CREATE_SERIAL_FAILED_3 0xFFFF0013 ++#define cOCT6100_CREATE_SERIAL_FAILED_4 0xFFFF0014 ++ ++#define cOCT6100_DESTROY_SERIAL_FAILED_0 0xFFFF0020 ++#define cOCT6100_DESTROY_SERIAL_FAILED_1 0xFFFF0021 ++#define cOCT6100_DESTROY_SERIAL_FAILED_2 0xFFFF0022 ++#define cOCT6100_DESTROY_SERIAL_FAILED_3 0xFFFF0023 ++#define cOCT6100_DESTROY_SERIAL_FAILED_4 0xFFFF0024 ++ ++#define cOCT6100_INVALID_SERIAL_HANDLE_0 0xFFFF0030 ++#define cOCT6100_INVALID_SERIAL_HANDLE_1 0xFFFF0031 ++#define cOCT6100_INVALID_SERIAL_HANDLE_2 0xFFFF0032 ++#define cOCT6100_INVALID_SERIAL_HANDLE_3 0xFFFF0033 ++#define cOCT6100_INVALID_SERIAL_HANDLE_4 0xFFFF0034 ++ ++#define cOCT6100_RELEASE_SERIAL_FAILED_0 0xFFFF0040 ++#define cOCT6100_RELEASE_SERIAL_FAILED_1 0xFFFF0041 ++#define cOCT6100_RELEASE_SERIAL_FAILED_2 0xFFFF0042 ++#define cOCT6100_RELEASE_SERIAL_FAILED_3 0xFFFF0043 ++#define cOCT6100_RELEASE_SERIAL_FAILED_4 0xFFFF0044 ++ ++#define cOCT6100_SEIZE_SERIAL_FAILED_0 0xFFFF0050 ++#define cOCT6100_SEIZE_SERIAL_FAILED_1 0xFFFF0051 ++#define cOCT6100_SEIZE_SERIAL_FAILED_2 0xFFFF0052 ++#define cOCT6100_SEIZE_SERIAL_FAILED_3 0xFFFF0053 ++#define cOCT6100_SEIZE_SERIAL_FAILED_4 0xFFFF0054 ++ ++#define cOCT6100_DRIVER_WRITE_FAILED_0 0xFFFF0060 ++#define cOCT6100_DRIVER_WRITE_FAILED_1 0xFFFF0061 ++#define cOCT6100_DRIVER_WRITE_FAILED_2 0xFFFF0062 ++#define cOCT6100_DRIVER_WRITE_FAILED_3 0xFFFF0063 ++#define cOCT6100_DRIVER_WRITE_FAILED_4 0xFFFF0064 ++ ++#define cOCT6100_DRIVER_WSMEAR_FAILED_0 0xFFFF0070 ++#define cOCT6100_DRIVER_WSMEAR_FAILED_1 0xFFFF0071 ++#define cOCT6100_DRIVER_WSMEAR_FAILED_2 0xFFFF0072 ++#define cOCT6100_DRIVER_WSMEAR_FAILED_3 0xFFFF0073 ++#define cOCT6100_DRIVER_WSMEAR_FAILED_4 0xFFFF0074 ++ ++#define cOCT6100_DRIVER_WBURST_FAILED_0 0xFFFF0080 ++#define cOCT6100_DRIVER_WBURST_FAILED_1 0xFFFF0081 ++#define cOCT6100_DRIVER_WBURST_FAILED_2 0xFFFF0082 ++#define cOCT6100_DRIVER_WBURST_FAILED_3 0xFFFF0083 ++#define cOCT6100_DRIVER_WBURST_FAILED_4 0xFFFF0084 ++ ++#define cOCT6100_DRIVER_READ_FAILED_0 0xFFFF0090 ++#define cOCT6100_DRIVER_READ_FAILED_1 0xFFFF0091 ++#define cOCT6100_DRIVER_READ_FAILED_2 0xFFFF0092 ++#define cOCT6100_DRIVER_READ_FAILED_3 0xFFFF0093 ++#define cOCT6100_DRIVER_READ_FAILED_4 0xFFFF0094 ++ ++#define cOCT6100_DRIVER_RBURST_FAILED_0 0xFFFF00A0 ++#define cOCT6100_DRIVER_RBURST_FAILED_1 0xFFFF00A1 ++#define cOCT6100_DRIVER_RBURST_FAILED_2 0xFFFF00A2 ++#define cOCT6100_DRIVER_RBURST_FAILED_3 0xFFFF00A3 ++#define cOCT6100_DRIVER_RBURST_FAILED_4 0xFFFF00A4 ++ ++ ++ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++/*Change this type if your platform uses 64bits semaphores/locks */ ++typedef void* tOCT6100_USER_SERIAL_OBJECT; ++ ++typedef struct _OCT6100_GET_TIME_ ++{ ++ PVOID pProcessContext; ++ UINT32 aulWallTimeUs[ 2 ]; ++ ++} tOCT6100_GET_TIME, *tPOCT6100_GET_TIME; ++ ++ ++ ++ ++ ++typedef struct _OCT6100_CREATE_SERIALIZE_OBJECT_ ++{ ++ PVOID pProcessContext; ++ PSZ pszSerialObjName; ++ tOCT6100_USER_SERIAL_OBJECT ulSerialObjHndl; ++ ++} tOCT6100_CREATE_SERIALIZE_OBJECT, *tPOCT6100_CREATE_SERIALIZE_OBJECT; ++ ++ ++typedef struct _OCT6100_DESTROY_SERIALIZE_OBJECT_ ++{ ++ PVOID pProcessContext; ++ tOCT6100_USER_SERIAL_OBJECT ulSerialObjHndl; ++ ++} tOCT6100_DESTROY_SERIALIZE_OBJECT, *tPOCT6100_DESTROY_SERIALIZE_OBJECT; ++ ++ ++typedef struct _OCT6100_SEIZE_SERIALIZE_OBJECT_ ++{ ++ PVOID pProcessContext; ++ tOCT6100_USER_SERIAL_OBJECT ulSerialObjHndl; ++ UINT32 ulTryTimeMs; ++ ++} tOCT6100_SEIZE_SERIALIZE_OBJECT, *tPOCT6100_SEIZE_SERIALIZE_OBJECT; ++ ++ ++typedef struct _OCT6100_RELEASE_SERIALIZE_OBJECT_ ++{ ++ PVOID pProcessContext; ++ tOCT6100_USER_SERIAL_OBJECT ulSerialObjHndl; ++ ++} tOCT6100_RELEASE_SERIALIZE_OBJECT, *tPOCT6100_RELEASE_SERIALIZE_OBJECT; ++ ++ ++typedef struct _OCT6100_WRITE_PARAMS_ ++{ ++ PVOID pProcessContext; ++ ++ UINT32 ulUserChipId; ++ UINT32 ulWriteAddress; ++ UINT16 usWriteData; ++ ++} tOCT6100_WRITE_PARAMS, *tPOCT6100_WRITE_PARAMS; ++ ++ ++typedef struct _OCT6100_WRITE_SMEAR_PARAMS_ ++{ ++ PVOID pProcessContext; ++ ++ UINT32 ulUserChipId; ++ UINT32 ulWriteAddress; ++ UINT32 ulWriteLength; ++ UINT16 usWriteData; ++ ++} tOCT6100_WRITE_SMEAR_PARAMS, *tPOCT6100_WRITE_SMEAR_PARAMS; ++ ++ ++typedef struct _OCT6100_WRITE_BURST_PARAMS_ ++{ ++ PVOID pProcessContext; ++ ++ UINT32 ulUserChipId; ++ UINT32 ulWriteAddress; ++ UINT32 ulWriteLength; ++ PUINT16 pusWriteData; ++ ++} tOCT6100_WRITE_BURST_PARAMS, *tPOCT6100_WRITE_BURST_PARAMS; ++ ++ ++typedef struct _OCT6100_READ_PARAMS_ ++{ ++ PVOID pProcessContext; ++ ++ UINT32 ulUserChipId; ++ UINT32 ulReadAddress; ++ PUINT16 pusReadData; ++ ++} tOCT6100_READ_PARAMS, *tPOCT6100_READ_PARAMS; ++ ++ ++typedef struct _OCT6100_READ_BURST_PARAMS_ ++{ ++ PVOID pProcessContext; ++ ++ UINT32 ulUserChipId; ++ UINT32 ulReadAddress; ++ UINT32 ulReadLength; ++ PUINT16 pusReadData; ++ ++} tOCT6100_READ_BURST_PARAMS, *tPOCT6100_READ_BURST_PARAMS; ++ ++ ++ ++ ++ ++ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++/* Time function. */ ++UINT32 Oct6100UserGetTime( ++ IN OUT tPOCT6100_GET_TIME f_pTime ); ++ ++ ++ ++/* Memory management functions. */ ++UINT32 Oct6100UserMemSet( ++ IN PVOID f_pAddress, ++ IN UINT32 f_ulPattern, ++ IN UINT32 f_ulLength ); ++ ++UINT32 Oct6100UserMemCopy( ++ IN PVOID f_pDestination, ++ IN const void *f_pSource, ++ IN UINT32 f_ulLength ); ++ ++/* Serialization functions. */ ++UINT32 Oct6100UserCreateSerializeObject( ++ IN OUT tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate); ++ ++UINT32 Oct6100UserDestroySerializeObject( ++ IN tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy); ++ ++UINT32 Oct6100UserSeizeSerializeObject( ++ IN tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize); ++ ++UINT32 Oct6100UserReleaseSerializeObject( ++ IN tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease); ++ ++/* Read/Write functions.*/ ++UINT32 Oct6100UserDriverWriteApi( ++ IN tPOCT6100_WRITE_PARAMS f_pWriteParams ); ++ ++UINT32 Oct6100UserDriverWriteOs( ++ IN tPOCT6100_WRITE_PARAMS f_pWriteParams ); ++ ++UINT32 Oct6100UserDriverWriteSmearApi( ++ IN tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams ); ++ ++UINT32 Oct6100UserDriverWriteSmearOs( ++ IN tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams ); ++ ++UINT32 Oct6100UserDriverWriteBurstApi( ++ IN tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams ); ++ ++UINT32 Oct6100UserDriverWriteBurstOs( ++ IN tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams ); ++ ++UINT32 Oct6100UserDriverReadApi( ++ IN OUT tPOCT6100_READ_PARAMS f_pReadParams ); ++ ++UINT32 Oct6100UserDriverReadOs( ++ IN OUT tPOCT6100_READ_PARAMS f_pReadParams ); ++ ++UINT32 Oct6100UserDriverReadBurstApi( ++ IN OUT tPOCT6100_READ_BURST_PARAMS f_pBurstParams ); ++ ++UINT32 Oct6100UserDriverReadBurstOs( ++ IN OUT tPOCT6100_READ_BURST_PARAMS f_pBurstParams ); ++ ++ ++ ++ ++ ++ ++ ++#endif /* __OCT6100_APIUD_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_inst.h 2020-10-28 00:17:08.667192264 +0100 +@@ -0,0 +1,375 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_channel_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_channel.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_channel_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 90 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHANNEL_INST_H__ ++#define __OCT6100_CHANNEL_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/***************************** TYPES ***************************************/ ++ ++#ifndef __KERNEL__ ++#include ++#endif ++ ++#ifndef PTR_TYPE ++#define PTR_TYPE UINT16 ++#endif ++ ++typedef struct _OCT6100_API_CHANNEL_TDM_ ++{ ++ /* Laws. */ ++ UINT8 byRinPcmLaw : 1; ++ UINT8 bySinPcmLaw : 1; ++ UINT8 byRoutPcmLaw : 1; ++ UINT8 bySoutPcmLaw : 1; ++ ++ UINT8 byRinNumTssts : 2; ++ UINT8 bySinNumTssts : 2; ++ UINT8 byRoutNumTssts : 2; ++ UINT8 bySoutNumTssts : 2; ++ ++ /* RIN port. */ ++ UINT16 usRinTimeslot; ++ UINT16 usRinStream; ++ ++ /* SIN port. */ ++ UINT16 usSinTimeslot; ++ UINT16 usSinStream; ++ ++ /* ROUT port. */ ++ UINT16 usRoutTimeslot; ++ UINT16 usRoutStream; ++ ++ /* SOUT port. */ ++ UINT16 usSoutTimeslot; ++ UINT16 usSoutStream; ++ ++ /* ROUT broadcast info. */ ++ UINT16 usRoutBrdcastTsstFirstEntry; ++ UINT16 usRoutBrdcastTsstNumEntry; ++ ++ /* SOUT broadcast info. */ ++ UINT16 usSoutBrdcastTsstFirstEntry; ++ UINT16 usSoutBrdcastTsstNumEntry; ++ ++} tOCT6100_API_CHANNEL_TDM, *tPOCT6100_API_CHANNEL_TDM; ++ ++typedef struct _OCT6100_API_CHANNEL_VQE_ ++{ ++ UINT8 fEnableNlp : 1; ++ UINT8 fEnableTailDisplacement : 1; ++ UINT8 fSinDcOffsetRemoval : 1; ++ UINT8 fRinDcOffsetRemoval : 1; ++ UINT8 fRinLevelControl : 1; ++ UINT8 fSoutLevelControl : 1; ++ UINT8 fRinAutomaticLevelControl : 1; ++ UINT8 fSoutAutomaticLevelControl : 1; ++ UINT8 fRinHighLevelCompensation : 1; ++ UINT8 fSoutAdaptiveNoiseReduction : 1; ++ UINT8 fDtmfToneRemoval : 1; ++ UINT8 fAcousticEcho : 1; ++ UINT8 byComfortNoiseMode : 2; ++ UINT8 fSoutNaturalListenerEnhancement : 1; ++ UINT8 fRoutNoiseReduction : 1; ++ UINT8 fEnableMusicProtection : 1; ++ UINT8 fIdleCodeDetection : 1; ++ UINT8 byAnrVoiceNoiseSegregation : 4; ++ UINT8 byDoubleTalkBehavior : 1; ++ UINT8 fSoutNoiseBleaching : 1; ++ UINT8 fSoutConferencingNoiseReduction : 1; ++ UINT8 byNonLinearityBehaviorA : 4; ++ UINT8 byNonLinearityBehaviorB : 4; ++ ++ UINT8 bySoutAutomaticListenerEnhancementGainDb; ++ UINT8 bySoutNaturalListenerEnhancementGainDb; ++ ++ OCT_INT8 chRinAutomaticLevelControlTargetDb; ++ OCT_INT8 chSoutAutomaticLevelControlTargetDb; ++ ++ OCT_INT8 chRinHighLevelCompensationThresholdDb; ++ ++ OCT_INT8 chRinLevelControlGainDb; ++ OCT_INT8 chSoutLevelControlGainDb; ++ ++ OCT_INT8 chDefaultErlDb; ++ OCT_INT8 chAecDefaultErlDb; ++ ++ OCT_INT8 chRoutNoiseReductionLevelGainDb; ++ OCT_INT8 chAnrSnrEnhancementDb; ++ ++ UINT16 usToneDisablerVqeActivationDelay; ++ UINT16 usAecTailLength; ++ ++ UINT16 usTailDisplacement; ++ UINT16 usTailLength; ++ ++} tOCT6100_API_CHANNEL_VQE, *tPOCT6100_API_CHANNEL_VQE; ++ ++typedef struct _OCT6100_API_CHANNEL_CODEC_ ++{ ++ UINT8 byAdpcmNibblePosition : 1; ++ UINT8 fEnableSilenceSuppression : 1; ++ ++ UINT8 byEncoderPort : 4; ++ UINT8 byDecoderPort : 4; ++ ++ UINT8 byPhasingType : 2; ++ ++ UINT8 byEncodingRate; ++ UINT8 byDecodingRate; ++ ++ UINT16 byPhase; ++} tOCT6100_API_CHANNEL_CODEC, *tPOCT6100_API_CHANNEL_CODEC; ++ ++typedef struct _OCT6100_API_CHANNEL_ ++{ ++ /*=======================================================================*/ ++ /* Channel configuration. */ ++ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved : 1; ++ ++ /* Count used to manage entry handles allocated to user. */ ++ UINT8 byEntryOpenCnt : 1; ++ ++ /* Is this a bidirectionnal channel? */ ++ UINT8 fBiDirChannel : 1; ++ ++ /* Enable tone disabler? */ ++ UINT8 fEnableToneDisabler : 1; ++ ++ /* Current echo operation mode. */ ++ UINT8 byEchoOperationMode : 3; ++ ++ UINT8 byToneDisablerStatus : 1; ++ ++ UINT8 fMute : 1; ++ UINT8 fTap : 1; ++ UINT8 fBeingTapped : 1; ++ UINT8 fCopyEventCreated : 1; ++ ++ UINT8 fSoutBufPlaying : 1; ++ UINT8 fRinBufPlaying : 1; ++ ++ UINT8 fRinBufPlayoutNotifyOnStop : 1; ++ UINT8 fRinBufPlayoutRepeatUsed : 1; ++ ++ ++ UINT8 fSoutBufPlayoutNotifyOnStop : 1; ++ UINT8 fSoutBufPlayoutRepeatUsed : 1; ++ ++ UINT8 fRinHardStop : 1; ++ UINT8 fSoutHardStop : 1; ++ ++ UINT8 byRinPlayoutStopEventType : 1; ++ UINT8 bySoutPlayoutStopEventType : 1; ++ ++ UINT8 fRinBufAdded : 1; ++ UINT8 fSoutBufAdded : 1; ++ ++ UINT8 fBufPlayoutActive : 1; ++ ++ /* Enable extended tone detection. */ ++ UINT8 fEnableExtToneDetection : 1; ++ ++ /* State of the codec structure associated to this channel. */ ++ UINT8 fSinSoutCodecActive : 1; ++ UINT8 fRinRoutCodecActive : 1; ++ ++ /* TSI chariot memory entry for the Rin/Rout stream. */ ++ UINT16 usRinRoutTsiMemIndex; ++ ++ /* TSI chariot memory entry for the Sin/Sout stream. */ ++ UINT16 usSinSoutTsiMemIndex; ++ ++ /* Additional TSI entry used to temporarily store the SIN signal. */ ++ UINT16 usExtraSinTsiMemIndex; ++ UINT16 usExtraSinTsiDependencyCnt; ++ ++ /* Additional TSI entry used to temporarily store the RIN signal. */ ++ UINT16 usExtraRinTsiMemIndex; ++ UINT16 usExtraRinTsiDependencyCnt; ++ ++ /* Conversion chariot memory entry. */ ++ UINT16 usRinRoutConversionMemIndex; ++ UINT16 usSinSoutConversionMemIndex; ++ ++ /* TSST control memory entry. */ ++ UINT16 usRinTsstIndex; ++ UINT16 usSinTsstIndex; ++ UINT16 usRoutTsstIndex; ++ UINT16 usSoutTsstIndex; ++ ++ /* SSPX memory entry. */ ++ UINT16 usEchoMemIndex; ++ ++ /* Active mixer events count to test for last event. */ ++ UINT16 usMixerEventCnt; ++ ++ /* Copy events. */ ++ UINT16 usSinCopyEventIndex; ++ UINT16 usSoutCopyEventIndex; ++ ++ /* Silence events. */ ++ UINT16 usRinSilenceEventIndex; ++ UINT16 usSinSilenceEventIndex; ++ ++ /* TDM configuration. */ ++ tOCT6100_API_CHANNEL_TDM TdmConfig; ++ ++ /* VQE configuration. */ ++ tOCT6100_API_CHANNEL_VQE VqeConfig; ++ ++ /* Currently muted ports. */ ++ UINT16 usMutedPorts; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Statistics section. */ ++ ++ INT16 sComfortNoiseLevel; ++ ++ UINT16 usCurrentEchoDelay; ++ UINT16 usMaxEchoDelay; ++ ++ UINT16 usNumEchoPathChanges; ++ UINT16 usNumEchoPathChangesOfst; ++ ++ INT16 sCurrentERL; ++ INT16 sCurrentERLE; ++ ++ INT16 sMaxERL; ++ INT16 sMaxERLE; ++ ++ INT16 sRinLevel; ++ INT16 sSinLevel; ++ ++ INT16 sRinAppliedGain; ++ INT16 sSoutAppliedGain; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Bridge information. */ ++ ++ UINT16 usBridgeIndex; ++ ++ UINT16 usLoadEventIndex; ++ UINT16 usSubStoreEventIndex; ++ ++ UINT16 usFlexConfParticipantIndex; ++ UINT16 usTapBridgeIndex; ++ UINT16 usTapChanIndex; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Buffer playout information. */ ++ ++ PTR_TYPE ulRinBufWritePtr; ++ PTR_TYPE ulRinBufSkipPtr; ++ PTR_TYPE ulSoutBufWritePtr; ++ PTR_TYPE ulSoutBufSkipPtr; ++ ++ /* User channel ID, transparently passed to the user. */ ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Copy events information. */ ++ ++ /* Number of copy events created. */ ++ UINT16 usCopyEventCnt; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Extended tone detection info. */ ++ ++ ++ UINT16 usExtToneChanIndex; ++ UINT16 usExtToneMixerIndex; ++ UINT16 usExtToneTsiIndex; ++ ++ /* Index of the phasing TSST */ ++ UINT16 usPhasingTsstIndex; ++ ++ /* Mode of operation of the channel based on the extended tone detection configuration. */ ++ PTR_TYPE ulExtToneChanMode; ++ ++ /*=======================================================================*/ ++ ++ /* Tone detection state. */ ++ /* This array is configured as follow. */ ++ /* Index 0 contain event 0 to 31 and Index 1 contains event 32 - 55 */ ++ PTR_TYPE ulLastSSToneDetected; ++ PTR_TYPE ulLastSSToneTimestamp; ++ ++ ++ PTR_TYPE ulRinUserBufPlayoutEventId; ++ PTR_TYPE ulSoutUserBufPlayoutEventId; ++ ++ UINT32 aulToneConf[2]; ++ UINT32 ulUserChanId; ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ ++ ++ /* Codec configuration. */ ++ tOCT6100_API_CHANNEL_CODEC CodecConfig; ++ ++} tOCT6100_API_CHANNEL, *tPOCT6100_API_CHANNEL; ++ ++typedef struct _OCT6100_API_BIDIR_CHANNEL_ ++{ ++ UINT16 usFirstChanIndex; ++ UINT16 usSecondChanIndex; ++ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved : 1; ++ /* Count used to manage entry handles allocated to user. */ ++ UINT8 byEntryOpenCnt; ++ ++} tOCT6100_API_BIDIR_CHANNEL, *tPOCT6100_API_BIDIR_CHANNEL; ++ ++#endif /* __OCT6100_CHANNEL_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,547 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_channel_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_channel.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_channel_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 84 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHANNEL_PUB_H__ ++#define __OCT6100_CHANNEL_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++/* Channel open structures. */ ++typedef struct _OCT6100_CHANNEL_OPEN_TDM_ ++{ ++ UINT32 ulRinNumTssts; ++ UINT32 ulSinNumTssts; ++ UINT32 ulRoutNumTssts; ++ UINT32 ulSoutNumTssts; ++ ++ UINT32 ulSinTimeslot; ++ UINT32 ulSinStream; ++ UINT32 ulSinPcmLaw; ++ ++ UINT32 ulSoutTimeslot; ++ UINT32 ulSoutStream; ++ UINT32 ulSoutPcmLaw; ++ ++ UINT32 ulRinTimeslot; ++ UINT32 ulRinStream; ++ UINT32 ulRinPcmLaw; ++ ++ UINT32 ulRoutTimeslot; ++ UINT32 ulRoutStream; ++ UINT32 ulRoutPcmLaw; ++ ++} tOCT6100_CHANNEL_OPEN_TDM, *tPOCT6100_CHANNEL_OPEN_TDM; ++ ++typedef struct _OCT6100_CHANNEL_OPEN_VQE_ ++{ ++ BOOL fEnableNlp; ++ BOOL fEnableTailDisplacement; ++ UINT32 ulTailDisplacement; ++ UINT32 ulTailLength; ++ ++ BOOL fSinDcOffsetRemoval; ++ BOOL fRinDcOffsetRemoval; ++ BOOL fRinLevelControl; ++ BOOL fSoutLevelControl; ++ BOOL fRinAutomaticLevelControl; ++ BOOL fSoutAutomaticLevelControl; ++ BOOL fRinHighLevelCompensation; ++ BOOL fAcousticEcho; ++ BOOL fSoutAdaptiveNoiseReduction; ++ BOOL fDtmfToneRemoval; ++ ++ BOOL fSoutNoiseBleaching; ++ BOOL fSoutConferencingNoiseReduction; ++ ++ UINT32 ulComfortNoiseMode; ++ UINT32 ulNonLinearityBehaviorA; ++ UINT32 ulNonLinearityBehaviorB; ++ ++ INT32 lRinLevelControlGainDb; ++ INT32 lSoutLevelControlGainDb; ++ INT32 lRinAutomaticLevelControlTargetDb; ++ INT32 lSoutAutomaticLevelControlTargetDb; ++ INT32 lRinHighLevelCompensationThresholdDb; ++ INT32 lDefaultErlDb; ++ INT32 lAecDefaultErlDb; ++ UINT32 ulAecTailLength; ++ UINT32 ulSoutAutomaticListenerEnhancementGainDb; ++ UINT32 ulSoutNaturalListenerEnhancementGainDb; ++ BOOL fSoutNaturalListenerEnhancement; ++ BOOL fRoutNoiseReduction; ++ INT32 lRoutNoiseReductionLevelGainDb; ++ INT32 lAnrSnrEnhancementDb; ++ UINT32 ulAnrVoiceNoiseSegregation; ++ UINT32 ulDoubleTalkBehavior; ++ ++ UINT32 ulToneDisablerVqeActivationDelay; ++ ++ BOOL fEnableMusicProtection; ++ BOOL fIdleCodeDetection; ++ ++ ++ ++} tOCT6100_CHANNEL_OPEN_VQE, *tPOCT6100_CHANNEL_OPEN_VQE; ++ ++typedef struct _OCT6100_CHANNEL_OPEN_CODEC_ ++{ ++ UINT32 ulAdpcmNibblePosition; ++ ++ UINT32 ulEncoderPort; ++ UINT32 ulEncodingRate; ++ ++ UINT32 ulDecoderPort; ++ UINT32 ulDecodingRate; ++ ++ BOOL fEnableSilenceSuppression; ++ UINT32 ulPhase; ++ UINT32 ulPhasingType; ++ UINT32 ulPhasingTsstHndl; ++ ++} tOCT6100_CHANNEL_OPEN_CODEC, *tPOCT6100_CHANNEL_OPEN_CODEC; ++ ++typedef struct _OCT6100_CHANNEL_OPEN_ ++{ ++ PUINT32 pulChannelHndl; ++ UINT32 ulUserChanId; ++ ++ UINT32 ulEchoOperationMode; ++ ++ BOOL fEnableToneDisabler; ++ ++ BOOL fEnableExtToneDetection; ++ ++ tOCT6100_CHANNEL_OPEN_TDM TdmConfig; ++ tOCT6100_CHANNEL_OPEN_VQE VqeConfig; ++ tOCT6100_CHANNEL_OPEN_CODEC CodecConfig; ++ ++ ++ ++} tOCT6100_CHANNEL_OPEN, *tPOCT6100_CHANNEL_OPEN; ++ ++/* Channel close structure. */ ++typedef struct _OCT6100_CHANNEL_CLOSE_ ++{ ++ UINT32 ulChannelHndl; ++ ++} tOCT6100_CHANNEL_CLOSE, *tPOCT6100_CHANNEL_CLOSE; ++ ++/* Channel modify structures. */ ++typedef struct _OCT6100_CHANNEL_MODIFY_TDM_ ++{ ++ UINT32 ulRinNumTssts; ++ UINT32 ulSinNumTssts; ++ UINT32 ulRoutNumTssts; ++ UINT32 ulSoutNumTssts; ++ ++ UINT32 ulSinTimeslot; ++ UINT32 ulSinStream; ++ UINT32 ulSinPcmLaw; ++ ++ UINT32 ulSoutTimeslot; ++ UINT32 ulSoutStream; ++ UINT32 ulSoutPcmLaw; ++ ++ UINT32 ulRinTimeslot; ++ UINT32 ulRinStream; ++ UINT32 ulRinPcmLaw; ++ ++ UINT32 ulRoutTimeslot; ++ UINT32 ulRoutStream; ++ UINT32 ulRoutPcmLaw; ++ ++} tOCT6100_CHANNEL_MODIFY_TDM, *tPOCT6100_CHANNEL_MODIFY_TDM; ++ ++typedef struct _OCT6100_CHANNEL_MODIFY_VQE_ ++{ ++ BOOL fEnableNlp; ++ BOOL fEnableTailDisplacement; ++ UINT32 ulTailDisplacement; ++ ++ BOOL fSinDcOffsetRemoval; ++ BOOL fRinDcOffsetRemoval; ++ BOOL fRinLevelControl; ++ BOOL fSoutLevelControl; ++ BOOL fRinAutomaticLevelControl; ++ BOOL fSoutAutomaticLevelControl; ++ BOOL fRinHighLevelCompensation; ++ BOOL fAcousticEcho; ++ BOOL fSoutAdaptiveNoiseReduction; ++ BOOL fDtmfToneRemoval; ++ ++ BOOL fSoutConferencingNoiseReduction; ++ BOOL fSoutNoiseBleaching; ++ ++ UINT32 ulNonLinearityBehaviorA; ++ UINT32 ulNonLinearityBehaviorB; ++ UINT32 ulComfortNoiseMode; ++ ++ INT32 lRinLevelControlGainDb; ++ INT32 lSoutLevelControlGainDb; ++ INT32 lRinAutomaticLevelControlTargetDb; ++ INT32 lSoutAutomaticLevelControlTargetDb; ++ INT32 lRinHighLevelCompensationThresholdDb; ++ INT32 lDefaultErlDb; ++ INT32 lAecDefaultErlDb; ++ UINT32 ulAecTailLength; ++ UINT32 ulSoutAutomaticListenerEnhancementGainDb; ++ UINT32 ulSoutNaturalListenerEnhancementGainDb; ++ BOOL fSoutNaturalListenerEnhancement; ++ BOOL fRoutNoiseReduction; ++ INT32 lRoutNoiseReductionLevelGainDb; ++ INT32 lAnrSnrEnhancementDb; ++ UINT32 ulAnrVoiceNoiseSegregation; ++ UINT32 ulDoubleTalkBehavior; ++ ++ UINT32 ulToneDisablerVqeActivationDelay; ++ ++ BOOL fEnableMusicProtection; ++ BOOL fIdleCodeDetection; ++ ++ ++ ++} tOCT6100_CHANNEL_MODIFY_VQE, *tPOCT6100_CHANNEL_MODIFY_VQE; ++ ++typedef struct _OCT6100_CHANNEL_MODIFY_CODEC_ ++{ ++ UINT32 ulEncoderPort; ++ UINT32 ulEncodingRate; ++ ++ UINT32 ulDecoderPort; ++ UINT32 ulDecodingRate; ++ ++ BOOL fEnableSilenceSuppression; ++ UINT32 ulPhase; ++ UINT32 ulPhasingType; ++ UINT32 ulPhasingTsstHndl; ++ ++} tOCT6100_CHANNEL_MODIFY_CODEC, *tPOCT6100_CHANNEL_MODIFY_CODEC; ++ ++typedef struct _OCT6100_CHANNEL_MODIFY_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulUserChanId; ++ UINT32 ulEchoOperationMode; ++ ++ BOOL fEnableToneDisabler; ++ ++ BOOL fApplyToAllChannels; ++ ++ BOOL fDisableToneDetection; ++ BOOL fStopBufferPlayout; ++ BOOL fRemoveConfBridgeParticipant; ++ BOOL fRemoveBroadcastTssts; ++ ++ BOOL fTdmConfigModified; /* TRUE/FALSE */ ++ BOOL fVqeConfigModified; /* TRUE/FALSE */ ++ BOOL fCodecConfigModified; /* TRUE/FALSE */ ++ ++ ++ tOCT6100_CHANNEL_MODIFY_TDM TdmConfig; ++ tOCT6100_CHANNEL_MODIFY_VQE VqeConfig; ++ tOCT6100_CHANNEL_MODIFY_CODEC CodecConfig; ++ ++} tOCT6100_CHANNEL_MODIFY, *tPOCT6100_CHANNEL_MODIFY; ++ ++typedef struct _OCT6100_CHANNEL_BROADCAST_TSST_ADD_ ++{ ++ UINT32 ulChannelHndl; ++ ++ UINT32 ulPort; ++ UINT32 ulTimeslot; ++ UINT32 ulStream; ++ ++} tOCT6100_CHANNEL_BROADCAST_TSST_ADD, *tPOCT6100_CHANNEL_BROADCAST_TSST_ADD; ++ ++typedef struct _OCT6100_CHANNEL_BROADCAST_TSST_REMOVE_ ++{ ++ UINT32 ulChannelHndl; ++ ++ UINT32 ulPort; ++ UINT32 ulTimeslot; ++ UINT32 ulStream; ++ ++ BOOL fRemoveAll; ++ ++} tOCT6100_CHANNEL_BROADCAST_TSST_REMOVE, *tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE; ++ ++/* Channel open structures.*/ ++typedef struct _OCT6100_CHANNEL_STATS_TDM_ ++{ ++ UINT32 ulMaxBroadcastTssts; ++ UINT32 ulNumRoutBroadcastTssts; ++ BOOL fMoreRoutBroadcastTssts; ++ UINT32 ulNumSoutBroadcastTssts; ++ BOOL fMoreSoutBroadcastTssts; ++ ++ UINT32 ulSinNumTssts; ++ UINT32 ulSoutNumTssts; ++ UINT32 ulRinNumTssts; ++ UINT32 ulRoutNumTssts; ++ ++ UINT32 ulSinTimeslot; ++ UINT32 ulSinStream; ++ UINT32 ulSinPcmLaw; ++ ++ UINT32 ulSoutTimeslot; ++ UINT32 ulSoutStream; ++ UINT32 ulSoutPcmLaw; ++ ++ PUINT32 pulSoutBroadcastTimeslot; ++ PUINT32 pulSoutBroadcastStream; ++ ++ UINT32 ulRinTimeslot; ++ UINT32 ulRinStream; ++ UINT32 ulRinPcmLaw; ++ ++ UINT32 ulRoutTimeslot; ++ UINT32 ulRoutStream; ++ UINT32 ulRoutPcmLaw; ++ ++ PUINT32 pulRoutBroadcastTimeslot; ++ PUINT32 pulRoutBroadcastStream; ++ ++} tOCT6100_CHANNEL_STATS_TDM, *tPOCT6100_CHANNEL_STATS_TDM; ++ ++typedef struct _OCT6100_CHANNEL_STATS_VQE_ ++{ ++ BOOL fEnableNlp; ++ BOOL fEnableTailDisplacement; ++ UINT32 ulTailDisplacement; ++ UINT32 ulTailLength; ++ ++ BOOL fSinDcOffsetRemoval; ++ BOOL fRinDcOffsetRemoval; ++ BOOL fRinLevelControl; ++ BOOL fSoutLevelControl; ++ BOOL fRinAutomaticLevelControl; ++ BOOL fSoutAutomaticLevelControl; ++ BOOL fRinHighLevelCompensation; ++ BOOL fAcousticEcho; ++ BOOL fSoutAdaptiveNoiseReduction; ++ BOOL fDtmfToneRemoval; ++ ++ BOOL fSoutConferencingNoiseReduction; ++ BOOL fSoutNoiseBleaching; ++ ++ UINT32 ulComfortNoiseMode; ++ UINT32 ulNonLinearityBehaviorA; ++ UINT32 ulNonLinearityBehaviorB; ++ ++ INT32 lRinLevelControlGainDb; ++ INT32 lSoutLevelControlGainDb; ++ INT32 lRinAutomaticLevelControlTargetDb; ++ INT32 lSoutAutomaticLevelControlTargetDb; ++ INT32 lRinHighLevelCompensationThresholdDb; ++ INT32 lDefaultErlDb; ++ INT32 lAecDefaultErlDb; ++ UINT32 ulAecTailLength; ++ UINT32 ulSoutAutomaticListenerEnhancementGainDb; ++ UINT32 ulSoutNaturalListenerEnhancementGainDb; ++ BOOL fSoutNaturalListenerEnhancement; ++ BOOL fRoutNoiseReduction; ++ INT32 lRoutNoiseReductionLevelGainDb; ++ INT32 lAnrSnrEnhancementDb; ++ UINT32 ulAnrVoiceNoiseSegregation; ++ UINT32 ulDoubleTalkBehavior; ++ ++ UINT32 ulToneDisablerVqeActivationDelay; ++ ++ BOOL fEnableMusicProtection; ++ BOOL fIdleCodeDetection; ++ ++ ++ ++} tOCT6100_CHANNEL_STATS_VQE, *tPOCT6100_CHANNEL_STATS_VQE; ++ ++typedef struct _OCT6100_CHANNEL_STATS_CODEC_ ++{ ++ UINT32 ulAdpcmNibblePosition; ++ ++ UINT32 ulEncoderPort; ++ UINT32 ulEncodingRate; ++ ++ UINT32 ulDecoderPort; ++ UINT32 ulDecodingRate; ++ ++ BOOL fEnableSilenceSuppression; ++ UINT32 ulPhase; ++ UINT32 ulPhasingType; ++ UINT32 ulPhasingTsstHndl; ++ ++} tOCT6100_CHANNEL_STATS_CODEC, *tPOCT6100_CHANNEL_STATS_CODEC; ++ ++typedef struct _OCT6100_CHANNEL_STATS_ ++{ ++ BOOL fResetStats; ++ ++ UINT32 ulChannelHndl; ++ UINT32 ulUserChanId; ++ ++ UINT32 ulEchoOperationMode; ++ BOOL fEnableToneDisabler; ++ ++ UINT32 ulMutePortsMask; ++ BOOL fEnableExtToneDetection; ++ ++ tOCT6100_CHANNEL_STATS_TDM TdmConfig; ++ tOCT6100_CHANNEL_STATS_VQE VqeConfig; ++ tOCT6100_CHANNEL_STATS_CODEC CodecConfig; ++ ++ /* Real stats. */ ++ UINT32 ulNumEchoPathChanges; ++ UINT32 ulToneDisablerStatus; ++ ++ INT32 lCurrentERL; ++ INT32 lCurrentERLE; ++ UINT32 ulCurrentEchoDelay; ++ ++ INT32 lMaxERL; ++ INT32 lMaxERLE; ++ UINT32 ulMaxEchoDelay; ++ ++ INT32 lRinLevel; ++ INT32 lSinLevel; ++ INT32 lRinAppliedGain; ++ INT32 lSoutAppliedGain; ++ INT32 lComfortNoiseLevel; ++ ++ BOOL fEchoCancellerConverged; ++ BOOL fSinVoiceDetected; ++ ++ ++ ++} tOCT6100_CHANNEL_STATS, *tPOCT6100_CHANNEL_STATS; ++ ++typedef struct _OCT6100_CHANNEL_CREATE_BIDIR_ ++{ ++ PUINT32 pulBiDirChannelHndl; ++ ++ UINT32 ulFirstChannelHndl; ++ UINT32 ulSecondChannelHndl; ++ ++ ++ ++} tOCT6100_CHANNEL_CREATE_BIDIR, *tPOCT6100_CHANNEL_CREATE_BIDIR; ++ ++typedef struct _OCT6100_CHANNEL_DESTROY_BIDIR_ ++{ ++ UINT32 ulBiDirChannelHndl; ++ ++} tOCT6100_CHANNEL_DESTROY_BIDIR, *tPOCT6100_CHANNEL_DESTROY_BIDIR; ++ ++typedef struct _OCT6100_CHANNEL_MUTE_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulPortMask; ++ ++} tOCT6100_CHANNEL_MUTE, *tPOCT6100_CHANNEL_MUTE; ++ ++typedef struct _OCT6100_CHANNEL_UNMUTE_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulPortMask; ++ ++} tOCT6100_CHANNEL_UNMUTE, *tPOCT6100_CHANNEL_UNMUTE; ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++ ++UINT32 Oct6100ChannelOpenDef( ++ OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ); ++UINT32 Oct6100ChannelOpen( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ); ++ ++UINT32 Oct6100ChannelCloseDef( ++ OUT tPOCT6100_CHANNEL_CLOSE f_pChannelClose ); ++UINT32 Oct6100ChannelClose( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_CLOSE f_pChannelClose ); ++ ++UINT32 Oct6100ChannelModifyDef( ++ OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ); ++UINT32 Oct6100ChannelModify( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ); ++ ++UINT32 Oct6100ChannelBroadcastTsstAddDef( ++ OUT tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd ); ++UINT32 Oct6100ChannelBroadcastTsstAdd( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd ); ++ ++UINT32 Oct6100ChannelBroadcastTsstRemoveDef( ++ OUT tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove ); ++UINT32 Oct6100ChannelBroadcastTsstRemove( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove ); ++ ++UINT32 Oct6100ChannelGetStatsDef( ++ OUT tPOCT6100_CHANNEL_STATS f_pChannelStats ); ++UINT32 Oct6100ChannelGetStats( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_STATS f_pChannelStats ); ++ ++UINT32 Oct6100ChannelCreateBiDirDef( ++ OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ); ++UINT32 Oct6100ChannelCreateBiDir( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ); ++ ++UINT32 Oct6100ChannelDestroyBiDirDef( ++ OUT tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ); ++UINT32 Oct6100ChannelDestroyBiDir( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ); ++ ++UINT32 Oct6100ChannelMuteDef( ++ OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ); ++UINT32 Oct6100ChannelMute( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ); ++ ++UINT32 Oct6100ChannelUnMuteDef( ++ OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ); ++UINT32 Oct6100ChannelUnMute( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ); ++ ++#endif /* __OCT6100_CHANNEL_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,515 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_open_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_chip_open.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_chip_open_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 122 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHIP_OPEN_INST_H__ ++#define __OCT6100_CHIP_OPEN_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_CHIP_CONFIG_ ++{ ++ UINT32 ulUserChipId; ++ PVOID pProcessContext; ++ ++ unsigned char const *pbyImageFile; /* Byte pointer to the image file to be uploaded into the chip. */ ++ UINT32 ulImageSize; /* Size of the image file (in bytes). */ ++ ++ UINT32 ulMemClkFreq; ++ UINT32 ulUpclkFreq; /* 33.33 or 66.66 MHz. */ ++ UINT8 fEnableMemClkOut; /* TRUE/FALSE */ ++ ++ UINT8 fMultiProcessSystem; ++ ++ UINT8 byMemoryType; /* SDRAM or DDR */ ++ UINT8 byNumMemoryChips; /* Number of memory chips present. */ ++ UINT32 ulMemoryChipSize; /* The size of the memory chips. */ ++ ++ UINT16 usMaxRwAccesses; ++ UINT16 usTailDisplacement; ++ ++ /* Resource allocation parameters. */ ++ UINT16 usMaxChannels; ++ UINT16 usMaxBiDirChannels; ++ ++ UINT32 aulTdmStreamFreqs[ cOCT6100_TDM_STREAM_MAX_GROUPS ]; ++ ++ UINT8 byMaxTdmStreams; ++ UINT8 byTdmSampling; ++ ++ UINT8 fEnableFastH100Mode; ++ UINT8 fEnableAcousticEcho; /* Acoustic echo enabled. */ ++ ++ UINT16 ausTimestampTimeslots[ 4 ]; ++ UINT16 ausTimestampStreams[ 4 ]; ++ ++ UINT8 fUseSynchTimestamp; ++ ++ /* Debug feature used to record stream information from a channel.*/ ++ UINT8 fEnableChannelRecording; ++ ++ UINT16 usMaxRemoteDebugSessions; ++ ++ UINT8 byInterruptPolarity; ++ ++ UINT16 usMaxTsiCncts; ++ ++ UINT8 fEnableExtToneDetection; ++ UINT8 fEnable2100StopEvent; ++ ++ ++ UINT16 usMaxConfBridges; ++ UINT16 usMaxFlexibleConfParticipants; ++ UINT16 usMaxPlayoutBuffers; ++ ++ /* Playout event software buffer size. */ ++ UINT32 ulSoftBufPlayoutEventsBufSize; ++ ++ /* Soft buffer size. */ ++ UINT32 ulSoftToneEventsBufSize; ++ ++ UINT16 usMaxPhasingTssts; ++ UINT16 usMaxAdpcmChannels; ++ ++ ++ ++ ++ ++ UINT8 fEnableProductionBist; ++ UINT32 ulProductionBistMode; ++ UINT32 ulNumProductionBistLoops; ++ ++} tOCT6100_API_CHIP_CONFIG, *tPOCT6100_API_CHIP_CONFIG; ++ ++ ++typedef struct _OCT6100_API_MISCELLANEOUS_ ++{ ++ /* Total size of external memories. */ ++ UINT32 ulTotalMemSize; ++ ++ UINT32 ulH100SlaveMode; ++ ++ /* Mclk frequency generated by the chip. */ ++ UINT32 ulMclkFreq; ++ ++ /* Array of UINT32s used to perform a burst of writes (avoids having to ++ allocate on the stack. The size of this array MUST NOT CHANGE (it's ++ used everywhere). */ ++ UINT16 ausSuperArray[ cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ]; ++ ++ /* Chip ID and revision.*/ ++ UINT16 usChipId; ++ UINT16 usChipRevision; ++ ++ /* Lsu CPU access variables.*/ ++ UINT16 usCpuLsuWritePtr; ++ UINT16 usCodepoint; ++ ++ /* Max number of channel supported.*/ ++ UINT16 usMaxNumberOfChannels; ++ UINT16 usMaxH100Speed; ++ UINT16 usTdmClkBoundary; ++ ++ UINT16 usNumBridgesOpened; ++ UINT16 usFirstBridge; ++ ++ ++ ++ ++ ++} tOCT6100_API_MISCELLANEOUS, *tPOCT6100_API_MISCELLANEOUS; ++ ++typedef struct _OCT6100_API_MEMORY_MAP_ ++{ ++ /*-----------------------------------------------------------------------------*/ ++ /* Structure contained in external memory. */ ++ ++ /* Memory mapping filled using TLV information from the chip. */ ++ ++ /* Main channel memory. */ ++ UINT32 ulChanMainMemBase; ++ UINT32 ulChanMainMemSize; ++ ++ UINT32 ulChanMainIoMemOfst; ++ ++ UINT32 ulChanMainRinCBMemOfst; ++ UINT32 ulChanMainRinCBMemSize; ++ UINT32 ulChanMainSinCBMemOfst; ++ UINT32 ulChanMainSinCBMemSize; ++ UINT32 ulChanMainSoutCBMemOfst; ++ UINT32 ulChanMainSoutCBMemSize; ++ ++ /* Free memory base address. */ ++ UINT32 ulFreeMemBaseAddress; ++ ++ /* Root channel config offset. */ ++ UINT32 ulChanRootConfOfst; ++ ++ /* Playout buffer info. */ ++ UINT32 ulChanMainRinPlayoutMemOfst; ++ UINT32 ulChanMainRinPlayoutMemSize; ++ UINT32 ulChanMainSoutPlayoutMemOfst; ++ UINT32 ulChanMainSoutPlayoutMemSize; ++ ++ /* Channel Stats location */ ++ UINT32 ulChanMainIoStatsOfst; ++ UINT32 ulChanMainIoStatsSize; ++ ++ /* Buffer playout fields. */ ++ tOCT6100_TLV_OFFSET PlayoutRinWritePtrOfst; ++ tOCT6100_TLV_OFFSET PlayoutRinIgnoreSkipCleanOfst; ++ tOCT6100_TLV_OFFSET PlayoutRinSkipPtrOfst; ++ tOCT6100_TLV_OFFSET PlayoutSoutWritePtrOfst; ++ tOCT6100_TLV_OFFSET PlayoutSoutIgnoreSkipCleanOfst; ++ tOCT6100_TLV_OFFSET PlayoutSoutSkipPtrOfst; ++ tOCT6100_TLV_OFFSET PlayoutRinReadPtrOfst; ++ tOCT6100_TLV_OFFSET PlayoutSoutReadPtrOfst; ++ tOCT6100_TLV_OFFSET PlayoutRinHardSkipOfst; ++ tOCT6100_TLV_OFFSET PlayoutSoutHardSkipOfst; ++ ++ /* Adaptive noise reduction. */ ++ tOCT6100_TLV_OFFSET AdaptiveNoiseReductionOfst; ++ ++ /* DC offset removal. */ ++ tOCT6100_TLV_OFFSET RinDcOffsetRemovalOfst; ++ tOCT6100_TLV_OFFSET SinDcOffsetRemovalOfst; ++ ++ /* Level control. */ ++ tOCT6100_TLV_OFFSET RinLevelControlOfst; ++ tOCT6100_TLV_OFFSET SoutLevelControlOfst; ++ ++ /* Auto level control. */ ++ tOCT6100_TLV_OFFSET RinAutoLevelControlTargetOfst; ++ tOCT6100_TLV_OFFSET SoutAutoLevelControlTargetOfst; ++ ++ /* High level compensation. */ ++ tOCT6100_TLV_OFFSET RinHighLevelCompensationThresholdOfst; ++ tOCT6100_TLV_OFFSET SoutHighLevelCompensationThresholdOfst; ++ ++ /* Auto level control and high level compensation status. */ ++ tOCT6100_TLV_OFFSET AlcHlcStatusOfst; ++ ++ /* Confort Noise Mode. */ ++ tOCT6100_TLV_OFFSET ComfortNoiseModeOfst; ++ ++ /* NLP control field. */ ++ tOCT6100_TLV_OFFSET NlpControlFieldOfst; ++ ++ /* VAD control field offset.*/ ++ tOCT6100_TLV_OFFSET VadControlFieldOfst; ++ ++ /* NLP Trivial field offset. */ ++ tOCT6100_TLV_OFFSET NlpTrivialFieldOfst; ++ ++ /* Acoustic echo field offset. */ ++ tOCT6100_TLV_OFFSET AecFieldOfst; ++ ++ /* Acoustic echo default ERL field offset. */ ++ tOCT6100_TLV_OFFSET AecDefaultErlFieldOfst; ++ ++ /* Non-linearity behavior A and B field offset. */ ++ tOCT6100_TLV_OFFSET PcmLeakFieldOfst; ++ tOCT6100_TLV_OFFSET NlpConvCapFieldOfst; ++ ++ /* Default ERL field offset. */ ++ tOCT6100_TLV_OFFSET DefaultErlFieldOfst; ++ ++ /* Tone Removal field offset.*/ ++ tOCT6100_TLV_OFFSET ToneRemovalFieldOfst; ++ ++ ++ ++ /* Channel config fields offset. */ ++ tOCT6100_TLV_OFFSET ChanMainIoMaxEchoPointOfst; ++ tOCT6100_TLV_OFFSET TailDisplEnableOfst; ++ ++ /* Pouch fields offset. */ ++ tOCT6100_TLV_OFFSET PouchBootInstructionOfst; ++ tOCT6100_TLV_OFFSET PouchBootResultOfst; ++ tOCT6100_TLV_OFFSET PouchTailDisplOfst; ++ ++ /* 2100 Hz Auto disabling fields offset. */ ++ tOCT6100_TLV_OFFSET ToneDisablerControlOfst; ++ ++ /* Conferencing dominant speaker field offset. */ ++ tOCT6100_TLV_OFFSET DominantSpeakerFieldOfst; ++ ++ /* Conferencing noise reduction field offset. */ ++ tOCT6100_TLV_OFFSET ConferencingNoiseReductionOfst; ++ ++ /* Per channel tail displacement field offset. */ ++ tOCT6100_TLV_OFFSET PerChanTailDisplacementFieldOfst; ++ ++ /* Per channel tail length field offset. */ ++ tOCT6100_TLV_OFFSET PerChanTailLengthFieldOfst; ++ ++ /* AF control/echo cancellation bypass. */ ++ tOCT6100_TLV_OFFSET AftControlOfst; ++ ++ /* Voice detected stat field offset. */ ++ tOCT6100_TLV_OFFSET SinVoiceDetectedStatOfst; ++ ++ /* Rin currently applied gain field offset. */ ++ tOCT6100_TLV_OFFSET RinAppliedGainStatOfst; ++ ++ /* Sout currently applied gain field offset. */ ++ tOCT6100_TLV_OFFSET SoutAppliedGainStatOfst; ++ ++ /* Adaptive listener enhancement field offset. */ ++ tOCT6100_TLV_OFFSET AdaptiveAleOfst; ++ ++ /* Rin NR field offset. */ ++ tOCT6100_TLV_OFFSET RinAnrOfst; ++ ++ /* Rin NR value field offset. */ ++ tOCT6100_TLV_OFFSET RinAnrValOfst; ++ ++ /* Sin Mute field offset. */ ++ tOCT6100_TLV_OFFSET SinMuteOfst; ++ ++ /* Rin Mute field offset. */ ++ tOCT6100_TLV_OFFSET RinMuteOfst; ++ ++ /* Sout ANR SNR enhancement offset. */ ++ tOCT6100_TLV_OFFSET AnrSnrEnhancementOfst; ++ ++ /* Sout ANR voice-noise segregation offset. */ ++ tOCT6100_TLV_OFFSET AnrVoiceNoiseSegregationOfst; ++ ++ /* Tone disabler VQE activation delay offset. */ ++ tOCT6100_TLV_OFFSET ToneDisablerVqeActivationDelayOfst; ++ ++ /* AF tail displacement value configuration offset. */ ++ tOCT6100_TLV_OFFSET AfTailDisplacementFieldOfst; ++ ++ /* Pouch counter field offset. */ ++ tOCT6100_TLV_OFFSET PouchCounterFieldOfst; ++ ++ /* Acoustic echo tail length. */ ++ tOCT6100_TLV_OFFSET AecTailLengthFieldOfst; ++ ++ /* Is ISR called field offset. */ ++ tOCT6100_TLV_OFFSET IsIsrCalledFieldOfst; ++ ++ /* Music protection enable field offset. */ ++ tOCT6100_TLV_OFFSET MusicProtectionFieldOfst; ++ ++ /* Rin port energy level statistics field offset. */ ++ tOCT6100_TLV_OFFSET RinEnergyStatFieldOfst; ++ ++ /* Sout port energy level statistics field offset. */ ++ tOCT6100_TLV_OFFSET SoutEnergyStatFieldOfst; ++ ++ /* Double talk behavior field offset. */ ++ tOCT6100_TLV_OFFSET DoubleTalkBehaviorFieldOfst; ++ ++ /* Idle code detection field offset. */ ++ tOCT6100_TLV_OFFSET IdleCodeDetectionFieldOfst; ++ ++ /* TSI memory mapping information.*/ ++ UINT32 ulNumTsiEntries; ++ ++ /*-----------------------------------------------------------------------------*/ ++ ++} tOCT6100_API_MEMORY_MAP, *tPOCT6100_API_MEMORY_MAP; ++ ++typedef struct _OCT6100_API_SOFT_BUFS_ ++{ ++ /* To avoid compilation errors. */ ++ UINT32 ulDummyVariable; ++ ++ /* Tone events buffer pointers. */ ++ UINT32 ulToneEventBufferWritePtr; ++ UINT32 ulToneEventBufferReadPtr; ++ UINT32 ulToneEventBufferSize; ++ UINT32 ulToneEventBufferMemOfst; ++ UINT32 ulToneEventBufferOverflowCnt; ++ ++ /* Playout events buffer pointers. */ ++ UINT32 ulBufPlayoutEventBufferWritePtr; ++ UINT32 ulBufPlayoutEventBufferReadPtr; ++ UINT32 ulBufPlayoutEventBufferSize; ++ UINT32 ulBufPlayoutEventBufferMemOfst; ++ UINT32 ulBufPlayoutEventBufferOverflowCnt; ++ ++} tOCT6100_API_SOFT_BUFS, *tPOCT6100_API_SOFT_BUFS; ++ ++typedef struct _OCT6100_API_IMAGE_REGION_ ++{ ++ UINT32 ulPart1Size; ++ UINT32 ulPart2Size; ++ UINT32 ulClockInfo; ++ ++ UINT32 ulReserved; ++ ++ UINT32 ulPart1BaseAddress; ++ UINT32 ulPart2BaseAddress; ++ ++} tOCT6100_API_IMAGE_REGION, *tPOCT6100_API_IMAGE_REGION; ++ ++typedef struct _OCT6100_API_IMAGE_INFO_ ++{ ++ UINT8 fBufferPlayout; ++ UINT8 fAdaptiveNoiseReduction; ++ UINT8 fRinDcOffsetRemoval; ++ UINT8 fSinDcOffsetRemoval; ++ ++ UINT8 fRinAutoLevelControl; ++ UINT8 fSoutAutoLevelControl; ++ UINT8 fRinHighLevelCompensation; ++ UINT8 fSoutHighLevelCompensation; ++ ++ UINT8 fAlcHlcStatus; ++ UINT8 fComfortNoise; ++ UINT8 fNlpControl; ++ UINT8 fSilenceSuppression; ++ ++ UINT8 fToneDisabler; ++ UINT8 fTailDisplacement; ++ UINT8 fPerChannelTailDisplacement; ++ UINT8 fAcousticEcho; ++ ++ UINT8 fAecEnabled; ++ UINT8 fToneRemoval; ++ UINT8 fDefaultErl; ++ UINT8 fMaxEchoPoint; ++ ++ UINT8 fNonLinearityBehaviorA; ++ UINT8 fNonLinearityBehaviorB; ++ UINT8 fAecDefaultErl; ++ UINT8 fAdpcm; ++ ++ UINT8 fConferencing; ++ UINT8 fConferencingNoiseReduction; ++ UINT8 fMusicProtection; ++ UINT8 fDominantSpeakerEnabled; ++ ++ UINT8 fAftControl; ++ UINT8 fSinVoiceDetectedStat; ++ UINT8 fRinAppliedGainStat; ++ UINT8 fSoutAppliedGainStat; ++ ++ UINT8 fListenerEnhancement; ++ UINT8 fRoutNoiseReduction; ++ UINT8 fRoutNoiseReductionLevel; ++ UINT8 fRinMute; ++ UINT8 fSinMute; ++ ++ UINT8 fAnrSnrEnhancement; ++ UINT8 fAnrVoiceNoiseSegregation; ++ UINT8 fRinBufferPlayoutHardSkip; ++ UINT8 fSoutBufferPlayoutHardSkip; ++ ++ UINT16 usMaxNumberOfChannels; ++ UINT8 fPerChannelTailLength; ++ UINT8 fToneDisablerVqeActivationDelay; ++ ++ UINT32 ulToneProfileNumber; ++ ++ UINT16 usMaxTailDisplacement; ++ UINT16 usMaxTailLength; ++ ++ UINT8 byNumToneDetectors; ++ UINT8 byMaxNumberPlayoutEvents; ++ ++ UINT8 fAfTailDisplacement; ++ UINT8 fAecTailLength; ++ ++ UINT8 fMusicProtectionConfiguration; ++ UINT8 byImageType; ++ ++ UINT8 fBufferPlayoutSkipInEvents; ++ UINT8 fSoutNoiseBleaching; ++ ++ UINT8 fRinEnergyStat; ++ UINT8 fSoutEnergyStat; ++ ++ UINT8 fDoubleTalkBehavior; ++ UINT8 fDoubleTalkBehaviorFieldOfst; ++ ++ UINT8 fIdleCodeDetection; ++ UINT8 fIdleCodeDetectionConfiguration; ++ ++ UINT8 fSinLevel; ++ ++ ++ ++ UINT8 szVersionNumber[ cOCT6100_VERSION_NUMBER_MAX_SIZE ]; ++ UINT32 ulBuildId; ++ ++ tOCT6100_TLV_TONE_INFO aToneInfo[ cOCT6100_MAX_TONE_EVENT ]; ++ ++} tOCT6100_API_IMAGE_INFO, *tPOCT6100_API_IMAGE_INFO; ++ ++typedef struct _OCT6100_API_MIXER_ ++{ ++ /* Pointer to the various event region. */ ++ UINT16 usFirstSoutCopyEventPtr; ++ UINT16 usLastSoutCopyEventPtr; ++ ++ UINT16 usFirstBridgeEventPtr; ++ UINT16 usLastBridgeEventPtr; ++ ++ UINT16 usFirstSinCopyEventPtr; ++ UINT16 usLastSinCopyEventPtr; ++ ++ /* Recording event info. */ ++ UINT16 usRecordCopyEventIndex; ++ UINT16 usRecordSinEventIndex; ++ ++} tOCT6100_API_MIXER, tPOCT6100_API_MIXER; ++ ++ ++typedef struct _OCT6100_API_BUFFER_PLAYOUT_MALLOC_INFO_ ++{ ++ /* Next node to be checked for free memory. */ ++ UINT32 ulRovingNode; ++ ++ /* First unused node in the unused list. */ ++ UINT32 ulFirstUnusedNode; ++ ++ /* Last unused node in the unused list. */ ++ UINT32 ulLastUnusedNode; ++ ++ /* Count of unused nodes. */ ++ UINT32 ulUnusedNodeCnt; ++ ++} tOCT6100_API_BUFFER_PLAYOUT_MALLOC_INFO, *tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_INFO; ++ ++ ++ ++ ++#endif /* __OCT6100_CHIP_OPEN_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,241 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_open_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_chip_open.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_chip_open_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 54 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHIP_OPEN_PUB_H__ ++#define __OCT6100_CHIP_OPEN_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_CHIP_OPEN_ ++{ ++ UINT32 ulUserChipId; ++ BOOL fMultiProcessSystem; ++ PVOID pProcessContext; ++ ++ UINT32 ulMaxRwAccesses; ++ ++ unsigned char const *pbyImageFile; /* Byte pointer to the image file to be uploaded into the chip. */ ++ UINT32 ulImageSize; /* Size of the image file (in bytes). */ ++ ++ UINT32 ulMemClkFreq; /* 10 - 133.3 MHz. */ ++ UINT32 ulUpclkFreq; /* 1 - 66.6 MHz. */ ++ BOOL fEnableMemClkOut; ++ ++ UINT32 ulMemoryType; /* SDRAM or DDR type external memory. */ ++ UINT32 ulNumMemoryChips; /* Number of memory chips present. */ ++ UINT32 ulMemoryChipSize; /* The size of the memory chips. */ ++ ++ UINT32 ulTailDisplacement; /* Tail displacement supported by the chip. */ ++ ++ BOOL fEnableAcousticEcho;/* Acoustic echo cancellation enabled. */ ++ ++ /* Resource allocation parameters. */ ++ UINT32 ulMaxChannels; ++ UINT32 ulMaxTsiCncts; ++ UINT32 ulMaxBiDirChannels; ++ UINT32 ulMaxConfBridges; ++ UINT32 ulMaxFlexibleConfParticipants; ++ UINT32 ulMaxPlayoutBuffers; ++ ++ ++ UINT32 ulMaxPhasingTssts; ++ UINT32 ulMaxAdpcmChannels; ++ BOOL fUseSynchTimestamp; ++ UINT32 aulTimestampTimeslots[ 4 ]; ++ UINT32 aulTimestampStreams[ 4 ]; ++ UINT32 ulInterruptPolarity; ++ tOCT6100_INTERRUPT_CONFIGURE InterruptConfig; ++ ++ UINT32 aulTdmStreamFreqs[ cOCT6100_TDM_STREAM_MAX_GROUPS ]; ++ UINT32 ulMaxTdmStreams; ++ UINT32 ulTdmSampling; ++ ++ BOOL fEnableFastH100Mode; ++ ++ UINT32 ulSoftToneEventsBufSize; /* In events. */ ++ BOOL fEnableExtToneDetection; ++ BOOL fEnable2100StopEvent; ++ ++ ++ UINT32 ulSoftBufferPlayoutEventsBufSize; /* In events. */ ++ UINT32 ulMaxRemoteDebugSessions; ++ ++ BOOL fEnableChannelRecording; ++ ++ BOOL fEnableProductionBist; ++ UINT32 ulProductionBistMode; ++ UINT32 ulNumProductionBistLoops; ++ ++} tOCT6100_CHIP_OPEN, *tPOCT6100_CHIP_OPEN; ++ ++typedef struct _OCT6100_GET_INSTANCE_SIZE_ ++{ ++ UINT32 ulApiInstanceSize; ++ ++} tOCT6100_GET_INSTANCE_SIZE, *tPOCT6100_GET_INSTANCE_SIZE; ++ ++typedef struct _OCT6100_CHIP_CLOSE_ ++{ ++ UINT32 ulDummyVariable; ++ ++} tOCT6100_CHIP_CLOSE, *tPOCT6100_CHIP_CLOSE; ++ ++typedef struct _OCT6100_CREATE_LOCAL_INSTANCE_ ++{ ++ tPOCT6100_INSTANCE_API pApiInstShared; ++ tPOCT6100_INSTANCE_API pApiInstLocal; ++ PVOID pProcessContext; ++ UINT32 ulUserChipId; ++ ++} tOCT6100_CREATE_LOCAL_INSTANCE, *tPOCT6100_CREATE_LOCAL_INSTANCE; ++ ++typedef struct _OCT6100_DESTROY_LOCAL_INSTANCE_ ++{ ++ UINT32 ulDummy; ++ ++} tOCT6100_DESTROY_LOCAL_INSTANCE, *tPOCT6100_DESTROY_LOCAL_INSTANCE; ++ ++typedef struct _OCT6100_GET_HW_REVISION_ ++{ ++ UINT32 ulUserChipId; ++ PVOID pProcessContext; ++ UINT32 ulRevisionNum; ++ ++} tOCT6100_GET_HW_REVISION, *tPOCT6100_GET_HW_REVISION; ++ ++typedef struct _OCT6100_FREE_RESOURCES_ ++{ ++ BOOL fFreeTsiConnections; ++ BOOL fFreeConferenceBridges; ++ BOOL fFreePlayoutBuffers; ++ BOOL fFreePhasingTssts; ++ BOOL fFreeAdpcmChannels; ++ ++} tOCT6100_FREE_RESOURCES, *tPOCT6100_FREE_RESOURCES; ++ ++typedef struct _OCT6100_PRODUCTION_BIST_ ++{ ++ UINT32 ulCurrentAddress; ++ UINT32 ulCurrentLoop; ++ UINT32 ulCurrentTest; ++ UINT32 ulBistStatus; ++ UINT32 ulFailedAddress; ++ UINT32 ulReadValue; ++ UINT32 ulExpectedValue; ++ ++} tOCT6100_PRODUCTION_BIST, *tPOCT6100_PRODUCTION_BIST; ++ ++typedef struct _OCT6100_API_GET_VERSION_ ++{ ++ UINT8 achApiVersion[ cOCT6100_API_VERSION_STRING_LENGTH ]; ++ ++} tOCT6100_API_GET_VERSION, *tPOCT6100_API_GET_VERSION; ++ ++typedef struct _OCT6100_API_GET_CAPACITY_PINS_ ++{ ++ UINT32 ulUserChipId; ++ PVOID pProcessContext; ++ UINT32 ulMemoryType; /* SDRAM or DDR type external memory. */ ++ BOOL fEnableMemClkOut; ++ UINT32 ulMemClkFreq; ++ UINT32 ulCapacityValue; ++} tOCT6100_API_GET_CAPACITY_PINS, *tPOCT6100_API_GET_CAPACITY_PINS; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ChipOpenDef( ++ OUT tPOCT6100_CHIP_OPEN f_pChipOpen ); ++UINT32 Oct6100ChipOpen( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHIP_OPEN f_pChipOpen ); ++ ++UINT32 Oct6100ChipCloseDef( ++ OUT tPOCT6100_CHIP_CLOSE f_pChipClose ); ++UINT32 Oct6100ChipClose( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHIP_CLOSE f_pChipClose ); ++ ++UINT32 Oct6100GetInstanceSizeDef( ++ OUT tPOCT6100_GET_INSTANCE_SIZE f_pInstanceSize ); ++UINT32 Oct6100GetInstanceSize( ++ IN OUT tPOCT6100_CHIP_OPEN f_pChipOpen, ++ IN OUT tPOCT6100_GET_INSTANCE_SIZE f_pInstanceSize ); ++ ++UINT32 Oct6100CreateLocalInstanceDef( ++ OUT tPOCT6100_CREATE_LOCAL_INSTANCE f_pCreateLocal ); ++UINT32 Oct6100CreateLocalInstance( ++ IN OUT tPOCT6100_CREATE_LOCAL_INSTANCE f_pCreateLocal ); ++ ++UINT32 Oct6100DestroyLocalInstanceDef( ++ OUT tPOCT6100_DESTROY_LOCAL_INSTANCE f_pDestroyLocal ); ++UINT32 Oct6100DestroyLocalInstance( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_DESTROY_LOCAL_INSTANCE f_pDestroyLocal ); ++ ++UINT32 Oct6100ApiGetVersionDef( ++ OUT tPOCT6100_API_GET_VERSION f_pApiGetVersion ); ++UINT32 Oct6100ApiGetVersion( ++ IN OUT tPOCT6100_API_GET_VERSION f_pApiGetVersion ); ++ ++UINT32 Oct6100GetHwRevisionDef( ++ OUT tPOCT6100_GET_HW_REVISION f_pRevision ); ++UINT32 Oct6100GetHwRevision( ++ IN OUT tPOCT6100_GET_HW_REVISION f_pRevision ); ++ ++UINT32 Oct6100FreeResourcesDef( ++ OUT tPOCT6100_FREE_RESOURCES f_pFreeResources ); ++UINT32 Oct6100FreeResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_FREE_RESOURCES f_pFreeResources ); ++ ++UINT32 Oct6100ProductionBistDef( ++ OUT tPOCT6100_PRODUCTION_BIST f_pProductionBist ); ++UINT32 Oct6100ProductionBist( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PRODUCTION_BIST f_pProductionBist ); ++ ++UINT32 Oct6100ApiGetCapacityPinsDef( ++ tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins); ++ ++UINT32 Oct6100ApiGetCapacityPins( ++ tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins ); ++ ++ ++#endif /* __OCT6100_CHIP_OPEN_PUB_H__ */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,84 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_stats_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_chip_stats.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_chip_stats_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 21 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHIP_STATS_INST_H__ ++#define __OCT6100_CHIP_STATS_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_CHIP_ERROR_STATS_ ++{ ++ UINT8 fFatalChipError; ++ ++ UINT32 ulInternalReadTimeoutCnt; ++ UINT32 ulSdramRefreshTooLateCnt; ++ UINT32 ulPllJitterErrorCnt; ++ ++ /* Internal tone detector error counter. */ ++ UINT32 ulToneDetectorErrorCnt; ++ ++ UINT32 ulOverflowToneEventsCnt; ++ ++ UINT32 ulH100OutOfSyncCnt; ++ UINT32 ulH100ClkABadCnt; ++ UINT32 ulH100ClkBBadCnt; ++ UINT32 ulH100FrameABadCnt; ++ ++ ++ ++} tOCT6100_API_CHIP_ERROR_STATS, *tPOCT6100_API_CHIP_ERROR_STATS; ++ ++typedef struct _OCT6100_API_CHIP_STATS_ ++{ ++ UINT16 usNumberChannels; ++ UINT16 usNumberBiDirChannels; ++ UINT16 usNumberTsiCncts; ++ UINT16 usNumberConfBridges; ++ UINT16 usNumberPlayoutBuffers; ++ UINT16 usNumEcChanUsingMixer; ++ ++ UINT32 ulPlayoutMemUsed; ++ UINT16 usNumberActiveBufPlayoutPorts; ++ ++ UINT16 usNumberPhasingTssts; ++ UINT16 usNumberAdpcmChans; ++ ++} tOCT6100_API_CHIP_STATS, *tPOCT6100_API_CHIP_STATS; ++ ++#endif /* __OCT6100_CHIP_STATS_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,150 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_stats_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_chip_stats.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_chip_stats_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 59 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHIP_STATS_PUB_H__ ++#define __OCT6100_CHIP_STATS_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_CHIP_STATS_ ++{ ++ BOOL fResetChipStats; ++ ++ UINT32 ulNumberChannels; ++ UINT32 ulNumberTsiCncts; ++ UINT32 ulNumberConfBridges; ++ UINT32 ulNumberPlayoutBuffers; ++ UINT32 ulPlayoutFreeMemSize; ++ UINT32 ulNumberPhasingTssts; ++ UINT32 ulNumberAdpcmChannels; ++ ++ UINT32 ulH100OutOfSynchCount; ++ UINT32 ulH100ClockABadCount; ++ UINT32 ulH100FrameABadCount; ++ UINT32 ulH100ClockBBadCount; ++ ++ UINT32 ulInternalReadTimeoutCount; ++ UINT32 ulSdramRefreshTooLateCount; ++ UINT32 ulPllJitterErrorCount; ++ ++ UINT32 ulOverflowToneEventsCount; ++ UINT32 ulSoftOverflowToneEventsCount; ++ ++ UINT32 ulSoftOverflowBufferPlayoutEventsCount; ++ ++} tOCT6100_CHIP_STATS, *tPOCT6100_CHIP_STATS; ++ ++typedef struct _OCT6100_CHIP_TONE_INFO_ ++{ ++ UINT32 ulToneID; ++ UINT32 ulDetectionPort; ++ ++ UINT8 aszToneName[ cOCT6100_TLV_MAX_TONE_NAME_SIZE ]; ++ ++} tOCT6100_CHIP_TONE_INFO, *tPOCT6100_CHIP_TONE_INFO; ++ ++typedef struct _OCT6100_CHIP_IMAGE_INFO_ ++{ ++ BOOL fBufferPlayout; ++ BOOL fAdaptiveNoiseReduction; ++ BOOL fSoutNoiseBleaching; ++ BOOL fAutoLevelControl; ++ BOOL fHighLevelCompensation; ++ BOOL fSilenceSuppression; ++ ++ BOOL fAdpcm; ++ BOOL fConferencing; ++ BOOL fConferencingNoiseReduction; ++ BOOL fDominantSpeaker; ++ ++ BOOL fAcousticEcho; ++ BOOL fAecTailLength; ++ BOOL fToneRemoval; ++ ++ BOOL fDefaultErl; ++ BOOL fNonLinearityBehaviorA; ++ BOOL fNonLinearityBehaviorB; ++ BOOL fPerChannelTailDisplacement; ++ BOOL fPerChannelTailLength; ++ BOOL fListenerEnhancement; ++ BOOL fRoutNoiseReduction; ++ BOOL fRoutNoiseReductionLevel; ++ BOOL fAnrSnrEnhancement; ++ BOOL fAnrVoiceNoiseSegregation; ++ BOOL fToneDisablerVqeActivationDelay; ++ BOOL fMusicProtection; ++ BOOL fDoubleTalkBehavior; ++ BOOL fIdleCodeDetection; ++ BOOL fSinLevel; ++ ++ UINT32 ulMaxChannels; ++ UINT32 ulNumTonesAvailable; ++ UINT32 ulToneProfileNumber; ++ UINT32 ulMaxTailDisplacement; ++ UINT32 ulMaxTailLength; ++ UINT32 ulDebugEventSize; ++ UINT32 ulMaxPlayoutEvents; ++ ++ UINT32 ulImageType; ++ ++ UINT8 szVersionNumber[ cOCT6100_VERSION_NUMBER_MAX_SIZE ]; ++ UINT32 ulBuildId; ++ ++ tOCT6100_CHIP_TONE_INFO aToneInfo[ cOCT6100_MAX_TONE_EVENT ]; ++ ++} tOCT6100_CHIP_IMAGE_INFO, *tPOCT6100_CHIP_IMAGE_INFO; ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ChipGetStatsDef( ++ OUT tPOCT6100_CHIP_STATS f_pChipStats ); ++ ++UINT32 Oct6100ChipGetStats( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_CHIP_STATS f_pChipStats ); ++ ++UINT32 Oct6100ChipGetImageInfoDef( ++ OUT tPOCT6100_CHIP_IMAGE_INFO f_pChipImageInfo ); ++ ++UINT32 Oct6100ChipGetImageInfo( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ OUT tPOCT6100_CHIP_IMAGE_INFO f_pChipImageInfo ); ++ ++#endif /* __OCT6100_CHIP_STATS_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,104 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_conf_bridge_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_conf_bridge.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_conf_bridge_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 19 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CONF_BRIDGE_INST_H__ ++#define __OCT6100_CONF_BRIDGE_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_CONF_BRIDGE_ ++{ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved; ++ ++ /* Entry counter for the resources. */ ++ UINT8 byEntryOpenCnt; ++ ++ /* Next bridge pointer. */ ++ UINT16 usNextBridgePtr; ++ ++ /* Previous bridge pointer. */ ++ UINT16 usPrevBridgePtr; ++ ++ /* Number of clients connected to the bridge. */ ++ UINT16 usNumClients; ++ ++ /* Store the index of the load event, to diffentiate him form the accumulate. */ ++ UINT16 usLoadIndex; ++ ++ /* Pointer to the first bridge events.*/ ++ UINT16 usFirstLoadEventPtr; ++ UINT16 usFirstSubStoreEventPtr; ++ UINT16 usLastSubStoreEventPtr; ++ ++ /* Pointer to the silence load event, if it exists. */ ++ UINT16 usSilenceLoadEventPtr; ++ ++ /* Flag specifying whether the dominant speaker is set or not. */ ++ UINT16 usDominantSpeakerChanIndex; ++ UINT8 fDominantSpeakerSet; ++ ++ /* Flag specifying if this is flexible conferencing bridge. */ ++ UINT8 fFlexibleConferencing; ++ ++ /* Number of clients being tapped. */ ++ UINT16 usNumTappedClients; ++ ++} tOCT6100_API_CONF_BRIDGE, *tPOCT6100_API_CONF_BRIDGE; ++ ++typedef struct _OCT6100_API_FLEX_CONF_PARTICIPANT_ ++{ ++ /* Input port of the conferencing for this participant. */ ++ UINT32 ulInputPort; ++ ++ /* Whether the flexible mixer has been created. */ ++ UINT8 fFlexibleMixerCreated; ++ ++ /* Listener mask ( who can hear us ). */ ++ UINT32 ulListenerMask; ++ ++ /* Our index in the listener mask. */ ++ UINT32 ulListenerMaskIndex; ++ ++ /* Mixer event indexes for this participant's mixer. */ ++ UINT16 ausLoadOrAccumulateEventIndex[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; ++ ++} tOCT6100_API_FLEX_CONF_PARTICIPANT, *tPOCT6100_API_FLEX_CONF_PARTICIPANT; ++ ++#endif /* __OCT6100_CONF_BRIDGE_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,169 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_conf_bridge_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_conf_bridge.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_conf_bridge_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 22 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CONF_BRIDGE_PUB_H__ ++#define __OCT6100_CONF_BRIDGE_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_CONF_BRIDGE_OPEN_ ++{ ++ PUINT32 pulConfBridgeHndl; /* Handle returned when the bridge is opened. */ ++ BOOL fFlexibleConferencing; ++ ++} tOCT6100_CONF_BRIDGE_OPEN, *tPOCT6100_CONF_BRIDGE_OPEN; ++ ++typedef struct _OCT6100_CONF_BRIDGE_CLOSE_ ++{ ++ UINT32 ulConfBridgeHndl; ++ ++} tOCT6100_CONF_BRIDGE_CLOSE, *tPOCT6100_CONF_BRIDGE_CLOSE; ++ ++typedef struct _OCT6100_CONF_BRIDGE_CHAN_ADD_ ++{ ++ UINT32 ulConfBridgeHndl; ++ UINT32 ulChannelHndl; ++ UINT32 ulInputPort; ++ UINT32 ulListenerMaskIndex; ++ UINT32 ulListenerMask; ++ BOOL fMute; ++ UINT32 ulTappedChannelHndl; ++ ++} tOCT6100_CONF_BRIDGE_CHAN_ADD, *tPOCT6100_CONF_BRIDGE_CHAN_ADD; ++ ++typedef struct _OCT6100_CONF_BRIDGE_CHAN_REMOVE_ ++{ ++ UINT32 ulConfBridgeHndl; ++ UINT32 ulChannelHndl; ++ BOOL fRemoveAll; ++ ++} tOCT6100_CONF_BRIDGE_CHAN_REMOVE, *tPOCT6100_CONF_BRIDGE_CHAN_REMOVE; ++ ++typedef struct _OCT6100_CONF_BRIDGE_CHAN_MUTE_ ++{ ++ UINT32 ulChannelHndl; ++ ++} tOCT6100_CONF_BRIDGE_CHAN_MUTE, *tPOCT6100_CONF_BRIDGE_CHAN_MUTE; ++ ++typedef struct _OCT6100_CONF_BRIDGE_CHAN_UNMUTE_ ++{ ++ UINT32 ulChannelHndl; ++ ++} tOCT6100_CONF_BRIDGE_CHAN_UNMUTE, *tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE; ++ ++typedef struct _OCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET_ ++{ ++ UINT32 ulConfBridgeHndl; ++ UINT32 ulChannelHndl; ++ ++} tOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET, *tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET; ++ ++typedef struct _OCT6100_CONF_BRIDGE_MASK_CHANGE_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulNewListenerMask; ++ ++} tOCT6100_CONF_BRIDGE_MASK_CHANGE, *tPOCT6100_CONF_BRIDGE_MASK_CHANGE; ++ ++typedef struct _OCT6100_CONF_BRIDGE_STATS_ ++{ ++ UINT32 ulConfBridgeHndl; ++ UINT32 ulNumChannels; ++ UINT32 ulNumTappedChannels; ++ BOOL fFlexibleConferencing; ++ ++} tOCT6100_CONF_BRIDGE_STATS, *tPOCT6100_CONF_BRIDGE_STATS; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ConfBridgeOpenDef( ++ OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ); ++UINT32 Oct6100ConfBridgeOpen( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ); ++ ++UINT32 Oct6100ConfBridgeCloseDef( ++ OUT tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ); ++UINT32 Oct6100ConfBridgeClose( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ); ++ ++UINT32 Oct6100ConfBridgeChanAddDef( ++ OUT tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ); ++UINT32 Oct6100ConfBridgeChanAdd( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ); ++ ++UINT32 Oct6100ConfBridgeChanRemoveDef( ++ OUT tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ); ++UINT32 Oct6100ConfBridgeChanRemove( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ); ++ ++UINT32 Oct6100ConfBridgeChanMuteDef( ++ OUT tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ); ++UINT32 Oct6100ConfBridgeChanMute( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ); ++ ++UINT32 Oct6100ConfBridgeChanUnMuteDef( ++ OUT tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ); ++UINT32 Oct6100ConfBridgeChanUnMute( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ); ++ ++UINT32 Oct6100ConfBridgeDominantSpeakerSetDef( ++ OUT tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ); ++UINT32 Oct6100ConfBridgeDominantSpeakerSet( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ); ++ ++UINT32 Oct6100ConfBridgeMaskChangeDef( ++ OUT tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ); ++UINT32 Oct6100ConfBridgeMaskChange( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ); ++ ++UINT32 Oct6100ConfBridgeGetStatsDef( ++ OUT tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ); ++UINT32 Oct6100ConfBridgeGetStats( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ); ++ ++#endif /* __OCT6100_CONF_BRIDGE_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,124 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_debug_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_debug.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_debug_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 10 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_DEBUG_INST_H__ ++#define __OCT6100_DEBUG_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_DEBUG_ ++{ ++ /* Information from the TLVs. */ ++ UINT32 ulDebugEventSize; ++ UINT32 ulMatrixBaseAddress; ++ UINT32 ulDebugChanStatsByteSize; ++ UINT32 ulDebugChanLiteStatsByteSize; ++ UINT32 ulHotChannelSelectBaseAddress; ++ UINT32 ulMatrixTimestampBaseAddress; ++ UINT32 ulAfWritePtrByteOffset; ++ UINT32 ulRecordedPcmEventByteSize; ++ UINT32 ulMatrixWpBaseAddress; ++ ++ /* Pouch counter presence in the image. */ ++ UINT8 fPouchCounter; ++ ++ /* Record channel indexes. */ ++ UINT16 usRecordMemIndex; ++ UINT16 usRecordChanIndex; ++ ++ UINT16 usRecordRinRoutTsiMemIndex; ++ UINT16 usRecordSinSoutTsiMemIndex; ++ ++ /* Debug channel information.*/ ++ UINT16 usCurrentDebugChanIndex; ++ ++ /* Matrix event mask. */ ++ UINT16 usMatrixCBMask; ++ ++ /* If data is being dumped now. */ ++ UINT8 fDebugDataBeingDumped; ++ ++ /* Index of the last event retrieved. */ ++ UINT16 usLastDebugEventIndex; ++ ++ /* Number of events to retrieve. */ ++ UINT16 usNumEvents; ++ ++ /* Chip debug event write ptr. */ ++ UINT16 usChipDebugEventWritePtr; ++ ++ /* Hot channel read data. */ ++ UINT16 ausHotChannelData[ 2 ]; ++ ++ /* Last PCM sample index. */ ++ UINT32 ulLastPcmSampleIndex; ++ ++ /* Last AF log read pointer. */ ++ UINT16 usLastAfLogReadPtr; ++ ++ /* AF log hardware write pointer. */ ++ UINT16 usAfLogWritePtr; ++ ++ /* Last tone event index retrieved. */ ++ UINT16 usLastToneEventIndex; ++ ++ /* Whether the image version string has been copied in the user buffer. */ ++ BOOL fImageVersionCopied; ++ ++ /* Whether the api version string has been copied in the user buffer. */ ++ BOOL fApiVersionCopied; ++ ++ /* Total number of bytes that will be returned for the current dump. */ ++ UINT32 ulDebugDataTotalNumBytes; ++ ++ /* Field to detect if the ISR is called present? */ ++ BOOL fIsIsrCalledField; ++ ++ /* Remaining number of bytes that will be returned for the current dump. */ ++ UINT32 ulDebugDataRemainingNumBytes; ++ ++ /* AF events control block size. */ ++ UINT32 ulAfEventCbByteSize; ++ ++ /* Current user selected data mode. Must be kept constant throughout a debug session. */ ++ UINT32 ulCurrentGetDataMode; ++ ++} tOCT6100_API_DEBUG, *tPOCT6100_API_DEBUG; ++ ++#endif /* __OCT6100_DEBUG_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,76 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_debug_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_debug.c. All elements defined in this file are for public ++ usage of the API. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 14 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_DEBUG_PUB_H__ ++#define __OCT6100_DEBUG_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_DEBUG_SELECT_CHANNEL_ ++{ ++ UINT32 ulChannelHndl; ++ ++} tOCT6100_DEBUG_SELECT_CHANNEL, *tPOCT6100_DEBUG_SELECT_CHANNEL; ++ ++typedef struct _OCT6100_DEBUG_GET_DATA_ ++{ ++ UINT32 ulGetDataMode; ++ UINT32 ulGetDataContent; ++ UINT32 ulRemainingNumBytes; ++ UINT32 ulTotalNumBytes; ++ UINT32 ulMaxBytes; ++ UINT32 ulValidNumBytes; ++ PUINT8 pbyData; ++ ++} tOCT6100_DEBUG_GET_DATA, *tPOCT6100_DEBUG_GET_DATA; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100DebugSelectChannelDef( ++ OUT tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan ); ++UINT32 Oct6100DebugSelectChannel( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan ); ++ ++UINT32 Oct6100DebugGetDataDef( ++ OUT tPOCT6100_DEBUG_GET_DATA f_pGetData ); ++UINT32 Oct6100DebugGetData( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_DEBUG_GET_DATA f_pGetData ); ++ ++#endif /* __OCT6100_DEBUG_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_defines.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_defines.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_defines.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_defines.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,679 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_defines.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Header file containing all defines used throughout the API. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.7 ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 171 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_DEFINES_H__ ++#define __OCT6100_DEFINES_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++/***************************** DEFINES *************************************/ ++ ++/* 32-bits values. */ ++#define cOCT6100_FFFFFFFF 0xFFFFFFFF ++#define cOCT6100_FFFFFFFE 0xFFFFFFFE ++#define cOCT6100_7FFFFFFF 0x7FFFFFFF ++ ++/* 16-bits values. */ ++#define cOCT6100_FFFD 0xFFFD ++#define cOCT6100_FFFE 0xFFFE ++#define cOCT6100_FFFF 0xFFFF ++#define cOCT6100_7FFF 0x7FFF ++ ++/* 8-bits values. */ ++#define cOCT6100_FF 0xFF ++ ++#define cOCT6100_CURRENT_VALUE cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_CHIP_ID cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_HANDLE cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_TIMESLOT cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_STREAM cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_VALUE cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_STAT cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_STAT_W cOCT6100_FFFF ++#define cOCT6100_INVALID_PCM_LAW cOCT6100_FF ++#define cOCT6100_INVALID_EVENT cOCT6100_FFFF ++#define cOCT6100_INVALID_INDEX cOCT6100_FFFF ++#define cOCT6100_INVALID_TONE cOCT6100_FFFFFFFF ++#define cOCT6100_INVALID_PORT cOCT6100_FF ++ ++#define cOCT6100_AUTO_SELECT cOCT6100_FFFFFFFE ++#define cOCT6100_AUTO_SELECT_TAIL cOCT6100_FFFE ++ ++#define cOCT6100_INVALID_BOOL 2 ++ ++#define cOCT6100_KEEP_PREVIOUS_SETTING 0x70100000 ++ ++#define cOCT6100_INVALID_SIGNED_STAT cOCT6100_7FFFFFFF ++#define cOCT6100_INVALID_SIGNED_STAT_W cOCT6100_7FFF ++#define cOCT6100_INVALID_ECHO_DELAY 0x400 ++ ++ ++ ++#define cOCT6100_SIZE_128 128 ++#define cOCT6100_SIZE_256 256 ++#define cOCT6100_SIZE_512 512 ++#define cOCT6100_SIZE_1K 1024 ++#define cOCT6100_SIZE_2K 2048 ++#define cOCT6100_SIZE_4K 4096 ++#define cOCT6100_SIZE_8K 8192 ++#define cOCT6100_SIZE_16K 16384 ++#define cOCT6100_SIZE_32K 32768 ++#define cOCT6100_SIZE_64K 65536 ++#define cOCT6100_SIZE_128K 131072 ++#define cOCT6100_SIZE_256K 262144 ++#define cOCT6100_SIZE_512K 524288 ++#define cOCT6100_SIZE_1M 1048576 ++#define cOCT6100_SIZE_2M 2097152 ++#define cOCT6100_SIZE_4M 4194304 ++#define cOCT6100_SIZE_8M 8388608 ++#define cOCT6100_SIZE_16M 16777216 ++#define cOCT6100_SIZE_32M 33554432 ++#define cOCT6100_SIZE_64M 67108864 ++#define cOCT6100_SIZE_128M 134217728 ++#define cOCT6100_SIZE_256M 268435456 ++#define cOCT6100_SIZE_512M 536870912 ++#define cOCT6100_SIZE_1G 1073741824 ++#define cOCT6100_SIZE_2G 2147483648 ++ ++#define cOCT6100_HNDL_TAG_MASK 0xFF000000 ++#define cOCT6100_HNDL_INDEX_MASK 0x0000FFFF ++#define cOCT6100_ENTRY_OPEN_CNT_MASK 0x000000FF ++#define cOCT6100_ENTRY_OPEN_CNT_SHIFT 16 ++ ++#define cOCT6100_HNDL_TAG_INVALID 0xFF000000 ++ ++#define cOCT6100_HNDL_TAG_CHANNEL 0x01000000 ++#define cOCT6100_HNDL_TAG_TSI_CNCT 0x02000000 ++#define cOCT6100_HNDL_TAG_CONF_BRIDGE 0x03000000 ++#define cOCT6100_HNDL_TAG_PHASING_TSST 0x04000000 ++#define cOCT6100_HNDL_TAG_BIDIR_CHANNEL 0x05000000 ++#define cOCT6100_HNDL_TAG_COPY_EVENT 0x06000000 ++#define cOCT6100_HNDL_TAG_ADPCM_CHANNEL 0x07000000 ++ ++#define cOCT6100_INVALID_HANDLE_TYPE cOCT6100_INVALID_VALUE ++ ++#define cOCT6100_MEMORY_ROUND_SIZE 16 ++ ++#define mOCT6100_ROUND_MEMORY_SIZE( ulMemorySize, ulTempVar ) \ ++ if ((ulTempVar = ulMemorySize % cOCT6100_MEMORY_ROUND_SIZE) != 0) \ ++ ulMemorySize += cOCT6100_MEMORY_ROUND_SIZE - ulTempVar; ++ ++#define mOCT6100_ROUND_ADDRESS( ulAddress, ulBoundary, ulTempVar ) \ ++ if ((ulTempVar = ulAddress % ulBoundary) != 0) \ ++ ulAddress += ulBoundary - ulTempVar; ++ ++#define cOCT6100_INTERNAL_CLOCK_SOURCE 0 ++#define cOCT6100_EXTERNAL_CLOCK_SOURCE 1 ++ ++#define cOCT6100_ACTIVE_HIGH_POLARITY 0 ++#define cOCT6100_ACTIVE_LOW_POLARITY 1 ++ ++#define cOCT6100_TDM_SAMPLE_AT_3_QUARTERS 0 ++#define cOCT6100_TDM_SAMPLE_AT_RISING_EDGE 1 ++#define cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE 2 ++ ++#define cOCT6100_TDM_STREAM_FREQ_2MHZ 0 ++#define cOCT6100_TDM_STREAM_FREQ_4MHZ 1 ++#define cOCT6100_TDM_STREAM_FREQ_8MHZ 2 ++#define cOCT6100_TDM_STREAM_FREQ_16MHZ 3 ++ ++#define cOCT6100_TDM_STREAM_MAX_GROUPS 8 ++ ++#define cOCT6100_PCM_U_LAW 0 ++#define cOCT6100_PCM_A_LAW 1 ++#define cOCT6100_PCM_UNCHANGED 2 ++#define cOCT6100_ADPCM_ENCODED 3 ++ ++#define cOCT6100_INTERRUPT_DISABLE 0 ++#define cOCT6100_INTERRUPT_NO_TIMEOUT 1 ++#define cOCT6100_INTERRUPT_TIMEOUT 2 ++ ++#define cOCT6100_NUMBER_TSSTS_1 1 ++#define cOCT6100_NUMBER_TSSTS_2 2 ++ ++#define cOCT6100_G711_64KBPS 1 ++#define cOCT6100_G726_40KBPS 2 ++#define cOCT6100_G726_32KBPS 3 ++#define cOCT6100_G726_24KBPS 4 ++#define cOCT6100_G726_16KBPS 5 ++#define cOCT6100_G727_40KBPS_4_1 6 ++#define cOCT6100_G727_40KBPS_3_2 7 ++#define cOCT6100_G727_40KBPS_2_3 8 ++#define cOCT6100_G727_32KBPS_4_0 9 ++#define cOCT6100_G727_32KBPS_3_1 10 ++#define cOCT6100_G727_32KBPS_2_2 11 ++#define cOCT6100_G727_24KBPS_3_0 12 ++#define cOCT6100_G727_24KBPS_2_1 13 ++#define cOCT6100_G727_16KBPS_2_0 14 ++#define cOCT6100_G726_ENCODED 15 ++#define cOCT6100_G711_G726_ENCODED 16 ++#define cOCT6100_G711_G727_2C_ENCODED 17 ++#define cOCT6100_G711_G727_3C_ENCODED 18 ++#define cOCT6100_G711_G727_4C_ENCODED 19 ++#define cOCT6100_G727_2C_ENCODED 20 ++#define cOCT6100_G727_3C_ENCODED 21 ++#define cOCT6100_G727_4C_ENCODED 22 ++ ++#define cOCT6100_ADPCM_IN_HIGH_BITS 0 ++#define cOCT6100_ADPCM_IN_LOW_BITS 1 ++ ++/* The values of these defines must not change. */ ++#define cOCT6100_H100_TRACKA 0 ++#define cOCT6100_H100_TRACKB 1 ++#define cOCT6100_H100_TRACKA_FALLBACKB 2 ++#define cOCT6100_H100_TRACKB_FALLBACKA 3 ++#define cOCT6100_H100_DISABLED 4 ++#define cOCT6100_H100_MASTERA 5 ++#define cOCT6100_H100_BACKUPA 6 ++#define cOCT6100_H100_MASTERB 7 ++#define cOCT6100_H100_BACKUPB 8 ++ ++#define cOCT6100_FREE_TSST 0 ++#define cOCT6100_RX_TSST 16 ++#define cOCT6100_TX_TSST 32 ++ ++#define cOCT6100_INTRPT_ACTIVE 0 ++#define cOCT6100_INTRPT_WILL_TIMEOUT 1 ++#define cOCT6100_INTRPT_IN_TIMEOUT 2 ++#define cOCT6100_INTRPT_DISABLED 3 ++ ++#define cOCT6100_EXTERNAL_MEM_BIST_TIMEOUT 1000000 ++ ++/* Clocks defines */ ++#define cOCT6100_UPCLK_FREQ_33_33_MHZ 33333333 ++ ++#define cOCT6100_MCLK_FREQ_133_MHZ 133000000 ++#define cOCT6100_MCLK_FREQ_125_MHZ 125000000 ++#define cOCT6100_MCLK_FREQ_117_MHZ 117000000 ++#define cOCT6100_MCLK_FREQ_108_MHZ 108000000 ++#define cOCT6100_MCLK_FREQ_100_MHZ 100000000 ++#define cOCT6100_MCLK_FREQ_92_MHZ 92000000 ++#define cOCT6100_MCLK_FREQ_83_MHZ 83000000 ++#define cOCT6100_MCLK_FREQ_75_MHZ 75000000 ++ ++/* Tone buffer defines.*/ ++#define cOCT6100_MAX_NUM_TONE_BUFFERS 1344 ++#define cOCT6100_MAX_TONES_PER_CALL 32 ++ ++/* Memory defines.*/ ++#define cOCT6100_MEM_TYPE_SDR 0 ++#define cOCT6100_MEM_TYPE_DDR 1 ++#define cOCT6100_MEM_TYPE_SDR_PLL_BYPASS 2 ++ ++#define cOCT6100_MEMORY_CHIP_SIZE_8MB cOCT6100_SIZE_8M ++#define cOCT6100_MEMORY_CHIP_SIZE_16MB cOCT6100_SIZE_16M ++#define cOCT6100_MEMORY_CHIP_SIZE_32MB cOCT6100_SIZE_32M ++#define cOCT6100_MEMORY_CHIP_SIZE_64MB cOCT6100_SIZE_64M ++#define cOCT6100_MEMORY_CHIP_SIZE_128MB cOCT6100_SIZE_128M ++ ++#define cOCT6100_MAX_NUM_MEMORY_CHIP 2 ++ ++#define cOCT6100_16MB_MEMORY_BANKS 0 ++#define cOCT6100_32MB_MEMORY_BANKS 1 ++#define cOCT6100_64MB_MEMORY_BANKS 2 ++#define cOCT6100_128MB_MEMORY_BANKS 3 ++ ++#define cOCT6100_1_MEMORY_BANKS 0 ++#define cOCT6100_2_MEMORY_BANKS 1 ++#define cOCT6100_3_MEMORY_BANKS 2 ++#define cOCT6100_4_MEMORY_BANKS 3 ++ ++/* Chip open defines.*/ ++#define cOCT6100_INTERNAL_TONE_ARRAY_SIZE 256 /* in words.*/ ++#ifndef cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ++#define cOCT6100_INTERNAL_SUPER_ARRAY_SIZE 128 /* in words.*/ ++#endif ++ ++/* Internal memory mapping.*/ ++ ++/*=======================================================================*/ ++#define cOCT6100_TSST_CONTROL_MEM_BASE 0x26000 ++ ++#define cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE 2 /* Each entries are 2 bytes.*/ ++#define cOCT6100_TSST_CONTROL_MEM_INPUT_TSST 0x0800 ++#define cOCT6100_TSST_CONTROL_MEM_OUTPUT_TSST 0x2000 ++ ++#define cOCT6100_TSST_CONTROL_MEM_PCM_LAW_OFFSET 12 ++#define cOCT6100_TSST_CONTROL_MEM_NIBBLE_POS_OFFSET 11 ++#define cOCT6100_TSST_CONTROL_MEM_TSST_NUM_OFFSET 12 ++ ++#define cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK 0x7FF ++ ++#define cOCT6100_TSST_CONTROL_PHASING_TSST_BASE_ENTRY 1344 ++#define cOCT6100_TSST_CONTROL_TIMESTAMP_BASE_ENTRY 1516 ++ ++/*=======================================================================*/ ++#define cOCT6100_CONVERSION_CONTROL_MEM_BASE 0x28000 ++ ++/* Each entries are 8 bytes but an 8 bytes mixer entry is located inbetween each entry.*/ ++#define cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE 16 ++#define cOCT6100_CONVERSION_CONTROL_MEM_ENCODER 0x0000 ++#define cOCT6100_CONVERSION_CONTROL_MEM_DECODER 0x8000 ++#define cOCT6100_CONVERSION_CONTROL_MEM_ACTIVATE_ENTRY 0x8000 ++#define cOCT6100_CONVERSION_CONTROL_MEM_RST_ON_NEXT_FR 0x8000 ++ ++#define cOCT6100_CONVERSION_CONTROL_MEM_PHASE_OFFSET 12 ++#define cOCT6100_CONVERSION_CONTROL_MEM_NIBBLE_POS_OFFSET 9 ++#define cOCT6100_CONVERSION_CONTROL_MEM_COMP_OFFSET 11 ++#define cOCT6100_CONVERSION_CONTROL_MEM_LAW_OFFSET 8 ++#define cOCT6100_CONVERSION_CONTROL_MEM_SIL_SUP_OFFSET 8 ++ ++#define cOCT6100_CONVERSION_CONTROL_PHASE_SIZE_BASE_ADD 0x5400 ++ ++/*=======================================================================*/ ++#define cOCT6100_MIXER_CONTROL_MEM_BASE 0x28008 ++ ++/* Each entries are 8 bytes but an 8 bytes mixer entry is located inbetween each entry.*/ ++#define cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE 16 ++#define cOCT6100_MIXER_CONTROL_MEM_SUB_STORE 0xA000 ++#define cOCT6100_MIXER_CONTROL_MEM_STORE 0x8000 ++#define cOCT6100_MIXER_CONTROL_MEM_LOAD 0x4000 ++#define cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE 0x6000 ++#define cOCT6100_MIXER_CONTROL_MEM_COPY 0x2000 ++#define cOCT6100_MIXER_CONTROL_MEM_NO_OP 0x0000 ++ ++#define cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET 11 ++ ++#define cOCT6100_MIXER_HEAD_NODE 0 ++#define cOCT6100_MIXER_TAIL_NODE 1 ++#define cOCT6100_MIXER_RECORD_COPY_NODE 2 ++ ++/*=======================================================================*/ ++#define cOCT6100_ECHO_CONTROL_MEM_BASE 0x14000 ++ ++#define cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE 4 /* Each entries are 8 bytes.*/ ++#define cOCT6100_ECHO_CONTROL_MEM_ACTIVATE_ENTRY 0x8000 ++#define cOCT6100_ECHO_CONTROL_MEM_EXTERNAL_AF_CTRL 0x2000 ++ ++#define cOCT6100_ECHO_CONTROL_MEM_DEBUG_OFFSET 14 ++#define cOCT6100_ECHO_CONTROL_MEM_AF_CONTROL 14 ++#define cOCT6100_ECHO_CONTROL_MEM_INPUT_LAW_OFFSET 12 ++#define cOCT6100_ECHO_CONTROL_MEM_OUTPUT_LAW_OFFSET 11 ++ ++#define cOCT6100_ECHO_CONTROL_MEM_TSI_MEM_MASK 0x7FF ++ ++/*=======================================================================*/ ++#define cOCT6100_ST_CONTROL_MEM_BASE 0x2000000 ++ ++#define cOCT6100_ST_CONTROL_MEM_ENTRY_SIZE 16 /* Each entries are 8 bytes.*/ ++ ++/*=======================================================================*/ ++#define cOCT6100_PART1_BASE 0x00080000 ++#define cOCT6100_PART1_CPU_LSU_CB_BASE cOCT6100_PART1_BASE+0x0000E3C0 /* 8 * 8 = 64 bytes */ ++#define cOCT6100_PART1_HW_LSU_CB_BASE cOCT6100_PART1_BASE+0x0000E400 /* 8 * 128 = 1K byte */ ++#define cOCT6100_PART1_END_STATICS_BASE cOCT6100_PART1_BASE+0x0000E9F0 /* 912 bytes available for your viewing pleasure. */ ++#define cOCT6100_PART1_API_SCRATCH_PAD cOCT6100_PART1_END_STATICS_BASE+4+(12*8) ++#define cOCT6100_PART1_EGO_REG cOCT6100_PART1_BASE+0x0007FF00 ++ ++/* External Memory mapping. */ ++#define cOCT6100_EXTERNAL_MEM_BLOCK_SIZE 1024 ++#define cOCT6100_EXTERNAL_MEM_BASE_ADDRESS 0x08000000 ++ ++ ++#define cOCT6100_TLV_BASE ( 0x00016000 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ++#define cOCT6100_CHANNEL_ROOT_BASE ( 0x00020000 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ++#define cOCT6100_PGSP_EVENT_OUT_BASE ( 0x002C0000 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ++#define cOCT6100_POUCH_BASE ( 0x002E0000 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ++#define cOCT6100_IMAGE_FILE_BASE ( 0x00300000 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ++ ++#define cOCT6100_CHANNEL_ROOT_SIZE 4096 ++#define cOCT6100_CHANNEL_ROOT_TOTAL_SIZE ( 672 * cOCT6100_CHANNEL_ROOT_SIZE ) ++#define cOCT6100_PGSP_EVENT_OUT_SIZE 131072 ++#define cOCT6100_PGSP_TONE_EVENT_SIZE 0x40 ++#define cOCT6100_IMAGE_FILE_SIZE 0x100000 ++ ++#define cOCT6100_MATRIX_TIMESTAMP_DWORD_ADD cOCT6100_POUCH_BASE + 0x8 ++#define cOCT6100_MATRIX_CHAN_SELECT_DWORD_ADD cOCT6100_POUCH_BASE + 0x14 ++#define cOCT6100_MATRIX_WRITE_PTR_DWORD_ADD cOCT6100_POUCH_BASE + 0x4 ++#define cOCT6100_MATRIX_PLL_JITTER_COUNT_ADD cOCT6100_POUCH_BASE + 0x1C ++#define cOCT6100_MATRIX_DWORD_BASE cOCT6100_POUCH_BASE + 0xE0000 ++ ++#define cOCT6100_CHANNEL_ROOT_GLOBAL_CONF_OFFSET 0x0000 ++ ++#define cOCT6100_NUM_WORDS_PER_TONE_EVENT 32 ++#define cOCT6100_NUM_PGSP_EVENT_OUT 2048 /* CPTAG: Must not be modified, represents number of events stored in hardware. */ ++#define cOCT6100_VALID_TONE_EVENT 0x8000 ++#define cOCT6100_LOCAL_TIMESTAMP_INCREMENT 32 /* 4 ms increment. */ ++#define cOCT6100_ABSOLUTE_MAX_NUM_PGSP_EVENT_OUT 65535 ++#define cOCT6100_MIN_TIMESLOT_FOR_TIMESTAMP 5 ++ ++ ++/*=======================================================================*/ ++#define cOCT6100_GSC_PGSP_CONTEXT_BASE_ADD_OFFSET 0x0C ++#define cOCT6100_GSC_PGSP_INIT_CONTEXT_BASE_ADD_OFFSET 0x10 ++#define cOCT6100_GSC_RIN_CIRC_BUFFER_BASE_ADD_OFFSET 0x14 ++#define cOCT6100_GSC_SIN_CIRC_BUFFER_BASE_ADD_OFFSET 0x18 ++#define cOCT6100_GSC_SOUT_CIRC_BUFFER_BASE_ADD_OFFSET 0x1C ++ ++#define cOCT6100_GSC_BUFFER_LAW_OFFSET 27 ++ ++/*=======================================================================*/ ++#define cOCT6100_CH_MAIN_PGSP_CONTEXT_OFFSET 0x00000 ++#define cOCT6100_CH_MAIN_TONE_EVENT_OFFSET 0x00488 ++ ++/*=======================================================================*/ ++#define cOCT6100_PLAYOUT_EVENT_REPEAT_OFFSET 31 ++#define cOCT6100_PLAYOUT_EVENT_LAW_OFFSET 30 ++#define cOCT6100_PLAYOUT_EVENT_MIX_OFFSET 28 ++#define cOCT6100_PLAYOUT_EVENT_LOOP_TIMES_OFFSET 27 ++#define cOCT6100_PLAYOUT_EVENT_GAIN_OFFSET 24 ++ ++#define cOCT6100_PLAYOUT_EVENT_MEM_SIZE 16 ++ ++/* Image related defines.*/ ++#define cOCT6100_MIN_IMAGE_SIZE 0x001000 ++#define cOCT6100_MAX_IMAGE_SIZE 0x100000 ++#define cOCT6100_MAX_IMAGE_REGION 60 ++#define cOCT6100_IMAGE_AF_CST_OFFSET 0x1000; ++ ++/* Max defines.*/ ++#ifndef cOCT6100_MAX_ECHO_CHANNELS ++#define cOCT6100_MAX_ECHO_CHANNELS 256 ++#endif ++#define cOCT6100_MAX_TSI_CNCTS 1530 ++#define cOCT6100_MAX_CALLER_ID_PLAYOUT_BUFFERS ( 3328 + 6 ) ++#define cOCT6100_MAX_PLAYOUT_BUFFERS ( 1344 + cOCT6100_MAX_CALLER_ID_PLAYOUT_BUFFERS ) ++#define cOCT6100_MAX_CONF_BRIDGE 672 ++#define cOCT6100_MAX_FLEX_CONF_PARTICIPANTS cOCT6100_MAX_ECHO_CHANNELS ++#define cOCT6100_MAX_PHASING_TSST 16 ++#define cOCT6100_MAX_ADPCM_CHANNELS 672 ++ ++#define cOCT6100_NUM_TSI_B4_PHASING 1344 ++#define cOCT6100_TOTAL_TSI_CONTROL_MEM_ENTRY 1534 ++#define cOCT6100_MAX_TSI_CONTROL_MEM_ENTRY 1344 ++#define cOCT6100_MAX_ECHO_CONTROL_MEM_ENTRY 672 ++#define cOCT6100_MAX_TSI_B4_TIMESTAMP 172 ++#define cOCT6100_TSI_MEM_FOR_TIMESTAMP 4 ++#define cOCT6100_API_EXT_TONE_EXTRA_TSI 1533 ++ ++/* Echo channel ports */ ++#define cOCT6100_CHANNEL_PORT_RIN 0 ++#define cOCT6100_CHANNEL_PORT_ROUT 1 ++#define cOCT6100_CHANNEL_PORT_SIN 2 ++#define cOCT6100_CHANNEL_PORT_SOUT 3 ++#define cOCT6100_CHANNEL_PORT_ROUT_SOUT 4 ++ ++#define cOCT6100_NO_ENCODING 10 ++#define cOCT6100_NO_DECODING 11 ++ ++/* Buffer playout defines */ ++#define cOCT6100_NO_SKIP 0 ++#define cOCT6100_BUFFER_PLAYOUT_MIN_SIZE 1024 ++#define cOCT6100_DEFAULT_TIMESTAMP 0 ++#define cOCT6100_MIXING_0_DB 0 ++#define cOCT6100_MIXING_MINUS_6_DB 1 ++#define cOCT6100_MIXING_MINUS_12_DB 2 ++#define cOCT6100_MIXING_MUTE 3 ++#define cOCT6100_PLAYOUT_GAIN 0x41000000 ++#define cOCT6100_PLAYOUT_EVENT 1 ++#define cOCT6100_MINIMUM_BUFFER_SIZE 64 ++#define cOCT6100_BUFFER_SIZE_GRANULARITY 16 ++#define cOCT6100_REPEAT_INFINITELY cOCT6100_INVALID_VALUE ++#define cOCT6100_REPEAT_MAX 32767 ++#define cOCT6100_SAMPLES_PER_MS 8 ++ ++/* For the playout events. */ ++#define cOCT6100_MAX_BUFFER_PLAYOUT_EVENT_PER_CALL 32 ++#define cOCT6100_MIN_BUFFER_PLAYOUT_EVENT 128 ++#define cOCT6100_MAX_BUFFER_PLAYOUT_EVENT 65535 ++/* Event types */ ++#define cOCT6100_BUFFER_PLAYOUT_EVENT_INVALID cOCT6100_INVALID_VALUE ++#define cOCT6100_BUFFER_PLAYOUT_EVENT_STOP 1 ++ ++ ++/* Phasing defines.*/ ++#define cOCT6100_SINGLE_PHASING 0 ++#define cOCT6100_DUAL_PHASING 1 ++#define cOCT6100_NO_PHASING 2 ++ ++/* Echo canceller mode.*/ ++#define cOCT6100_ELECTRIC_EC 0 ++#define cOCT6100_ELECTRIC_EC_DISPLACEMENT 1 ++#define cOCT6100_ACCOUSTIC_ES 2 ++ ++/* Echo control modes.*/ ++#define cOCT6100_ECHO_OP_MODE_NORMAL 0 ++#define cOCT6100_ECHO_OP_MODE_HT_FREEZE 1 ++#define cOCT6100_ECHO_OP_MODE_HT_RESET 2 ++#define cOCT6100_ECHO_OP_MODE_POWER_DOWN 3 ++#define cOCT6100_ECHO_OP_MODE_EXTERNAL 4 ++#define cOCT6100_ECHO_OP_MODE_NO_ECHO 5 ++#define cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION 6 ++#define cOCT6100_ECHO_OP_MODE_G169_ALC cOCT6100_ECHO_OP_MODE_NO_ECHO ++ ++/* 2100 Hz disabling configuration. */ ++#define cOCT6100_NEVER_DISABLED 0 ++#define cOCT6100_G164_2100_HZ 1 ++#define cOCT6100_G165_2100_HZ_WITH_PHASE_REV 2 ++ ++/* TSST defines.*/ ++#define cOCT6100_UNASSIGNED cOCT6100_FFFD ++ ++#define cOCT6100_MAX_TSSTS (cOCT6100_MAX_ECHO_CHANNELS*4) /* cOCT6100_MAX_ECHO_CHANNELS channels, 4 TSSTs per channel. */ ++#define cOCT6100_TWO_TSSTS_INDEX_MASK 0x8000 ++#define cOCT6100_TSST_INDEX_MASK 0x7FFF ++#define cOCT6100_INPUT_TSST 0 ++#define cOCT6100_OUTPUT_TSST 1 ++ ++/* Conference bridges defines.*/ ++/* CPTAG: No application needs for mixer events. */ ++/* 2 needed for head and tail nodes. 2 more needed to get through channel modify function. */ ++/* Careful. This value cannot be zero. */ ++#ifndef cOCT6100_MAX_MIXER_EVENTS ++#define cOCT6100_MAX_MIXER_EVENTS 4 ++#endif ++#define cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE 32 ++#define cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED 672 ++#define cOCT6100_CONF_NO_DOMINANT_SPEAKER_HNDL cOCT6100_FFFFFFFE ++ ++/* Conversion memory defines.*/ ++#define cOCT6100_MAX_CONVERSION_MEMORY_BLOCKS (cOCT6100_MAX_ECHO_CHANNELS*2) /* CPTAG: Max this out to the expected max number of channels * 2, was 1344 */ ++ ++/* Tone detection defines.*/ ++#define cOCT6100_MAX_TONE_NUMBER 55 ++ ++/* Register definition and address. */ ++#define cOCT6100_TONE_EVENT_WRITE_PTR_REG 0x722 ++#define cOCT6100_TONE_EVENT_READ_PTR_REG 0x720 ++ ++/* Special Signaling tone IDs. */ ++#define cOCT6100_TONE_SIN_SYSTEM7_2000 0x20000023 ++#define cOCT6100_TONE_SIN_SYSTEM7_1780 0x20000024 ++#define cOCT6100_TONE_ROUT_G168_2100GB_ON 0x10000000 ++#define cOCT6100_TONE_ROUT_G168_2100GB_WSPR 0x10000002 ++#define cOCT6100_TONE_ROUT_G168_1100GB_ON 0x10000004 ++#define cOCT6100_TONE_ROUT_G168_2100GB_ON_WIDE_A 0x10000005 ++#define cOCT6100_TONE_ROUT_G168_2100GB_ON_WIDE_B 0x10000006 ++#define cOCT6100_TONE_ROUT_G168_2100GB_WSPR_WIDE 0x10000008 ++#define cOCT6100_TONE_SOUT_G168_2100GB_ON 0x40000000 ++#define cOCT6100_TONE_SOUT_G168_2100GB_WSPR 0x40000002 ++#define cOCT6100_TONE_SOUT_G168_1100GB_ON 0x40000004 ++#define cOCT6100_TONE_SOUT_G168_2100GB_ON_WIDE_A 0x40000005 ++#define cOCT6100_TONE_SOUT_G168_2100GB_ON_WIDE_B 0x40000006 ++#define cOCT6100_TONE_SOUT_G168_2100GB_WSPR_WIDE 0x40000008 ++#define cOCT6100_TONE_SIN_SYSTEM5_2400 0x20000020 ++#define cOCT6100_TONE_SIN_SYSTEM5_2600 0x20000021 ++#define cOCT6100_TONE_SIN_SYSTEM5_2400_2600 0x20000022 ++ ++#define cOCT6100_CHIP_ID_REVISION_REG 0x17E ++ ++/* BOOT type. */ ++#define cOCT6100_AF_BOOT_TYPE 0x5 ++#define cOCT6100_PRODUCTION_BOOT_TYPE 0x7 ++#define cOCT6100_PRODUCTION_SHORT_BOOT_TYPE 0x8 ++ ++/*Production Bist Modes*/ ++#define cOCT6100_PRODUCTION_BIST_STANDARD 0x0 ++#define cOCT6100_PRODUCTION_BIST_SHORT 0x1 ++ ++/* Interrupt register masks.*/ ++#define cOCT6100_INTRPT_MASK_REG_102H 0x0001 ++#define cOCT6100_INTRPT_MASK_REG_202H 0x1C01 ++#define cOCT6100_INTRPT_MASK_REG_302H 0xF100 ++#define cOCT6100_INTRPT_MASK_REG_502H 0x0002 ++#define cOCT6100_INTRPT_MASK_REG_702H 0x0002 ++ ++#define cOCT6100_DECODER_MEMORY_OFFSET 672 ++ ++/* Debug defines.*/ ++#define cOCT6100_DEBUG_MAX_READ_LENGTH 10240 ++#define cOCT6100_DEBUG_SOUT_MAX_READ_LENGTH 2560 ++#define cOCT6100_DEBUG_CHAN_RECORD_INDEX 64 ++#define cOCT6100_DEBUG_RECORD_BUFFER_BYTE_SIZE 0x20000 ++#define cOCT6100_DEBUG_RECORD_MATRIX_SIZE 0x8000 ++#define cOCT6100_DEBUG_RECORD_READ_DATA_BYTE_SIZE 1024 ++#define cOCT6100_DEBUG_RECORD_BLOCK_BYTE_SIZE 0x1000 ++ ++/* Tone event defines.*/ ++#define cOCT6100_MAX_TONE_EVENT 56 ++#define cOCT6100_TONE_PRESENT 0 ++#define cOCT6100_TONE_STOP 1 ++#define cOCT6100_TONE_REFRESH 2 ++ ++/* TLV defines.*/ ++#define cOCT6100_TLV_MAX_ADDRESS 0x10000000 ++#define cOCT6100_TLV_MAX_TONE_NAME_SIZE 64 ++ ++#define cOCT6100_VERSION_NUMBER_MAX_SIZE 1016 ++ ++/* Echo Tail defines.*/ ++#define cOCT6100_TAIL_LENGTH_32MS 32 ++#define cOCT6100_TAIL_LENGTH_64MS 64 ++#define cOCT6100_TAIL_LENGTH_128MS 128 ++#define cOCT6100_MAX_ECHO_TAIL_DISPLACEMENT 5600 /* In milliseconds */ ++ ++ ++ ++ ++ ++/* Generic loop counter.*/ ++#define cOCT6100_MAX_LOOP 0x2000 ++/* CPU boot timeout counter. */ ++#define cOCT6100_MAX_LOOP_CPU_TIMEOUT 0x20000 ++ ++/* Automatic level control */ ++#define cOCT6100_PASS_THROUGH_LEVEL_CONTROL 0x90 ++ ++/* Channel stats debug info */ ++#define cOCT6100_DEBUG_CHAN_STATS_EVENT_BYTE_SIZE 1024 ++#define cOCT6100_DEBUG_CHAN_STATS_LITE_EVENT_BYTE_SIZE 720 ++ ++/* Image start string define */ ++#define cOCT6100_IMAGE_START_STRING "EDS3_IMAGE_NAME" ++ ++/* Tone image info defines.*/ ++#define cOCT6100_TONE_INFO_START_STRING "[ToneDetectorInfo]" ++#define cOCT6100_TONE_INFO_STOP_STRING "[~ToneDetectorInfo]" ++#define cOCT6100_TONE_INFO_EVENT_STRING "TONEEVENT=0x" ++ ++#define cOCT6100_MAX_NLP_CONF_DWORD 20 ++ ++/* Tail displacement info.*/ ++#define cOCT6100_MAX_TAIL_DISPLACEMENT 896 ++ ++/* Comfort noise define */ ++#define cOCT6100_COMFORT_NOISE_NORMAL 0x0 ++#define cOCT6100_COMFORT_NOISE_EXTENDED 0x3 ++#define cOCT6100_COMFORT_NOISE_OFF 0x2 ++#define cOCT6100_COMFORT_NOISE_FAST_LATCH 0x1 ++ ++/* Mixer event type.*/ ++#define cOCT6100_EVENT_TYPE_SOUT_COPY 0x0 ++#define cOCT6100_EVENT_TYPE_SIN_COPY 0x1 ++ ++/* Tone disabler status.*/ ++#define cOCT6100_TONE_DISABLER_EC_ENABLED 0 ++#define cOCT6100_TONE_DISABLER_EC_DISABLED 1 ++ ++/* ADPCM Channel defines */ ++#define cOCT6100_ADPCM_ENCODING 0 ++#define cOCT6100_ADPCM_DECODING 1 ++ ++/* Double talk behavior modes. */ ++#define cOCT6100_DOUBLE_TALK_BEH_NORMAL 0x0 ++#define cOCT6100_DOUBLE_TALK_BEH_LESS_AGGRESSIVE 0x1 ++ ++/* Api Version string length.*/ ++#define cOCT6100_API_VERSION_STRING_LENGTH 32 ++ ++/* Extended tone detection information. */ ++#define cOCT6100_API_EXT_TONE_DISABLED 0 ++#define cOCT6100_API_EXT_TONE_SIN_PORT_MODE 1 ++#define cOCT6100_API_EXT_TONE_RIN_PORT_MODE 2 ++ ++ ++ ++/* Mute/UnMute defines. */ ++#define cOCT6100_CHANNEL_MUTE_PORT_NONE 0x00 ++#define cOCT6100_CHANNEL_MUTE_PORT_RIN 0x01 ++#define cOCT6100_CHANNEL_MUTE_PORT_ROUT 0x02 ++#define cOCT6100_CHANNEL_MUTE_PORT_SIN 0x04 ++#define cOCT6100_CHANNEL_MUTE_PORT_SOUT 0x08 ++#define cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES 0x10 ++ ++/* Debug get data dump modes. */ ++#define cOCT6100_DEBUG_GET_DATA_MODE_16S_LITE 0x0 ++#define cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE 0x1 ++#define cOCT6100_DEBUG_GET_DATA_MODE_16S 0x2 ++#define cOCT6100_DEBUG_GET_DATA_MODE_120S 0x3 ++ ++/* Debug get data dump content. */ ++#define cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE 0x0 /* Full binary dump to be sent for support. */ ++#define cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM 0x1 /* Only Rin PCM stream data. */ ++#define cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM 0x2 /* Only Sin PCM stream data. */ ++#define cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM 0x3 /* Only Sout PCM stream data. */ ++ ++ ++ ++#define cOCT6100_BIST_IN_PROGRESS 0x0 ++#define cOCT6100_BIST_CONFIGURATION_FAILED 0x1 ++#define cOCT6100_BIST_STATUS_CRC_FAILED 0x2 ++#define cOCT6100_BIST_MEMORY_FAILED 0x3 ++#define cOCT6100_BIST_SUCCESS 0x4 ++ ++/* Image types. */ ++#define cOCT6100_IMAGE_TYPE_WIRELINE 0x0 ++#define cOCT6100_IMAGE_TYPE_COMBINED 0x1 ++ ++/* Fatal general error types. */ ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_1 0x0001 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_2 0x0002 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_3 0x0004 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_4 0x0008 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_5 0x0010 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_6 0x0020 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_7 0x0040 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_8 0x0080 ++#define cOCT6100_FATAL_GENERAL_ERROR_TYPE_9 0x0100 ++ ++#endif /* __OCT6100_DEFINES_H__ */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_errors.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_errors.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_errors.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_errors.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,838 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_errors.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Header file containing all defines used for error codes. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 205 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_ERRORS_H__ ++#define __OCT6100_ERRORS_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++/***************************** DEFINES *************************************/ ++ ++#define cOCT6100_ERR_OK 0x00000000 ++#define cOCT6100_ERR_BASE 0x00100000 ++ ++#define cOCT6100_NOT_SUPPORTED_BASE (0xFF000 + cOCT6100_ERR_BASE) ++ ++/* Not supported defines. */ ++#define cOCT6100_ERR_NOT_SUPPORTED_OPEN_DEBUG_RECORD (0x00000 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLP_CONTROL (0x00001 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_BKG_NOISE_FREEZE (0x00002 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_DC_OFFSET_REM (0x00003 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_DC_OFFSET_REM (0x00004 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_AUTO_LC (0x00005 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SOUT_AUTO_LC (0x00006 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR (0x00007 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_DISPLACEMENT (0x00008 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ENCODING (0x00009 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DECODING (0x0000A + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_LAW_TRANSLATION (0x0000B + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO (0x0000C + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DEFAULT_ERL (0x0000D + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DOUBLE_TALK (0x0000E + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NON_LINEARITY_B (0x0000F + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_AEC_DEFAULT_ERL (0x00010 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_HIGH_LEVEL_COMP (0x00011 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_PER_CHAN_TAIL (0x00012 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIL_SUP (0x00013 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_OPEN_ACOUSTIC_ECHO (0x00014 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_OPEN_TAIL_DISPLACEMENT_VALUE (0x00015 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_OPEN_MAX_ECHO_CHANNELS_VALUE (0x00016 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ALE (0x00017 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLE (0x00018 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ROUT_NR (0x00019 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_MUTE_FEATURES (0x0001A + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SNR_ENHANCEMENT (0x0001B + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SEGREGATION (0x0001C + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_OPEN_USE_SYNCH_TIMESTAMP (0x0001D + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_LENGTH (0x0001E + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY (0x0001F + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH (0x00020 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_MUSIC_PROTECTION (0x00021 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_DEBUG_DATA_MODE_120S (0x00022 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_TONE_NOT_PRESENT_IN_FIRMWARE (0x00023 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_DOUBLE_TALK_BEHAVIOR_MODE (0x00024 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION (0x00025 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION_CONFIG (0x00026 + cOCT6100_NOT_SUPPORTED_BASE) ++ ++ ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ROUT_NOISE_REDUCTION_GAIN (0x0002B + cOCT6100_NOT_SUPPORTED_BASE) ++ ++#define cOCT6100_ERR_NOT_SUPPORTED_BUFFER_PLAYOUT (0x00100 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_CNR (0x00101 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CONF_BRIDGE (0x00102 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CALLER_ID (0x00104 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NOISE_BLEACHING (0x00105 + cOCT6100_NOT_SUPPORTED_BASE) ++ ++#define cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_REMOVAL (0x00300 + cOCT6100_NOT_SUPPORTED_BASE) ++#define cOCT6100_ERR_NOT_SUPPORTED_DOMINANT_SPEAKER (0x00301 + cOCT6100_NOT_SUPPORTED_BASE) ++ ++ ++ ++#define cOCT6100_ERR_OPEN_INVALID_DEVICE (0x03000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INSUFFICIENT_EXTERNAL_MEMORY (0x03001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MEMORY_CHIP_SIZE (0x03002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_UP_CLK_FREQ (0x03003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_USER_CHIP_ID (0x03004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MULTI_PROCESS_SYSTEM (0x03005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_RW_ACCESSES (0x03006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_IMAGE_SIZE (0x03007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_IMAGE_FILE (0x03008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MEM_CLK_FREQ (0x03009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MEMORY_CHIPS_NUMBER (0x0300A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TOTAL_MEMORY_SIZE (0x0300B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_USE_SYNCH_TIMESTAMP (0x0300C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TIMESTAMP_STREAM (0x0300D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TIMESTAMP_TIMESLOT (0x0300E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TIMESTAMP_TSSTS (0x0300F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TDM_STREAM_FREQS (0x03010 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TDM_SAMPLING (0x03011 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_FAST_H100_MODE (0x03012 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_ECHO_CHANNELS (0x03013 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_PLAYOUT_BUFFERS (0x03014 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_TSI_CNCTS (0x03015 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_PHASING_TSSTS (0x03016 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_EXTERNAL_MEM_BIST_FAILED (0x03017 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_EXTERNAL_MEM_BIST_TIMEOUT (0x03018 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_SDRAM_BIST_FAILED (0x03019 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_CORRUPTED_IMAGE (0x0301A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR (0x0301B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_SOFT_TONE_EVENT_SIZE (0x0301C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INTERRUPT_POLARITY (0x0301D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_FATAL_GENERAL_CONFIG (0x0301E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_REMOTE_DEBUG_SESSIONS (0x0301F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ENABLE_MEM_CLK_OUT (0x03020 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_TDM_STREAM (0x03021 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_CONF_BRIDGES (0x03022 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_OPEN_AF_CPU_TIMEOUT (0x03024 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MEMORY_TYPE (0x03025 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_FATAL_MEMORY_CONFIG (0x03026 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ERROR_MEMORY_CONFIG (0x03027 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_CONFIG (0x03028 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ERROR_H100_CONFIG (0x03029 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_FATAL_MEMORY_TIMEOUT (0x0302A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ERROR_MEMORY_TIMEOUT (0x0302B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_TIMEOUT (0x0302C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ERROR_H100_TIMEOUT (0x0302D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_IMAGE_WRITE_FAILED (0x0302E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_CRC_ERROR (0x0302F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_EGO_TIMEOUT (0x03030 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_SOFT_DEBUG_EVENT_BUF_SIZE (0x03031 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TONE_INFO_START_TAG_NOT_FOUND (0x03032 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TONE_INFO_STOP_TAG_NOT_FOUND (0x03033 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INVALID_TONE_EVENT (0x03034 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INVALID_TONE_NAME (0x03035 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INVALID_EVENT_NUMBER_SIZE (0x03036 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INTERNAL_MEMORY_BIST (0x03037 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_TAIL_DISPLACEMENT (0x03038 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_DEBUG_CHANNEL_RECORDING (0x03039 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_BIDIR_CHANNELS (0x0303A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_FUNCTIONAL_BIST_FAILED (0x0303C + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_OPEN_MAX_ADPCM_CHANNELS (0x0303E + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_OPEN_ENABLE_EXT_TONE_DETECTION (0x03040 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_SOFT_PLAYOUT_STOP_EVENT_SIZE (0x03041 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INVALID_FIRMWARE_OR_CAPACITY_PINS (0x03042 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ENABLE_ACOUSTIC_ECHO (0x03043 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_OPEN_USER_WRITE_BURST_FAILED (0x03045 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_USER_WRITE_SMEAR_FAILED (0x03046 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_USER_READ_BURST_FAILED (0x03047 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_MAX_FLEXIBLE_CONF_PARTICIPANTS (0x03048 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_OPEN_DEBUG_MEM_INDEX (0x03051 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_ENABLE_CALLER_ID (0x03052 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_CALLER_ID_PLAYOUT_BUFFERS (0x03053 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_OPEN_ENABLE_PRODUCTION_BIST (0x03055 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_PRODUCTION_BIST_ACTIVATED (0x03056 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_NUM_PRODUCTION_BIST_LOOPS (0x03057 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_PRODUCTION_BOOT_FAILED (0x03058 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_PRODUCTION_BIST_CONF_FAILED (0x03059 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_PRODUCTION_BIST_POUCH_ERROR (0x0305A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_INVALID_TLV_LENGTH (0x0305B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_OPEN_PRODUCTION_BIST_MODE (0x0305C + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_OPEN_ENABLE_2100_STOP_EVENT (0x03060 + cOCT6100_ERR_BASE) ++ ++ ++#define cOCT6100_ERR_CAP_PINS_INVALID_CHIP_STATE (0x03081 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CAP_PINS_INVALID_CAPACITY_VALUE (0x03082 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_TSI_CNCT_ALL_CHANNELS_ARE_OPENED (0x04000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_DISABLED (0x04001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_INVALID_HANDLE (0x04002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_INPUT_TIMESLOT (0x04003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_INPUT_STREAM (0x04004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_OUTPUT_TIMESLOT (0x04005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_OUTPUT_STREAM (0x04006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_INPUT_PCM_LAW (0x04007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_TIMESLOT (0x04008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_STREAM (0x04009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_TSST_RESERVED (0x0400A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_NOT_OPEN (0x0400B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_ASSOCIATED_TSST_RESERVED (0x0400C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSI_CNCT_NO_MORE_TSI_AVAILABLE (0x0400D + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED (0x05000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_PATTERN (0x05001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_TOO_SMALL (0x05002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_PCM_LAW (0x05003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ALL_BUFFERS_OPEN (0x05004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE (0x05005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX (0x05006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN (0x05007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ACTIVE_DEPENDENCIES (0x05008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID (0x05009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN (0x0500A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ROUT_PORT_PLAYING (0x0500B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_SOUT_PORT_PLAYING (0x0500C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_PORT_INVALID (0x0500D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT (0x0500E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL (0x0500F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT (0x05010 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ADD_MIXING (0x05011 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_STOP_CLEANLY (0x05012 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_NOT_STARTED (0x05013 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_WRITE_BYTE_COUNT (0x05015 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ECHO_OP_MODE (0x05016 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_LENGTH_INVALID (0x05017 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_OFFSET_INVALID (0x05018 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_RESET (0x05019 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_BUF_EMPTY (0x0501A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_MAX_EVENT (0x0501B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_DISABLED (0x0501C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_NOTIFY_ON_STOP (0x0501D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ALLOW_ACTIVE (0x0501E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_STILL_ACTIVE (0x0501F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_REPEAT_USED (0x05020 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_NLP_DISABLED (0x05021 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_MALLOC_ZERO (0x05022 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_NO_MEMORY (0x05023 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_MALLOC_POINT_NOT_FOUND (0x05024 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT_COUNT (0x05025 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_ADD_GAIN_DB (0x05026 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_BUFFER_PLAYOUT_LIST_EMPTY (0x05027 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_MEMORY_ALL_TSI_MEM_ENTRY_RESERVED (0x06000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MEMORY_ALL_ECHO_MEM_ENTRY_RESERVED (0x06002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MEMORY_EXTERNAL_MEMORY_FULL (0x06003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MEMORY_ALL_CONVERSION_MEM_ENTRY_RESERVED (0x06004 + cOCT6100_ERR_BASE) ++ ++ ++#define cOCT6100_ERR_CHANNEL_DISABLED (0x07000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_INVALID_HANDLE (0x07001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_NUM_TSSTS (0x07002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_NUM_TSSTS (0x07003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_NUM_TSSTS (0x07004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_NUM_TSSTS (0x07005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_TIMESLOT (0x07006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_STREAM (0x07007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_TIMESLOT (0x07008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_STREAM (0x07009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT (0x0700A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_STREAM (0x0700B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT (0x0700C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_STREAM (0x0700D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_MISSING_TSST (0x07012 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIL_SUP_ENABLE (0x07013 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_PHASING_TYPE (0x07014 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE (0x07015 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_PHASING_TSST_NOT_OPEN (0x07016 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_PHASING_INVALID_PHASE (0x07017 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_DEBUG (0x07018 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ECHO_OP_MODE (0x0701F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_DC_OFFSET_REM (0x07020 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_DC_OFFSET_REM (0x07021 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL (0x07022 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL (0x07023 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL_GAIN (0x07024 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL_GAIN (0x07025 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_ADAPT_NOISE_REDUCTION (0x07026 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ALL_CHANNELS_ARE_OPENED (0x07027 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_NOT_OPEN (0x07029 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ADPCM_NIBBLE (0x0702A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_ADD_PORT (0x0702B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_ADD_TIMESLOT (0x0702C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_ADD_STREAM (0x0702D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_INVALID (0x0702E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_PCM_LAW (0x0702F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_PCM_LAW (0x07030 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_PCM_LAW (0x07031 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_PCM_LAW (0x07032 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_DECODER_PORT (0x07033 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ENCODER_PORT (0x07034 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_DECODING_RATE (0x07035 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ENCODING_RATE (0x07036 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ENABLE_NLP (0x07037 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_COMFORT_NOISE_MODE (0x07038 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_PHASING_TSST_REQUIRED (0x07039 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIL_SUP_INVALID_ENCODER_PORT (0x0703A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_MODIFY_CODEC_CONFIG (0x0703B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_MODIFY_VQE_CONFIG (0x0703C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_MODIFY_TDM_CONFIG (0x0703D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_RIN_PORT_INVALID (0x0703E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_SIN_PORT_INVALID (0x0703F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_REMOVE_PORT (0x07041 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_REMOVE_TIMESLOT (0x07042 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_REMOVE_STREAM (0x07043 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_REMOVE_INVALID_TSST (0x07044 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_GET_STATS_MAX_BROADCAST_TSST (0x07045 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_BROADCAST_TIMESLOT (0x07046 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_BROADCAST_STREAM (0x07047 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_BROADCAST_TIMESLOT (0x07048 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_BROADCAST_STREAM (0x07049 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ACTIVE_DEPENDENCIES (0x0704A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TONE_DISABLER_ENABLE (0x0704B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TAIL_LENGTH (0x07053 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TAIL_DISPLACEMENT (0x07054 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_INVALID_RIN_CB_SIZE (0x07058 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TSST_REMOVE_NO_BROADCAST_TSST (0x07059 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_INVALID_CODEC_POSITION (0x0705A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_STATS_RESET (0x0705B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ENABLE_TAIL_DISPLACEMENT (0x0705C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE (0x0705E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_BIDIR_FIRST_CHANNEL_HANDLE (0x0705F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_BIDIR_SECOND_CHANNEL_HANDLE (0x07060 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_CODEC_ACTIVATED (0x07061 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ALREADY_BIDIR (0x07062 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ALL_BIDIR_CHANNELS_ARE_OPENED (0x07063 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_FIRST_CHAN_SOUT_PORT (0x07064 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_FIRST_CHAN_RIN_PORT (0x07065 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SECOND_CHAN_SOUT_PORT (0x07066 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SECOND_CHAN_RIN_PORT (0x07067 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_BIDIR_PCM_LAW (0x07068 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_BIDIR_CHAN_NOT_OPEN (0x07069 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION (0x0706A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION (0x0706B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL (0x0706C + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_NO_VALID_TDM_CLOCKS (0x0706E + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_OUT_OF_TSI_MEMORY (0x07073 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TONE_REMOVAL (0x07075 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO (0x07077 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_DEFAULT_ERL (0x07079 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_DOUBLE_TALK (0x0707B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_PHASE_TYPE_REQUIRED (0x0707C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIL_SUP_NLP_MUST_BE_ENABLED (0x0707D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ENABLE_EXT_TONE_DETECTION (0x0707E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DECODER_PORT (0x0707F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DISABLED (0x07080 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_NON_LINEARITY_B (0x07082 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_FIRST_CHAN_IN_CONFERENCE (0x07083 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SECOND_CHAN_IN_CONFERENCE (0x07084 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TAIL_DISPLACEMENT_CANNOT_MODIFY (0x07085 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_NON_LINEARITY_B_CANNOT_MODIFY (0x07086 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_NOT_ENABLED (0x07087 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_BIDIR_DISABLED (0x0708B + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_TAIL_DISPLACEMENT_INVALID (0x0708D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_PER_CHAN_TAIL_DISPLACEMENT (0x0708E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_CONFERENCE_NOISE_REDUCTION (0x0708F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_AEC_DEFAULT_ERL (0x07092 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED (0x07093 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL (0x07094 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL (0x07095 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL_TARGET (0x07096 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL_TARGET (0x07097 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_MANUAL (0x07098 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_MANUAL (0x07099 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP (0x0709A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_HIGH_LEVEL_COMP (0x0709C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_MANUAL (0x0709D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_THRESHOLD (0x0709E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_MUTE_MASK (0x0709F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_MUTE_MASK_SIN (0x070A0 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ALE_RATIO (0x070A1 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_NLE_FLAG (0x070A2 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ALE_NLE_SIMULTANEOUSLY (0x070A3 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_NOISE_REDUCTION (0x070A4 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ANR_SNR_ENHANCEMENT (0x070A5 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ANR_SEGREGATION (0x070A6 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_NLE_RATIO (0x070A7 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_APPLY_TO_ALL_CHANNELS (0x070A8 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_STREAM_UNASSIGN (0x070A9 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT_UNASSIGN (0x070AA + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_STREAM_UNASSIGN (0x070AB + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_RIN_TIMESLOT_UNASSIGN (0x070AC + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_STREAM_UNASSIGN (0x070AD + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT_UNASSIGN (0x070AE + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_STREAM_UNASSIGN (0x070AF + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SIN_TIMESLOT_UNASSIGN (0x070B0 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_DISABLE_TONE_DETECTION (0x070B1 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_STOP_BUFFER_PLAYOUT (0x070B2 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_REMOVE_CONF_BRIDGE_PARTICIPANT (0x070B3 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_REMOVE_BROADCAST_TSSTS (0x070B4 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY (0x070B5 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_OUT_OF_MIXER_EVENTS (0x070B8 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH (0x070B9 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ENABLE_MUSIC_PROTECTION (0x070BA + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_TAIL_LENGTH_INVALID (0x070BB + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_SUM (0x070BC + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_DOUBLE_TALK_MODE (0x070BD + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING (0x070BE + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING_NR (0x070BF + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ANR_CNR_SIMULTANEOUSLY (0x070C0 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_IDLE_CODE_DETECTION (0x070C1 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_MUST_ENABLE_TONE_DISABLER (0x070C2 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL_REQUIRED (0x070C5 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL_REQUIRED (0x070C6 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_AUTO_LEVEL_CONTROL_REQUIRED (0x070C8 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHANNEL_COMFORT_NOISE_REQUIRED (0x070CB + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CHANNEL_ROUT_NOISE_REDUCTION_GAIN (0x070CC + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_PHASING_TSST_ALL_ENTRIES_ARE_OPENED (0x08000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_PHASING_TSST_DISABLED (0x08001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_PHASING_TSST_INVALID_HANDLE (0x08002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_PHASING_TSST_TIMESLOT (0x08003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_PHASING_TSST_STREAM (0x08004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_PHASING_TSST_PHASING_LENGTH (0x08005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_PHASING_TSST_NOT_OPEN (0x08006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_PHASING_TSST_ACTIVE_DEPENDENCIES (0x08007 + cOCT6100_ERR_BASE) ++ ++ ++#define cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE (0x09000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_DISABLED (0x09001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN (0x09002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_ACTIVE_DEPENDENCIES (0x09003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE (0x09004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND (0x09005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_ALL_BUFFERS_OPEN (0x09006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_REMOVE_INVALID_HANDLE (0x09007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE (0x09008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_MUTE (0x09009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE (0x0900A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_ALREADY_MUTED (0x0900B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_NOT_MUTED (0x0900C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_CODEC_ACTIVE (0x0900D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_MIXER_FULL (0x0900E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ALREADY_ON_BRIDGE (0x0900F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_REMOVE_ALL (0x09010 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_EXT_TONE_ENABLED (0x09011 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_INVALID_INPUT_PORT (0x09012 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_DOMINANT_SPEAKER (0x09013 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_BIDIR (0x09015 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CNR_MUST_BE_ENABLED (0x09016 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_NLP_MUST_BE_ENABLED (0x09017 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF (0x09018 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_PARTICIPANT_CNT (0x09019 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_MASK_INDEX (0x0901A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_ALL_BUFFERS_OPEN (0x0901B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_DISABLED (0x0901C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_INDEX_USED (0x0901D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_SIMPLE_BRIDGE (0x0901E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_COPY_EVENTS (0x0901F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE (0x09020 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_TAP_NOT_SUPPORTED (0x09021 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_BRIDGE (0x09022 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY (0x09023 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_SAME_BRIDGE (0x09024 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_TAP_SOUT_ONLY (0x09025 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_ALREADY_TAPPED (0x09026 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_ALWAYS_MUTE (0x09027 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION (0x09028 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_MISC_CANNOT_ROUND_UP_NUMBER (0x0A000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MISC_ASCII_CONVERSION_FAILED (0x0A001 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID (0x0B000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TONE_DETECTION_CHANNEL_NOT_OPEN (0x0B001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TONE_DETECTION_TONE_NUMBER_INVALID (0x0B002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TONE_DETECTION_TONE_NOT_ACTIVATED (0x0B003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TONE_DETECTION_TONE_ACTIVATED (0x0B004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TONE_DETECTION_TONE_NOT_AVAILABLE (0x0B005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TONE_DETECTION_DISABLE_ALL (0x0B006 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_EVENTS_GET_TONE_RESET_BUFS (0x0C000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_EVENTS_TONE_BUF_EMPTY (0x0C001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_EVENTS_MAX_TONES (0x0C002 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_INTRPTS_RW_ERROR (0x0D000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_NOT_ACTIVE (0x0D001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_FATAL_GENERAL_CONFIG (0x0D002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_FATAL_MEMORY_CONFIG (0x0D003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_DATA_ERR_MEMORY_CONFIG (0x0D004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_OVERFLOW_TONE_EVENTS_CONFIG (0x0D005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_H100_ERROR_CONFIG (0x0D006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_FATAL_GENERAL_TIMEOUT (0x0D007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_FATAL_MEMORY_TIMEOUT (0x0D008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_DATA_ERR_MEMORY_TIMEOUT (0x0D009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_OVERFLOW_TONE_EVENTS_TIMEOUT (0x0D00A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_H100_ERROR_TIMEOUT (0x0D00B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_AF_TIMESTAMP_READ_TIMEOUT (0x0D00C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_INTRPTS_NLP_TIMESTAMP_READ_TIMEOUT (0x0D00D + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_TSST_TIMESLOT (0x0E000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSST_STREAM (0x0E001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSST_TSST_RESERVED (0x0E002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSST_ASSOCIATED_TSST_RESERVED (0x0E003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_TSST_ALL_TSSTS_ARE_OPENED (0x0E004 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_MULTIPROC_API_INST_SHARED (0x10000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MULTIPROC_API_INST_LOCAL (0x10001 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_DEBUG_CHANNEL_INVALID_HANDLE (0x11000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_PORT (0x11001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_READ_LENGTH (0x11002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_SOUT_READ_LENGTH (0x11003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_READ_DATA (0x11004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_GET_EVENTS_RESET_BUFS (0x11005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_GET_EVENTS_BUF_EMPTY (0x11006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RECORD_RIN_PTR_INVALID (0x11007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RECORD_SIN_PTR_INVALID (0x11008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RECORD_ROUT_PTR_INVALID (0x11009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RECORD_SOUT_PTR_INVALID (0x1100A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RECORD_RAW_DATA_PTR_INVALID (0x1100B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RECORD_LENGTH_INVALID (0x1100C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RECORD_NO_CHAN_SELECTED (0x1100D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_PCM_LAW (0x1100E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_CHANNEL_RECORDING_DISABLED (0x1100F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_GET_DATA_MAX_BYTES (0x11010 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_GET_DATA_PTR_INVALID (0x11011 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_RC_CHANNEL_RECORDING_DISABLED (0x11012 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_GET_DATA_MODE (0x11013 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_CHANNEL_IN_POWER_DOWN (0x11014 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_GET_DATA_CONTENT (0x11015 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_DEBUG_GET_DATA_MODE_CANNOT_CHANGE (0x11016 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_MIXER_ALL_COPY_EVENT_ENTRY_OPENED (0x12000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_COPY_EVENT_HANDLE (0x12001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_SOURCE_CHAN_HANDLE (0x12002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_DESTINATION_CHAN_HANDLE (0x12003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_SOURCE_PORT (0x12004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_DESTINATION_PORT (0x12005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_EVENT_NOT_OPEN (0x12006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_SOURCE_ADPCM_RESOURCES_ACTIVATED (0x12007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_DEST_ADPCM_RESOURCES_ACTIVATED (0x12008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_MIXER_ALL_MIXER_EVENT_ENTRY_OPENED (0x12009 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_ADPCM_CHAN_DISABLED (0x13000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_INVALID_HANDLE (0x13001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_INPUT_TIMESLOT (0x13002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_INPUT_STREAM (0x13003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_OUTPUT_TIMESLOT (0x13004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_OUTPUT_STREAM (0x13005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_INPUT_NUM_TSSTS (0x13006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_OUTPUT_NUM_TSSTS (0x13007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_INPUT_PCM_LAW (0x13008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_MODE (0x13009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_ENCODING_RATE (0x1300A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_DECODING_RATE (0x1300B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_INCOMPATIBLE_NUM_TSSTS (0x1300C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_NO_MORE_TSI_AVAILABLE (0x1300D + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_OUTPUT_PCM_LAW (0x1300E + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_ADPCM_NIBBLE_POSITION (0x1300F + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_NOT_OPEN (0x13010 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_ADPCM_CHAN_ALL_ADPCM_CHAN_ARE_OPENED (0x13011 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_CHIP_STATS_RESET (0x14000 + cOCT6100_ERR_BASE) ++ ++ ++ ++#define cOCT6100_ERR_PRODUCTION_BIST_DISABLED (0x16000 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_REMOTEDEBUG_RECEIVED_PKT_PAYLOAD (0x2C000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_RESPONSE_PKT_PAYLOAD (0x2C001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_RECEIVED_PKT_LENGTH (0x2C002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_RESPONSE_PKT_LENGTH (0x2C003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_ENDIAN_DETECTION_FIELD (0x2C004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_CHECKSUM (0x2C005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTE_DEBUG_PARSING_ERROR (0x2C006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_ALL_SESSIONS_OPEN (0x2C007 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_INVALID_PACKET (0x2C008 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_TRANSACTION_ANSWERED (0x2C009 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_INAVLID_SESSION_NUMBER (0x2C00A + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_INVALID_HOT_CHAN_INDEX (0x2C00B + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_DISABLED (0x2C00C + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_REMOTEDEBUG_INVALID_RPC_COMMAND_NUM (0x2C00D + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_TLV_TIMEOUT (0x31000 + cOCT6100_ERR_BASE) ++ ++/* Fatal errors must always be greater or equal to 0xE000. */ ++#define cOCT6100_ERR_FATAL (0xDE000 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_FATAL_DRIVER_WRITE_API (0xDE000 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_FATAL_DRIVER_WRITE_EXT_API (0xDE001 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_FATAL_DRIVER_WRITE_SMEAR_API (0xDE002 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_FATAL_DRIVER_WRITE_BURST_API (0xDE003 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_FATAL_DRIVER_READ_API (0xDE004 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_FATAL_DRIVER_READ_BURST_API (0xDE005 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_FATAL_DRIVER_READ_DEBUG_API (0xDE006 + cOCT6100_ERR_BASE) ++#define cOCT6100_ERR_FATAL_DRIVER_WRITE_ARRAY_API (0xDE007 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_FATAL_BASE (0xDF000 + cOCT6100_ERR_BASE) ++ ++#define cOCT6100_ERR_FATAL_0 (0x00000 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_1 (0x00001 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_2 (0x00002 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_3 (0x00003 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_4 (0x00004 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_5 (0x00005 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_6 (0x00006 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_7 (0x00007 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_8 (0x00008 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_9 (0x00009 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A (0x0000A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B (0x0000B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C (0x0000C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D (0x0000D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E (0x0000E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_F (0x0000F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_10 (0x00010 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_11 (0x00011 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_12 (0x00012 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_13 (0x00013 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_14 (0x00014 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_15 (0x00015 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_16 (0x00016 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_17 (0x00017 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_18 (0x00018 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_19 (0x00019 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_1A (0x0001A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_1B (0x0001B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_1C (0x0001C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_1D (0x0001D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_1E (0x0001E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_1F (0x0001F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_20 (0x00020 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_21 (0x00021 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_22 (0x00022 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_23 (0x00023 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_24 (0x00024 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_25 (0x00025 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_26 (0x00026 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_27 (0x00027 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_28 (0x00028 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_29 (0x00029 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_2A (0x0002A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_2B (0x0002B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_2C (0x0002C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_2D (0x0002D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_2E (0x0002E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_2F (0x0002F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_30 (0x00030 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_31 (0x00031 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_32 (0x00032 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_33 (0x00033 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_34 (0x00034 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_35 (0x00035 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_36 (0x00036 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_37 (0x00037 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_38 (0x00038 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_39 (0x00039 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_3A (0x0003A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_3B (0x0003B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_3C (0x0003C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_3D (0x0003D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_3E (0x0003E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_3F (0x0003F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_40 (0x00040 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_41 (0x00041 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_42 (0x00042 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_43 (0x00043 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_44 (0x00044 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_45 (0x00045 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_46 (0x00046 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_47 (0x00047 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_48 (0x00048 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_49 (0x00049 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_4A (0x0004A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_4B (0x0004B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_4C (0x0004C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_4D (0x0004D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_4E (0x0004E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_4F (0x0004F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_50 (0x00050 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_51 (0x00051 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_52 (0x00052 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_53 (0x00053 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_54 (0x00054 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_55 (0x00055 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_56 (0x00056 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_57 (0x00057 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_58 (0x00058 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_59 (0x00059 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_5A (0x0005A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_5B (0x0005B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_5C (0x0005C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_5D (0x0005D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_5E (0x0005E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_5F (0x0005F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_60 (0x00060 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_61 (0x00061 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_62 (0x00062 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_63 (0x00063 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_64 (0x00064 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_65 (0x00065 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_66 (0x00066 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_67 (0x00067 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_68 (0x00068 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_69 (0x00069 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_6A (0x0006A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_6B (0x0006B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_6C (0x0006C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_6D (0x0006D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_6E (0x0006E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_6F (0x0006F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_70 (0x00070 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_71 (0x00071 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_72 (0x00072 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_73 (0x00073 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_74 (0x00074 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_75 (0x00075 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_76 (0x00076 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_77 (0x00077 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_78 (0x00078 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_79 (0x00079 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_7A (0x0007A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_7B (0x0007B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_7C (0x0007C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_7D (0x0007D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_7E (0x0007E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_7F (0x0007F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_80 (0x00080 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_81 (0x00081 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_82 (0x00082 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_83 (0x00083 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_84 (0x00084 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_85 (0x00085 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_86 (0x00086 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_87 (0x00087 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_88 (0x00088 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_89 (0x00089 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_8A (0x0008A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_8B (0x0008B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_8C (0x0008C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_8D (0x0008D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_8E (0x0008E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_8F (0x0008F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_90 (0x00090 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_91 (0x00091 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_92 (0x00092 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_93 (0x00093 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_94 (0x00094 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_95 (0x00095 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_96 (0x00096 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_97 (0x00097 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_98 (0x00098 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_99 (0x00099 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_9A (0x0009A + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_9B (0x0009B + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_9C (0x0009C + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_9D (0x0009D + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_9E (0x0009E + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_9F (0x0009F + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A0 (0x000A0 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A1 (0x000A1 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A2 (0x000A2 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A3 (0x000A3 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A4 (0x000A4 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A5 (0x000A5 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A6 (0x000A6 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A7 (0x000A7 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A8 (0x000A8 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_A9 (0x000A9 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_AA (0x000AA + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_AB (0x000AB + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_AC (0x000AC + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_AD (0x000AD + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_AE (0x000AE + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_AF (0x000AF + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B0 (0x000B0 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B1 (0x000B1 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B2 (0x000B2 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B3 (0x000B3 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B4 (0x000B4 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B5 (0x000B5 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B6 (0x000B6 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B7 (0x000B7 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B8 (0x000B8 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_B9 (0x000B9 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_BA (0x000BA + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_BB (0x000BB + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_BC (0x000BC + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_BD (0x000BD + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_BE (0x000BE + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_BF (0x000BF + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C0 (0x000C0 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C1 (0x000C1 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C2 (0x000C2 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C3 (0x000C3 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C4 (0x000C4 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C5 (0x000C5 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C6 (0x000C6 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C7 (0x000C7 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C8 (0x000C8 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_C9 (0x000C9 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_CA (0x000CA + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_CB (0x000CB + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_CC (0x000CC + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_CD (0x000CD + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_CE (0x000CE + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_CF (0x000CF + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D0 (0x000D0 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D1 (0x000D1 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D2 (0x000D2 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D3 (0x000D3 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D4 (0x000D4 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D5 (0x000D5 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D6 (0x000D6 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D7 (0x000D7 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D8 (0x000D8 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_D9 (0x000D9 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_DA (0x000DA + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_DB (0x000DB + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_DC (0x000DC + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_DD (0x000DD + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_DE (0x000DE + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_DF (0x000DF + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E0 (0x000E0 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E1 (0x000E1 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E2 (0x000E2 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E3 (0x000E3 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E4 (0x000E4 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E5 (0x000E5 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E6 (0x000E6 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E7 (0x000E7 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E8 (0x000E8 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_E9 (0x000E9 + cOCT6100_FATAL_BASE) ++#define cOCT6100_ERR_FATAL_EA (0x000EA + cOCT6100_FATAL_BASE) ++ ++#endif /* __OCT6100_ERRORS_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,69 @@ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_events_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_events.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_events_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 12 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_EVENTS_INST_H__ ++#define __OCT6100_EVENTS_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_TONE_EVENT_ ++{ ++ UINT32 ulChannelHandle; ++ UINT32 ulUserChanId; ++ UINT32 ulToneDetected; /* Tone number of the tone detected. */ ++ UINT32 ulTimestamp; ++ UINT32 ulEventType; ++ UINT32 ulExtToneDetectionPort; ++ ++} tOCT6100_API_TONE_EVENT, *tPOCT6100_API_TONE_EVENT; ++ ++typedef struct _OCT6100_API_BUFFER_PLAYOUT_EVENT_ ++{ ++ UINT32 ulChannelHandle; ++ UINT32 ulUserChanId; ++ UINT32 ulChannelPort; ++ UINT32 ulTimestamp; ++ UINT32 ulUserEventId; ++ UINT32 ulEventType; ++ ++} tOCT6100_API_BUFFER_PLAYOUT_EVENT, *tPOCT6100_API_BUFFER_PLAYOUT_EVENT; ++ ++#endif /* __OCT6100_EVENTS_INST_H__ */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,111 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_events_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_events.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_events_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 14 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_EVENTS_PUB_H__ ++#define __OCT6100_EVENTS_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_TONE_EVENT_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulUserChanId; ++ ++ UINT32 ulToneDetected; ++ ++ UINT32 ulTimestamp; ++ UINT32 ulEventType; ++ ++ UINT32 ulExtToneDetectionPort; ++ ++} tOCT6100_TONE_EVENT, *tPOCT6100_TONE_EVENT; ++ ++typedef struct _OCT6100_EVENT_GET_TONE_ ++{ ++ BOOL fMoreEvents; ++ BOOL fResetBufs; ++ ++ UINT32 ulMaxToneEvent; ++ UINT32 ulNumValidToneEvent; ++ ++ tPOCT6100_TONE_EVENT pToneEvent; ++ ++} tOCT6100_EVENT_GET_TONE, *tPOCT6100_EVENT_GET_TONE; ++ ++typedef struct _OCT6100_BUFFER_PLAYOUT_EVENT_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulUserChanId; ++ UINT32 ulChannelPort; ++ ++ UINT32 ulTimestamp; ++ ++ UINT32 ulUserEventId; ++ UINT32 ulEventType; ++ ++} tOCT6100_BUFFER_PLAYOUT_EVENT, *tPOCT6100_BUFFER_PLAYOUT_EVENT; ++ ++typedef struct _OCT6100_BUFFER_PLAYOUT_GET_EVENT_ ++{ ++ BOOL fMoreEvents; ++ BOOL fResetBufs; ++ ++ UINT32 ulMaxEvent; ++ UINT32 ulNumValidEvent; ++ ++ tPOCT6100_BUFFER_PLAYOUT_EVENT pBufferPlayoutEvent; ++ ++} tOCT6100_BUFFER_PLAYOUT_GET_EVENT, *tPOCT6100_BUFFER_PLAYOUT_GET_EVENT; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100EventGetToneDef( ++ OUT tPOCT6100_EVENT_GET_TONE f_pEventGetTone ); ++UINT32 Oct6100EventGetTone( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_EVENT_GET_TONE f_pEventGetTone ); ++ ++UINT32 Oct6100BufferPlayoutGetEventDef( ++ OUT tPOCT6100_BUFFER_PLAYOUT_GET_EVENT f_pBufPlayoutGetEvent ); ++UINT32 Oct6100BufferPlayoutGetEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_GET_EVENT f_pBufPlayoutGetEvent ); ++ ++#endif /* __OCT6100_EVENTS_PUB_H__ */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,134 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_interrupts_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_interrupts.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_interrupts_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 16 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_INTERRUPTS_INST_H__ ++#define __OCT6100_INTERRUPTS_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_INTRPT_CONFIG_ ++{ ++ /* The configuration of each group of interrupts. Each can have one of the ++ following values: ++ cOCT6100_INTRPT_DISABLE, ++ cOCT6100_INTRPT_NO_TIMEOUT, ++ cOCT6100_INTRPT_TIMEOUT. */ ++ UINT8 byFatalGeneralConfig; ++ UINT8 byFatalMemoryConfig; ++ UINT8 byErrorMemoryConfig; ++ UINT8 byErrorOverflowToneEventsConfig; ++ UINT8 byErrorH100Config; ++ ++ /* The timeout value for each interrupt group, if the corresponding ++ configuration variable is set to cOCT6100_INTRPT_TIMEOUT. This ++ value is kept in mclk cycles. */ ++ UINT32 ulFatalMemoryTimeoutMclk; ++ UINT32 ulErrorMemoryTimeoutMclk; ++ UINT32 ulErrorOverflowToneEventsTimeoutMclk; ++ UINT32 ulErrorH100TimeoutMclk; ++ ++} tOCT6100_API_INTRPT_CONFIG, *tPOCT6100_API_INTRPT_CONFIG; ++ ++typedef struct _OCT6100_API_INTRPT_MANAGE_ ++{ ++ /* Number of mclk cycles in 1ms. */ ++ UINT32 ulNumMclkCyclesIn1Ms; ++ ++ /* Whether the mclk interrupt is active. */ ++ UINT8 fMclkIntrptActive; ++ UINT32 ulNextMclkIntrptTimeHigh; ++ UINT32 ulNextMclkIntrptTimeLow; ++ ++ /* Mclk time read from registers. */ ++ UINT32 ulRegMclkTimeHigh; ++ UINT32 ulRegMclkTimeLow; ++ ++ /* Used by the interrupt service routine. */ ++ UINT16 usRegister102h; ++ UINT16 usRegister202h; ++ UINT16 usRegister302h; ++ UINT16 usRegister502h; ++ UINT16 usRegister702h; ++ ++ /* The state of each interrupt group. Can be one of the following: ++ cOCT6100_INTRPT_ACTIVE, ++ cOCT6100_INTRPT_WILL_TIMEOUT, ++ cOCT6100_INTRPT_IN_TIMEOUT, ++ cOCT6100_INTRPT_WILL_DISABLED. */ ++ UINT16 byFatalGeneralState; ++ UINT16 byFatalMemoryState; ++ UINT16 byErrorMemoryState; ++ UINT16 byErrorOverflowToneEventsState; ++ UINT16 byErrorH100State; ++ ++ /* The time at which each disabled interrupt was disabled, in mclk cycles. */ ++ UINT32 ulFatalMemoryDisableMclkHigh; ++ UINT32 ulFatalMemoryDisableMclkLow; ++ UINT32 ulErrorMemoryDisableMclkHigh; ++ UINT32 ulErrorMemoryDisableMclkLow; ++ UINT32 ulErrorOverflowToneEventsDisableMclkHigh; ++ UINT32 ulErrorOverflowToneEventsDisableMclkLow; ++ UINT32 ulErrorH100DisableMclkHigh; ++ UINT32 ulErrorH100DisableMclkLow; ++ ++ /* The time at which each disabled interrupt group is to be reenabled, ++ in number of mclk cycles. */ ++ UINT32 ulFatalGeneralEnableMclkHigh; ++ UINT32 ulFatalGeneralEnableMclkLow; ++ UINT32 ulFatalMemoryEnableMclkHigh; ++ UINT32 ulFatalMemoryEnableMclkLow; ++ UINT32 ulErrorMemoryEnableMclkHigh; ++ UINT32 ulErrorMemoryEnableMclkLow; ++ UINT32 ulErrorOverflowToneEventsEnableMclkHigh; ++ UINT32 ulErrorOverflowToneEventsEnableMclkLow; ++ UINT32 ulErrorH100EnableMclkHigh; ++ UINT32 ulErrorH100EnableMclkLow; ++ ++ /* If this is set, buffer playout events are pending. */ ++ UINT8 fBufferPlayoutEventsPending; ++ /* If this is set, tone events are pending. */ ++ UINT8 fToneEventsPending; ++ ++ ++ ++ UINT8 fIsrCalled; ++ ++} tOCT6100_API_INTRPT_MANAGE, *tPOCT6100_API_INTRPT_MANAGE; ++ ++#endif /* __OCT6100_INTERRUPTS_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,102 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_interrupts_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_interrupts.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_interrupts_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 23 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_INTERRUPTS_PUB_H__ ++#define __OCT6100_INTERRUPTS_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_INTERRUPT_CONFIGURE_ ++{ ++ UINT32 ulFatalGeneralConfig; ++ UINT32 ulFatalMemoryConfig; ++ ++ UINT32 ulErrorMemoryConfig; ++ UINT32 ulErrorOverflowToneEventsConfig; ++ UINT32 ulErrorH100Config; ++ ++ UINT32 ulFatalMemoryTimeout; ++ UINT32 ulErrorMemoryTimeout; ++ UINT32 ulErrorOverflowToneEventsTimeout; ++ UINT32 ulErrorH100Timeout; ++ ++} tOCT6100_INTERRUPT_CONFIGURE, *tPOCT6100_INTERRUPT_CONFIGURE; ++ ++typedef struct _OCT6100_INTERRUPT_FLAGS_ ++{ ++ BOOL fFatalGeneral; ++ UINT32 ulFatalGeneralFlags; ++ ++ BOOL fFatalReadTimeout; ++ ++ BOOL fErrorRefreshTooLate; ++ BOOL fErrorPllJitter; ++ ++ BOOL fErrorOverflowToneEvents; ++ ++ BOOL fErrorH100OutOfSync; ++ BOOL fErrorH100ClkA; ++ BOOL fErrorH100ClkB; ++ BOOL fErrorH100FrameA; ++ ++ BOOL fToneEventsPending; ++ BOOL fBufferPlayoutEventsPending; ++ ++ BOOL fApiSynch; ++ ++ ++ ++} tOCT6100_INTERRUPT_FLAGS, *tPOCT6100_INTERRUPT_FLAGS; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100InterruptConfigureDef( ++ OUT tPOCT6100_INTERRUPT_CONFIGURE f_pConfigInts ); ++UINT32 Oct6100InterruptConfigure( ++ IN tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_INTERRUPT_CONFIGURE f_pConfigInts ); ++ ++UINT32 Oct6100InterruptServiceRoutineDef( ++ OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ); ++UINT32 Oct6100InterruptServiceRoutine( ++ IN tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ); ++ ++#endif /* __OCT6100_INTERRUPTS_PUB_H__ */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,86 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_mixer_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_mixer.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_mixer_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 13 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_MIXER_INST_H__ ++#define __OCT6100_MIXER_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_MIXER_EVENT_ ++{ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved; ++ ++ /* Type of the event.*/ ++ UINT16 usEventType; ++ ++ /* Source channel index */ ++ UINT16 usSourceChanIndex; ++ ++ /* Destination channel index */ ++ UINT16 usDestinationChanIndex; ++ ++ /* Pointer to the next entry.*/ ++ UINT16 usNextEventPtr; ++ ++} tOCT6100_API_MIXER_EVENT, *tPOCT6100_API_MIXER_EVENT; ++ ++ ++typedef struct _OCT6100_API_COPY_EVENT_ ++{ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved; ++ ++ /* Count used to manage entry handles allocated to user. */ ++ UINT8 byEntryOpenCnt; ++ ++ /* Source + destination ports. */ ++ UINT8 bySourcePort; ++ UINT8 byDestinationPort; ++ ++ /* Index of the channels associated to this event.*/ ++ UINT16 usSourceChanIndex; ++ UINT16 usDestinationChanIndex; ++ ++ UINT16 usMixerEventIndex; ++ ++} tOCT6100_API_COPY_EVENT, *tPOCT6100_API_COPY_EVENT; ++ ++ ++#endif /* __OCT6100_MIXER_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,77 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_mixer_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_mixer.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_mixer_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 7 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_MIXER_PUB_H__ ++#define __OCT6100_MIXER_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_COPY_EVENT_CREATE_ ++{ ++ PUINT32 pulCopyEventHndl; ++ ++ UINT32 ulSourceChanHndl; ++ UINT32 ulSourcePort; ++ ++ UINT32 ulDestinationChanHndl; ++ UINT32 ulDestinationPort; ++ ++} tOCT6100_COPY_EVENT_CREATE, *tPOCT6100_COPY_EVENT_CREATE; ++ ++typedef struct _OCT6100_COPY_EVENT_DESTROY_ ++{ ++ UINT32 ulCopyEventHndl; ++ ++} tOCT6100_COPY_EVENT_DESTROY, *tPOCT6100_COPY_EVENT_DESTROY; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100MixerCopyEventCreateDef( ++ OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate ); ++UINT32 Oct6100MixerCopyEventCreate( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate ); ++ ++UINT32 Oct6100MixerCopyEventDestroyDef( ++ OUT tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy ); ++UINT32 Oct6100MixerCopyEventDestroy( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy ); ++ ++#endif /* __OCT6100_MIXER_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,68 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_phasing_tsst_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_phasing_tsst.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_phasing_tsst_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 11 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_PHASING_TSST_INST_H__ ++#define __OCT6100_PHASING_TSST_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_PHASING_TSST_ ++{ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved; ++ ++ /* Count used to manage entry handles allocated to user. */ ++ UINT8 byEntryOpenCnt; ++ ++ /* Count of number of resources connected in some way to this buffer. */ ++ UINT16 usDependencyCnt; ++ ++ /* TDM timeslot and stream where the counter is read. */ ++ UINT16 usStream; ++ UINT16 usTimeslot; ++ ++ /* Length of the phasing TSST counter. */ ++ UINT16 usPhasingLength; ++ ++ /* TSST control index where the counter comes from. */ ++ UINT16 usPhasingTsstIndex; ++ ++} tOCT6100_API_PHASING_TSST, *tPOCT6100_API_PHASING_TSST; ++ ++#endif /* __OCT6100_PHASING_TSST_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,78 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_phasing_tsst_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_phasing_tsst.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_phasing_tsst_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 10 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_PHASING_TSST_PUB_H__ ++#define __OCT6100_PHASING_TSST_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_PHASING_TSST_OPEN_ ++{ ++ PUINT32 pulPhasingTsstHndl; ++ ++ UINT32 ulPhasingLength; ++ UINT32 ulTimeslot; ++ UINT32 ulStream; ++ ++ ++ ++} tOCT6100_PHASING_TSST_OPEN, *tPOCT6100_PHASING_TSST_OPEN; ++ ++typedef struct _OCT6100_PHASING_TSST_CLOSE_ ++{ ++ UINT32 ulPhasingTsstHndl; ++ ++} tOCT6100_PHASING_TSST_CLOSE, *tPOCT6100_PHASING_TSST_CLOSE; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100PhasingTsstOpenDef( ++ OUT tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ); ++UINT32 Oct6100PhasingTsstOpen( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ); ++ ++UINT32 Oct6100PhasingTsstCloseDef( ++ OUT tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose ); ++UINT32 Oct6100PhasingTsstClose( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose ); ++ ++#endif /* __OCT6100_PHASING_TSST_PUB_H__ */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,88 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_playout_buf_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_playout_buf.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_playout_buf_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 10 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_PLAYOUT_BUF_INST_H__ ++#define __OCT6100_PLAYOUT_BUF_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++#define mOCT6100_GET_BUFFER_MEMORY_NODE_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE )(( PUINT8 )pSharedInfo + pSharedInfo->ulPlayoutBufMemoryNodeListOfst ); ++ ++#define mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE )(( PUINT8 )pSharedInfo + pSharedInfo->ulPlayoutBufMemoryNodeListOfst)) + ulIndex; ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE_ ++{ ++ /* Next node. */ ++ UINT32 ulNext; ++ ++ /* Previous node. */ ++ UINT32 ulPrevious; ++ ++ /* Start address of this node. */ ++ UINT32 ulStartAddress; ++ ++ /* Size of this node. */ ++ UINT32 ulSize; ++ ++ /* Allocated node? Free node? */ ++ UINT8 fAllocated; ++ ++} tOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE, *tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE; ++ ++typedef struct _OCT6100_API_BUFFER_ ++{ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved; ++ ++ /* Pcm law of the buffer. */ ++ UINT8 byBufferPcmLaw; ++ ++ /* Number of channels currently playing this buffer.*/ ++ UINT16 usDependencyCnt; ++ ++ /* Length of the buffer ( in bytes ).*/ ++ UINT32 ulBufferSize; ++ ++ /* Address in external memory of the buffer. */ ++ UINT32 ulBufferBase; ++ ++} tOCT6100_API_BUFFER, *tPOCT6100_API_BUFFER; ++ ++#endif /* __OCT6100_PLAYOUT_BUF_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,183 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_playout_buf_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_playout_buf.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_playout_buf_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 21 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_PLAYOUT_BUF_PUB_H__ ++#define __OCT6100_PLAYOUT_BUF_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_BUFFER_LOAD_ ++{ ++ PUINT32 pulBufferIndex; /* Index identifying the buffer. */ ++ PUINT32 pulPlayoutFreeMemSize; /* Amount of free memory available for other buffers. */ ++ ++ PUINT8 pbyBufferPattern; /* A byte pointer pointing to a valid buffer to be loaded into the chip's external memory. */ ++ UINT32 ulBufferSize; /* Size of the buffer loaded into external memory. */ ++ ++ UINT32 ulBufferPcmLaw; /* Buffer PCM law. */ ++ ++} tOCT6100_BUFFER_LOAD, *tPOCT6100_BUFFER_LOAD; ++ ++typedef struct _OCT6100_BUFFER_LOAD_BLOCK_INIT_ ++{ ++ PUINT32 pulBufferIndex; /* Index identifying the buffer. */ ++ PUINT32 pulPlayoutFreeMemSize; /* Amount of free memory available for other buffers. */ ++ ++ UINT32 ulBufferSize; /* Size of the buffer to be loaded in memory. This space will be reserved. */ ++ ++ UINT32 ulBufferPcmLaw; /* Buffer PCM law. */ ++ ++} tOCT6100_BUFFER_LOAD_BLOCK_INIT, *tPOCT6100_BUFFER_LOAD_BLOCK_INIT; ++ ++typedef struct _OCT6100_BUFFER_LOAD_BLOCK_ ++{ ++ UINT32 ulBufferIndex; /* Index identifying the buffer. */ ++ ++ /* Offset, in bytes, of the first byte in the block to be loaded. */ ++ /* This offset is with respect to the beginning of the buffer. */ ++ /* This value must be modulo 2 */ ++ UINT32 ulBlockOffset; ++ ++ /* Size of the block to be loaded into external memory. */ ++ /* This value must be modulo 2. */ ++ UINT32 ulBlockLength; ++ ++ /* A pointer pointing to a valid buffer block to be loaded */ ++ /* into the chip's external memory. This is a pointer to the entire */ ++ /* buffer. The API uses the ulBlockOffset and ulBlockLength to index */ ++ /* within this buffer and obtain the block to be loaded. */ ++ PUINT8 pbyBufferPattern; ++ ++} tOCT6100_BUFFER_LOAD_BLOCK, *tPOCT6100_BUFFER_LOAD_BLOCK; ++ ++typedef struct _OCT6100_BUFFER_UNLOAD_ ++{ ++ UINT32 ulBufferIndex; /* Index identifying the buffer. */ ++ ++} tOCT6100_BUFFER_UNLOAD, *tPOCT6100_BUFFER_UNLOAD; ++ ++typedef struct _OCT6100_BUFFER_PLAYOUT_ADD_ ++{ ++ UINT32 ulChannelHndl; /* Echo cancelling channel on which to play the buffer. */ ++ ++ UINT32 ulBufferIndex; /* Index identifying the buffer. */ ++ ++ UINT32 ulPlayoutPort; /* Selected channel port where to play to tone. */ ++ UINT32 ulMixingMode; /* Weither or not the voice stream will be muted while playing the buffer. */ ++ ++ INT32 lGainDb; /* Gain applied to the buffer that will be played on the specified port. */ ++ ++ BOOL fRepeat; /* Use ulRepeatCount variable. */ ++ UINT32 ulRepeatCount; /* Number of times to repeat playing the selected buffer. */ ++ ++ UINT32 ulDuration; /* Duration in millisecond that this buffer should play. Setting this overrides fRepeat. */ ++ ++ UINT32 ulBufferLength; /* Length of the buffer to play (starting at the beginning), AUTO_SELECT for all. */ ++ ++} tOCT6100_BUFFER_PLAYOUT_ADD, *tPOCT6100_BUFFER_PLAYOUT_ADD; ++ ++typedef struct _OCT6100_BUFFER_PLAYOUT_START_ ++{ ++ UINT32 ulChannelHndl; /* Echo cancelling channel on which to play the buffer. */ ++ UINT32 ulPlayoutPort; /* Selected channel port where to play to tone. */ ++ ++ BOOL fNotifyOnPlayoutStop; /* Check if the buffers have finished playing on this channel/port. */ ++ /* The events are queued in a soft buffer that the user must empty regularly. */ ++ UINT32 ulUserEventId; /* Returned to the user when the playout is finished and the user has set the fNotifyOnPlayoutStop flag. */ ++ ++ BOOL fAllowStartWhileActive; /* Use this to add buffers to something that is already playing on the channel/port. */ ++ ++} tOCT6100_BUFFER_PLAYOUT_START, *tPOCT6100_BUFFER_PLAYOUT_START; ++ ++typedef struct _OCT6100_BUFFER_PLAYOUT_STOP_ ++{ ++ UINT32 ulChannelHndl; /* Echo cancelling channel on which to play the buffer. */ ++ UINT32 ulPlayoutPort; /* Selected channel port where to play to tone. */ ++ BOOL fStopCleanly; /* Whether or not the skip will be clean. */ ++ ++ PBOOL pfAlreadyStopped; /* Whether playout was already stopped or not. */ ++ PBOOL pfNotifyOnPlayoutStop; /* Whether the user chosed to receive an event on playout stop. */ ++ ++} tOCT6100_BUFFER_PLAYOUT_STOP, *tPOCT6100_BUFFER_PLAYOUT_STOP; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100BufferPlayoutLoadDef( ++ OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad ); ++UINT32 Oct6100BufferPlayoutLoad( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad ); ++ ++UINT32 Oct6100BufferPlayoutLoadBlockInitDef( ++ OUT tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ); ++UINT32 Oct6100BufferPlayoutLoadBlockInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ); ++ ++UINT32 Oct6100BufferPlayoutLoadBlockDef( ++ OUT tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ); ++UINT32 Oct6100BufferPlayoutLoadBlock( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ); ++ ++UINT32 Oct6100BufferPlayoutUnloadDef( ++ OUT tPOCT6100_BUFFER_UNLOAD f_pBufferUnload ); ++UINT32 Oct6100BufferPlayoutUnload( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_UNLOAD f_pBufferUnload ); ++ ++UINT32 Oct6100BufferPlayoutAddDef( ++ OUT tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ); ++UINT32 Oct6100BufferPlayoutAdd( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ); ++ ++UINT32 Oct6100BufferPlayoutStartDef( ++ OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart ); ++UINT32 Oct6100BufferPlayoutStart( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart ); ++ ++UINT32 Oct6100BufferPlayoutStopDef( ++ OUT tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ); ++UINT32 Oct6100BufferPlayoutStop( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ); ++ ++#endif /* __OCT6100_PLAYOUT_BUF_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,73 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_remote_debug_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_remote_debug.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_remote_debug_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 6 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_REMOTE_DEBUG_INST_H__ ++#define __OCT6100_REMOTE_DEBUG_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_REMOTE_DEBUG_INFO_ ++{ ++ UINT32 ulSessionTreeOfst; ++ UINT32 ulSessionListOfst; ++ UINT32 ulSessionListHead; ++ UINT32 ulSessionListTail; ++ ++ UINT32 ulPktCacheOfst; ++ UINT32 ulDataBufOfst; ++ ++ UINT32 ulNumSessionsOpen; ++ UINT32 ulMaxSessionsOpen; ++ ++} tOCT6100_API_REMOTE_DEBUG_INFO, *tPOCT6100_API_REMOTE_DEBUG_INFO; ++ ++typedef struct _OCT6100_API_REMOTE_DEBUG_SESSION_ ++{ ++ UINT32 ulSessionNum; ++ UINT32 ulTransactionNum; ++ UINT32 ulPktRetryNum; ++ UINT32 ulPktByteSize; ++ ++ UINT32 aulLastPktTime[ 2 ]; ++ UINT32 ulForwardLink; ++ UINT32 ulBackwardLink; ++ ++} tOCT6100_API_REMOTE_DEBUG_SESSION, *tPOCT6100_API_REMOTE_DEBUG_SESSION; ++ ++#endif /* __OCT6100_REMOTE_DEBUG_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,64 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_remote_debug_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_remote_debug.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_remote_debug_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 6 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_REMOTE_DEBUG_PUB_H__ ++#define __OCT6100_REMOTE_DEBUG_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_REMOTE_DEBUG_ ++{ ++ PUINT32 pulReceivedPktPayload; ++ UINT32 ulReceivedPktLength; ++ ++ PUINT32 pulResponsePktPayload; ++ UINT32 ulMaxResponsePktLength; ++ UINT32 ulResponsePktLength; ++ ++} tOCT6100_REMOTE_DEBUG, *tPOCT6100_REMOTE_DEBUG; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100RemoteDebugDef( ++ OUT tPOCT6100_REMOTE_DEBUG f_pRemoteDebug ); ++UINT32 Oct6100RemoteDebug( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_REMOTE_DEBUG f_pRemoteDebug ); ++ ++#endif /* __OCT6100_REMOTE_DEBUG_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tlv_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tlv_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tlv_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tlv_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,72 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tlv_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_tlv.c. All elements defined in this file are for public ++ usage of the API. All instate elements are defined in the ++ oct6100_tlv_inst.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 7 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TLV_INST_H__ ++#define __OCT6100_TLV_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_TLV_OFFSET_ ++{ ++ /* The dword offset contain the number of dword from a base address to reach the desired dword. ++ ++ i.e. usDwordOffset = (total bit offset) / 32; */ ++ ++ UINT16 usDwordOffset; ++ ++ /* The bit offset will contain the bit offset required to right shift the DWORD read and obtain ++ the desired value. This field is depend on the field size. ++ ++ i.e. byBitOffset = 31 - ((total bit offset) % 32) - byFieldSize; */ ++ ++ UINT8 byBitOffset; ++ UINT8 byFieldSize; ++ ++} tOCT6100_TLV_OFFSET, *tPOCT6100_TLV_OFFSET; ++ ++typedef struct _OCT6100_TLV_TONE_INFO_ ++{ ++ UINT32 ulToneID; ++ UINT32 ulDetectionPort; ++ ++ UINT8 aszToneName[ cOCT6100_TLV_MAX_TONE_NAME_SIZE ]; ++ ++ ++ ++} tOCT6100_TLV_TONE_INFO, *tPOCT6100_TLV_TONE_INFO; ++ ++#endif /* __OCT6100_TLV_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,46 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tone_detection_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_tone_detection_buf.c. All elements defined in this file are for ++ public usage of the API. All private elements are defined in the ++ oct6100_tone_detection_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 8 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TONE_DETECTION_INST_H__ ++#define __OCT6100_TONE_DETECTION_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++ ++#endif /* __OCT6100_TONE_DETECTION_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,74 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tone_detection_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_tone_detection.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_tone_detection_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 10 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TONE_DETECTION_PUB_H__ ++#define __OCT6100_TONE_DETECTION_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_TONE_DETECTION_ENABLE_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulToneNumber; ++ ++} tOCT6100_TONE_DETECTION_ENABLE, *tPOCT6100_TONE_DETECTION_ENABLE; ++ ++typedef struct _OCT6100_TONE_DETECTION_DISABLE_ ++{ ++ UINT32 ulChannelHndl; ++ UINT32 ulToneNumber; ++ BOOL fDisableAll; ++ ++} tOCT6100_TONE_DETECTION_DISABLE, *tPOCT6100_TONE_DETECTION_DISABLE; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ToneDetectionEnableDef( ++ OUT tPOCT6100_TONE_DETECTION_ENABLE f_pBufferLoad ); ++UINT32 Oct6100ToneDetectionEnable( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TONE_DETECTION_ENABLE f_pBufferLoad ); ++ ++UINT32 Oct6100ToneDetectionDisableDef( ++ OUT tPOCT6100_TONE_DETECTION_DISABLE f_pBufferUnload ); ++UINT32 Oct6100ToneDetectionDisable( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TONE_DETECTION_DISABLE f_pBufferUnload ); ++ ++#endif /* __OCT6100_TONE_DETECTION_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,70 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tsi_cnct_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_tsi_cnct.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_tsi_cnct_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 9 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TSI_CNCT_INST_H__ ++#define __OCT6100_TSI_CNCT_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_TSI_CNCT_ ++{ ++ /* Flag specifying whether the entry is used or not. */ ++ UINT8 fReserved; ++ ++ /* Count used to manage entry handles allocated to user. */ ++ UINT8 byEntryOpenCnt; ++ ++ /* Input PCM law. */ ++ UINT8 byInputPcmLaw; ++ ++ /* TSI chariot memory entry. */ ++ UINT16 usTsiMemIndex; ++ ++ /* Input and output timeslot information. */ ++ UINT16 usInputTimeslot; ++ UINT16 usInputStream; ++ ++ UINT16 usOutputTimeslot; ++ UINT16 usOutputStream; ++ ++ /* Internal info for quick access to structures associated to this TSI cnct. */ ++ UINT16 usInputTsstIndex; ++ UINT16 usOutputTsstIndex; ++ ++} tOCT6100_API_TSI_CNCT, *tPOCT6100_API_TSI_CNCT; ++ ++#endif /* __OCT6100_TSI_CNCT_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_pub.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_pub.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_pub.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_pub.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,76 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tsi_cnct_pub.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_tsi_cnct.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_tsi_cnct_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 11 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TSI_CNCT_PUB_H__ ++#define __OCT6100_TSI_CNCT_PUB_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_TSI_CNCT_OPEN_ ++{ ++ PUINT32 pulTsiCnctHndl; ++ ++ UINT32 ulInputTimeslot; ++ UINT32 ulInputStream; ++ UINT32 ulOutputTimeslot; ++ UINT32 ulOutputStream; ++ ++} tOCT6100_TSI_CNCT_OPEN, *tPOCT6100_TSI_CNCT_OPEN; ++ ++typedef struct _OCT6100_TSI_CNCT_CLOSE_ ++{ ++ UINT32 ulTsiCnctHndl; ++ ++} tOCT6100_TSI_CNCT_CLOSE, *tPOCT6100_TSI_CNCT_CLOSE; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100TsiCnctOpenDef( ++ OUT tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ); ++UINT32 Oct6100TsiCnctOpen( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ); ++ ++UINT32 Oct6100TsiCnctCloseDef( ++ OUT tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose ); ++UINT32 Oct6100TsiCnctClose( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose ); ++ ++#endif /* __OCT6100_TSI_CNCT_PUB_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsst_inst.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsst_inst.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsst_inst.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsst_inst.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,55 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tsst_inst.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines, macros, and structures pertaining to the file ++ oct6100_tsst.c. All elements defined in this file are for public ++ usage of the API. All private elements are defined in the ++ oct6100_tsst_priv.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 5 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TSST_INST_H__ ++#define __OCT6100_TSST_INST_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_TSST_ENTRY_ ++{ ++ UINT16 usTsstMemoryIndex; /* Index in the TSST memory of the TSST */ ++ UINT16 usTsstValue; /* Tsst value given by the user. */ ++ /* bit 5:0 = stream value, bit 13:6 = timeslot value. */ ++ ++ UINT16 usNextEntry; /* Pointer to the next entry in the list. */ ++ ++} tOCT6100_API_TSST_ENTRY, *tPOCT6100_API_TSST_ENTRY; ++ ++#endif /* __OCT6100_TSST_INST_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octdef.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octdef.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octdef.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octdef.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,116 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octdef.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Common system definitions. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 12 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCTDEF_H__ ++#define __OCTDEF_H__ ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/*-------------------------------------------------------------------------- ++ Get Platform Dependency headers ++----------------------------------------------------------------------------*/ ++#include "octosdependant.h" ++ ++ ++/*-------------------------------------------------------------------------- ++ Common Type definitions ++----------------------------------------------------------------------------*/ ++#include "octtype.h" ++ ++/***************************** DEFINES *************************************/ ++ ++/* List of functions to skip compiling since we don't use them */ ++#include "digium_unused.h" ++ ++ ++ ++/*-------------------------------------------------------------------------- ++ Miscellaneous constants ++----------------------------------------------------------------------------*/ ++ ++#ifndef PROTO ++#define PROTO extern ++#endif ++ ++/* Generic return codes. */ ++#define cOCTDEF_RC_OK 0 /* Generic Ok */ ++#define cOCTDEF_RC_ERROR 1 /* Generic Error */ ++ ++/* Default return values of all OCTAPI functions. */ ++#ifndef GENERIC_OK ++#define GENERIC_OK 0x00000000 ++#endif ++ ++#ifndef GENERIC_ERROR ++#define GENERIC_ERROR 0x00000001 ++#endif ++ ++#ifndef GENERIC_BAD_PARAM ++#define GENERIC_BAD_PARAM 0x00000002 ++#endif ++ ++/* Defines of boolean expressions (TRUE/FALSE) */ ++#ifndef FALSE ++#define FALSE (BOOL)0 ++#endif ++ ++#ifndef TRUE ++#define TRUE (BOOL)1 ++#endif ++ ++/*-------------------------------------------------------------------------- ++ DLL Import-Export ++----------------------------------------------------------------------------*/ ++ ++#ifdef OCT_WINENV ++#define DLLIMP __declspec( dllimport ) ++#define DLLEXP __declspec( dllexport ) ++#else ++#define DLLIMP ++#define DLLEXP ++#endif ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __OCTDEF_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octmac.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octmac.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octmac.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octmac.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,98 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octmac.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ Common macro definitions. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 14 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#ifndef __OCTMAC_H__ ++#define __OCTMAC_H__ ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/***************************** DEFINES *************************************/ ++ ++/* Combine l & h to form a 32 bit quantity. */ ++#define mMAKEULONG(l, h) ((ULONG)(((USHORT)(l)) | (((ULONG)((USHORT)(h))) << 16))) ++ ++#define mLOUCHAR(w) ((UCHAR)(w)) ++#define mHIUCHAR(w) ((UCHAR)(((USHORT)(w) >> 8) & 0xff)) ++#define mLOUSHORT(l) ((USHORT)((ULONG)l)) ++#define mHIUSHORT(l) ((USHORT)(((ULONG)(l) >> 16) & 0xffff)) ++#define mLOSHORT(l) ((SHORT)((ULONG)l)) ++#define mHISHORT(l) ((SHORT)(((ULONG)(l) >> 16) & 0xffff)) ++ ++/* Combine l & h to form a 16 bit quantity. */ ++#define mMAKEUSHORT(l, h) (((USHORT)(l)) | ((USHORT)(h)) << 8) ++#define mMAKESHORT(l, h) ((SHORT)mMAKEUSHORT(l, h)) ++ ++/* Extract high and low order parts of 16 and 32 bit quantity */ ++#define mLOBYTE(w) mLOUCHAR(w) ++#define mHIBYTE(w) mHIUCHAR(w) ++#define mMAKELONG(l, h) ((LONG)mMAKEULONG(l, h)) ++ ++/*-------------------------------------------------------------------------- ++ Bite conversion macro ++----------------------------------------------------------------------------*/ ++#define mSWAP_INT16(x) mMAKEUSHORT( mHIBYTE(x), mLOBYTE(x) ) ++#define mSWAP_INT32(x) mMAKEULONG( mSWAP_INT16(mHIUSHORT(x)), mSWAP_INT16(mLOUSHORT(x)) ) ++ ++ ++/* Cast any variable to an instance of the specified type. */ ++#define mMAKETYPE(v, type) (*((type *)&v)) ++ ++/* Calculate the byte offset of a field in a structure of type type. */ ++#define mFIELDOFFSET(type, field) ((UINT32)&(((type *)0)->field)) ++#define mCOUNTOF(array) (sizeof(array)/sizeof(array[0])) ++ ++#define mMAX(a,b) (((a) > (b)) ? (a) : (b)) ++#define mMIN(a,b) (((a) < (b)) ? (a) : (b)) ++ ++#define mDIM(x) (sizeof(x) / sizeof(x[0])) ++ ++#define mFROMDIGIT(ch) ((ch) - 0x30) /* digit to char */ ++#define mTODIGIT(ch) ((ch) + 0x30) /* int to char */ ++ ++#define mISLEAP(a) ( !( a % 400 ) || ( ( a % 100 ) && !( a % 4 ) ) ) ++ ++#define mFOREVER for( ;; ) ++ ++#define mROUND_TO_NEXT_4( a ) ( ((a) % 4) ? ( (a) + 4 - ((a)%4) ) : (a) ) ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __OCTMAC_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octosdependant.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octosdependant.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octosdependant.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octosdependant.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,170 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octosdependant.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file is included to set target-specific constants. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 18 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCTOSDEPENDANT_H__ ++#define __OCTOSDEPENDANT_H__ ++ ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ++ ++/***************************************************************************** ++ ++ Known define values ++ ++ MSDEV: ++ WIN32 == WINDOWS 32 bit app ++ __WIN32__ == WINDOWS 32 bit app ++ _Windows == WINDOWS 16 bit app ++ ++ _WINDOWS == Windows application .. not console ++ _DLL == Dll Application ++ _CONSOLE == Console Application .. no windows ++ ++ BORLANDC ++ __TURBOC__ == Turbo Compiler ++ __BORLANDC__ == Borland compiler ++ __OS2__ == Borland OS2 compiler ++ _Windows == Windows 16 bit app ++ ++ GCC Compiler ++ __GNUC__ == GCC Compiler ++ __unix__ == Unix system ++ __vax__ == Unix system ++ unix == Unix system ++ vax == vax system ++ ++ TORNADO ++ _VXWORKS_ == VXWORK ++ ++ ECOS/CYGWIN ++ _ECOS_ == eCos ++ ++ SOLARIS ++ _SOLARIS_ == Solaris ++ ++*****************************************************************************/ ++ ++/* Machine endian type */ ++ ++#define OCT_MACH_LITTLE_ENDIAN 1 ++#define OCT_MACH_BIG_ENDIAN 2 ++ ++/* Try to find current OCT_MACH_ENDIAN from compiler define values */ ++#if !defined( MACH_TYPE_BIG_ENDIAN ) && !defined( MACH_TYPE_LITTLE_ENDIAN ) ++ /* Does GNU defines the endian ? */ ++ #if defined(__GNU_C__) ++ #if defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__) ++ #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN ++ #elif defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) ++ #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN ++ #endif ++ #endif ++ ++ /* Try with cpu type */ ++ #if !defined(OCT_MACH_ENDIAN) ++ /* Look for intel */ ++ #if defined( _M_IX86 ) ++ #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN ++ /* Look for PowerPC */ ++ #elif defined( _M_MPPC ) || defined( _M_PPC ) || defined(PPC) || defined(__PPC) || defined(_ARCH_PPC) ++ #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN ++ /* Look for Blackfin */ ++ #elif defined( __bfin__ ) ++ #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN ++ #elif defined( CPU ) ++ #if CPU==PPC860 || CPU==SIMNT ++ #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN ++ #else ++ #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN ++ #endif ++ #else ++ #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN ++ #endif ++ #endif ++#else ++ #if defined( MACH_TYPE_BIG_ENDIAN ) ++ #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN ++ #else ++ #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN ++ #endif ++#endif ++ ++/* Find system type if not already defined */ ++#if !defined( OCT_NTDRVENV ) && !defined( OCT_VXENV ) && !defined( OCT_WINENV ) ++ ++#if defined( WIN32 ) || defined( __WIN32__ ) || defined( _WIN32_ ) || defined( WIN32S ) ++ /* Verif if building a win32 driver */ ++ #if ( defined( WIN32 ) && WIN32==100 ) ++ #define OCT_NTDRVENV ++ #else ++ #define OCT_WINENV ++ #endif ++#elif defined( _VXWORKS_ ) ++ #define OCT_VXENV ++#elif defined( _ECOS_ ) ++#ifndef OCT_ECOSENV ++ #define OCT_ECOSENV ++#endif /* OCT_ECOSENV */ ++#elif defined( _SOLARIS_ ) ++ #define OCT_SOLARISENV ++#elif defined( _LINUX_ ) ++ #define OCT_LINUXENV ++#else ++ /* Unknown environment */ ++ #define OCT_UNKNOWNENV ++#endif /* WIN env */ ++ ++#endif /* Already defined */ ++ ++#if defined( __KERNEL__ ) && defined( OCT_LINUXENV ) ++#define OCT_LINUXDRVENV ++#endif ++ ++#ifdef _DEBUG ++#define OCT_OPT_USER_DEBUG ++#endif ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __OCTOSDEPENDANT_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octrpc/oct6100_rpc_protocol.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octrpc/oct6100_rpc_protocol.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octrpc/oct6100_rpc_protocol.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octrpc/oct6100_rpc_protocol.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,348 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_rpc_protocol.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all defines and prototypes related to the OCT6100 RPC ++ protocol for exchanging debug commands. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 6 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_RPC_PROTOCOL_H__ ++#define __OCT6100_RPC_PROTOCOL_H__ ++ ++/***************************** DEFINES *************************************/ ++ ++#define cOCTRPC_INTERFACE_VERSION 0x00010002 ++ ++/* Octasic commands. */ ++#define cOCT6100_RPC_CHIP_LIST 0xFF000000 ++#define cOCT6100_RPC_CHIP_CHOICE 0xFF000001 ++#define cOCT6100_RPC_ENV_DISCONNECT 0xFF000002 ++ ++/* Commands */ ++/* Read commands */ ++#define cOCT6100_RPC_READ_WORD 0x00000000 ++#define cOCT6100_RPC_READ_BURST 0x00000001 ++#define cOCT6100_RPC_READ_DEBUG 0x00000002 ++#define cOCT6100_RPC_READ_ARRAY 0x00000003 ++#define cOCT6100_RPC_API_DISCONNECT 0x00000004 ++ ++/* Write commands */ ++#define cOCT6100_RPC_WRITE_WORD 0x00000010 ++#define cOCT6100_RPC_WRITE_BURST 0x00000011 ++#define cOCT6100_RPC_WRITE_SMEAR 0x00000012 ++#define cOCT6100_RPC_WRITE_INC 0x00000013 ++ ++/* Debug commands.*/ ++#define cOCT6100_RPC_SET_HOT_CHANNEL 0x00000014 ++#define cOCT6100_RPC_GET_DEBUG_CHAN_INDEX 0x00000015 ++ ++#define cOCTRPC_UNKNOWN_COMMAND_NUM 0xFFFFFFFF ++ ++/* Errors */ ++#define cOCT6100_RPCERR_OK 0x00000000 ++#define cOCT6100_RPCERR_INVALID_COMMAND_NUMBER 0x00000001 ++#define cOCT6100_RPCERR_INVALID_COMMAND_PAYLOAD 0x00000002 ++#define cOCT6100_RPCERR_INVALID_COMMAND_LENGTH 0x00000003 ++ ++ ++/***************************** TYPES ***************************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_READ_WORD ++ ++Description: Command structure for the read of one word. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulAddress Address at which to read. ++OUT ulReadData The word read, returned. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_READ_WORD_ ++{ ++ UINT32 IN ulAddress; ++ UINT32 OUT ulReadData; ++ ++} tOCT6100_RPC_READ_WORD, *tPOCT6100_RPC_READ_WORD; ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_READ_BURST ++ ++Description: Command structure for a read burst. The burst starts at the ++ given address and reads the specified number of consecutive ++ words. ++ ++ Whereas every command structure uses a complete dword for every ++ member, irrespective of the size of data unit needed, this ++ structure does not do so for the read data. To save bandwidth ++ the read data words are returned two per dword. ++ ++Example packet: 31 16 15 0 ++ ------------------------------------------- ++ | ulAddress = 0x100 | ++ ------------------------------------------- ++ | ulBurstLength = 0x3 | ++ ------------------------------------------- ++ aulReadData -> | D0 | D1 | ++ ------------------------------------------- ++ | D2 | xx | ++ ------------------------------------------- ++ ++ Dy is the read data at ulAddress + 2 * y. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulAddress Address at which to read. ++IN ulBurstLength The number of consecutive words to be read. ++OUT aulReadData The read data returned. The dwords of the structure ++ starting at this address are arranged as indicated in ++ the example packet above. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_READ_BURST_ ++{ ++ UINT32 IN ulAddress; ++ UINT32 IN ulBurstLength; ++ UINT32 OUT aulReadData[ 1 ]; ++ ++} tOCT6100_RPC_READ_BURST, *tPOCT6100_RPC_READ_BURST; ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_READ_ARRAY ++ ++Description: Command structure for a variable number of reads. The reads do ++ not have to be at contiguous addresses. ++ ++ Whereas every command structure uses a complete dword for every ++ member, irrespective of the size of data unit needed, this ++ structure does not do so for the read data. To save bandwidth ++ the read data words are returned two per dword, and the ++ parity bits are returned 16 per dword (two parity bits per read ++ access). ++ ++Example packet: 31 16 15 0 ++ ------------------------------------------- ++ | ulArrayLength = 0x3 | ++ ------------------------------------------- ++ aulArrayData ->| A0 | ++ ------------------------------------------- ++ | A1 | ++ ------------------------------------------- ++ | A2 | ++ ------------------------------------------- ++ | D0 | D1 | ++ ------------------------------------------- ++ | D2 | xx | ++ ------------------------------------------- ++ ++ Ay is the address for access y. ++ Dy is the read data at Ay. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulArrayLength Number of reads to do. ++IN OUT aulArrayData The addresses at which to read (IN) and the read data ++ returned (OUT). The dwords of the command structure ++ starting at this address are arranged as indicated in ++ the example packet above. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_READ_ARRAY ++{ ++ UINT32 IN ulArrayLength; ++ UINT32 IN OUT aulArrayData[ 1 ]; ++ ++} tOCT6100_RPC_READ_ARRAY, *tPOCT6100_RPC_READ_ARRAY; ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_WRITE_WORD ++ ++Description: Command structure for the write of one word. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulAddress Address at which to write. ++IN ulWriteData The word to write. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_WRITE_WORD_ ++{ ++ UINT32 IN ulAddress; ++ UINT32 IN ulParity; ++ UINT32 IN ulWriteData; ++ ++} tOCT6100_RPC_WRITE_WORD, *tPOCT6100_RPC_WRITE_WORD; ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_WRITE_SMEAR ++ ++Description: Command structure for the write of one word at one or many ++ consecutive addresses. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulAddress Address of first write. ++IN ulSmearLength Number of consecutive addresses to write. ++IN ulWriteData The word to write at each address. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_WRITE_SMEAR_ ++{ ++ UINT32 IN ulAddress; ++ UINT32 IN ulSmearLength; ++ UINT32 IN ulParity; ++ UINT32 IN ulWriteData; ++ ++} tOCT6100_RPC_WRITE_SMEAR, *tPOCT6100_RPC_WRITE_SMEAR; ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_WRITE_INC ++ ++Description: Command structure for the write of an incremental pattern at ++ one or many consecutive addresses. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulAddress Address of first write. ++IN ulIncLength Number of consecutive addresses to write. ++IN ulWriteData The first word of the incremental pattern. For each ++ consecutive write the word will be incremented by 1. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_WRITE_INC_ ++{ ++ UINT32 IN ulAddress; ++ UINT32 IN ulIncLength; ++ UINT32 IN ulParity; ++ UINT32 IN ulWriteData; ++ ++} tOCT6100_RPC_WRITE_INC, *tPOCT6100_RPC_WRITE_INC; ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_WRITE_BURST ++ ++Description: Command structure for a write burst. The burst starts at the ++ given address and writes a given word for each address. ++ ++ Whereas every command structure uses a complete dword for every ++ member, irrespective of the size of data unit needed, this ++ structure does not do so for the write data. To save bandwidth ++ the write data words are sent two per dword. ++ ++Example packet: 31 16 15 0 ++ ------------------------------------------- ++ | ulAddress = 0x100 | ++ ------------------------------------------- ++ | ulBurstLength = 0x3 | ++ ------------------------------------------- ++ aulWriteData ->| D0 | D1 | ++ ------------------------------------------- ++ | D2 | xx | ++ ------------------------------------------- ++ ++ Dy is the write data for ulAddress + 2 * y. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulAddress First address at which to write. ++IN ulBurstLength The number of consecutive addresses to be write. ++IN aulWriteData The write data words. The dwords of the structure ++ starting at this address are arranged as indicated in ++ the example packet above. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_WRITE_BURST_ ++{ ++ UINT32 IN ulAddress; ++ UINT32 IN ulBurstLength; ++ UINT32 IN ulParity; ++ UINT32 IN aulWriteData[ 1 ]; ++ ++} tOCT6100_RPC_WRITE_BURST, *tPOCT6100_RPC_WRITE_BURST; ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_SET_HOT_CHANNEL ++ ++Description: Command structure to set the hot channel. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulDebugChannel Index of the channel to debug. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_SET_HOT_CHANNEL_ ++{ ++ UINT32 IN ulHotChannel; ++ UINT32 IN ulPcmLaw; ++ ++} tOCT6100_RPC_SET_HOT_CHANNEL, *tPOCT6100_RPC_SET_HOT_CHANNEL; ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Structure: OCT6100_RPC_GET_DEBUG_CHAN_INDEX ++ ++Description: Command structure to get the debug channel index used by the API. ++ ++------------------------------------------------------------------------------- ++| Member | Description ++------------------------------------------------------------------------------- ++IN ulDebugChannel Index of the channel to debug. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++typedef struct _OCT6100_RPC_GET_DEBUG_CHAN_INDEX_ ++{ ++ UINT32 OUT ulDebugChanIndex; ++ ++} tOCT6100_RPC_GET_DEBUG_CHAN_INDEX, *tPOCT6100_RPC_GET_DEBUG_CHAN_INDEX; ++ ++#endif /* __OCT6100_RPC_PROTOCOL_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octrpc/rpc_protocol.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octrpc/rpc_protocol.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octrpc/rpc_protocol.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octrpc/rpc_protocol.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,115 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: rpc_protocol.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++This file contains RPC related definitions and prototypes. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 23 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __RPC_PROTOCOL_H__ ++#define __RPC_PROTOCOL_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++#define cOCTRPC_ENDIAN_DETECT 0x27182819 ++#define cOCTRPC_ENDIAN_DETECT_BYTE_W 0x19 ++#define cOCTRPC_ENDIAN_DETECT_BYTE_X 0x28 ++#define cOCTRPC_ENDIAN_DETECT_BYTE_Y 0x18 ++#define cOCTRPC_ENDIAN_DETECT_BYTE_Z 0x27 ++#define cOCTRPC_ECHO_PROTOCOL 0x00000000 ++ ++#define cOCTRPC_MIN_PACKET_BYTE_LENGTH (sizeof( tOCTRPC_OGRDTP_HEADER )) ++#define cOCTRPC_FIRST_COMMAND_BYTE_OFFSET (sizeof( tOCTRPC_OGRDTP_HEADER ) + sizeof( tOCTRPC_INTERFACE_HEADER )) ++#define cOCTRPC_GENERIC_HEADERS_BYTE_SIZE (sizeof( tOCTRPC_OGRDTP_HEADER ) + sizeof( tOCTRPC_INTERFACE_HEADER ) + sizeof( tOCTRPC_COMMAND_HEADER )) ++#define cOCTRPC_MAX_PACKET_BYTE_LENGTH 32768 ++ ++/* Protocol versions */ ++#define cOCTRPC_PROTOCOL_V1_0 0x00010000 ++#define cOCTRPC_PROTOCOL_V1_1 0x00010001 ++#define cOCTRPC_PROTOCOL_V1_2 0x00010002 ++#define cOCTRPC_PROTOCOL_V1_3 0x00010003 ++#define cOCTRPC_OCTASIC_PROTOCOL_V1_0 0xFF010000 ++#define cOCTRPC_OCTASIC_PROTOCOL_V1_1 0xFF010001 ++#define cOCTRPC_OCTASIC_PROTOCOL_V1_2 0xFF010002 ++#define cOCTRPC_OCTASIC_PROTOCOL_V1_3 0xFF010003 ++ ++/* Chips */ ++#define cOCTRPC_OCT8304_INTERFACE 0x00000000 ++#define cOCTRPC_OCT6100_INTERFACE 0x00000001 ++ ++/* Timeout values. */ ++#define cOCTRPC_SESSION_TIMEOUT 30 ++ ++/* Generic errors */ ++#define cOCTRPC_RDBGERR_OK 0x00000000 ++#define cOCTRPC_RDBGERR_NO_ANSWER 0xFFFF0000 ++#define cOCTRPC_RDBGERR_ALL_SESSIONS_OPEN 0xFFFF0001 ++#define cOCTRPC_RDBGERR_PROTOCOL_NUMBER 0xFFFF0002 ++#define cOCTRPC_RDBGERR_NO_COMMAND_HEADER 0xFFFF0003 ++#define cOCTRPC_RDBGERR_INTERFACE_TYPE 0xFFFF0004 ++#define cOCTRPC_RDBGERR_INTERFACE_VERSION 0xFFFF0005 ++#define cOCTRPC_RDBGERR_INVALID_PACKET_LENGTH 0xFFFF0006 ++#define cOCTRPC_RDBGERR_INVALID_COMMAND_LENGTH 0xFFFF0007 ++#define cOCTRPC_RDBGERR_INVALID_COMMAND_NUMBER 0xFFFF0008 ++#define cOCTRPC_RDBGERR_PACKET_TOO_LARGE 0xFFFF0009 ++#define cOCTRPC_RDBGERR_LIST_EMPTY 0xFFFF000A ++ ++#define cOCTRPC_RDBGERR_FATAL 0xFFFFFFFF ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCTRPC_OGRDTP_HEADER_ ++{ ++ UINT32 IN ulEndianDetect; ++ UINT32 IN ulDebugSessionNum; ++ UINT32 IN ulTransactionNum; ++ UINT32 IN ulPktRetryNum; ++ UINT32 IN ulPktByteSize; ++ UINT32 IN ulChecksum; ++ UINT32 OUT ulParsingError; ++ UINT32 IN ulRpcProtocolNum; ++ ++} tOCTRPC_OGRDTP_HEADER, *tPOCTRPC_OGRDTP_HEADER; ++ ++typedef struct _OCTRPC_INTERFACE_HEADER_ ++{ ++ UINT32 IN ulInterfaceType; ++ UINT32 IN ulInterfaceVersion; ++ ++} tOCTRPC_INTERFACE_HEADER, *tPOCTRPC_INTERFACE_HEADER; ++ ++typedef struct _OCTRPC_COMMAND_HEADER_ ++{ ++ UINT32 IN ulCommandByteSize; ++ UINT32 IN OUT ulRpcCommandNum; ++ UINT32 OUT ulFunctionResult; ++ ++} tOCTRPC_COMMAND_HEADER, *tPOCTRPC_COMMAND_HEADER; ++ ++#endif /* __RPC_PROTOCOL_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octtype.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octtype.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octtype.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octtype.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,159 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octtype.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file defines the base storage types. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 18 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#ifndef __OCTTYPE_H__ ++#define __OCTTYPE_H__ ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*-------------------------------------------------------------------------- ++ Include target-specific header if available ++----------------------------------------------------------------------------*/ ++#if defined( OCT_NTDRVENV ) ++ #include "octtypentdrv.h" /* All NT driver typedef */ ++#elif defined( OCT_WINENV ) ++ #include "octtypewin.h" /* All Win32 typedef */ ++#elif defined( OCT_VXENV ) ++ #include "octtypevx.h" /* All VxWorks typedef */ ++#else ++/*-------------------------------------------------------------------------- ++ No target-specific header available ++----------------------------------------------------------------------------*/ ++ ++#ifdef SZ ++#undef SZ ++#endif ++ ++/***************************** DEFINES *************************************/ ++/* 16-bit integer */ ++typedef unsigned short UINT16; ++typedef signed short INT16; ++typedef unsigned short *PUINT16; ++typedef signed short *PINT16; ++ ++/* 8-bit integer */ ++typedef unsigned char UINT8; ++typedef signed char INT8; ++typedef signed char OCT_INT8; ++typedef unsigned char *PUINT8; ++typedef signed char *PINT8; ++ ++ ++/* 32 bit integer */ ++typedef unsigned int UINT32; ++typedef signed int INT32; ++typedef INT32 * PINT32; ++typedef UINT32 * PUINT32; ++ ++/* Long integer */ ++typedef signed long LONG; ++typedef unsigned long ULONG; ++typedef long * PLONG; ++typedef unsigned long * PULONG; ++ ++/* Short integer */ ++typedef short SHORT; ++typedef unsigned short USHORT; ++typedef short * PSHORT; ++typedef unsigned short *PUSHORT; ++ ++/* 8-bit integer*/ ++typedef unsigned char BYTE; ++typedef BYTE * PBYTE; ++typedef unsigned char UCHAR; ++ ++/* Character and strings */ ++typedef char CHAR; ++typedef CHAR SZ; ++typedef CHAR * PSZ; ++typedef CHAR * PCHAR; ++ ++/* Double integers */ ++typedef double DOUBLE; ++typedef double * PDOUBLE; ++typedef float FLOAT; ++typedef float * PFLOAT; ++ ++typedef void VOID; ++typedef void * PVOID; ++ ++/* Booleans */ ++typedef int BOOL; ++typedef BOOL * PBOOL; ++ ++/* Integers */ ++typedef int INT; ++typedef int * PINT; ++typedef unsigned int UINT; ++typedef unsigned int * PUINT; ++ ++/* Define pseudo-keywords IN and OUT if not defined yet */ ++#ifndef IN ++#define IN /* IN param */ ++#endif ++ ++#ifndef OUT ++#define OUT /* OUT param */ ++#endif ++ ++/* LONG LONG */ ++#define LLONG signed long long ++#define PLLONG signed long long * ++#define ULLONG unsigned long long ++#define PULLONG unsigned long long * ++ ++#ifndef OPT ++#define OPT /* OPT param */ ++#endif ++ ++typedef PSZ * PPSZ; ++ ++#if defined(__FreeBSD__) ++#include ++#else ++#include ++#endif ++ ++#endif ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __OCTTYPE_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octtypevx.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octtypevx.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octtypevx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octtypevx.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,132 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octtypevx.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file defines the base storage types for the VxWorks environment. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 9 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCTTYPEVX_H__ ++#define __OCTTYPEVX_H__ ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "vxWorks.h" ++ ++/* 16-bit pointer integer */ ++typedef unsigned short *PUINT16; ++typedef signed short *PINT16; ++ ++/* 8-bit integer pointer */ ++typedef unsigned char *PUINT8; ++typedef signed char *PINT8; ++ ++/* 32-bit integer pointer */ ++typedef INT32 * PINT32; ++typedef UINT32 * PUINT32; ++ ++/* Long integer pointer */ ++/*Intel library for file system definition*/ ++#ifndef DATATYPE_H ++typedef long LONG; ++#endif ++typedef long * PLONG; ++typedef unsigned long * PULONG; ++ ++/* Short integer pointer */ ++typedef short SHORT; ++typedef short * PSHORT; ++typedef unsigned short *PUSHORT; ++ ++/* 8-bit integer*/ ++#if (CPU!=SIMNT) && !defined(DATATYPE_H) ++typedef char BYTE; ++#endif ++ ++ ++typedef BYTE * PBYTE; ++ ++/* Character and strings */ ++/*Intel library for file system definition*/ ++#ifndef DATATYPE_H ++typedef char CHAR; ++#endif ++typedef char * PCHAR; ++typedef CHAR SZ; ++typedef CHAR * PSZ; ++typedef signed char OCT_INT8; ++ ++/* Double integers */ ++typedef double DOUBLE; ++typedef double * PDOUBLE; ++typedef float FLOAT; ++typedef float * PFLOAT; ++ ++typedef void * PVOID; ++ ++/* Booleans */ ++typedef BOOL * PBOOL; ++ ++/* Integers */ ++typedef int INT; ++typedef int * PINT; ++typedef unsigned int PUINT; ++ ++/* Define pseudo-keywords IN and OUT if not defined yet */ ++#ifndef IN ++#define IN /* IN param */ ++#endif ++ ++#ifndef OUT ++#define OUT /* OUT param */ ++#endif ++ ++/* LONG LONG */ ++#define LLONG signed long long ++#define PLLONG signed long long * ++#define ULLONG unsigned long long ++#define PULLONG unsigned long long * ++ ++#ifndef OPT ++#define OPT /* OPT param */ ++#endif ++ ++typedef PSZ * PPSZ; ++ ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __OCTTYPEVX_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/include/octtypewin.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octtypewin.h +--- linux-source-4.19/drivers/dahdi/oct612x/include/octtypewin.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/include/octtypewin.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,100 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: octtypewin.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file defines the base storage types for the Windows environment. ++ Includes the Windows definition file and add the missing ones here. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 16 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCTTYPEWIN_H__ ++#define __OCTTYPEWIN_H__ ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++#define WIN32_LEAN_AND_MEAN /* just get the base type definition from Windows */ ++#include ++ ++/* Disable argument not used warning */ ++#pragma warning( disable : 4100 ) ++/* Disable Level 4 warning: nonstandard extension used : translation unit is empty */ ++#pragma warning( disable : 4206 ) ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* 16-bit integer */ ++typedef unsigned short UINT16; ++typedef signed short INT16; ++typedef unsigned short *PUINT16; ++typedef signed short *PINT16; ++ ++/* 8-bit integer */ ++typedef unsigned char UINT8; ++typedef signed char INT8; ++typedef signed char OCT_INT8; ++typedef unsigned char *PUINT8; ++typedef signed char *PINT8; ++ ++typedef double DOUBLE; ++ ++ ++/* 32 bit integer */ ++#if ( defined( _MSC_VER ) && _MSC_VER == 1100 ) ++/* MFC5 compiler does not define UINT32 */ ++typedef unsigned int UINT32; ++typedef signed int INT32; ++typedef INT32 * PINT32; ++typedef UINT32 * PUINT32; ++#endif /* _MSC_VER */ ++ ++/* LONG LONG */ ++#define LLONG signed __int64 ++#define PLLONG signed __int64 * ++#define ULLONG unsigned __int64 ++#define PULLONG unsigned __int64 * ++ ++/* Double integers */ ++typedef double DOUBLE; ++typedef double * PDOUBLE; ++typedef float FLOAT; ++typedef float * PFLOAT; ++ ++#ifndef OPT ++#define OPT /* OPT param */ ++#endif ++ ++typedef PSZ * PPSZ; ++ ++/*-------------------------------------------------------------------------- ++ C language ++----------------------------------------------------------------------------*/ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __OCTTYPEWIN_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/oct612x-user.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/oct612x-user.c +--- linux-source-4.19/drivers/dahdi/oct612x/oct612x-user.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/oct612x-user.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,207 @@ ++/* ++ * Octasic OCT6100 Interface ++ * ++ * Copyright (C) 2013 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 ++ ++#include ++ ++#include "oct612x.h" ++ ++UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime) ++{ ++ /* Why couldn't they just take a timeval like everyone else? */ ++ u64 total_usecs; ++ ++ total_usecs = ktime_to_us(ktime_get_real()); ++ f_pTime->aulWallTimeUs[0] = total_usecs; ++ f_pTime->aulWallTimeUs[1] = total_usecs >> 32; ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, ++ UINT32 f_ulLength) ++{ ++ memset(f_pAddress, f_ulPattern, f_ulLength); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, ++ UINT32 f_ulLength) ++{ ++ memcpy(f_pDestination, f_pSource, f_ulLength); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserCreateSerializeObject( ++ tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate) ++{ ++ struct oct612x_context *context = f_pCreate->pProcessContext; ++ struct mutex *lock = kzalloc(sizeof(*lock), GFP_KERNEL); ++ if (!lock) { ++ dev_err(context->dev, "Out of memory in %s.\n", __func__); ++ return cOCT6100_ERR_BASE; ++ } ++ mutex_init(lock); ++ f_pCreate->ulSerialObjHndl = lock; ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserDestroySerializeObject( ++ tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy) ++{ ++ struct mutex *lock = f_pDestroy->ulSerialObjHndl; ++ kfree(lock); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserSeizeSerializeObject( ++ tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize) ++{ ++ struct mutex *lock = f_pSeize->ulSerialObjHndl; ++ mutex_lock(lock); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserReleaseSerializeObject( ++ tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease) ++{ ++ struct mutex *lock = f_pRelease->ulSerialObjHndl; ++ mutex_unlock(lock); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams) ++{ ++ struct oct612x_context *context = f_pWriteParams->pProcessContext; ++#ifdef OCTASIC_DEBUG ++ if (!context || !context->ops || !context->ops->write) { ++ pr_debug("Invalid call to %s\n", __func__); ++ return cOCT6100_ERR_BASE; ++ } ++#endif ++ context->ops->write(context, f_pWriteParams->ulWriteAddress, ++ f_pWriteParams->usWriteData); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams) ++{ ++ struct oct612x_context *context = f_pSmearParams->pProcessContext; ++#ifdef OCTASIC_DEBUG ++ if (!context || !context->ops || !context->ops->write_smear) { ++ pr_debug("Invalid call to %s\n", __func__); ++ return cOCT6100_ERR_BASE; ++ } ++#endif ++ context->ops->write_smear(context, f_pSmearParams->ulWriteAddress, ++ f_pSmearParams->usWriteData, ++ f_pSmearParams->ulWriteLength); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserDriverWriteBurstApi( ++ tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams) ++{ ++ struct oct612x_context *context = f_pBurstParams->pProcessContext; ++#ifdef OCTASIC_DEBUG ++ if (!context || !context->ops || !context->ops->write_burst) { ++ pr_debug("Invalid call to %s\n", __func__); ++ return cOCT6100_ERR_BASE; ++ } ++#endif ++ context->ops->write_burst(context, f_pBurstParams->ulWriteAddress, ++ f_pBurstParams->pusWriteData, ++ f_pBurstParams->ulWriteLength); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams) ++{ ++ struct oct612x_context *context = f_pReadParams->pProcessContext; ++#ifdef OCTASIC_DEBUG ++ if (!context || !context->ops || !context->ops->read) { ++ pr_debug("Invalid call to %s\n", __func__); ++ return cOCT6100_ERR_BASE; ++ } ++#endif ++ context->ops->read(context, f_pReadParams->ulReadAddress, ++ f_pReadParams->pusReadData); ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams) ++{ ++ struct oct612x_context *context = f_pBurstParams->pProcessContext; ++#ifdef OCTASIC_DEBUG ++ if (!context || !context->ops || !context->ops->read_burst) { ++ pr_debug("Invalid call to %s\n", __func__); ++ return cOCT6100_ERR_BASE; ++ } ++#endif ++ context->ops->read_burst(context, f_pBurstParams->ulReadAddress, ++ f_pBurstParams->pusReadData, ++ f_pBurstParams->ulReadLength); ++ return cOCT6100_ERR_OK; ++} ++ ++EXPORT_SYMBOL(Oct6100ChipOpen); ++EXPORT_SYMBOL(Oct6100ChipClose); ++EXPORT_SYMBOL(Oct6100ChipCloseDef); ++EXPORT_SYMBOL(Oct6100GetInstanceSize); ++EXPORT_SYMBOL(Oct6100GetInstanceSizeDef); ++EXPORT_SYMBOL(Oct6100ChipOpenDef); ++EXPORT_SYMBOL(Oct6100ChannelModify); ++EXPORT_SYMBOL(Oct6100ToneDetectionEnableDef); ++EXPORT_SYMBOL(Oct6100InterruptServiceRoutine); ++EXPORT_SYMBOL(Oct6100InterruptServiceRoutineDef); ++EXPORT_SYMBOL(Oct6100ApiGetCapacityPins); ++EXPORT_SYMBOL(Oct6100ToneDetectionEnable); ++EXPORT_SYMBOL(Oct6100EventGetToneDef); ++EXPORT_SYMBOL(Oct6100EventGetTone); ++EXPORT_SYMBOL(Oct6100ApiGetCapacityPinsDef); ++EXPORT_SYMBOL(Oct6100ChannelOpen); ++EXPORT_SYMBOL(Oct6100ChannelOpenDef); ++EXPORT_SYMBOL(Oct6100ChannelModifyDef); ++ ++static int __init oct612x_module_init(void) ++{ ++ /* 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_device(NULL, NULL); ++ return 0; ++} ++module_init(oct612x_module_init); ++ ++static void __exit oct612x_module_cleanup(void) ++{ ++ /* Nothing to do */; ++} ++module_exit(oct612x_module_cleanup); ++ ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_DESCRIPTION("Octasic OCT6100 Hardware Echocan Library"); ++MODULE_LICENSE("GPL v2"); +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/oct612x.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/oct612x.h +--- linux-source-4.19/drivers/dahdi/oct612x/oct612x.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/oct612x.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,49 @@ ++/* ++ * Octasic OCT6100 Interface ++ * ++ * Copyright (C) 2013 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 __OCT612X_H__ ++#define __OCT612X_H__ ++ ++#include ++ ++struct oct612x_context; ++ ++/** ++ * struct oct612x_ops - Callbacks used by oct612x library to talk to part. ++ * ++ */ ++struct oct612x_ops { ++ int (*write)(struct oct612x_context *context, u32 address, u16 value); ++ int (*read)(struct oct612x_context *context, u32 address, u16 *value); ++ int (*write_smear)(struct oct612x_context *context, u32 address, ++ u16 value, size_t count); ++ int (*write_burst)(struct oct612x_context *context, u32 address, ++ const u16 *value, size_t count); ++ int (*read_burst)(struct oct612x_context *context, u32 address, ++ u16 *value, size_t count); ++}; ++ ++struct oct612x_context { ++ const struct oct612x_ops *ops; ++ struct device *dev; ++}; ++ ++#endif /* __OCT612X_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octasic-helper linux-source-4.19-dahdi/drivers/dahdi/oct612x/octasic-helper +--- linux-source-4.19/drivers/dahdi/oct612x/octasic-helper 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octasic-helper 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,39 @@ ++#!/bin/sh ++ ++# ++# Jeffrey C. Ollie ++# ++# $1 == information requested ++# $2 == path to octasic directory ++# ++ ++APIDIR=$2/octdeviceapi/oct6100api/oct6100_api ++ ++case $1 in ++ objects) ++ echo $APIDIR/oct6100_adpcm_chan.o \ ++ $APIDIR/oct6100_channel.o \ ++ $APIDIR/oct6100_chip_open.o \ ++ $APIDIR/oct6100_chip_stats.o \ ++ $APIDIR/oct6100_conf_bridge.o \ ++ $APIDIR/oct6100_debug.o \ ++ $APIDIR/oct6100_events.o \ ++ $APIDIR/oct6100_interrupts.o \ ++ $APIDIR/oct6100_memory.o \ ++ $APIDIR/oct6100_miscellaneous.o \ ++ $APIDIR/oct6100_mixer.o \ ++ $APIDIR/oct6100_phasing_tsst.o \ ++ $APIDIR/oct6100_playout_buf.o \ ++ $APIDIR/oct6100_remote_debug.o \ ++ $APIDIR/oct6100_tlv.o \ ++ $APIDIR/oct6100_tone_detection.o \ ++ $APIDIR/oct6100_tsi_cnct.o \ ++ $APIDIR/oct6100_tsst.o \ ++ $2/apilib/bt/octapi_bt0.o \ ++ $2/apilib/largmath/octapi_largmath.o \ ++ $2/apilib/llman/octapi_llman.o ++ ;; ++ cflags) ++ echo -I$2/include -I$2/octdeviceapi -I$2/octdeviceapi/oct6100api ++ ;; ++esac +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_adpcm_chan_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_adpcm_chan_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_adpcm_chan_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_adpcm_chan_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,131 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_adpcm_chan_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_adpcm_chan.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_adpcm_chan_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 7 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_ADPCM_CHAN_PRIV_H__ ++#define __OCT6100_ADPCM_CHAN_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/* ADPCM channel list pointer macros. */ ++#define mOCT6100_GET_ADPCM_CHAN_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_ADPCM_CHAN )(( PUINT8 )pSharedInfo + pSharedInfo->ulAdpcmChanListOfst ); ++ ++#define mOCT6100_GET_ADPCM_CHAN_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_ADPCM_CHAN )(( PUINT8 )pSharedInfo + pSharedInfo->ulAdpcmChanListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_ADPCM_CHAN_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulAdpcmChanAllocOfst); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetAdpcmChanSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiAdpcmChanSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++ ++UINT32 Oct6100AdpcmChanOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ); ++ ++UINT32 Oct6100ApiCheckAdpcmChanParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ); ++ ++UINT32 Oct6100ApiReserveAdpcmChanResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen, ++ OUT PUINT16 f_pusTsiChanIndex, ++ OUT PUINT16 f_pusAdpcmMemIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ); ++ ++UINT32 Oct6100ApiWriteAdpcmChanStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen, ++ IN UINT16 f_usAdpcmMemIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ); ++ ++UINT32 Oct6100ApiUpdateAdpcmChanEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen, ++ IN UINT16 f_usTsiChanIndex, ++ IN UINT16 f_usAdpcmMemIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ); ++ ++UINT32 Oct6100AdpcmChanCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose ); ++ ++UINT32 Oct6100ApiAssertAdpcmChanParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose, ++ OUT PUINT16 f_pusTsiChanIndex, ++ OUT PUINT16 f_pusAdpcmMemIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ); ++ ++UINT32 Oct6100ApiInvalidateAdpcmChanStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usAdpcmChanIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ); ++ ++UINT32 Oct6100ApiReleaseAdpcmChanResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsiChanIndex, ++ IN UINT16 f_usAdpcmMemIndex, ++ IN UINT16 f_usTsiMemIndex ); ++ ++UINT32 Oct6100ApiReserveAdpcmChanEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusAdpcmChanIndex ); ++ ++UINT32 Oct6100ApiReleaseAdpcmChanEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usAdpcmChanIndex ); ++ ++#endif /* __OCT6100_ADPCM_CHAN_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1237 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_adpcm_chan.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to open and close ADPCM channels. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 16 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_adpcm_chan_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_adpcm_chan_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_tsst_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_adpcm_chan_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100AdpcmChanOpen ++ ++Description: This function opens an ADPCM channel between two TDM timeslots. ++ This channel will perform ADPCM compression or decompression ++ depending on the channel mode. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pAdpcmChanOpen Pointer to ADPCM channel open structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100AdpcmChanOpenDef ++UINT32 Oct6100AdpcmChanOpenDef( ++ tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ) ++{ ++ f_pAdpcmChanOpen->pulChanHndl = NULL; ++ ++ f_pAdpcmChanOpen->ulInputTimeslot = cOCT6100_INVALID_TIMESLOT; ++ f_pAdpcmChanOpen->ulInputStream = cOCT6100_INVALID_STREAM; ++ f_pAdpcmChanOpen->ulInputNumTssts = 1; ++ f_pAdpcmChanOpen->ulInputPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ f_pAdpcmChanOpen->ulOutputTimeslot = cOCT6100_INVALID_TIMESLOT; ++ f_pAdpcmChanOpen->ulOutputStream = cOCT6100_INVALID_STREAM; ++ f_pAdpcmChanOpen->ulOutputPcmLaw = cOCT6100_PCM_U_LAW; ++ f_pAdpcmChanOpen->ulOutputNumTssts = 1; ++ ++ f_pAdpcmChanOpen->ulChanMode = cOCT6100_ADPCM_ENCODING; ++ f_pAdpcmChanOpen->ulEncodingRate = cOCT6100_G726_32KBPS; ++ f_pAdpcmChanOpen->ulDecodingRate = cOCT6100_G726_32KBPS; ++ ++ f_pAdpcmChanOpen->ulAdpcmNibblePosition = cOCT6100_ADPCM_IN_LOW_BITS; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100AdpcmChanOpen ++UINT32 Oct6100AdpcmChanOpen( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100AdpcmChanOpenSer( f_pApiInstance, f_pAdpcmChanOpen ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100AdpcmChanClose ++ ++Description: This function closes an opened ADPCM channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pAdpcmChanClose Pointer to ADPCM channel close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100AdpcmChanCloseDef ++UINT32 Oct6100AdpcmChanCloseDef( ++ tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose ) ++{ ++ f_pAdpcmChanClose->ulChanHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100AdpcmChanClose ++UINT32 Oct6100AdpcmChanClose( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100AdpcmChanCloseSer( f_pApiInstance, f_pAdpcmChanClose ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetAdpcmChanSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of the ADPCM memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetAdpcmChanSwSizes ++UINT32 Oct6100ApiGetAdpcmChanSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Determine the amount of memory required for the API ADPCM channel list.*/ ++ f_pInstSizes->ulAdpcmChannelList = f_pOpenChip->ulMaxAdpcmChannels * sizeof( tOCT6100_API_ADPCM_CHAN ); ++ ++ if ( f_pOpenChip->ulMaxAdpcmChannels > 0 ) ++ { ++ /* Calculate memory needed for ADPCM memory allocation */ ++ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxAdpcmChannels, &f_pInstSizes->ulAdpcmChannelAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_48; ++ } ++ else ++ { ++ f_pInstSizes->ulAdpcmChannelAlloc = 0; ++ } ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulAdpcmChannelList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulAdpcmChannelAlloc, ulTempVar ) ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAdpcmChanSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to the ADPCM memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAdpcmChanSwInit ++UINT32 Oct6100ApiAdpcmChanSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_ADPCM_CHAN pChannelsTsiList; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulMaxAdpcmChannels; ++ PVOID pAdpcmChannelsAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Initialize the ADPCM channel API list.*/ ++ ulMaxAdpcmChannels = pSharedInfo->ChipConfig.usMaxAdpcmChannels; ++ ++ /* Set all entries in the ADPCM channel list to unused. */ ++ mOCT6100_GET_ADPCM_CHAN_LIST_PNT( pSharedInfo, pChannelsTsiList ) ++ ++ /* Clear the memory */ ++ Oct6100UserMemSet( pChannelsTsiList, 0x00, sizeof(tOCT6100_API_ADPCM_CHAN) * ulMaxAdpcmChannels ); ++ ++ /* Initialize the ADPCM channel allocation structures to "all free". */ ++ if ( ulMaxAdpcmChannels > 0 ) ++ { ++ mOCT6100_GET_ADPCM_CHAN_ALLOC_PNT( pSharedInfo, pAdpcmChannelsAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pAdpcmChannelsAlloc, ulMaxAdpcmChannels ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_BD; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100AdpcmChanOpenSer ++ ++Description: Opens an ADPCM channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pAdpcmChanOpen Pointer to an ADPCM channel open structure ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100AdpcmChanOpenSer ++UINT32 Oct6100AdpcmChanOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ) ++{ ++ UINT16 usAdpcmChanIndex; ++ UINT16 usTsiMemIndex; ++ UINT16 usAdpcmMemIndex; ++ UINT16 usInputTsstIndex; ++ UINT16 usOutputTsstIndex; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the ADPCM channel open structure for errors. */ ++ ulResult = Oct6100ApiCheckAdpcmChanParams( f_pApiInstance, f_pAdpcmChanOpen ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the ADPCM channel. */ ++ ulResult = Oct6100ApiReserveAdpcmChanResources( f_pApiInstance, f_pAdpcmChanOpen, &usAdpcmChanIndex, &usAdpcmMemIndex, &usTsiMemIndex, &usInputTsstIndex, &usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write all necessary structures to activate the ADPCM channel. */ ++ ulResult = Oct6100ApiWriteAdpcmChanStructs( f_pApiInstance, f_pAdpcmChanOpen, usAdpcmMemIndex, usTsiMemIndex, usInputTsstIndex, usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the ADPCM channel entry in the API list. */ ++ ulResult = Oct6100ApiUpdateAdpcmChanEntry( f_pApiInstance, f_pAdpcmChanOpen, usAdpcmChanIndex, usAdpcmMemIndex, usTsiMemIndex, usInputTsstIndex, usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckAdpcmChanParams ++ ++Description: Checks the user's ADPCM channel open configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pAdpcmChanOpen Pointer to ADPCM channel open configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckAdpcmChanParams ++UINT32 Oct6100ApiCheckAdpcmChanParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen ) ++{ ++ UINT32 ulResult; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxAdpcmChannels == 0 ) ++ return cOCT6100_ERR_ADPCM_CHAN_DISABLED; ++ ++ if ( f_pAdpcmChanOpen->pulChanHndl == NULL ) ++ return cOCT6100_ERR_ADPCM_CHAN_INVALID_HANDLE; ++ ++ /* Check the input TDM streams, timeslots component for errors. */ ++ if ( f_pAdpcmChanOpen->ulInputNumTssts != 1 && ++ f_pAdpcmChanOpen->ulInputNumTssts != 2 ) ++ return cOCT6100_ERR_ADPCM_CHAN_INPUT_NUM_TSSTS; ++ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ f_pAdpcmChanOpen->ulInputNumTssts, ++ f_pAdpcmChanOpen->ulInputTimeslot, ++ f_pAdpcmChanOpen->ulInputStream, ++ cOCT6100_INPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_ADPCM_CHAN_INPUT_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_ADPCM_CHAN_INPUT_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ ++ if( f_pAdpcmChanOpen->ulInputPcmLaw != cOCT6100_PCM_U_LAW && ++ f_pAdpcmChanOpen->ulInputPcmLaw != cOCT6100_PCM_A_LAW ) ++ return cOCT6100_ERR_ADPCM_CHAN_INPUT_PCM_LAW; ++ ++ /* Check the output TDM streams, timeslots component for errors. */ ++ if ( f_pAdpcmChanOpen->ulOutputNumTssts != 1 && ++ f_pAdpcmChanOpen->ulOutputNumTssts != 2 ) ++ return cOCT6100_ERR_ADPCM_CHAN_OUTPUT_NUM_TSSTS; ++ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ f_pAdpcmChanOpen->ulOutputNumTssts, ++ f_pAdpcmChanOpen->ulOutputTimeslot, ++ f_pAdpcmChanOpen->ulOutputStream, ++ cOCT6100_OUTPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_ADPCM_CHAN_OUTPUT_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_ADPCM_CHAN_OUTPUT_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ if( f_pAdpcmChanOpen->ulOutputPcmLaw != cOCT6100_PCM_U_LAW && ++ f_pAdpcmChanOpen->ulOutputPcmLaw != cOCT6100_PCM_A_LAW ) ++ return cOCT6100_ERR_ADPCM_CHAN_OUTPUT_PCM_LAW; ++ ++ /* Now, check the channel mode. */ ++ if ( f_pAdpcmChanOpen->ulChanMode != cOCT6100_ADPCM_ENCODING && ++ f_pAdpcmChanOpen->ulChanMode != cOCT6100_ADPCM_DECODING ) ++ return cOCT6100_ERR_ADPCM_CHAN_MODE; ++ ++ if ( f_pAdpcmChanOpen->ulChanMode == cOCT6100_ADPCM_ENCODING ) ++ { ++ /* Check the encoding rate. */ ++ if ( ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G711_64KBPS ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G726_40KBPS ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G726_32KBPS ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G726_24KBPS ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G726_16KBPS ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_40KBPS_4_1 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_40KBPS_3_2 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_40KBPS_2_3 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_32KBPS_4_0 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_32KBPS_3_1 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_32KBPS_2_2 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_24KBPS_3_0 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_24KBPS_2_1 ) && ++ ( f_pAdpcmChanOpen->ulEncodingRate != cOCT6100_G727_16KBPS_2_0 ) ) ++ return cOCT6100_ERR_ADPCM_CHAN_ENCODING_RATE; ++ } ++ else /* if ( f_pAdpcmChanOpen->ulChanMode != cOCT6100_ADPCM_DECODING ) */ ++ { ++ /* Check the decoding rate. */ ++ if ( f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G711_64KBPS && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G726_40KBPS && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G726_32KBPS && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G726_24KBPS && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G726_16KBPS && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G726_ENCODED && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G711_G726_ENCODED && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G727_2C_ENCODED && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G727_3C_ENCODED && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G727_4C_ENCODED && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G711_G727_2C_ENCODED && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G711_G727_3C_ENCODED && ++ f_pAdpcmChanOpen->ulDecodingRate != cOCT6100_G711_G727_4C_ENCODED ) ++ return cOCT6100_ERR_ADPCM_CHAN_DECODING_RATE; ++ ++ /* Make sure that two timeslots are allocated if PCM-ECHO encoded is selected. */ ++ if ( (f_pAdpcmChanOpen->ulDecodingRate == cOCT6100_G711_G726_ENCODED || ++ f_pAdpcmChanOpen->ulDecodingRate == cOCT6100_G711_G727_2C_ENCODED || ++ f_pAdpcmChanOpen->ulDecodingRate == cOCT6100_G711_G727_3C_ENCODED || ++ f_pAdpcmChanOpen->ulDecodingRate == cOCT6100_G711_G727_4C_ENCODED ) && ++ f_pAdpcmChanOpen->ulInputNumTssts != 2 ) ++ return cOCT6100_ERR_ADPCM_CHAN_INCOMPATIBLE_NUM_TSSTS; ++ } ++ ++ /* Check the nibble position. */ ++ if ( f_pAdpcmChanOpen->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_LOW_BITS && ++ f_pAdpcmChanOpen->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_HIGH_BITS ) ++ return cOCT6100_ERR_ADPCM_CHAN_ADPCM_NIBBLE_POSITION; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveAdpcmChanResources ++ ++Description: Reserves all resources needed for the new ADPCM channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pAdpcmChanOpen Pointer to ADPCM channel configuration structure. ++f_pusAdpcmChanIndex Allocated entry in ADPCM channel list. ++f_pusAdpcmMemIndex Allocated entry in the ADPCM control memory. ++f_pusTsiMemIndex Allocated entry in the TSI chariot memory. ++f_pusInputTsstIndex TSST memory index of the input samples. ++f_pusOutputTsstIndex TSST memory index of the output samples. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveAdpcmChanResources ++UINT32 Oct6100ApiReserveAdpcmChanResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen, ++ OUT PUINT16 f_pusAdpcmChanIndex, ++ OUT PUINT16 f_pusAdpcmMemIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ UINT32 ulTempVar; ++ BOOL fAdpcmChanEntry = FALSE; ++ BOOL fAdpcmMemEntry = FALSE; ++ BOOL fTsiMemEntry = FALSE; ++ BOOL fInputTsst = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Reserve an entry in the ADPCM channel list. */ ++ ulResult = Oct6100ApiReserveAdpcmChanEntry( f_pApiInstance, f_pusAdpcmChanIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fAdpcmChanEntry = TRUE; ++ ++ /* Find a TSI memory entry.*/ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, f_pusTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fTsiMemEntry = TRUE; ++ ++ /* Find a conversion memory entry. */ ++ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, f_pusAdpcmMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fAdpcmMemEntry = TRUE; ++ ++ /* Reserve the input TSST entry. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ f_pAdpcmChanOpen->ulInputTimeslot, ++ f_pAdpcmChanOpen->ulInputStream, ++ f_pAdpcmChanOpen->ulInputNumTssts, ++ cOCT6100_INPUT_TSST, ++ f_pusInputTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fInputTsst = TRUE; ++ ++ /* Reserve the output TSST entry. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ f_pAdpcmChanOpen->ulOutputTimeslot, ++ f_pAdpcmChanOpen->ulOutputStream, ++ f_pAdpcmChanOpen->ulOutputNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ f_pusOutputTsstIndex, ++ NULL ); ++ } ++ } ++ } ++ else ++ { ++ /* Return an error other than a fatal error. */ ++ ulResult = cOCT6100_ERR_ADPCM_CHAN_NO_MORE_TSI_AVAILABLE; ++ } ++ } ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if( fAdpcmChanEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseAdpcmChanEntry( f_pApiInstance, *f_pusAdpcmChanIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fTsiMemEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, *f_pusTsiMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fAdpcmMemEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, *f_pusAdpcmMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fInputTsst == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ f_pAdpcmChanOpen->ulInputTimeslot, ++ f_pAdpcmChanOpen->ulInputStream, ++ f_pAdpcmChanOpen->ulInputNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteAdpcmChanStructs ++ ++Description: Performs all the required structure writes to configure the ++ new ADPCM channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pAdpcmChanOpen Pointer to ADPCM channel configuration structure. ++f_pusAdpcmChanIndex Allocated entry in ADPCM channel list. ++f_pusAdpcmMemIndex Allocated entry in the ADPCM control memory. ++f_pusTsiMemIndex Allocated entry in the TSI chariot memory. ++f_pusInputTsstIndex TSST memory index of the input samples. ++f_pusOutputTsstIndex TSST memory index of the output samples. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteAdpcmChanStructs ++UINT32 Oct6100ApiWriteAdpcmChanStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen, ++ IN UINT16 f_usAdpcmMemIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ UINT32 ulCompType = 0; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Configure the TSST control memory. */ ++ ++ /* Set the input TSST control entry. */ ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_usInputTsstIndex, ++ f_usTsiMemIndex, ++ f_pAdpcmChanOpen->ulInputPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the output TSST control entry. */ ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_usOutputTsstIndex, ++ f_pAdpcmChanOpen->ulAdpcmNibblePosition, ++ f_pAdpcmChanOpen->ulOutputNumTssts, ++ f_usTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Configure the ADPCM memory. */ ++ ++ if ( f_pAdpcmChanOpen->ulChanMode == cOCT6100_ADPCM_ENCODING ) ++ { ++ switch( f_pAdpcmChanOpen->ulEncodingRate ) ++ { ++ case cOCT6100_G711_64KBPS: ++ ++ if ( f_pAdpcmChanOpen->ulOutputPcmLaw == cOCT6100_PCM_U_LAW ) ++ ulCompType = 0x4; ++ else /* if ( f_pAdpcmChanOpen->ulOutputPcmLaw != cOCT6100_PCM_U_LAW ) */ ++ ulCompType = 0x5; ++ break; ++ case cOCT6100_G726_40KBPS: ulCompType = 0x3; break; ++ case cOCT6100_G726_32KBPS: ulCompType = 0x2; break; ++ case cOCT6100_G726_24KBPS: ulCompType = 0x1; break; ++ case cOCT6100_G726_16KBPS: ulCompType = 0x0; break; ++ case cOCT6100_G727_40KBPS_4_1: ulCompType = 0xD; break; ++ case cOCT6100_G727_40KBPS_3_2: ulCompType = 0xA; break; ++ case cOCT6100_G727_40KBPS_2_3: ulCompType = 0x6; break; ++ case cOCT6100_G727_32KBPS_4_0: ulCompType = 0xE; break; ++ case cOCT6100_G727_32KBPS_3_1: ulCompType = 0xB; break; ++ case cOCT6100_G727_32KBPS_2_2: ulCompType = 0x7; break; ++ case cOCT6100_G727_24KBPS_3_0: ulCompType = 0xC; break; ++ case cOCT6100_G727_24KBPS_2_1: ulCompType = 0x8; break; ++ case cOCT6100_G727_16KBPS_2_0: ulCompType = 0x9; break; ++ } ++ ++ ulResult = Oct6100ApiWriteEncoderMemory( f_pApiInstance, ++ f_usAdpcmMemIndex, ++ ulCompType, ++ f_usTsiMemIndex, ++ FALSE, ++ f_pAdpcmChanOpen->ulAdpcmNibblePosition, ++ cOCT6100_INVALID_INDEX, ++ cOCT6100_INVALID_VALUE, ++ cOCT6100_INVALID_VALUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else /* if ( f_pAdpcmChanOpen->ulChanMode != cOCT6100_ADPCM_DECODING ) */ ++ { ++ switch( f_pAdpcmChanOpen->ulDecodingRate ) ++ { ++ case cOCT6100_G711_64KBPS: ulCompType = 0x8; break; ++ case cOCT6100_G726_40KBPS: ulCompType = 0x3; break; ++ case cOCT6100_G726_32KBPS: ulCompType = 0x2; break; ++ case cOCT6100_G726_24KBPS: ulCompType = 0x1; break; ++ case cOCT6100_G726_16KBPS: ulCompType = 0x0; break; ++ case cOCT6100_G727_2C_ENCODED: ulCompType = 0x4; break; ++ case cOCT6100_G727_3C_ENCODED: ulCompType = 0x5; break; ++ case cOCT6100_G727_4C_ENCODED: ulCompType = 0x6; break; ++ case cOCT6100_G726_ENCODED: ulCompType = 0x9; break; ++ case cOCT6100_G711_G726_ENCODED: ulCompType = 0xA; break; ++ case cOCT6100_G711_G727_2C_ENCODED: ulCompType = 0xC; break; ++ case cOCT6100_G711_G727_3C_ENCODED: ulCompType = 0xD; break; ++ case cOCT6100_G711_G727_4C_ENCODED: ulCompType = 0xE; break; ++ } ++ ++ ulResult = Oct6100ApiWriteDecoderMemory( f_pApiInstance, ++ f_usAdpcmMemIndex, ++ ulCompType, ++ f_usTsiMemIndex, ++ f_pAdpcmChanOpen->ulOutputPcmLaw, ++ f_pAdpcmChanOpen->ulAdpcmNibblePosition ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateAdpcmChanEntry ++ ++Description: Updates the new ADPCM channel in the ADPCM channel list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pAdpcmChanOpen Pointer to ADPCM channel open configuration structure. ++f_usAdpcmChanIndex Allocated entry in the ADPCM channel list. ++f_usAdpcmMemIndex Allocated entry in ADPCM memory. ++f_usTsiMemIndex Allocated entry in TSI chariot memory. ++f_usInputTsstIndex TSST control memory index of the input TSST. ++f_usOutputTsstIndex TSST control memory index of the output TSST. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateAdpcmChanEntry ++UINT32 Oct6100ApiUpdateAdpcmChanEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_OPEN f_pAdpcmChanOpen, ++ IN UINT16 f_usAdpcmChanIndex, ++ IN UINT16 f_usAdpcmMemIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ) ++{ ++ tPOCT6100_API_ADPCM_CHAN pAdpcmChanEntry; ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Obtain a pointer to the new ADPCM channel's list entry. */ ++ ++ mOCT6100_GET_ADPCM_CHAN_ENTRY_PNT( f_pApiInstance->pSharedInfo, pAdpcmChanEntry, f_usAdpcmChanIndex ) ++ ++ /* Copy the buffer's configuration and allocated resources. */ ++ pAdpcmChanEntry->usInputTimeslot = (UINT16)( f_pAdpcmChanOpen->ulInputTimeslot & 0xFFFF ); ++ pAdpcmChanEntry->usInputStream = (UINT16)( f_pAdpcmChanOpen->ulInputStream & 0xFFFF ); ++ pAdpcmChanEntry->byInputNumTssts = (UINT8)( f_pAdpcmChanOpen->ulInputNumTssts & 0xFF ); ++ pAdpcmChanEntry->byInputPcmLaw = (UINT8)( f_pAdpcmChanOpen->ulInputPcmLaw & 0xFF ); ++ ++ pAdpcmChanEntry->usOutputTimeslot = (UINT16)( f_pAdpcmChanOpen->ulOutputTimeslot & 0xFFFF ); ++ pAdpcmChanEntry->usOutputStream = (UINT16)( f_pAdpcmChanOpen->ulOutputStream & 0xFFFF ); ++ pAdpcmChanEntry->byOutputNumTssts = (UINT8)( f_pAdpcmChanOpen->ulOutputNumTssts & 0xFF ); ++ pAdpcmChanEntry->byOutputPcmLaw = (UINT8)( f_pAdpcmChanOpen->ulOutputPcmLaw & 0xFF ); ++ ++ /* Store hardware related information. */ ++ pAdpcmChanEntry->usTsiMemIndex = f_usTsiMemIndex; ++ pAdpcmChanEntry->usAdpcmMemIndex = f_usAdpcmMemIndex; ++ pAdpcmChanEntry->usInputTsstIndex = f_usInputTsstIndex; ++ pAdpcmChanEntry->usOutputTsstIndex = f_usOutputTsstIndex; ++ ++ /* Form handle returned to user. */ ++ *f_pAdpcmChanOpen->pulChanHndl = cOCT6100_HNDL_TAG_ADPCM_CHANNEL | (pAdpcmChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usAdpcmChanIndex; ++ ++ /* Finally, mark the ADPCM channel as opened. */ ++ pAdpcmChanEntry->fReserved = TRUE; ++ ++ /* Increment the number of ADPCM channel opened. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberAdpcmChans++; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100AdpcmChanCloseSer ++ ++Description: Closes an ADPCM channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pAdpcmChanClose Pointer to ADPCM channel close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100AdpcmChanCloseSer ++UINT32 Oct6100AdpcmChanCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose ) ++{ ++ UINT16 usAdpcmChanIndex; ++ UINT16 usTsiMemIndex; ++ UINT16 usAdpcmMemIndex; ++ UINT16 usInputTsstIndex; ++ UINT16 usOutputTsstIndex; ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertAdpcmChanParams( f_pApiInstance, f_pAdpcmChanClose, &usAdpcmChanIndex, &usAdpcmMemIndex, &usTsiMemIndex, &usInputTsstIndex, &usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the ADPCM channel. */ ++ ulResult = Oct6100ApiInvalidateAdpcmChanStructs( f_pApiInstance, usAdpcmMemIndex, usInputTsstIndex, usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the ADPCM channel. */ ++ ulResult = Oct6100ApiReleaseAdpcmChanResources( f_pApiInstance, usAdpcmChanIndex, usAdpcmMemIndex, usTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Invalidate the handle. */ ++ f_pAdpcmChanClose->ulChanHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertAdpcmChanParams ++ ++Description: Validate the handle given by the user and verify the state of ++ the ADPCM channel about to be closed. ++ Also return all required information to deactivate the channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pAdpcmChanClose Pointer to ADPCM channel close structure. ++f_pusAdpcmChanIndex Index of the ADPCM channel structure in the API list. ++f_pusAdpcmMemIndex Index of the ADPCM memory structure in the API list. ++f_pusTsiMemIndex Index of the TSI chariot memory used for this channel. ++f_pusInputTsstIndex Index of the input entry in the TSST control memory. ++f_pusOutputTsstIndex Index of the output entry in the TSST control memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertAdpcmChanParams ++UINT32 Oct6100ApiAssertAdpcmChanParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_ADPCM_CHAN_CLOSE f_pAdpcmChanClose, ++ OUT PUINT16 f_pusAdpcmChanIndex, ++ OUT PUINT16 f_pusAdpcmMemIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_ADPCM_CHAN pAdpcmChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pAdpcmChanClose->ulChanHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_ADPCM_CHANNEL ) ++ return cOCT6100_ERR_ADPCM_CHAN_INVALID_HANDLE; ++ ++ *f_pusAdpcmChanIndex = (UINT16)( f_pAdpcmChanClose->ulChanHndl & cOCT6100_HNDL_INDEX_MASK ); ++ ++ if ( *f_pusAdpcmChanIndex >= pSharedInfo->ChipConfig.usMaxAdpcmChannels ) ++ return cOCT6100_ERR_ADPCM_CHAN_INVALID_HANDLE; ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_ADPCM_CHAN_ENTRY_PNT( pSharedInfo, pAdpcmChanEntry, *f_pusAdpcmChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pAdpcmChanClose->ulChanHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pAdpcmChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_ADPCM_CHAN_NOT_OPEN; ++ if ( ulEntryOpenCnt != pAdpcmChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_ADPCM_CHAN_INVALID_HANDLE; ++ ++ /* Return info needed to close the channel and release all resources. */ ++ *f_pusInputTsstIndex = pAdpcmChanEntry->usInputTsstIndex; ++ *f_pusOutputTsstIndex = pAdpcmChanEntry->usOutputTsstIndex; ++ *f_pusTsiMemIndex = pAdpcmChanEntry->usTsiMemIndex; ++ *f_pusAdpcmMemIndex = pAdpcmChanEntry->usAdpcmMemIndex; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidateAdpcmChanStructs ++ ++Description: Closes an ADPCM channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usAdpcmMemIndex Index of the ADPCM memory. ++f_usInputTsstIndex Index of the input entry in the TSST control memory. ++f_usOutputTsstIndex Index of the output entry in the TSST control memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidateAdpcmChanStructs ++UINT32 Oct6100ApiInvalidateAdpcmChanStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usAdpcmMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Deactivate the TSST control memory. */ ++ ++ /* Set the input TSST control entry to unused. */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( f_usInputTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = 0x0000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the output TSST control entry to unused. */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( f_usOutputTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = 0x0000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Clear the ADPCM memory. */ ++ ++ ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, f_usAdpcmMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseAdpcmChanResources ++ ++Description: Release and clear the API entry associated to the ADPCM channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_ulAdpcmChanIndex Index of the ADPCM channel in the API list. ++f_usAdpcmMemIndex Index of the ADPCM memory used. ++f_usTsiMemIndex Index of the TSI memory used. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseAdpcmChanResources ++UINT32 Oct6100ApiReleaseAdpcmChanResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usAdpcmChanIndex, ++ IN UINT16 f_usAdpcmMemIndex, ++ IN UINT16 f_usTsiMemIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_ADPCM_CHAN pAdpcmChanEntry; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_ADPCM_CHAN_ENTRY_PNT( pSharedInfo, pAdpcmChanEntry, f_usAdpcmChanIndex ); ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Release all resources associated with ADPCM channel. */ ++ ++ /* Release the entry in the ADPCM channel list. */ ++ ulResult = Oct6100ApiReleaseAdpcmChanEntry( f_pApiInstance, f_usAdpcmChanIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, f_usAdpcmMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, f_usTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Release the input TSST entry. */ ++ ulResult = Oct6100ApiReleaseTsst( ++ f_pApiInstance, ++ pAdpcmChanEntry->usInputTimeslot, ++ pAdpcmChanEntry->usInputStream, ++ pAdpcmChanEntry->byInputNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Release the output TSST entry. */ ++ ulResult = Oct6100ApiReleaseTsst( ++ f_pApiInstance, ++ pAdpcmChanEntry->usOutputTimeslot, ++ pAdpcmChanEntry->usOutputStream, ++ pAdpcmChanEntry->byOutputNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ } ++ } ++ } ++ } ++ ++ /* Check if an error occured while releasing the reserved resources. */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult >= cOCT6100_ERR_FATAL ) ++ return ulResult; ++ else ++ return cOCT6100_ERR_FATAL_4A; ++ } ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Update the ADPCM channel's list entry. */ ++ ++ /* Mark the channel as closed. */ ++ pAdpcmChanEntry->fReserved = FALSE; ++ pAdpcmChanEntry->byEntryOpenCnt++; ++ ++ /* Decrement the number of ADPCM channels opened. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberAdpcmChans--; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveAdpcmChanEntry ++ ++Description: Reserves one of the ADPCM channel API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pusAdpcmChanIndex Resulting index reserved in the ADPCM channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveAdpcmChanEntry ++UINT32 Oct6100ApiReserveAdpcmChanEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusAdpcmChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pAdpcmChanAlloc; ++ UINT32 ulResult; ++ UINT32 ulAdpcmChanIndex; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_ADPCM_CHAN_ALLOC_PNT( pSharedInfo, pAdpcmChanAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pAdpcmChanAlloc, &ulAdpcmChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_ADPCM_CHAN_ALL_ADPCM_CHAN_ARE_OPENED; ++ else ++ return cOCT6100_ERR_FATAL_BE; ++ } ++ ++ *f_pusAdpcmChanIndex = (UINT16)( ulAdpcmChanIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseAdpcmChanEntry ++ ++Description: Releases the specified ADPCM channel API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usAdpcmChanIndex Index reserved in the ADPCM channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseAdpcmChanEntry ++UINT32 Oct6100ApiReleaseAdpcmChanEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usAdpcmChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pAdpcmChanAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_ADPCM_CHAN_ALLOC_PNT( pSharedInfo, pAdpcmChanAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pAdpcmChanAlloc, f_usAdpcmChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_BF; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,13933 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_channel.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to open, modify and close echo ++ cancellation channels. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 492 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#if defined(__FreeBSD__) ++#include ++#include ++#else ++#ifndef __KERNEL__ ++#include ++#include ++#define kmalloc(size, type) malloc(size) ++#define kfree(ptr) free(ptr) ++#define GFP_ATOMIC 0 /* Dummy */ ++#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) ++#else ++#include ++#include ++#endif ++#endif ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_mixer_inst.h" ++#include "oct6100api/oct6100_tsi_cnct_inst.h" ++#include "oct6100api/oct6100_conf_bridge_inst.h" ++#include "oct6100api/oct6100_tone_detection_inst.h" ++#include "oct6100api/oct6100_phasing_tsst_inst.h" ++#include "oct6100api/oct6100_tsst_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_tsi_cnct_pub.h" ++#include "oct6100api/oct6100_playout_buf_pub.h" ++#include "oct6100api/oct6100_phasing_tsst_pub.h" ++#include "oct6100api/oct6100_mixer_pub.h" ++#include "oct6100api/oct6100_conf_bridge_pub.h" ++#include "oct6100api/oct6100_tone_detection_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_debug_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_tsst_priv.h" ++#include "oct6100_mixer_priv.h" ++#include "oct6100_phasing_tsst_priv.h" ++#include "oct6100_tsi_cnct_priv.h" ++#include "oct6100_playout_buf_priv.h" ++#include "oct6100_conf_bridge_priv.h" ++#include "oct6100_tone_detection_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_debug_priv.h" ++ ++ ++/**************************** PUBLIC FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelOpen ++ ++Description: This function opens a echo cancellation channel. An echo cancellation ++ channel is constituted of two voice stream (RIN/ROUT and SIN/SOUT), and ++ an echo cancelling core. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelOpen Pointer to echo channel open structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelOpenDef ++UINT32 Oct6100ChannelOpenDef( ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) ++{ ++ f_pChannelOpen->pulChannelHndl = NULL; ++ f_pChannelOpen->ulUserChanId = cOCT6100_INVALID_VALUE; ++ f_pChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; ++ f_pChannelOpen->fEnableToneDisabler = FALSE; ++ f_pChannelOpen->fEnableExtToneDetection = FALSE; ++ ++ /* VQE configuration.*/ ++ f_pChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE; ++ f_pChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE; ++ f_pChannelOpen->VqeConfig.fRinLevelControl = FALSE; ++ f_pChannelOpen->VqeConfig.lRinLevelControlGainDb = 0; ++ f_pChannelOpen->VqeConfig.fSoutLevelControl = FALSE; ++ f_pChannelOpen->VqeConfig.lSoutLevelControlGainDb = 0; ++ f_pChannelOpen->VqeConfig.fRinAutomaticLevelControl = FALSE; ++ f_pChannelOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = -20; ++ f_pChannelOpen->VqeConfig.fSoutAutomaticLevelControl = FALSE; ++ f_pChannelOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = -20; ++ f_pChannelOpen->VqeConfig.fRinHighLevelCompensation = FALSE; ++ f_pChannelOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = -10; ++ f_pChannelOpen->VqeConfig.fSoutAdaptiveNoiseReduction = FALSE; ++ f_pChannelOpen->VqeConfig.fSoutNoiseBleaching = FALSE; ++ f_pChannelOpen->VqeConfig.fSoutConferencingNoiseReduction = FALSE; ++ f_pChannelOpen->VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; ++ f_pChannelOpen->VqeConfig.fEnableNlp = TRUE; ++ f_pChannelOpen->VqeConfig.fEnableTailDisplacement = FALSE; ++ f_pChannelOpen->VqeConfig.ulTailDisplacement = cOCT6100_AUTO_SELECT_TAIL; ++ f_pChannelOpen->VqeConfig.ulTailLength = cOCT6100_AUTO_SELECT_TAIL; ++ ++ f_pChannelOpen->VqeConfig.fDtmfToneRemoval = FALSE; ++ ++ f_pChannelOpen->VqeConfig.fAcousticEcho = FALSE; ++ f_pChannelOpen->VqeConfig.lDefaultErlDb = -6; ++ f_pChannelOpen->VqeConfig.ulAecTailLength = 128; ++ f_pChannelOpen->VqeConfig.lAecDefaultErlDb = 0; ++ f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorA = 1; ++ f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorB = 0; ++ f_pChannelOpen->VqeConfig.ulDoubleTalkBehavior = cOCT6100_DOUBLE_TALK_BEH_NORMAL; ++ f_pChannelOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = 0; ++ f_pChannelOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = 0; ++ f_pChannelOpen->VqeConfig.fSoutNaturalListenerEnhancement = FALSE; ++ f_pChannelOpen->VqeConfig.fRoutNoiseReduction = FALSE; ++ f_pChannelOpen->VqeConfig.lRoutNoiseReductionLevelGainDb = -18; ++ f_pChannelOpen->VqeConfig.lAnrSnrEnhancementDb = -18; ++ f_pChannelOpen->VqeConfig.ulAnrVoiceNoiseSegregation = 6; ++ f_pChannelOpen->VqeConfig.ulToneDisablerVqeActivationDelay = 300; ++ f_pChannelOpen->VqeConfig.fEnableMusicProtection = FALSE; ++ /* Older images have idle code detection hard-coded to enabled. */ ++ f_pChannelOpen->VqeConfig.fIdleCodeDetection = TRUE; ++ ++ /* TDM configuration.*/ ++ f_pChannelOpen->TdmConfig.ulRinNumTssts = 1; ++ f_pChannelOpen->TdmConfig.ulSinNumTssts = 1; ++ f_pChannelOpen->TdmConfig.ulRoutNumTssts = 1; ++ f_pChannelOpen->TdmConfig.ulSoutNumTssts = 1; ++ ++ f_pChannelOpen->TdmConfig.ulRinTimeslot = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulRinStream = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulRinPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ f_pChannelOpen->TdmConfig.ulSinTimeslot = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulSinStream = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulSinPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ f_pChannelOpen->TdmConfig.ulRoutTimeslot = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulRoutStream = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulRoutPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ f_pChannelOpen->TdmConfig.ulSoutTimeslot = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulSoutStream = cOCT6100_UNASSIGNED; ++ f_pChannelOpen->TdmConfig.ulSoutPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ /* CODEC configuration.*/ ++ f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition = cOCT6100_ADPCM_IN_LOW_BITS; ++ ++ f_pChannelOpen->CodecConfig.ulEncoderPort = cOCT6100_CHANNEL_PORT_SOUT; ++ f_pChannelOpen->CodecConfig.ulEncodingRate = cOCT6100_G711_64KBPS; ++ f_pChannelOpen->CodecConfig.ulDecoderPort = cOCT6100_CHANNEL_PORT_RIN; ++ f_pChannelOpen->CodecConfig.ulDecodingRate = cOCT6100_G711_64KBPS; ++ ++ f_pChannelOpen->CodecConfig.fEnableSilenceSuppression = FALSE; ++ f_pChannelOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; ++ f_pChannelOpen->CodecConfig.ulPhase = 1; ++ f_pChannelOpen->CodecConfig.ulPhasingType = cOCT6100_NO_PHASING; ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelOpen ++UINT32 Oct6100ChannelOpen( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelOpenSer( f_pApiInstance, f_pChannelOpen ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelClose ++ ++Description: This function closes an echo canceller channel ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelClose Pointer to channel close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelCloseDef ++UINT32 Oct6100ChannelCloseDef( ++ IN OUT tPOCT6100_CHANNEL_CLOSE f_pChannelClose ) ++{ ++ f_pChannelClose->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelClose ++UINT32 Oct6100ChannelClose( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelCloseSer( f_pApiInstance, f_pChannelClose ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelModify ++ ++Description: This function will modify the parameter of an echo channel. If ++ the call to this channel allows the channel to go from power down ++ to enable, the API will activate it. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelModify Pointer to echo channel change structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelModifyDef ++UINT32 Oct6100ChannelModifyDef( ++ IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) ++{ ++ f_pChannelModify->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pChannelModify->ulUserChanId = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->ulEchoOperationMode = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->fEnableToneDisabler = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->fApplyToAllChannels = FALSE; ++ ++ f_pChannelModify->fDisableToneDetection = FALSE; ++ f_pChannelModify->fStopBufferPlayout = FALSE; ++ f_pChannelModify->fRemoveConfBridgeParticipant = FALSE; ++ f_pChannelModify->fRemoveBroadcastTssts = FALSE; ++ ++ f_pChannelModify->fTdmConfigModified = FALSE; ++ f_pChannelModify->fVqeConfigModified = FALSE; ++ f_pChannelModify->fCodecConfigModified = FALSE; ++ ++ /* VQE config. */ ++ f_pChannelModify->VqeConfig.fSinDcOffsetRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fRinDcOffsetRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fRinLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lRinLevelControlGainDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fSoutLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lSoutLevelControlGainDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fRinAutomaticLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lRinAutomaticLevelControlTargetDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fSoutAutomaticLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lSoutAutomaticLevelControlTargetDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fRinHighLevelCompensation = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lRinHighLevelCompensationThresholdDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fSoutAdaptiveNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fSoutNoiseBleaching = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fSoutConferencingNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulComfortNoiseMode = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fEnableNlp = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fEnableTailDisplacement = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulTailDisplacement = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->VqeConfig.fDtmfToneRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->VqeConfig.fAcousticEcho = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lDefaultErlDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulAecTailLength = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lAecDefaultErlDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulNonLinearityBehaviorA = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulNonLinearityBehaviorB = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulDoubleTalkBehavior = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fSoutNaturalListenerEnhancement = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fRoutNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lRoutNoiseReductionLevelGainDb = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.lAnrSnrEnhancementDb = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulAnrVoiceNoiseSegregation = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.ulToneDisablerVqeActivationDelay = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fEnableMusicProtection = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->VqeConfig.fIdleCodeDetection = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ /* TDM config. */ ++ f_pChannelModify->TdmConfig.ulRinNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulSinNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulRoutNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulSoutNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->TdmConfig.ulRinTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulRinStream = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulRinPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->TdmConfig.ulSinTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulSinStream = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulSinPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->TdmConfig.ulRoutTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulRoutStream = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulRoutPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->TdmConfig.ulSoutTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulSoutStream = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->TdmConfig.ulSoutPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ /* CODEC config. */ ++ f_pChannelModify->CodecConfig.ulEncoderPort = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->CodecConfig.ulEncodingRate = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->CodecConfig.ulDecoderPort = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->CodecConfig.ulDecodingRate = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ f_pChannelModify->CodecConfig.fEnableSilenceSuppression = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->CodecConfig.ulPhasingTsstHndl = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->CodecConfig.ulPhase = cOCT6100_KEEP_PREVIOUS_SETTING; ++ f_pChannelModify->CodecConfig.ulPhasingType = cOCT6100_KEEP_PREVIOUS_SETTING; ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelModify ++UINT32 Oct6100ChannelModify( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Check the apply to all channels flag first. */ ++ if ( f_pChannelModify->fApplyToAllChannels != TRUE && ++ f_pChannelModify->fApplyToAllChannels != FALSE ) ++ return cOCT6100_ERR_CHANNEL_APPLY_TO_ALL_CHANNELS; ++ ++ /* Check if must apply modification to all channels. */ ++ if ( f_pChannelModify->fApplyToAllChannels == TRUE ) ++ { ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT16 usChanIndex; ++ ++ /* Loop through all channels and look for the opened ones. */ ++ for ( usChanIndex = 0; usChanIndex < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; usChanIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, usChanIndex ); ++ ++ /* Check if this one is opened. */ ++ if ( pChanEntry->fReserved == TRUE ) ++ { ++ /* Channel is opened. Form handle and call actual modify function. */ ++ f_pChannelModify->ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | usChanIndex; ++ ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelModifySer( f_pApiInstance, f_pChannelModify ); ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ break; ++ } ++ } ++ } ++ else /* if ( f_pChannelModify->fApplyToAllChannels == FALSE ) */ ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelModifySer( f_pApiInstance, f_pChannelModify ); ++ } ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelCreateBiDir ++ ++Description: This function creates a bidirectional channel using two standard ++ echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelCreateBiDir Pointer to channel create BiDir structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelCreateBiDirDef ++UINT32 Oct6100ChannelCreateBiDirDef( ++ IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ) ++{ ++ f_pChannelCreateBiDir->pulBiDirChannelHndl = NULL; ++ ++ f_pChannelCreateBiDir->ulFirstChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pChannelCreateBiDir->ulSecondChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelCreateBiDir ++UINT32 Oct6100ChannelCreateBiDir( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelCreateBiDirSer( f_pApiInstance, f_pChannelCreateBiDir ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelDestroyBiDir ++ ++Description: This function destroys a bidirectional channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelDestroyBiDir Pointer to channel destroy BiDir structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelDestroyBiDirDef ++UINT32 Oct6100ChannelDestroyBiDirDef( ++ IN OUT tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ) ++{ ++ f_pChannelDestroyBiDir->ulBiDirChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelDestroyBiDir ++UINT32 Oct6100ChannelDestroyBiDir( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelDestroyBiDirSer( f_pApiInstance, f_pChannelDestroyBiDir ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelBroadcastTsstAdd ++ ++Description: This function adds a TSST to one of the two output ports of a channel. ++ This TSST can never be modified by a call to Oct6100ChannelModify. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelBroadcastTsstAdd Pointer to the an Add Broadcast TSST structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelBroadcastTsstAddDef ++UINT32 Oct6100ChannelBroadcastTsstAddDef( ++ tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelBroadcastTsstAdd ) ++{ ++ f_pChannelBroadcastTsstAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ f_pChannelBroadcastTsstAdd->ulPort = cOCT6100_INVALID_PORT; ++ f_pChannelBroadcastTsstAdd->ulTimeslot = cOCT6100_INVALID_TIMESLOT; ++ f_pChannelBroadcastTsstAdd->ulStream = cOCT6100_INVALID_STREAM; ++ ++ return cOCT6100_ERR_OK; ++ ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelBroadcastTsstAdd ++UINT32 Oct6100ChannelBroadcastTsstAdd( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelBroadcastTsstAdd ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelBroadcastTsstAddSer( f_pApiInstance, f_pChannelBroadcastTsstAdd ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelBroadcastTsstRemove ++ ++Description: This function removes a TSST from one of the two output ports of a channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelBroadcastTsstRemove Pointer to the a Remove Broadcast TSST structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelBroadcastTsstRemoveDef ++UINT32 Oct6100ChannelBroadcastTsstRemoveDef( ++ tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelBroadcastTsstRemove ) ++{ ++ f_pChannelBroadcastTsstRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ f_pChannelBroadcastTsstRemove->ulPort = cOCT6100_INVALID_PORT; ++ f_pChannelBroadcastTsstRemove->ulTimeslot = cOCT6100_INVALID_TIMESLOT; ++ f_pChannelBroadcastTsstRemove->ulStream = cOCT6100_INVALID_STREAM; ++ ++ f_pChannelBroadcastTsstRemove->fRemoveAll = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ChannelBroadcastTsstRemove ++UINT32 Oct6100ChannelBroadcastTsstRemove( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelBroadcastTsstRemove ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, f_pChannelBroadcastTsstRemove ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelGetStats ++ ++Description: This function retrieves all the config and stats related to the channel ++ designated by ulChannelHndl. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelStats Pointer to a tOCT6100_CHANNEL_STATS structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelGetStatsDef ++UINT32 Oct6100ChannelGetStatsDef( ++ IN OUT tPOCT6100_CHANNEL_STATS f_pChannelStats ) ++{ ++ f_pChannelStats->fResetStats = FALSE; ++ ++ f_pChannelStats->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pChannelStats->ulUserChanId = cOCT6100_INVALID_STAT; ++ f_pChannelStats->ulEchoOperationMode = cOCT6100_INVALID_STAT; ++ f_pChannelStats->fEnableToneDisabler = FALSE; ++ f_pChannelStats->ulMutePortsMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; ++ f_pChannelStats->fEnableExtToneDetection = FALSE; ++ ++ /* VQE configuration.*/ ++ f_pChannelStats->VqeConfig.fEnableNlp = FALSE; ++ f_pChannelStats->VqeConfig.fEnableTailDisplacement = FALSE; ++ f_pChannelStats->VqeConfig.ulTailDisplacement = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.ulTailLength = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->VqeConfig.fSinDcOffsetRemoval = FALSE; ++ f_pChannelStats->VqeConfig.fRinDcOffsetRemoval = FALSE; ++ f_pChannelStats->VqeConfig.fRinLevelControl = FALSE; ++ f_pChannelStats->VqeConfig.fSoutLevelControl = FALSE; ++ f_pChannelStats->VqeConfig.fRinAutomaticLevelControl = FALSE; ++ f_pChannelStats->VqeConfig.fSoutAutomaticLevelControl = FALSE; ++ f_pChannelStats->VqeConfig.fRinHighLevelCompensation = FALSE; ++ f_pChannelStats->VqeConfig.fAcousticEcho = FALSE; ++ f_pChannelStats->VqeConfig.fSoutAdaptiveNoiseReduction = FALSE; ++ f_pChannelStats->VqeConfig.fDtmfToneRemoval = FALSE; ++ ++ f_pChannelStats->VqeConfig.fSoutNoiseBleaching = FALSE; ++ f_pChannelStats->VqeConfig.fSoutConferencingNoiseReduction = FALSE; ++ ++ f_pChannelStats->VqeConfig.ulComfortNoiseMode = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.ulNonLinearityBehaviorA = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.ulNonLinearityBehaviorB = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.ulDoubleTalkBehavior = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.lRinLevelControlGainDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.lSoutLevelControlGainDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.lRinAutomaticLevelControlTargetDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.lSoutAutomaticLevelControlTargetDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.lRinHighLevelCompensationThresholdDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.lDefaultErlDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.lAecDefaultErlDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.ulAecTailLength = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.fSoutNaturalListenerEnhancement = FALSE; ++ f_pChannelStats->VqeConfig.fRoutNoiseReduction = FALSE; ++ f_pChannelStats->VqeConfig.lRoutNoiseReductionLevelGainDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.lAnrSnrEnhancementDb = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->VqeConfig.ulAnrVoiceNoiseSegregation = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.ulToneDisablerVqeActivationDelay = cOCT6100_INVALID_STAT; ++ f_pChannelStats->VqeConfig.fEnableMusicProtection = FALSE; ++ f_pChannelStats->VqeConfig.fIdleCodeDetection = FALSE; ++ ++ ++ ++ /* TDM configuration.*/ ++ f_pChannelStats->TdmConfig.ulMaxBroadcastTssts = 0; ++ f_pChannelStats->TdmConfig.fMoreRoutBroadcastTssts = FALSE; ++ f_pChannelStats->TdmConfig.fMoreSoutBroadcastTssts = FALSE; ++ ++ f_pChannelStats->TdmConfig.ulNumRoutBroadcastTssts = 0; ++ f_pChannelStats->TdmConfig.ulNumSoutBroadcastTssts = 0; ++ ++ f_pChannelStats->TdmConfig.ulRinNumTssts = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulSinNumTssts = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulRoutNumTssts = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulSoutNumTssts = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->TdmConfig.ulRinTimeslot = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulRinStream = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulRinPcmLaw = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->TdmConfig.ulSinTimeslot = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulSinStream = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulSinPcmLaw = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->TdmConfig.ulRoutTimeslot = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulRoutStream = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulRoutPcmLaw = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->TdmConfig.pulRoutBroadcastTimeslot = NULL; ++ f_pChannelStats->TdmConfig.pulRoutBroadcastStream = NULL; ++ ++ f_pChannelStats->TdmConfig.ulSoutTimeslot = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulSoutStream = cOCT6100_INVALID_STAT; ++ f_pChannelStats->TdmConfig.ulSoutPcmLaw = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->TdmConfig.pulSoutBroadcastTimeslot = NULL; ++ f_pChannelStats->TdmConfig.pulSoutBroadcastStream = NULL; ++ ++ ++ /* CODEC configuration.*/ ++ f_pChannelStats->CodecConfig.ulAdpcmNibblePosition = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->CodecConfig.ulEncoderPort = cOCT6100_INVALID_STAT; ++ f_pChannelStats->CodecConfig.ulEncodingRate = cOCT6100_INVALID_STAT; ++ f_pChannelStats->CodecConfig.ulDecoderPort = cOCT6100_INVALID_STAT; ++ f_pChannelStats->CodecConfig.ulDecodingRate = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->CodecConfig.fEnableSilenceSuppression = FALSE; ++ f_pChannelStats->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_STAT; ++ f_pChannelStats->CodecConfig.ulPhase = cOCT6100_INVALID_STAT; ++ f_pChannelStats->CodecConfig.ulPhasingType = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->ulNumEchoPathChanges = cOCT6100_INVALID_STAT; ++ f_pChannelStats->ulToneDisablerStatus = cOCT6100_INVALID_STAT; ++ f_pChannelStats->fEchoCancellerConverged = FALSE; ++ f_pChannelStats->fSinVoiceDetected = FALSE; ++ f_pChannelStats->lCurrentERL = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->lCurrentERLE = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->ulCurrentEchoDelay = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->lMaxERL = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->lMaxERLE = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->ulMaxEchoDelay = cOCT6100_INVALID_STAT; ++ ++ f_pChannelStats->lRinLevel = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->lSinLevel = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->lRinAppliedGain = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->lSoutAppliedGain = cOCT6100_INVALID_SIGNED_STAT; ++ f_pChannelStats->lComfortNoiseLevel = cOCT6100_INVALID_SIGNED_STAT; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelGetStats ++UINT32 Oct6100ChannelGetStats( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_STATS f_pChannelStats ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ApiChannelGetStatsSer( f_pApiInstance, f_pChannelStats ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelMute ++ ++Description: This function mutes some or all of the ports designated by ++ ulChannelHndl. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelMute Pointer to a tPOCT6100_CHANNEL_MUTE structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelMuteDef ++UINT32 Oct6100ChannelMuteDef( ++ IN OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ) ++{ ++ f_pChannelMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pChannelMute->ulPortMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelMute ++UINT32 Oct6100ChannelMute( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelMuteSer( f_pApiInstance, f_pChannelMute ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelUnMute ++ ++Description: This function unmutes some or all of the ports designated by ++ ulChannelHndl. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelUnMute Pointer to a tPOCT6100_CHANNEL_UNMUTE structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelUnMuteDef ++UINT32 Oct6100ChannelUnMuteDef( ++ IN OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) ++{ ++ f_pChannelUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pChannelUnMute->ulPortMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChannelUnMute ++UINT32 Oct6100ChannelUnMute( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChannelUnMuteSer( f_pApiInstance, f_pChannelUnMute ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetChannelsEchoSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of the ECHO memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetChannelsEchoSwSizes ++UINT32 Oct6100ApiGetChannelsEchoSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ UINT32 ulMaxChannels; ++ ++ ulMaxChannels = f_pOpenChip->ulMaxChannels; ++ ++ if ( f_pOpenChip->fEnableChannelRecording == TRUE && ulMaxChannels != 672 ) ++ ulMaxChannels++; ++ ++ /* Determine the amount of memory required for the API echo channel list.*/ ++ f_pInstSizes->ulChannelList = ulMaxChannels * sizeof( tOCT6100_API_CHANNEL ); /* Add one for the record channel.*/ ++ f_pInstSizes->ulBiDirChannelList = f_pOpenChip->ulMaxBiDirChannels * sizeof( tOCT6100_API_BIDIR_CHANNEL ); ++ if ( ulMaxChannels > 0 ) ++ { ++ /* Calculate memory needed for ECHO memory allocation */ ++ ulResult = OctapiLlmAllocGetSize( ulMaxChannels, &f_pInstSizes->ulChannelAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_0; ++ } ++ else ++ { ++ f_pInstSizes->ulChannelAlloc = 0; ++ } ++ if ( f_pOpenChip->ulMaxBiDirChannels > 0 ) ++ { ++ /* Calculate memory needed for ECHO memory allocation */ ++ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxBiDirChannels, &f_pInstSizes->ulBiDirChannelAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_0; ++ } ++ else ++ { ++ f_pInstSizes->ulBiDirChannelAlloc = 0; ++ } ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulChannelList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulChannelAlloc, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulBiDirChannelList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulBiDirChannelAlloc, ulTempVar ) ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiChannelsEchoSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to the ECHO memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiChannelsEchoSwInit ++UINT32 Oct6100ApiChannelsEchoSwInit( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_CHANNEL pChannelsEchoList; ++ tPOCT6100_API_BIDIR_CHANNEL pBiDirChannelsList; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT16 usMaxChannels; ++ PVOID pEchoChanAlloc; ++ PVOID pBiDirChanAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of the API instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Initialize the ECHO channel API list.*/ ++ usMaxChannels = pSharedInfo->ChipConfig.usMaxChannels; ++ ++ /* add a channel to initialize if the recording is activated. */ ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ usMaxChannels++; ++ ++ /* Set all entries in the ADCPM channel list to unused. */ ++ mOCT6100_GET_CHANNEL_LIST_PNT( pSharedInfo, pChannelsEchoList ); ++ ++ /* Initialize the API ECHO channels allocation software to "all free". */ ++ if ( usMaxChannels > 0 ) ++ { ++ /* Clear the memory */ ++ Oct6100UserMemSet( pChannelsEchoList, 0x00, sizeof(tOCT6100_API_CHANNEL) * usMaxChannels ); ++ ++ mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoChanAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pEchoChanAlloc, usMaxChannels ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1; ++ } ++ ++ mOCT6100_GET_BIDIR_CHANNEL_LIST_PNT( pSharedInfo, pBiDirChannelsList ); ++ ++ if ( pSharedInfo->ChipConfig.usMaxBiDirChannels > 0 ) ++ { ++ /* Clear the memory */ ++ Oct6100UserMemSet( pBiDirChannelsList, 0x00, sizeof(tOCT6100_API_BIDIR_CHANNEL) * pSharedInfo->ChipConfig.usMaxBiDirChannels ); ++ ++ mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pBiDirChanAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pBiDirChanAlloc, pSharedInfo->ChipConfig.usMaxBiDirChannels ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A9; ++ ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelOpenSer ++ ++Description: Opens a echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelOpen Pointer to channel configuration structure. Then handle ++ identifying the buffer in all future function calls is ++ returned in this structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelOpenSer ++UINT32 Oct6100ChannelOpenSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) ++{ ++ tOCT6100_API_ECHO_CHAN_INDEX *ChannelIndexConf; ++ UINT32 ulResult; ++ ++ ChannelIndexConf = kmalloc(sizeof(*ChannelIndexConf), GFP_ATOMIC); ++ ++ if (!ChannelIndexConf) ++ return cOCT6100_ERR_FATAL_0; ++ ++ /* Check the user's configuration of the echo cancellation channel for errors. */ ++ ulResult = Oct6100ApiCheckChannelParams( f_pApiInstance, f_pChannelOpen, ChannelIndexConf ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ goto out; ++ ++ /* Reserve all resources needed by the echo cancellation channel. */ ++ ulResult = Oct6100ApiReserveChannelResources( f_pApiInstance, f_pChannelOpen, ChannelIndexConf ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ goto out; ++ ++ /* Write all necessary structures to activate the echo cancellation channel. */ ++ ulResult = Oct6100ApiWriteChannelStructs( f_pApiInstance, f_pChannelOpen, ChannelIndexConf ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ goto out; ++ ++ /* Update the new echo cancellation channels's entry in the ECHO channel list. */ ++ ulResult = Oct6100ApiUpdateChannelEntry( f_pApiInstance, f_pChannelOpen, ChannelIndexConf ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ goto out; ++ ++ kfree(ChannelIndexConf); ++ return cOCT6100_ERR_OK; ++ ++out: ++ kfree(ChannelIndexConf); ++ return ulResult; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckChannelParams ++ ++Description: Checks the user's echo cancellation channel open configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelOpen Pointer to echo cancellation channel open configuration structure. ++f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckChannelParams ++UINT32 Oct6100ApiCheckChannelParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) ++{ ++ tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; ++ tPOCT6100_CHANNEL_OPEN_VQE pVqeConfig; ++ tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; ++ UINT32 ulDecoderNumTssts; ++ UINT32 ulResult; ++ ++ /* Dereference the configuration structure for clearer code and faster access.*/ ++ pTdmConfig = &f_pChannelOpen->TdmConfig; ++ pVqeConfig = &f_pChannelOpen->VqeConfig; ++ pCodecConfig = &f_pChannelOpen->CodecConfig; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels == 0 ) ++ return cOCT6100_ERR_CHANNEL_DISABLED; ++ ++ if ( f_pChannelOpen->pulChannelHndl == NULL ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NORMAL && ++ f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_FREEZE && ++ f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET && ++ f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN && ++ f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL && ++ f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION && ++ f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE; ++ ++ /* Check the 2100Hz echo disabling configuration.*/ ++ if ( f_pChannelOpen->fEnableToneDisabler != TRUE && ++ f_pChannelOpen->fEnableToneDisabler != FALSE ) ++ return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ENABLE; ++ ++ /* Check the extended Tone Detection flag value.*/ ++ if ( f_pChannelOpen->fEnableExtToneDetection != TRUE && ++ f_pChannelOpen->fEnableExtToneDetection != FALSE ) ++ return cOCT6100_ERR_CHANNEL_ENABLE_EXT_TONE_DETECTION; ++ ++ /* Check that extented tone detection is actually enabled by the user. */ ++ if ( ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) && ++ ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableExtToneDetection == FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DISABLED; ++ ++ ++ ++ /*==============================================================================*/ ++ /* Check the TDM configuration parameters.*/ ++ ++ ulResult = Oct6100ApiCheckTdmConfig( f_pApiInstance, pTdmConfig ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Now validate the VQE parameters */ ++ ++ ulResult = Oct6100ApiCheckVqeConfig( f_pApiInstance, pVqeConfig, f_pChannelOpen->fEnableToneDisabler ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Verify if the echo operation mode selected can be applied. */ ++ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ && ( pVqeConfig->fEnableNlp == FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; ++ ++ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ++ && ( pVqeConfig->fEnableNlp == FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; ++ ++ /* Comfort noise must be activated for speech recognition mode to work. */ ++ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ++ && ( pVqeConfig->ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_OFF ) ) ++ return cOCT6100_ERR_CHANNEL_COMFORT_NOISE_REQUIRED; ++ ++ /*==============================================================================*/ ++ ++ /*==============================================================================*/ ++ /* Finally, validate the CODEC configuration.*/ ++ ++ if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ ulDecoderNumTssts = pTdmConfig->ulRinNumTssts; ++ else /* pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ++ ulDecoderNumTssts = pTdmConfig->ulSinNumTssts; ++ ++ ulResult = Oct6100ApiCheckCodecConfig( f_pApiInstance, pCodecConfig, ulDecoderNumTssts, &f_pChanIndexConf->usPhasingTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ ++ /* make sure that if silence suppression is activated, the NLP is enabled.*/ ++ if ( pCodecConfig->fEnableSilenceSuppression == TRUE && pVqeConfig->fEnableNlp == FALSE ) ++ return cOCT6100_ERR_CHANNEL_SIL_SUP_NLP_MUST_BE_ENABLED; ++ ++ /* Verify if law conversion is allowed. */ ++ if ( pCodecConfig->ulEncoderPort == cOCT6100_NO_ENCODING || ++ pCodecConfig->ulDecoderPort == cOCT6100_NO_DECODING ) ++ { ++ /* No law conversion can occurs if one ADPCM memory is not reserved.*/ ++ if ( pTdmConfig->ulRinPcmLaw != pTdmConfig->ulRoutPcmLaw ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_LAW_TRANSLATION; ++ ++ if ( pTdmConfig->ulSinPcmLaw != pTdmConfig->ulSoutPcmLaw ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_LAW_TRANSLATION; ++ } ++ ++ /* Verify if the config supports extended tone detection.*/ ++ if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) ++ { ++ if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DECODER_PORT; ++ } ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveChannelResources ++ ++Description: Reserves all resources needed for the new channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelOpen Pointer to echo cancellation channel configuration structure. ++f_pulChannelIndex Allocated entry in ECHO channel list. ++f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveChannelResources ++UINT32 Oct6100ApiReserveChannelResources( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; ++ tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; ++ ++ UINT32 ulResult; ++ UINT32 ulTempVar; ++ UINT32 ulFreeMixerEventCnt; ++ ++ BOOL fRinTsstEntry = FALSE; ++ BOOL fSinTsstEntry = FALSE; ++ BOOL fRoutTsstEntry = FALSE; ++ BOOL fSoutTsstEntry = FALSE; ++ ++ BOOL fRinRoutTsiMemEntry = FALSE; ++ BOOL fSinSoutTsiMemEntry = FALSE; ++ ++ BOOL fEchoChanEntry = FALSE; ++ ++ PUINT16 pusRinRoutConversionMemIndex = NULL; ++ PUINT16 pusSinSoutConversionMemIndex = NULL; ++ BOOL fRinRoutConversionMemEntry = FALSE; ++ BOOL fSinSoutConversionMemEntry = FALSE; ++ ++ BOOL fExtToneChanEntry = FALSE; ++ BOOL fExtToneTsiEntry = FALSE; ++ BOOL fExtToneMixerEntry = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain a local pointer to the configuration structures.*/ ++ pTdmConfig = &f_pChannelOpen->TdmConfig; ++ pCodecConfig = &f_pChannelOpen->CodecConfig; ++ ++ /*===============================================================================*/ ++ /* Reserve Echo and TSI entries. */ ++ ++ ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, ++ &f_pChanIndexConf->usEchoChanIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fEchoChanEntry = TRUE; ++ ++ /* Set the echo, encoder and decoder memory indexes.*/ ++ f_pChanIndexConf->usEchoMemIndex = f_pChanIndexConf->usEchoChanIndex; ++ ++ /* Reserve an entry for the RIN/ROUT tsi chariot memory. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ &f_pChanIndexConf->usRinRoutTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fRinRoutTsiMemEntry = TRUE; ++ ++ /* Reserve an entry for the SIN/SOUT tsi chariot memory. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ &f_pChanIndexConf->usSinSoutTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fSinSoutTsiMemEntry = TRUE; ++ ++ /* Reserve an ADPCM memory block for compression if required.*/ ++ if ( pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ pusRinRoutConversionMemIndex = &f_pChanIndexConf->usRinRoutConversionMemIndex; ++ } ++ else if ( pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ pusSinSoutConversionMemIndex = &f_pChanIndexConf->usSinSoutConversionMemIndex; ++ } ++ ++ /* Reserve an ADPCM memory block for decompression if required.*/ ++ if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ pusRinRoutConversionMemIndex = &f_pChanIndexConf->usRinRoutConversionMemIndex; ++ } ++ else if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) ++ { ++ pusSinSoutConversionMemIndex = &f_pChanIndexConf->usSinSoutConversionMemIndex; ++ } ++ ++ ++ /* Reserve the conversion memories. */ ++ if ( pusRinRoutConversionMemIndex != NULL ) ++ { ++ /* Reserve a conversion memory for the Rin/Rout stream. */ ++ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, ++ pusRinRoutConversionMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fRinRoutConversionMemEntry = TRUE; ++ } ++ } ++ else ++ { ++ /* No conversion memory reserved.*/ ++ f_pChanIndexConf->usRinRoutConversionMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ if ( ( pusSinSoutConversionMemIndex != NULL ) && ++ ( ulResult == cOCT6100_ERR_OK ) ) ++ { ++ /* Reserve a conversion memory for the Sin/Sout stream. */ ++ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, ++ pusSinSoutConversionMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fSinSoutConversionMemEntry = TRUE; ++ } ++ } ++ else ++ { ++ /* No conversion memory reserved.*/ ++ f_pChanIndexConf->usSinSoutConversionMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Reserve any resources required if the extended Tone detection is enabled.*/ ++ if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) ++ { ++ ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, ++ &f_pChanIndexConf->usExtToneChanIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fExtToneChanEntry = TRUE; ++ ++ /* Reserve an entry for the TSI chariot memory for the additionnal channel. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ &f_pChanIndexConf->usExtToneTsiIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fExtToneTsiEntry = TRUE; ++ ++ /* Reserve an entry for the TSI chariot memory for the additionnal channel. */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, ++ &f_pChanIndexConf->usExtToneMixerIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fExtToneMixerEntry = TRUE; ++ } ++ } ++ } ++ else ++ { ++ f_pChanIndexConf->usExtToneChanIndex = cOCT6100_INVALID_INDEX; ++ f_pChanIndexConf->usExtToneMixerIndex = cOCT6100_INVALID_INDEX; ++ f_pChanIndexConf->usExtToneTsiIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ else ++ { ++ /* Return an error other then a Fatal.*/ ++ ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_TSI_MEMORY; ++ } ++ } ++ else ++ { ++ /* Return an error other then a Fatal.*/ ++ ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_TSI_MEMORY; ++ } ++ } ++ ++ /*===============================================================================*/ ++ ++ /*===============================================================================*/ ++ /* Now reserve the TSST entries if required.*/ ++ ++ /* Reserve the Rin TSST entry */ ++ if ( (ulResult == cOCT6100_ERR_OK ) && ++ (pTdmConfig->ulRinTimeslot != cOCT6100_UNASSIGNED && ++ pTdmConfig->ulRinStream != cOCT6100_UNASSIGNED) ) ++ { ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pTdmConfig->ulRinTimeslot, ++ pTdmConfig->ulRinStream, ++ pTdmConfig->ulRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ &f_pChanIndexConf->usRinTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fRinTsstEntry = TRUE; ++ } ++ else ++ { ++ f_pChanIndexConf->usRinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ ++ if ( (ulResult == cOCT6100_ERR_OK ) && ++ (pTdmConfig->ulSinTimeslot != cOCT6100_UNASSIGNED && ++ pTdmConfig->ulSinStream != cOCT6100_UNASSIGNED) ) ++ { ++ /* Reserve the Sin TSST entry.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pTdmConfig->ulSinTimeslot, ++ pTdmConfig->ulSinStream, ++ pTdmConfig->ulSinNumTssts, ++ cOCT6100_INPUT_TSST, ++ &f_pChanIndexConf->usSinTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fSinTsstEntry = TRUE; ++ } ++ else ++ { ++ f_pChanIndexConf->usSinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ if ( (ulResult == cOCT6100_ERR_OK ) && ++ (pTdmConfig->ulRoutTimeslot != cOCT6100_UNASSIGNED && ++ pTdmConfig->ulRoutStream != cOCT6100_UNASSIGNED) ) ++ { ++ /* Reserve the Rout TSST entry.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pTdmConfig->ulRoutTimeslot, ++ pTdmConfig->ulRoutStream, ++ pTdmConfig->ulRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ &f_pChanIndexConf->usRoutTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fRoutTsstEntry = TRUE; ++ } ++ else ++ { ++ f_pChanIndexConf->usRoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ ++ if ( (ulResult == cOCT6100_ERR_OK ) && ++ (pTdmConfig->ulSoutTimeslot != cOCT6100_UNASSIGNED && ++ pTdmConfig->ulSoutStream != cOCT6100_UNASSIGNED) ) ++ { ++ /* Reserve the Sout TSST entry.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pTdmConfig->ulSoutTimeslot, ++ pTdmConfig->ulSoutStream, ++ pTdmConfig->ulSoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ &f_pChanIndexConf->usSoutTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fSoutTsstEntry = TRUE; ++ } ++ else ++ { ++ f_pChanIndexConf->usSoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /*===============================================================================*/ ++ ++ ++ /*===============================================================================*/ ++ /* Check if there are a couple of mixer events available for us. */ ++ ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ UINT32 ulMixerEventCntNeeded = 0; ++ ++ /* Calculate how many mixer events are needed. */ ++ if ( f_pChanIndexConf->usRinTsstIndex == cOCT6100_INVALID_INDEX ) ++ ulMixerEventCntNeeded++; ++ ++ if ( f_pChanIndexConf->usSinTsstIndex == cOCT6100_INVALID_INDEX ) ++ ulMixerEventCntNeeded++; ++ ++ /* If at least 1 mixer event is needed, check if those are available. */ ++ if ( ulMixerEventCntNeeded != 0 ) ++ { ++ ulResult = Oct6100ApiGetFreeMixerEventCnt( f_pApiInstance, &ulFreeMixerEventCnt ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* The API might need more mixer events if the ports have to be muted. */ ++ /* Check if these are available. */ ++ if ( ulFreeMixerEventCnt < ulMixerEventCntNeeded ) ++ { ++ ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_MIXER_EVENTS; ++ } ++ } ++ } ++ } ++ ++ /*===============================================================================*/ ++ ++ ++ /*===============================================================================*/ ++ /* Release the resources if something went wrong */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /*===============================================================================*/ ++ /* Release the previously reserved resources .*/ ++ if( fRinTsstEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->ulRinTimeslot, ++ pTdmConfig->ulRinStream, ++ pTdmConfig->ulRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fSinTsstEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->ulSinTimeslot, ++ pTdmConfig->ulSinStream, ++ pTdmConfig->ulSinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fRoutTsstEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->ulRoutTimeslot, ++ pTdmConfig->ulRoutStream, ++ pTdmConfig->ulRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fSoutTsstEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->ulSoutTimeslot, ++ pTdmConfig->ulSoutStream, ++ pTdmConfig->ulSoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fRinRoutTsiMemEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, ++ f_pChanIndexConf->usRinRoutTsiMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fSinSoutTsiMemEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, ++ f_pChanIndexConf->usSinSoutTsiMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /*===============================================================================*/ ++ ++ /*===============================================================================*/ ++ /* Release the previously reserved echo resources .*/ ++ if( fEchoChanEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseEchoEntry( f_pApiInstance, ++ f_pChanIndexConf->usEchoChanIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /*===============================================================================*/ ++ ++ /*===============================================================================*/ ++ /* Release the previously reserved resources for the extended tone detection.*/ ++ if( fExtToneChanEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseEchoEntry( f_pApiInstance, ++ f_pChanIndexConf->usExtToneChanIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fExtToneTsiEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, ++ f_pChanIndexConf->usExtToneTsiIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fExtToneMixerEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, ++ f_pChanIndexConf->usExtToneMixerIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ /*===============================================================================*/ ++ ++ /*===============================================================================*/ ++ /* Release the conversion resources. */ ++ if( fRinRoutConversionMemEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, ++ f_pChanIndexConf->usRinRoutConversionMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fSinSoutConversionMemEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, ++ f_pChanIndexConf->usSinSoutConversionMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /*===============================================================================*/ ++ ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteChannelStructs ++ ++Description: Performs all the required structure writes to configure the ++ new echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelOpen Pointer to echo cancellation channel configuration structure. ++f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteChannelStructs ++UINT32 Oct6100ApiWriteChannelStructs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulResult; ++ UINT32 ulDwordAddress; ++ UINT32 ulDwordData; ++ BOOL fConversionEnabled = FALSE; ++ BOOL fProgramAdpcmMem; ++ UINT32 ulCompType = 0; ++ UINT32 ulPcmLaw; ++ UINT16 usTempTsiMemIndex; ++ UINT16 usConversionMemIndex; ++ UINT32 ulToneEventNumber; ++ BOOL fSSTone; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain a local pointer to the TDM configuration structure.*/ ++ pTdmConfig = &f_pChannelOpen->TdmConfig; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_pChanIndexConf->usEchoChanIndex ); ++ ++ /*==============================================================================*/ ++ /* Configure the Input Tsst control memory.*/ ++ ++ /* Set the RIN Tsst control entry.*/ ++ if ( f_pChanIndexConf->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_pChanIndexConf->usRinTsstIndex, ++ f_pChanIndexConf->usRinRoutTsiMemIndex, ++ pTdmConfig->ulRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Set the SIN Tsst control entry.*/ ++ if ( f_pChanIndexConf->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_pChanIndexConf->usSinTsstIndex, ++ f_pChanIndexConf->usSinSoutTsiMemIndex, ++ pTdmConfig->ulSinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*==============================================================================*/ ++ ++ /*==============================================================================*/ ++ /* Configure the ADPCM control memory for the Decoder.*/ ++ ++ /* Set the codec state flags.*/ ++ f_pChanIndexConf->fRinRoutCodecActive = FALSE; ++ f_pChanIndexConf->fSinSoutCodecActive = FALSE; ++ ++ if ( f_pChannelOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING ) ++ { ++ fProgramAdpcmMem = TRUE; ++ ++ switch( f_pChannelOpen->CodecConfig.ulDecodingRate ) ++ { ++ case cOCT6100_G711_64KBPS: ++ ulCompType = 0x8; ++ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ if ( pTdmConfig->ulRinPcmLaw == pTdmConfig->ulRoutPcmLaw ) ++ fProgramAdpcmMem = FALSE; ++ ++ /* Check if both ports are assigned. If not, no law conversion needed here.. */ ++ if ( ( pTdmConfig->ulRinStream == cOCT6100_UNASSIGNED ) ++ || ( pTdmConfig->ulRoutStream == cOCT6100_UNASSIGNED ) ) ++ fProgramAdpcmMem = FALSE; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ++ { ++ if ( pTdmConfig->ulSinPcmLaw == pTdmConfig->ulSoutPcmLaw ) ++ fProgramAdpcmMem = FALSE; ++ ++ if ( ( pTdmConfig->ulSinStream == cOCT6100_UNASSIGNED ) ++ || ( pTdmConfig->ulSoutStream == cOCT6100_UNASSIGNED ) ) ++ fProgramAdpcmMem = FALSE; ++ } ++ break; ++ case cOCT6100_G726_40KBPS: ++ ulCompType = 0x3; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_32KBPS: ++ ulCompType = 0x2; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_24KBPS: ++ ulCompType = 0x1; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_16KBPS: ++ ulCompType = 0x0; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_2C_ENCODED: ++ ulCompType = 0x4; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_3C_ENCODED: ++ ulCompType = 0x5; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_4C_ENCODED: ++ ulCompType = 0x6; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_ENCODED: ++ ulCompType = 0x9; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G726_ENCODED: ++ ulCompType = 0xA; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G727_2C_ENCODED: ++ ulCompType = 0xC; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G727_3C_ENCODED: ++ ulCompType = 0xD; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G727_4C_ENCODED: ++ ulCompType = 0xE; ++ fConversionEnabled = TRUE; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_D4; ++ } ++ ++ if ( fProgramAdpcmMem == TRUE ) ++ { ++ /* Set the chariot memory based on the selected port.*/ ++ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ usTempTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; ++ ulPcmLaw = pTdmConfig->ulRoutPcmLaw; /* Set the law for later use */ ++ ++ /* Set the codec state flags.*/ ++ f_pChanIndexConf->fRinRoutCodecActive = TRUE; ++ ++ /* Set the conversion memory index to use for decompression */ ++ usConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ++ { ++ usTempTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; ++ ulPcmLaw = pTdmConfig->ulSoutPcmLaw; /* Set the law for later use */ ++ ++ /* Set the codec state flags.*/ ++ f_pChanIndexConf->fSinSoutCodecActive = TRUE; ++ ++ /* Set the conversion memory index to use for decompression */ ++ usConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; ++ } ++ ++ ulResult = Oct6100ApiWriteDecoderMemory( f_pApiInstance, ++ usConversionMemIndex, ++ ulCompType, ++ usTempTsiMemIndex, ++ ulPcmLaw, ++ f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Configure the ADPCM control memory for the Encoder */ ++ ++ if ( f_pChannelOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING ) ++ { ++ fProgramAdpcmMem = TRUE; ++ ++ switch( f_pChannelOpen->CodecConfig.ulEncodingRate ) ++ { ++ case cOCT6100_G711_64KBPS: ++ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ if ( pTdmConfig->ulRoutPcmLaw == cOCT6100_PCM_U_LAW ) ++ ulCompType = 0x4; ++ else ++ ulCompType = 0x5; ++ ++ /* Check for law conversion.*/ ++ if ( pTdmConfig->ulRinPcmLaw == pTdmConfig->ulRoutPcmLaw ) ++ fProgramAdpcmMem = FALSE; ++ ++ /* Check if both ports are assigned. If not, no law conversion needed here.. */ ++ if ( ( pTdmConfig->ulRinStream == cOCT6100_UNASSIGNED ) ++ || ( pTdmConfig->ulRoutStream == cOCT6100_UNASSIGNED ) ) ++ fProgramAdpcmMem = FALSE; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ if ( pTdmConfig->ulSoutPcmLaw == cOCT6100_PCM_U_LAW ) ++ ulCompType = 0x4; ++ else ++ ulCompType = 0x5; ++ ++ /* Check for law conversion.*/ ++ if ( pTdmConfig->ulSinPcmLaw == pTdmConfig->ulSoutPcmLaw ) ++ fProgramAdpcmMem = FALSE; ++ ++ /* Check if both ports are assigned. If not, no law conversion needed here.. */ ++ if ( ( pTdmConfig->ulSinStream == cOCT6100_UNASSIGNED ) ++ || ( pTdmConfig->ulSoutStream == cOCT6100_UNASSIGNED ) ) ++ fProgramAdpcmMem = FALSE; ++ } ++ ++ break; ++ case cOCT6100_G726_40KBPS: ++ ulCompType = 0x3; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_32KBPS: ++ ulCompType = 0x2; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_24KBPS: ++ ulCompType = 0x1; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_16KBPS: ++ ulCompType = 0x0; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_40KBPS_4_1: ++ ulCompType = 0xD; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_40KBPS_3_2: ++ ulCompType = 0xA; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_40KBPS_2_3: ++ ulCompType = 0x6; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_32KBPS_4_0: ++ ulCompType = 0xE; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_32KBPS_3_1: ++ ulCompType = 0xB; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_32KBPS_2_2: ++ ulCompType = 0x7; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_24KBPS_3_0: ++ ulCompType = 0xC; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_24KBPS_2_1: ++ ulCompType = 0x8; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_16KBPS_2_0: ++ ulCompType = 0x9; ++ fConversionEnabled = TRUE; ++ break; ++ ++ default: ++ return cOCT6100_ERR_FATAL_D5; ++ } ++ ++ /* Program the APDCM memory only if ADPCM is requried.*/ ++ if ( fProgramAdpcmMem == TRUE || f_pChanIndexConf->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Set the chariot memory based on the selected port.*/ ++ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ usTempTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; ++ ++ /* Set the codec state flags.*/ ++ f_pChanIndexConf->fRinRoutCodecActive = TRUE; ++ ++ /* Set the conversion memory index to use for compression */ ++ usConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; ++ } ++ ++ else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ usTempTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; ++ ++ /* Set the codec state flags.*/ ++ f_pChanIndexConf->fSinSoutCodecActive = TRUE; ++ ++ /* Set the conversion memory index to use for compression */ ++ usConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; ++ } ++ ++ ulResult = Oct6100ApiWriteEncoderMemory( f_pApiInstance, ++ usConversionMemIndex, ++ ulCompType, ++ usTempTsiMemIndex, ++ f_pChannelOpen->CodecConfig.fEnableSilenceSuppression, ++ f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, ++ f_pChanIndexConf->usPhasingTsstIndex, ++ f_pChannelOpen->CodecConfig.ulPhasingType, ++ f_pChannelOpen->CodecConfig.ulPhase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Clearing the tone events bit vector */ ++ ++ ulDwordAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_pChanIndexConf->usEchoChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ulDwordAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ++ ulDwordData = 0x00000000; ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulDwordAddress += 4; ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Write the VQE memory */ ++ ++ ulResult = Oct6100ApiWriteVqeMemory( f_pApiInstance, ++ &f_pChannelOpen->VqeConfig, ++ f_pChannelOpen, ++ f_pChanIndexConf->usEchoChanIndex, ++ f_pChanIndexConf->usEchoMemIndex, ++ TRUE, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ /*==============================================================================*/ ++ /* Write the echo memory */ ++ ++ ulResult = Oct6100ApiWriteEchoMemory( f_pApiInstance, ++ pTdmConfig, ++ f_pChannelOpen, ++ f_pChanIndexConf->usEchoMemIndex, ++ f_pChanIndexConf->usRinRoutTsiMemIndex, ++ f_pChanIndexConf->usSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ ++ /*==============================================================================*/ ++ /* Mute channel if required, this is done on a port basis */ ++ ++ /* Initialize the silence indexes to invalid for now. */ ++ pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Set the TSI memory indexes. */ ++ pChanEntry->usRinRoutTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; ++ pChanEntry->usSinSoutTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, ++ f_pChanIndexConf->usEchoChanIndex, ++ f_pChanIndexConf->usRinTsstIndex, ++ f_pChanIndexConf->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Set the dominant speaker to unassigned, if required. */ ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled == TRUE ) ++ { ++ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_pChanIndexConf->usEchoChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* If necessary, configure the extended tone detection channel.*/ ++ ++ if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) ++ { ++ UINT32 ulTempSinLaw; ++ UINT32 ulTempSoutLaw; ++ UINT32 ulTempEchoOpMode; ++ ++ /* save the original law.*/ ++ ulTempSinLaw = pTdmConfig->ulSinPcmLaw; ++ ulTempSoutLaw = pTdmConfig->ulSoutPcmLaw; ++ ulTempEchoOpMode = f_pChannelOpen->ulEchoOperationMode; ++ ++ /* Now, make sure the Sin and Sout law are the same as the Rin law.*/ ++ ++ pTdmConfig->ulSinPcmLaw = pTdmConfig->ulRinPcmLaw; ++ pTdmConfig->ulSoutPcmLaw = pTdmConfig->ulRinPcmLaw; ++ ++ f_pChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_NORMAL; ++ ++ /* Write the Echo and VQE memory of the extended channel.*/ ++ ++ ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, ++ pTdmConfig, ++ &f_pChannelOpen->VqeConfig, ++ f_pChannelOpen, ++ f_pChanIndexConf->usExtToneChanIndex, ++ f_pChanIndexConf->usExtToneChanIndex, ++ cOCT6100_API_EXT_TONE_EXTRA_TSI, ++ f_pChanIndexConf->usExtToneTsiIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now, write the mixer event used to copy the RIN signal of the original channel ++ into the SIN signal of the exteded channel. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_pChanIndexConf->usExtToneMixerIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= f_pChanIndexConf->usRinRoutTsiMemIndex; ++ WriteParams.usWriteData |= pTdmConfig->ulRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = f_pChanIndexConf->usExtToneTsiIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Now insert the Sin copy event into the list.*/ ++ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_pChanIndexConf->usExtToneMixerIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY, ++ f_pChanIndexConf->usEchoChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*=======================================================================*/ ++ ++ /*==============================================================================*/ ++ /* Clearing the tone events bit vector */ ++ ++ ulDwordAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_pChanIndexConf->usExtToneChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ulDwordAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ++ ulDwordData = 0x00000000; ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulDwordAddress += 4; ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ /* Write back the original values in the channel open structure.*/ ++ ++ pTdmConfig->ulSinPcmLaw = ulTempSinLaw; ++ pTdmConfig->ulSoutPcmLaw = ulTempSoutLaw; ++ ++ f_pChannelOpen->ulEchoOperationMode = ulTempEchoOpMode; ++ } ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* If necessary, configure the SS tone detection. */ ++ ++ for ( ulToneEventNumber = 0; ulToneEventNumber < cOCT6100_MAX_TONE_EVENT; ulToneEventNumber++ ) ++ { ++ /* Check if the current tone is a SS tone. */ ++ ulResult = Oct6100ApiIsSSTone( ++ f_pApiInstance, ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID, ++ &fSSTone ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( fSSTone == TRUE ) ++ { ++ /* Write to all resources needed to activate tone detection on this SS tone. */ ++ ulResult = Oct6100ApiWriteToneDetectEvent( ++ f_pApiInstance, ++ f_pChanIndexConf->usEchoChanIndex, ++ ulToneEventNumber, ++ ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Configure the Output Tsst control memory.*/ ++ ++ /* Set the ROUT Tsst control entry.*/ ++ if ( f_pChanIndexConf->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_pChanIndexConf->usRoutTsstIndex, ++ f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, ++ pTdmConfig->ulRoutNumTssts, ++ f_pChanIndexConf->usRinRoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Set the SOUT Tsst control entry.*/ ++ if ( f_pChanIndexConf->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_pChanIndexConf->usSoutTsstIndex, ++ f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, ++ pTdmConfig->ulSoutNumTssts, ++ f_pChanIndexConf->usSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateChannelEntry ++ ++Description: Updates the new channel in the ECHO channel list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelOpen Pointer to echo cancellation channel configuration structure. ++f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateChannelEntry ++UINT32 Oct6100ApiUpdateChannelEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; ++ tPOCT6100_CHANNEL_OPEN_VQE pVqeConfig; ++ tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; ++ ++ /* Obtain a pointer to the config structures of the tPOCT6100_CHANNEL_OPEN structure. */ ++ pTdmConfig = &f_pChannelOpen->TdmConfig; ++ pVqeConfig = &f_pChannelOpen->VqeConfig; ++ pCodecConfig = &f_pChannelOpen->CodecConfig; ++ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_pChanIndexConf->usEchoChanIndex ) ++ ++ /*=======================================================================*/ ++ /* Copy the channel's configuration and allocated resources. */ ++ pChanEntry->ulUserChanId = f_pChannelOpen->ulUserChanId; ++ pChanEntry->byEchoOperationMode = (UINT8)( f_pChannelOpen->ulEchoOperationMode & 0xFF ); ++ pChanEntry->fEnableToneDisabler = (UINT8)( f_pChannelOpen->fEnableToneDisabler & 0xFF ); ++ pChanEntry->fEnableExtToneDetection = (UINT8)( f_pChannelOpen->fEnableExtToneDetection & 0xFF ); ++ ++ /* Save the VQE configuration.*/ ++ pChanEntry->VqeConfig.byComfortNoiseMode = (UINT8)( pVqeConfig->ulComfortNoiseMode & 0xFF ); ++ pChanEntry->VqeConfig.fEnableNlp = (UINT8)( pVqeConfig->fEnableNlp & 0xFF ); ++ pChanEntry->VqeConfig.fEnableTailDisplacement = (UINT8)( pVqeConfig->fEnableTailDisplacement ); ++ pChanEntry->VqeConfig.usTailDisplacement = (UINT16)( pVqeConfig->ulTailDisplacement & 0xFFFF ); ++ pChanEntry->VqeConfig.usTailLength = (UINT16)( pVqeConfig->ulTailLength & 0xFFFF ); ++ ++ pChanEntry->VqeConfig.fSinDcOffsetRemoval = (UINT8)( pVqeConfig->fSinDcOffsetRemoval & 0xFF ); ++ pChanEntry->VqeConfig.fRinDcOffsetRemoval = (UINT8)( pVqeConfig->fRinDcOffsetRemoval & 0xFF ); ++ pChanEntry->VqeConfig.fRinLevelControl = (UINT8)( pVqeConfig->fRinLevelControl & 0xFF ); ++ pChanEntry->VqeConfig.chRinLevelControlGainDb = (OCT_INT8)( pVqeConfig->lRinLevelControlGainDb & 0xFF ); ++ pChanEntry->VqeConfig.fSoutLevelControl = (UINT8)( pVqeConfig->fSoutLevelControl & 0xFF ); ++ pChanEntry->VqeConfig.chSoutLevelControlGainDb = (OCT_INT8)( pVqeConfig->lSoutLevelControlGainDb & 0xFF ); ++ pChanEntry->VqeConfig.fRinAutomaticLevelControl = (UINT8)( pVqeConfig->fRinAutomaticLevelControl & 0xFF ); ++ pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb = (OCT_INT8)( pVqeConfig->lRinAutomaticLevelControlTargetDb & 0xFF ); ++ pChanEntry->VqeConfig.fSoutAutomaticLevelControl = (UINT8)( pVqeConfig->fSoutAutomaticLevelControl & 0xFF ); ++ pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb = (OCT_INT8)( pVqeConfig->lSoutAutomaticLevelControlTargetDb & 0xFF ); ++ pChanEntry->VqeConfig.fRinHighLevelCompensation = (UINT8)( pVqeConfig->fRinHighLevelCompensation & 0xFF ); ++ pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb = (OCT_INT8)( pVqeConfig->lRinHighLevelCompensationThresholdDb & 0xFF ); ++ pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction = (UINT8)( pVqeConfig->fSoutAdaptiveNoiseReduction & 0xFF ); ++ pChanEntry->VqeConfig.fSoutNoiseBleaching = (UINT8)( pVqeConfig->fSoutNoiseBleaching & 0xFF ); ++ pChanEntry->VqeConfig.fSoutConferencingNoiseReduction = (UINT8)( pVqeConfig->fSoutConferencingNoiseReduction & 0xFF ); ++ ++ pChanEntry->VqeConfig.fAcousticEcho = (UINT8)( pVqeConfig->fAcousticEcho & 0xFF ); ++ ++ pChanEntry->VqeConfig.fDtmfToneRemoval = (UINT8)( pVqeConfig->fDtmfToneRemoval & 0xFF ); ++ ++ pChanEntry->VqeConfig.chDefaultErlDb = (OCT_INT8)( pVqeConfig->lDefaultErlDb & 0xFF ); ++ pChanEntry->VqeConfig.chAecDefaultErlDb = (OCT_INT8)( pVqeConfig->lAecDefaultErlDb & 0xFF ); ++ pChanEntry->VqeConfig.usAecTailLength = (UINT16)( pVqeConfig->ulAecTailLength & 0xFFFF ); ++ pChanEntry->VqeConfig.byNonLinearityBehaviorA = (UINT8)( pVqeConfig->ulNonLinearityBehaviorA & 0xFF ); ++ pChanEntry->VqeConfig.byNonLinearityBehaviorB = (UINT8)( pVqeConfig->ulNonLinearityBehaviorB & 0xFF ); ++ pChanEntry->VqeConfig.byDoubleTalkBehavior = (UINT8)( pVqeConfig->ulDoubleTalkBehavior & 0xFF ); ++ pChanEntry->VqeConfig.chAnrSnrEnhancementDb = (OCT_INT8)( pVqeConfig->lAnrSnrEnhancementDb & 0xFF ); ++ pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation = (UINT8)( pVqeConfig->ulAnrVoiceNoiseSegregation & 0xFF ); ++ pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay = (UINT16)( pVqeConfig->ulToneDisablerVqeActivationDelay & 0xFFFF ); ++ ++ pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb = (UINT8)( pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb & 0xFF ); ++ pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb = (UINT8)( pVqeConfig->ulSoutNaturalListenerEnhancementGainDb & 0xFF ); ++ pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement = (UINT8)( pVqeConfig->fSoutNaturalListenerEnhancement & 0xFF ); ++ pChanEntry->VqeConfig.fRoutNoiseReduction = (UINT8)( pVqeConfig->fRoutNoiseReduction & 0xFF ); ++ pChanEntry->VqeConfig.chRoutNoiseReductionLevelGainDb = (OCT_INT8) (pVqeConfig->lRoutNoiseReductionLevelGainDb & 0xFF); ++ pChanEntry->VqeConfig.fEnableMusicProtection = (UINT8)( pVqeConfig->fEnableMusicProtection & 0xFF ); ++ pChanEntry->VqeConfig.fIdleCodeDetection = (UINT8)( pVqeConfig->fIdleCodeDetection & 0xFF ); ++ ++ /* Save the codec information.*/ ++ pChanEntry->CodecConfig.byAdpcmNibblePosition = (UINT8)( pCodecConfig->ulAdpcmNibblePosition & 0xFF ); ++ ++ pChanEntry->CodecConfig.byDecoderPort = (UINT8)( pCodecConfig->ulDecoderPort & 0xFF ); ++ pChanEntry->CodecConfig.byDecodingRate = (UINT8)( pCodecConfig->ulDecodingRate & 0xFF ); ++ pChanEntry->CodecConfig.byEncoderPort = (UINT8)( pCodecConfig->ulEncoderPort & 0xFF ); ++ pChanEntry->CodecConfig.byEncodingRate = (UINT8)( pCodecConfig->ulEncodingRate & 0xFF ); ++ ++ pChanEntry->CodecConfig.fEnableSilenceSuppression = (UINT8)( pCodecConfig->fEnableSilenceSuppression & 0xFF ); ++ pChanEntry->CodecConfig.byPhase = (UINT8)( pCodecConfig->ulPhase & 0xFF ); ++ pChanEntry->CodecConfig.byPhasingType = (UINT8)( pCodecConfig->ulPhasingType & 0xFF ); ++ ++ /* Save the RIN settings.*/ ++ pChanEntry->TdmConfig.byRinPcmLaw = (UINT8)( pTdmConfig->ulRinPcmLaw & 0xFF ); ++ pChanEntry->TdmConfig.usRinTimeslot = (UINT16)( pTdmConfig->ulRinTimeslot & 0xFFFF ); ++ pChanEntry->TdmConfig.usRinStream = (UINT16)( pTdmConfig->ulRinStream & 0xFFFF ); ++ ++ /* Save the SIN settings.*/ ++ pChanEntry->TdmConfig.bySinPcmLaw = (UINT8)( pTdmConfig->ulSinPcmLaw & 0xFF ); ++ pChanEntry->TdmConfig.usSinTimeslot = (UINT16)( pTdmConfig->ulSinTimeslot & 0xFFFF ); ++ pChanEntry->TdmConfig.usSinStream = (UINT16)( pTdmConfig->ulSinStream & 0xFFFF ); ++ ++ /* Save the ROUT settings.*/ ++ pChanEntry->TdmConfig.byRoutPcmLaw = (UINT8)( pTdmConfig->ulRoutPcmLaw & 0xFF ); ++ pChanEntry->TdmConfig.usRoutTimeslot = (UINT16)( pTdmConfig->ulRoutTimeslot & 0xFFFF ); ++ pChanEntry->TdmConfig.usRoutStream = (UINT16)( pTdmConfig->ulRoutStream & 0xFFFF ); ++ ++ pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; ++ pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry = 0; ++ ++ /* Save the SOUT settings.*/ ++ pChanEntry->TdmConfig.bySoutPcmLaw = (UINT8)( pTdmConfig->ulSoutPcmLaw & 0xFF ); ++ pChanEntry->TdmConfig.usSoutTimeslot = (UINT16)( pTdmConfig->ulSoutTimeslot & 0xFFFF ); ++ pChanEntry->TdmConfig.usSoutStream = (UINT16)( pTdmConfig->ulSoutStream & 0xFFFF ); ++ ++ pChanEntry->TdmConfig.byRinNumTssts = (UINT8)( pTdmConfig->ulRinNumTssts & 0xFF ); ++ pChanEntry->TdmConfig.bySinNumTssts = (UINT8)( pTdmConfig->ulSinNumTssts & 0xFF ); ++ pChanEntry->TdmConfig.byRoutNumTssts = (UINT8)( pTdmConfig->ulRoutNumTssts & 0xFF ); ++ pChanEntry->TdmConfig.bySoutNumTssts = (UINT8)( pTdmConfig->ulSoutNumTssts & 0xFF ); ++ pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; ++ pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry = 0; ++ ++ /* Save the extended Tone detection information.*/ ++ pChanEntry->usExtToneChanIndex = f_pChanIndexConf->usExtToneChanIndex; ++ pChanEntry->usExtToneMixerIndex = f_pChanIndexConf->usExtToneMixerIndex; ++ pChanEntry->usExtToneTsiIndex = f_pChanIndexConf->usExtToneTsiIndex; ++ ++ if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) ++ { ++ tPOCT6100_API_CHANNEL pExtToneChanEntry; ++ ++ /* Set the mode of the original channel. He is the channel performing detection on the ++ SIN port. The extended channel will perform detection on the RIN port.*/ ++ pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_SIN_PORT_MODE; ++ ++ /* Now, program the associated channel.*/ ++ ++ /* Obtain a pointer to the extended tone detection channel entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pExtToneChanEntry, f_pChanIndexConf->usExtToneChanIndex ); ++ ++ pExtToneChanEntry->fReserved = TRUE; ++ pExtToneChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_RIN_PORT_MODE; /* Detect on RIN port.*/ ++ pExtToneChanEntry->usExtToneChanIndex = f_pChanIndexConf->usEchoChanIndex; ++ ++ pExtToneChanEntry->aulToneConf[ 0 ] = 0; ++ pExtToneChanEntry->aulToneConf[ 1 ] = 0; ++ ++ } ++ else ++ { ++ /* No extended tone detection supported.*/ ++ pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_DISABLED; ++ } ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Store hardware related information.*/ ++ pChanEntry->usRinRoutTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; ++ pChanEntry->usSinSoutTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; ++ pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ pChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ ++ /* We are not being tapped for now. */ ++ pChanEntry->fBeingTapped = FALSE; ++ ++ pChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; ++ pChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; ++ ++ /* The copy event has not yet been created. */ ++ pChanEntry->fCopyEventCreated = FALSE; ++ ++ pChanEntry->usRinRoutConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; ++ pChanEntry->usSinSoutConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; ++ ++ pChanEntry->usPhasingTsstIndex = f_pChanIndexConf->usPhasingTsstIndex; ++ ++ pChanEntry->fSinSoutCodecActive = f_pChanIndexConf->fSinSoutCodecActive; ++ pChanEntry->fRinRoutCodecActive = f_pChanIndexConf->fRinRoutCodecActive; ++ ++ ++ ++ pChanEntry->usEchoMemIndex = f_pChanIndexConf->usEchoMemIndex; ++ ++ pChanEntry->usRinTsstIndex = f_pChanIndexConf->usRinTsstIndex; ++ pChanEntry->usSinTsstIndex = f_pChanIndexConf->usSinTsstIndex; ++ pChanEntry->usRoutTsstIndex = f_pChanIndexConf->usRoutTsstIndex; ++ pChanEntry->usSoutTsstIndex = f_pChanIndexConf->usSoutTsstIndex; ++ ++ pChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ pChanEntry->usSoutCopyEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Nothing muted for now. */ ++ pChanEntry->usMutedPorts = cOCT6100_CHANNEL_MUTE_PORT_NONE; ++ ++ /* Set all the GW feature initial value.*/ ++ /* Bridge info */ ++ pChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; ++ pChanEntry->fMute = FALSE; ++ ++ pChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; ++ pChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Buffer playout info.*/ ++ pChanEntry->fRinBufPlaying = FALSE; ++ pChanEntry->fSoutBufPlaying = FALSE; ++ ++ /* Tone detection state. */ ++ /* This array is configured as follow.*/ ++ /* Index 0 contain event 0 to 31 (msb = event 31) and Index 1 contain index 32 - 55 */ ++ pChanEntry->aulToneConf[ 0 ] = 0; ++ pChanEntry->aulToneConf[ 1 ] = 0; ++ pChanEntry->ulLastSSToneDetected = (PTR_TYPE)cOCT6100_INVALID_VALUE; ++ pChanEntry->ulLastSSToneTimestamp = (PTR_TYPE)cOCT6100_INVALID_VALUE; ++ ++ /* Initialize the bidirectional flag.*/ ++ pChanEntry->fBiDirChannel = FALSE; ++ ++ /*=======================================================================*/ ++ /* Init some of the stats.*/ ++ ++ pChanEntry->sMaxERL = cOCT6100_INVALID_SIGNED_STAT_W; ++ pChanEntry->sMaxERLE = cOCT6100_INVALID_SIGNED_STAT_W; ++ pChanEntry->usMaxEchoDelay = cOCT6100_INVALID_STAT_W; ++ pChanEntry->usNumEchoPathChangesOfst = 0; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Update the dependency of the phasing TSST if one is associated to the chanel.*/ ++ ++ if ( f_pChanIndexConf->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ tPOCT6100_API_PHASING_TSST pPhasingEntry; ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, f_pChanIndexConf->usPhasingTsstIndex ); ++ ++ pPhasingEntry->usDependencyCnt++; ++ } ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ ++ /* Form handle returned to user. */ ++ *f_pChannelOpen->pulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_pChanIndexConf->usEchoChanIndex; ++ ++ /* Finally, mark the channel as open. */ ++ pChanEntry->fReserved = TRUE; ++ pChanEntry->usExtraSinTsiDependencyCnt = 0; ++ ++ /* Increment the number of channel open.*/ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels++; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelCloseSer ++ ++Description: Closes a echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelClose Pointer to echo cancellation channel close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelCloseSer ++UINT32 Oct6100ChannelCloseSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose ) ++{ ++ UINT16 usChannelIndex; ++ ++ ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertChannelParams( f_pApiInstance, ++ f_pChannelClose, ++ ++ &usChannelIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the echo cancellation channel. */ ++ ulResult = Oct6100ApiInvalidateChannelStructs( f_pApiInstance, ++ ++ usChannelIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the echo cancellation channel. */ ++ ulResult = Oct6100ApiReleaseChannelResources( f_pApiInstance, usChannelIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Invalidate the handle.*/ ++ f_pChannelClose->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertChannelParams ++ ++Description: Validate the handle given by the user and verify the state of ++ the channel about to be closed. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelClose Pointer to echo cancellation channel close structure. ++f_pulFpgaChanIndex Pointer to the FPGA channel index associated to this channel. ++f_pusChanIndex Pointer to the index of the channel within the API instance. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertChannelParams ++UINT32 Oct6100ApiAssertChannelParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose, ++ ++ IN OUT PUINT16 f_pusChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pChannelClose->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ *f_pusChanIndex = (UINT16)( f_pChannelClose->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelClose->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ if ( pChanEntry->fBiDirChannel == TRUE ) ++ return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; ++ ++ /*=======================================================================*/ ++ ++ /* Check if the channel is bound to a bridge. */ ++ if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_ACTIVE_DEPENDENCIES; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidateChannelStructs ++ ++Description: Closes a echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulFpgaChanIndex Index of the channel within the SCN_PLC FPGA. ++f_usChanIndex Index of the channel within the API instance. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidateChannelStructs ++UINT32 Oct6100ApiInvalidateChannelStructs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ IN UINT16 f_usChanIndex ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_CHANNEL_TDM pTdmConfig; ++ tPOCT6100_API_TSST_ENTRY pTsstEntry; ++ tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_WRITE_SMEAR_PARAMS SmearParams; ++ UINT32 ulResult; ++ UINT16 usCurrentEntry; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ /* Obtain local pointer to the TDM configuration of the channel */ ++ pTdmConfig = &pChanEntry->TdmConfig; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ SmearParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ SmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* If this channel is currently debugged, automatically close the debug channel. */ ++ if ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ && ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex == f_usChanIndex ) ) ++ { ++ tOCT6100_DEBUG_SELECT_CHANNEL SelectDebugChan; ++ ++ /* Ensure forward compatibility. */ ++ Oct6100DebugSelectChannelDef( &SelectDebugChan ); ++ ++ /* Set the hot channel to an invalid handle to disable recording. */ ++ SelectDebugChan.ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ /* Call the serialized fonction. */ ++ ulResult = Oct6100DebugSelectChannelSer( f_pApiInstance, &SelectDebugChan, FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Deactivate the TSST control memory if used. */ ++ ++ /* RIN port.*/ ++ if ( pTdmConfig->usRinTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Deactivate the TSST entry.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usRinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* SIN port.*/ ++ if ( pTdmConfig->usSinTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Deactivate the TSST entry.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usSinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ /* ROUT port.*/ ++ ++ if ( pTdmConfig->usRoutTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Deactivate the TSST entry.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usRoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Now the broadcast TSST.*/ ++ usCurrentEntry = pTdmConfig->usRoutBrdcastTsstFirstEntry; ++ while( usCurrentEntry != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ /* Deactivate the TSST entry.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pTsstEntry->usTsstMemoryIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move to the next entry.*/ ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ } ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* SOUT port.*/ ++ ++ if ( pTdmConfig->usSoutTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Deactivate the TSST entry.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usSoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Now the broadcast TSST.*/ ++ usCurrentEntry = pTdmConfig->usSoutBrdcastTsstFirstEntry; ++ while( usCurrentEntry != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ /* Deactivate the TSST entry.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pTsstEntry->usTsstMemoryIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move to the next entry.*/ ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ } ++ /*=======================================================================*/ ++ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Deactivate the ECHO control memory entry.*/ ++ ++ /* Set the input Echo control entry to unused.*/ ++ WriteParams.ulWriteAddress = cOCT6100_ECHO_CONTROL_MEM_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x85FF; /* TSI index 1535 reserved for power-down mode */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = 0xC5FF; /* TSI index 1535 reserved for power-down mode */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*------------------------------------------------------------------------------*/ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Deactivate the conversion control memories if used. */ ++ ++ if ( pChanEntry->usRinRoutConversionMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Rin/Rout stream conversion memory was used */ ++ ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, pChanEntry->usRinRoutConversionMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pChanEntry->usSinSoutConversionMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Sin/Sout stream conversion memory was used */ ++ ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, pChanEntry->usSinSoutConversionMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Clear the silence copy events if they were created. */ ++ ++ /* Unmute the Rin port if it was muted. */ ++ if ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_DF; ++ ++ pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Unmute the Sin port if it was muted. */ ++ if ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pChanEntry->usSinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usSinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_E0; ++ ++ pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ /* Synch all the buffer playout field.*/ ++ if ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE ) ++ { ++ Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); ++ ++ BufferPlayoutStop.ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ BufferPlayoutStop.fStopCleanly = FALSE; ++ ++ BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ++ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( ++ f_pApiInstance, ++ &BufferPlayoutStop, ++ f_usChanIndex, ++ pChanEntry->usEchoMemIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; ++ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( ++ f_pApiInstance, ++ &BufferPlayoutStop, ++ f_usChanIndex, ++ pChanEntry->usEchoMemIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ ++ ++ ++ ++ /* Free all resources reserved for extended tone detection.*/ ++ if ( pChanEntry->fEnableExtToneDetection == TRUE ) ++ { ++ /*------------------------------------------------------------------------------*/ ++ /* Deactivate the ECHO control memory entry of the extended channel.*/ ++ ++ /* Set the input Echo control entry to unused.*/ ++ WriteParams.ulWriteAddress = cOCT6100_ECHO_CONTROL_MEM_BASE + ( pChanEntry->usExtToneChanIndex * cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x85FF; /* TSI index 1535 reserved for power-down mode */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = 0xC5FF; /* TSI index 1535 reserved for power-down mode */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*------------------------------------------------------------------------------*/ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Remove the mixer event used to copy the RIN signal to the SIN port of the extended ++ channel.*/ ++ ++ /* Clear the Copy event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usExtToneMixerIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pChanEntry->usExtToneMixerIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ } ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Reset PGSP */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ WriteParams.usWriteData = 0x0800; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Clear the mute with feature bit. */ ++ ++ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ++ { ++ ulResult = Oct6100ApiMuteSinWithFeatures( f_pApiInstance, f_usChanIndex, FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Clear the VQE memory. */ ++ ++ SmearParams.ulWriteAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst + 0x20; ++ SmearParams.usWriteData = 0x0000; ++ SmearParams.ulWriteLength = 2; ++ ++ mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ /*------------------------------------------------------------------------------*/ ++ /* Clear the NLP memory. */ ++ ++ SmearParams.ulWriteAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst + 0x28; ++ SmearParams.usWriteData = 0x0000; ++ SmearParams.ulWriteLength = 2; ++ ++ mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Clear the AF information memory. */ ++ ++ SmearParams.ulWriteAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( pChanEntry->usEchoMemIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; ++ SmearParams.usWriteData = 0x0000; ++ SmearParams.ulWriteLength = 12; ++ ++ mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*Reset ALC status*/ ++ WriteParams.ulWriteAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( pChanEntry->usEchoMemIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst + 0x3A; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseChannelResources ++ ++Description: Release and clear the API entry associated to the echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usChannelIndex Index of the echo cancellation channel in the API list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseChannelResources ++UINT32 Oct6100ApiReleaseChannelResources( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChannelIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_CHANNEL_TDM pTdmConfig; ++ tPOCT6100_API_TSST_ENTRY pTsstEntry; ++ UINT32 ulResult; ++ UINT16 usCurrentEntry; ++ UINT32 ulTimeslot; ++ UINT32 ulStream; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChannelIndex ); ++ ++ /* Obtain local pointer to the TDM configurationof the channel */ ++ pTdmConfig = &pChanEntry->TdmConfig; ++ ++ /* Release the two TSI chariot memory entries.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usRinRoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_2; ++ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_3; ++ ++ /* Now release the ECHO channel and control memory entries.*/ ++ ulResult = Oct6100ApiReleaseEchoEntry( f_pApiInstance, f_usChannelIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_4; ++ ++ /* Release the conversion resources.*/ ++ if ( pChanEntry->usRinRoutConversionMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, pChanEntry->usRinRoutConversionMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_B9; ++ ++ pChanEntry->usRinRoutConversionMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ if ( pChanEntry->usSinSoutConversionMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, pChanEntry->usSinSoutConversionMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_BA; ++ ++ pChanEntry->usSinSoutConversionMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /*=========================================================================*/ ++ /* Release the TSST control memory entries if any were reserved.*/ ++ if ( pTdmConfig->usRinTimeslot != cOCT6100_UNASSIGNED) ++ { ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->usRinTimeslot, ++ pTdmConfig->usRinStream, ++ pTdmConfig->byRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_5; ++ } ++ ++ if ( pTdmConfig->usSinTimeslot != cOCT6100_UNASSIGNED) ++ { ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->usSinTimeslot, ++ pTdmConfig->usSinStream, ++ pTdmConfig->bySinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_6; ++ } ++ ++ /*=======================================================================*/ ++ /* Release all the TSSTs associated to the ROUT port of this channel. */ ++ if ( pTdmConfig->usRoutTimeslot != cOCT6100_UNASSIGNED) ++ { ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->usRoutTimeslot, ++ pTdmConfig->usRoutStream, ++ pTdmConfig->byRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_7; ++ } ++ ++ /* Now release the Broadcast TSSTs. */ ++ usCurrentEntry = pTdmConfig->usRoutBrdcastTsstFirstEntry; ++ while( usCurrentEntry != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ ulTimeslot = pTsstEntry->usTsstValue >> 5; ++ ulStream = pTsstEntry->usTsstValue & 0x1F; ++ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ ulTimeslot, ++ ulStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_OUTPUT_TSST, ++ usCurrentEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_8; ++ ++ /* Move to the next entry.*/ ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ ++ /* Invalidate the current entry.*/ ++ pTsstEntry->usTsstMemoryIndex = 0xFFFF; ++ pTsstEntry->usTsstValue = 0xFFFF; ++ pTsstEntry->usNextEntry = cOCT6100_INVALID_INDEX; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Release all the TSSTs associated to the SOUT port of this channel. */ ++ if ( pTdmConfig->usSoutTimeslot != cOCT6100_UNASSIGNED) ++ { ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTdmConfig->usSoutTimeslot, ++ pTdmConfig->usSoutStream, ++ pTdmConfig->bySoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_9; ++ } ++ ++ /* Now release the Broadcast TSSTs. */ ++ usCurrentEntry = pTdmConfig->usSoutBrdcastTsstFirstEntry; ++ while( usCurrentEntry != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ ulTimeslot = pTsstEntry->usTsstValue >> 5; ++ ulStream = pTsstEntry->usTsstValue & 0x1F; ++ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ ulTimeslot, ++ ulStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_OUTPUT_TSST, ++ usCurrentEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A; ++ ++ /* Move to the next entry.*/ ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ ++ /* Invalidate the current entry.*/ ++ pTsstEntry->usTsstMemoryIndex = 0xFFFF; ++ pTsstEntry->usTsstValue = 0xFFFF; ++ pTsstEntry->usNextEntry = cOCT6100_INVALID_INDEX; ++ } ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Update the dependency of the phasing TSST if one is associated to the chanel.*/ ++ ++ if ( pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ tPOCT6100_API_PHASING_TSST pPhasingEntry; ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, pChanEntry->usPhasingTsstIndex ); ++ ++ pPhasingEntry->usDependencyCnt--; ++ } ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Release any resources reserved for the extended tone detection.*/ ++ ++ if ( pChanEntry->fEnableExtToneDetection == TRUE ) ++ { ++ tPOCT6100_API_CHANNEL pExtToneChanEntry; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pExtToneChanEntry, pChanEntry->usExtToneChanIndex ); ++ ++ /* Release the ECHO channel and control memory entries.*/ ++ ulResult = Oct6100ApiReleaseEchoEntry( f_pApiInstance, pChanEntry->usExtToneChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_C1; ++ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtToneTsiIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_C2; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usExtToneMixerIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_C3; ++ ++ /* Now release the channel entry */ ++ pExtToneChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_DISABLED; ++ pExtToneChanEntry->fReserved = FALSE; ++ ++ /* Set the current entry to disable, just in case.*/ ++ pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_DISABLED; ++ } ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Update the channel's list entry. */ ++ ++ /* Clear the NLP dword array. */ ++ Oct6100UserMemSet( pChanEntry->aulNlpConfDword, 0, sizeof( pChanEntry->aulNlpConfDword ) ); ++ ++ /* Clear the echo operation mode. */ ++ pChanEntry->byEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; ++ ++ /* Mark the channel as closed. */ ++ pChanEntry->fReserved = FALSE; ++ pChanEntry->byEntryOpenCnt++; ++ ++ /* Reset the port, the bridge and BidirInfo */ ++ pChanEntry->usMutedPorts = cOCT6100_CHANNEL_MUTE_PORT_NONE; ++ pChanEntry->fBiDirChannel = FALSE; ++ pChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Decrement the number of channel open.*/ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels--; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++ ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelModifySer ++ ++Description: Modify an echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelModify Pointer to channel configuration structure. The handle ++ identifying the buffer in all future function calls is ++ returned in this structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelModifySer ++UINT32 Oct6100ChannelModifySer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) ++{ ++ UINT16 usChanIndex; ++ UINT32 ulResult; ++ UINT16 usNewRinTsstIndex; ++ UINT16 usNewSinTsstIndex; ++ UINT16 usNewRoutTsstIndex; ++ UINT16 usNewSoutTsstIndex; ++ UINT8 fSinSoutCodecActive = FALSE; ++ UINT8 fRinRoutCodecActive = FALSE; ++ UINT16 usNewPhasingTsstIndex; ++ tOCT6100_CHANNEL_OPEN *pTempChanOpen; ++ ++ /* We don't want this 290 byte structure on the stack */ ++ pTempChanOpen = kmalloc(sizeof(*pTempChanOpen), GFP_ATOMIC); ++ if (!pTempChanOpen) ++ return cOCT6100_ERR_FATAL_0; ++ ++ /* Check the user's configuration of the echo cancellation channel for errors. */ ++ ulResult = Oct6100ApiCheckChannelModify( f_pApiInstance, ++ f_pChannelModify, ++ pTempChanOpen, ++ &usNewPhasingTsstIndex, ++ &usChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ goto out; ++ ++ /* Reserve all resources needed by the echo cancellation channel. */ ++ ulResult = Oct6100ApiModifyChannelResources( f_pApiInstance, ++ f_pChannelModify, ++ usChanIndex, ++ &usNewRinTsstIndex, ++ &usNewSinTsstIndex, ++ &usNewRoutTsstIndex, ++ &usNewSoutTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ goto out; ++ ++ /* Write all necessary structures to activate the echo cancellation channel. */ ++ ulResult = Oct6100ApiModifyChannelStructs( f_pApiInstance, ++ f_pChannelModify, ++ pTempChanOpen, ++ usChanIndex, ++ usNewPhasingTsstIndex, ++ &fSinSoutCodecActive, ++ &fRinRoutCodecActive, ++ usNewRinTsstIndex, ++ usNewSinTsstIndex, ++ usNewRoutTsstIndex, ++ usNewSoutTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ goto out; ++ ++ /* Update the new echo cancellation channels's entry in the ECHO channel list. */ ++ ulResult = Oct6100ApiModifyChannelEntry( f_pApiInstance, ++ f_pChannelModify, ++ pTempChanOpen, ++ usChanIndex, ++ usNewPhasingTsstIndex, ++ fSinSoutCodecActive, ++ fRinRoutCodecActive, ++ usNewRinTsstIndex, ++ usNewSinTsstIndex, ++ usNewRoutTsstIndex, ++ usNewSoutTsstIndex ); ++out: ++ kfree(pTempChanOpen); ++ ++ return ulResult; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckChannelModify ++ ++Description: Checks the user's echo cancellation channel modify structure for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelModify Pointer to echo cancellation channel modify structure. ++f_pTempChanOpen Pointer to a channel open structure. ++f_pusNewPhasingTsstIndex Pointer to a new phasing TSST index within the API instance. ++f_pusChanIndex Pointer to the channel index within the API instance channel list ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckChannelModify ++UINT32 Oct6100ApiCheckChannelModify( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN tPOCT6100_CHANNEL_OPEN f_pTempChanOpen, ++ OUT PUINT16 f_pusNewPhasingTsstIndex, ++ OUT PUINT16 f_pusChanIndex ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulResult; ++ UINT32 ulEntryOpenCnt; ++ UINT32 ulDecoderNumTssts; ++ ++ /* Check the provided handle. */ ++ if ( (f_pChannelModify->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ *f_pusChanIndex = (UINT16)( f_pChannelModify->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelModify->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Check the general modify parameters. */ ++ ++ if ( f_pChannelModify->ulEchoOperationMode != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NORMAL && ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_FREEZE && ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET && ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN && ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL && ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION && ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE; ++ ++ /* Check the 2100Hz echo disabling configuration.*/ ++ if ( f_pChannelModify->fEnableToneDisabler != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->fEnableToneDisabler != TRUE && ++ f_pChannelModify->fEnableToneDisabler != FALSE ) ++ return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ENABLE; ++ ++ /* Check the disable tone detection flag. */ ++ if ( f_pChannelModify->fDisableToneDetection != TRUE && ++ f_pChannelModify->fDisableToneDetection != FALSE ) ++ return cOCT6100_ERR_CHANNEL_DISABLE_TONE_DETECTION; ++ ++ /* Check the stop buffer playout flag. */ ++ if ( f_pChannelModify->fStopBufferPlayout != TRUE && ++ f_pChannelModify->fStopBufferPlayout != FALSE ) ++ return cOCT6100_ERR_CHANNEL_STOP_BUFFER_PLAYOUT; ++ ++ /* Check the remove conference bridge participant flag. */ ++ if ( f_pChannelModify->fRemoveConfBridgeParticipant != TRUE && ++ f_pChannelModify->fRemoveConfBridgeParticipant != FALSE ) ++ return cOCT6100_ERR_CHANNEL_REMOVE_CONF_BRIDGE_PARTICIPANT; ++ ++ /* Check the remove broadcast timeslots flag. */ ++ if ( f_pChannelModify->fRemoveBroadcastTssts != TRUE && ++ f_pChannelModify->fRemoveBroadcastTssts != FALSE ) ++ return cOCT6100_ERR_CHANNEL_REMOVE_BROADCAST_TSSTS; ++ ++ if ( f_pChannelModify->fCodecConfigModified != TRUE && ++ f_pChannelModify->fCodecConfigModified != FALSE ) ++ return cOCT6100_ERR_CHANNEL_MODIFY_CODEC_CONFIG; ++ ++ if ( f_pChannelModify->fVqeConfigModified != TRUE && ++ f_pChannelModify->fVqeConfigModified != FALSE ) ++ return cOCT6100_ERR_CHANNEL_MODIFY_VQE_CONFIG; ++ ++ if ( f_pChannelModify->fTdmConfigModified != TRUE && ++ f_pChannelModify->fTdmConfigModified != FALSE ) ++ return cOCT6100_ERR_CHANNEL_MODIFY_TDM_CONFIG; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Verify if any law change was requested. If so reprogram all structures.*/ ++ ++ if (( f_pChannelModify->fTdmConfigModified == TRUE ) && ++ ( f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->TdmConfig.ulRoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING )) ++ { ++ f_pChannelModify->fVqeConfigModified = TRUE; ++ f_pChannelModify->fCodecConfigModified = TRUE; ++ } ++ /*=======================================================================*/ ++ ++ ulResult = Oct6100ApiUpdateOpenStruct( f_pApiInstance, f_pChannelModify, f_pTempChanOpen, pChanEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* All further check will now be performed using the TempOpenChan structure in order ++ to reuse the checks written for the open channel structure.*/ ++ ++ ++ ++ /* Check the TDM config.*/ ++ if ( f_pChannelModify->fTdmConfigModified == TRUE ) ++ { ++ tPOCT6100_CHANNEL_MODIFY_TDM pModifyTdm; ++ tPOCT6100_CHANNEL_OPEN_TDM pOpenTdm; ++ ++ pModifyTdm = &f_pChannelModify->TdmConfig; ++ pOpenTdm = &f_pTempChanOpen->TdmConfig; ++ ++ ulResult = Oct6100ApiCheckTdmConfig( f_pApiInstance, ++ pOpenTdm ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if that Stream and Timeslot values are valid.*/ ++ ++ /* Check the RIN port.*/ ++ if ( f_pChannelModify->TdmConfig.ulRinStream == cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; ++ ++ if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_RIN_STREAM; ++ ++ if ( pChanEntry->fBeingTapped == TRUE ) ++ { ++ /* Check that the Rin stream + timeslot are not being assigned. */ ++ if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_RIN_STREAM; ++ ++ if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; ++ } ++ } ++ ++ /* Check the SIN port.*/ ++ if ( f_pChannelModify->TdmConfig.ulSinStream == cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT; ++ ++ if ( f_pChannelModify->TdmConfig.ulSinStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_SIN_STREAM; ++ ++ /* Check the ROUT port.*/ ++ if ( f_pChannelModify->TdmConfig.ulRoutStream == cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT; ++ ++ if ( f_pChannelModify->TdmConfig.ulRoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_ROUT_STREAM; ++ ++ /* Check the SOUT port.*/ ++ if ( f_pChannelModify->TdmConfig.ulSoutStream == cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; ++ ++ if ( f_pChannelModify->TdmConfig.ulSoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ return cOCT6100_ERR_CHANNEL_SOUT_STREAM; ++ ++ /* Verify if the channel is currently part of a bidirectional channel, and if */ ++ /* so perform the required checks. */ ++ if ( pChanEntry->fBiDirChannel == TRUE ) ++ { ++ /* Check the ports that must remain unassigned.*/ ++ if ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; ++ if ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; ++ ++ /* Check that no PCM law change is requested.*/ ++ if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) ++ return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; ++ if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) ++ return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; ++ } ++ ++ /* If this channel is on a conference bridge, a few more things must be checked. */ ++ if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* If conferencing, law conversion cannot be applied. */ ++ /* This check is done only if both input and output ports are assigned. */ ++ if ( ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) ++ && ( f_pTempChanOpen->TdmConfig.ulRoutTimeslot != cOCT6100_UNASSIGNED ) ) ++ { ++ /* Laws must be the same! */ ++ if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) ++ return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; ++ } ++ ++ /* Check for Sin. */ ++ if ( ( f_pTempChanOpen->TdmConfig.ulSinTimeslot != cOCT6100_UNASSIGNED ) ++ && ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) ) ++ { ++ /* Laws must be the same! */ ++ if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) ++ return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; ++ } ++ ++ /* Check if ADPCM is requested. */ ++ if ( f_pTempChanOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING && ++ f_pTempChanOpen->CodecConfig.ulEncodingRate != cOCT6100_G711_64KBPS ) ++ { ++ /* No ADPCM in a conference bridge! */ ++ return cOCT6100_ERR_CHANNEL_ENCODING_RATE; ++ } ++ ++ if ( f_pTempChanOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING && ++ f_pTempChanOpen->CodecConfig.ulDecodingRate != cOCT6100_G711_64KBPS ) ++ { ++ /* No ADPCM in a conference bridge! */ ++ return cOCT6100_ERR_CHANNEL_DECODING_RATE; ++ } ++ } ++ ++ if ( f_pTempChanOpen->CodecConfig.ulEncoderPort == cOCT6100_NO_ENCODING || ++ f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_NO_DECODING ) ++ { ++ /* Make sure no law conversion is attempted since it is not supported by the device.*/ ++ if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) ++ return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; ++ if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) ++ return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; ++ } ++ ++ if ( pChanEntry->fEnableExtToneDetection == TRUE && ++ f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DECODER_PORT; ++ ++ /* A few special checks must be done if the configuration is to be applied */ ++ /* to all opened channels. */ ++ if ( f_pChannelModify->fApplyToAllChannels == TRUE ) ++ { ++ /* When the configuration to be applied is for all channels, */ ++ /* check that the stream and timeslot parameters are not being assigned. */ ++ ++ /* Check the Rout port. */ ++ if ( f_pChannelModify->TdmConfig.ulRoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Check that the Rout ports is being unassigned. */ ++ if ( f_pTempChanOpen->TdmConfig.ulRoutStream != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_ROUT_STREAM_UNASSIGN; ++ if ( f_pTempChanOpen->TdmConfig.ulRoutTimeslot != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT_UNASSIGN; ++ } ++ ++ /* Check the Rin port. */ ++ if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Check that the Rin ports is being unassigned. */ ++ if ( f_pTempChanOpen->TdmConfig.ulRinStream != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_RIN_STREAM_UNASSIGN; ++ if ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT_UNASSIGN; ++ } ++ ++ /* Check the Sout port. */ ++ if ( f_pChannelModify->TdmConfig.ulSoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Check that the Sout ports is being unassigned. */ ++ if ( f_pTempChanOpen->TdmConfig.ulSoutStream != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_SOUT_STREAM_UNASSIGN; ++ if ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT_UNASSIGN; ++ } ++ ++ /* Check the Sin port. */ ++ if ( f_pChannelModify->TdmConfig.ulSinStream != cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Check that the Sin ports is being unassigned. */ ++ if ( f_pTempChanOpen->TdmConfig.ulSinStream != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_SIN_STREAM_UNASSIGN; ++ if ( f_pTempChanOpen->TdmConfig.ulSinTimeslot != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT_UNASSIGN; ++ } ++ } ++ } ++ ++ /* Check the VQE config.*/ ++ if ( f_pChannelModify->fVqeConfigModified == TRUE ) ++ { ++ ulResult = Oct6100ApiCheckVqeConfig( f_pApiInstance, ++ &f_pTempChanOpen->VqeConfig, ++ f_pTempChanOpen->fEnableToneDisabler ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Verify if the echo operation mode selected can be applied. */ ++ if ( ( f_pTempChanOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ && ( f_pTempChanOpen->VqeConfig.fEnableNlp == FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; ++ ++ if ( ( f_pTempChanOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ++ && ( f_pTempChanOpen->VqeConfig.fEnableNlp == FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; ++ ++ /* Comfort noise must be activated for speech recognition mode to work. */ ++ if ( ( f_pTempChanOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ++ && ( f_pTempChanOpen->VqeConfig.ulComfortNoiseMode == cOCT6100_COMFORT_NOISE_OFF ) ) ++ return cOCT6100_ERR_CHANNEL_COMFORT_NOISE_REQUIRED; ++ ++ /* Check the Codec config.*/ ++ if ( f_pChannelModify->fCodecConfigModified == TRUE ) ++ { ++ if ( f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ ulDecoderNumTssts = f_pTempChanOpen->TdmConfig.ulRinNumTssts; ++ else /* f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ++ ulDecoderNumTssts = f_pTempChanOpen->TdmConfig.ulSinNumTssts; ++ ++ ulResult = Oct6100ApiCheckCodecConfig( f_pApiInstance, ++ &f_pTempChanOpen->CodecConfig, ++ ulDecoderNumTssts, ++ f_pusNewPhasingTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ ++ /* make sure that if silence suppression is activated, the NLP is enabled.*/ ++ if ( f_pTempChanOpen->CodecConfig.fEnableSilenceSuppression == TRUE && f_pTempChanOpen->VqeConfig.fEnableNlp == FALSE ) ++ return cOCT6100_ERR_CHANNEL_SIL_SUP_NLP_MUST_BE_ENABLED; ++ ++ /* Verify if the channel is currently part of a bidirectional channel, and if so perform ++ the required checks.*/ ++ if ( pChanEntry->fBiDirChannel == TRUE ) ++ { ++ /* Check the ports that must remain unassigned.*/ ++ if ( f_pTempChanOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING && ++ f_pTempChanOpen->CodecConfig.ulEncodingRate != cOCT6100_G711_64KBPS ) ++ return cOCT6100_ERR_CHANNEL_ENCODING_RATE; ++ ++ if ( f_pTempChanOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING && ++ f_pTempChanOpen->CodecConfig.ulDecodingRate != cOCT6100_G711_64KBPS ) ++ return cOCT6100_ERR_CHANNEL_DECODING_RATE; ++ } ++ ++ } ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiModifyChannelResources ++ ++Description: Reserves any new resources needed for the channel ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelModify Pointer to echo cancellation channel configuration structure. ++f_usChanIndex Allocated entry in ECHO channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiModifyChannelResources ++UINT32 Oct6100ApiModifyChannelResources( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN UINT16 f_usChanIndex, ++ OUT PUINT16 f_pusNewRinTsstIndex, ++ OUT PUINT16 f_pusNewSinTsstIndex, ++ OUT PUINT16 f_pusNewRoutTsstIndex, ++ OUT PUINT16 f_pusNewSoutTsstIndex ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ tPOCT6100_API_CHANNEL_TDM pApiTdmConf; ++ tPOCT6100_CHANNEL_MODIFY_TDM pModifyTdmConf; ++ ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 ulTempVar = cOCT6100_ERR_OK; ++ UINT32 ulFreeMixerEventCnt; ++ ++ BOOL fRinReleased = FALSE; ++ BOOL fSinReleased = FALSE; ++ BOOL fRoutReleased = FALSE; ++ BOOL fSoutReleased = FALSE; ++ ++ BOOL fRinReserved = FALSE; ++ BOOL fSinReserved = FALSE; ++ BOOL fRoutReserved = FALSE; ++ BOOL fSoutReserved = FALSE; ++ ++ BOOL fReserveRin = FALSE; ++ BOOL fReserveSin = FALSE; ++ BOOL fReserveRout = FALSE; ++ BOOL fReserveSout = FALSE; ++ ++ BOOL fRinRoutConversionMemReserved = FALSE; ++ BOOL fSinSoutConversionMemReserved = FALSE; ++ ++ ++ UINT32 ulRinNumTssts = 1; ++ UINT32 ulSinNumTssts = 1; ++ UINT32 ulRoutNumTssts = 1; ++ UINT32 ulSoutNumTssts = 1; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain local pointer to the TDM configuration structure of the tPOCT6100_CHANNEL_MODIFY structure. */ ++ pModifyTdmConf = &f_pChannelModify->TdmConfig; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ /* Obtain local pointer to the TDM configuration structure of the tPOCT6100_API_CHANNEL structure. */ ++ pApiTdmConf = &pChanEntry->TdmConfig; ++ ++ /*===============================================================================*/ ++ /* Modify TSST resources if required.*/ ++ if ( f_pChannelModify->fTdmConfigModified == TRUE ) ++ { ++ /* First release any entry that need to be released.*/ ++ if ( ( pModifyTdmConf->ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ || ( pModifyTdmConf->ulRinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ ) ++ { ++ if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Release the previously reserved entry.*/ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usRinTimeslot, ++ pChanEntry->TdmConfig.usRinStream, ++ pChanEntry->TdmConfig.byRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fRinReleased = TRUE; ++ } ++ } ++ ++ fReserveRin = TRUE; ++ } ++ ++ /* Release SIN port.*/ ++ if ( ( ulResult == cOCT6100_ERR_OK ) ++ && ( ( pModifyTdmConf->ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ || ( pModifyTdmConf->ulSinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ ) ) ++ { ++ if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Release the previously reserved entry.*/ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usSinTimeslot, ++ pChanEntry->TdmConfig.usSinStream, ++ pChanEntry->TdmConfig.bySinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fSinReleased = TRUE; ++ } ++ } ++ ++ fReserveSin = TRUE; ++ } ++ ++ /* Release ROUT port.*/ ++ if ( ( ulResult == cOCT6100_ERR_OK ) ++ && ( ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ || ( pModifyTdmConf->ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ ) ) ++ { ++ if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Release the previously reserved entry.*/ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usRoutTimeslot, ++ pChanEntry->TdmConfig.usRoutStream, ++ pChanEntry->TdmConfig.byRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fRoutReleased = TRUE; ++ } ++ } ++ ++ fReserveRout = TRUE; ++ } ++ ++ /* Release the SOUT port.*/ ++ if ( ( ulResult == cOCT6100_ERR_OK ) ++ && ( ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ || ( pModifyTdmConf->ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ ) ) ++ { ++ if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Release the previously reserved entry.*/ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usSoutTimeslot, ++ pChanEntry->TdmConfig.usSoutStream, ++ pChanEntry->TdmConfig.bySoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fSoutReleased = TRUE; ++ } ++ } ++ ++ fReserveSout = TRUE; ++ } ++ ++ /* Now reserve any new entry required.*/ ++ ++ /* Modify RIN port.*/ ++ if ( ( fReserveRin == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) ++ { ++ if ( pModifyTdmConf->ulRinTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Check what number of TSSTs should be reserved this time. */ ++ if ( pModifyTdmConf->ulRinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ ulRinNumTssts = pApiTdmConf->byRinNumTssts; ++ } ++ else /* if ( pModifyTdmConf->ulRinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* New number of TSSTs. */ ++ ulRinNumTssts = pModifyTdmConf->ulRinNumTssts; ++ } ++ ++ if ( pModifyTdmConf->ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Reserve the new number of TSSTs. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pApiTdmConf->usRinTimeslot, ++ pApiTdmConf->usRinStream, ++ ulRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ f_pusNewRinTsstIndex, ++ NULL ); ++ } ++ else /* if ( pModifyTdmConf->ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* Reserve the new TSST.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pModifyTdmConf->ulRinTimeslot, ++ pModifyTdmConf->ulRinStream, ++ ulRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ f_pusNewRinTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fRinReserved = TRUE; ++ } ++ } ++ } ++ else ++ { ++ *f_pusNewRinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ else ++ { ++ *f_pusNewRinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Modify SIN port.*/ ++ if ( ( fReserveSin == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) ++ { ++ if ( pModifyTdmConf->ulSinTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Check what number of TSSTs should be reserved this time. */ ++ if ( pModifyTdmConf->ulSinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ ulSinNumTssts = pApiTdmConf->bySinNumTssts; ++ } ++ else /* if ( pModifyTdmConf->ulSinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* New number of TSSTs. */ ++ ulSinNumTssts = pModifyTdmConf->ulSinNumTssts; ++ } ++ ++ if ( pModifyTdmConf->ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Reserve the new number of TSSTs. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pApiTdmConf->usSinTimeslot, ++ pApiTdmConf->usSinStream, ++ ulSinNumTssts, ++ cOCT6100_INPUT_TSST, ++ f_pusNewSinTsstIndex, ++ NULL ); ++ } ++ else /* if ( pModifyTdmConf->ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* Reserve the new TSST.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pModifyTdmConf->ulSinTimeslot, ++ pModifyTdmConf->ulSinStream, ++ ulSinNumTssts, ++ cOCT6100_INPUT_TSST, ++ f_pusNewSinTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fSinReserved = TRUE; ++ } ++ } ++ } ++ else ++ { ++ *f_pusNewSinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ else ++ { ++ *f_pusNewSinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Modify ROUT port.*/ ++ if ( ( fReserveRout == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) ++ { ++ if ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Check what number of TSSTs should be reserved this time. */ ++ if ( pModifyTdmConf->ulRoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ ulRoutNumTssts = pApiTdmConf->byRoutNumTssts; ++ } ++ else /* if ( pModifyTdmConf->ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* New number of TSSTs. */ ++ ulRoutNumTssts = pModifyTdmConf->ulRoutNumTssts; ++ } ++ ++ if ( pModifyTdmConf->ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Reserve the new number of TSSTs. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pApiTdmConf->usRoutTimeslot, ++ pApiTdmConf->usRoutStream, ++ ulRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ f_pusNewRoutTsstIndex, ++ NULL ); ++ } ++ else /* if ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* Reserve the new TSST.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pModifyTdmConf->ulRoutTimeslot, ++ pModifyTdmConf->ulRoutStream, ++ ulRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ f_pusNewRoutTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fRoutReserved = TRUE; ++ } ++ } ++ } ++ else ++ { ++ *f_pusNewRoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ else ++ { ++ *f_pusNewRoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Modify SOUT port.*/ ++ if ( ( fReserveSout == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) ++ { ++ if ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_UNASSIGNED ) ++ { ++ /* Check what number of TSSTs should be reserved this time. */ ++ if ( pModifyTdmConf->ulSoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ ulSoutNumTssts = pApiTdmConf->bySoutNumTssts; ++ } ++ else /* if ( pModifyTdmConf->ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* New number of TSSTs. */ ++ ulSoutNumTssts = pModifyTdmConf->ulSoutNumTssts; ++ } ++ ++ if ( pModifyTdmConf->ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* Reserve the new number of TSSTs. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pApiTdmConf->usSoutTimeslot, ++ pApiTdmConf->usSoutStream, ++ ulSoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ f_pusNewSoutTsstIndex, ++ NULL ); ++ } ++ else /* if ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ ++ { ++ /* Reserve the new TSST.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ pModifyTdmConf->ulSoutTimeslot, ++ pModifyTdmConf->ulSoutStream, ++ ulSoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ f_pusNewSoutTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fSoutReserved = TRUE; ++ } ++ } ++ } ++ else ++ { ++ *f_pusNewSoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ else ++ { ++ *f_pusNewSoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ ++ } ++ ++ if ( f_pChannelModify->fCodecConfigModified == TRUE ) ++ { ++ if ( ulResult == cOCT6100_ERR_OK && ++ pChanEntry->usRinRoutConversionMemIndex == cOCT6100_INVALID_INDEX && ++ ( f_pChannelModify->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT || ++ f_pChannelModify->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ) ++ { ++ /* Reserve an ADPCM memory block.*/ ++ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, &pChanEntry->usRinRoutConversionMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fRinRoutConversionMemReserved = TRUE; ++ } ++ } ++ ++ if ( ulResult == cOCT6100_ERR_OK && ++ pChanEntry->usSinSoutConversionMemIndex == cOCT6100_INVALID_INDEX && ++ ( f_pChannelModify->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT || ++ f_pChannelModify->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) ) ++ { ++ /* Reserve an ADPCM memory block.*/ ++ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, &pChanEntry->usSinSoutConversionMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fSinSoutConversionMemReserved = TRUE; ++ } ++ } ++ } ++ ++ ++ /*===============================================================================*/ ++ /* Check if there are a couple of mixer events available for us. */ ++ ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ UINT32 ulMixerEventCntNeeded = 0; ++ ++ /* Calculate how many mixer events are needed. */ ++ if ( pChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* If the channel is in bidir mode, do not create the Rin silence event!!! */ ++ if ( pChanEntry->fBiDirChannel == FALSE ) ++ { ++ if ( ( *f_pusNewRinTsstIndex == cOCT6100_INVALID_INDEX ) ++ && ( pChanEntry->usRinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) ++ ulMixerEventCntNeeded++; ++ } ++ } ++ ++ if ( ( *f_pusNewSinTsstIndex == cOCT6100_INVALID_INDEX ) ++ && ( pChanEntry->usSinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) ++ { ++ ulMixerEventCntNeeded++; ++ } ++ ++ /* If at least 1 mixer event is needed, check if those are available. */ ++ if ( ulMixerEventCntNeeded != 0 ) ++ { ++ ulResult = Oct6100ApiGetFreeMixerEventCnt( f_pApiInstance, &ulFreeMixerEventCnt ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* The API might need more mixer events if the ports have to be muted. */ ++ /* Check if these are available. */ ++ if ( ulFreeMixerEventCnt < ulMixerEventCntNeeded ) ++ { ++ ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_MIXER_EVENTS; ++ } ++ } ++ } ++ } ++ ++ /*===============================================================================*/ ++ ++ /* Verify if an error occured. */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Release any resources newly reserved.*/ ++ if ( fRinReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pModifyTdmConf->ulRinTimeslot, ++ pModifyTdmConf->ulRinStream, ++ ulRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* For the SIN port.*/ ++ if ( fSinReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pModifyTdmConf->ulSinTimeslot, ++ pModifyTdmConf->ulSinStream, ++ ulSinNumTssts, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* For the ROUT port.*/ ++ if ( fRoutReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pModifyTdmConf->ulRoutTimeslot, ++ pModifyTdmConf->ulRoutStream, ++ ulRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* For the SOUT port.*/ ++ if ( fSoutReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pModifyTdmConf->ulSoutTimeslot, ++ pModifyTdmConf->ulSoutStream, ++ ulSoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* Now make sure any resources released gets reserved back again.*/ ++ ++ /* For the RIN port.*/ ++ if ( fRinReleased == TRUE ) ++ { ++ /* Reserve the new TSST.*/ ++ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usRinTimeslot, ++ pChanEntry->TdmConfig.usRinStream, ++ pChanEntry->TdmConfig.byRinNumTssts, ++ cOCT6100_INPUT_TSST, ++ &pChanEntry->usRinTsstIndex, ++ NULL ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* For the SIN port.*/ ++ if ( fSinReleased == TRUE ) ++ { ++ /* Reserve the new TSST.*/ ++ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usSinTimeslot, ++ pChanEntry->TdmConfig.usSinStream, ++ pChanEntry->TdmConfig.bySinNumTssts, ++ cOCT6100_INPUT_TSST, ++ &pChanEntry->usSinTsstIndex, ++ NULL ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* For the ROUT port.*/ ++ if ( fRoutReleased == TRUE ) ++ { ++ /* Reserve the new TSST.*/ ++ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usRoutTimeslot, ++ pChanEntry->TdmConfig.usRoutStream, ++ pChanEntry->TdmConfig.byRoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ &pChanEntry->usRoutTsstIndex, ++ NULL ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* For the SOUT port.*/ ++ if ( fSoutReleased == TRUE ) ++ { ++ /* Reserve the new TSST.*/ ++ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, ++ pChanEntry->TdmConfig.usSoutTimeslot, ++ pChanEntry->TdmConfig.usSoutStream, ++ pChanEntry->TdmConfig.bySoutNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ &pChanEntry->usSoutTsstIndex, ++ NULL ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* Release the conversion memories if they were reserved.*/ ++ if ( fRinRoutConversionMemReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, ++ pChanEntry->usRinRoutConversionMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fSinSoutConversionMemReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, ++ pChanEntry->usSinSoutConversionMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /* Now return the error.*/ ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiModifyChannelStructs ++ ++Description: Performs all the required structure writes to configure the ++ echo cancellation channel based on the new modifications. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelModify Pointer to echo cancellation channel configuration structure. ++f_pChannelOpen Pointer to a structure used to store the multiple resources indexes. ++f_usChanIndex Index of the channel within the API's channel list. ++f_usNewPhasingTsstIndex Index of the new phasing TSST. ++f_pfSinSoutCodecActive Pointer to the state of the SIN/SOUT codec. ++f_pfRinRoutCodecActive Pointer to the state of the RIN/ROUT codec. ++f_usNewRinTsstIndex New RIN TSST memory index. ++f_usNewSinTsstIndex New SIN TSST memory index. ++f_usNewRoutTsstIndex New ROUT TSST memory index. ++f_usNewSoutTsstIndex New SOUT TSST memory index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiModifyChannelStructs ++UINT32 Oct6100ApiModifyChannelStructs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewPhasingTsstIndex, ++ OUT PUINT8 f_pfSinSoutCodecActive, ++ OUT PUINT8 f_pfRinRoutCodecActive, ++ IN UINT16 f_usNewRinTsstIndex, ++ IN UINT16 f_usNewSinTsstIndex, ++ IN UINT16 f_usNewRoutTsstIndex, ++ IN UINT16 f_usNewSoutTsstIndex ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tPOCT6100_API_CHANNEL_CODEC pApiCodecConf; ++ tPOCT6100_API_CHANNEL_TDM pApiTdmConf; ++ tPOCT6100_API_CHANNEL_VQE pApiVqeConf; ++ ++ UINT32 ulResult; ++ UINT16 usReadData; ++ ++ UINT16 usSinTsstIndex; ++ UINT16 usRinTsstIndex; ++ ++ UINT32 ulToneConfIndex; ++ BOOL fClearPlayoutPointers = FALSE; ++ ++ BOOL fConversionEnabled = FALSE; ++ ++ ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ /* Obtain local pointer to the configuration structures of the tPOCT6100_API_CHANNEL structure. */ ++ pApiCodecConf = &pChanEntry->CodecConfig; ++ pApiTdmConf = &pChanEntry->TdmConfig; ++ pApiVqeConf = &pChanEntry->VqeConfig; ++ ++ /*=======================================================================*/ ++ /* Init the RIN and SIN TSST index */ ++ ++ usRinTsstIndex = pChanEntry->usRinTsstIndex; ++ usSinTsstIndex = pChanEntry->usSinTsstIndex; ++ ++ ++ /*==============================================================================*/ ++ /* Clear the TSST that will be release.*/ ++ ++ if ( f_pChannelModify->fTdmConfigModified == TRUE ) ++ { ++ /* Modify RIN port.*/ ++ if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Clear the previous entry */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usRinTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Modify SIN port.*/ ++ if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Clear the previous entry */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usSinTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Modify ROUT port.*/ ++ if ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Clear the previous entry */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usRoutTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Modify SOUT port.*/ ++ if ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING) ++ { ++ if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Clear the previous entry */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usSoutTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Now, Configure the Tsst control memory.*/ ++ ++ if ( f_pChannelModify->fTdmConfigModified == TRUE ) ++ { ++ /* Modify RIN port.*/ ++ if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ usRinTsstIndex = f_usNewRinTsstIndex; ++ ++ if ( f_usNewRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ if ( pChanEntry->usExtraRinTsiMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_usNewRinTsstIndex, ++ pChanEntry->usExtraRinTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_usNewRinTsstIndex, ++ pChanEntry->usRinRoutTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ if ( f_pChannelModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( pChanEntry->usExtraRinTsiMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usRinTsstIndex, ++ pChanEntry->usExtraRinTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else ++ { ++ if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usRinTsstIndex, ++ pChanEntry->usRinRoutTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Modify SIN port.*/ ++ if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ usSinTsstIndex = f_usNewSinTsstIndex; ++ ++ if ( f_usNewSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ if ( pChanEntry->usExtraSinTsiMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Write the new entry now.*/ ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_usNewSinTsstIndex, ++ pChanEntry->usExtraSinTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulSinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ /* Write the new entry now.*/ ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_usNewSinTsstIndex, ++ pChanEntry->usSinSoutTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulSinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ if ( f_pChannelModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING && ++ f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( pChanEntry->usExtraSinTsiMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usSinTsstIndex , ++ pChanEntry->usExtraSinTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulSinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else ++ { ++ if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usSinTsstIndex , ++ pChanEntry->usSinSoutTsiMemIndex, ++ f_pChannelOpen->TdmConfig.ulSinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Modify ROUT port.*/ ++ if ( ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ || ( f_pChannelModify->TdmConfig.ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ ) ++ { ++ if ( f_usNewRoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ if ( f_pChannelModify->TdmConfig.ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* If this output port is not muted. */ ++ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) ++ { ++ /* Write the new entry now.*/ ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_usNewRoutTsstIndex, ++ pApiCodecConf->byAdpcmNibblePosition, ++ f_pChannelModify->TdmConfig.ulRoutNumTssts, ++ pChanEntry->usRinRoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else ++ { ++ /* If this output port is not muted. */ ++ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) ++ { ++ /* Write the new entry now.*/ ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_usNewRoutTsstIndex, ++ pApiCodecConf->byAdpcmNibblePosition, ++ pApiTdmConf->byRoutNumTssts, ++ pChanEntry->usRinRoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ } ++ ++ /* Modify SOUT port.*/ ++ if ( ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ || ( f_pChannelModify->TdmConfig.ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ ) ++ { ++ if ( f_usNewSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ if ( f_pChannelModify->TdmConfig.ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ /* If this output port is not muted. */ ++ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) ++ { ++ /* Write the new entry now.*/ ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_usNewSoutTsstIndex, ++ pApiCodecConf->byAdpcmNibblePosition, ++ f_pChannelModify->TdmConfig.ulSoutNumTssts, ++ pChanEntry->usSinSoutTsiMemIndex ); ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else ++ { ++ /* If this output port is not muted. */ ++ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) ++ { ++ /* Write the new entry now.*/ ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_usNewSoutTsstIndex, ++ pApiCodecConf->byAdpcmNibblePosition, ++ pApiTdmConf->bySoutNumTssts, ++ pChanEntry->usSinSoutTsiMemIndex ); ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ } ++ ++ ++ ++ } ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Modify the Encoder/Decoder memory if required.*/ ++ ++ if ( f_pChannelModify->fCodecConfigModified == TRUE ) ++ { ++ UINT32 ulCompType = 0; ++ UINT16 usTempTsiMemIndex; ++ UINT16 usDecoderMemIndex; ++ UINT16 usEncoderMemIndex; ++ UINT32 ulPcmLaw; ++ UINT16 usPhasingIndex; ++ BOOL fModifyAdpcmMem = TRUE; ++ ++ /*==============================================================================*/ ++ /* Reprogram the Decoder memory.*/ ++ ++ if ( pChanEntry->CodecConfig.byDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ usDecoderMemIndex = pChanEntry->usRinRoutConversionMemIndex; ++ } ++ else ++ { ++ usDecoderMemIndex = pChanEntry->usSinSoutConversionMemIndex; ++ } ++ ++ if ( pChanEntry->CodecConfig.byEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ usEncoderMemIndex = pChanEntry->usRinRoutConversionMemIndex; ++ } ++ else ++ { ++ usEncoderMemIndex = pChanEntry->usSinSoutConversionMemIndex; ++ } ++ ++ if ( usDecoderMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ switch( f_pChannelOpen->CodecConfig.ulDecodingRate ) ++ { ++ case cOCT6100_G711_64KBPS: ++ ulCompType = 0x8; ++ ++ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ if ( f_pChannelOpen->TdmConfig.ulRinPcmLaw == f_pChannelOpen->TdmConfig.ulRoutPcmLaw ) ++ fModifyAdpcmMem = FALSE; ++ ++ /* Check if both ports are assigned. If not, no law conversion needed here.. */ ++ if ( ( f_pChannelOpen->TdmConfig.ulRinStream == cOCT6100_UNASSIGNED ) ++ || ( f_pChannelOpen->TdmConfig.ulRoutStream == cOCT6100_UNASSIGNED ) ) ++ fModifyAdpcmMem = FALSE; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ++ { ++ if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) ++ fModifyAdpcmMem = FALSE; ++ ++ /* Check if both ports are assigned. If not, no law conversion needed here.. */ ++ if ( ( f_pChannelOpen->TdmConfig.ulSinStream == cOCT6100_UNASSIGNED ) ++ || ( f_pChannelOpen->TdmConfig.ulSoutStream == cOCT6100_UNASSIGNED ) ) ++ fModifyAdpcmMem = FALSE; ++ } ++ ++ break; ++ case cOCT6100_G726_40KBPS: ++ ulCompType = 0x3; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_32KBPS: ++ ulCompType = 0x2; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_24KBPS: ++ ulCompType = 0x1; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_16KBPS: ++ ulCompType = 0x0; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_2C_ENCODED: ++ ulCompType = 0x4; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_3C_ENCODED: ++ ulCompType = 0x5; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_4C_ENCODED: ++ ulCompType = 0x6; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_ENCODED: ++ ulCompType = 0x9; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G726_ENCODED: ++ ulCompType = 0xA; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G727_2C_ENCODED: ++ ulCompType = 0xC; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G727_3C_ENCODED: ++ ulCompType = 0xD; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G711_G727_4C_ENCODED: ++ ulCompType = 0xE; ++ fConversionEnabled = TRUE; ++ break; ++ ++ default: ++ return cOCT6100_ERR_FATAL_D6; ++ } ++ ++ if ( fModifyAdpcmMem == TRUE ) ++ { ++ /* Set the chariot memory based on the selected port.*/ ++ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ usTempTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; ++ ulPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; /* Set the law for later use */ ++ ++ /* Flag the entry as active.*/ ++ *f_pfRinRoutCodecActive = TRUE; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ++ { ++ usTempTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; ++ ulPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; /* Set the law for later use */ ++ ++ /* Flag the entry as active.*/ ++ *f_pfSinSoutCodecActive = TRUE; ++ } ++ ++ ulResult = Oct6100ApiWriteDecoderMemory( f_pApiInstance, ++ usDecoderMemIndex, ++ ulCompType, ++ usTempTsiMemIndex, ++ ulPcmLaw, ++ pApiCodecConf->byAdpcmNibblePosition ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, ++ usDecoderMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Flag the entry as deactivated.*/ ++ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ *f_pfRinRoutCodecActive = FALSE; ++ } ++ else ++ { ++ *f_pfSinSoutCodecActive = FALSE; ++ } ++ } ++ } ++ ++ /*==============================================================================*/ ++ ++ ++ ++ ++ /*==============================================================================*/ ++ /* Reprogram the Encoder memory.*/ ++ ++ if ( usEncoderMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ++ fModifyAdpcmMem = TRUE; ++ ++ /* Set the chariot memory based on the selected port.*/ ++ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ usTempTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; ++ ulPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; /* Set the law for later use */ ++ } ++ else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ usTempTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; ++ ulPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; /* Set the law for later use */ ++ } ++ ++ /* Set the phasing index .*/ ++ if ( f_usNewPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ usPhasingIndex = f_usNewPhasingTsstIndex; ++ else ++ usPhasingIndex = pChanEntry->usPhasingTsstIndex; ++ ++ switch( f_pChannelOpen->CodecConfig.ulEncodingRate ) ++ { ++ case cOCT6100_G711_64KBPS: ++ if ( ulPcmLaw == cOCT6100_PCM_U_LAW ) ++ ulCompType = 0x4; ++ else /* ulPcmLaw == cOCT6100_PCM_A_LAW */ ++ ulCompType = 0x5; ++ ++ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ if ( f_pChannelOpen->TdmConfig.ulRinPcmLaw == f_pChannelOpen->TdmConfig.ulRoutPcmLaw ) ++ fModifyAdpcmMem = FALSE; ++ ++ /* Check if both ports are assigned. If not, no law conversion needed here.. */ ++ if ( ( f_pChannelOpen->TdmConfig.ulRinStream == cOCT6100_UNASSIGNED ) ++ || ( f_pChannelOpen->TdmConfig.ulRoutStream == cOCT6100_UNASSIGNED ) ) ++ fModifyAdpcmMem = FALSE; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) ++ fModifyAdpcmMem = FALSE; ++ ++ /* Check if both ports are assigned. If not, no law conversion needed here.. */ ++ if ( ( f_pChannelOpen->TdmConfig.ulSinStream == cOCT6100_UNASSIGNED ) ++ || ( f_pChannelOpen->TdmConfig.ulSoutStream == cOCT6100_UNASSIGNED ) ) ++ fModifyAdpcmMem = FALSE; ++ } ++ break; ++ case cOCT6100_G726_40KBPS: ++ ulCompType = 0x3; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_32KBPS: ++ ulCompType = 0x2; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_24KBPS: ++ ulCompType = 0x1; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G726_16KBPS: ++ ulCompType = 0x0; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_40KBPS_4_1: ++ ulCompType = 0xD; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_40KBPS_3_2: ++ ulCompType = 0xA; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_40KBPS_2_3: ++ ulCompType = 0x6; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_32KBPS_4_0: ++ ulCompType = 0xE; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_32KBPS_3_1: ++ ulCompType = 0xB; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_32KBPS_2_2: ++ ulCompType = 0x7; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_24KBPS_3_0: ++ ulCompType = 0xC; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_24KBPS_2_1: ++ ulCompType = 0x8; ++ fConversionEnabled = TRUE; ++ break; ++ ++ case cOCT6100_G727_16KBPS_2_0: ++ ulCompType = 0x9; ++ fConversionEnabled = TRUE; ++ break; ++ ++ default: ++ return cOCT6100_ERR_FATAL_D7; ++ } ++ ++ if ( fModifyAdpcmMem == TRUE ) ++ { ++ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ *f_pfRinRoutCodecActive = TRUE; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ *f_pfSinSoutCodecActive = TRUE; ++ } ++ ++ ulResult = Oct6100ApiWriteEncoderMemory( f_pApiInstance, ++ usEncoderMemIndex, ++ ulCompType, ++ usTempTsiMemIndex, ++ f_pChannelOpen->CodecConfig.fEnableSilenceSuppression, ++ pApiCodecConf->byAdpcmNibblePosition, ++ usPhasingIndex, ++ f_pChannelOpen->CodecConfig.ulPhasingType, ++ f_pChannelOpen->CodecConfig.ulPhase ); ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, ++ usEncoderMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ *f_pfRinRoutCodecActive = FALSE; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ *f_pfSinSoutCodecActive = FALSE; ++ } ++ } ++ } ++ ++ /*==============================================================================*/ ++ } ++ ++ ++ ++ ++ /*==============================================================================*/ ++ /* Modify the VQE parameter if required.*/ ++ ++ if ( ( f_pChannelModify->fVqeConfigModified == TRUE ) ++ || ( (UINT8)f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ++ || ( f_pChannelOpen->fEnableToneDisabler != pChanEntry->fEnableToneDisabler ) ) ++ { ++ ulResult = Oct6100ApiWriteVqeMemory( f_pApiInstance, ++ &f_pChannelOpen->VqeConfig, ++ f_pChannelOpen, ++ f_usChanIndex, ++ pChanEntry->usEchoMemIndex, ++ FALSE, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*==============================================================================*/ ++ /* Modify the Echo memory if required.*/ ++ if ( f_pChannelModify->fEnableToneDisabler != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->ulEchoOperationMode != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->TdmConfig.ulRoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || ++ f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ ulResult = Oct6100ApiWriteEchoMemory( f_pApiInstance, ++ &f_pChannelOpen->TdmConfig, ++ f_pChannelOpen, ++ pChanEntry->usEchoMemIndex, ++ pChanEntry->usRinRoutTsiMemIndex, ++ pChanEntry->usSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Synch all the buffer playout field if needed by echo operation mode. */ ++ /* Note that Oct6100ApiWriteVqeMemory does not clear the playout pointers */ ++ /* since the flag is set to FALSE. */ ++ if ( ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE ) ++ && ( ( f_pChannelModify->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_HT_FREEZE ) ++ || ( f_pChannelModify->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN ) ) ) ++ { ++ /* Buffer playout must be stopped. */ ++ fClearPlayoutPointers = TRUE; ++ } ++ } ++ ++ /*==============================================================================*/ ++ /* Modify the Mixer events if law changes are requested. */ ++ ++ if ( pChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX && ++ f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Modify the value according to the new law.*/ ++ if ( f_pChannelModify->TdmConfig.ulSinPcmLaw == cOCT6100_PCM_A_LAW ) ++ WriteParams.usWriteData = (UINT16)( usReadData | ( f_pChannelModify->TdmConfig.ulSinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET )); ++ else ++ WriteParams.usWriteData = (UINT16)( usReadData & (~( f_pChannelModify->TdmConfig.ulSinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET ))); ++ ++ /* Write back the new value.*/ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pChanEntry->usSoutCopyEventIndex != cOCT6100_INVALID_INDEX && ++ f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Modify the value according to the new law.*/ ++ if ( f_pChannelModify->TdmConfig.ulSoutPcmLaw == cOCT6100_PCM_A_LAW ) ++ WriteParams.usWriteData = (UINT16)( usReadData | ( f_pChannelModify->TdmConfig.ulSoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET )); ++ else ++ WriteParams.usWriteData = (UINT16)( usReadData & (~( f_pChannelModify->TdmConfig.ulSoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET ))); ++ ++ /* Write back the new value.*/ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*==============================================================================*/ ++ /* Mute channel if required, this is done on a port basis */ ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, ++ f_usChanIndex, ++ usRinTsstIndex, ++ usSinTsstIndex, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ /* Completely disable tone detection? */ ++ if ( f_pChannelModify->fDisableToneDetection == TRUE ) ++ { ++ /* Check if tone detection has been enabled on this channel. */ ++ for (ulToneConfIndex = 0; ulToneConfIndex < ARRAY_SIZE(pChanEntry->aulToneConf); ulToneConfIndex++) ++ { ++ /* Check if some tone has been activated on this channel. */ ++ if ( pChanEntry->aulToneConf[ ulToneConfIndex ] != 0 ) ++ { ++ tOCT6100_TONE_DETECTION_DISABLE ToneDetectDisable; ++ ++ /* Call the default function to make sure all parameters are assigned default values. */ ++ ulResult = Oct6100ToneDetectionDisableDef( &ToneDetectDisable ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Form channel handle. */ ++ ToneDetectDisable.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ++ ++ /* Disable all tones activated on this channel. */ ++ ToneDetectDisable.fDisableAll = TRUE; ++ ++ /* Call tone detection serialized function. */ ++ ulResult = Oct6100ToneDetectionDisableSer( f_pApiInstance, &ToneDetectDisable ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Get out of the loop, tone detection has been disabled! */ ++ break; ++ } ++ } ++ } ++ ++ /* Hard-stop buffer playout? */ ++ if ( f_pChannelModify->fStopBufferPlayout == TRUE ) ++ { ++ /* Check if playout has been started on the Rout port. */ ++ if ( ( pChanEntry->fRinBufPlaying == TRUE ) || ( pChanEntry->fRinBufAdded == TRUE ) ) ++ { ++ tOCT6100_BUFFER_PLAYOUT_STOP PlayoutStop; ++ ++ /* Call the default function to make sure all parameters are assigned default values. */ ++ ulResult = Oct6100BufferPlayoutStopDef( &PlayoutStop ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Hard stop request. */ ++ PlayoutStop.fStopCleanly = FALSE; ++ ++ /* Form channel handle. */ ++ PlayoutStop.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ++ ++ /* For the Rout port. */ ++ PlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ++ ++ /* Call buffer playout stop serialized function. */ ++ ulResult = Oct6100BufferPlayoutStopSer( f_pApiInstance, &PlayoutStop ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ /* The chip might still be playing a last buffer. Make sure it hard-stops! */ ++ fClearPlayoutPointers = TRUE; ++ } ++ ++ /* Check if playout has been started on the Sout port. */ ++ if ( ( pChanEntry->fSoutBufPlaying == TRUE ) || ( pChanEntry->fSoutBufAdded == TRUE ) ) ++ { ++ tOCT6100_BUFFER_PLAYOUT_STOP PlayoutStop; ++ ++ /* Call the default function to make sure all parameters are assigned default values. */ ++ ulResult = Oct6100BufferPlayoutStopDef( &PlayoutStop ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Hard stop request. */ ++ PlayoutStop.fStopCleanly = FALSE; ++ ++ /* Form channel handle. */ ++ PlayoutStop.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ++ ++ /* For the Rout port. */ ++ PlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; ++ ++ /* Call buffer playout stop serialized function. */ ++ ulResult = Oct6100BufferPlayoutStopSer( f_pApiInstance, &PlayoutStop ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ /* The chip might still be playing a last buffer. Make sure it hard-stops! */ ++ fClearPlayoutPointers = TRUE; ++ } ++ } ++ ++ /* Remove participant from bridge? */ ++ if ( f_pChannelModify->fRemoveConfBridgeParticipant == TRUE ) ++ { ++ /* Check if this channel is on a bridge. */ ++ if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Channel is on a bridge, remove it. */ ++ tOCT6100_CONF_BRIDGE_CHAN_REMOVE BridgeChanRemove; ++ ++ /* Call the default function to make sure all parameters are assigned default values. */ ++ ulResult = Oct6100ConfBridgeChanRemoveDef( &BridgeChanRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Form channel handle. */ ++ BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ++ ++ /* Do not remove all channels, only the one specified. */ ++ BridgeChanRemove.fRemoveAll = FALSE; ++ ++ /* No need to assign conference bridge handle, the remove function will figure it out. */ ++ ++ /* Call conference bridge channel remove serialized function. */ ++ ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY ) ++ { ++ tPOCT6100_API_CHANNEL pTapChanEntry; ++ ++ /* Get a pointer to the tap channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTapChanEntry, pChanEntry->usTapChanIndex ) ++ ++ /* Form tap channel handle. */ ++ BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pTapChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | pChanEntry->usTapChanIndex; ++ ++ ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Re-form original channel handle. */ ++ BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ++ ++ ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ } ++ } ++ ++ /* Remove all broadcast TSSTs? */ ++ if ( f_pChannelModify->fRemoveBroadcastTssts == TRUE ) ++ { ++ /* Check if broadcast TSSTs were used on the Rout port. */ ++ if ( pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry != cOCT6100_INVALID_INDEX ) ++ { ++ tOCT6100_CHANNEL_BROADCAST_TSST_REMOVE BroadcastTsstRemove; ++ ++ ulResult = Oct6100ChannelBroadcastTsstRemoveDef( &BroadcastTsstRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Form channel handle. */ ++ BroadcastTsstRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ++ ++ /* Remove all broadcast TSSTs associated to the current channel. */ ++ BroadcastTsstRemove.fRemoveAll = TRUE; ++ ++ /* On the Rout port. */ ++ BroadcastTsstRemove.ulPort = cOCT6100_CHANNEL_PORT_ROUT; ++ ++ ulResult = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, &BroadcastTsstRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ ++ /* Check if broadcast TSSTs were used on the Sout port. */ ++ if ( pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry != cOCT6100_INVALID_INDEX ) ++ { ++ tOCT6100_CHANNEL_BROADCAST_TSST_REMOVE BroadcastTsstRemove; ++ ++ ulResult = Oct6100ChannelBroadcastTsstRemoveDef( &BroadcastTsstRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Form channel handle. */ ++ BroadcastTsstRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ++ ++ /* Remove all broadcast TSSTs associated to the current channel. */ ++ BroadcastTsstRemove.fRemoveAll = TRUE; ++ ++ /* On the Sout port. */ ++ BroadcastTsstRemove.ulPort = cOCT6100_CHANNEL_PORT_SOUT; ++ ++ ulResult = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, &BroadcastTsstRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Check if have to make sure buffer playout is stopped. */ ++ if ( fClearPlayoutPointers == TRUE ) ++ { ++ tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; ++ ++ Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); ++ ++ BufferPlayoutStop.fStopCleanly = FALSE; ++ BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ++ ++ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( ++ f_pApiInstance, ++ &BufferPlayoutStop, ++ f_usChanIndex, ++ pChanEntry->usEchoMemIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; ++ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( ++ f_pApiInstance, ++ &BufferPlayoutStop, ++ f_usChanIndex, ++ pChanEntry->usEchoMemIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiModifyChannelEntry ++ ++Description: Updates the channel structure in the ECHO channel list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelModify Pointer to echo cancellation channel modify structure. ++f_pChannelOpen Pointer to echo cancellation channel configuration structure. ++f_usChanIndex Index of the channel within the API's channel list. ++f_usNewPhasingTsstIndex Index of the new phasing TSST. ++f_fSinSoutCodecActive State of the SIN/SOUT codec. ++f_fRinRoutCodecActive State of the RIN/ROUT codec. ++f_usNewRinTsstIndex New RIN TSST memory index. ++f_usNewSinTsstIndex New SIN TSST memory index. ++f_usNewRoutTsstIndex New ROUT TSST memory index. ++f_usNewSoutTsstIndex New SOUT TSST memory index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiModifyChannelEntry ++UINT32 Oct6100ApiModifyChannelEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewPhasingTsstIndex, ++ IN UINT8 f_fSinSoutCodecActive, ++ IN UINT8 f_fRinRoutCodecActive, ++ IN UINT16 f_usNewRinTsstIndex, ++ IN UINT16 f_usNewSinTsstIndex, ++ IN UINT16 f_usNewRoutTsstIndex, ++ IN UINT16 f_usNewSoutTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_CHANNEL_CODEC pApiCodecConf; ++ tPOCT6100_API_CHANNEL_TDM pApiTdmConf; ++ tPOCT6100_API_CHANNEL_VQE pApiVqeConf; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ /* Obtain local pointer to the configuration structures of the tPOCT6100_API_CHANNEL structure. */ ++ pApiCodecConf = &pChanEntry->CodecConfig; ++ pApiTdmConf = &pChanEntry->TdmConfig; ++ pApiVqeConf = &pChanEntry->VqeConfig; ++ ++ /*=======================================================================*/ ++ /* Copy the channel's general configuration. */ ++ ++ pChanEntry->ulUserChanId = f_pChannelOpen->ulUserChanId; ++ pChanEntry->byEchoOperationMode = (UINT8)( f_pChannelOpen->ulEchoOperationMode & 0xFF ); ++ pChanEntry->fEnableToneDisabler = (UINT8)( f_pChannelOpen->fEnableToneDisabler & 0xFF ); ++ ++ /* Save the codec state.*/ ++ pChanEntry->fSinSoutCodecActive = (UINT8)( f_fSinSoutCodecActive & 0xFF ); ++ pChanEntry->fRinRoutCodecActive = (UINT8)( f_fRinRoutCodecActive & 0xFF ); ++ ++ /*=======================================================================*/ ++ /* Copy the channel's TDM configuration of all the modified fields. */ ++ ++ if ( f_pChannelModify->fTdmConfigModified == TRUE ) ++ { ++ pApiTdmConf->byRinPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulRinPcmLaw & 0xFF ); ++ pApiTdmConf->bySinPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulSinPcmLaw & 0xFF ); ++ pApiTdmConf->byRoutPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulRoutPcmLaw & 0xFF ); ++ pApiTdmConf->bySoutPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulSoutPcmLaw & 0xFF ); ++ ++ pApiTdmConf->byRinNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulRinNumTssts & 0xFF ); ++ pApiTdmConf->bySinNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulSinNumTssts & 0xFF ); ++ pApiTdmConf->byRoutNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulRoutNumTssts & 0xFF ); ++ pApiTdmConf->bySoutNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulSoutNumTssts & 0xFF ); ++ ++ if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( f_usNewRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ pApiTdmConf->usRinStream = (UINT16)( f_pChannelOpen->TdmConfig.ulRinStream & 0xFFFF ); ++ pApiTdmConf->usRinTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulRinTimeslot & 0xFFFF ); ++ pChanEntry->usRinTsstIndex = f_usNewRinTsstIndex; ++ } ++ else /* f_ulNewRinTsstIndex != cOCT6100_INVALID_INDEX */ ++ { ++ pApiTdmConf->usRinStream = cOCT6100_UNASSIGNED; ++ pApiTdmConf->usRinTimeslot = cOCT6100_UNASSIGNED; ++ pChanEntry->usRinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( f_usNewSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ pApiTdmConf->usSinStream = (UINT16)( f_pChannelOpen->TdmConfig.ulSinStream & 0xFFFF ); ++ pApiTdmConf->usSinTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulSinTimeslot & 0xFFFF ); ++ pChanEntry->usSinTsstIndex = f_usNewSinTsstIndex; ++ } ++ else /* f_ulNewSinTsstIndex != cOCT6100_INVALID_INDEX */ ++ { ++ pApiTdmConf->usSinStream = cOCT6100_UNASSIGNED; ++ pApiTdmConf->usSinTimeslot = cOCT6100_UNASSIGNED; ++ pChanEntry->usSinTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ if ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( f_usNewRoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ pApiTdmConf->usRoutStream = (UINT16)( f_pChannelOpen->TdmConfig.ulRoutStream & 0xFFFF ); ++ pApiTdmConf->usRoutTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulRoutTimeslot & 0xFFFF ); ++ pChanEntry->usRoutTsstIndex = f_usNewRoutTsstIndex; ++ } ++ else /* f_ulNewRoutTsstIndex != cOCT6100_INVALID_INDEX */ ++ { ++ pApiTdmConf->usRoutStream = cOCT6100_UNASSIGNED; ++ pApiTdmConf->usRoutTimeslot = cOCT6100_UNASSIGNED; ++ pChanEntry->usRoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ if ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( f_usNewSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ pApiTdmConf->usSoutStream = (UINT16)( f_pChannelOpen->TdmConfig.ulSoutStream & 0xFFFF ); ++ pApiTdmConf->usSoutTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulSoutTimeslot & 0xFFFF ); ++ pChanEntry->usSoutTsstIndex = f_usNewSoutTsstIndex; ++ } ++ else /* f_ulNewSoutTsstIndex != cOCT6100_INVALID_INDEX */ ++ { ++ pApiTdmConf->usSoutStream = cOCT6100_UNASSIGNED; ++ pApiTdmConf->usSoutTimeslot = cOCT6100_UNASSIGNED; ++ pChanEntry->usSoutTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ ++ /*=======================================================================*/ ++ /* Copy the channel's VQE configuration of all the modified fields. */ ++ ++ if ( f_pChannelModify->fVqeConfigModified == TRUE ) ++ { ++ pApiVqeConf->fEnableNlp = (UINT8)( f_pChannelOpen->VqeConfig.fEnableNlp & 0xFF ); ++ pApiVqeConf->byComfortNoiseMode = (UINT8)( f_pChannelOpen->VqeConfig.ulComfortNoiseMode & 0xFF ); ++ pApiVqeConf->fSinDcOffsetRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fSinDcOffsetRemoval & 0xFF ); ++ pApiVqeConf->fRinDcOffsetRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fRinDcOffsetRemoval & 0xFF ); ++ pApiVqeConf->fRinLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fRinLevelControl & 0xFF ); ++ pApiVqeConf->fSoutLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fSoutLevelControl & 0xFF ); ++ pApiVqeConf->fRinAutomaticLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fRinAutomaticLevelControl & 0xFF ); ++ pApiVqeConf->fSoutAutomaticLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fSoutAutomaticLevelControl & 0xFF ); ++ pApiVqeConf->fRinHighLevelCompensation = (UINT8)( f_pChannelOpen->VqeConfig.fRinHighLevelCompensation & 0xFF ); ++ ++ pApiVqeConf->fSoutAdaptiveNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fSoutAdaptiveNoiseReduction & 0xFF ); ++ pApiVqeConf->fSoutNoiseBleaching = (UINT8)( f_pChannelOpen->VqeConfig.fSoutNoiseBleaching & 0xFF ); ++ pApiVqeConf->fSoutConferencingNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fSoutConferencingNoiseReduction & 0xFF ); ++ pApiVqeConf->chRinLevelControlGainDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lRinLevelControlGainDb & 0xFF ); ++ pApiVqeConf->chSoutLevelControlGainDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lSoutLevelControlGainDb & 0xFF ); ++ pApiVqeConf->chRinAutomaticLevelControlTargetDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lRinAutomaticLevelControlTargetDb & 0xFF ); ++ pApiVqeConf->chSoutAutomaticLevelControlTargetDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb & 0xFF ); ++ pApiVqeConf->chRinHighLevelCompensationThresholdDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lRinHighLevelCompensationThresholdDb & 0xFF ); ++ pApiVqeConf->fEnableTailDisplacement = (UINT8)( f_pChannelOpen->VqeConfig.fEnableTailDisplacement & 0xFF ); ++ pApiVqeConf->usTailDisplacement = (UINT16)( f_pChannelOpen->VqeConfig.ulTailDisplacement & 0xFFFF ); ++ pApiVqeConf->usTailLength = (UINT16)( f_pChannelOpen->VqeConfig.ulTailLength & 0xFFFF ); ++ pApiVqeConf->fAcousticEcho = (UINT8)( f_pChannelOpen->VqeConfig.fAcousticEcho & 0xFF ); ++ pApiVqeConf->fDtmfToneRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fDtmfToneRemoval & 0xFF ); ++ ++ pApiVqeConf->chDefaultErlDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lDefaultErlDb & 0xFF ); ++ pApiVqeConf->chAecDefaultErlDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lAecDefaultErlDb & 0xFF ); ++ pApiVqeConf->usAecTailLength = (UINT16)( f_pChannelOpen->VqeConfig.ulAecTailLength & 0xFFFF ); ++ pApiVqeConf->chAnrSnrEnhancementDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lAnrSnrEnhancementDb & 0xFF ); ++ pApiVqeConf->byAnrVoiceNoiseSegregation = (UINT8)( f_pChannelOpen->VqeConfig.ulAnrVoiceNoiseSegregation & 0xFF ); ++ pApiVqeConf->usToneDisablerVqeActivationDelay = (UINT16)( f_pChannelOpen->VqeConfig.ulToneDisablerVqeActivationDelay & 0xFFFF ); ++ pApiVqeConf->byNonLinearityBehaviorA = (UINT8)( f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorA & 0xFF ); ++ pApiVqeConf->byNonLinearityBehaviorB = (UINT8)( f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorB & 0xFF ); ++ pApiVqeConf->byDoubleTalkBehavior = (UINT8)( f_pChannelOpen->VqeConfig.ulDoubleTalkBehavior & 0xFF ); ++ pApiVqeConf->bySoutAutomaticListenerEnhancementGainDb = (UINT8)( f_pChannelOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb & 0xFF ); ++ pApiVqeConf->bySoutNaturalListenerEnhancementGainDb = (UINT8)( f_pChannelOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb & 0xFF ); ++ pApiVqeConf->fSoutNaturalListenerEnhancement = (UINT8)( f_pChannelOpen->VqeConfig.fSoutNaturalListenerEnhancement & 0xFF ); ++ pApiVqeConf->fRoutNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fRoutNoiseReduction & 0xFF ); ++ pApiVqeConf->chRoutNoiseReductionLevelGainDb = (OCT_INT8)( f_pChannelOpen->VqeConfig.lRoutNoiseReductionLevelGainDb & 0xFF ); ++ pApiVqeConf->fEnableMusicProtection = (UINT8)( f_pChannelOpen->VqeConfig.fEnableMusicProtection & 0xFF ); ++ pApiVqeConf->fIdleCodeDetection = (UINT8)( f_pChannelOpen->VqeConfig.fIdleCodeDetection & 0xFF ); ++ } ++ ++ /*=======================================================================*/ ++ /* Copy the channel's CODEC configuration of all the modified fields. */ ++ if ( f_pChannelModify->fCodecConfigModified == TRUE ) ++ { ++ pApiCodecConf->byAdpcmNibblePosition = (UINT8)( f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition & 0xFF ); ++ pApiCodecConf->byEncoderPort = (UINT8)( f_pChannelOpen->CodecConfig.ulEncoderPort & 0xFF ); ++ pApiCodecConf->byEncodingRate = (UINT8)( f_pChannelOpen->CodecConfig.ulEncodingRate & 0xFF ); ++ pApiCodecConf->byDecoderPort = (UINT8)( f_pChannelOpen->CodecConfig.ulDecoderPort & 0xFF ); ++ pApiCodecConf->byDecodingRate = (UINT8)( f_pChannelOpen->CodecConfig.ulDecodingRate & 0xFF ); ++ pApiCodecConf->fEnableSilenceSuppression = (UINT8)( f_pChannelOpen->CodecConfig.fEnableSilenceSuppression & 0xFF ); ++ pApiCodecConf->byPhase = (UINT8)( f_pChannelOpen->CodecConfig.ulPhase & 0xFF ); ++ pApiCodecConf->byPhasingType = (UINT8)( f_pChannelOpen->CodecConfig.ulPhasingType & 0xFF ); ++ ++ /* Update the API phasing TSST structure */ ++ if ( f_usNewPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ tPOCT6100_API_PHASING_TSST pPhasingTsst; ++ ++ /* Release the previous phasing TSST if the channel was already bound to one.*/ ++ if ( pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, pChanEntry->usPhasingTsstIndex ); ++ ++ pPhasingTsst->usDependencyCnt--; ++ } ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, f_usNewPhasingTsstIndex ); ++ ++ pPhasingTsst->usDependencyCnt++; ++ pChanEntry->usPhasingTsstIndex = f_usNewPhasingTsstIndex; ++ ++ } ++ } ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelBroadcastTsstAddSer ++ ++Description: Assign a TSST to one of the port of an echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstAdd Pointer to TSST assign structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelBroadcastTsstAddSer ++UINT32 Oct6100ChannelBroadcastTsstAddSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd ) ++{ ++ UINT16 usChanIndex; ++ UINT16 usNewTsstIndex; ++ UINT16 usNewTsstEntry; ++ UINT32 ulResult; ++ ++ ulResult = Oct6100ApiCheckChanTsstAddParams( f_pApiInstance, f_pChannelTsstAdd, &usChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReserveTsstAddResources( f_pApiInstance, f_pChannelTsstAdd, usChanIndex, &usNewTsstIndex, &usNewTsstEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiWriteTsstAddStructs( f_pApiInstance, f_pChannelTsstAdd, usChanIndex, usNewTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiUpdateTsstAddChanEntry( f_pApiInstance, f_pChannelTsstAdd, usChanIndex, usNewTsstIndex, usNewTsstEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckChanTsstAddParams ++ ++Description: Verify the validity of the tPOCT6100_CHANNEL_BROADCAST_TSST_ADD ++ structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. ++f_pusChanIndex Pointer to a structure used to store the multiple resources indexes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckChanTsstAddParams ++UINT32 Oct6100ApiCheckChanTsstAddParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, ++ OUT PUINT16 f_pusChanIndex ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulResult; ++ UINT32 ulNumTssts = 1; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check the provided handle. */ ++ if ( (f_pChannelTsstAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ *f_pusChanIndex = (UINT16)( f_pChannelTsstAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelTsstAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ /* validate the port parameter.*/ ++ if ( f_pChannelTsstAdd->ulPort != cOCT6100_CHANNEL_PORT_ROUT && ++ f_pChannelTsstAdd->ulPort != cOCT6100_CHANNEL_PORT_SOUT ) ++ return cOCT6100_ERR_CHANNEL_TSST_ADD_PORT; ++ ++ /* Get the required number of TSST based on the port.*/ ++ switch( f_pChannelTsstAdd->ulPort ) ++ { ++ case cOCT6100_CHANNEL_PORT_ROUT: ++ ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; ++ break; ++ case cOCT6100_CHANNEL_PORT_SOUT: ++ ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_B; ++ } ++ ++ /* Check the validity of the timeslot and stream. */ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ ulNumTssts, ++ f_pChannelTsstAdd->ulTimeslot, ++ f_pChannelTsstAdd->ulStream, ++ cOCT6100_OUTPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_CHANNEL_TSST_ADD_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_CHANNEL_TSST_ADD_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveTsstAddResources ++ ++Description: Reserve the entry for the new broadcast TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. ++f_usChanIndex Channel index within the API's channel list. ++f_pusNewTsstIndex Pointer to the new TSST index within the API's TSST memory. ++f_pusNewTsstEntry Pointer to the new TSST entry within the API's TSST list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveTsstAddResources ++UINT32 Oct6100ApiReserveTsstAddResources( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, ++ IN UINT16 f_usChanIndex, ++ OUT PUINT16 f_pusNewTsstIndex, ++ OUT PUINT16 f_pusNewTsstEntry ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulResult; ++ UINT32 ulNumTssts = 1; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ switch( f_pChannelTsstAdd->ulPort ) ++ { ++ case cOCT6100_CHANNEL_PORT_ROUT: ++ ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; ++ break; ++ case cOCT6100_CHANNEL_PORT_SOUT: ++ ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_C; ++ } ++ ++ /* Reserve the new entry.*/ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ f_pChannelTsstAdd->ulTimeslot, ++ f_pChannelTsstAdd->ulStream, ++ ulNumTssts, ++ cOCT6100_OUTPUT_TSST, ++ f_pusNewTsstIndex, ++ f_pusNewTsstEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteTsstAddStructs ++ ++Description: Configure the TSST control memory for the new TSST entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. ++f_usChanIndex Channel index. ++f_usNewTsstIndex Tsst index in the TSST control memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteTsstAddStructs ++UINT32 Oct6100ApiWriteTsstAddStructs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewTsstIndex ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT16 usTsiMemIndex; ++ UINT32 ulNumTssts = 1; ++ ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ switch( f_pChannelTsstAdd->ulPort ) ++ { ++ case cOCT6100_CHANNEL_PORT_ROUT: ++ usTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; ++ ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; ++ break; ++ case cOCT6100_CHANNEL_PORT_SOUT: ++ usTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; ++ ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_D; ++ } ++ ++ ++ /* Write the new entry now.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usNewTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_OUTPUT_TSST; ++ WriteParams.usWriteData |= (UINT16)( pChanEntry->CodecConfig.byAdpcmNibblePosition << cOCT6100_TSST_CONTROL_MEM_NIBBLE_POS_OFFSET ); ++ WriteParams.usWriteData |= (UINT16)( (ulNumTssts - 1) << cOCT6100_TSST_CONTROL_MEM_TSST_NUM_OFFSET ); ++ WriteParams.usWriteData |= (UINT16)( usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateTsstAddChanEntry ++ ++Description: Update the associated channel API entry to add the new broacast TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstAdd Pointer to echo cancellation channel open configuration structure. ++f_usChanIndex Channel index. ++f_usNewTsstIndex TSST index within the TSST control memory. ++f_usNewTsstEntry TSST entry within the API TSST list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateTsstAddChanEntry ++UINT32 Oct6100ApiUpdateTsstAddChanEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewTsstIndex, ++ IN UINT16 f_usNewTsstEntry ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_TSST_ENTRY pTsstEntry; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, f_usNewTsstEntry ); ++ ++ /* Update the channel entry.*/ ++ if ( f_pChannelTsstAdd->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ /* Add the new TSST entry to the broadcast list.*/ ++ pTsstEntry->usNextEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; ++ pTsstEntry->usTsstMemoryIndex = (UINT16)f_usNewTsstIndex; ++ pTsstEntry->usTsstValue = (UINT16)( (f_pChannelTsstAdd->ulTimeslot << 5) | f_pChannelTsstAdd->ulStream ); ++ ++ /* Modify the first entry pointer.*/ ++ pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = f_usNewTsstEntry; ++ ++ /* Increment the number of broadcast TSST. */ ++ pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry++; ++ ++ } ++ else /* f_pChannelTsstAdd->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ /* Add the new TSST entry to the broadcast list.*/ ++ pTsstEntry->usNextEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; ++ pTsstEntry->usTsstMemoryIndex = (UINT16)f_usNewTsstIndex; ++ pTsstEntry->usTsstValue = (UINT16)( (f_pChannelTsstAdd->ulTimeslot << 5) | f_pChannelTsstAdd->ulStream ); ++ ++ /* Modify the first entry pointer.*/ ++ pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = f_usNewTsstEntry; ++ ++ /* Increment the number of broadcast TSST. */ ++ pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry++; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelBroadcastTsstRemoveSer ++ ++Description: Removes a broadcast TSST from one of the output port of an ++ echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstRemove Pointer to TSST remove structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelBroadcastTsstRemoveSer ++UINT32 Oct6100ChannelBroadcastTsstRemoveSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove) ++{ ++ UINT16 usChanIndex; ++ UINT16 usTsstIndex; ++ UINT16 usTsstEntry; ++ UINT16 usPrevTsstEntry; ++ UINT32 ulResult; ++ ++ ulResult = Oct6100ApiAssertChanTsstRemoveParams( f_pApiInstance, f_pChannelTsstRemove, &usChanIndex, &usTsstIndex, &usTsstEntry, &usPrevTsstEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiInvalidateTsstRemoveStructs( f_pApiInstance, usChanIndex, usTsstIndex, f_pChannelTsstRemove->ulPort, f_pChannelTsstRemove->fRemoveAll ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseTsstRemoveResources( f_pApiInstance, f_pChannelTsstRemove, usChanIndex, usTsstIndex, usTsstEntry, usPrevTsstEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertChanTsstRemoveParams ++ ++Description: Verify the validity of the tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE ++ structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstRemove Pointer to echo cancellation channel open configuration structure. ++f_pulChanIndex Pointer to a channel index. ++f_pulNewTsstIndex Pointer to a TSST index within the TSST control memory. ++f_pulNewTsstEntry Pointer to a TSST entry within the API TSST list. ++f_pulPrevTsstEntry Pointer to the previous TSST entry. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertChanTsstRemoveParams ++UINT32 Oct6100ApiAssertChanTsstRemoveParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, ++ OUT PUINT16 f_pusChanIndex, ++ OUT PUINT16 f_pusTsstIndex, ++ OUT PUINT16 f_pusTsstEntry, ++ OUT PUINT16 f_pusPrevTsstEntry ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_TSST_ENTRY pTsstEntry; ++ UINT32 ulResult; ++ UINT32 ulNumTssts = 1; ++ UINT32 ulEntryOpenCnt; ++ UINT16 usCurrentEntry; ++ UINT16 usTsstValue; ++ UINT16 usNumEntry; ++ ++ /* Check the provided handle. */ ++ if ( (f_pChannelTsstRemove->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ *f_pusChanIndex = (UINT16)( f_pChannelTsstRemove->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelTsstRemove->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ /* validate the port parameter.*/ ++ if ( f_pChannelTsstRemove->ulPort != cOCT6100_CHANNEL_PORT_ROUT && ++ f_pChannelTsstRemove->ulPort != cOCT6100_CHANNEL_PORT_SOUT ) ++ return cOCT6100_ERR_CHANNEL_TSST_REMOVE_PORT; ++ ++ /* Verify that the requested entry is present in the channel's port broadcast TSST.*/ ++ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; ++ usNumEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry; ++ } ++ else /* f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; ++ usNumEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry; ++ } ++ ++ /* Verify if at least one TSST is present on the channel port.*/ ++ if ( usNumEntry == 0 ) ++ return cOCT6100_ERR_CHANNEL_TSST_REMOVE_NO_BROADCAST_TSST; ++ ++ /* Get the required number of TSST based on the port.*/ ++ switch( f_pChannelTsstRemove->ulPort ) ++ { ++ case cOCT6100_CHANNEL_PORT_ROUT: ++ ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; ++ break; ++ case cOCT6100_CHANNEL_PORT_SOUT: ++ ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_E; ++ } ++ ++ /* Initialize the TSST entry to invalid.*/ ++ *f_pusTsstEntry = cOCT6100_INVALID_INDEX; ++ *f_pusPrevTsstEntry = cOCT6100_INVALID_INDEX; ++ *f_pusTsstIndex = cOCT6100_INVALID_INDEX; ++ ++ if ( f_pChannelTsstRemove->fRemoveAll != TRUE ) ++ { ++ /* Check the validity of the timeslot and Stream.*/ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ ulNumTssts, ++ f_pChannelTsstRemove->ulTimeslot, ++ f_pChannelTsstRemove->ulStream, ++ cOCT6100_OUTPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_CHANNEL_TSST_REMOVE_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_CHANNEL_TSST_REMOVE_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ ++ /* Set the TSST value based on the timeslot and stream value.*/ ++ usTsstValue = (UINT16)( (f_pChannelTsstRemove->ulTimeslot << 5) | f_pChannelTsstRemove->ulStream ); ++ ++ while( usCurrentEntry != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ if ( usTsstValue == pTsstEntry->usTsstValue ) ++ { ++ /* A match was found.*/ ++ *f_pusTsstEntry = usCurrentEntry; ++ *f_pusTsstIndex = pTsstEntry->usTsstMemoryIndex; ++ break; ++ } ++ ++ /* Move on to the next entry.*/ ++ *f_pusPrevTsstEntry = usCurrentEntry; ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ } ++ ++ if ( *f_pusTsstEntry == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_TSST_REMOVE_INVALID_TSST; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidateTsstRemoveStructs ++ ++Description: Invalidate the entry of the broadcast TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usChanIndex Channel index. ++f_usTsstIndex TSST index within the TSST control memory. ++f_ulPort Channel port where the TSST are removed from. (only used if remove all == TRUE) ++f_fRemoveAll Remove all flag. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidateTsstRemoveStructs ++UINT32 Oct6100ApiInvalidateTsstRemoveStructs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usTsstIndex, ++ IN UINT32 f_ulPort, ++ IN BOOL f_fRemoveAll ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ if ( f_fRemoveAll == FALSE ) ++ { ++ /* Deactivate the entry now.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else /* f_fRemoveAll == TRUE */ ++ { ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_TSST_ENTRY pTsstEntry; ++ UINT16 usTsstEntry; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ /* Clear all entry associated to the selected port.*/ ++ if ( f_ulPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ usTsstEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; ++ else ++ usTsstEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; ++ ++ do ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usTsstEntry ); ++ ++ /* Deactivate the entry now.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( ( pTsstEntry->usTsstMemoryIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usTsstEntry = pTsstEntry->usNextEntry; ++ ++ } while ( usTsstEntry != cOCT6100_INVALID_INDEX ); ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseTsstRemoveResources ++ ++Description: Release all API resources associated to the Removed TSST and ++ update the channel entry accordingly. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelTsstRemove Pointer to echo cancellation channel open configuration structure. ++f_usChanIndex Channel index. ++f_usTsstIndex TSST index within the TSST control memory. ++f_usTsstEntry TSST entry within the API's TSST list. ++f_usPrevTsstEntry Previous TSST entry within the API's TSST list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseTsstRemoveResources ++UINT32 Oct6100ApiReleaseTsstRemoveResources( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usTsstIndex, ++ IN UINT16 f_usTsstEntry, ++ IN UINT16 f_usPrevTsstEntry ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_TSST_ENTRY pTsstEntry; ++ tPOCT6100_API_TSST_ENTRY pPrevTsstEntry; ++ UINT16 usCurrentEntry; ++ UINT32 ulResult; ++ UINT32 ulTimeslot; ++ UINT32 ulStream; ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ if ( f_pChannelTsstRemove->fRemoveAll == FALSE ) ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, f_usTsstEntry ); ++ ++ /* Update the channel entry.*/ ++ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ /* Check if the entry was the first in the list.*/ ++ if ( f_usPrevTsstEntry == cOCT6100_INVALID_INDEX ) ++ { ++ pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = pTsstEntry->usNextEntry; ++ } ++ else /* f_ulPrevTsstEntry != cOCT6100_INVALID_INDEX */ ++ { ++ /* Get a pointer to the previous entry.*/ ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPrevTsstEntry, f_usPrevTsstEntry ); ++ pPrevTsstEntry->usNextEntry = pTsstEntry->usNextEntry; ++ } ++ ++ /* Decrement the number of entry.*/ ++ pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry--; ++ } ++ else /* f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ /* Check if the entry was the first in the list.*/ ++ if ( f_usPrevTsstEntry == cOCT6100_INVALID_INDEX ) ++ { ++ pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = pTsstEntry->usNextEntry; ++ } ++ else /* f_ulPrevTsstEntry != cOCT6100_INVALID_INDEX */ ++ { ++ /* Get a pointer to the previous entry.*/ ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPrevTsstEntry, f_usPrevTsstEntry ); ++ pPrevTsstEntry->usNextEntry = pTsstEntry->usNextEntry; ++ } ++ ++ /* Decrement the number of entry.*/ ++ pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry--; ++ } ++ ++ ulTimeslot = pTsstEntry->usTsstValue >> 5; ++ ulStream = pTsstEntry->usTsstValue & 0x1F; ++ ++ /* Release the entry.*/ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ ulTimeslot, ++ ulStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_OUTPUT_TSST, ++ f_usTsstEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else /* f_pChannelTsstRemove->fRemoveAll == TRUE */ ++ { ++ ++ /* Update the channel entry.*/ ++ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; ++ else ++ usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; ++ ++ do ++ { ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ ulTimeslot = pTsstEntry->usTsstValue >> 5; ++ ulStream = pTsstEntry->usTsstValue & 0x1F; ++ ++ /* Release the entry.*/ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ ulTimeslot, ++ ulStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_OUTPUT_TSST, ++ usCurrentEntry ); /* Release the entry.*/ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ ++ /* Clear the previous node.*/ ++ pTsstEntry->usTsstMemoryIndex = 0xFFFF; ++ pTsstEntry->usTsstValue = 0xFFFF; ++ pTsstEntry->usNextEntry = cOCT6100_INVALID_INDEX; ++ ++ } while ( usCurrentEntry != cOCT6100_INVALID_INDEX ); ++ ++ /* Reset the channel status.*/ ++ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; ++ pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry = 0; ++ } ++ else ++ { ++ pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; ++ pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry = 0; ++ } ++ } ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiChannelGetStatsSer ++ ++Description: Serialized function that returns all the stats of the specified ++ channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelStats Pointer to a channel stats structure. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiChannelGetStatsSer ++UINT32 Oct6100ApiChannelGetStatsSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_STATS f_pChannelStats ) ++{ ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_READ_BURST_PARAMS BurstParams; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_TSST_ENTRY pTsstEntry; ++ UINT32 ulEntryOpenCnt; ++ UINT16 usCurrentEntry; ++ UINT16 usTsstCount; ++ UINT32 ulBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulTempData; ++ UINT32 ulMask; ++ UINT16 usChanIndex; ++ UINT16 ausReadData[ 32 ]; ++ ++ BYTE byRinEnergyRaw; ++ BYTE bySinEnergyRaw; ++ BYTE bySoutEnergyRaw; ++ INT32 lSoutEnergyIndB; ++ BYTE byCnEnergyRaw; ++ UINT16 usEchoDelayInFrames; ++ UINT16 usErlRaw; ++ ++ UINT32 ulResult; ++ UINT16 usReadData; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ BurstParams.pusReadData = ausReadData; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Check the reset stats flag.*/ ++ if ( f_pChannelStats->fResetStats != TRUE && f_pChannelStats->fResetStats != FALSE ) ++ return cOCT6100_ERR_CHANNEL_STATS_RESET; ++ ++ /* Check the provided handle. */ ++ if ( cOCT6100_HNDL_TAG_CHANNEL != (f_pChannelStats->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ usChanIndex = (UINT16)( f_pChannelStats->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( usChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, usChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelStats->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ /* Check the value of the max broadcast tsst.*/ ++ if ( f_pChannelStats->TdmConfig.ulMaxBroadcastTssts > cOCT6100_MAX_TSSTS ) ++ return cOCT6100_ERR_CHANNEL_GET_STATS_MAX_BROADCAST_TSST; ++ ++ if ( f_pChannelStats->TdmConfig.ulMaxBroadcastTssts != 0 ) ++ { ++ /* Check if memory was allocated by the user for the stream and timeslot values.*/ ++ if ( f_pChannelStats->TdmConfig.pulRoutBroadcastTimeslot == NULL ) ++ return cOCT6100_ERR_CHANNEL_ROUT_BROADCAST_TIMESLOT; ++ ++ if ( f_pChannelStats->TdmConfig.pulRoutBroadcastStream == NULL ) ++ return cOCT6100_ERR_CHANNEL_ROUT_BROADCAST_STREAM; ++ ++ if ( f_pChannelStats->TdmConfig.pulSoutBroadcastTimeslot == NULL ) ++ return cOCT6100_ERR_CHANNEL_SOUT_BROADCAST_TIMESLOT; ++ ++ if ( f_pChannelStats->TdmConfig.pulSoutBroadcastStream == NULL ) ++ return cOCT6100_ERR_CHANNEL_SOUT_BROADCAST_STREAM; ++ } ++ ++ /* Copy the general configuration.*/ ++ f_pChannelStats->ulUserChanId = pChanEntry->ulUserChanId; ++ f_pChannelStats->ulEchoOperationMode = pChanEntry->byEchoOperationMode; ++ f_pChannelStats->fEnableToneDisabler = pChanEntry->fEnableToneDisabler; ++ f_pChannelStats->ulMutePortsMask = pChanEntry->usMutedPorts; ++ f_pChannelStats->fEnableExtToneDetection = pChanEntry->fEnableExtToneDetection; ++ ++ ++ ++ /* Copy the TDM configuration.*/ ++ f_pChannelStats->TdmConfig.ulNumRoutBroadcastTssts = pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry; ++ f_pChannelStats->TdmConfig.ulNumSoutBroadcastTssts = pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry; ++ ++ f_pChannelStats->TdmConfig.ulSinNumTssts = pChanEntry->TdmConfig.bySinNumTssts; ++ f_pChannelStats->TdmConfig.ulSinTimeslot = pChanEntry->TdmConfig.usSinTimeslot; ++ f_pChannelStats->TdmConfig.ulSinStream = pChanEntry->TdmConfig.usSinStream; ++ f_pChannelStats->TdmConfig.ulSinPcmLaw = pChanEntry->TdmConfig.bySinPcmLaw; ++ ++ f_pChannelStats->TdmConfig.ulSoutNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; ++ f_pChannelStats->TdmConfig.ulSoutTimeslot = pChanEntry->TdmConfig.usSoutTimeslot; ++ f_pChannelStats->TdmConfig.ulSoutStream = pChanEntry->TdmConfig.usSoutStream; ++ f_pChannelStats->TdmConfig.ulSoutPcmLaw = pChanEntry->TdmConfig.bySoutPcmLaw; ++ ++ /* Copy the SOUT Broadcast TSST into the Stream and timeslot array.*/ ++ usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; ++ for( usTsstCount = 0; (usTsstCount < pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry) && (usTsstCount < f_pChannelStats->TdmConfig.ulMaxBroadcastTssts); usTsstCount++ ) ++ { ++ if ( usCurrentEntry == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_FATAL_F; ++ ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ f_pChannelStats->TdmConfig.pulSoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue & 0x1F; ++ f_pChannelStats->TdmConfig.pulSoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue >> 5; ++ ++ /* Obtain the index of the next entry.*/ ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ } ++ ++ /* Check if all Sout Broadcast TSST were returned.*/ ++ if ( usTsstCount < pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry ) ++ { ++ f_pChannelStats->TdmConfig.fMoreSoutBroadcastTssts = TRUE; ++ } ++ else /* usTsstCount >= pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry */ ++ { ++ f_pChannelStats->TdmConfig.fMoreSoutBroadcastTssts = FALSE; ++ } ++ ++ f_pChannelStats->TdmConfig.ulRinNumTssts = pChanEntry->TdmConfig.byRinNumTssts; ++ f_pChannelStats->TdmConfig.ulRinTimeslot = pChanEntry->TdmConfig.usRinTimeslot; ++ f_pChannelStats->TdmConfig.ulRinStream = pChanEntry->TdmConfig.usRinStream; ++ f_pChannelStats->TdmConfig.ulRinPcmLaw = pChanEntry->TdmConfig.byRinPcmLaw; ++ ++ f_pChannelStats->TdmConfig.ulRoutNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; ++ f_pChannelStats->TdmConfig.ulRoutTimeslot = pChanEntry->TdmConfig.usRoutTimeslot; ++ f_pChannelStats->TdmConfig.ulRoutStream = pChanEntry->TdmConfig.usRoutStream; ++ f_pChannelStats->TdmConfig.ulRoutPcmLaw = pChanEntry->TdmConfig.byRoutPcmLaw; ++ ++ ++ /* Copy the ROUT Broadcast TSST into the Stream and timeslot array.*/ ++ usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; ++ for( usTsstCount = 0; (usTsstCount < pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry) && (usTsstCount < f_pChannelStats->TdmConfig.ulMaxBroadcastTssts); usTsstCount++ ) ++ { ++ if ( usCurrentEntry == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_FATAL_10; ++ ++ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); ++ ++ f_pChannelStats->TdmConfig.pulRoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue & 0x1F; ++ f_pChannelStats->TdmConfig.pulRoutBroadcastStream[ usTsstCount ] = pTsstEntry->usTsstValue >> 5; ++ ++ /* Obtain the index of the next entry.*/ ++ usCurrentEntry = pTsstEntry->usNextEntry; ++ } ++ ++ /* Check if all Rout Broadcast TSST were returned.*/ ++ if ( usTsstCount < pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry ) ++ { ++ f_pChannelStats->TdmConfig.fMoreRoutBroadcastTssts = TRUE; ++ } ++ else /* usTsstCount >= pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry */ ++ { ++ f_pChannelStats->TdmConfig.fMoreRoutBroadcastTssts = FALSE; ++ } ++ ++ /* Copy the VQE configuration.*/ ++ f_pChannelStats->VqeConfig.fEnableNlp = pChanEntry->VqeConfig.fEnableNlp; ++ f_pChannelStats->VqeConfig.ulComfortNoiseMode = pChanEntry->VqeConfig.byComfortNoiseMode; ++ f_pChannelStats->VqeConfig.fEnableTailDisplacement = pChanEntry->VqeConfig.fEnableTailDisplacement; ++ if ( pChanEntry->VqeConfig.usTailDisplacement != cOCT6100_AUTO_SELECT_TAIL ) ++ f_pChannelStats->VqeConfig.ulTailDisplacement = pChanEntry->VqeConfig.usTailDisplacement; ++ else ++ f_pChannelStats->VqeConfig.ulTailDisplacement = f_pApiInstance->pSharedInfo->ChipConfig.usTailDisplacement; ++ ++ if ( pChanEntry->VqeConfig.usTailLength != cOCT6100_AUTO_SELECT_TAIL ) ++ f_pChannelStats->VqeConfig.ulTailLength = pChanEntry->VqeConfig.usTailLength; ++ else ++ f_pChannelStats->VqeConfig.ulTailLength = f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailLength; ++ ++ ++ ++ f_pChannelStats->VqeConfig.fSinDcOffsetRemoval = pChanEntry->VqeConfig.fSinDcOffsetRemoval; ++ f_pChannelStats->VqeConfig.fRinDcOffsetRemoval = pChanEntry->VqeConfig.fRinDcOffsetRemoval; ++ f_pChannelStats->VqeConfig.fRinLevelControl = pChanEntry->VqeConfig.fRinLevelControl; ++ f_pChannelStats->VqeConfig.fSoutLevelControl = pChanEntry->VqeConfig.fSoutLevelControl; ++ f_pChannelStats->VqeConfig.fRinAutomaticLevelControl = pChanEntry->VqeConfig.fRinAutomaticLevelControl; ++ f_pChannelStats->VqeConfig.fSoutAutomaticLevelControl = pChanEntry->VqeConfig.fSoutAutomaticLevelControl; ++ f_pChannelStats->VqeConfig.fRinHighLevelCompensation = pChanEntry->VqeConfig.fRinHighLevelCompensation; ++ f_pChannelStats->VqeConfig.fSoutAdaptiveNoiseReduction = pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction; ++ f_pChannelStats->VqeConfig.fSoutNoiseBleaching = pChanEntry->VqeConfig.fSoutNoiseBleaching; ++ f_pChannelStats->VqeConfig.fSoutConferencingNoiseReduction = pChanEntry->VqeConfig.fSoutConferencingNoiseReduction; ++ f_pChannelStats->VqeConfig.lRinLevelControlGainDb = pChanEntry->VqeConfig.chRinLevelControlGainDb; ++ f_pChannelStats->VqeConfig.lSoutLevelControlGainDb = pChanEntry->VqeConfig.chSoutLevelControlGainDb; ++ f_pChannelStats->VqeConfig.lRinAutomaticLevelControlTargetDb = pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb; ++ f_pChannelStats->VqeConfig.lSoutAutomaticLevelControlTargetDb = pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb; ++ f_pChannelStats->VqeConfig.lRinHighLevelCompensationThresholdDb = pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb; ++ f_pChannelStats->VqeConfig.fAcousticEcho = pChanEntry->VqeConfig.fAcousticEcho; ++ f_pChannelStats->VqeConfig.fDtmfToneRemoval = pChanEntry->VqeConfig.fDtmfToneRemoval; ++ ++ f_pChannelStats->VqeConfig.lDefaultErlDb = pChanEntry->VqeConfig.chDefaultErlDb; ++ f_pChannelStats->VqeConfig.lAecDefaultErlDb = pChanEntry->VqeConfig.chAecDefaultErlDb; ++ f_pChannelStats->VqeConfig.ulAecTailLength = pChanEntry->VqeConfig.usAecTailLength; ++ f_pChannelStats->VqeConfig.lAnrSnrEnhancementDb = pChanEntry->VqeConfig.chAnrSnrEnhancementDb; ++ f_pChannelStats->VqeConfig.ulAnrVoiceNoiseSegregation = pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation; ++ f_pChannelStats->VqeConfig.ulToneDisablerVqeActivationDelay = pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay; ++ f_pChannelStats->VqeConfig.ulNonLinearityBehaviorA = pChanEntry->VqeConfig.byNonLinearityBehaviorA; ++ f_pChannelStats->VqeConfig.ulNonLinearityBehaviorB = pChanEntry->VqeConfig.byNonLinearityBehaviorB; ++ f_pChannelStats->VqeConfig.ulDoubleTalkBehavior = pChanEntry->VqeConfig.byDoubleTalkBehavior; ++ f_pChannelStats->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb; ++ f_pChannelStats->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb; ++ f_pChannelStats->VqeConfig.fSoutNaturalListenerEnhancement = pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement; ++ f_pChannelStats->VqeConfig.fRoutNoiseReduction = pChanEntry->VqeConfig.fRoutNoiseReduction; ++ f_pChannelStats->VqeConfig.lRoutNoiseReductionLevelGainDb = pChanEntry->VqeConfig.chRoutNoiseReductionLevelGainDb; ++ f_pChannelStats->VqeConfig.fEnableMusicProtection = pChanEntry->VqeConfig.fEnableMusicProtection; ++ f_pChannelStats->VqeConfig.fIdleCodeDetection = pChanEntry->VqeConfig.fIdleCodeDetection; ++ ++ /* Copy the CODEC configuration.*/ ++ f_pChannelStats->CodecConfig.ulAdpcmNibblePosition = pChanEntry->CodecConfig.byAdpcmNibblePosition; ++ ++ f_pChannelStats->CodecConfig.ulEncoderPort = pChanEntry->CodecConfig.byEncoderPort; ++ f_pChannelStats->CodecConfig.ulEncodingRate = pChanEntry->CodecConfig.byEncodingRate; ++ ++ f_pChannelStats->CodecConfig.ulDecoderPort = pChanEntry->CodecConfig.byDecoderPort; ++ f_pChannelStats->CodecConfig.ulDecodingRate = pChanEntry->CodecConfig.byDecodingRate; ++ ++ f_pChannelStats->CodecConfig.fEnableSilenceSuppression = pChanEntry->CodecConfig.fEnableSilenceSuppression; ++ f_pChannelStats->CodecConfig.ulPhase = pChanEntry->CodecConfig.byPhase; ++ f_pChannelStats->CodecConfig.ulPhasingType = pChanEntry->CodecConfig.byPhasingType; ++ ++ if ( pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ tPOCT6100_API_PHASING_TSST pPhasingTsstEntry; ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingTsstEntry, pChanEntry->usPhasingTsstIndex ); ++ ++ f_pChannelStats->CodecConfig.ulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingTsstEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pChanEntry->usPhasingTsstIndex; ++ } ++ else ++ { ++ f_pChannelStats->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; ++ } ++ ++ ++ /* Reset the stats and exit if the reset flag is set.*/ ++ if ( f_pChannelStats->fResetStats == TRUE ) ++ { ++ pChanEntry->sMaxERLE = cOCT6100_INVALID_SIGNED_STAT_W; ++ pChanEntry->sMaxERL = cOCT6100_INVALID_SIGNED_STAT_W; ++ pChanEntry->usMaxEchoDelay = cOCT6100_INVALID_STAT_W; ++ } ++ ++ /*---------------------------------------------------------------------*/ ++ /* Update the API internal stats.*/ ++ ++ BurstParams.ulReadAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + (usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ BurstParams.ulReadAddress += f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsOfst; ++ BurstParams.ulReadLength = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsSize / 2; /* Length in words.*/ ++ ++ mOCT6100_DRIVER_READ_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the energy stat are found in the new memory location. */ ++ if ( ( pSharedInfo->ImageInfo.fRinEnergyStat == TRUE ) ++ && ( pSharedInfo->ImageInfo.fSoutEnergyStat == TRUE ) ) ++ { ++ ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst.byBitOffset; ++ ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst.byFieldSize; ++ ++ ReadParams.ulReadAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + (usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ReadParams.ulReadAddress += f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst + ulFeatureBytesOffset; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ /* Must read in memory directly since this value is changed by hardware */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ /* Clear previous value set in the feature field. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= ulMask; ++ ++ /* Shift to get value. */ ++ ulTempData = ulTempData >> ulFeatureBitOffset; ++ ++ /* Overwrite value read the old way. */ ++ ausReadData[ 0 ] &= 0x00FF; ++ ausReadData[ 0 ] |= (UINT16)( ( ulTempData << 8 ) & 0xFF00 ); ++ ++ ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst.byBitOffset; ++ ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst.byFieldSize; ++ ++ ReadParams.ulReadAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + (usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ReadParams.ulReadAddress += f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst + ulFeatureBytesOffset; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ /* Must read in memory directly since this value is changed by hardware */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ /* Clear previous value set in the feature field. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= ulMask; ++ ++ /* Shift to get value. */ ++ ulTempData = ulTempData >> ulFeatureBitOffset; ++ ++ /* Overwrite value read the old way. */ ++ ausReadData[ 1 ] &= 0x00FF; ++ ausReadData[ 1 ] |= (UINT16)( ( ulTempData << 8 ) & 0xFF00 ); ++ } ++ ++ byRinEnergyRaw = (BYTE)(( ausReadData[ 0 ] >> 8 ) & 0xFF); ++ bySinEnergyRaw = (BYTE)(( ausReadData[ 0 ] >> 0 ) & 0xFF); ++ bySoutEnergyRaw = (BYTE)(( ausReadData[ 1 ] >> 8 ) & 0xFF); ++ byCnEnergyRaw = (BYTE)(( ausReadData[ 5 ] >> 8 ) & 0xFF); ++ ++ usEchoDelayInFrames = (UINT16)(ausReadData[ 4 ]); ++ usErlRaw = ausReadData[ 2 ]; ++ ++ pChanEntry->byToneDisablerStatus = (UINT8)(( ausReadData[ 5 ] >> 0 ) & 0xFF); ++ if ( f_pChannelStats->fResetStats == TRUE ) ++ { ++ pChanEntry->usNumEchoPathChangesOfst = (UINT16)(ausReadData[ 3 ]); ++ pChanEntry->usNumEchoPathChanges = 0; ++ } ++ else /* if ( f_pChannelStats->fResetStats == FALSE ) */ ++ { ++ pChanEntry->usNumEchoPathChanges = (UINT16)( ausReadData[ 3 ] - pChanEntry->usNumEchoPathChangesOfst ); ++ } ++ ++ pChanEntry->sComfortNoiseLevel = (INT16)( Oct6100ApiOctFloatToDbEnergyByte( byCnEnergyRaw ) & 0xFFFF ); ++ pChanEntry->sComfortNoiseLevel -= 12; ++ pChanEntry->sRinLevel = (INT16)( Oct6100ApiOctFloatToDbEnergyByte( byRinEnergyRaw ) & 0xFFFF ); ++ pChanEntry->sRinLevel -= 12; ++ pChanEntry->sSinLevel = (INT16)( Oct6100ApiOctFloatToDbEnergyByte( bySinEnergyRaw ) & 0xFFFF ); ++ pChanEntry->sSinLevel -= 12; ++ lSoutEnergyIndB = Oct6100ApiOctFloatToDbEnergyByte( bySoutEnergyRaw ); ++ lSoutEnergyIndB -= 12; ++ ++ /* Process some stats only if the channel is converged.*/ ++ if ( ( usEchoDelayInFrames != cOCT6100_INVALID_ECHO_DELAY ) ++ && ( pChanEntry->byEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN ) ++ && ( pChanEntry->byEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET ) ) ++ { ++ /* Update the current ERL. */ ++ pChanEntry->sCurrentERL = (INT16)( Oct6100ApiOctFloatToDbEnergyHalf( usErlRaw ) & 0xFFFF ); ++ pChanEntry->sCurrentERLE = (INT16)( ( lSoutEnergyIndB - pChanEntry->sSinLevel ) & 0xFFFF ); ++ pChanEntry->usCurrentEchoDelay = (UINT16)( usEchoDelayInFrames / 8 ); /* To convert in msec.*/ ++ ++ /* Update the max value if required.*/ ++ if ( pChanEntry->usCurrentEchoDelay > pChanEntry->usMaxEchoDelay || ++ pChanEntry->usMaxEchoDelay == cOCT6100_INVALID_STAT_W ) ++ { ++ pChanEntry->usMaxEchoDelay = pChanEntry->usCurrentEchoDelay; ++ } ++ ++ if ( pChanEntry->sCurrentERL > pChanEntry->sMaxERL || ++ pChanEntry->sMaxERL == cOCT6100_INVALID_SIGNED_STAT_W ) ++ { ++ pChanEntry->sMaxERL = pChanEntry->sCurrentERL; ++ } ++ ++ if ( pChanEntry->sCurrentERLE > pChanEntry->sMaxERLE || ++ pChanEntry->sMaxERLE == cOCT6100_INVALID_SIGNED_STAT_W ) ++ { ++ pChanEntry->sMaxERLE = pChanEntry->sCurrentERLE; ++ } ++ } ++ else ++ { ++ pChanEntry->sCurrentERLE = cOCT6100_INVALID_SIGNED_STAT_W; ++ pChanEntry->sCurrentERL = cOCT6100_INVALID_SIGNED_STAT_W; ++ pChanEntry->usCurrentEchoDelay = cOCT6100_INVALID_STAT_W; ++ } ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fRinAppliedGainStat == TRUE ) ++ { ++ /* Calculate base address for auto level control + high level compensation configuration. */ ++ ulBaseAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + ( usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; ++ ++ ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst.byBitOffset; ++ ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst.byFieldSize; ++ ++ ReadParams.ulReadAddress = ulBaseAddress + ulFeatureBytesOffset; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ /* Must read in memory directly since this value is changed by hardware */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= ulMask; ++ ++ /* Shift to get value. */ ++ ulTempData = ulTempData >> ulFeatureBitOffset; ++ ++ pChanEntry->sRinAppliedGain = (INT16)( 2 * (INT16)( Oct6100ApiOctFloatToDbEnergyHalf( (UINT16)( ulTempData & 0xFFFF ) ) & 0xFFFF ) ); ++ } ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fSoutAppliedGainStat == TRUE ) ++ { ++ /* Calculate base address for auto level control + high level compensation configuration. */ ++ ulBaseAddress = f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase + ( usChanIndex * f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; ++ ++ ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst.byBitOffset; ++ ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst.byFieldSize; ++ ++ ReadParams.ulReadAddress = ulBaseAddress + ulFeatureBytesOffset; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ /* Must read in memory directly since this value is changed by hardware */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulFeatureBitOffset < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ /* Clear previous value set in the feature field. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= ulMask; ++ ++ /* Shift to get value. */ ++ ulTempData = ulTempData >> ulFeatureBitOffset; ++ ++ pChanEntry->sSoutAppliedGain = (INT16)( 2 * (INT16)( Oct6100ApiOctFloatToDbEnergyHalf( (UINT16)( ulTempData & 0xFFFF ) ) & 0xFFFF ) ); ++ } ++ ++ /*---------------------------------------------------------------------*/ ++ /* Return the real stats.*/ ++ ++ f_pChannelStats->ulNumEchoPathChanges = pChanEntry->usNumEchoPathChanges; ++ if ( usEchoDelayInFrames != cOCT6100_INVALID_ECHO_DELAY ) ++ { ++ f_pChannelStats->fEchoCancellerConverged = TRUE; ++ } ++ else ++ { ++ f_pChannelStats->fEchoCancellerConverged = FALSE; ++ } ++ if ( pChanEntry->sCurrentERL == cOCT6100_INVALID_SIGNED_STAT_W ) ++ f_pChannelStats->lCurrentERL = cOCT6100_INVALID_SIGNED_STAT; ++ else ++ f_pChannelStats->lCurrentERL = pChanEntry->sCurrentERL; ++ ++ if ( pChanEntry->sMaxERL == cOCT6100_INVALID_SIGNED_STAT_W ) ++ f_pChannelStats->lMaxERL = cOCT6100_INVALID_SIGNED_STAT; ++ else ++ f_pChannelStats->lMaxERL = pChanEntry->sMaxERL; ++ ++ if ( pChanEntry->usMaxEchoDelay == cOCT6100_INVALID_STAT_W ) ++ f_pChannelStats->ulMaxEchoDelay = cOCT6100_INVALID_STAT; ++ else ++ f_pChannelStats->ulMaxEchoDelay = pChanEntry->usMaxEchoDelay; ++ ++ if ( pChanEntry->sRinLevel == cOCT6100_INVALID_SIGNED_STAT_W ) ++ f_pChannelStats->lRinLevel = cOCT6100_INVALID_SIGNED_STAT; ++ else ++ f_pChannelStats->lRinLevel = pChanEntry->sRinLevel; ++ ++ if ( pSharedInfo->ImageInfo.fSinLevel == TRUE ) ++ { ++ if ( pChanEntry->sSinLevel == cOCT6100_INVALID_SIGNED_STAT_W ) ++ f_pChannelStats->lSinLevel = cOCT6100_INVALID_SIGNED_STAT; ++ else ++ f_pChannelStats->lSinLevel = pChanEntry->sSinLevel; ++ } ++ else /* if ( pSharedInfo->ImageInfo.fSinLevel != TRUE ) */ ++ { ++ /* SIN level is not supported in this image. */ ++ f_pChannelStats->lSinLevel = cOCT6100_INVALID_SIGNED_STAT; ++ } ++ ++ f_pChannelStats->lRinAppliedGain = pChanEntry->VqeConfig.chRinLevelControlGainDb; ++ if ( ( f_pApiInstance->pSharedInfo->ImageInfo.fRinAppliedGainStat == TRUE ) ++ && ( ( pChanEntry->VqeConfig.fRinAutomaticLevelControl == TRUE ) ++ || ( pChanEntry->VqeConfig.fRinHighLevelCompensation == TRUE ) ) ) ++ { ++ f_pChannelStats->lRinAppliedGain = pChanEntry->sRinAppliedGain; ++ } ++ ++ f_pChannelStats->lSoutAppliedGain = pChanEntry->VqeConfig.chSoutLevelControlGainDb; ++ if ( ( f_pApiInstance->pSharedInfo->ImageInfo.fSoutAppliedGainStat == TRUE ) ++ && ( pChanEntry->VqeConfig.fSoutAutomaticLevelControl == TRUE ) ) ++ { ++ f_pChannelStats->lSoutAppliedGain = pChanEntry->sSoutAppliedGain; ++ } ++ ++ if ( pChanEntry->usCurrentEchoDelay == cOCT6100_INVALID_STAT_W ) ++ f_pChannelStats->ulCurrentEchoDelay = cOCT6100_INVALID_STAT; ++ else ++ f_pChannelStats->ulCurrentEchoDelay = pChanEntry->usCurrentEchoDelay; ++ ++ if ( pSharedInfo->ImageInfo.fSinLevel == TRUE ) ++ { ++ if ( pChanEntry->sCurrentERLE == cOCT6100_INVALID_SIGNED_STAT_W ) ++ f_pChannelStats->lCurrentERLE = cOCT6100_INVALID_SIGNED_STAT; ++ else ++ f_pChannelStats->lCurrentERLE = pChanEntry->sCurrentERLE; ++ } ++ else /* if ( pSharedInfo->ImageInfo.fSinLevel != TRUE ) */ ++ { ++ f_pChannelStats->lCurrentERLE = cOCT6100_INVALID_SIGNED_STAT; ++ } ++ ++ if ( pSharedInfo->ImageInfo.fSinLevel == TRUE ) ++ { ++ if ( pChanEntry->sMaxERLE == cOCT6100_INVALID_SIGNED_STAT_W ) ++ f_pChannelStats->lMaxERLE = cOCT6100_INVALID_SIGNED_STAT; ++ else ++ f_pChannelStats->lMaxERLE = pChanEntry->sMaxERLE; ++ } ++ else /* if ( pSharedInfo->ImageInfo.fSinLevel != TRUE ) */ ++ { ++ f_pChannelStats->lMaxERLE = cOCT6100_INVALID_SIGNED_STAT; ++ } ++ ++ f_pChannelStats->lComfortNoiseLevel = pChanEntry->sComfortNoiseLevel; ++ f_pChannelStats->ulToneDisablerStatus = pChanEntry->byToneDisablerStatus; ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fSinVoiceDetectedStat == TRUE ) ++ { ++ UINT32 ulVoiceDetectedBytesOfst = f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst.usDwordOffset * 4; ++ UINT32 ulVoiceDetectedBitOfst = f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst.byBitOffset; ++ UINT32 ulVoiceDetectedFieldSize = f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst.byFieldSize; ++ ++ /* Set the channel root base address.*/ ++ UINT32 ulChannelRootBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( usChanIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ ReadParams.ulReadAddress = ulChannelRootBaseAddress + ulVoiceDetectedBytesOfst; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulVoiceDetectedBitOfst < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ /* Must read in memory directly since this value is changed by hardware */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulVoiceDetectedBitOfst < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulVoiceDetectedFieldSize, ulVoiceDetectedBitOfst, &ulMask ); ++ ++ if ( ( ulTempData & ulMask ) != 0x0 ) ++ f_pChannelStats->fSinVoiceDetected = TRUE; ++ else ++ f_pChannelStats->fSinVoiceDetected = FALSE; ++ } ++ ++ /*---------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveEchoEntry ++ ++Description: Reserves one of the echo channel API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pusEchoIndex Resulting index reserved in the echo channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveEchoEntry ++UINT32 Oct6100ApiReserveEchoEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusEchoIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pEchoAlloc; ++ UINT32 ulResult; ++ UINT32 ulEchoIndex; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pEchoAlloc, &ulEchoIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_CHANNEL_ALL_CHANNELS_ARE_OPENED; ++ else ++ return cOCT6100_ERR_FATAL_11; ++ } ++ ++ *f_pusEchoIndex = (UINT16)( ulEchoIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseEchoEntry ++ ++Description: Releases the specified ECHO channel API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usEchoIndex Index reserved in the echo channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseEchoEntry ++UINT32 Oct6100ApiReleaseEchoEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEchoIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pEchoAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pEchoAlloc, f_usEchoIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_12; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBiDirChanEntry ++ ++Description: Reserves one of the bidirectional channel API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pusBiDirChanIndex Resulting index reserved in the bidir channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBiDirChanEntry ++UINT32 Oct6100ApiReserveBiDirChanEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusBiDirChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pChanAlloc; ++ UINT32 ulResult; ++ UINT32 ulBiDirChanIndex; ++ ++ /* Get local pointer to shared portion of the API instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pChanAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pChanAlloc, &ulBiDirChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_CHANNEL_ALL_BIDIR_CHANNELS_ARE_OPENED; ++ else ++ return cOCT6100_ERR_FATAL_9F; ++ } ++ ++ *f_pusBiDirChanIndex = (UINT16)( ulBiDirChanIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBiDirChanEntry ++ ++Description: Releases the specified bidirectional channel API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulBiDirChanIndex Bidirectional channel index within the API's Bidir channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBiDirChanEntry ++UINT32 Oct6100ApiReleaseBiDirChanEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulBiDirChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pChanAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pChanAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pChanAlloc, f_ulBiDirChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_A0; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckTdmConfig ++ ++Description: This function will check the validity of the TDM config parameter ++ of an Open TDM config structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pTdmConfig TDM config of the channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckTdmConfig ++UINT32 Oct6100ApiCheckTdmConfig( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig ) ++{ ++ UINT32 ulResult; ++ ++ /*==============================================================================*/ ++ /* Check the TDM configuration parameters.*/ ++ ++ /* Check the validity of the timeslot and Stream only if it is defined.*/ ++ if ( f_pTdmConfig->ulRinTimeslot != cOCT6100_UNASSIGNED || ++ f_pTdmConfig->ulRinStream != cOCT6100_UNASSIGNED ) ++ { ++ if ( f_pTdmConfig->ulRinNumTssts != 1 && ++ f_pTdmConfig->ulRinNumTssts != 2 ) ++ return cOCT6100_ERR_CHANNEL_RIN_NUM_TSSTS; ++ ++ /* Check the RIN TDM streams, timeslots component for errors.*/ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ f_pTdmConfig->ulRinNumTssts, ++ f_pTdmConfig->ulRinTimeslot, ++ f_pTdmConfig->ulRinStream, ++ cOCT6100_INPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_CHANNEL_RIN_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Check the validity of the timeslot and Stream only if it is defined.*/ ++ if ( f_pTdmConfig->ulRoutTimeslot != cOCT6100_UNASSIGNED || ++ f_pTdmConfig->ulRoutStream != cOCT6100_UNASSIGNED ) ++ { ++ if ( f_pTdmConfig->ulRoutNumTssts != 1 && ++ f_pTdmConfig->ulRoutNumTssts != 2 ) ++ return cOCT6100_ERR_CHANNEL_ROUT_NUM_TSSTS; ++ ++ /* Check the ROUT TDM streams, timeslots component for errors.*/ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ f_pTdmConfig->ulRoutNumTssts, ++ f_pTdmConfig->ulRoutTimeslot, ++ f_pTdmConfig->ulRoutStream, ++ cOCT6100_OUTPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_CHANNEL_ROUT_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Check the validity of the timeslot and Stream only if it is defined.*/ ++ if ( f_pTdmConfig->ulSinTimeslot != cOCT6100_UNASSIGNED || ++ f_pTdmConfig->ulSinStream != cOCT6100_UNASSIGNED ) ++ { ++ if ( f_pTdmConfig->ulSinNumTssts != 1 && ++ f_pTdmConfig->ulSinNumTssts != 2 ) ++ return cOCT6100_ERR_CHANNEL_SIN_NUM_TSSTS; ++ ++ /* Check the SIN TDM streams, timeslots component for errors.*/ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ f_pTdmConfig->ulSinNumTssts, ++ f_pTdmConfig->ulSinTimeslot, ++ f_pTdmConfig->ulSinStream, ++ cOCT6100_INPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_CHANNEL_SIN_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Check the validity of the timeslot and Stream only if it is defined.*/ ++ if ( f_pTdmConfig->ulSoutTimeslot != cOCT6100_UNASSIGNED || ++ f_pTdmConfig->ulSoutStream != cOCT6100_UNASSIGNED ) ++ { ++ if ( f_pTdmConfig->ulSoutNumTssts != 1 && ++ f_pTdmConfig->ulSoutNumTssts != 2 ) ++ return cOCT6100_ERR_CHANNEL_SOUT_NUM_TSSTS; ++ ++ /* Check the ROUT TDM streams, timeslots component for errors.*/ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ f_pTdmConfig->ulSoutNumTssts, ++ f_pTdmConfig->ulSoutTimeslot, ++ f_pTdmConfig->ulSoutStream, ++ cOCT6100_OUTPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_CHANNEL_SOUT_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Check the PCM law parameters.*/ ++ if ( f_pTdmConfig->ulRinPcmLaw != cOCT6100_PCM_U_LAW && ++ f_pTdmConfig->ulRinPcmLaw != cOCT6100_PCM_A_LAW ) ++ return cOCT6100_ERR_CHANNEL_RIN_PCM_LAW; ++ ++ if ( f_pTdmConfig->ulSinPcmLaw != cOCT6100_PCM_U_LAW && ++ f_pTdmConfig->ulSinPcmLaw != cOCT6100_PCM_A_LAW ) ++ return cOCT6100_ERR_CHANNEL_SIN_PCM_LAW; ++ ++ if ( f_pTdmConfig->ulRoutPcmLaw != cOCT6100_PCM_U_LAW && ++ f_pTdmConfig->ulRoutPcmLaw != cOCT6100_PCM_A_LAW ) ++ return cOCT6100_ERR_CHANNEL_ROUT_PCM_LAW; ++ ++ if ( f_pTdmConfig->ulSoutPcmLaw != cOCT6100_PCM_U_LAW && ++ f_pTdmConfig->ulSoutPcmLaw != cOCT6100_PCM_A_LAW ) ++ return cOCT6100_ERR_CHANNEL_SOUT_PCM_LAW; ++ ++ /*==============================================================================*/ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckVqeConfig ++ ++Description: This function will check the validity of the VQE config parameter ++ of an Open VQE config structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pVqeConfig VQE config of the channel. ++f_fEnableToneDisabler Whether the tone disabler is active or not. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckVqeConfig ++UINT32 Oct6100ApiCheckVqeConfig( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN BOOL f_fEnableToneDisabler ) ++{ ++ tPOCT6100_API_IMAGE_INFO pImageInfo; ++ ++ pImageInfo = &f_pApiInstance->pSharedInfo->ImageInfo; ++ ++ if ( f_pVqeConfig->fEnableNlp != TRUE && f_pVqeConfig->fEnableNlp != FALSE ) ++ return cOCT6100_ERR_CHANNEL_ENABLE_NLP; ++ ++ if ( f_pVqeConfig->fEnableNlp == TRUE && pImageInfo->fNlpControl == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLP_CONTROL; ++ ++ ++ ++ /* Check the comfort noise mode.*/ ++ if ( f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_OFF && pImageInfo->fComfortNoise == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_BKG_NOISE_FREEZE; ++ ++ if ( f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_NORMAL && ++ f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_EXTENDED && ++ f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_FAST_LATCH && ++ f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_OFF ) ++ return cOCT6100_ERR_CHANNEL_COMFORT_NOISE_MODE; ++ ++ /* Check the DC offset removal.*/ ++ if ( f_pVqeConfig->fSinDcOffsetRemoval != TRUE && f_pVqeConfig->fSinDcOffsetRemoval != FALSE ) ++ return cOCT6100_ERR_CHANNEL_SIN_DC_OFFSET_REM; ++ ++ if ( f_pVqeConfig->fSinDcOffsetRemoval == TRUE && pImageInfo->fSinDcOffsetRemoval == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_DC_OFFSET_REM; ++ ++ if ( f_pVqeConfig->fRinDcOffsetRemoval != TRUE && f_pVqeConfig->fRinDcOffsetRemoval != FALSE ) ++ return cOCT6100_ERR_CHANNEL_RIN_DC_OFFSET_REM; ++ ++ if ( f_pVqeConfig->fRinDcOffsetRemoval == TRUE && pImageInfo->fRinDcOffsetRemoval == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_DC_OFFSET_REM; ++ ++ /* Check the Level control.*/ ++ if ( f_pVqeConfig->fRinLevelControl != TRUE && f_pVqeConfig->fRinLevelControl != FALSE ) ++ return cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL; ++ ++ if ( f_pVqeConfig->fSoutLevelControl != TRUE && f_pVqeConfig->fSoutLevelControl != FALSE ) ++ return cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL; ++ ++ if ( ( f_pVqeConfig->lRinLevelControlGainDb < -24 ) || ( f_pVqeConfig->lRinLevelControlGainDb > 24 ) ) ++ return cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL_GAIN; ++ ++ if ( ( f_pVqeConfig->lSoutLevelControlGainDb < -24 ) || ( f_pVqeConfig->lSoutLevelControlGainDb > 24 ) ) ++ return cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL_GAIN; ++ ++ if ( ( f_pVqeConfig->fRinAutomaticLevelControl != TRUE ) && ( f_pVqeConfig->fRinAutomaticLevelControl != FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL; ++ ++ if ( ( f_pVqeConfig->fRinHighLevelCompensation != TRUE ) && ( f_pVqeConfig->fRinHighLevelCompensation != FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP; ++ ++ if ( ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) && ( pImageInfo->fRinAutoLevelControl == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_AUTO_LC; ++ ++ if ( ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) && ( pImageInfo->fRinHighLevelCompensation == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_HIGH_LEVEL_COMP; ++ ++ if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) ++ { ++ if ( f_pVqeConfig->fRinLevelControl == TRUE ) ++ return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_MANUAL; ++ ++ if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ++ return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_HIGH_LEVEL_COMP; ++ ++ if ( ( f_pVqeConfig->lRinAutomaticLevelControlTargetDb < -40 || f_pVqeConfig->lRinAutomaticLevelControlTargetDb > 0 ) ) ++ return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL_TARGET; ++ } ++ ++ if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ++ { ++ if ( f_pVqeConfig->fRinLevelControl == TRUE ) ++ return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_MANUAL; ++ ++ if ( ( f_pVqeConfig->lRinHighLevelCompensationThresholdDb < -40 || f_pVqeConfig->lRinHighLevelCompensationThresholdDb > 0 ) ) ++ return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_THRESHOLD; ++ } ++ ++ if ( f_pVqeConfig->fSoutAutomaticLevelControl != TRUE && f_pVqeConfig->fSoutAutomaticLevelControl != FALSE ) ++ return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL; ++ ++ if ( ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) && ( pImageInfo->fSoutAutoLevelControl == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SOUT_AUTO_LC; ++ ++ if ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) ++ { ++ if ( f_pVqeConfig->fSoutLevelControl == TRUE ) ++ return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_MANUAL; ++ ++ if ( ( f_pVqeConfig->lSoutAutomaticLevelControlTargetDb < -40 || f_pVqeConfig->lSoutAutomaticLevelControlTargetDb > 0 ) ) ++ return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL_TARGET; ++ } ++ ++ if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction != TRUE && ++ f_pVqeConfig->fSoutAdaptiveNoiseReduction != FALSE ) ++ return cOCT6100_ERR_CHANNEL_SOUT_ADAPT_NOISE_REDUCTION; ++ ++ if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE && pImageInfo->fAdaptiveNoiseReduction == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR; ++ ++ if ( f_pVqeConfig->fSoutConferencingNoiseReduction != TRUE && ++ f_pVqeConfig->fSoutConferencingNoiseReduction != FALSE ) ++ return cOCT6100_ERR_CHANNEL_SOUT_CONFERENCE_NOISE_REDUCTION; ++ ++ if ( f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE && pImageInfo->fConferencingNoiseReduction == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_CNR; ++ ++ /* Validate Sout noise bleaching parameter. */ ++ if ( f_pVqeConfig->fSoutNoiseBleaching != TRUE && ++ f_pVqeConfig->fSoutNoiseBleaching != FALSE ) ++ return cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING; ++ ++ /* Check if firmware supports Sout noise bleaching. */ ++ if ( f_pVqeConfig->fSoutNoiseBleaching == TRUE && pImageInfo->fSoutNoiseBleaching == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NOISE_BLEACHING; ++ ++ /* If Sout noise bleaching is requested, no ANR or CNR shall be activated. */ ++ if ( f_pVqeConfig->fSoutNoiseBleaching == TRUE ) ++ { ++ /* No xNR! */ ++ if ( ( f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE ) ++ || ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE ) ) ++ return cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING_NR; ++ } ++ ++ /* Cannot activate both ANR and CNR when noise bleaching is present */ ++ if ( pImageInfo->fSoutNoiseBleaching == TRUE ) ++ { ++ if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE && ++ f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE ) ++ return cOCT6100_ERR_CHANNEL_ANR_CNR_SIMULTANEOUSLY; ++ } ++ ++ /* Validate the DTMF tone removal parameter.*/ ++ if ( f_pVqeConfig->fDtmfToneRemoval != TRUE && f_pVqeConfig->fDtmfToneRemoval != FALSE ) ++ return cOCT6100_ERR_CHANNEL_TONE_REMOVAL; ++ ++ if ( f_pVqeConfig->fDtmfToneRemoval == TRUE && pImageInfo->fToneRemoval == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_REMOVAL; ++ ++ ++ ++ /* Check the Tail displacement enable.*/ ++ if ( f_pVqeConfig->fEnableTailDisplacement != TRUE && f_pVqeConfig->fEnableTailDisplacement != FALSE ) ++ return cOCT6100_ERR_CHANNEL_ENABLE_TAIL_DISPLACEMENT; ++ ++ if ( f_pVqeConfig->fEnableTailDisplacement == TRUE && pImageInfo->fTailDisplacement == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_DISPLACEMENT; ++ ++ /* Check the Tail displacement value.*/ ++ if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) ++ { ++ if ( f_pVqeConfig->ulTailDisplacement != cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ /* Check if this feature is supported by the image. */ ++ if ( pImageInfo->fPerChannelTailDisplacement == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_PER_CHAN_TAIL; ++ ++ /* Check that this value is not greater then what the image supports. */ ++ if ( f_pVqeConfig->ulTailDisplacement > pImageInfo->usMaxTailDisplacement ) ++ return cOCT6100_ERR_CHANNEL_TAIL_DISPLACEMENT_INVALID; ++ } ++ } ++ ++ /* Check the tail length value. */ ++ if ( f_pVqeConfig->ulTailLength != cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ /* Check if this feature is supported by the image. */ ++ if ( ( pImageInfo->fPerChannelTailLength == FALSE ) ++ && ( (UINT16)( f_pVqeConfig->ulTailLength & 0xFFFF ) != pImageInfo->usMaxTailLength ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_LENGTH; ++ ++ if ( ( f_pVqeConfig->ulTailLength < 32 ) || ( f_pVqeConfig->ulTailLength > 128 ) ++ || ( ( f_pVqeConfig->ulTailLength % 4 ) != 0x0 ) ) ++ return cOCT6100_ERR_CHANNEL_TAIL_LENGTH; ++ ++ /* Check if the requested tail length is supported by the chip. */ ++ if ( f_pVqeConfig->ulTailLength > pImageInfo->usMaxTailLength ) ++ return cOCT6100_ERR_CHANNEL_TAIL_LENGTH_INVALID; ++ } ++ ++ /* Validate the acoustic echo cancellation parameter.*/ ++ if ( f_pVqeConfig->fAcousticEcho != TRUE && f_pVqeConfig->fAcousticEcho != FALSE ) ++ return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO; ++ ++ if ( f_pVqeConfig->fAcousticEcho == TRUE && pImageInfo->fAcousticEcho == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO; ++ ++ if ( f_pVqeConfig->fAcousticEcho == TRUE ) ++ { ++ /* Check if acoustic echo tail length configuration is supported in the image. */ ++ if ( ( f_pVqeConfig->ulAecTailLength != 128 ) && ( pImageInfo->fAecTailLength == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH; ++ ++ /* Check the requested acoustic echo tail length. */ ++ if ( ( f_pVqeConfig->ulAecTailLength != 128 ) ++ && ( f_pVqeConfig->ulAecTailLength != 256 ) ++ && ( f_pVqeConfig->ulAecTailLength != 512 ) ++ && ( f_pVqeConfig->ulAecTailLength != 1024 ) ) ++ return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH; ++ ++ if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) ++ { ++ UINT32 ulTailSum; ++ ++ /* Start with requested tail displacement. */ ++ if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTailSum = f_pApiInstance->pSharedInfo->ChipConfig.usTailDisplacement; ++ } ++ else ++ { ++ ulTailSum = f_pVqeConfig->ulTailDisplacement; ++ } ++ ++ /* Add requested tail length. */ ++ if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTailSum += f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailLength; ++ } ++ else ++ { ++ ulTailSum += f_pVqeConfig->ulTailLength; ++ } ++ ++ /* The tail sum must be smaller then the requested AEC tail length. */ ++ if ( ulTailSum > f_pVqeConfig->ulAecTailLength ) ++ return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_SUM; ++ } ++ } ++ ++ /* Validate the Default ERL parameter.*/ ++ if ( f_pVqeConfig->lDefaultErlDb != -6 && pImageInfo->fDefaultErl == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DEFAULT_ERL; ++ ++ if ( ( f_pVqeConfig->lDefaultErlDb != 0 ) && ++ ( f_pVqeConfig->lDefaultErlDb != -3 ) && ++ ( f_pVqeConfig->lDefaultErlDb != -6 ) && ++ ( f_pVqeConfig->lDefaultErlDb != -9 ) && ++ ( f_pVqeConfig->lDefaultErlDb != -12 ) ) ++ return cOCT6100_ERR_CHANNEL_DEFAULT_ERL; ++ ++ /* Validate the Default AEC ERL parameter.*/ ++ if ( f_pVqeConfig->lAecDefaultErlDb != 0 && pImageInfo->fAecDefaultErl == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_AEC_DEFAULT_ERL; ++ ++ if ( f_pVqeConfig->lAecDefaultErlDb != 0 && f_pVqeConfig->lAecDefaultErlDb != -3 && f_pVqeConfig->lAecDefaultErlDb != -6 ) ++ return cOCT6100_ERR_CHANNEL_AEC_DEFAULT_ERL; ++ ++ /* Validate the non-linearity A parameter.*/ ++ if ( f_pVqeConfig->ulNonLinearityBehaviorA != 1 && pImageInfo->fNonLinearityBehaviorA == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DOUBLE_TALK; ++ ++ if ( f_pVqeConfig->ulNonLinearityBehaviorA >= 14 ) ++ return cOCT6100_ERR_CHANNEL_DOUBLE_TALK; ++ ++ /* Validate the non-linearity B parameter.*/ ++ if ( f_pVqeConfig->ulNonLinearityBehaviorB != 0 && pImageInfo->fNonLinearityBehaviorB == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NON_LINEARITY_B; ++ ++ if ( f_pVqeConfig->ulNonLinearityBehaviorB >= 9 ) ++ return cOCT6100_ERR_CHANNEL_NON_LINEARITY_B; ++ ++ /* Check if configuring the double talk behavior is supported in the firmware. */ ++ if ( f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_NORMAL && pImageInfo->fDoubleTalkBehavior == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_DOUBLE_TALK_BEHAVIOR_MODE; ++ ++ /* Validate the double talk behavior mode parameter. */ ++ if ( f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_NORMAL && f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_LESS_AGGRESSIVE ) ++ return cOCT6100_ERR_CHANNEL_DOUBLE_TALK_MODE; ++ ++ /* Validate the Sout automatic listener enhancement ratio. */ ++ if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 && pImageInfo->fListenerEnhancement == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ALE; ++ ++ if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb > 30 ) ++ return cOCT6100_ERR_CHANNEL_ALE_RATIO; ++ ++ /* Validate the Sout natural listener enhancement ratio. */ ++ if ( f_pVqeConfig->fSoutNaturalListenerEnhancement != TRUE && f_pVqeConfig->fSoutNaturalListenerEnhancement != FALSE ) ++ return cOCT6100_ERR_CHANNEL_NLE_FLAG; ++ ++ if ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE && pImageInfo->fListenerEnhancement == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLE; ++ ++ if ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) ++ { ++ if ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb > 30 ) ++ return cOCT6100_ERR_CHANNEL_NLE_RATIO; ++ } ++ ++ /* Both ALE and NLE cannot be activated simultaneously. */ ++ if ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 ) ++ && ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) ) ++ return cOCT6100_ERR_CHANNEL_ALE_NLE_SIMULTANEOUSLY; ++ ++ /* Validate Rout noise reduction. */ ++ if ( f_pVqeConfig->fRoutNoiseReduction != TRUE && f_pVqeConfig->fRoutNoiseReduction != FALSE ) ++ return cOCT6100_ERR_CHANNEL_ROUT_NOISE_REDUCTION; ++ ++ /* Check if Rout noise reduction is supported. */ ++ if ( f_pVqeConfig->fRoutNoiseReduction == TRUE && pImageInfo->fRoutNoiseReduction == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ROUT_NR; ++ ++ /*Check if noise reduction level gain is supported*/ ++ if ( ( pImageInfo->fRoutNoiseReductionLevel == FALSE ) && ( f_pVqeConfig->lRoutNoiseReductionLevelGainDb != -18 ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ROUT_NOISE_REDUCTION_GAIN; ++ ++ if ( ( f_pVqeConfig->lRoutNoiseReductionLevelGainDb != 0 ) && ++ ( f_pVqeConfig->lRoutNoiseReductionLevelGainDb != -6 ) && ++ ( f_pVqeConfig->lRoutNoiseReductionLevelGainDb != -12 ) && ++ ( f_pVqeConfig->lRoutNoiseReductionLevelGainDb != -18 ) ) ++ ++ return cOCT6100_ERR_CHANNEL_ROUT_NOISE_REDUCTION_GAIN; ++ ++ /* Check if ANR SNRE is supported. */ ++ if ( ( f_pVqeConfig->lAnrSnrEnhancementDb != -18 ) && ( pImageInfo->fAnrSnrEnhancement == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SNR_ENHANCEMENT; ++ ++ /* Validate Sout ANR SNR enhancement. */ ++ if ( ( f_pVqeConfig->lAnrSnrEnhancementDb != -9 ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != -12 ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != -15 ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != -18 ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != -21 ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != -24 ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != -27 ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != -30 ) ) ++ return cOCT6100_ERR_CHANNEL_ANR_SNR_ENHANCEMENT; ++ ++ /* Validate ANR voice-noise segregation. */ ++ if ( f_pVqeConfig->ulAnrVoiceNoiseSegregation > 15 ) ++ return cOCT6100_ERR_CHANNEL_ANR_SEGREGATION; ++ ++ /* Check if ANR VN segregation is supported. */ ++ if ( ( f_pVqeConfig->ulAnrVoiceNoiseSegregation != 6 ) && ( pImageInfo->fAnrVoiceNoiseSegregation == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SEGREGATION; ++ ++ /* Check if the loaded image supports tone disabler VQE activation delay. */ ++ if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != 300 ) ++ && ( pImageInfo->fToneDisablerVqeActivationDelay == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY; ++ ++ /* Check if the specified tone disabler VQE activation delay is correct. */ ++ if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay < 300 ) ++ || ( ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay - 300 ) % 512 ) != 0 ) ) ++ return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY; ++ ++ /* Check the enable music protection flag. */ ++ if ( ( f_pVqeConfig->fEnableMusicProtection != TRUE ) && ( f_pVqeConfig->fEnableMusicProtection != FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_ENABLE_MUSIC_PROTECTION; ++ ++ /* The music protection module can only be activated if the image supports it. */ ++ if ( ( f_pVqeConfig->fEnableMusicProtection == TRUE ) && ++ ( pImageInfo->fMusicProtection == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_MUSIC_PROTECTION; ++ ++ /* Check the enable idle code detection flag. */ ++ if ( ( f_pVqeConfig->fIdleCodeDetection != TRUE ) && ( f_pVqeConfig->fIdleCodeDetection != FALSE ) ) ++ return cOCT6100_ERR_CHANNEL_IDLE_CODE_DETECTION; ++ ++ /* The idle code detection module can only be activated if the image supports it. */ ++ if ( ( f_pVqeConfig->fIdleCodeDetection == TRUE ) && ( pImageInfo->fIdleCodeDetection == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION; ++ ++ /* The idle code detection module can be disabled only if idle code detection configuration */ ++ /* is supported in the image. */ ++ if ( pImageInfo->fIdleCodeDetection == TRUE ) ++ { ++ if ( ( f_pVqeConfig->fIdleCodeDetection == FALSE ) && ( pImageInfo->fIdleCodeDetectionConfiguration == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION_CONFIG; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckCodecConfig ++ ++Description: This function will check the validity of the Codec config parameter ++ of an Open Codec config structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCodecConfig Codec config of the channel. ++f_ulDecoderNumTssts Number of TSST for the decoder. ++f_pusPhasingTsstIndex Pointer to the Phasing TSST index within the API's phasing TSST list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckCodecConfig ++UINT32 Oct6100ApiCheckCodecConfig( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_CODEC f_pCodecConfig, ++ IN UINT32 f_ulDecoderNumTssts, ++ OUT PUINT16 f_pusPhasingTsstIndex ) ++{ ++ ++ /* Verify the ADPCM nibble value.*/ ++ if ( f_pCodecConfig->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_LOW_BITS && ++ f_pCodecConfig->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_HIGH_BITS ) ++ return cOCT6100_ERR_CHANNEL_ADPCM_NIBBLE; ++ ++ /* Verify the Encoder port.*/ ++ if ( f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_ROUT && ++ f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_SOUT && ++ f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) ++ return cOCT6100_ERR_CHANNEL_ENCODER_PORT; ++ ++ /* Verify the Decoder port.*/ ++ if ( f_pCodecConfig->ulDecoderPort != cOCT6100_CHANNEL_PORT_RIN && ++ f_pCodecConfig->ulDecoderPort != cOCT6100_CHANNEL_PORT_SIN && ++ f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) ++ return cOCT6100_ERR_CHANNEL_DECODER_PORT; ++ ++ /* The codec cannot be on the same stream.*/ ++ if ( f_pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT && ++ f_pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ return cOCT6100_ERR_CHANNEL_INVALID_CODEC_POSITION; ++ ++ if ( f_pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT && ++ f_pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) ++ return cOCT6100_ERR_CHANNEL_INVALID_CODEC_POSITION; ++ ++ /* Verify if the requested functions are supported by the chip.*/ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm == FALSE && ++ f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) ++ { ++ if ( f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ENCODING; ++ } ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm == FALSE && ++ f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) ++ { ++ if ( f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DECODING; ++ } ++ ++ /* Check if encoder port has been specified when a rate has been set. */ ++ if ( f_pCodecConfig->ulEncoderPort == cOCT6100_NO_ENCODING && ++ f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) ++ return cOCT6100_ERR_CHANNEL_ENCODER_PORT; ++ ++ /* Check if decoder port has been specified when a rate has been set. */ ++ if ( f_pCodecConfig->ulDecoderPort == cOCT6100_NO_DECODING && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS ) ++ return cOCT6100_ERR_CHANNEL_DECODER_PORT; ++ ++ /* Check Encoder related parameter if one is used.*/ ++ if ( f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) ++ { ++ /* Check the Encoder compression rate.*/ ++ if ( ( f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_40KBPS ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_32KBPS ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_24KBPS ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_16KBPS ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_4_1 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_3_2 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_2_3 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_4_0 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_3_1 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_2_2 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_24KBPS_3_0 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_24KBPS_2_1 ) && ++ ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_16KBPS_2_0 ) ) ++ return cOCT6100_ERR_CHANNEL_ENCODING_RATE; ++ ++ /* Verify phasing information.*/ ++ if ( f_pCodecConfig->ulPhasingType != cOCT6100_SINGLE_PHASING && ++ f_pCodecConfig->ulPhasingType != cOCT6100_DUAL_PHASING && ++ f_pCodecConfig->ulPhasingType != cOCT6100_NO_PHASING ) ++ return cOCT6100_ERR_CHANNEL_PHASING_TYPE; ++ ++ /* Verify the silence suppression parameters.*/ ++ if ( f_pCodecConfig->fEnableSilenceSuppression != TRUE && ++ f_pCodecConfig->fEnableSilenceSuppression != FALSE ) ++ return cOCT6100_ERR_CHANNEL_SIL_SUP_ENABLE; ++ ++ if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && ++ f_pApiInstance->pSharedInfo->ImageInfo.fSilenceSuppression == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIL_SUP; ++ ++ if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && ++ f_pCodecConfig->ulPhasingType == cOCT6100_NO_PHASING ) ++ return cOCT6100_ERR_CHANNEL_PHASE_TYPE_REQUIRED; ++ ++ if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && ++ f_pCodecConfig->ulPhasingTsstHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_CHANNEL_PHASING_TSST_REQUIRED; ++ ++ if ( f_pCodecConfig->ulPhasingTsstHndl == cOCT6100_INVALID_HANDLE && ++ f_pCodecConfig->ulPhasingType != cOCT6100_NO_PHASING ) ++ return cOCT6100_ERR_CHANNEL_PHASING_TSST_REQUIRED; ++ ++ /* Silence suppression can only be performed if the encoder is using the SOUT port.*/ ++ if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && ++ f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_SOUT ) ++ return cOCT6100_ERR_CHANNEL_SIL_SUP_INVALID_ENCODER_PORT; ++ ++ /* Check phasing TSST info if phasing is required.*/ ++ if ( f_pCodecConfig->ulPhasingTsstHndl != cOCT6100_INVALID_HANDLE ) ++ { ++ tPOCT6100_API_PHASING_TSST pPhasingEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check the provided handle. */ ++ if ( (f_pCodecConfig->ulPhasingTsstHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_PHASING_TSST ) ++ return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; ++ ++ *f_pusPhasingTsstIndex = (UINT16)( f_pCodecConfig->ulPhasingTsstHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusPhasingTsstIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPhasingTssts ) ++ return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, *f_pusPhasingTsstIndex ); ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pCodecConfig->ulPhasingTsstHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Verify if the state of the phasing TSST.*/ ++ if ( pPhasingEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_PHASING_TSST_NOT_OPEN; ++ if ( ulEntryOpenCnt != pPhasingEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; ++ ++ /* Check the specified phase value against the phasing length of the phasing TSST.*/ ++ if ( ( f_pCodecConfig->ulPhase == 0 ) ++ || ( f_pCodecConfig->ulPhase >= pPhasingEntry->usPhasingLength ) ) ++ return cOCT6100_ERR_CHANNEL_PHASING_INVALID_PHASE; ++ } ++ else ++ { ++ *f_pusPhasingTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ else ++ { ++ *f_pusPhasingTsstIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ ++ /* Check Decoder related parameter if one is used.*/ ++ if ( f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) ++ { ++ /* Check the Decoding rate.*/ ++ if ( f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G726_40KBPS && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G726_32KBPS && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G726_24KBPS && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G726_16KBPS && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G726_ENCODED && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G726_ENCODED && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G727_2C_ENCODED && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G727_3C_ENCODED && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G727_4C_ENCODED && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_2C_ENCODED && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_3C_ENCODED && ++ f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_4C_ENCODED ) ++ return cOCT6100_ERR_CHANNEL_DECODING_RATE; ++ ++ /* Make sure that two timeslot are allocated if PCM-ECHO encoded is selected.*/ ++ if ( (f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G726_ENCODED || ++ f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_2C_ENCODED || ++ f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_3C_ENCODED || ++ f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_4C_ENCODED ) && ++ f_ulDecoderNumTssts != 2 ) ++ return cOCT6100_ERR_CHANNEL_MISSING_TSST; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteInputTsstControlMemory ++ ++Description: This function configure a TSST control memory entry in internal memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usTsstIndex TSST index within the TSST control memory. ++f_usTsiMemIndex TSI index within the TSI chariot memory. ++f_ulTsstInputLaw PCM law of the input TSST. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteInputTsstControlMemory ++UINT32 Oct6100ApiWriteInputTsstControlMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsstIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT32 f_ulTsstInputLaw ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_INPUT_TSST; ++ WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; ++ ++ /* Set the PCM law.*/ ++ WriteParams.usWriteData |= f_ulTsstInputLaw << cOCT6100_TSST_CONTROL_MEM_PCM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteOutputTsstControlMemory ++ ++Description: This function configure a TSST control memory entry in internal memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteOutputTsstControlMemory ++UINT32 Oct6100ApiWriteOutputTsstControlMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsstIndex, ++ IN UINT32 f_ulAdpcmNibblePosition, ++ IN UINT32 f_ulNumTssts, ++ IN UINT16 f_usTsiMemIndex ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_OUTPUT_TSST; ++ WriteParams.usWriteData |= f_ulAdpcmNibblePosition << cOCT6100_TSST_CONTROL_MEM_NIBBLE_POS_OFFSET; ++ WriteParams.usWriteData |= (f_ulNumTssts - 1) << cOCT6100_TSST_CONTROL_MEM_TSST_NUM_OFFSET; ++ WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteEncoderMemory ++ ++Description: This function configure a Encoded memory entry in internal memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulEncoderIndex Index of the encoder block within the ADPCM context memory. ++f_ulCompType Compression rate of the encoder. ++f_usTsiMemIndex TSI index within the TSI chariot memory used by the encoder. ++f_ulEnableSilenceSuppression Silence suppression enable flag. ++f_ulAdpcmNibblePosition ADPCM nibble position. ++f_usPhasingTsstIndex Phasing TSST index within the API's Phassing TSST list. ++f_ulPhasingType Type of the Phasing TSST. ++f_ulPhase Phase used with this encoder. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteEncoderMemory ++UINT32 Oct6100ApiWriteEncoderMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulEncoderIndex, ++ IN UINT32 f_ulCompType, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT32 f_ulEnableSilenceSuppression, ++ IN UINT32 f_ulAdpcmNibblePosition, ++ IN UINT16 f_usPhasingTsstIndex, ++ IN UINT32 f_ulPhasingType, ++ IN UINT32 f_ulPhase ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base */ ++ WriteParams.ulWriteAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_ulEncoderIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ENCODER; ++ WriteParams.usWriteData |= f_ulCompType << cOCT6100_CONVERSION_CONTROL_MEM_COMP_OFFSET; ++ WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base + 2 */ ++ WriteParams.ulWriteAddress += 2; ++ ++ /* Set the phasing TSST number.*/ ++ if ( f_usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ WriteParams.usWriteData = (UINT16)( f_usPhasingTsstIndex << cOCT6100_CONVERSION_CONTROL_MEM_PHASE_OFFSET ); ++ else ++ WriteParams.usWriteData = 0; ++ ++ /* Set the phasing type and the phase value if required.*/ ++ switch( f_ulPhasingType ) ++ { ++ case cOCT6100_NO_PHASING: ++ WriteParams.usWriteData |= 0x1 << 10; ++ break; ++ case cOCT6100_SINGLE_PHASING: ++ WriteParams.usWriteData |= f_ulPhase; ++ break; ++ case cOCT6100_DUAL_PHASING: ++ WriteParams.usWriteData |= 0x1 << 11; ++ WriteParams.usWriteData |= f_ulPhase; ++ break; ++ default: ++ /* No problem. */ ++ break; ++ } ++ ++ /* Set the silence suppression flag.*/ ++ WriteParams.usWriteData |= f_ulEnableSilenceSuppression << cOCT6100_CONVERSION_CONTROL_MEM_SIL_SUP_OFFSET; ++ ++ /* Set the nibble position.*/ ++ WriteParams.usWriteData |= f_ulAdpcmNibblePosition << cOCT6100_CONVERSION_CONTROL_MEM_NIBBLE_POS_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base + 4 */ ++ WriteParams.ulWriteAddress += 2; ++ ++ /* Set the reset mode */ ++ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_RST_ON_NEXT_FR; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base + 6 */ ++ WriteParams.ulWriteAddress += 2; ++ ++ /* Set the reset mode */ ++ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ACTIVATE_ENTRY; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteDecoderMemory ++ ++Description: This function configure a Decoder memory entry in internal memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usDecoderIndex Index of the decoder block within the ADPCM context memory. ++f_ulCompType Decompression rate of the decoder. ++f_usTsiMemIndex TSI index within the TSI chariot memory. ++f_ulPcmLaw PCM law of the decoded samples. ++f_ulAdpcmNibblePosition ADPCM nibble position. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteDecoderMemory ++UINT32 Oct6100ApiWriteDecoderMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usDecoderIndex, ++ IN UINT32 f_ulCompType, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT32 f_ulPcmLaw, ++ IN UINT32 f_ulAdpcmNibblePosition ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base */ ++ WriteParams.ulWriteAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_usDecoderIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_DECODER; ++ WriteParams.usWriteData |= f_ulCompType << cOCT6100_CONVERSION_CONTROL_MEM_COMP_OFFSET; ++ WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base + 2 */ ++ WriteParams.ulWriteAddress += 2; ++ ++ /* Set the nibble position.*/ ++ WriteParams.usWriteData = (UINT16)( f_ulAdpcmNibblePosition << cOCT6100_CONVERSION_CONTROL_MEM_NIBBLE_POS_OFFSET ); ++ ++ /* Set the law.*/ ++ WriteParams.usWriteData |= f_ulPcmLaw << cOCT6100_CONVERSION_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base + 4 */ ++ WriteParams.ulWriteAddress += 2; ++ ++ /* Set the reset mode */ ++ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_RST_ON_NEXT_FR; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ /* Conversion Control Base + 6 */ ++ WriteParams.ulWriteAddress += 2; ++ ++ /* Set the reset mode */ ++ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ACTIVATE_ENTRY; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiClearConversionMemory ++ ++Description: This function clears a conversion memory entry in internal ++ memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usConversionMemIndex Index of the block within the conversion memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiClearConversionMemory ++UINT32 Oct6100ApiClearConversionMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usConversionMemIndex ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT32 ulBaseAddress; ++ UINT16 usReadData; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ WriteParams.usWriteData = 0; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /*==============================================================================*/ ++ /* Clear the entry */ ++ ulBaseAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_usConversionMemIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); ++ /* The "activate" bit at offset +6 must be cleared first. */ ++ WriteParams.ulWriteAddress = ulBaseAddress + 6; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Read at 0x200 to make sure there is no corruption on channel 0. */ ++ ReadParams.ulReadAddress = 0x200; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Then clear the rest of the structure. */ ++ WriteParams.ulWriteAddress = ulBaseAddress + 4; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + 2; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteVqeMemory ++ ++Description: This function configure an echo memory entry in internal memory and ++ external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pVqeConfig Pointer to a VQE config structure. ++f_pChannelOpen Pointer to a channel configuration structure. ++f_usChanIndex Index of the echo channel in the API instance. ++f_usEchoMemIndex Index of the echo channel within the SSPX memory. ++f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. ++f_fModifyOnly Flag indicating if the configuration should be ++ modified only. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteVqeMemory ++UINT32 Oct6100ApiWriteVqeMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearPlayoutPointers, ++ IN BOOL f_fModifyOnly ) ++{ ++ UINT32 ulResult; ++ ++ /* Write the NLP software configuration structure. */ ++ ulResult = Oct6100ApiWriteVqeNlpMemory( ++ f_pApiInstance, ++ f_pVqeConfig, ++ f_pChannelOpen, ++ f_usChanIndex, ++ f_usEchoMemIndex, ++ f_fClearPlayoutPointers, ++ f_fModifyOnly ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write the AF software configuration structure. */ ++ ulResult = Oct6100ApiWriteVqeAfMemory( ++ f_pApiInstance, ++ f_pVqeConfig, ++ f_pChannelOpen, ++ f_usChanIndex, ++ f_usEchoMemIndex, ++ f_fClearPlayoutPointers, ++ f_fModifyOnly ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++UINT32 oct6100_retrieve_nlp_conf_dword(tPOCT6100_INSTANCE_API f_pApiInst, ++ tPOCT6100_API_CHANNEL f_pChanEntry, ++ UINT32 f_ulAddress, ++ UINT32 *f_pulConfigDword) ++{ ++ tOCT6100_READ_PARAMS _ReadParams; ++ UINT16 _usReadData; ++ UINT32 ulResult = cOCT6100_ERR_FATAL_8E; ++ (*f_pulConfigDword) = cOCT6100_INVALID_VALUE; ++ ++ _ReadParams.pProcessContext = f_pApiInst->pProcessContext; ++ mOCT6100_ASSIGN_USER_READ_WRITE_OBJ(f_pApiInst, _ReadParams); ++ _ReadParams.ulUserChipId = f_pApiInst->pSharedInfo->ChipConfig.ulUserChipId; ++ _ReadParams.pusReadData = &_usReadData; ++ ++ /* Read the first 16 bits.*/ ++ _ReadParams.ulReadAddress = f_ulAddress; ++ mOCT6100_DRIVER_READ_API(_ReadParams, ulResult); ++ if (ulResult == cOCT6100_ERR_OK) { ++ /* Save data.*/ ++ (*f_pulConfigDword) = _usReadData << 16; ++ ++ /* Read the last 16 bits .*/ ++ _ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API(_ReadParams, ulResult); ++ if (ulResult == cOCT6100_ERR_OK) { ++ /* Save data.*/ ++ (*f_pulConfigDword) |= _usReadData; ++ ulResult = cOCT6100_ERR_OK; ++ } ++ } ++ return ulResult; ++} ++ ++UINT32 oct6100_save_nlp_conf_dword(tPOCT6100_INSTANCE_API f_pApiInst, ++ tPOCT6100_API_CHANNEL f_pChanEntry, ++ UINT32 f_ulAddress, ++ UINT32 f_ulConfigDword) ++{ ++ UINT32 ulResult; ++ ++ /* Write the config DWORD. */ ++ tOCT6100_WRITE_PARAMS _WriteParams; ++ ++ _WriteParams.pProcessContext = f_pApiInst->pProcessContext; ++ mOCT6100_ASSIGN_USER_READ_WRITE_OBJ(f_pApiInst, _WriteParams) ++ _WriteParams.ulUserChipId = f_pApiInst->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Write the first 16 bits. */ ++ _WriteParams.ulWriteAddress = f_ulAddress; ++ _WriteParams.usWriteData = (UINT16)((f_ulConfigDword >> 16) & 0xFFFF); ++ mOCT6100_DRIVER_WRITE_API(_WriteParams, ulResult); ++ ++ if (ulResult == cOCT6100_ERR_OK) { ++ /* Write the last word. */ ++ _WriteParams.ulWriteAddress = f_ulAddress + 2; ++ _WriteParams.usWriteData = (UINT16)(f_ulConfigDword & 0xFFFF); ++ mOCT6100_DRIVER_WRITE_API(_WriteParams, ulResult); ++ } ++ return ulResult; ++} ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteVqeNlpMemory ++ ++Description: This function configures the NLP related VQE features of an ++ echo channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pVqeConfig Pointer to a VQE config structure. ++f_pChannelOpen Pointer to a channel configuration structure. ++f_usChanIndex Index of the echo channel in the API instance. ++f_usEchoMemIndex Index of the echo channel within the SSPX memory. ++f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. ++f_fModifyOnly Flag indicating if the configuration should be ++ modified only. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteVqeNlpMemory ++UINT32 Oct6100ApiWriteVqeNlpMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearPlayoutPointers, ++ IN BOOL f_fModifyOnly ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ UINT32 ulNlpConfigBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulMask; ++ UINT16 usTempData; ++ BOOL fEchoOperationModeChanged; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ /*==============================================================================*/ ++ /* Configure the CPU NLP configuration of the channel feature by feature.*/ ++ ++ ulNlpConfigBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ /* Set initial value to zero.*/ ++ ulTempData = 0; ++ ++ /* Configure Adaptive Noise Reduction.*/ ++ if (pSharedInfo->ImageInfo.fAdaptiveNoiseReduction == TRUE) { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->fSoutAdaptiveNoiseReduction != pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction ) ++ || ( f_pVqeConfig->fSoutNoiseBleaching != pChanEntry->VqeConfig.fSoutNoiseBleaching ) ++ ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set adaptive noise reduction on the SOUT port.*/ ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fSoutAdaptiveNoiseReduction ) << ulFeatureBitOffset ); ++ ++ /* If SOUT noise bleaching is requested, ANR must be activated. */ ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fSoutNoiseBleaching ) << ulFeatureBitOffset ); ++ ++ /* First read the DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Configure Rout Noise Reduction. */ ++ if (pSharedInfo->ImageInfo.fRoutNoiseReduction == TRUE) { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fRoutNoiseReduction != pChanEntry->VqeConfig.fRoutNoiseReduction ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinAnrOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.RinAnrOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.RinAnrOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set noise reduction on the Rout port. */ ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fRoutNoiseReduction ) << ulFeatureBitOffset ); ++ ++ /* Write the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ if (pSharedInfo->ImageInfo.fRoutNoiseReductionLevel == TRUE) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( (f_pVqeConfig->lRoutNoiseReductionLevelGainDb != pChanEntry->VqeConfig.chRoutNoiseReductionLevelGainDb ) ++ ||( f_pVqeConfig->fRoutNoiseReduction != pChanEntry->VqeConfig.fRoutNoiseReduction ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinAnrValOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.RinAnrValOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.RinAnrValOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if (f_pVqeConfig->fRoutNoiseReduction == TRUE) ++ { ++ switch( f_pVqeConfig->lRoutNoiseReductionLevelGainDb) ++ { ++ case 0: ulTempData |= ( 0 << ulFeatureBitOffset ); ++ break; ++ case -6: ulTempData |= ( 1 << ulFeatureBitOffset ); ++ break; ++ case -12: ulTempData |= ( 2 << ulFeatureBitOffset ); ++ break; ++ case -18: ulTempData |= ( 3 << ulFeatureBitOffset ); ++ break; ++ default: ulTempData |= ( 0 << ulFeatureBitOffset ); ++ break; ++ } ++ } ++ else ++ ulTempData |= ( 0 << ulFeatureBitOffset ); ++ ++ /* Write the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ } ++ ++ /* Configure Sout ANR SNR enhancement. */ ++ if ( pSharedInfo->ImageInfo.fAnrSnrEnhancement == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->lAnrSnrEnhancementDb != pChanEntry->VqeConfig.chAnrSnrEnhancementDb ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set ANR SNR enhancement on the Sout port. */ ++ switch( f_pVqeConfig->lAnrSnrEnhancementDb ) ++ { ++ case -9: ulTempData |= ( 7 << ulFeatureBitOffset ); ++ break; ++ case -12: ulTempData |= ( 6 << ulFeatureBitOffset ); ++ break; ++ case -15: ulTempData |= ( 5 << ulFeatureBitOffset ); ++ break; ++ case -21: ulTempData |= ( 3 << ulFeatureBitOffset ); ++ break; ++ case -24: ulTempData |= ( 2 << ulFeatureBitOffset ); ++ break; ++ case -27: ulTempData |= ( 1 << ulFeatureBitOffset ); ++ break; ++ case -30: ulTempData |= ( 0 << ulFeatureBitOffset ); ++ break; ++ default: ulTempData |= ( 4 << ulFeatureBitOffset ); ++ /* -18 */ ++ break; ++ } ++ ++ /* Write the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Configure Sout ANR voice-noise segregation. */ ++ if ( pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->ulAnrVoiceNoiseSegregation != pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set ANR voice-noise segregation on the Sout port. */ ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->ulAnrVoiceNoiseSegregation ) << ulFeatureBitOffset ); ++ ++ /* Write the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Configure the tone disabler VQE activation delay. */ ++ if ( pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay ) ++ || ( f_pChannelOpen->fEnableToneDisabler != pChanEntry->fEnableToneDisabler ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set the tone disabler VQE activation delay. The VQE activation delay */ ++ /* is only set if the tone disabler is activated. */ ++ if ( f_pChannelOpen->fEnableToneDisabler == TRUE ) ++ ulTempData |= ( ( (UINT32)( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay - 300 ) / 512 ) ) << ulFeatureBitOffset ); ++ else ++ ulTempData |= ( 0 ) << ulFeatureBitOffset; ++ ++ /* Write the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Configure Conferencing Noise Reduction.*/ ++ if ( pSharedInfo->ImageInfo.fConferencingNoiseReduction == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->fSoutConferencingNoiseReduction != pChanEntry->VqeConfig.fSoutConferencingNoiseReduction ) ++ || ( f_pVqeConfig->fSoutNoiseBleaching != pChanEntry->VqeConfig.fSoutNoiseBleaching ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set conferencing noise reduction on the SOUT port. */ ++ ulTempData |= (f_pVqeConfig->fSoutConferencingNoiseReduction << ulFeatureBitOffset ); ++ ++ /* If SOUT noise bleaching is requested, CNR must be activated. */ ++ ulTempData |= (f_pVqeConfig->fSoutNoiseBleaching << ulFeatureBitOffset ); ++ ++ /* Save the DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the DC removal on RIN ports.*/ ++ if ( pSharedInfo->ImageInfo.fRinDcOffsetRemoval == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fRinDcOffsetRemoval != pChanEntry->VqeConfig.fRinDcOffsetRemoval ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set adaptive noise reduction on the SOUT port.*/ ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fRinDcOffsetRemoval ) << ulFeatureBitOffset ); ++ ++ /* The write the new DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the DC removal on SIN ports.*/ ++ if ( pSharedInfo->ImageInfo.fSinDcOffsetRemoval == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fSinDcOffsetRemoval != pChanEntry->VqeConfig.fSinDcOffsetRemoval ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set adaptive noise reduction on the SOUT port.*/ ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fSinDcOffsetRemoval ) << ulFeatureBitOffset ); ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the level control. */ ++ if ( ( pChanEntry->byEchoOperationMode != f_pChannelOpen->ulEchoOperationMode ) ++ && ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NORMAL ) ) ++ fEchoOperationModeChanged = TRUE; ++ else ++ fEchoOperationModeChanged = FALSE; ++ ++ /* If opening the channel, all level control configuration must be written. */ ++ if ( f_fModifyOnly == FALSE ) ++ fEchoOperationModeChanged = TRUE; ++ ulResult = Oct6100ApiSetChannelLevelControl( f_pApiInstance, ++ f_pVqeConfig, ++ f_usChanIndex, ++ f_usEchoMemIndex, ++ fEchoOperationModeChanged ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the background noise freeze.*/ ++ if ( pSharedInfo->ImageInfo.fComfortNoise == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->ulComfortNoiseMode != pChanEntry->VqeConfig.byComfortNoiseMode ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ulTempData |= ( f_pVqeConfig->ulComfortNoiseMode << ulFeatureBitOffset ); ++ ++ /* Save the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the state of the NLP */ ++ if ( pSharedInfo->ImageInfo.fNlpControl == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fEnableNlp != pChanEntry->VqeConfig.fEnableNlp ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpControlFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpControlFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpControlFieldOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( f_pVqeConfig->fEnableNlp == FALSE ) ++ ulTempData |= 0x1 << ulFeatureBitOffset; ++ ++ /* Save the new DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the tail configuration. */ ++ ulResult = Oct6100ApiSetChannelTailConfiguration( ++ f_pApiInstance, ++ f_pVqeConfig, ++ f_usChanIndex, ++ f_usEchoMemIndex, ++ f_fModifyOnly ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the Default ERL. */ ++ if ( ( pSharedInfo->ImageInfo.fDefaultErl == TRUE ) && ( f_pVqeConfig->fAcousticEcho == FALSE ) ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->lDefaultErlDb != pChanEntry->VqeConfig.chDefaultErlDb ) ++ || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ++ || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.DefaultErlFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.DefaultErlFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.DefaultErlFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Convert the DB value to octasic's float format. (In energy) */ ++ if ( ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ && ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) ++ { ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lDefaultErlDb ); ++ } ++ else ++ { ++ /* Clear the defautl ERL when using the no echo cancellation operation mode. */ ++ usTempData = 0x0; ++ } ++ ++ if ( ulFeatureFieldLength < 16 ) ++ usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); ++ ++ ulTempData |= ( usTempData << ulFeatureBitOffset ); ++ ++ /* Save the new DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the Acoustic echo control.*/ ++ if ( pSharedInfo->ImageInfo.fAcousticEcho == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AecFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AecFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fAcousticEcho ) << ulFeatureBitOffset ); ++ ++ /* Then save the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the Acoustic Echo Default ERL. */ ++ if ( ( pSharedInfo->ImageInfo.fAecDefaultErl == TRUE ) && ( f_pVqeConfig->fAcousticEcho == TRUE ) ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->lAecDefaultErlDb != pChanEntry->VqeConfig.chAecDefaultErlDb ) ++ || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ && ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) ++ { ++ /* Convert the DB value to octasic's float format. (In energy) */ ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lAecDefaultErlDb ); ++ } ++ else ++ { ++ /* Clear the AEC defautl ERL when using the no echo cancellation operation mode. */ ++ usTempData = 0x0; ++ } ++ ++ if ( ulFeatureFieldLength < 16 ) ++ usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); ++ ++ ulTempData |= ( usTempData << ulFeatureBitOffset ); ++ ++ /* Then save the DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the DTMF tone removal bit.*/ ++ if ( pSharedInfo->ImageInfo.fToneRemoval == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fDtmfToneRemoval != pChanEntry->VqeConfig.fDtmfToneRemoval ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fDtmfToneRemoval ) << ulFeatureBitOffset ); ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ ++ ++ /* Set the non-linear behavior A.*/ ++ if ( pSharedInfo->ImageInfo.fNonLinearityBehaviorA == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->ulNonLinearityBehaviorA != pChanEntry->VqeConfig.byNonLinearityBehaviorA ) ++ || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) ++ { ++ UINT16 ausLookupTable[ 14 ] = { 0x3663, 0x3906, 0x399C, 0x3A47, 0x3B06, 0x3B99, 0x3C47, 0x3D02, 0x3D99, 0x3E47, 0x3F00, 0x3F99, 0x4042, 0x4100 }; ++ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PcmLeakFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.PcmLeakFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.PcmLeakFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /*If we support ANR level the TLV is shared over 2 bits*/ ++ if (ulFeatureBitOffset == 18) ++ { ++ ulFeatureBitOffset -= 2; ++ ausLookupTable[ f_pVqeConfig->ulNonLinearityBehaviorA ] &= 0xFFFC; ++ } ++ ++ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) ++ ulTempData |= ( 0x0 << ulFeatureBitOffset ); ++ else ++ ulTempData |= ( ausLookupTable[ f_pVqeConfig->ulNonLinearityBehaviorA ] << ulFeatureBitOffset ); ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Synch all the buffer playout field.*/ ++ if ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE && f_fClearPlayoutPointers == TRUE ) ++ { ++ Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); ++ ++ BufferPlayoutStop.ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ BufferPlayoutStop.fStopCleanly = TRUE; ++ ++ BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ++ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( ++ f_pApiInstance, ++ &BufferPlayoutStop, ++ f_usChanIndex, ++ f_usEchoMemIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; ++ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( ++ f_pApiInstance, ++ &BufferPlayoutStop, ++ f_usChanIndex, ++ f_usEchoMemIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*==============================================================================*/ ++ /* Write the 2100 Hz Echo Disabling mode */ ++ ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pChannelOpen->fEnableToneDisabler != pChanEntry->fEnableToneDisabler ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneDisablerControlOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneDisablerControlOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneDisablerControlOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* This is a disable bit, so it must be set only if the enable flag is set to false. */ ++ if ( f_pChannelOpen->fEnableToneDisabler == FALSE ) ++ ulTempData |= 0x1 << ulFeatureBitOffset; ++ ++ /* Save the DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Write the Nlp Trivial enable flag. */ ++ ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ++ ++ ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) ++ { ++ ulTempData |= TRUE << ulFeatureBitOffset; ++ } ++ ++ ++ /* Then write the DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Set the double talk behavior mode. */ ++ if ( pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->ulDoubleTalkBehavior != pChanEntry->VqeConfig.byDoubleTalkBehavior ) ) ) ++ { ++ /* The field is located in the CPURO structure. */ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ulTempData |= (f_pVqeConfig->ulDoubleTalkBehavior << ulFeatureBitOffset ); ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Set the music protection enable. */ ++ if ( ( pSharedInfo->ImageInfo.fMusicProtection == TRUE ) ++ && ( pSharedInfo->ImageInfo.fMusicProtectionConfiguration == TRUE ) ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fEnableMusicProtection != pChanEntry->VqeConfig.fEnableMusicProtection ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ if ( f_pVqeConfig->fEnableMusicProtection == TRUE ) ++ ulTempData |= ( 1 << ulFeatureBitOffset ); ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteVqeAfMemory ++ ++Description: This function configures the AF related VQE features of an ++ echo channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pVqeConfig Pointer to a VQE config structure. ++f_pChannelOpen Pointer to a channel configuration structure. ++f_usChanIndex Index of the echo channel in the API instance. ++f_usEchoMemIndex Index of the echo channel within the SSPX memory. ++f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. ++f_fModifyOnly Flag indicating if the configuration should be ++ modified only. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteVqeAfMemory ++UINT32 Oct6100ApiWriteVqeAfMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearPlayoutPointers, ++ IN BOOL f_fModifyOnly ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ UINT32 ulAfConfigBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulMask; ++ UINT16 usTempData; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ /*==============================================================================*/ ++ /* Write the AF CPU configuration of the channel feature by feature.*/ ++ ++ /* Calculate AF CPU configuration base address. */ ++ ulAfConfigBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; ++ ++ /* Set initial value to zero.*/ ++ ulTempData = 0; ++ ++ /*==============================================================================*/ ++ /* Program the Maximum echo point within the Main channel memory.*/ ++ if ( pSharedInfo->ImageInfo.fMaxEchoPoint == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->lDefaultErlDb != pChanEntry->VqeConfig.chDefaultErlDb ) ++ || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) ++ { ++ /* Write the echo tail length */ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Convert the DB value to octasic's float format.*/ ++ if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ { ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lDefaultErlDb ); ++ } ++ else ++ { ++ /* Clear max echo point. No echo cancellation here. */ ++ usTempData = 0x0; ++ } ++ ++ if ( ulFeatureFieldLength < 16 ) ++ usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); ++ ++ ulTempData |= usTempData << ulFeatureBitOffset; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Set the non-linear behavior B.*/ ++ if ( pSharedInfo->ImageInfo.fNonLinearityBehaviorB == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->ulNonLinearityBehaviorB != pChanEntry->VqeConfig.byNonLinearityBehaviorB ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ulTempData |= (f_pVqeConfig->ulNonLinearityBehaviorB << ulFeatureBitOffset ); ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Set the listener enhancement feature. */ ++ if ( pSharedInfo->ImageInfo.fListenerEnhancement == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb ) ++ || ( f_pVqeConfig->fSoutNaturalListenerEnhancement != pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement ) ++ || ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AdaptiveAleOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AdaptiveAleOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AdaptiveAleOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 ) ++ { ++ UINT32 ulGainDb; ++ ++ ulGainDb = f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb / 3; ++ ++ /* Round up. */ ++ if ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb % 3 ) != 0x0 ) ++ ulGainDb ++; ++ ++ ulTempData |= ( ulGainDb << ulFeatureBitOffset ); ++ } ++ else if ( f_pVqeConfig->fSoutNaturalListenerEnhancement != 0 ) ++ { ++ UINT32 ulGainDb; ++ ++ ulGainDb = f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb / 3; ++ ++ /* Round up. */ ++ if ( ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb % 3 ) != 0x0 ) ++ ulGainDb ++; ++ ++ ulTempData |= ( ( 0x80 | ulGainDb ) << ulFeatureBitOffset ); ++ } ++ ++ /* Now write the DWORD where the field is located containing the new configuration. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Set the idle code detection enable. */ ++ if ( ( pSharedInfo->ImageInfo.fIdleCodeDetection == TRUE ) ++ && ( pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration == TRUE ) ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->fIdleCodeDetection != pChanEntry->VqeConfig.fIdleCodeDetection ) ) ) ++ { ++ /* Calculate base address in the AF software configuration. */ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ if ( f_pVqeConfig->fIdleCodeDetection == FALSE ) ++ ulTempData |= ( 1 << ulFeatureBitOffset ); ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Set the AFT control field. */ ++ if ( pSharedInfo->ImageInfo.fAftControl == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AftControlOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AftControlOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AftControlOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* If the operation mode is no echo, set the field such that echo cancellation is disabled. */ ++ if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ { ++ ulTempData |= ( 0x1234 << ulFeatureBitOffset ); ++ } ++ else if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ++ { ++ /* For clarity. */ ++ ulTempData |= ( 0x0 << ulFeatureBitOffset ); ++ } ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfigBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteEchoMemory ++ ++Description: This function configure an echo memory entry in internal memory.and ++ external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pTdmConfig Pointer to a TDM config structure. ++f_pChannelOpen Pointer to a channel configuration structure. ++f_usEchoIndex Echo channel index within the SSPX memory. ++f_usRinRoutTsiIndex RIN/ROUT TSI index within the TSI chariot memory ++f_usSinSoutTsiIndex SIN/SOUT TSI index within the TSI chariot memory ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteEchoMemory ++UINT32 Oct6100ApiWriteEchoMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usEchoIndex, ++ IN UINT16 f_usRinRoutTsiIndex, ++ IN UINT16 f_usSinSoutTsiIndex ) ++ ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ UINT32 ulBaseAddress; ++ UINT32 ulRinPcmLaw; ++ UINT32 ulRoutPcmLaw; ++ UINT32 ulSinPcmLaw; ++ UINT32 ulSoutPcmLaw; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Set immediately the PCM law to be programmed in the SSPX and NLP memory.*/ ++ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ ulRinPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; ++ ulRoutPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; ++ ulSinPcmLaw = f_pChannelOpen->TdmConfig.ulSinPcmLaw; ++ ulSoutPcmLaw = f_pChannelOpen->TdmConfig.ulSinPcmLaw; ++ } ++ else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ++ { ++ ulRinPcmLaw = f_pChannelOpen->TdmConfig.ulRinPcmLaw; ++ ulRoutPcmLaw = f_pChannelOpen->TdmConfig.ulRinPcmLaw; ++ ulSinPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; ++ ulSoutPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; ++ } ++ ++ /*==============================================================================*/ ++ /* Configure the Global Static Configuration of the channel.*/ ++ ++ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + cOCT6100_CHANNEL_ROOT_GLOBAL_CONF_OFFSET; ++ ++ /* Set the PGSP context base address. */ ++ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + cOCT6100_CH_MAIN_PGSP_CONTEXT_OFFSET; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_CONTEXT_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the PGSP init context base address. */ ++ ulTempData = ( cOCT6100_IMAGE_FILE_BASE + 0x200 ) & 0x07FFFFFF; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_INIT_CONTEXT_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the RIN circular buffer base address. */ ++ ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst) & 0x07FFFF00; ++ ulTempData |= ( ulRoutPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); ++ ++ /* Set the circular buffer size.*/ ++ if (( pSharedInfo->MemoryMap.ulChanMainRinCBMemSize & 0xFFFF00FF ) != 0 ) ++ return cOCT6100_ERR_CHANNEL_INVALID_RIN_CB_SIZE; ++ ulTempData |= pSharedInfo->MemoryMap.ulChanMainRinCBMemSize >> 8; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_RIN_CIRC_BUFFER_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the SIN circular buffer base address. */ ++ ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst) & 0x07FFFF00; ++ ulTempData |= ( ulSinPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SIN_CIRC_BUFFER_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the SOUT circular buffer base address. */ ++ ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst ) & 0x07FFFF00; ++ ulTempData |= ( ulSoutPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SOUT_CIRC_BUFFER_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* ECHO SSPX Memory configuration.*/ ++ ++ WriteParams.ulWriteAddress = cOCT6100_ECHO_CONTROL_MEM_BASE + ( f_usEchoIndex * cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE ); ++ ++ /* ECHO memory BASE + 2 */ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = 0x0000; ++ ++ /* Set the echo control field.*/ ++ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) ++ || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) ++ { ++ WriteParams.usWriteData |= cOCT6100_ECHO_OP_MODE_NORMAL << cOCT6100_ECHO_CONTROL_MEM_AF_CONTROL; ++ } ++ else if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL ) ++ { ++ WriteParams.usWriteData |= f_pChannelOpen->ulEchoOperationMode << cOCT6100_ECHO_CONTROL_MEM_AF_CONTROL; ++ } ++ ++ /* Set the SIN/SOUT law.*/ ++ WriteParams.usWriteData |= ulSinPcmLaw << cOCT6100_ECHO_CONTROL_MEM_INPUT_LAW_OFFSET; ++ WriteParams.usWriteData |= ulSoutPcmLaw << cOCT6100_ECHO_CONTROL_MEM_OUTPUT_LAW_OFFSET; ++ ++ /* Set the TSI chariot memory field.*/ ++ WriteParams.usWriteData |= f_usSinSoutTsiIndex & cOCT6100_ECHO_CONTROL_MEM_TSI_MEM_MASK; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* ECHO memory BASE */ ++ WriteParams.ulWriteAddress -= 2; ++ WriteParams.usWriteData = cOCT6100_ECHO_CONTROL_MEM_ACTIVATE_ENTRY; ++ ++ /* Set the RIN/ROUT law.*/ ++ WriteParams.usWriteData |= ulRinPcmLaw << cOCT6100_ECHO_CONTROL_MEM_INPUT_LAW_OFFSET; ++ WriteParams.usWriteData |= ulRoutPcmLaw << cOCT6100_ECHO_CONTROL_MEM_OUTPUT_LAW_OFFSET; ++ ++ /* Set the RIN external echo control bit.*/ ++ if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_EXTERNAL ) ++ WriteParams.usWriteData |= cOCT6100_ECHO_CONTROL_MEM_EXTERNAL_AF_CTRL; ++ ++ /* Set the TSI chariot memory field.*/ ++ WriteParams.usWriteData |= f_usRinRoutTsiIndex & cOCT6100_ECHO_CONTROL_MEM_TSI_MEM_MASK; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateOpenStruct ++ ++Description: This function will copy the new parameter from the modify structure ++ into a channel open structure to be processed later by the same path ++ as the channel open function. ++ If a parameter is set to keep previous, it's current value will be ++ extracted from the channel entry in the API. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++IN f_pApiInstance Pointer to an API instance structure. ++IN f_pChanModify Pointer to a channel modify structure. ++IN OUT f_pChanOpen Pointer to a channel open structure. ++IN f_pChanEntry Pointer to an API channel structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateOpenStruct ++UINT32 Oct6100ApiUpdateOpenStruct( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChanModify, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChanOpen, ++ IN tPOCT6100_API_CHANNEL f_pChanEntry ) ++{ ++ ++ /* Check the generic Echo parameters.*/ ++ if ( f_pChanModify->ulEchoOperationMode == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->ulEchoOperationMode = f_pChanEntry->byEchoOperationMode; ++ else ++ f_pChanOpen->ulEchoOperationMode = f_pChanModify->ulEchoOperationMode; ++ ++ ++ if ( f_pChanModify->fEnableToneDisabler == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->fEnableToneDisabler = f_pChanEntry->fEnableToneDisabler; ++ else ++ f_pChanOpen->fEnableToneDisabler = f_pChanModify->fEnableToneDisabler; ++ ++ ++ if ( f_pChanModify->ulUserChanId == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->ulUserChanId = f_pChanEntry->ulUserChanId; ++ else ++ f_pChanOpen->ulUserChanId = f_pChanModify->ulUserChanId; ++ ++ ++ ++ /*======================================================================*/ ++ /* Now update the TDM config.*/ ++ /* Rin PCM LAW */ ++ if ( f_pChanModify->TdmConfig.ulRinPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRinPcmLaw = f_pChanEntry->TdmConfig.byRinPcmLaw; ++ else ++ f_pChanOpen->TdmConfig.ulRinPcmLaw = f_pChanModify->TdmConfig.ulRinPcmLaw; ++ ++ /* Sin PCM LAW */ ++ if ( f_pChanModify->TdmConfig.ulSinPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSinPcmLaw = f_pChanEntry->TdmConfig.bySinPcmLaw; ++ else ++ f_pChanOpen->TdmConfig.ulSinPcmLaw = f_pChanModify->TdmConfig.ulSinPcmLaw; ++ ++ /* Rout PCM LAW */ ++ if ( f_pChanModify->TdmConfig.ulRoutPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRoutPcmLaw = f_pChanEntry->TdmConfig.byRoutPcmLaw; ++ else ++ f_pChanOpen->TdmConfig.ulRoutPcmLaw = f_pChanModify->TdmConfig.ulRoutPcmLaw; ++ ++ /* Sout PCM LAW */ ++ if ( f_pChanModify->TdmConfig.ulSoutPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSoutPcmLaw = f_pChanEntry->TdmConfig.bySoutPcmLaw; ++ else ++ f_pChanOpen->TdmConfig.ulSoutPcmLaw = f_pChanModify->TdmConfig.ulSoutPcmLaw; ++ ++ ++ /* Rin Timeslot */ ++ if ( f_pChanModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRinTimeslot = f_pChanEntry->TdmConfig.usRinTimeslot; ++ else ++ f_pChanOpen->TdmConfig.ulRinTimeslot = f_pChanModify->TdmConfig.ulRinTimeslot; ++ ++ /* Rin Stream */ ++ if ( f_pChanModify->TdmConfig.ulRinStream == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRinStream = f_pChanEntry->TdmConfig.usRinStream; ++ else ++ f_pChanOpen->TdmConfig.ulRinStream = f_pChanModify->TdmConfig.ulRinStream; ++ ++ /* Rin Num TSSTs */ ++ if ( f_pChanModify->TdmConfig.ulRinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRinNumTssts = f_pChanEntry->TdmConfig.byRinNumTssts; ++ else ++ f_pChanOpen->TdmConfig.ulRinNumTssts = f_pChanModify->TdmConfig.ulRinNumTssts; ++ ++ ++ /* Sin Timeslot */ ++ if ( f_pChanModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSinTimeslot = f_pChanEntry->TdmConfig.usSinTimeslot; ++ else ++ f_pChanOpen->TdmConfig.ulSinTimeslot = f_pChanModify->TdmConfig.ulSinTimeslot; ++ ++ /* Sin Stream */ ++ if ( f_pChanModify->TdmConfig.ulSinStream == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSinStream = f_pChanEntry->TdmConfig.usSinStream; ++ else ++ f_pChanOpen->TdmConfig.ulSinStream = f_pChanModify->TdmConfig.ulSinStream; ++ ++ /* Sin Num TSSTs */ ++ if ( f_pChanModify->TdmConfig.ulSinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSinNumTssts = f_pChanEntry->TdmConfig.bySinNumTssts; ++ else ++ f_pChanOpen->TdmConfig.ulSinNumTssts = f_pChanModify->TdmConfig.ulSinNumTssts; ++ ++ ++ /* Rout Timeslot */ ++ if ( f_pChanModify->TdmConfig.ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRoutTimeslot = f_pChanEntry->TdmConfig.usRoutTimeslot; ++ else ++ f_pChanOpen->TdmConfig.ulRoutTimeslot = f_pChanModify->TdmConfig.ulRoutTimeslot; ++ ++ /* Rout Stream */ ++ if ( f_pChanModify->TdmConfig.ulRoutStream == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRoutStream = f_pChanEntry->TdmConfig.usRoutStream; ++ else ++ f_pChanOpen->TdmConfig.ulRoutStream = f_pChanModify->TdmConfig.ulRoutStream; ++ ++ /* Rout Num TSSTs */ ++ if ( f_pChanModify->TdmConfig.ulRoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulRoutNumTssts = f_pChanEntry->TdmConfig.byRoutNumTssts; ++ else ++ f_pChanOpen->TdmConfig.ulRoutNumTssts = f_pChanModify->TdmConfig.ulRoutNumTssts; ++ ++ ++ /* Sout Timeslot */ ++ if ( f_pChanModify->TdmConfig.ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSoutTimeslot = f_pChanEntry->TdmConfig.usSoutTimeslot; ++ else ++ f_pChanOpen->TdmConfig.ulSoutTimeslot = f_pChanModify->TdmConfig.ulSoutTimeslot; ++ ++ /* Sout Stream */ ++ if ( f_pChanModify->TdmConfig.ulSoutStream == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSoutStream = f_pChanEntry->TdmConfig.usSoutStream; ++ else ++ f_pChanOpen->TdmConfig.ulSoutStream = f_pChanModify->TdmConfig.ulSoutStream; ++ ++ /* Sout Num TSSTs */ ++ if ( f_pChanModify->TdmConfig.ulSoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->TdmConfig.ulSoutNumTssts = f_pChanEntry->TdmConfig.bySoutNumTssts; ++ else ++ f_pChanOpen->TdmConfig.ulSoutNumTssts = f_pChanModify->TdmConfig.ulSoutNumTssts; ++ ++ /*======================================================================*/ ++ ++ /*======================================================================*/ ++ /* Now update the VQE config.*/ ++ ++ if ( f_pChanModify->VqeConfig.ulComfortNoiseMode == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulComfortNoiseMode = f_pChanEntry->VqeConfig.byComfortNoiseMode; ++ else ++ f_pChanOpen->VqeConfig.ulComfortNoiseMode = f_pChanModify->VqeConfig.ulComfortNoiseMode; ++ ++ if ( f_pChanModify->VqeConfig.fEnableNlp == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fEnableNlp = f_pChanEntry->VqeConfig.fEnableNlp; ++ else ++ f_pChanOpen->VqeConfig.fEnableNlp = f_pChanModify->VqeConfig.fEnableNlp; ++ ++ if ( f_pChanModify->VqeConfig.fEnableTailDisplacement == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fEnableTailDisplacement = f_pChanEntry->VqeConfig.fEnableTailDisplacement; ++ else ++ f_pChanOpen->VqeConfig.fEnableTailDisplacement = f_pChanModify->VqeConfig.fEnableTailDisplacement; ++ ++ if ( f_pChanModify->VqeConfig.ulTailDisplacement == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulTailDisplacement = f_pChanEntry->VqeConfig.usTailDisplacement; ++ else ++ f_pChanOpen->VqeConfig.ulTailDisplacement = f_pChanModify->VqeConfig.ulTailDisplacement; ++ ++ /* Tail length cannot be modifed. */ ++ f_pChanOpen->VqeConfig.ulTailLength = f_pChanEntry->VqeConfig.usTailLength; ++ ++ ++ ++ if ( f_pChanModify->VqeConfig.fRinDcOffsetRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fRinDcOffsetRemoval = f_pChanEntry->VqeConfig.fRinDcOffsetRemoval; ++ else ++ f_pChanOpen->VqeConfig.fRinDcOffsetRemoval = f_pChanModify->VqeConfig.fRinDcOffsetRemoval; ++ ++ ++ if ( f_pChanModify->VqeConfig.fRinLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fRinLevelControl = f_pChanEntry->VqeConfig.fRinLevelControl; ++ else ++ f_pChanOpen->VqeConfig.fRinLevelControl = f_pChanModify->VqeConfig.fRinLevelControl; ++ ++ ++ if ( f_pChanModify->VqeConfig.fRinAutomaticLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fRinAutomaticLevelControl = f_pChanEntry->VqeConfig.fRinAutomaticLevelControl; ++ else ++ f_pChanOpen->VqeConfig.fRinAutomaticLevelControl = f_pChanModify->VqeConfig.fRinAutomaticLevelControl; ++ ++ ++ if ( f_pChanModify->VqeConfig.fRinHighLevelCompensation == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fRinHighLevelCompensation = f_pChanEntry->VqeConfig.fRinHighLevelCompensation; ++ else ++ f_pChanOpen->VqeConfig.fRinHighLevelCompensation = f_pChanModify->VqeConfig.fRinHighLevelCompensation; ++ ++ ++ if ( f_pChanModify->VqeConfig.lRinHighLevelCompensationThresholdDb == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = f_pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb; ++ else ++ f_pChanOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = f_pChanModify->VqeConfig.lRinHighLevelCompensationThresholdDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.fSinDcOffsetRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fSinDcOffsetRemoval = f_pChanEntry->VqeConfig.fSinDcOffsetRemoval; ++ else ++ f_pChanOpen->VqeConfig.fSinDcOffsetRemoval = f_pChanModify->VqeConfig.fSinDcOffsetRemoval; ++ ++ ++ if ( f_pChanModify->VqeConfig.fSoutAdaptiveNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fSoutAdaptiveNoiseReduction = f_pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction; ++ else ++ f_pChanOpen->VqeConfig.fSoutAdaptiveNoiseReduction = f_pChanModify->VqeConfig.fSoutAdaptiveNoiseReduction; ++ ++ ++ if ( f_pChanModify->VqeConfig.fSoutConferencingNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fSoutConferencingNoiseReduction = f_pChanEntry->VqeConfig.fSoutConferencingNoiseReduction; ++ else ++ f_pChanOpen->VqeConfig.fSoutConferencingNoiseReduction = f_pChanModify->VqeConfig.fSoutConferencingNoiseReduction; ++ ++ ++ if ( f_pChanModify->VqeConfig.fSoutNoiseBleaching == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fSoutNoiseBleaching = f_pChanEntry->VqeConfig.fSoutNoiseBleaching; ++ else ++ f_pChanOpen->VqeConfig.fSoutNoiseBleaching = f_pChanModify->VqeConfig.fSoutNoiseBleaching; ++ ++ ++ if ( f_pChanModify->VqeConfig.fSoutLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fSoutLevelControl = f_pChanEntry->VqeConfig.fSoutLevelControl; ++ else ++ f_pChanOpen->VqeConfig.fSoutLevelControl = f_pChanModify->VqeConfig.fSoutLevelControl; ++ ++ ++ if ( f_pChanModify->VqeConfig.fSoutAutomaticLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fSoutAutomaticLevelControl = f_pChanEntry->VqeConfig.fSoutAutomaticLevelControl; ++ else ++ f_pChanOpen->VqeConfig.fSoutAutomaticLevelControl = f_pChanModify->VqeConfig.fSoutAutomaticLevelControl; ++ ++ ++ if ( f_pChanModify->VqeConfig.lRinLevelControlGainDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) ++ f_pChanOpen->VqeConfig.lRinLevelControlGainDb = f_pChanEntry->VqeConfig.chRinLevelControlGainDb; ++ else ++ f_pChanOpen->VqeConfig.lRinLevelControlGainDb = f_pChanModify->VqeConfig.lRinLevelControlGainDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.lSoutLevelControlGainDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) ++ f_pChanOpen->VqeConfig.lSoutLevelControlGainDb = f_pChanEntry->VqeConfig.chSoutLevelControlGainDb; ++ else ++ f_pChanOpen->VqeConfig.lSoutLevelControlGainDb = f_pChanModify->VqeConfig.lSoutLevelControlGainDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.lRinAutomaticLevelControlTargetDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) ++ f_pChanOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = f_pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb; ++ else ++ f_pChanOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = f_pChanModify->VqeConfig.lRinAutomaticLevelControlTargetDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.lSoutAutomaticLevelControlTargetDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) ++ f_pChanOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = f_pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb; ++ else ++ f_pChanOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = f_pChanModify->VqeConfig.lSoutAutomaticLevelControlTargetDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.lDefaultErlDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) ++ f_pChanOpen->VqeConfig.lDefaultErlDb = f_pChanEntry->VqeConfig.chDefaultErlDb; ++ else ++ f_pChanOpen->VqeConfig.lDefaultErlDb = f_pChanModify->VqeConfig.lDefaultErlDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.lAecDefaultErlDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) ++ f_pChanOpen->VqeConfig.lAecDefaultErlDb = f_pChanEntry->VqeConfig.chAecDefaultErlDb; ++ else ++ f_pChanOpen->VqeConfig.lAecDefaultErlDb = f_pChanModify->VqeConfig.lAecDefaultErlDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.ulAecTailLength == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulAecTailLength = f_pChanEntry->VqeConfig.usAecTailLength; ++ else ++ f_pChanOpen->VqeConfig.ulAecTailLength = f_pChanModify->VqeConfig.ulAecTailLength; ++ ++ ++ if ( f_pChanModify->VqeConfig.fAcousticEcho == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fAcousticEcho = f_pChanEntry->VqeConfig.fAcousticEcho; ++ else ++ f_pChanOpen->VqeConfig.fAcousticEcho = f_pChanModify->VqeConfig.fAcousticEcho; ++ ++ ++ if ( f_pChanModify->VqeConfig.fDtmfToneRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fDtmfToneRemoval = f_pChanEntry->VqeConfig.fDtmfToneRemoval; ++ else ++ f_pChanOpen->VqeConfig.fDtmfToneRemoval = f_pChanModify->VqeConfig.fDtmfToneRemoval; ++ ++ ++ ++ ++ ++ if ( f_pChanModify->VqeConfig.ulNonLinearityBehaviorA == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulNonLinearityBehaviorA = f_pChanEntry->VqeConfig.byNonLinearityBehaviorA; ++ else ++ f_pChanOpen->VqeConfig.ulNonLinearityBehaviorA = f_pChanModify->VqeConfig.ulNonLinearityBehaviorA; ++ ++ ++ if ( f_pChanModify->VqeConfig.ulNonLinearityBehaviorB == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulNonLinearityBehaviorB = f_pChanEntry->VqeConfig.byNonLinearityBehaviorB; ++ else ++ f_pChanOpen->VqeConfig.ulNonLinearityBehaviorB = f_pChanModify->VqeConfig.ulNonLinearityBehaviorB; ++ ++ ++ if ( f_pChanModify->VqeConfig.ulDoubleTalkBehavior == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulDoubleTalkBehavior = f_pChanEntry->VqeConfig.byDoubleTalkBehavior; ++ else ++ f_pChanOpen->VqeConfig.ulDoubleTalkBehavior = f_pChanModify->VqeConfig.ulDoubleTalkBehavior; ++ ++ ++ if ( f_pChanModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = f_pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb; ++ else ++ f_pChanOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = f_pChanModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = f_pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb; ++ else ++ f_pChanOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = f_pChanModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.fSoutNaturalListenerEnhancement == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fSoutNaturalListenerEnhancement = f_pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement; ++ else ++ f_pChanOpen->VqeConfig.fSoutNaturalListenerEnhancement = f_pChanModify->VqeConfig.fSoutNaturalListenerEnhancement; ++ ++ ++ if ( f_pChanModify->VqeConfig.fRoutNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fRoutNoiseReduction = f_pChanEntry->VqeConfig.fRoutNoiseReduction; ++ else ++ f_pChanOpen->VqeConfig.fRoutNoiseReduction = f_pChanModify->VqeConfig.fRoutNoiseReduction; ++ ++ if ( f_pChanModify->VqeConfig.lRoutNoiseReductionLevelGainDb == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.lRoutNoiseReductionLevelGainDb = f_pChanEntry->VqeConfig.chRoutNoiseReductionLevelGainDb; ++ else ++ f_pChanOpen->VqeConfig.lRoutNoiseReductionLevelGainDb = f_pChanModify->VqeConfig.lRoutNoiseReductionLevelGainDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.lAnrSnrEnhancementDb == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.lAnrSnrEnhancementDb = f_pChanEntry->VqeConfig.chAnrSnrEnhancementDb; ++ else ++ f_pChanOpen->VqeConfig.lAnrSnrEnhancementDb = f_pChanModify->VqeConfig.lAnrSnrEnhancementDb; ++ ++ ++ if ( f_pChanModify->VqeConfig.ulAnrVoiceNoiseSegregation == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulAnrVoiceNoiseSegregation = f_pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation; ++ else ++ f_pChanOpen->VqeConfig.ulAnrVoiceNoiseSegregation = f_pChanModify->VqeConfig.ulAnrVoiceNoiseSegregation; ++ ++ ++ if ( f_pChanModify->VqeConfig.ulToneDisablerVqeActivationDelay == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.ulToneDisablerVqeActivationDelay = f_pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay; ++ else ++ f_pChanOpen->VqeConfig.ulToneDisablerVqeActivationDelay = f_pChanModify->VqeConfig.ulToneDisablerVqeActivationDelay; ++ ++ ++ if ( f_pChanModify->VqeConfig.fEnableMusicProtection == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fEnableMusicProtection = f_pChanEntry->VqeConfig.fEnableMusicProtection; ++ else ++ f_pChanOpen->VqeConfig.fEnableMusicProtection = f_pChanModify->VqeConfig.fEnableMusicProtection; ++ ++ ++ if ( f_pChanModify->VqeConfig.fIdleCodeDetection == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->VqeConfig.fIdleCodeDetection = f_pChanEntry->VqeConfig.fIdleCodeDetection; ++ else ++ f_pChanOpen->VqeConfig.fIdleCodeDetection = f_pChanModify->VqeConfig.fIdleCodeDetection; ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Finaly the codec config.*/ ++ ++ if ( f_pChanModify->CodecConfig.ulDecoderPort == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->CodecConfig.ulDecoderPort = f_pChanEntry->CodecConfig.byDecoderPort; ++ else ++ f_pChanOpen->CodecConfig.ulDecoderPort = f_pChanModify->CodecConfig.ulDecoderPort; ++ ++ ++ if ( f_pChanModify->CodecConfig.ulDecodingRate == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->CodecConfig.ulDecodingRate = f_pChanEntry->CodecConfig.byDecodingRate; ++ else ++ f_pChanOpen->CodecConfig.ulDecodingRate = f_pChanModify->CodecConfig.ulDecodingRate; ++ ++ ++ if ( f_pChanModify->CodecConfig.ulEncoderPort == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->CodecConfig.ulEncoderPort = f_pChanEntry->CodecConfig.byEncoderPort; ++ else ++ f_pChanOpen->CodecConfig.ulEncoderPort = f_pChanModify->CodecConfig.ulEncoderPort; ++ ++ ++ if ( f_pChanModify->CodecConfig.ulEncodingRate == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->CodecConfig.ulEncodingRate = f_pChanEntry->CodecConfig.byEncodingRate; ++ else ++ f_pChanOpen->CodecConfig.ulEncodingRate = f_pChanModify->CodecConfig.ulEncodingRate; ++ ++ if ( f_pChanModify->CodecConfig.fEnableSilenceSuppression == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->CodecConfig.fEnableSilenceSuppression = f_pChanEntry->CodecConfig.fEnableSilenceSuppression; ++ else ++ f_pChanOpen->CodecConfig.fEnableSilenceSuppression = f_pChanModify->CodecConfig.fEnableSilenceSuppression; ++ ++ if ( f_pChanModify->CodecConfig.ulPhasingType == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->CodecConfig.ulPhasingType = f_pChanEntry->CodecConfig.byPhasingType; ++ else ++ f_pChanOpen->CodecConfig.ulPhasingType = f_pChanModify->CodecConfig.ulPhasingType; ++ ++ if ( f_pChanModify->CodecConfig.ulPhase == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ f_pChanOpen->CodecConfig.ulPhase = f_pChanEntry->CodecConfig.byPhase; ++ else ++ f_pChanOpen->CodecConfig.ulPhase = f_pChanModify->CodecConfig.ulPhase; ++ ++ if ( f_pChanModify->CodecConfig.ulPhasingTsstHndl == cOCT6100_KEEP_PREVIOUS_SETTING ) ++ { ++ if ( f_pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ tPOCT6100_API_PHASING_TSST pPhasingEntry; ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, f_pChanEntry->usPhasingTsstIndex ); ++ ++ /* Now recreate the Phasing TSST handle.*/ ++ f_pChanOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_pChanEntry->usPhasingTsstIndex; ++ } ++ else ++ { ++ f_pChanOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; ++ } ++ } ++ else ++ { ++ f_pChanOpen->CodecConfig.ulPhasingTsstHndl = f_pChanModify->CodecConfig.ulPhasingTsstHndl; ++ } ++ ++ f_pChanOpen->CodecConfig.ulAdpcmNibblePosition = f_pChanEntry->CodecConfig.byAdpcmNibblePosition; ++ /*======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRetrieveNlpConfDword ++ ++Description: This function is used by the API to store on a per channel basis ++ the various confguration DWORD from the device. The API performs ++ less read to the chip that way since it is always in synch with the ++ chip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChanEntry Pointer to an API channel structure.. ++f_ulAddress Address that needs to be modified.. ++f_pulConfigDword Pointer to the content stored in the API located at the ++ desired address. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRetrieveNlpConfDword ++UINT32 Oct6100ApiRetrieveNlpConfDword( ++ ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_CHANNEL f_pChanEntry, ++ IN UINT32 f_ulAddress, ++ OUT PUINT32 f_pulConfigDword ) ++{ ++ UINT32 ulResult; ++ UINT32 ulFirstEmptyIndex = 0xFFFFFFFF; ++ UINT32 i; ++ ++ /* Search for the Dword.*/ ++ for ( i = 0; i < cOCT6100_MAX_NLP_CONF_DWORD; i++ ) ++ { ++ if ( ( ulFirstEmptyIndex == 0xFFFFFFFF ) && ( f_pChanEntry->aulNlpConfDword[ i ][ 0 ] == 0x0 ) ) ++ ulFirstEmptyIndex = i; ++ ++ if ( f_pChanEntry->aulNlpConfDword[ i ][ 0 ] == f_ulAddress ) ++ { ++ /* We found the matching Dword.*/ ++ *f_pulConfigDword = f_pChanEntry->aulNlpConfDword[ i ][ 1 ]; ++ return cOCT6100_ERR_OK; ++ } ++ } ++ ++ if ( i == cOCT6100_MAX_NLP_CONF_DWORD && ulFirstEmptyIndex == 0xFFFFFFFF ) ++ return cOCT6100_ERR_FATAL_8E; ++ ++ /* We did not found any entry, let's create a new entry.*/ ++ f_pChanEntry->aulNlpConfDword[ ulFirstEmptyIndex ][ 0 ] = f_ulAddress; ++ ++ ++ /* Read the DWORD where the field is located.*/ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulAddress, ++ f_pulConfigDword ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiSaveNlpConfDword ++ ++Description: This function stores a configuration Dword within an API channel ++ structure and then writes it into the chip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChanEntry Pointer to an API channel structure.. ++f_ulAddress Address that needs to be modified.. ++f_pulConfigDword content to be stored in the API located at the ++ desired address. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiSaveNlpConfDword ++UINT32 Oct6100ApiSaveNlpConfDword( ++ ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_CHANNEL f_pChanEntry, ++ IN UINT32 f_ulAddress, ++ IN UINT32 f_ulConfigDword ) ++{ ++ UINT32 ulResult; ++ UINT32 i; ++ ++ /* Search for the Dword.*/ ++ for ( i = 0; i < cOCT6100_MAX_NLP_CONF_DWORD; i++ ) ++ { ++ ++ if ( f_pChanEntry->aulNlpConfDword[ i ][ 0 ] == f_ulAddress ) ++ { ++ /* We found the matching Dword.*/ ++ f_pChanEntry->aulNlpConfDword[ i ][ 1 ] = f_ulConfigDword; ++ break; ++ } ++ } ++ ++ if ( i == cOCT6100_MAX_NLP_CONF_DWORD ) ++ return cOCT6100_ERR_FATAL_8F; ++ ++ ++ /* Write the config DWORD.*/ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ++ f_ulAddress, ++ f_ulConfigDword ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelCreateBiDirSer ++ ++Description: Creates a bidirectional echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelCreateBiDir Pointer to a create bidirectionnal channel structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelCreateBiDirSer ++UINT32 Oct6100ChannelCreateBiDirSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ) ++{ ++ UINT16 usFirstChanIndex; ++ UINT16 usFirstChanExtraTsiIndex; ++ UINT16 usFirstChanSinCopyEventIndex; ++ UINT16 usFirstChanSoutCopyEventIndex; ++ UINT16 usSecondChanIndex; ++ UINT16 usSecondChanExtraTsiIndex; ++ UINT16 usSecondChanSinCopyEventIndex; ++ UINT16 usSecondChanSoutCopyEventIndex; ++ UINT16 usBiDirChanIndex; ++ UINT32 ulResult; ++ ++ ++ /* Check the user's configuration of the bidir channel for errors. */ ++ ulResult = Oct6100ApiCheckChannelCreateBiDirParams( f_pApiInstance, ++ f_pChannelCreateBiDir, ++ &usFirstChanIndex, ++ &usFirstChanExtraTsiIndex, ++ &usFirstChanSinCopyEventIndex, ++ &usSecondChanIndex, ++ &usSecondChanExtraTsiIndex, ++ &usSecondChanSinCopyEventIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the bidir channel. */ ++ ulResult = Oct6100ApiReserveChannelCreateBiDirResources(f_pApiInstance, ++ ++ &usBiDirChanIndex, ++ &usFirstChanExtraTsiIndex, ++ &usFirstChanSinCopyEventIndex, ++ &usFirstChanSoutCopyEventIndex, ++ &usSecondChanExtraTsiIndex, ++ &usSecondChanSinCopyEventIndex, ++ &usSecondChanSoutCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write all necessary structures to activate the echo cancellation channel. */ ++ ulResult = Oct6100ApiWriteChannelCreateBiDirStructs( f_pApiInstance, ++ ++ usFirstChanIndex, ++ usFirstChanExtraTsiIndex, ++ usFirstChanSinCopyEventIndex, ++ usFirstChanSoutCopyEventIndex, ++ usSecondChanIndex, ++ usSecondChanExtraTsiIndex, ++ usSecondChanSinCopyEventIndex, ++ usSecondChanSoutCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the new echo cancellation channels's entry in the ECHO channel list. */ ++ ulResult = Oct6100ApiUpdateBiDirChannelEntry( f_pApiInstance, ++ f_pChannelCreateBiDir, ++ usBiDirChanIndex, ++ usFirstChanIndex, ++ usFirstChanExtraTsiIndex, ++ usFirstChanSinCopyEventIndex, ++ usFirstChanSoutCopyEventIndex, ++ usSecondChanIndex, ++ usSecondChanExtraTsiIndex, ++ usSecondChanSinCopyEventIndex, ++ usSecondChanSoutCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckChannelCreateBiDirParams ++ ++Description: Checks the user's parameter passed to the create bidirectional channel ++ function. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelCreateBiDir Pointer to a create bidirectionnal channel structure. ++f_pusFirstChanIndex Pointer to the first channel index. ++f_pusFirstChanExtraTsiIndex Pointer to the first channel extra TSI index. ++f_pusFirstChanSinCopyEventIndex Pointer to the first channel Sin copy event index. ++f_pusSecondChanIndex Pointer to the second channel index. ++f_pusSecondChanExtraTsiIndex Pointer to the second channel extra TSI index. ++f_pusSecondChanSinCopyEventIndex Pointer to the second channel Sin copy event index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckChannelCreateBiDirParams ++UINT32 Oct6100ApiCheckChannelCreateBiDirParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir, ++ OUT PUINT16 f_pusFirstChanIndex, ++ OUT PUINT16 f_pusFirstChanExtraTsiIndex, ++ OUT PUINT16 f_pusFirstChanSinCopyEventIndex, ++ OUT PUINT16 f_pusSecondChanIndex, ++ OUT PUINT16 f_pusSecondChanExtraTsiIndex, ++ OUT PUINT16 f_pusSecondChanSinCopyEventIndex ++ ++ ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pFirstChanEntry; ++ tPOCT6100_API_CHANNEL pSecondChanEntry; ++ UINT32 ulEntryOpenCnt; ++ BOOL fCheckTssts = TRUE; ++ ++ /* Obtain shared resources pointer.*/ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* validate the bidirectional channel handle memory.*/ ++ if ( f_pChannelCreateBiDir->pulBiDirChannelHndl == NULL ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; ++ ++ ++ ++ /* Check if bi-dir channels are activated. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxBiDirChannels == 0 ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_DISABLED; ++ ++ /*=======================================================================*/ ++ /* Verify the first channel handle. */ ++ ++ if ( (f_pChannelCreateBiDir->ulFirstChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_FIRST_CHANNEL_HANDLE; ++ ++ *f_pusFirstChanIndex = (UINT16)( f_pChannelCreateBiDir->ulFirstChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusFirstChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_FIRST_CHANNEL_HANDLE; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, *f_pusFirstChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelCreateBiDir->ulFirstChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pFirstChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pFirstChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_FIRST_CHANNEL_HANDLE; ++ ++ /* Check the specific state of the channel.*/ ++ if ( pFirstChanEntry->fRinRoutCodecActive == TRUE && pFirstChanEntry->CodecConfig.byEncoderPort != cOCT6100_CHANNEL_PORT_ROUT) ++ return cOCT6100_ERR_CHANNEL_CODEC_ACTIVATED; ++ if ( pFirstChanEntry->fSinSoutCodecActive == TRUE && pFirstChanEntry->CodecConfig.byEncoderPort != cOCT6100_CHANNEL_PORT_SOUT) ++ return cOCT6100_ERR_CHANNEL_CODEC_ACTIVATED; ++ if ( pFirstChanEntry->fBiDirChannel == TRUE ) ++ return cOCT6100_ERR_CHANNEL_ALREADY_BIDIR; ++ ++ if ( pFirstChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_FIRST_CHAN_IN_CONFERENCE; ++ ++ if ( fCheckTssts == TRUE ) ++ { ++ if ( pFirstChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_FIRST_CHAN_SOUT_PORT; ++ if ( pFirstChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_FIRST_CHAN_RIN_PORT; ++ } ++ ++ /* Return the desired info.*/ ++ *f_pusFirstChanExtraTsiIndex = pFirstChanEntry->usExtraSinTsiMemIndex; ++ *f_pusFirstChanSinCopyEventIndex = pFirstChanEntry->usSinCopyEventIndex; ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Verify the second channel handle. */ ++ ++ if ( (f_pChannelCreateBiDir->ulSecondChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_SECOND_CHANNEL_HANDLE; ++ ++ *f_pusSecondChanIndex = (UINT16)( f_pChannelCreateBiDir->ulSecondChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusSecondChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_SECOND_CHANNEL_HANDLE; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, *f_pusSecondChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelCreateBiDir->ulSecondChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pSecondChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pSecondChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_SECOND_CHANNEL_HANDLE; ++ ++ /* Check the specific state of the channel.*/ ++ if ( pSecondChanEntry->fRinRoutCodecActive == TRUE && pSecondChanEntry->CodecConfig.byEncoderPort != cOCT6100_CHANNEL_PORT_ROUT) ++ return cOCT6100_ERR_CHANNEL_CODEC_ACTIVATED; ++ if ( pSecondChanEntry->fSinSoutCodecActive == TRUE && pSecondChanEntry->CodecConfig.byEncoderPort != cOCT6100_CHANNEL_PORT_SOUT) ++ { ++ ++ return cOCT6100_ERR_CHANNEL_CODEC_ACTIVATED; ++ } ++ ++ if ( pSecondChanEntry->fBiDirChannel == TRUE ) ++ return cOCT6100_ERR_CHANNEL_ALREADY_BIDIR; ++ ++ if ( fCheckTssts == TRUE ) ++ { ++ if ( pSecondChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_SECOND_CHAN_SOUT_PORT; ++ if ( pSecondChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_SECOND_CHAN_RIN_PORT; ++ } ++ ++ if ( pSecondChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CHANNEL_SECOND_CHAN_IN_CONFERENCE; ++ ++ /* Return the desired info.*/ ++ *f_pusSecondChanExtraTsiIndex = pSecondChanEntry->usExtraSinTsiMemIndex; ++ *f_pusSecondChanSinCopyEventIndex = pSecondChanEntry->usSinCopyEventIndex; ++ /*=======================================================================*/ ++ ++ /* Check the law compatibility.*/ ++ if ( pFirstChanEntry->TdmConfig.bySoutPcmLaw != pSecondChanEntry->TdmConfig.byRinPcmLaw || ++ pFirstChanEntry->TdmConfig.byRinPcmLaw != pSecondChanEntry->TdmConfig.bySoutPcmLaw ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_PCM_LAW; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveChannelCreateBiDirResources ++ ++Description: Reserves all resources needed for the new bidirectional channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pusBiDirChanIndex Pointer to the index of the bidirectionnal channel within the API instance. ++f_pusFirstChanExtraTsiIndex Pointer to the first channel extra TSI index. ++f_pusFirstChanSinCopyEventIndex Pointer to the first channel Sin copy event index. ++f_pusFirstChanSoutCopyEventIndex Pointer to the first channel Sout copy event index. ++f_pusSecondChanExtraTsiIndex Pointer to the second channel extra TSI index. ++f_pusSecondChanSinCopyEventIndex Pointer to the second channel Sin copy event index. ++f_pusSecondChanSoutCopyEventIndex Pointer to the second channel Sout copy event index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveChannelCreateBiDirResources ++UINT32 Oct6100ApiReserveChannelCreateBiDirResources( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ OUT PUINT16 f_pusBiDirChanIndex, ++ IN OUT PUINT16 f_pusFirstChanExtraTsiIndex, ++ IN OUT PUINT16 f_pusFirstChanSinCopyEventIndex, ++ OUT PUINT16 f_pusFirstChanSoutCopyEventIndex, ++ IN OUT PUINT16 f_pusSecondChanExtraTsiIndex, ++ IN OUT PUINT16 f_pusSecondChanSinCopyEventIndex, ++ OUT PUINT16 f_pusSecondChanSoutCopyEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 ulTempVar; ++ ++ BOOL fBiDirChanIndex = FALSE; ++ BOOL fFirstExtraTsi = FALSE; ++ BOOL fSecondExtraTsi = FALSE; ++ BOOL fFirstSinCopyEvent = FALSE; ++ BOOL fSecondSinCopyEvent = FALSE; ++ BOOL fFirstSoutCopyEvent = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /*===============================================================================*/ ++ /* Verify and reserve the resources that might already by allocated. */ ++ ++ ++ { ++ if ( *f_pusFirstChanExtraTsiIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* Reserve the first Extra TSI memory entry */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ f_pusFirstChanExtraTsiIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fFirstExtraTsi = TRUE; ++ } ++ ++ if ( *f_pusFirstChanSinCopyEventIndex == cOCT6100_INVALID_INDEX && ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Reserve the Sin copy event for the first channel.*/ ++ ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, ++ f_pusFirstChanSinCopyEventIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fFirstSinCopyEvent = TRUE; ++ } ++ } ++ ++ if ( *f_pusSecondChanExtraTsiIndex == cOCT6100_INVALID_INDEX && ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Reserve the second Extra TSI memory entry */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ f_pusSecondChanExtraTsiIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fSecondExtraTsi = TRUE; ++ } ++ ++ if ( *f_pusSecondChanSinCopyEventIndex == cOCT6100_INVALID_INDEX && ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Reserve the Sin copy event for the second channel.*/ ++ ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, ++ f_pusSecondChanSinCopyEventIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fSecondSinCopyEvent = TRUE; ++ } ++ /*===============================================================================*/ ++ ++ ++ /*===============================================================================*/ ++ /* Now reserve all the resources specific to bidirectional channels */ ++ ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReserveBiDirChanEntry( f_pApiInstance, ++ f_pusBiDirChanIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fBiDirChanIndex = TRUE; ++ ++ ++ { ++ ++ /* Reserve the first channel Sout copy mixer event.*/ ++ ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, ++ f_pusFirstChanSoutCopyEventIndex ); ++ } ++ ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fFirstSoutCopyEvent = TRUE; ++ ++ /* Reserve the second channel Sout copy mixer event.*/ ++ ulResult = Oct6100ApiReserveMixerEventEntry ( f_pApiInstance, ++ f_pusSecondChanSoutCopyEventIndex ); ++ } ++ } ++ } ++ ++ /*===============================================================================*/ ++ ++ ++ /*===============================================================================*/ ++ /* Release the resources if something went wrong */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /*===============================================================================*/ ++ /* Release the previously reserved echo resources .*/ ++ if ( fBiDirChanIndex == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseBiDirChanEntry( f_pApiInstance, ++ *f_pusBiDirChanIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fFirstExtraTsi == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, ++ *f_pusFirstChanExtraTsiIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fSecondExtraTsi == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, ++ *f_pusSecondChanExtraTsiIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fFirstSinCopyEvent == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, ++ *f_pusFirstChanSinCopyEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fSecondSinCopyEvent == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, ++ *f_pusSecondChanSinCopyEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( ( fFirstSoutCopyEvent == TRUE ) ++ ++ ) ++ { ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, ++ *f_pusFirstChanSoutCopyEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ /*===============================================================================*/ ++ ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteChannelCreateBiDirStructs ++ ++Description: Performs all the required structure writes to configure the ++ new echo cancellation channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usFirstChanIndex Pointer to the first channel index. ++f_usFirstChanExtraTsiIndex Pointer to the first channel extra TSI index. ++f_usFirstChanSinCopyEventIndex Pointer to the first channel Sin copy event index. ++f_usFirstChanSoutCopyEventIndex Pointer to the first channel Sout copy event index. ++f_usFirstChanIndex Pointer to the second channel index. ++f_usSecondChanExtraTsiIndex Pointer to the second channel extra TSI index. ++f_usSecondChanSinCopyEventIndex Pointer to the second channel Sin copy event index. ++f_usSecondChanSoutCopyEventIndex Pointer to the second channel Sout copy event index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteChannelCreateBiDirStructs ++UINT32 Oct6100ApiWriteChannelCreateBiDirStructs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usFirstChanExtraTsiIndex, ++ IN UINT16 f_usFirstChanSinCopyEventIndex, ++ IN UINT16 f_usFirstChanSoutCopyEventIndex, ++ IN UINT16 f_usSecondChanIndex, ++ IN UINT16 f_usSecondChanExtraTsiIndex, ++ IN UINT16 f_usSecondChanSinCopyEventIndex, ++ IN UINT16 f_usSecondChanSoutCopyEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pFirstChanEntry; ++ tPOCT6100_API_CHANNEL pSecondChanEntry; ++ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*==============================================================================*/ ++ /* Get a pointer to the two channel entry.*/ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); ++ ++ ++ ++ ++ { ++ /*==============================================================================*/ ++ /* Configure the Tsst control memory and add the Sin copy event if necessary. */ ++ ++ /*=======================================================================*/ ++ /* Program the Sin Copy event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usFirstChanSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= f_usFirstChanExtraTsiIndex; ++ WriteParams.usWriteData |= pFirstChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( pFirstChanEntry->usSinSoutTsiMemIndex ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Configure the TSST memory.*/ ++ if ( pFirstChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pFirstChanEntry->usSinTsstIndex, ++ f_usFirstChanExtraTsiIndex, ++ pFirstChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Now insert the event into the event list.*/ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_usFirstChanSinCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY, ++ f_usFirstChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ } ++ ++ ++ ++ /*==============================================================================*/ ++ /* Configure the Tsst control memory and add the Sin copy event if necessary.*/ ++ ++ /*=======================================================================*/ ++ /* Program the Sin Copy event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSecondChanSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= f_usSecondChanExtraTsiIndex; ++ WriteParams.usWriteData |= pSecondChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( pSecondChanEntry->usSinSoutTsiMemIndex ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Configure the TSST memory.*/ ++ if ( pSecondChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pSecondChanEntry->usSinTsstIndex, ++ f_usSecondChanExtraTsiIndex, ++ pSecondChanEntry->TdmConfig.bySinPcmLaw ); ++ } ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Now insert the event into the event list.*/ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_usSecondChanSinCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY, ++ f_usSecondChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ ++ /*==============================================================================*/ ++ /* Now, let's configure the two Sout copy events.*/ ++ ++ ++ /* First event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usFirstChanSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= pFirstChanEntry->usSinSoutTsiMemIndex; ++ WriteParams.usWriteData |= pFirstChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pSecondChanEntry->usRinRoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_usFirstChanSoutCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY, ++ f_usFirstChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ /* Second event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSecondChanSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= pSecondChanEntry->usSinSoutTsiMemIndex; ++ WriteParams.usWriteData |= pSecondChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pFirstChanEntry->usRinRoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_usSecondChanSoutCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY, ++ f_usSecondChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ /* Clear + release the silence events if they were created. */ ++ ++ if ( pFirstChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pFirstChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pFirstChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_E0; ++ ++ pFirstChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ if ( ( pSecondChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ ++ ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pSecondChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pSecondChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_E0; ++ ++ pSecondChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateBiDirChannelEntry ++ ++Description: Updates the new bidir channel and the channel used to create that channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateBiDirChannelEntry ++UINT32 Oct6100ApiUpdateBiDirChannelEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir, ++ IN UINT16 f_usBiDirChanIndex, ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usFirstChanExtraTsiIndex, ++ IN UINT16 f_usFirstChanSinCopyEventIndex, ++ IN UINT16 f_usFirstChanSoutCopyEventIndex, ++ IN UINT16 f_usSecondChanIndex, ++ IN UINT16 f_usSecondChanExtraTsiIndex, ++ IN UINT16 f_usSecondChanSinCopyEventIndex, ++ IN UINT16 f_usSecondChanSoutCopyEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pFirstChanEntry; ++ tPOCT6100_API_CHANNEL pSecondChanEntry; ++ tPOCT6100_API_BIDIR_CHANNEL pBiDirChanEntry; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, f_usBiDirChanIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); ++ ++ /*=======================================================================*/ ++ /* Copy the channel's configuration and allocated resources. */ ++ ++ pFirstChanEntry->usExtraSinTsiMemIndex = f_usFirstChanExtraTsiIndex; ++ pFirstChanEntry->usSinCopyEventIndex = f_usFirstChanSinCopyEventIndex; ++ pFirstChanEntry->usSoutCopyEventIndex = f_usFirstChanSoutCopyEventIndex; ++ ++ pSecondChanEntry->usExtraSinTsiMemIndex = f_usSecondChanExtraTsiIndex; ++ pSecondChanEntry->usSinCopyEventIndex = f_usSecondChanSinCopyEventIndex; ++ pSecondChanEntry->usSoutCopyEventIndex = f_usSecondChanSoutCopyEventIndex; ++ ++ /* Save the channel info in the bidir channel.*/ ++ pBiDirChanEntry->usFirstChanIndex = f_usFirstChanIndex; ++ pBiDirChanEntry->usSecondChanIndex = f_usSecondChanIndex; ++ ++ ++ ++ /* Increment the extra TSI memory dependency count.*/ ++ ++ pFirstChanEntry->usExtraSinTsiDependencyCnt++; ++ pSecondChanEntry->usExtraSinTsiDependencyCnt++; ++ ++ /* Set the bidir flag in the channel structure.*/ ++ pFirstChanEntry->fBiDirChannel = TRUE; ++ pSecondChanEntry->fBiDirChannel = TRUE; ++ ++ /*=======================================================================*/ ++ ++ /* Form handle returned to user. */ ++ *f_pChannelCreateBiDir->pulBiDirChannelHndl = cOCT6100_HNDL_TAG_BIDIR_CHANNEL | (pBiDirChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usBiDirChanIndex; ++ ++ /* Finally, mark the channel as open. */ ++ pBiDirChanEntry->fReserved = TRUE; ++ ++ /* Increment the number of channel open.*/ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberBiDirChannels++; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelDestroyBiDirSer ++ ++Description: Closes a bidirectional channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelDestroyBiDir Pointer to a destroy bidirectionnal channel structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelDestroyBiDirSer ++UINT32 Oct6100ChannelDestroyBiDirSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ) ++{ ++ UINT16 usBiDirChanIndex; ++ UINT16 usFirstChanIndex; ++ UINT16 usSecondChanIndex; ++ ++ ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertDestroyBiDirChanParams( f_pApiInstance, ++ f_pChannelDestroyBiDir, ++ &usBiDirChanIndex, ++ ++ &usFirstChanIndex, ++ &usSecondChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the echo cancellation channel. */ ++ ulResult = Oct6100ApiInvalidateBiDirChannelStructs( f_pApiInstance, ++ ++ usFirstChanIndex, ++ usSecondChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the echo cancellation channel. */ ++ ulResult = Oct6100ApiReleaseBiDirChannelResources( f_pApiInstance, ++ usBiDirChanIndex, ++ ++ usFirstChanIndex, ++ usSecondChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Invalidate the handle.*/ ++ f_pChannelDestroyBiDir->ulBiDirChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertDestroyBiDirChanParams ++ ++Description: Validate the handle given by the user and verify the state of ++ the channel about to be closed. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChannelDestroyBiDir Pointer to a destroy bidirectional channel structure. ++f_pusBiDirChanIndex Pointer to the bidir channel entry within the API's list. ++f_pusFirstChanIndex Pointer to the first channel index part of the bidir channel. ++f_pusFirstChanIndex Pointer to the second channel index part of the bidir channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertDestroyBiDirChanParams ++UINT32 Oct6100ApiAssertDestroyBiDirChanParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir, ++ IN OUT PUINT16 f_pusBiDirChanIndex, ++ ++ IN OUT PUINT16 f_pusFirstChanIndex, ++ IN OUT PUINT16 f_pusSecondChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BIDIR_CHANNEL pBiDirChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pChannelDestroyBiDir->ulBiDirChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_BIDIR_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; ++ ++ *f_pusBiDirChanIndex = (UINT16)( f_pChannelDestroyBiDir->ulBiDirChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusBiDirChanIndex >= pSharedInfo->ChipConfig.usMaxBiDirChannels ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the bidir channel's list entry. */ ++ ++ mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, *f_pusBiDirChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelDestroyBiDir->ulBiDirChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pBiDirChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_CHAN_NOT_OPEN; ++ if ( ulEntryOpenCnt != pBiDirChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_BIDIR_CHANNEL_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ /* Return the index of the channel used to create this bidirectional channel.*/ ++ *f_pusFirstChanIndex = pBiDirChanEntry->usFirstChanIndex; ++ *f_pusSecondChanIndex = pBiDirChanEntry->usSecondChanIndex; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidateBiDirChannelStructs ++ ++Description: Destroy the link between the two channels. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidateBiDirChannelStructs ++UINT32 Oct6100ApiInvalidateBiDirChannelStructs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usSecondChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pFirstChanEntry; ++ tPOCT6100_API_CHANNEL pSecondChanEntry; ++ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Get pointers to the API entry of the two channel used to create the bidir channel.*/ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); ++ ++ /* Clear the SIN copy event of the first channel and release the Extra TSI memory if ++ this feature was the only one using it. */ ++ ++ { ++ if ( pFirstChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /*=======================================================================*/ ++ /* Clear the Sin Copy event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pFirstChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Configure the TSST memory.*/ ++ if ( pFirstChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pFirstChanEntry->usSinTsstIndex, ++ pFirstChanEntry->usSinSoutTsiMemIndex, ++ pFirstChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pFirstChanEntry->usSinCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ } ++ } ++ ++ /* Clear the SIN copy event of the first channel and release the Extra TSI memory if ++ this feature was the only one using it. */ ++ if ( pSecondChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /*=======================================================================*/ ++ /* Clear the Sin Copy event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSecondChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Configure the TSST memory.*/ ++ if ( pSecondChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pSecondChanEntry->usSinTsstIndex, ++ pSecondChanEntry->usSinSoutTsiMemIndex, ++ pSecondChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pSecondChanEntry->usSinCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ } ++ ++ /* Now remove the sout copy of the first channel.*/ ++ ++ ++ { ++ /*=======================================================================*/ ++ /* Clear the Sout Copy event of the first channel.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pFirstChanEntry->usSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*=======================================================================*/ ++ ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pFirstChanEntry->usSoutCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ ++ ++ /* Now remove the sout copy of the second channel.*/ ++ ++ /*=======================================================================*/ ++ /* Clear the Sout Copy event of the second channel.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSecondChanEntry->usSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*=======================================================================*/ ++ ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pSecondChanEntry->usSoutCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBiDirChannelResources ++ ++Description: Release and clear the API entry associated to the bidirectional channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usBiDirChanIndex Index of the bidirectionnal channel in the API's bidir channel list. ++f_usFirstChanIndex Index of the first channel used to create the bidir channel. ++f_usSecondChanIndex Index of the second channel used to create the bidir channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBiDirChannelResources ++UINT32 Oct6100ApiReleaseBiDirChannelResources( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBiDirChanIndex, ++ ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usSecondChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BIDIR_CHANNEL pBiDirChanEntry; ++ tPOCT6100_API_CHANNEL pFirstChanEntry; ++ tPOCT6100_API_CHANNEL pSecondChanEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEventEntry; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, f_usBiDirChanIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pFirstChanEntry, f_usFirstChanIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSecondChanEntry, f_usSecondChanIndex ); ++ ++ /* Release the bidir entry.*/ ++ ulResult = Oct6100ApiReleaseBiDirChanEntry( f_pApiInstance, f_usBiDirChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_AC; ++ ++ /* Release the Extra TSI memory and the SIN copy event if required.*/ ++ ++ { ++ if ( pFirstChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /* Release the two TSI chariot memory entries.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pFirstChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A3; ++ ++ /* Relese the SIN copy event.*/ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pFirstChanEntry->usSinCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A4; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pFirstChanEntry->usSinCopyEventIndex ); ++ ++ /* Invalidate the entry.*/ ++ pTempEventEntry->fReserved = FALSE; ++ pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pFirstChanEntry->usExtraSinTsiDependencyCnt--; ++ pFirstChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ pFirstChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ pFirstChanEntry->usExtraSinTsiDependencyCnt--; ++ } ++ } ++ ++ if ( pSecondChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /* Release the two TSI chariot memory entries.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pSecondChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A5; ++ ++ /* Relese the SIN copy event.*/ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pSecondChanEntry->usSinCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A6; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pSecondChanEntry->usSinCopyEventIndex ); ++ /* Invalidate the entry.*/ ++ pTempEventEntry->fReserved = FALSE; ++ pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pSecondChanEntry->usExtraSinTsiDependencyCnt--; ++ pSecondChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ pSecondChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ pSecondChanEntry->usExtraSinTsiDependencyCnt--; ++ } ++ ++ ++ { ++ /* Release the SOUT copy event of the first channel.*/ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pFirstChanEntry->usSoutCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A7; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pFirstChanEntry->usSoutCopyEventIndex ); ++ /* Invalidate the entry.*/ ++ pTempEventEntry->fReserved = FALSE; ++ pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Release the SOUT copy event of the second channel.*/ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pSecondChanEntry->usSoutCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_A8; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, pSecondChanEntry->usSoutCopyEventIndex ); ++ /* Invalidate the entry.*/ ++ pTempEventEntry->fReserved = FALSE; ++ pTempEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ ++ /*=======================================================================*/ ++ /* Update the first channel's list entry. */ ++ ++ /* Mark the channel as closed. */ ++ pFirstChanEntry->usSoutCopyEventIndex = cOCT6100_INVALID_INDEX; ++ pFirstChanEntry->fBiDirChannel = FALSE; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Update the second channel's list entry. */ ++ ++ /* Mark the channel as closed. */ ++ ++ pSecondChanEntry->usSoutCopyEventIndex = cOCT6100_INVALID_INDEX; ++ pSecondChanEntry->fBiDirChannel = FALSE; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Update the bidirectional channel's list entry. */ ++ ++ /* Mark the channel as closed. */ ++ pBiDirChanEntry->fReserved = FALSE; ++ pBiDirChanEntry->byEntryOpenCnt++; ++ ++ pBiDirChanEntry->usFirstChanIndex = cOCT6100_INVALID_INDEX; ++ pBiDirChanEntry->usSecondChanIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Decrement the number of channel open.*/ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberBiDirChannels--; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Check if some of the ports must be muted back. */ ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, ++ f_usFirstChanIndex, ++ pFirstChanEntry->usRinTsstIndex, ++ pFirstChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, ++ f_usSecondChanIndex, ++ pSecondChanEntry->usRinTsstIndex, ++ pSecondChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ApiOctFloatToDbEnergyByte ++INT32 Oct6100ApiOctFloatToDbEnergyByte(UINT8 x) ++{ ++ INT32 lResult; ++ ++ lResult = Oct6100ApiOctFloatToDbEnergyHalf( (UINT16)(x << 8) ); ++ return lResult; ++} ++#endif ++ ++#if !SKIP_Oct6100ApiOctFloatToDbEnergyHalf ++INT32 Oct6100ApiOctFloatToDbEnergyHalf(UINT16 x) ++{ ++ INT32 y; ++ UINT16 m; ++ ++ y = (((x >> 8) & 0x7F) - 0x41) * 3; ++ ++ m = (UINT16)((x & 0x00E0) >> 5); ++ if (m < 2) y += 0; ++ else if (m < 5) y += 1; ++ else y += 2; ++ ++ return y; ++} ++#endif ++ ++#if !SKIP_Oct6100ApiDbAmpHalfToOctFloat ++UINT16 Oct6100ApiDbAmpHalfToOctFloat(INT32 x) ++{ ++ INT32 db_div6; ++ INT32 db_mod6; ++ UINT16 rval; ++ INT32 x_unsigned; ++ ++ if(x < 0) ++ { ++ x_unsigned = -x; ++ } ++ else ++ { ++ x_unsigned = x; ++ } ++ ++ db_div6 = x_unsigned / 6; ++ db_mod6 = x_unsigned % 6; ++ ++ if(x < 0) ++ { ++ if(db_mod6 == 0) ++ { ++ /* Change nothing! */ ++ db_div6 = -db_div6; ++ } ++ else ++ { ++ /* When we are negative, round down, and then adjust modulo. For example, if ++ x is -1, then db_div6 is 0 and db_mod6 is 1. We adjust so db_div6 = -1 and ++ db_mod6 = 5, which gives the correct adjustment. */ ++ db_div6 = -db_div6-1; ++ db_mod6 = 6 - db_mod6; ++ } ++ } ++ ++ rval = (UINT16)(0x4100 + db_div6 * 0x100); ++ ++ if(db_mod6 == 0) ++ { ++ rval += 0x0000; ++ } ++ else if(db_mod6 == 1) ++ { ++ rval += 0x0020; ++ } ++ else if(db_mod6 == 2) ++ { ++ rval += 0x0040; ++ } ++ else if(db_mod6 == 3) ++ { ++ rval += 0x0070; ++ } ++ else if(db_mod6 == 4) ++ { ++ rval += 0x0090; ++ } ++ else /* if(db_mod6 == 5) */ ++ { ++ rval += 0x00D0; ++ } ++ ++ return rval; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteDebugChanMemory ++ ++Description: This function configure a debug channel echo memory entry ++ in internal memory.and external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pTdmConfig Pointer to a TDM configuration structure. ++f_pVqeConfig Pointer to a VQE configuration structure. ++f_pChannelOpen Pointer to a channel configuration structure. ++f_usChanIndex Index of the echo channel in the API instance. ++f_usEchoMemIndex Index of the echo channel within the SSPX memory. ++f_usRinRoutTsiIndex RIN/ROUT TSI index within the TSI chariot memory. ++f_usSinSoutTsiIndex SIN/SOUT TSI index within the TSI chariot memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteDebugChanMemory ++UINT32 Oct6100ApiWriteDebugChanMemory( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN UINT16 f_usRinRoutTsiIndex, ++ IN UINT16 f_usSinSoutTsiIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ ++ /* Obtain pointer to local portion of the instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /*==============================================================================*/ ++ /* Write the VQE configuration of the debug channel. */ ++ ++ ulResult = Oct6100ApiWriteVqeMemory( ++ f_pApiInstance, ++ f_pVqeConfig, ++ f_pChannelOpen, ++ f_usChanIndex, ++ f_usEchoMemIndex, ++ TRUE, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ ++ /*==============================================================================*/ ++ ++ /* Write the echo memory configuration of the debug channel. */ ++ ulResult = Oct6100ApiWriteEchoMemory( ++ f_pApiInstance, ++ f_pTdmConfig, ++ f_pChannelOpen, ++ f_usEchoMemIndex, ++ f_usRinRoutTsiIndex, ++ f_usSinSoutTsiIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiDebugChannelOpen ++ ++Description: Internal function used to open a debug channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiDebugChannelOpen ++UINT32 Oct6100ApiDebugChannelOpen( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_CHANNEL_OPEN TempChanOpen; ++ ++ UINT32 ulResult; ++ UINT16 usChanIndex; ++ UINT16 usDummyEchoIndex; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Let's program the channel memory.*/ ++ Oct6100ChannelOpenDef( &TempChanOpen ); ++ ++ TempChanOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_HT_RESET; /* Activate the channel in reset.*/ ++ TempChanOpen.VqeConfig.fEnableNlp = FALSE; ++ TempChanOpen.VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; ++ TempChanOpen.VqeConfig.fSinDcOffsetRemoval = FALSE; ++ TempChanOpen.VqeConfig.fRinDcOffsetRemoval = FALSE; ++ TempChanOpen.VqeConfig.lDefaultErlDb = 0; ++ ++ /* Loop to reserve the proper entry for the debug channel */ ++ for( usChanIndex = 0; usChanIndex < ( pSharedInfo->DebugInfo.usRecordChanIndex + 1 ); usChanIndex ++ ) ++ { ++ ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, &usDummyEchoIndex ); ++ if( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Loop to free all entries except the one for the debug channel */ ++ for( usChanIndex = pSharedInfo->DebugInfo.usRecordChanIndex; usChanIndex > 0; ) ++ { ++ usChanIndex--; ++ ulResult = Oct6100ApiReleaseEchoEntry( f_pApiInstance, usChanIndex ); ++ if( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, ++ &TempChanOpen.TdmConfig, ++ &TempChanOpen.VqeConfig, ++ &TempChanOpen, ++ pSharedInfo->DebugInfo.usRecordChanIndex, ++ pSharedInfo->DebugInfo.usRecordMemIndex, ++ pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex, ++ pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiMuteChannelPort ++ ++Description: This function will verify if a input TSST is bound to the RIN and ++ SIN port. If not, the port will be muted. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiMutePorts ++UINT32 Oct6100ApiMutePorts( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEchoIndex, ++ IN UINT16 f_usRinTsstIndex, ++ IN UINT16 f_usSinTsstIndex, ++ IN BOOL f_fCheckBridgeIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usEchoIndex ); ++ ++ /* Mute the Rin port. */ ++ if ( ( f_fCheckBridgeIndex == FALSE ) ++ || ( ( f_fCheckBridgeIndex == TRUE ) && ( pChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ) ) ++ { ++ /* If the channel is in bidir mode, do not create the Rin silence event!!! */ ++ if ( pChanEntry->fBiDirChannel == FALSE ) ++ { ++ if ( ( ( f_usRinTsstIndex == cOCT6100_INVALID_INDEX ) || ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ) ++ && ( pChanEntry->usRinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) ++ { ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, ++ &pChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now, write the mixer event used to copy the RIN signal of the silence channel ++ into the RIN signal of the current channel. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usRinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= 1534; ++ WriteParams.usWriteData |= cOCT6100_PCM_U_LAW << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pChanEntry->usRinRoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Now insert the Sin copy event into the list.*/ ++ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ pChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY, ++ f_usEchoIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Mute the Sin port. */ ++ if ( ( ( f_usSinTsstIndex == cOCT6100_INVALID_INDEX ) || ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) ++ && ( pChanEntry->usSinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) ++ { ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, ++ &pChanEntry->usSinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now, write the mixer event used to copy the SIN signal of the silence channel ++ into the SIN signal of the current channel. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= 1534; ++ WriteParams.usWriteData |= cOCT6100_PCM_U_LAW << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Now insert the Sin copy event into the list.*/ ++ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ pChanEntry->usSinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY, ++ f_usEchoIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Unmute the Rin port if it was muted. */ ++ if ( ( ( f_usRinTsstIndex != cOCT6100_INVALID_INDEX ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) == 0x0 ) ) ++ && ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_E1; ++ ++ pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Unmute the Sin port if it was muted. */ ++ if ( ( ( f_usSinTsstIndex != cOCT6100_INVALID_INDEX ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) == 0x0 ) ) ++ && ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pChanEntry->usSinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usSinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_E2; ++ ++ pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiSetChannelLevelControl ++ ++Description: This function will configure the level control on a given ++ channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pVqeConfig VQE config of the channel. ++f_usChanIndex Index of the channel within the API instance. ++f_usEchoMemIndex Index of the echo channel within the SSPX memory. ++f_fClearAlcHlcStatusBit If this is set, the ALC-HLC status bit must be ++ incremented. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiSetChannelLevelControl ++UINT32 Oct6100ApiSetChannelLevelControl( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearAlcHlcStatusBit ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ UINT32 ulBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulMask; ++ UINT32 i; ++ UINT16 usTempData; ++ UINT8 byLastStatus; ++ BOOL fDisableAlcFirst; ++ ++ /* Get local pointer to shared portion of the API instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain a pointer to the channel list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ /* Before doing anything, check if the configuration has changed. */ ++ if ( ( f_fClearAlcHlcStatusBit == TRUE ) ++ || ( f_pVqeConfig->fRinLevelControl != pChanEntry->VqeConfig.fRinLevelControl ) ++ || ( f_pVqeConfig->lRinLevelControlGainDb != pChanEntry->VqeConfig.chRinLevelControlGainDb ) ++ || ( f_pVqeConfig->fRinAutomaticLevelControl != pChanEntry->VqeConfig.fRinAutomaticLevelControl ) ++ || ( f_pVqeConfig->lRinAutomaticLevelControlTargetDb != pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb ) ++ || ( f_pVqeConfig->fRinHighLevelCompensation != pChanEntry->VqeConfig.fRinHighLevelCompensation ) ++ || ( f_pVqeConfig->lRinHighLevelCompensationThresholdDb != pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb ) ++ || ( f_pVqeConfig->fSoutLevelControl != pChanEntry->VqeConfig.fSoutLevelControl ) ++ || ( f_pVqeConfig->lSoutLevelControlGainDb != pChanEntry->VqeConfig.chSoutLevelControlGainDb ) ++ || ( f_pVqeConfig->fSoutAutomaticLevelControl != pChanEntry->VqeConfig.fSoutAutomaticLevelControl ) ++ || ( f_pVqeConfig->lSoutAutomaticLevelControlTargetDb != pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb ) ++ || ( f_pVqeConfig->fSoutNaturalListenerEnhancement != pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement ) ++ || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb ) ++ || ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb ) ) ++ { ++ /* Calculate base address for manual level control configuration. */ ++ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ /* Set the Level control on RIN port.*/ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.RinLevelControlOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( ( f_pVqeConfig->fRinLevelControl == TRUE ) ++ || ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) ++ || ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ) ++ { ++ /* Set the level control value.*/ ++ if ( ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) ++ || ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ) ++ ulTempData |= ( 0xFF << ulFeatureBitOffset ); ++ else ++ { ++ /* Convert the dB value into OctFloat format.*/ ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pVqeConfig->lRinLevelControlGainDb ); ++ usTempData -= 0x3800; ++ usTempData &= 0x0FF0; ++ usTempData >>= 4; ++ ++ ulTempData |= ( usTempData << ulFeatureBitOffset ); ++ } ++ } ++ else /* ( ( f_pVqeConfig->fRinLevelControl == FALSE ) && ( f_pVqeConfig->fRinAutomaticLevelControl == FALSE ) && ( f_pVqeConfig->fRinHighLevelCompensation == FALSE ) ) */ ++ { ++ ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset ); ++ } ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the Level control on SOUT port.*/ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutLevelControlOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutLevelControlOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutLevelControlOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( ( f_pVqeConfig->fSoutLevelControl == TRUE ) ++ || ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) ++ || ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) ++ || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0x0 ) ) ++ { ++ /* Set the level control value.*/ ++ if ( ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) ++ || ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) ++ || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0x0 ) ) ++ ulTempData |= ( 0xFF << ulFeatureBitOffset ); ++ else ++ { ++ /* Convert the dB value into OctFloat format.*/ ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pVqeConfig->lSoutLevelControlGainDb ); ++ usTempData -= 0x3800; ++ usTempData &= 0x0FF0; ++ usTempData >>= 4; ++ ++ ulTempData |= ( usTempData << ulFeatureBitOffset ); ++ } ++ } ++ else ++ { ++ ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset ); ++ } ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Calculate base address for auto level control + high level compensation configuration. */ ++ ulBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; ++ ++ /* Check which one is to be disabled first. */ ++ if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) ++ fDisableAlcFirst = FALSE; ++ else ++ fDisableAlcFirst = TRUE; ++ ++ for ( i = 0; i < 2; i ++ ) ++ { ++ /* Set the auto level control target Db for the Rin port. */ ++ if ( ( ( i == 0 ) && ( fDisableAlcFirst == TRUE ) ) || ( ( i == 1 ) && ( fDisableAlcFirst == FALSE ) ) ) ++ { ++ if ( pSharedInfo->ImageInfo.fRinAutoLevelControl == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) ++ { ++ /* Convert the dB value into OctFloat format.*/ ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lRinAutomaticLevelControlTargetDb ); ++ ++ /* Set auto level control target on the Rin port. */ ++ ulTempData |= ( usTempData << ulFeatureBitOffset ); ++ } ++ else /* if ( f_pVqeConfig->fRinAutomaticLevelControl == FALSE ) */ ++ { ++ /* Disable auto level control. */ ++ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); ++ } ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else ++ { ++ /* Set the high level compensation threshold Db for the Rin port. */ ++ if ( pSharedInfo->ImageInfo.fRinHighLevelCompensation == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ++ { ++ /* Convert the dB value into OctFloat format.*/ ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lRinHighLevelCompensationThresholdDb ); ++ ++ /* Set high level compensation threshold on the Rin port. */ ++ ulTempData |= ( usTempData << ulFeatureBitOffset ); ++ } ++ else /* if ( f_pVqeConfig->fRinHighLevelCompensation == FALSE ) */ ++ { ++ /* Disable high level compensation. */ ++ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); ++ } ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Set the auto level control target Db for the Sout port. */ ++ if ( pSharedInfo->ImageInfo.fRinAutoLevelControl == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) ++ { ++ /* Convert the dB value into OctFloat format.*/ ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lSoutAutomaticLevelControlTargetDb ); ++ ++ /* Set auto level control target on the Sout port. */ ++ ulTempData |= ( usTempData << ulFeatureBitOffset ); ++ } ++ else /* if ( f_pVqeConfig->fSoutAutomaticLevelControl == FALSE ) */ ++ { ++ /* Disable auto level control. */ ++ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); ++ } ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Set the high level compensation threshold Db for the Sout port. */ ++ if ( pSharedInfo->ImageInfo.fSoutHighLevelCompensation == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Disable high level compensation on Sout for now. */ ++ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Check if have to clear the ALC-HLC status. */ ++ if ( ( pSharedInfo->ImageInfo.fAlcHlcStatus == TRUE ) ++ && ( ( f_fClearAlcHlcStatusBit == TRUE ) ++ ++ ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AlcHlcStatusOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AlcHlcStatusOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AlcHlcStatusOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Get previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ /* Retrieve last status. */ ++ byLastStatus = (UINT8)( ( ( ulTempData & ulMask ) >> ulFeatureBitOffset ) & 0xFF ); ++ ++ /* Increment to reset context. */ ++ byLastStatus ++; ++ ++ /* Just in case, not to overwrite some context in external memory. */ ++ byLastStatus &= ( 0x1 << ulFeatureFieldLength ) - 1; ++ ++ /* Clear last status. */ ++ ulTempData &= (~ulMask); ++ ++ /* Set new status. */ ++ ulTempData |= ( byLastStatus << ulFeatureBitOffset ); ++ ++ /* Save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiSetChannelTailConfiguration ++ ++Description: This function will configure the tail displacement and length ++ on a given channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pVqeConfig VQE config of the channel. ++f_usChanIndex Index of the channel within the API instance. ++f_usEchoMemIndex Index of the echo channel within the SSPX memory. ++f_fModifyOnly Function called from a modify or open? ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiSetChannelTailConfiguration ++UINT32 Oct6100ApiSetChannelTailConfiguration( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fModifyOnly ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ UINT32 ulNlpConfBaseAddress; ++ UINT32 ulAfConfBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulMask; ++ UINT32 ulTailSum; ++ BOOL fTailDisplacementModified = FALSE; ++ ++ /* Get local pointer to shared portion of the API instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain a pointer to the channel list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); ++ ++ /* Calculate base addresses of NLP + AF configuration structure for the specified channel. */ ++ ulNlpConfBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ulAfConfBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainIoMemOfst; ++ ++ /* Set the tail displacement.*/ ++ if ( pSharedInfo->ImageInfo.fTailDisplacement == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->fEnableTailDisplacement != pChanEntry->VqeConfig.fEnableTailDisplacement ) ++ || ( f_pVqeConfig->ulTailDisplacement != pChanEntry->VqeConfig.usTailDisplacement ) ++ || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) ++ { ++ /* Remember that the tail displacement parameters were changed. */ ++ fTailDisplacementModified = TRUE; ++ ++ /* Check if we must set the tail displacement value. */ ++ if ( ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) ++ && ( pSharedInfo->ImageInfo.fPerChannelTailDisplacement == TRUE ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ if ( ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) ++ && ( f_pVqeConfig->ulTailDisplacement != 0x0 ) ) ++ { ++ if ( pSharedInfo->ImageInfo.fAfTailDisplacement == FALSE ) ++ { ++ if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTempData |= ( ( ( pSharedInfo->ChipConfig.usTailDisplacement / 16 ) ) << ulFeatureBitOffset ); ++ } ++ else ++ { ++ ulTempData |= ( ( ( f_pVqeConfig->ulTailDisplacement / 16 ) ) << ulFeatureBitOffset ); ++ } ++ } ++ else /* if ( pSharedInfo->ImageInfo.fAfTailDisplacement == TRUE ) */ ++ { ++ /* If AEC is not activated, this must be set to the requested tail displacement. */ ++ if ( f_pVqeConfig->fAcousticEcho == FALSE ) ++ { ++ if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTailSum = pSharedInfo->ChipConfig.usTailDisplacement; ++ } ++ else ++ { ++ ulTailSum = f_pVqeConfig->ulTailDisplacement; ++ } ++ ++ if ( ulTailSum == 0 ) ++ { ++ ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); ++ } ++ else if ( ulTailSum <= 128 ) ++ { ++ ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); ++ } ++ else if ( ulTailSum <= 384 ) ++ { ++ ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); ++ } ++ else /* if ( ulTailSum <= 896 ) */ ++ { ++ ulTempData |= ( ( 7 ) << ulFeatureBitOffset ); ++ } ++ } ++ else /* if ( f_pVqeConfig->fAcousticEcho == FALSE ) */ ++ { ++ /* Otherwise, the tail displacement is configured differently. This field stays to 0. */ ++ ulTempData |= ( 0x0 << ulFeatureBitOffset ); ++ } ++ } ++ } ++ ++ /* Then save the new DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pSharedInfo->ImageInfo.fAfTailDisplacement == TRUE ) ++ { ++ /* Set the tail displacement offset in the AF. */ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTempData |= ( ( ( pSharedInfo->ChipConfig.usTailDisplacement / 16 ) ) << ulFeatureBitOffset ); ++ } ++ else ++ { ++ ulTempData |= ( ( ( f_pVqeConfig->ulTailDisplacement / 16 ) ) << ulFeatureBitOffset ); ++ } ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.TailDisplEnableOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.TailDisplEnableOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.TailDisplEnableOfst.byFieldSize; ++ ++ /* First read the DWORD where the field is located.*/ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ulTempData |= ( ( (UINT32)f_pVqeConfig->fEnableTailDisplacement ) << ulFeatureBitOffset ); ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the tail length. */ ++ if ( pSharedInfo->ImageInfo.fPerChannelTailLength == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( f_pVqeConfig->ulTailLength != pChanEntry->VqeConfig.usTailLength ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ /* Check if must automatically select maximum or if must use user specific value. */ ++ if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTempData |= ( ( ( pSharedInfo->ImageInfo.usMaxTailLength - 32 ) / 4 ) << ulFeatureBitOffset ); ++ } ++ else ++ { ++ ulTempData |= ( ( ( f_pVqeConfig->ulTailLength - 32 ) / 4 ) << ulFeatureBitOffset ); ++ } ++ ++ /* Then save the DWORD where the field is located.*/ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulAfConfBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Configure AEC tail length. */ ++ if ( pSharedInfo->ImageInfo.fAecTailLength == TRUE ) ++ { ++ /* Check if the configuration has been changed. */ ++ if ( ( f_fModifyOnly == FALSE ) ++ || ( fTailDisplacementModified == TRUE ) ++ || ( ( f_fModifyOnly == TRUE ) ++ && ( ( f_pVqeConfig->ulAecTailLength != pChanEntry->VqeConfig.usAecTailLength ) ++ || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set acoustic echo tail length. */ ++ if ( f_pVqeConfig->fAcousticEcho == TRUE ) ++ { ++ switch( f_pVqeConfig->ulAecTailLength ) ++ { ++ case 1024: ++ ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); ++ break; ++ case 512: ++ ulTempData |= ( ( 2 ) << ulFeatureBitOffset ); ++ break; ++ case 256: ++ ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); ++ break; ++ case 128: ++ default: ++ ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); ++ break; ++ } ++ } ++ else if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) ++ { ++ /* No acoustic echo case. */ ++ ++ /* Start with requested tail displacement. */ ++ if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTailSum = pSharedInfo->ChipConfig.usTailDisplacement; ++ } ++ else ++ { ++ ulTailSum = f_pVqeConfig->ulTailDisplacement; ++ } ++ ++ /* Add requested tail length. */ ++ if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) ++ { ++ ulTailSum += pSharedInfo->ImageInfo.usMaxTailLength; ++ } ++ else ++ { ++ ulTailSum += f_pVqeConfig->ulTailLength; ++ } ++ ++ /* Round this value up. */ ++ if ( ulTailSum <= 128 ) ++ { ++ ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); ++ } ++ else if ( ulTailSum <= 256 ) ++ { ++ ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); ++ } ++ else if ( ulTailSum <= 512 ) ++ { ++ ulTempData |= ( ( 2 ) << ulFeatureBitOffset ); ++ } ++ else /* if ( ulTailSum <= 1024 ) */ ++ { ++ ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); ++ } ++ } ++ else ++ { ++ /* Keep this to zero. */ ++ ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); ++ } ++ ++ /* Write the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulNlpConfBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelMuteSer ++ ++Description: This function will mute some of the ports on a given ++ channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelMute What channel/ports to mute. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelMuteSer ++UINT32 Oct6100ChannelMuteSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MUTE f_pChannelMute ) ++{ ++ UINT32 ulResult; ++ UINT16 usChanIndex; ++ UINT16 usPortMask; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertChannelMuteParams( f_pApiInstance, ++ f_pChannelMute, ++ &usChanIndex, ++ &usPortMask ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Call the actual channel mute ports function. */ ++ ulResult = Oct6100ApiMuteChannelPorts( f_pApiInstance, ++ usChanIndex, ++ usPortMask, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertChannelMuteParams ++ ++Description: Check the user parameters passed to the channel mute function. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelMute What channel/ports to mute. ++f_pusChanIndex Resulting channel index where the muting should ++ be applied. ++f_pusPorts Port mask on which to apply the muting. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertChannelMuteParams ++UINT32 Oct6100ApiAssertChannelMuteParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MUTE f_pChannelMute, ++ OUT PUINT16 f_pusChanIndex, ++ OUT PUINT16 f_pusPorts ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pChannelMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ *f_pusChanIndex = (UINT16)( f_pChannelMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ if ( pChanEntry->fBiDirChannel == TRUE ) ++ return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; ++ ++ /*=======================================================================*/ ++ ++ /* Check the provided port mask. */ ++ ++ if ( ( f_pChannelMute->ulPortMask & ++ ~( cOCT6100_CHANNEL_MUTE_PORT_NONE | ++ cOCT6100_CHANNEL_MUTE_PORT_RIN | ++ cOCT6100_CHANNEL_MUTE_PORT_ROUT | ++ cOCT6100_CHANNEL_MUTE_PORT_SIN | ++ cOCT6100_CHANNEL_MUTE_PORT_SOUT | ++ cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) ) != 0 ) ++ return cOCT6100_ERR_CHANNEL_MUTE_MASK; ++ ++ /* Sin + Sin with features cannot be muted simultaneously. */ ++ if ( ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ++ && ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) ++ return cOCT6100_ERR_CHANNEL_MUTE_MASK_SIN; ++ ++ /* Check if Sin mute with features is supported by the firmware. */ ++ if ( ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ++ && ( pSharedInfo->ImageInfo.fSinMute == FALSE ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_MUTE_FEATURES; ++ ++ /* Return the ports to the calling function. */ ++ *f_pusPorts = (UINT16)( f_pChannelMute->ulPortMask & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChannelUnMuteSer ++ ++Description: This function will unmute some of the ports on a given ++ channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelUnMute What channel/ports to unmute. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChannelUnMuteSer ++UINT32 Oct6100ChannelUnMuteSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) ++{ ++ UINT32 ulResult; ++ UINT16 usChanIndex; ++ UINT16 usPortMask; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertChannelUnMuteParams( f_pApiInstance, ++ f_pChannelUnMute, ++ &usChanIndex, ++ &usPortMask ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Call the actual channel mute ports function. */ ++ ulResult = Oct6100ApiMuteChannelPorts( f_pApiInstance, ++ usChanIndex, ++ usPortMask, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertChannelUnMuteParams ++ ++Description: Check the user parameters passed to the channel unmute function. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pChannelUnMute What channel/ports to Unmute. ++f_pusChanIndex Resulting channel index where the muting should ++ be applied. ++f_pusPorts Port mask on which to apply the muting. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertChannelUnMuteParams ++UINT32 Oct6100ApiAssertChannelUnMuteParams( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute, ++ OUT PUINT16 f_pusChanIndex, ++ OUT PUINT16 f_pusPorts ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pChannelUnMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ *f_pusChanIndex = (UINT16)( f_pChannelUnMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pChannelUnMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ if ( pChanEntry->fBiDirChannel == TRUE ) ++ return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; ++ ++ /*=======================================================================*/ ++ ++ /* Check the provided port mask. */ ++ ++ if ( ( f_pChannelUnMute->ulPortMask & ++ ~( cOCT6100_CHANNEL_MUTE_PORT_NONE | ++ cOCT6100_CHANNEL_MUTE_PORT_RIN | ++ cOCT6100_CHANNEL_MUTE_PORT_ROUT | ++ cOCT6100_CHANNEL_MUTE_PORT_SIN | ++ cOCT6100_CHANNEL_MUTE_PORT_SOUT | ++ cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) ) != 0 ) ++ return cOCT6100_ERR_CHANNEL_MUTE_MASK; ++ ++ /* Return the ports to the calling function. */ ++ *f_pusPorts = (UINT16)( f_pChannelUnMute->ulPortMask & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiMuteSinWithFeatures ++ ++Description: Mute or Unmute the sin with features port. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usChanIndex Resulting channel index where the muting should ++ be applied. ++f_fEnableSinWithFeatures Whether to enable the feature or not. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiMuteSinWithFeatures ++UINT32 Oct6100ApiMuteSinWithFeatures( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN BOOL f_fEnableSinWithFeatures ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ UINT32 ulTempData; ++ UINT32 ulBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulMask; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ if ( pSharedInfo->ImageInfo.fSinMute == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.SinMuteOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.SinMuteOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.SinMuteOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ /* Clear the mute flag. */ ++ ulTempData &= (~ulMask); ++ ++ /* Set the mute flag on the Sin port.*/ ++ if ( f_fEnableSinWithFeatures == TRUE ) ++ ulTempData |= ( 0x1 << ulFeatureBitOffset ); ++ ++ /* Write the new DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiMuteChannelPorts ++ ++Description: Mute or Unmute the specified ports, according to the mask. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usChanIndex Resulting channel index where the muting should ++ be applied. ++f_usPortMask Port mask on which to apply the muting/unmuting. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiMuteChannelPorts ++UINT32 Oct6100ApiMuteChannelPorts( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usPortMask, ++ IN BOOL f_fMute ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ BOOL fDisableSinWithFeatures = FALSE; ++ BOOL fEnableSinWithFeatures = FALSE; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ /* Rin port. */ ++ if ( ( f_fMute == TRUE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) == 0x0 ) ) ++ { ++ /* Mute this port. */ ++ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_RIN; ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_RIN; ++ return ulResult; ++ } ++ } ++ else if ( ( f_fMute == FALSE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ) ++ { ++ /* Unmute this port. */ ++ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_RIN; ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Rout port. */ ++ if ( ( f_fMute == TRUE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) ) ++ { ++ /* Mute this port. */ ++ ++ if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usRoutTsstIndex, ++ pChanEntry->CodecConfig.byAdpcmNibblePosition, ++ pChanEntry->TdmConfig.byRoutNumTssts, ++ 1534 ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_ROUT; ++ } ++ else if ( ( f_fMute == FALSE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) ) ++ { ++ /* Unmute this port. */ ++ ++ if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usRoutTsstIndex, ++ pChanEntry->CodecConfig.byAdpcmNibblePosition, ++ pChanEntry->TdmConfig.byRoutNumTssts, ++ pChanEntry->usRinRoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_ROUT; ++ } ++ ++ /* Sin port. */ ++ if ( ( f_fMute == TRUE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) == 0x0 ) ) ++ { ++ /* Mute this port. */ ++ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SIN; ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN; ++ return ulResult; ++ } ++ } ++ else if ( ++ ( ( f_fMute == FALSE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) ++ || ++ ( ( f_fMute == TRUE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) ) ++ { ++ /* Unmute this port. */ ++ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN; ++ ++ ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Sout port. */ ++ if ( ( f_fMute == TRUE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) ) ++ { ++ /* Mute this port. */ ++ ++ if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usSoutTsstIndex, ++ pChanEntry->CodecConfig.byAdpcmNibblePosition, ++ pChanEntry->TdmConfig.bySoutNumTssts, ++ 1534 ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SOUT; ++ } ++ else if ( ( f_fMute == FALSE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) ) ++ { ++ /* Unmute this port. */ ++ ++ if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usSoutTsstIndex, ++ pChanEntry->CodecConfig.byAdpcmNibblePosition, ++ pChanEntry->TdmConfig.bySoutNumTssts, ++ pChanEntry->usSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SOUT; ++ } ++ ++ /* Sin with features port. */ ++ if ( ( f_fMute == TRUE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) == 0x0 ) ) ++ { ++ /* Mute this port. */ ++ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES; ++ fEnableSinWithFeatures = TRUE; ++ } ++ else if ( ++ ( ( f_fMute == FALSE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) ++ || ++ ( ( f_fMute == TRUE ) ++ && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ++ && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) ) ++ { ++ /* Unmute this port. */ ++ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES; ++ ++ fDisableSinWithFeatures = TRUE; ++ } ++ ++ /* Check if must enable or disable SIN mute with features. */ ++ if ( fDisableSinWithFeatures == TRUE || fEnableSinWithFeatures == TRUE ) ++ { ++ ulResult = Oct6100ApiMuteSinWithFeatures( f_pApiInstance, f_usChanIndex, fEnableSinWithFeatures ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,6917 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_open.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the functions used to power-up the chip according to the ++ user's configuration. Also, the API instance is initialized to reflect the ++ desired configuration. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 347 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#if defined(__FreeBSD__) ++#include ++#include ++#else ++#ifndef __KERNEL__ ++#include ++#define kmalloc(size, type) malloc(size) ++#define kfree(ptr) free(ptr) ++#define GFP_ATOMIC 0 /*Dummy */ ++#else ++#include ++#include ++#endif ++#endif ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++ ++#include "apilib/octapi_bt0.h" ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_tsi_cnct_inst.h" ++#include "oct6100api/oct6100_events_inst.h" ++#include "oct6100api/oct6100_conf_bridge_inst.h" ++#include "oct6100api/oct6100_playout_buf_inst.h" ++ ++#include "oct6100api/oct6100_mixer_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_adpcm_chan_inst.h" ++#include "oct6100api/oct6100_phasing_tsst_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++ ++#include "oct6100api/oct6100_chip_stats_pub.h" ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_tsi_cnct_pub.h" ++#include "oct6100api/oct6100_events_pub.h" ++#include "oct6100api/oct6100_conf_bridge_pub.h" ++#include "oct6100api/oct6100_playout_buf_pub.h" ++ ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_adpcm_chan_pub.h" ++#include "oct6100api/oct6100_phasing_tsst_pub.h" ++#include "oct6100api/oct6100_remote_debug_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_mixer_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_debug_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_interrupts_priv.h" ++#include "oct6100_chip_stats_priv.h" ++#include "octrpc/rpc_protocol.h" ++#include "oct6100_remote_debug_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_tsst_priv.h" ++#include "oct6100_tsi_cnct_priv.h" ++#include "oct6100_mixer_priv.h" ++#include "oct6100_events_priv.h" ++#include "oct6100_conf_bridge_priv.h" ++#include "oct6100_playout_buf_priv.h" ++ ++#include "oct6100_channel_priv.h" ++#include "oct6100_adpcm_chan_priv.h" ++#include "oct6100_phasing_tsst_priv.h" ++#include "oct6100_tlv_priv.h" ++#include "oct6100_debug_priv.h" ++#include "oct6100_version.h" ++ ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100GetInstanceSizeDef ++ ++Description: Retrieves the size of the required API instance structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pGetSize Structure containing API instance size. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100GetInstanceSizeDef ++UINT32 Oct6100GetInstanceSizeDef( ++ tPOCT6100_GET_INSTANCE_SIZE f_pGetSize ) ++{ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100GetInstanceSize ++UINT32 Oct6100GetInstanceSize( ++ tPOCT6100_CHIP_OPEN f_pChipOpen, ++ tPOCT6100_GET_INSTANCE_SIZE f_pGetSize ) ++{ ++ tOCT6100_API_INSTANCE_SIZES InstanceSizes; ++ UINT32 ulResult; ++ ++ /* Check user configuration for errors and conflicts. */ ++ ulResult = Oct6100ApiCheckChipConfiguration( f_pChipOpen ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Calculate the instance size required for user's configuration. */ ++ ulResult = Oct6100ApiCalculateInstanceSizes( f_pChipOpen, &InstanceSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Return required size to user. */ ++ f_pGetSize->ulApiInstanceSize = InstanceSizes.ulApiInstTotal; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChipOpenDef ++ ++Description: Inserts default chip configuration parameters into the ++ structure pointed to by f_pChipOpen. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pChipOpen Structure containing user chip configuration. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChipOpenDef ++UINT32 Oct6100ChipOpenDef( ++ tPOCT6100_CHIP_OPEN f_pChipOpen ) ++{ ++ UINT32 i; ++ ++ f_pChipOpen->ulUserChipId = 0; ++ f_pChipOpen->fMultiProcessSystem = FALSE; ++ f_pChipOpen->pProcessContext = NULL; ++ ++ f_pChipOpen->ulMaxRwAccesses = 8; ++ ++ f_pChipOpen->pbyImageFile = NULL; ++ f_pChipOpen->ulImageSize = 0; ++ ++ f_pChipOpen->ulMemClkFreq = 133000000; /* 133 Mhz */ ++ f_pChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; /* 33.33 Mhz */ ++ f_pChipOpen->fEnableMemClkOut = TRUE; ++ ++ f_pChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; ++ f_pChipOpen->ulNumMemoryChips = 1; ++ f_pChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_64MB; ++ ++ /* Set the tail displacement to zero. */ ++ f_pChipOpen->ulTailDisplacement = 0; ++ ++ /* Disable acoustic echo by default. */ ++ f_pChipOpen->fEnableAcousticEcho = FALSE; ++ ++ /* Resource allocation parameters. */ ++ f_pChipOpen->ulMaxChannels = 256; ++ f_pChipOpen->ulMaxTsiCncts = 0; ++ f_pChipOpen->ulMaxBiDirChannels = 0; ++ f_pChipOpen->ulMaxConfBridges = 0; ++ f_pChipOpen->ulMaxFlexibleConfParticipants = 0; ++ f_pChipOpen->ulMaxPlayoutBuffers = 0; ++ ++ f_pChipOpen->ulMaxPhasingTssts = 0; ++ f_pChipOpen->ulMaxAdpcmChannels = 0; ++ f_pChipOpen->ulMaxTdmStreams = 32; ++ f_pChipOpen->fUseSynchTimestamp = FALSE; ++ for ( i = 0; i < 4; i++ ) ++ { ++ f_pChipOpen->aulTimestampTimeslots[ i ] = cOCT6100_INVALID_TIMESLOT; ++ f_pChipOpen->aulTimestampStreams[ i ] = cOCT6100_INVALID_STREAM; ++ } ++ f_pChipOpen->fEnableFastH100Mode = FALSE; ++ ++ /* Configure the soft tone event buffer. */ ++ f_pChipOpen->ulSoftToneEventsBufSize = 128; ++ f_pChipOpen->fEnableExtToneDetection = FALSE; ++ f_pChipOpen->fEnable2100StopEvent = FALSE; ++ ++ /* Configure the soft playout event buffer. */ ++ f_pChipOpen->ulSoftBufferPlayoutEventsBufSize = cOCT6100_INVALID_VALUE; ++ ++ /* Interrupt configuration. */ ++ f_pChipOpen->ulInterruptPolarity = cOCT6100_ACTIVE_LOW_POLARITY; ++ ++ f_pChipOpen->InterruptConfig.ulErrorMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pChipOpen->InterruptConfig.ulFatalGeneralConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pChipOpen->InterruptConfig.ulFatalMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pChipOpen->InterruptConfig.ulFatalMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pChipOpen->InterruptConfig.ulErrorH100Config = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ ++ f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout = 100; ++ f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout = 100; ++ f_pChipOpen->InterruptConfig.ulErrorH100Timeout = 100; ++ f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout = 100; ++ f_pChipOpen->ulMaxRemoteDebugSessions = 0; ++ f_pChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_3_QUARTERS; ++ for ( i = 0; i < cOCT6100_TDM_STREAM_MAX_GROUPS; i++ ) ++ f_pChipOpen->aulTdmStreamFreqs[ i ] = cOCT6100_TDM_STREAM_FREQ_8MHZ; ++ ++ ++ ++ f_pChipOpen->fEnableChannelRecording = FALSE; ++ f_pChipOpen->fEnableProductionBist = FALSE; ++ f_pChipOpen->ulProductionBistMode = cOCT6100_PRODUCTION_BIST_STANDARD; ++ f_pChipOpen->ulNumProductionBistLoops = 1; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChipOpen ++ ++Description: Configures the chip according to the user specified ++ configuration f_pChipOpen. This function will perform all I/O ++ accesses necessary and initialize the API instance to reflect ++ the configuration. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChipOpen Structure containing user chip configuration. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChipOpen ++UINT32 Oct6100ChipOpen( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CHIP_OPEN f_pChipOpen ) ++{ ++ tOCT6100_API_INSTANCE_SIZES *InstanceSizes; ++ UINT32 ulStructSize; ++ UINT32 ulResult; ++ UINT32 ulTempVar; ++ ++ /* Check user chip configuration parameters for errors. */ ++ ulResult = Oct6100ApiCheckChipConfiguration( f_pChipOpen ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the host system is multi-process or not and adjust instance accordingly. */ ++ if ( f_pChipOpen->fMultiProcessSystem != TRUE ) ++ { ++ /* Set pointer to tOCT6100_SHARED_INFO structure within instance. */ ++ ulStructSize = sizeof( tOCT6100_INSTANCE_API ); ++ mOCT6100_ROUND_MEMORY_SIZE( ulStructSize, ulTempVar ) ++ ++ f_pApiInstance->pSharedInfo = ( tPOCT6100_SHARED_INFO )(( PUINT8 )f_pApiInstance + ulStructSize); ++ ++ /* Save the process context specified by the user. */ ++ f_pApiInstance->pProcessContext = f_pChipOpen->pProcessContext; ++ ++ /* Create serialization object handles. */ ++ ulResult = Oct6100ApiCreateSerializeObjects( f_pApiInstance, f_pChipOpen->ulUserChipId ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Copy the configuration structure. */ ++ ulResult = Oct6100ApiCopyChipConfiguration( f_pApiInstance, f_pChipOpen ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Perform various calculations based on user chip configuration. */ ++ ulResult = Oct6100ApiInitializeMiscellaneousVariables( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ InstanceSizes = kmalloc(sizeof(tOCT6100_API_INSTANCE_SIZES), GFP_ATOMIC); ++ if (!InstanceSizes) ++ return cOCT6100_ERR_FATAL_0; ++ ++ /* Calculate the amount of memory needed for the API instance structure. */ ++ ulResult = Oct6100ApiCalculateInstanceSizes( f_pChipOpen, InstanceSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) { ++ kfree(InstanceSizes); ++ return ulResult; ++ } ++ ++ /* Allocate the memory for the API instance structure internal pointers. */ ++ ulResult = Oct6100ApiAllocateInstanceMemory( f_pApiInstance, InstanceSizes ); ++ kfree(InstanceSizes); ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Initialize the allocated instance structure memory. */ ++ ulResult = Oct6100ApiInitializeInstanceMemory( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Initialize the tone information structure. */ ++ ulResult = Oct6100ApiInitToneInfo( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Test the CPU registers. */ ++ ulResult = Oct6100ApiCpuRegisterBist( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Boot the FC2 PLL. */ ++ ulResult = Oct6100ApiBootFc2Pll( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Program the FC1 PLL. */ ++ ulResult = Oct6100ApiProgramFc1Pll( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Decode the key and bist internal memories. */ ++ ulResult = Oct6100ApiDecodeKeyAndBist( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Boot the FC1 PLL. */ ++ ulResult = Oct6100ApiBootFc1Pll( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Boot the SDRAM. */ ++ ulResult = Oct6100ApiBootSdram( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Bist the external memory. */ ++ ulResult = Oct6100ApiExternalMemoryBist( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Initialize the external memory. */ ++ ulResult = Oct6100ApiExternalMemoryInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Load the image into the chip. */ ++ ulResult = Oct6100ApiLoadImage( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write the clock distribution registers. */ ++ ulResult = Oct6100ApiEnableClocks( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Program the NLP processor. */ ++ ulResult = Oct6100ApiProgramNLP( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_OPEN_EGO_TIMEOUT ) ++ ulResult = Oct6100ApiProgramNLP( f_pApiInstance ); ++ } ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( f_pChipOpen->fEnableProductionBist == FALSE ) ++ { ++ /* Read all TLV fields present in external memory. */ ++ ulResult = Oct6100ApiProcessTlvRegion( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Configure the H.100 interface. */ ++ ulResult = Oct6100ApiSetH100Register( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Write miscellaneous registers. */ ++ ulResult = Oct6100ApiWriteMiscellaneousRegisters( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Proceed with the rest only if the production BIST has not been requested. */ ++ if ( f_pChipOpen->fEnableProductionBist == FALSE ) ++ { ++ /* Initialize the errors counters. */ ++ ulResult = Oct6100ApiChipStatsSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Get revision number of chip. */ ++ ulResult = Oct6100ApiGetChipRevisionNum( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ ++ ++ ++ /* Initialize the channels. */ ++ ulResult = Oct6100ApiInitChannels( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Initialize the mixer memory. */ ++ ulResult = Oct6100ApiInitMixer( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Initialize the mixer memory. */ ++ ulResult = Oct6100ApiInitRecordResources( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Initialize free external memory for buffer playout. */ ++ ulResult = Oct6100ApiBufferPlayoutMemorySwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ ++ ++ /*Clear all interrupts that could have occured during startup*/ ++ ulResult = Oct6100ApiClearInterrupts( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Configure the interrupt registers. */ ++ ulResult = Oct6100ApiIsrHwInit( f_pApiInstance, &f_pChipOpen->InterruptConfig ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChipCloseDef ++ ++Description: Puts the chip into soft reset. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChipClose Pointer to a tOCT6100_CHIP_CLOSE structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChipCloseDef ++UINT32 Oct6100ChipCloseDef( ++ tPOCT6100_CHIP_CLOSE f_pChipClose ) ++{ ++ f_pChipClose->ulDummyVariable = 0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ChipClose ++UINT32 Oct6100ChipClose( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CHIP_CLOSE f_pChipClose ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ WriteParams.ulWriteAddress = 0x100; ++ WriteParams.usWriteData = 0x0000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Destroy the allocated ressources used for serialization. */ ++ ulResult = Oct6100ApiDestroySerializeObjects( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100CreateLocalInstance ++ ++Description: Creates a local instance for a process in a multi-process ++ host system. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pCreateLocal Structure used to create process' local instance. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100CreateLocalInstanceDef ++UINT32 Oct6100CreateLocalInstanceDef( ++ tPOCT6100_CREATE_LOCAL_INSTANCE f_pCreateLocal ) ++{ ++ f_pCreateLocal->pApiInstShared = NULL; ++ f_pCreateLocal->pApiInstLocal = NULL; ++ f_pCreateLocal->pProcessContext = NULL; ++ f_pCreateLocal->ulUserChipId = 0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100CreateLocalInstance ++UINT32 Oct6100CreateLocalInstance( ++ tPOCT6100_CREATE_LOCAL_INSTANCE f_pCreateLocal ) ++{ ++ tPOCT6100_INSTANCE_API pApiInstLocal; ++ UINT32 ulApiInstSize; ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Check user's structure for errors. */ ++ if ( f_pCreateLocal->pApiInstShared == NULL ) ++ return cOCT6100_ERR_MULTIPROC_API_INST_SHARED; ++ ++ if ( f_pCreateLocal->pApiInstLocal == NULL ) ++ return cOCT6100_ERR_MULTIPROC_API_INST_LOCAL; ++ ++ /* Get local pointer to local instance. */ ++ pApiInstLocal = f_pCreateLocal->pApiInstLocal; ++ ++ /* Assign pointers to local structure. */ ++ ulApiInstSize = sizeof( tOCT6100_INSTANCE_API ); ++ mOCT6100_ROUND_MEMORY_SIZE( ulApiInstSize, ulTempVar ) ++ ++ pApiInstLocal->pSharedInfo = ( tPOCT6100_SHARED_INFO )(( PUINT8 )f_pCreateLocal->pApiInstShared + ulApiInstSize); ++ pApiInstLocal->pProcessContext = f_pCreateLocal->pProcessContext; ++ ++ /* Create serialization object handles needed. */ ++ ulResult = Oct6100ApiCreateSerializeObjects( pApiInstLocal, f_pCreateLocal->ulUserChipId ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100DestroyLocalInstance ++ ++Description: Release local instance for a process in a multi-process ++ host system. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pDestroyLocal Structure used to destroy the process' local instance. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100DestroyLocalInstanceDef ++UINT32 Oct6100DestroyLocalInstanceDef( ++ tPOCT6100_DESTROY_LOCAL_INSTANCE f_pDestroyLocal ) ++{ ++ f_pDestroyLocal->ulDummy = 0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100DestroyLocalInstance ++UINT32 Oct6100DestroyLocalInstance( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_DESTROY_LOCAL_INSTANCE f_pDestroyLocal ) ++{ ++ UINT32 ulResult; ++ ++ /* Destroy the allocated ressources used for serialization. */ ++ ulResult = Oct6100ApiDestroySerializeObjects( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100GetHwRevision ++ ++Description: Gets the hardware revision number of the chip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pGetHwRev Pointer to user structure in which to return revision ++ number. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100GetHwRevisionDef ++UINT32 Oct6100GetHwRevisionDef( ++ tPOCT6100_GET_HW_REVISION f_pGetHwRev ) ++{ ++ f_pGetHwRev->ulUserChipId = cOCT6100_INVALID_CHIP_ID; ++ f_pGetHwRev->pProcessContext = NULL; ++ f_pGetHwRev->ulRevisionNum = cOCT6100_INVALID_VALUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100GetHwRevision ++UINT32 Oct6100GetHwRevision( ++ tPOCT6100_GET_HW_REVISION f_pGetHwRev ) ++{ ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ ++ /* Read the hardware revision register. */ ++ ReadParams.pProcessContext = f_pGetHwRev->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pGetHwRev->ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ReadParams.ulReadAddress = 0x17E; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ f_pGetHwRev->ulRevisionNum = ( usReadData >> 8 ) & 0xFF; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100FreeResources ++ ++Description: This function closes all opened channels and frees all ++ specified global resources used by the chip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pFreeResources Pointer to user structure in which to choose what ++ to free. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100FreeResourcesDef ++UINT32 Oct6100FreeResourcesDef( ++ tPOCT6100_FREE_RESOURCES f_pFreeResources ) ++{ ++ f_pFreeResources->fFreeTsiConnections = FALSE; ++ f_pFreeResources->fFreeConferenceBridges = FALSE; ++ f_pFreeResources->fFreePlayoutBuffers = FALSE; ++ f_pFreeResources->fFreePhasingTssts = FALSE; ++ f_pFreeResources->fFreeAdpcmChannels = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100FreeResources ++UINT32 Oct6100FreeResources( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_FREE_RESOURCES f_pFreeResources ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100FreeResourcesSer( f_pApiInstance, f_pFreeResources ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ProductionBist ++ ++Description: This function retrieves the current BIST status of the ++ firmware. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pProductionBist Pointer to user structure where the bist information ++ will be returned. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ProductionBistDef ++UINT32 Oct6100ProductionBistDef( ++ tPOCT6100_PRODUCTION_BIST f_pProductionBist ) ++{ ++ f_pProductionBist->ulCurrentAddress = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulCurrentLoop = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulFailedAddress = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulReadValue = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulExpectedValue = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulBistStatus = cOCT6100_BIST_IN_PROGRESS; ++ f_pProductionBist->ulCurrentTest = cOCT6100_INVALID_VALUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ProductionBist ++UINT32 Oct6100ProductionBist( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_PRODUCTION_BIST f_pProductionBist ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ProductionBistSer( f_pApiInstance, f_pProductionBist ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetVersion ++ ++Description: Retrieves the API version. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pApiGetVersion Pointer to structure that will receive version information. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetVersionDef ++UINT32 Oct6100ApiGetVersionDef( ++ tPOCT6100_API_GET_VERSION f_pApiGetVersion ) ++{ ++ UINT32 i; ++ ++ /* Initialize the string. */ ++ for ( i = 0; i < cOCT6100_API_VERSION_STRING_LENGTH; i++ ) ++ f_pApiGetVersion->achApiVersion[ i ] = 0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ApiGetVersion ++UINT32 Oct6100ApiGetVersion( ++ tPOCT6100_API_GET_VERSION f_pApiGetVersion ) ++{ ++ /* Copy API version information to user. */ ++ Oct6100UserMemCopy( f_pApiGetVersion->achApiVersion, cOCT6100_API_VERSION, sizeof(cOCT6100_API_VERSION) ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetCapacityPins ++ ++Description: Retrieves the Capcity Pins value. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pGetCapacityPins Pointer to the parameters structure needed ++ by GetCapacityPins(). ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetCapacityPinsDef ++UINT32 Oct6100ApiGetCapacityPinsDef( ++ tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins) ++{ ++ ++ f_pGetCapacityPins->pProcessContext = NULL; ++ f_pGetCapacityPins->ulUserChipId = 0; ++ f_pGetCapacityPins->ulMemoryType = cOCT6100_MEM_TYPE_DDR; ++ f_pGetCapacityPins->ulCapacityValue = cOCT6100_INVALID_VALUE; ++ f_pGetCapacityPins->fEnableMemClkOut = TRUE; ++ f_pGetCapacityPins->ulMemClkFreq = 133000000; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ApiGetCapacityPins ++UINT32 Oct6100ApiGetCapacityPins( ++ tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins ) ++{ ++ ++ UINT32 ulResult; ++ ++ tOCT6100_INSTANCE_API ApiInstance; ++ ++ Oct6100UserMemSet(&ApiInstance,0,sizeof(tOCT6100_INSTANCE_API)); ++ ++ /*Check parameters*/ ++ if ( f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_133_MHZ && ++ f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_125_MHZ && ++ f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_117_MHZ && ++ f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_108_MHZ && ++ f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_100_MHZ && ++ f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_92_MHZ && ++ f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_83_MHZ && ++ f_pGetCapacityPins->ulMemClkFreq != cOCT6100_MCLK_FREQ_75_MHZ ) ++ return cOCT6100_ERR_OPEN_MEM_CLK_FREQ; ++ ++ if ( f_pGetCapacityPins->fEnableMemClkOut != TRUE && ++ f_pGetCapacityPins->fEnableMemClkOut != FALSE ) ++ return cOCT6100_ERR_OPEN_ENABLE_MEM_CLK_OUT; ++ ++ if ( f_pGetCapacityPins->ulMemoryType != cOCT6100_MEM_TYPE_SDR && ++ f_pGetCapacityPins->ulMemoryType != cOCT6100_MEM_TYPE_DDR && ++ f_pGetCapacityPins->ulMemoryType != cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ return cOCT6100_ERR_OPEN_MEMORY_TYPE; ++ ++ ++ ++ ApiInstance.pProcessContext = f_pGetCapacityPins->pProcessContext; ++ ++ ++ ++ ulResult = Oct6100ApiReadCapacity(&ApiInstance, f_pGetCapacityPins); ++ ++ ++ ++ return ulResult; ++} ++#endif ++ ++/*************************** PRIVATE FUNCTIONS *****************************/ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReadCapacity ++ ++Description: Read the capacity pins using modified functions from the openchip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pChipOpen Pointer to chip configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_OCT6100ApiReadCapacity ++UINT32 Oct6100ApiReadCapacity( IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins) ++{ ++ UINT32 ulResult; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT16 usReadData; ++ ++ /*Read capacity Pins*/ ++ ++ ++ ReadParams.pProcessContext = f_pGetCapacityPins->pProcessContext; ++ ReadParams.ulUserChipId = f_pGetCapacityPins->ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /*Check the Reset register*/ ++ ReadParams.ulReadAddress = 0x100; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ((usReadData & 0xFFFF) != 0x0000) ++ return cOCT6100_ERR_CAP_PINS_INVALID_CHIP_STATE; ++ ++ /* Test the CPU registers. */ ++ ulResult = Oct6100ApiCpuRegisterBistReadCap( f_pApiInstance, f_pGetCapacityPins ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Boot the FC2 PLL. */ ++ ulResult = Oct6100ApiBootFc2PllReadCap( f_pApiInstance,f_pGetCapacityPins ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Program the FC1 PLL. */ ++ ulResult = Oct6100ApiProgramFc1PllReadCap( f_pApiInstance,f_pGetCapacityPins ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( (f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR) || ++ (f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) ++ { ++ ReadParams.ulReadAddress = 0x168; ++ } ++ else ++ ReadParams.ulReadAddress = 0x166; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ switch (usReadData & 0xF) ++ { ++ case 0x9: ++ f_pGetCapacityPins->ulCapacityValue = 16; ++ break; ++ case 0x8: ++ f_pGetCapacityPins->ulCapacityValue = 32; ++ break; ++ case 0xE: ++ f_pGetCapacityPins->ulCapacityValue = 64; ++ break; ++ case 0x0: ++ f_pGetCapacityPins->ulCapacityValue = 128; ++ break; ++ case 0x2: ++ f_pGetCapacityPins->ulCapacityValue = 256; ++ break; ++ case 0x5: ++ f_pGetCapacityPins->ulCapacityValue = 512; ++ break; ++ case 0x6: ++ f_pGetCapacityPins->ulCapacityValue = 672; ++ break; ++ default: ++ f_pGetCapacityPins->ulCapacityValue = (usReadData & 0xF); ++ return cOCT6100_ERR_CAP_PINS_INVALID_CAPACITY_VALUE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckChipConfiguration ++ ++Description: Checks the user chip configuration structure for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pChipOpen Pointer to chip configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckChipConfiguration ++UINT32 Oct6100ApiCheckChipConfiguration( ++ IN tPOCT6100_CHIP_OPEN f_pChipOpen ) ++{ ++ UINT32 ulTempVar; ++ UINT32 i; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Check general parameters. */ ++ if ( f_pChipOpen->fMultiProcessSystem != TRUE && ++ f_pChipOpen->fMultiProcessSystem != FALSE ) ++ return cOCT6100_ERR_OPEN_MULTI_PROCESS_SYSTEM; ++ ++ if ( f_pChipOpen->ulMaxRwAccesses < 1 || ++ f_pChipOpen->ulMaxRwAccesses > 1024) ++ return cOCT6100_ERR_OPEN_MAX_RW_ACCESSES; ++ ++ /* Check the clocks. */ ++ if ( f_pChipOpen->ulUpclkFreq != cOCT6100_UPCLK_FREQ_33_33_MHZ ) ++ return cOCT6100_ERR_OPEN_UP_CLK_FREQ; ++ ++ if ( f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_133_MHZ ) ++ return cOCT6100_ERR_OPEN_MEM_CLK_FREQ; ++ ++ if ( f_pChipOpen->fEnableMemClkOut != TRUE && ++ f_pChipOpen->fEnableMemClkOut != FALSE ) ++ return cOCT6100_ERR_OPEN_ENABLE_MEM_CLK_OUT; ++ ++ /* Check the image file. */ ++ if ( f_pChipOpen->ulImageSize < cOCT6100_MIN_IMAGE_SIZE || ++ f_pChipOpen->ulImageSize > cOCT6100_MAX_IMAGE_SIZE ) ++ return cOCT6100_ERR_OPEN_IMAGE_SIZE; ++ ++ if ( f_pChipOpen->pbyImageFile == NULL ) ++ return cOCT6100_ERR_OPEN_IMAGE_FILE; ++ ++ ulTempVar = Oct6100ApiCheckImageFileHeader(f_pChipOpen); ++ if (ulTempVar != cOCT6100_ERR_OK) ++ return ulTempVar; ++ ++ /* Check the acoustic echo activation flag. */ ++ if ( f_pChipOpen->fEnableAcousticEcho != TRUE && ++ f_pChipOpen->fEnableAcousticEcho != FALSE ) ++ return cOCT6100_ERR_OPEN_ENABLE_ACOUSTIC_ECHO; ++ ++ /* Check the tail displacement parameter. */ ++ if ( f_pChipOpen->ulTailDisplacement > cOCT6100_MAX_TAIL_DISPLACEMENT ) ++ return cOCT6100_ERR_OPEN_TAIL_DISPLACEMENT; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Check TDM bus configuration parameters. */ ++ for ( i = 0; i < 8; i++ ) ++ { ++ if ( f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_2MHZ && ++ f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_4MHZ && ++ f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_8MHZ) ++ return cOCT6100_ERR_OPEN_TDM_STREAM_FREQS; ++ } ++ ++ if ( f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_3_QUARTERS && ++ f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_RISING_EDGE && ++ f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE ) ++ return cOCT6100_ERR_OPEN_TDM_SAMPLING; ++ ++ if ( f_pChipOpen->fEnableFastH100Mode != TRUE && ++ f_pChipOpen->fEnableFastH100Mode != FALSE ) ++ return cOCT6100_ERR_OPEN_FAST_H100_MODE; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Check external memory configuration parameters. */ ++ if ( f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_SDR && ++ f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_DDR && ++ f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ return cOCT6100_ERR_OPEN_MEMORY_TYPE; ++ ++ if ( f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_8MB && ++ f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_16MB && ++ f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_32MB && ++ f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_64MB && ++ f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_128MB ) ++ return cOCT6100_ERR_OPEN_MEMORY_CHIP_SIZE; ++ ++ if ( f_pChipOpen->ulMemoryChipSize == cOCT6100_MEMORY_CHIP_SIZE_8MB && ++ f_pChipOpen->ulMemoryType == cOCT6100_MEM_TYPE_DDR ) ++ return cOCT6100_ERR_OPEN_MEMORY_CHIP_SIZE; ++ ++ if ( f_pChipOpen->ulNumMemoryChips < 1 || ++ f_pChipOpen->ulNumMemoryChips > cOCT6100_MAX_NUM_MEMORY_CHIP ) ++ return cOCT6100_ERR_OPEN_MEMORY_CHIPS_NUMBER; ++ ++ /* Check the total memory size. */ ++ ulTempVar = f_pChipOpen->ulMemoryChipSize * f_pChipOpen->ulNumMemoryChips; ++ if ( ulTempVar < cOCT6100_MEMORY_CHIP_SIZE_16MB || ++ ulTempVar > cOCT6100_MEMORY_CHIP_SIZE_128MB ) ++ return cOCT6100_ERR_OPEN_TOTAL_MEMORY_SIZE; ++ ++ if ( f_pChipOpen->ulMaxTdmStreams != 4 && ++ f_pChipOpen->ulMaxTdmStreams != 8 && ++ f_pChipOpen->ulMaxTdmStreams != 16 && ++ f_pChipOpen->ulMaxTdmStreams != 32 ) ++ return cOCT6100_ERR_OPEN_MAX_TDM_STREAM; ++ ++ if ( f_pChipOpen->ulMaxTdmStreams > 8 && ++ f_pChipOpen->ulMemClkFreq == cOCT6100_MCLK_FREQ_75_MHZ ) ++ return cOCT6100_ERR_OPEN_MAX_TDM_STREAM; ++ ++ if ( f_pChipOpen->fUseSynchTimestamp != TRUE && ++ f_pChipOpen->fUseSynchTimestamp != FALSE ) ++ return cOCT6100_ERR_OPEN_USE_SYNCH_TIMESTAMP; ++ ++ if ( f_pChipOpen->fUseSynchTimestamp == TRUE ) ++ { ++ return cOCT6100_ERR_NOT_SUPPORTED_OPEN_USE_SYNCH_TIMESTAMP; ++ } ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Check soft buffer for tone events size. */ ++ if (f_pChipOpen->ulSoftToneEventsBufSize < 64 || ++ f_pChipOpen->ulSoftToneEventsBufSize > cOCT6100_ABSOLUTE_MAX_NUM_PGSP_EVENT_OUT ) ++ return cOCT6100_ERR_OPEN_SOFT_TONE_EVENT_SIZE; ++ ++ if ( f_pChipOpen->fEnableExtToneDetection != TRUE && ++ f_pChipOpen->fEnableExtToneDetection != FALSE ) ++ return cOCT6100_ERR_OPEN_ENABLE_EXT_TONE_DETECTION; ++ ++ if ( f_pChipOpen->fEnable2100StopEvent != TRUE && ++ f_pChipOpen->fEnable2100StopEvent != FALSE) ++ return cOCT6100_ERR_OPEN_ENABLE_2100_STOP_EVENT; ++ ++ /* Check soft buffer for playout events size. */ ++ if ( ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE ) ++ && ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize < cOCT6100_MIN_BUFFER_PLAYOUT_EVENT || ++ f_pChipOpen->ulSoftBufferPlayoutEventsBufSize > cOCT6100_MAX_BUFFER_PLAYOUT_EVENT ) ) ++ return cOCT6100_ERR_OPEN_SOFT_PLAYOUT_STOP_EVENT_SIZE; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Check interrupt configuration parameters. */ ++ if ( f_pChipOpen->ulInterruptPolarity != cOCT6100_ACTIVE_LOW_POLARITY && ++ f_pChipOpen->ulInterruptPolarity != cOCT6100_ACTIVE_HIGH_POLARITY ) ++ return cOCT6100_ERR_OPEN_INTERRUPT_POLARITY; ++ ++ if ( f_pChipOpen->InterruptConfig.ulFatalGeneralConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulFatalGeneralConfig != cOCT6100_INTERRUPT_DISABLE ) ++ return cOCT6100_ERR_OPEN_FATAL_GENERAL_CONFIG; ++ ++ if ( f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_DISABLE ) ++ return cOCT6100_ERR_OPEN_FATAL_MEMORY_CONFIG; ++ ++ if ( f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_DISABLE ) ++ return cOCT6100_ERR_OPEN_ERROR_MEMORY_CONFIG; ++ ++ if ( f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_DISABLE ) ++ return cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_CONFIG; ++ ++ if ( f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_NO_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_DISABLE ) ++ return cOCT6100_ERR_OPEN_ERROR_H100_CONFIG; ++ ++ /* Check the timeout value. */ ++ if ( f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout < 10 || ++ f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout > 10000 ) ++ return cOCT6100_ERR_OPEN_FATAL_MEMORY_TIMEOUT; ++ ++ if ( f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout < 10 || ++ f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout > 10000 ) ++ return cOCT6100_ERR_OPEN_ERROR_MEMORY_TIMEOUT; ++ ++ if ( f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout < 10 || ++ f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout > 10000 ) ++ return cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_TIMEOUT; ++ ++ if ( f_pChipOpen->InterruptConfig.ulErrorH100Timeout < 10 || ++ f_pChipOpen->InterruptConfig.ulErrorH100Timeout > 10000 ) ++ return cOCT6100_ERR_OPEN_ERROR_H100_TIMEOUT; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Check maximum resources. */ ++ ++ switch ( f_pChipOpen->ulMemClkFreq ) ++ { ++ case 133000000: ++ ulTempVar = 672; ++ break; ++ case 125000000: ++ ulTempVar = 624; ++ break; ++ case 117000000: ++ ulTempVar = 576; ++ break; ++ case 108000000: ++ ulTempVar = 528; ++ break; ++ case 100000000: ++ ulTempVar = 480; ++ break; ++ case 92000000: ++ ulTempVar = 432; ++ break; ++ case 83000000: ++ ulTempVar = 384; ++ break; ++ case 75000000: ++ ulTempVar = 336; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_DA; ++ } ++ ++ if ( f_pChipOpen->ulMaxChannels > ulTempVar ) ++ return cOCT6100_ERR_OPEN_MAX_ECHO_CHANNELS; ++ ++ if ( f_pChipOpen->ulMaxTsiCncts > cOCT6100_MAX_TSI_CNCTS ) ++ return cOCT6100_ERR_OPEN_MAX_TSI_CNCTS; ++ ++ ++ if ( f_pChipOpen->ulMaxBiDirChannels > 255 ) ++ return cOCT6100_ERR_OPEN_MAX_BIDIR_CHANNELS; ++ ++ if ( f_pChipOpen->ulMaxBiDirChannels > (f_pChipOpen->ulMaxChannels / 2) ) ++ return cOCT6100_ERR_OPEN_MAX_BIDIR_CHANNELS; ++ ++ if ( f_pChipOpen->ulMaxConfBridges > cOCT6100_MAX_CONF_BRIDGE ) ++ return cOCT6100_ERR_OPEN_MAX_CONF_BRIDGES; ++ ++ if ( f_pChipOpen->ulMaxFlexibleConfParticipants > cOCT6100_MAX_FLEX_CONF_PARTICIPANTS ) ++ return cOCT6100_ERR_OPEN_MAX_FLEXIBLE_CONF_PARTICIPANTS; ++ ++ if ( f_pChipOpen->ulMaxPlayoutBuffers > cOCT6100_MAX_PLAYOUT_BUFFERS ) ++ return cOCT6100_ERR_OPEN_MAX_PLAYOUT_BUFFERS; ++ ++ ++ ++ if ( f_pChipOpen->ulMaxPhasingTssts > cOCT6100_MAX_PHASING_TSST ) ++ return cOCT6100_ERR_OPEN_MAX_PHASING_TSSTS; ++ ++ if ( f_pChipOpen->ulMaxAdpcmChannels > cOCT6100_MAX_ADPCM_CHANNELS ) ++ return cOCT6100_ERR_OPEN_MAX_ADPCM_CHANNELS; ++ ++ if ( f_pChipOpen->ulMaxRemoteDebugSessions > 256 ) ++ return cOCT6100_ERR_OPEN_MAX_REMOTE_DEBUG_SESSIONS; ++ ++ ++ ++ ++ ++ /* Check the channel recording flag. */ ++ if ( f_pChipOpen->fEnableChannelRecording != TRUE && ++ f_pChipOpen->fEnableChannelRecording != FALSE ) ++ return cOCT6100_ERR_OPEN_DEBUG_CHANNEL_RECORDING; ++ ++ /* Check the enable production BIST flag. */ ++ if ( ( f_pChipOpen->fEnableProductionBist != TRUE ) ++ && ( f_pChipOpen->fEnableProductionBist != FALSE ) ) ++ return cOCT6100_ERR_OPEN_ENABLE_PRODUCTION_BIST; ++ ++ /* Check number of loops for the production BIST. */ ++ if ( f_pChipOpen->fEnableProductionBist == TRUE ) ++ { ++ if ( f_pChipOpen->ulNumProductionBistLoops == 0 ) ++ return cOCT6100_ERR_OPEN_NUM_PRODUCTION_BIST_LOOPS; ++ ++ if ( (f_pChipOpen->ulProductionBistMode != cOCT6100_PRODUCTION_BIST_STANDARD) && ++ (f_pChipOpen->ulProductionBistMode != cOCT6100_PRODUCTION_BIST_SHORT) ) ++ return cOCT6100_ERR_OPEN_PRODUCTION_BIST_MODE; ++ } ++ ++ /* If the production BIST has been requested, make sure all */ ++ /* other resources are disabled. */ ++ if ( f_pChipOpen->fEnableProductionBist == TRUE ) ++ { ++ /* All must be disabled. */ ++ f_pChipOpen->ulMaxChannels = 0; ++ f_pChipOpen->ulMaxTsiCncts = 0; ++ f_pChipOpen->fEnableChannelRecording = FALSE; ++ f_pChipOpen->ulMaxBiDirChannels = 0; ++ f_pChipOpen->ulMaxConfBridges = 0; ++ f_pChipOpen->ulMaxPlayoutBuffers = 0; ++ f_pChipOpen->ulSoftBufferPlayoutEventsBufSize = cOCT6100_INVALID_VALUE; ++ f_pChipOpen->ulMaxPhasingTssts = 0; ++ f_pChipOpen->ulMaxAdpcmChannels = 0; ++ ++ ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCopyChipConfiguration ++ ++Description: Copies the chip configuration from the user supplied config ++ structure to the instance structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChipOpen Pointer to chip configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCopyChipConfiguration ++UINT32 Oct6100ApiCopyChipConfiguration( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHIP_OPEN f_pChipOpen ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 i; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ pSharedInfo->ChipConfig.ulUserChipId = f_pChipOpen->ulUserChipId; ++ pSharedInfo->ChipConfig.fMultiProcessSystem = (UINT8)( f_pChipOpen->fMultiProcessSystem & 0xFF ); ++ ++ pSharedInfo->ChipConfig.usMaxRwAccesses = (UINT16)( f_pChipOpen->ulMaxRwAccesses & 0xFFFF ); ++ ++ pSharedInfo->ChipConfig.pbyImageFile = f_pChipOpen->pbyImageFile; ++ pSharedInfo->ChipConfig.ulImageSize = f_pChipOpen->ulImageSize; ++ ++ pSharedInfo->ChipConfig.ulMemClkFreq = f_pChipOpen->ulMemClkFreq; ++ pSharedInfo->ChipConfig.ulUpclkFreq = f_pChipOpen->ulUpclkFreq; ++ ++ pSharedInfo->ChipConfig.byMemoryType = (UINT8)( f_pChipOpen->ulMemoryType & 0xFF ); ++ pSharedInfo->ChipConfig.byNumMemoryChips = (UINT8)( f_pChipOpen->ulNumMemoryChips & 0xFF ); ++ pSharedInfo->ChipConfig.ulMemoryChipSize = f_pChipOpen->ulMemoryChipSize; ++ ++ pSharedInfo->ChipConfig.usTailDisplacement = (UINT16)( f_pChipOpen->ulTailDisplacement & 0xFFFF ); ++ pSharedInfo->ChipConfig.fEnableAcousticEcho = (UINT8)( f_pChipOpen->fEnableAcousticEcho & 0xFF ); ++ /* Resource allocation parameters. */ ++ if ( f_pChipOpen->fEnableChannelRecording == TRUE && f_pChipOpen->ulMaxChannels == 672 ) ++ pSharedInfo->ChipConfig.usMaxChannels = (UINT16)( ( f_pChipOpen->ulMaxChannels - 1 ) & 0xFFFF ); ++ else ++ pSharedInfo->ChipConfig.usMaxChannels = (UINT16)( f_pChipOpen->ulMaxChannels & 0xFFFF ); ++ pSharedInfo->ChipConfig.usMaxTsiCncts = (UINT16)( f_pChipOpen->ulMaxTsiCncts & 0xFFFF ); ++ pSharedInfo->ChipConfig.usMaxBiDirChannels = (UINT16)( f_pChipOpen->ulMaxBiDirChannels & 0xFFFF ); ++ pSharedInfo->ChipConfig.usMaxConfBridges = (UINT16)( f_pChipOpen->ulMaxConfBridges & 0xFFFF ); ++ pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants = (UINT16)( f_pChipOpen->ulMaxFlexibleConfParticipants & 0xFFFF ); ++ pSharedInfo->ChipConfig.usMaxPlayoutBuffers = (UINT16)( f_pChipOpen->ulMaxPlayoutBuffers & 0xFFFF ); ++ ++ pSharedInfo->ChipConfig.usMaxPhasingTssts = (UINT16)( f_pChipOpen->ulMaxPhasingTssts & 0xFFFF ); ++ pSharedInfo->ChipConfig.usMaxAdpcmChannels = (UINT16)( f_pChipOpen->ulMaxAdpcmChannels & 0xFFFF ); ++ pSharedInfo->ChipConfig.byMaxTdmStreams = (UINT8)( f_pChipOpen->ulMaxTdmStreams & 0xFF ); ++ pSharedInfo->ChipConfig.fUseSynchTimestamp = (UINT8)( f_pChipOpen->fUseSynchTimestamp & 0xFF ); ++ for ( i = 0; i < 4; i++ ) ++ { ++ pSharedInfo->ChipConfig.ausTimestampTimeslots[ i ] = (UINT16)( f_pChipOpen->aulTimestampTimeslots[ i ] & 0xFFFF ); ++ pSharedInfo->ChipConfig.ausTimestampStreams[ i ] = (UINT16)( f_pChipOpen->aulTimestampStreams[ i ] & 0xFFFF ); ++ } ++ pSharedInfo->ChipConfig.byInterruptPolarity = (UINT8)( f_pChipOpen->ulInterruptPolarity & 0xFF ); ++ ++ pSharedInfo->ChipConfig.byTdmSampling = (UINT8)( f_pChipOpen->ulTdmSampling & 0xFF ); ++ pSharedInfo->ChipConfig.fEnableFastH100Mode = (UINT8)( f_pChipOpen->fEnableFastH100Mode & 0xFF ); ++ ++ for ( i = 0; i < cOCT6100_TDM_STREAM_MAX_GROUPS; i++ ) ++ { ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->ChipConfig.aulTdmStreamFreqs[ i ] = cOCT6100_TDM_STREAM_FREQ_16MHZ; ++ else ++ pSharedInfo->ChipConfig.aulTdmStreamFreqs[ i ] = f_pChipOpen->aulTdmStreamFreqs[ i ]; ++ } ++ ++ pSharedInfo->ChipConfig.fEnableFastH100Mode = (UINT8)( f_pChipOpen->fEnableFastH100Mode & 0xFF ); ++ pSharedInfo->ChipConfig.fEnableMemClkOut = (UINT8)( f_pChipOpen->fEnableMemClkOut & 0xFF ); ++ ++ /* Add 1 to the circular buffer such that all user requested events can fit in the circular queue. */ ++ pSharedInfo->ChipConfig.ulSoftToneEventsBufSize = f_pChipOpen->ulSoftToneEventsBufSize + 1; ++ pSharedInfo->ChipConfig.fEnableExtToneDetection = (UINT8)( f_pChipOpen->fEnableExtToneDetection & 0xFF ); ++ pSharedInfo->ChipConfig.fEnable2100StopEvent = (UINT8)( f_pChipOpen->fEnable2100StopEvent & 0xFF ); ++ ++ if ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE ) ++ pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize = f_pChipOpen->ulSoftBufferPlayoutEventsBufSize + 1; ++ else ++ pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize = 0; ++ pSharedInfo->ChipConfig.usMaxRemoteDebugSessions = (UINT16)( f_pChipOpen->ulMaxRemoteDebugSessions & 0xFFFF ); ++ ++ pSharedInfo->ChipConfig.fEnableChannelRecording = (UINT8)( f_pChipOpen->fEnableChannelRecording & 0xFF ); ++ ++ ++ ++ pSharedInfo->ChipConfig.fEnableProductionBist = (UINT8)( f_pChipOpen->fEnableProductionBist & 0xFF ); ++ pSharedInfo->ChipConfig.ulProductionBistMode = f_pChipOpen->ulProductionBistMode; ++ pSharedInfo->ChipConfig.ulNumProductionBistLoops = f_pChipOpen->ulNumProductionBistLoops; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInitializeMiscellaneousVariables ++ ++Description: Function where all the various parameters from the API instance ++ are set to their defaults value. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInitializeMiscellaneousVariables ++UINT32 Oct6100ApiInitializeMiscellaneousVariables( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 i; ++ ++ /* Obtain pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Calculate the total memory available. */ ++ pSharedInfo->MiscVars.ulTotalMemSize = pSharedInfo->ChipConfig.ulMemoryChipSize * pSharedInfo->ChipConfig.byNumMemoryChips; ++ ++ /* Software buffers initialization. */ ++ ++ /* Tones */ ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; ++ pSharedInfo->SoftBufs.ulToneEventBufferReadPtr = 0; ++ pSharedInfo->SoftBufs.ulToneEventBufferSize = pSharedInfo->ChipConfig.ulSoftToneEventsBufSize; ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt = 0; ++ ++ /* Playout */ ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr = 0; ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr = 0; ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize = pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize; ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt = 0; ++ ++ /* Set the number of conference bridges opened to zero. */ ++ pSharedInfo->MiscVars.usNumBridgesOpened = 0; ++ pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX; ++ ++ /* Set the H.100 slave mode. */ ++ pSharedInfo->MiscVars.ulH100SlaveMode = cOCT6100_H100_TRACKA; ++ ++ /* Save the Mclk value.*/ ++ pSharedInfo->MiscVars.ulMclkFreq = pSharedInfo->ChipConfig.ulMemClkFreq; ++ ++ /* Init the NLP params. */ ++ pSharedInfo->MiscVars.usCodepoint = 0; ++ pSharedInfo->MiscVars.usCpuLsuWritePtr = 0; ++ ++ /* Pouch counter not present until TLVs are read. */ ++ pSharedInfo->DebugInfo.fPouchCounter = FALSE; ++ pSharedInfo->DebugInfo.fIsIsrCalledField = FALSE; ++ ++ /* Initialize the image info parameters */ ++ pSharedInfo->ImageInfo.fAdaptiveNoiseReduction = FALSE; ++ pSharedInfo->ImageInfo.fSoutNoiseBleaching = FALSE; ++ pSharedInfo->ImageInfo.fComfortNoise = FALSE; ++ pSharedInfo->ImageInfo.fBufferPlayout = TRUE; ++ pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip = FALSE; ++ pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip = FALSE; ++ pSharedInfo->ImageInfo.fNlpControl = FALSE; ++ pSharedInfo->ImageInfo.fRinAutoLevelControl = FALSE; ++ pSharedInfo->ImageInfo.fSoutAutoLevelControl = FALSE; ++ pSharedInfo->ImageInfo.fRinHighLevelCompensation = FALSE; ++ pSharedInfo->ImageInfo.fSoutHighLevelCompensation = FALSE; ++ pSharedInfo->ImageInfo.fAlcHlcStatus = FALSE; ++ pSharedInfo->ImageInfo.fRinDcOffsetRemoval = FALSE; ++ pSharedInfo->ImageInfo.fSilenceSuppression = FALSE; ++ pSharedInfo->ImageInfo.fSinDcOffsetRemoval = FALSE; ++ pSharedInfo->ImageInfo.fToneDisabler = FALSE; ++ pSharedInfo->ImageInfo.fAdpcm = FALSE; ++ pSharedInfo->ImageInfo.fTailDisplacement = FALSE; ++ pSharedInfo->ImageInfo.fConferencing = FALSE; ++ pSharedInfo->ImageInfo.fConferencingNoiseReduction = FALSE; ++ pSharedInfo->ImageInfo.fDominantSpeakerEnabled = FALSE; ++ pSharedInfo->ImageInfo.fAecEnabled = FALSE; ++ pSharedInfo->ImageInfo.fAcousticEcho = FALSE; ++ pSharedInfo->ImageInfo.fToneRemoval = FALSE; ++ ++ pSharedInfo->ImageInfo.fDefaultErl = FALSE; ++ pSharedInfo->ImageInfo.fMaxEchoPoint = FALSE; ++ pSharedInfo->ImageInfo.fNonLinearityBehaviorA = FALSE; ++ pSharedInfo->ImageInfo.fNonLinearityBehaviorB = FALSE; ++ pSharedInfo->ImageInfo.fPerChannelTailDisplacement = FALSE; ++ pSharedInfo->ImageInfo.fPerChannelTailLength = FALSE; ++ pSharedInfo->ImageInfo.fAfTailDisplacement = FALSE; ++ pSharedInfo->ImageInfo.fMusicProtection = FALSE; ++ pSharedInfo->ImageInfo.fAftControl = FALSE; ++ pSharedInfo->ImageInfo.fSinVoiceDetectedStat = FALSE; ++ pSharedInfo->ImageInfo.fRinAppliedGainStat = FALSE; ++ pSharedInfo->ImageInfo.fSoutAppliedGainStat = FALSE; ++ pSharedInfo->ImageInfo.fListenerEnhancement = FALSE; ++ pSharedInfo->ImageInfo.fRoutNoiseReduction = FALSE; ++ pSharedInfo->ImageInfo.fRoutNoiseReductionLevel = FALSE; ++ pSharedInfo->ImageInfo.fAnrSnrEnhancement = FALSE; ++ pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation = FALSE; ++ pSharedInfo->ImageInfo.fRinMute = FALSE; ++ pSharedInfo->ImageInfo.fSinMute = FALSE; ++ pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay = FALSE; ++ pSharedInfo->ImageInfo.fAecTailLength = FALSE; ++ pSharedInfo->ImageInfo.fMusicProtectionConfiguration= FALSE; ++ pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents = FALSE; ++ pSharedInfo->ImageInfo.fRinEnergyStat = FALSE; ++ pSharedInfo->ImageInfo.fSoutEnergyStat = FALSE; ++ pSharedInfo->ImageInfo.fDoubleTalkBehavior = FALSE; ++ pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst = FALSE; ++ pSharedInfo->ImageInfo.fIdleCodeDetection = TRUE; ++ pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration = FALSE; ++ pSharedInfo->ImageInfo.fSinLevel = TRUE; ++ ++ pSharedInfo->ImageInfo.usMaxNumberOfChannels = 0; ++ pSharedInfo->ImageInfo.ulToneProfileNumber = cOCT6100_INVALID_VALUE; ++ pSharedInfo->ImageInfo.ulBuildId = cOCT6100_INVALID_VALUE; ++ pSharedInfo->ImageInfo.byImageType = cOCT6100_IMAGE_TYPE_WIRELINE; ++ pSharedInfo->ImageInfo.usMaxTailDisplacement = 0; ++ pSharedInfo->ImageInfo.usMaxTailLength = cOCT6100_TAIL_LENGTH_128MS; ++ pSharedInfo->DebugInfo.ulDebugEventSize = 0x100; ++ pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents = 32; ++ pSharedInfo->DebugInfo.ulMatrixBaseAddress = cOCT6100_MATRIX_DWORD_BASE; ++ pSharedInfo->DebugInfo.ulDebugChanStatsByteSize = cOCT6100_DEBUG_CHAN_STATS_EVENT_BYTE_SIZE; ++ pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize = cOCT6100_DEBUG_CHAN_STATS_LITE_EVENT_BYTE_SIZE; ++ pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress= cOCT6100_MATRIX_CHAN_SELECT_DWORD_ADD; ++ pSharedInfo->DebugInfo.ulMatrixTimestampBaseAddress = cOCT6100_MATRIX_TIMESTAMP_DWORD_ADD; ++ pSharedInfo->DebugInfo.ulMatrixWpBaseAddress = cOCT6100_MATRIX_WRITE_PTR_DWORD_ADD; ++ pSharedInfo->DebugInfo.ulAfWritePtrByteOffset = 206; ++ pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize = 4096; ++ pSharedInfo->DebugInfo.ulAfEventCbByteSize = 0x100000; ++ ++ /* Set all tones to invalid. */ ++ pSharedInfo->ImageInfo.byNumToneDetectors = 0; ++ for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) ++ { ++ pSharedInfo->ImageInfo.aToneInfo[ i ].ulToneID = cOCT6100_INVALID_VALUE; ++ pSharedInfo->ImageInfo.aToneInfo[ i ].ulDetectionPort = cOCT6100_INVALID_PORT; ++ Oct6100UserMemSet( pSharedInfo->ImageInfo.aToneInfo[ i ].aszToneName, 0x00, cOCT6100_TLV_MAX_TONE_NAME_SIZE ); ++ } ++ /* Initialize the channel recording info. */ ++ pSharedInfo->DebugInfo.usRecordChanIndex = pSharedInfo->ChipConfig.usMaxChannels; ++ pSharedInfo->DebugInfo.usRecordMemIndex = cOCT6100_INVALID_INDEX; ++ ++ pSharedInfo->DebugInfo.usCurrentDebugChanIndex = cOCT6100_INVALID_INDEX; ++ /* Initialize the mixer information. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastSinCopyEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pSharedInfo->MixerInfo.usRecordCopyEventIndex = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usRecordSinEventIndex = cOCT6100_INVALID_INDEX; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCalculateInstanceSizes ++ ++Description: Calculates the amount of memory needed for the instance ++ structure memory block based on the user's configuration. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pChipOpen Pointer to user chip configuration structure. ++ ++f_pInstSizes Pointer to structure containing the size of memory needed ++ by all pointers internal to the API instance. The memory ++ is needed to keep track of the present state of all the ++ chip's resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCalculateInstanceSizes ++UINT32 Oct6100ApiCalculateInstanceSizes( ++ IN OUT tPOCT6100_CHIP_OPEN f_pChipOpen, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulApiInstProcessSpecific; ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Start with all instance sizes set to 0. */ ++ Oct6100UserMemSet( f_pInstSizes, 0x00, sizeof( tOCT6100_API_INSTANCE_SIZES ) ); ++ ++ /* All memory sizes are rounded up to the next multiple of 64 bytes. */ ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Obtain size of static members of API instance. */ ++ f_pInstSizes->ulApiInstStatic = sizeof( tOCT6100_SHARED_INFO ); ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulApiInstStatic, ulTempVar ) ++ ++ /* Calculate memory needed by pointers internal to the API instance. */ ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Calculate memory needed for the EC channels. */ ++ ulResult = Oct6100ApiGetChannelsEchoSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*-----------------------------------------------------------------------------*/ ++ /* Memory needed by the TSI structures. */ ++ ulResult = Oct6100ApiGetTsiCnctSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*-----------------------------------------------------------------------------*/ ++ /* Calculate memory needed for the conference bridges. */ ++ ulResult = Oct6100ApiGetConfBridgeSwSizes( f_pChipOpen, f_pInstSizes ); ++ /* Calculate memory needed for list and allocation software serialization. */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Memory needed by the buffer playout structures. */ ++ ulResult = Oct6100ApiGetPlayoutBufferSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Memory needed by soft Rx Event buffers. */ ++ ulResult = Oct6100ApiGetEventsSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Calculate memory needed for phasing tssts. */ ++ ulResult = Oct6100ApiGetPhasingTsstSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*-----------------------------------------------------------------------------*/ ++ /* Calculate memory needed for the ADPCM channels. */ ++ ulResult = Oct6100ApiGetAdpcmChanSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Calculate memory needed for the management of TSSTs. */ ++ ulResult = Oct6100ApiGetTsstSwSizes( f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Calculate memory needed for the management of the mixer. */ ++ ulResult = Oct6100ApiGetMixerSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Determine amount of memory needed for memory allocation softwares. These ++ pieces of software will be responsible for the allocation of the chip's ++ external memory and API memory. */ ++ ulResult = Oct6100ApiGetMemorySwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Memory needed for remote debugging sessions. */ ++ ulResult = Oct6100ApiGetRemoteDebugSwSizes( f_pChipOpen, f_pInstSizes ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Calculate total memory needed by pointers internal to API instance. The ++ total contains both the process specific portion of the instance ++ (tOCT6100_INSTANCE_API) and the shared portion (tOCT6100_SHARED_INFO). The ++ process specific portion will be used only in the case where the host system ++ is a single-process one. */ ++ ++ ulApiInstProcessSpecific = sizeof( tOCT6100_INSTANCE_API ); ++ mOCT6100_ROUND_MEMORY_SIZE( ulApiInstProcessSpecific, ulTempVar ) ++ f_pInstSizes->ulApiInstTotal = ++ f_pInstSizes->ulChannelList + ++ f_pInstSizes->ulChannelAlloc + ++ f_pInstSizes->ulTsiCnctList + ++ f_pInstSizes->ulTsiCnctAlloc + ++ f_pInstSizes->ulSoftToneEventsBuffer + ++ f_pInstSizes->ulSoftBufPlayoutEventsBuffer + ++ f_pInstSizes->ulBiDirChannelList + ++ f_pInstSizes->ulBiDirChannelAlloc + ++ f_pInstSizes->ulConfBridgeList + ++ f_pInstSizes->ulConfBridgeAlloc + ++ f_pInstSizes->ulFlexConfParticipantsList + ++ f_pInstSizes->ulFlexConfParticipantsAlloc + ++ f_pInstSizes->ulPlayoutBufList + ++ f_pInstSizes->ulPlayoutBufAlloc + ++ f_pInstSizes->ulPlayoutBufMemoryNodeList + ++ ++ f_pInstSizes->ulCopyEventList + ++ f_pInstSizes->ulCopyEventAlloc + ++ f_pInstSizes->ulMixerEventList + ++ f_pInstSizes->ulMixerEventAlloc + ++ f_pInstSizes->ulPhasingTsstList + ++ f_pInstSizes->ulPhasingTsstAlloc + ++ f_pInstSizes->ulAdpcmChannelList + ++ f_pInstSizes->ulAdpcmChannelAlloc + ++ f_pInstSizes->ulConversionMemoryAlloc + ++ f_pInstSizes->ulTsiMemoryAlloc + ++ f_pInstSizes->ulRemoteDebugList + ++ f_pInstSizes->ulRemoteDebugTree + ++ f_pInstSizes->ulRemoteDebugPktCache + ++ f_pInstSizes->ulRemoteDebugDataBuf + ++ f_pInstSizes->ulTsstEntryList + ++ f_pInstSizes->ulTsstEntryAlloc + ++ f_pInstSizes->ulTsstAlloc + ++ f_pInstSizes->ulApiInstStatic + ++ ulApiInstProcessSpecific; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAllocateInstanceMemory ++ ++Description: Allocates the API instance memory to the various members of ++ the structure f_pApiInstance according to the sizes contained ++ in f_pInstSizes. No initialization of this memory is ++ performed. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pInstSizes Pointer to structure containing the size of memory needed ++ by all pointers internal to the API instance. The memory ++ is needed to keep track of the present state of all the ++ chip's resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAllocateInstanceMemory ++UINT32 Oct6100ApiAllocateInstanceMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulOffset; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get address of first UINT32 of memory in API instance structure following */ ++ /* the static members of the API instance structure. */ ++ ulOffset = f_pInstSizes->ulApiInstStatic; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the echo channels.*/ ++ pSharedInfo->ulChannelListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulChannelList; ++ pSharedInfo->ulChannelAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulChannelAlloc; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the TSI connections */ ++ pSharedInfo->ulTsiCnctListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulTsiCnctList; ++ pSharedInfo->ulTsiCnctAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulTsiCnctAlloc; ++ pSharedInfo->ulMixerEventListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulMixerEventList; ++ pSharedInfo->ulMixerEventAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulMixerEventAlloc; ++ ++ pSharedInfo->ulBiDirChannelListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulBiDirChannelList; ++ pSharedInfo->ulBiDirChannelAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulBiDirChannelAlloc; ++ pSharedInfo->ulCopyEventListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulCopyEventList; ++ pSharedInfo->ulCopyEventAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulCopyEventAlloc; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the conference bridges */ ++ pSharedInfo->ulConfBridgeListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulConfBridgeList; ++ pSharedInfo->ulConfBridgeAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulConfBridgeAlloc; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the flexible conferencing participants. */ ++ pSharedInfo->ulFlexConfParticipantListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulFlexConfParticipantsList; ++ pSharedInfo->ulFlexConfParticipantAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulFlexConfParticipantsAlloc; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the play-out buffers */ ++ pSharedInfo->ulPlayoutBufListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulPlayoutBufList; ++ pSharedInfo->ulPlayoutBufAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulPlayoutBufAlloc; ++ pSharedInfo->ulPlayoutBufMemoryNodeListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulPlayoutBufMemoryNodeList; ++ ++ ++ ++ /*===================================================================*/ ++ /* Allocate memory for the phasing TSSTs */ ++ pSharedInfo->ulPhasingTsstListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulPhasingTsstList; ++ pSharedInfo->ulPhasingTsstAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulPhasingTsstAlloc; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the ADPCM channel */ ++ pSharedInfo->ulAdpcmChanAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulAdpcmChannelAlloc; ++ pSharedInfo->ulAdpcmChanListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulAdpcmChannelList; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the conversion memory */ ++ pSharedInfo->ulConversionMemoryAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulConversionMemoryAlloc; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the TSI chariot memory */ ++ pSharedInfo->ulTsiMemoryAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulTsiMemoryAlloc; ++ ++ /*===================================================================*/ ++ /* Allocate memory for the TSST management */ ++ pSharedInfo->ulTsstAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulTsstAlloc; ++ pSharedInfo->ulTsstListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulTsstEntryList; ++ pSharedInfo->ulTsstListAllocOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulTsstEntryAlloc; ++ ++ /*===================================================================*/ ++ pSharedInfo->SoftBufs.ulToneEventBufferMemOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulSoftToneEventsBuffer; ++ ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferMemOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulSoftBufPlayoutEventsBuffer; ++ /*===================================================================*/ ++ pSharedInfo->RemoteDebugInfo.ulSessionListOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulRemoteDebugList; ++ ++ pSharedInfo->RemoteDebugInfo.ulSessionTreeOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulRemoteDebugTree; ++ ++ pSharedInfo->RemoteDebugInfo.ulDataBufOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulRemoteDebugDataBuf; ++ ++ pSharedInfo->RemoteDebugInfo.ulPktCacheOfst = ulOffset; ++ ulOffset += f_pInstSizes->ulRemoteDebugPktCache; ++ /*===================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInitializeInstanceMemory ++ ++Description: Initializes the various members of the structure f_pApiInstance ++ to reflect the current state of the chip and its resources. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInitializeInstanceMemory ++UINT32 Oct6100ApiInitializeInstanceMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ UINT32 ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize API EC channels. */ ++ ulResult = Oct6100ApiChannelsEchoSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the API TSI connection structures. */ ++ ulResult = Oct6100ApiTsiCnctSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the API conference bridges. */ ++ ulResult = Oct6100ApiConfBridgeSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the API buffer playout structures. */ ++ ulResult = Oct6100ApiPlayoutBufferSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the API phasing tssts. */ ++ ulResult = Oct6100ApiPhasingTsstSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the API ADPCM channels. */ ++ ulResult = Oct6100ApiAdpcmChanSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the external memory management structures. */ ++ ulResult = Oct6100ApiMemorySwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize TSST management stuctures. */ ++ ulResult = Oct6100ApiTsstSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the mixer management stuctures. */ ++ ulResult = Oct6100ApiMixerSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Initialize the remote debugging session management variables. */ ++ ulResult = Oct6100ApiRemoteDebuggingSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*-----------------------------------------------------------------------------*/ ++ /* Configure the interrupt registers. */ ++ ulResult = Oct6100ApiIsrSwInit( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetChipRevisionNum ++ ++Description: Reads the chip's revision number register. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetChipRevisionNum ++UINT32 Oct6100ApiGetChipRevisionNum( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get the chip revision number. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.ulReadAddress = cOCT6100_CHIP_ID_REVISION_REG; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save the info in the API miscellaneous structure. */ ++ pSharedInfo->MiscVars.usChipId = (UINT16)( usReadData & 0xFF ); ++ pSharedInfo->MiscVars.usChipRevision = (UINT16)( usReadData >> 8 ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckImageFileHeader ++ ++Description: This function check if the image loaded is valid ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckImageFileHeader ++UINT32 Oct6100ApiCheckImageFileHeader( ++ IN tPOCT6100_CHIP_OPEN f_pChipOpen ) ++{ ++ ++ PUINT8 pszImageInfoStart = NULL; ++ UINT32 ulStrLen; ++ ++ ulStrLen = Oct6100ApiStrLen( (PUINT8)cOCT6100_IMAGE_START_STRING ); ++ pszImageInfoStart = (PUINT8) Oct6100ApiStrStr(f_pChipOpen->pbyImageFile,(PUINT8)cOCT6100_IMAGE_START_STRING, ++ f_pChipOpen->pbyImageFile + ulStrLen); ++ if (pszImageInfoStart == NULL) ++ return cOCT6100_ERR_OPEN_IMAGE_FILE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiDecodeKeyAndBist ++ ++Description: This function decodes the key and runs the automatic BIST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiDecodeKeyAndBist ++UINT32 Oct6100ApiDecodeKeyAndBist( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT16 ausBistData[ 3 ]; ++ UINT16 usReadData; ++ UINT32 ulResult; ++ BOOL fBitEqual; ++ UINT32 i; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain a local pointer to the chip config structure */ ++ /* contained in the instance structure. */ ++ pChipConfig = &pSharedInfo->ChipConfig; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pChipConfig->ulUserChipId; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pChipConfig->ulUserChipId; ++ ++ /* Write key in CPU internal memory. */ ++ for(i=0; i<8; i++) ++ { ++ WriteParams.ulWriteAddress = 0x150; ++ WriteParams.usWriteData = 0x0000; ++ if (( i % 2 ) == 0) ++ { ++ WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 2]) << 8; ++ WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 3]) << 0; ++ } ++ else ++ { ++ WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 0]) << 8; ++ WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 1]) << 0; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x152; ++ WriteParams.usWriteData = (UINT16)( 0x8000 | i ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Write one in CPU internal memory. */ ++ for(i=0; i<8; i++) ++ { ++ WriteParams.ulWriteAddress = 0x150; ++ if (i == 0) ++ { ++ WriteParams.usWriteData = 0x0001; ++ } ++ else ++ { ++ WriteParams.usWriteData = 0x0000; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x152; ++ WriteParams.usWriteData = (UINT16)( 0x8000 | ( i + 8 )); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Clear memory access registers: */ ++ WriteParams.ulWriteAddress = 0x150; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x152; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Run BISTs and key decode. */ ++ WriteParams.ulWriteAddress = 0x160; ++ WriteParams.usWriteData = 0x0081; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Wait for the key decode PC to clear. */ ++ ulResult = Oct6100ApiWaitForPcRegisterBit( f_pApiInstance, 0x160, 0, 0, 100000, &fBitEqual ); ++ if ( TRUE != fBitEqual ) ++ return cOCT6100_ERR_FATAL_13; ++ ++ /* Read the key valid bit to make sure everything is ok. */ ++ ReadParams.ulReadAddress = 0x160; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Either the firmware image was not loaded correctly (from pointer given by user) */ ++ /* or the channel capacity pins of the chip do not match what the firmware is expecting. */ ++ if ( ( usReadData & 0x4 ) == 0 ) ++ return cOCT6100_ERR_OPEN_INVALID_FIRMWARE_OR_CAPACITY_PINS; ++ ++ /* Read the result of the internal memory bist. */ ++ ReadParams.ulReadAddress = 0x110; ++ ReadParams.pusReadData = &ausBistData[ 0 ]; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ReadParams.ulReadAddress = 0x114; ++ ReadParams.pusReadData = &ausBistData[ 1 ]; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ReadParams.ulReadAddress = 0x118; ++ ReadParams.pusReadData = &ausBistData[ 2 ]; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if an error was reported. */ ++ if (ausBistData[0] != 0x0000 || ausBistData[1] != 0x0000 || ausBistData[2] != 0x0000) ++ return cOCT6100_ERR_OPEN_INTERNAL_MEMORY_BIST; ++ ++ /* Put key decoder in powerdown. */ ++ WriteParams.ulWriteAddress = 0x160; ++ WriteParams.usWriteData = 0x008A; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBootFc2PllReadCap ++ ++Description: Configures the chip's FC2 PLL. Special version for GetcapacityPins. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++UINT32 Oct6100ApiBootFc2PllReadCap( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 aulWaitTime[ 2 ]; ++ UINT32 ulResult; ++ UINT32 ulFc2PllDivisor = 0; ++ UINT32 ulMtDivisor = 0; ++ UINT32 ulFcDivisor = 0; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pGetCapacityPins->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pGetCapacityPins->ulUserChipId; ++ ++ /* First put the chip and main registers in soft-reset. */ ++ WriteParams.ulWriteAddress = 0x100; ++ WriteParams.usWriteData = 0x0; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulFc2PllDivisor = 0x1050; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ ++ /* Setup delay chains. */ ++ if ( (f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR) || (f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) ++ { ++ /* SDRAM */ ++ WriteParams.ulWriteAddress = 0x1B0; ++ WriteParams.usWriteData = 0x1003; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B2; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B4; ++ WriteParams.usWriteData = 0x4030; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B6; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else /* if ( cOCT6100_MEM_TYPE_DDR == pChipConfig->byMemoryType ) */ ++ { ++ /* DDR */ ++ WriteParams.ulWriteAddress = 0x1B0; ++ WriteParams.usWriteData = 0x201F; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B2; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B4; ++ WriteParams.usWriteData = 0x1000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B6; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* udqs */ ++ WriteParams.ulWriteAddress = 0x1B8; ++ WriteParams.usWriteData = 0x1003; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1BA; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* ldqs */ ++ WriteParams.ulWriteAddress = 0x1BC; ++ WriteParams.usWriteData = 0x1000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1BE; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x12C; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x12E; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Select fc2pll for fast_clk and mtsclk sources. Select mem_clk_i for afclk. */ ++ WriteParams.ulWriteAddress = 0x140; ++ WriteParams.usWriteData = (UINT16)ulMtDivisor; ++ ++ if ( f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ WriteParams.usWriteData |= 0x0001; ++ else ++ WriteParams.usWriteData |= 0x0004; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x144; ++ WriteParams.usWriteData = (UINT16)ulFcDivisor; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x13E; ++ WriteParams.usWriteData = 0x0001; /* Remove reset from above divisors */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Select upclk directly as ref source for fc2pll. */ ++ WriteParams.ulWriteAddress = 0x134; ++ WriteParams.usWriteData = 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Setup fc2pll. */ ++ WriteParams.ulWriteAddress = 0x132; ++ WriteParams.usWriteData = (UINT16)ulFc2PllDivisor; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.usWriteData |= 0x02; /* Raise fb divisor reset. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.usWriteData |= 0x80; /* Raise IDDTN signal.*/ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Wait for fc2pll to stabilize. */ ++ aulWaitTime[ 0 ] = 2000; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Drive mem_clk_o out on proper interface. */ ++ if ( TRUE == f_pGetCapacityPins->fEnableMemClkOut ) ++ { ++ if ( (f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR) || (f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) ++ { ++ WriteParams.ulWriteAddress = 0x128; ++ WriteParams.usWriteData = 0x0301; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_DDR || f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ { ++ WriteParams.ulWriteAddress = 0x12A; ++ WriteParams.usWriteData = 0x000F; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBootFc2Pll ++ ++Description: Configures the chip's FC2 PLL. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBootFc2Pll ++UINT32 Oct6100ApiBootFc2Pll( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 aulWaitTime[ 2 ]; ++ UINT32 ulResult; ++ UINT32 ulFc2PllDivisor = 0; ++ UINT32 ulMtDivisor = 0; ++ UINT32 ulFcDivisor = 0; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain local pointer to chip configuration structure. */ ++ pChipConfig = &pSharedInfo->ChipConfig; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pChipConfig->ulUserChipId; ++ ++ /* First put the chip and main registers in soft-reset. */ ++ WriteParams.ulWriteAddress = 0x100; ++ WriteParams.usWriteData = 0x0; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Select register configuration based on the memory frequency. */ ++ switch ( f_pApiInstance->pSharedInfo->ChipConfig.ulMemClkFreq ) ++ { ++ case 133000000: ++ ulFc2PllDivisor = 0x1050; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 672; ++ pSharedInfo->MiscVars.usMaxH100Speed = 124; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x050B; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0516; ++ ++ break; ++ case 125000000: ++ ulFc2PllDivisor = 0x0F50; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 624; ++ pSharedInfo->MiscVars.usMaxH100Speed = 116; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x04CA; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x04D4; ++ ++ break; ++ case 117000000: ++ ulFc2PllDivisor = 0x0E50; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 576; ++ pSharedInfo->MiscVars.usMaxH100Speed = 108; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0489; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0492; ++ ++ break; ++ case 108000000: ++ ulFc2PllDivisor = 0x0D50; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 528; ++ pSharedInfo->MiscVars.usMaxH100Speed = 99; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0408; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0410; ++ ++ break; ++ case 100000000: ++ ulFc2PllDivisor = 0x0C50; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 480; ++ pSharedInfo->MiscVars.usMaxH100Speed = 91; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x03C8; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x03D0; ++ ++ break; ++ case 92000000: ++ ulFc2PllDivisor = 0x0B50; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 432; ++ pSharedInfo->MiscVars.usMaxH100Speed = 83; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0387; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x038E; ++ ++ break; ++ case 83000000: ++ ulFc2PllDivisor = 0x0A50; ++ ulMtDivisor = 0x4300; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 384; ++ pSharedInfo->MiscVars.usMaxH100Speed = 74; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0346; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x034C; ++ ++ break; ++ case 75000000: ++ ulFc2PllDivisor = 0x0950; ++ ulMtDivisor = 0x4200; ++ ulFcDivisor = 0x4043; ++ pSharedInfo->MiscVars.usMaxNumberOfChannels = 336; ++ pSharedInfo->MiscVars.usMaxH100Speed = 64; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x0306; ++ else ++ pSharedInfo->MiscVars.usTdmClkBoundary = 0x030C; ++ ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_DB; ++ } ++ ++ /* Verify that the max channel is not too big based on the chip frequency. */ ++ if ( pSharedInfo->ChipConfig.usMaxChannels > pSharedInfo->MiscVars.usMaxNumberOfChannels ) ++ return cOCT6100_ERR_OPEN_MAX_ECHO_CHANNELS; ++ ++ /* Setup delay chains. */ ++ if ( (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) ++ { ++ /* SDRAM */ ++ WriteParams.ulWriteAddress = 0x1B0; ++ WriteParams.usWriteData = 0x1003; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B2; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B4; ++ WriteParams.usWriteData = 0x4030; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B6; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else /* if ( cOCT6100_MEM_TYPE_DDR == pChipConfig->byMemoryType ) */ ++ { ++ /* DDR */ ++ WriteParams.ulWriteAddress = 0x1B0; ++ WriteParams.usWriteData = 0x201F; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B2; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B4; ++ WriteParams.usWriteData = 0x1000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1B6; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* udqs */ ++ WriteParams.ulWriteAddress = 0x1B8; ++ WriteParams.usWriteData = 0x1003; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1BA; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* ldqs */ ++ WriteParams.ulWriteAddress = 0x1BC; ++ WriteParams.usWriteData = 0x1000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x1BE; ++ WriteParams.usWriteData = 0x0021; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x12C; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x12E; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Select fc2pll for fast_clk and mtsclk sources. Select mem_clk_i for afclk. */ ++ WriteParams.ulWriteAddress = 0x140; ++ WriteParams.usWriteData = (UINT16)ulMtDivisor; ++ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ WriteParams.usWriteData |= 0x0001; ++ else ++ WriteParams.usWriteData |= 0x0004; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x144; ++ WriteParams.usWriteData = (UINT16)ulFcDivisor; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x13E; ++ WriteParams.usWriteData = 0x0001; /* Remove reset from above divisors */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Select upclk directly as ref source for fc2pll. */ ++ WriteParams.ulWriteAddress = 0x134; ++ WriteParams.usWriteData = 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Setup fc2pll. */ ++ WriteParams.ulWriteAddress = 0x132; ++ WriteParams.usWriteData = (UINT16)ulFc2PllDivisor; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.usWriteData |= 0x02; /* Raise fb divisor reset. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.usWriteData |= 0x80; /* Raise IDDTN signal.*/ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Wait for fc2pll to stabilize. */ ++ aulWaitTime[ 0 ] = 2000; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Drive mem_clk_o out on proper interface. */ ++ if ( TRUE == pChipConfig->fEnableMemClkOut ) ++ { ++ if ( (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) ++ { ++ WriteParams.ulWriteAddress = 0x128; ++ WriteParams.usWriteData = 0x0301; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_DDR || pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ { ++ WriteParams.ulWriteAddress = 0x12A; ++ WriteParams.usWriteData = 0x000F; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiProgramFc1PllReadCap ++ ++Description: Configures the chip's FC1 PLL. Special version for getCapacityPins. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++UINT32 Oct6100ApiProgramFc1PllReadCap( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 aulWaitTime[ 2 ]; ++ UINT32 ulResult; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pGetCapacityPins->ulUserChipId; ++ ++ /* Programm P/Z bits. */ ++ WriteParams.ulWriteAddress = 0x130; ++ ++ if ( f_pGetCapacityPins->ulMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ WriteParams.usWriteData = 0x0041; ++ else ++ WriteParams.usWriteData = 0x0040; ++ ++ WriteParams.usWriteData |= ( f_pGetCapacityPins->ulMemoryType << 8 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Raise FB divisor. */ ++ WriteParams.usWriteData |= 0x0002; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Raise IDDTN. */ ++ WriteParams.usWriteData |= 0x0080; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Wait for fc1pll to stabilize. */ ++ aulWaitTime[ 0 ] = 2000; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Enable all the clock domains to do reset procedure. */ ++ WriteParams.ulWriteAddress = 0x186; ++ WriteParams.usWriteData = 0x015F; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ aulWaitTime[ 0 ] = 15000; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiProgramFc1Pll ++ ++Description: Configures the chip's FC1 PLL. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiProgramFc1Pll ++UINT32 Oct6100ApiProgramFc1Pll( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 aulWaitTime[ 2 ]; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain local pointer to chip configuration structure. */ ++ pChipConfig = &pSharedInfo->ChipConfig; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pChipConfig->ulUserChipId; ++ ++ /* Programm P/Z bits. */ ++ WriteParams.ulWriteAddress = 0x130; ++ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) ++ WriteParams.usWriteData = 0x0041; ++ else ++ WriteParams.usWriteData = 0x0040; ++ ++ WriteParams.usWriteData |= ( pChipConfig->byMemoryType << 8 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Raise FB divisor. */ ++ WriteParams.usWriteData |= 0x0002; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Raise IDDTN. */ ++ WriteParams.usWriteData |= 0x0080; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Wait for fc1pll to stabilize. */ ++ aulWaitTime[ 0 ] = 2000; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Enable all the clock domains to do reset procedure. */ ++ WriteParams.ulWriteAddress = 0x186; ++ WriteParams.usWriteData = 0x015F; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ aulWaitTime[ 0 ] = 15000; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBootFc1Pll ++ ++Description: Boot the chip's FC1 PLL. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBootFc1Pll ++UINT32 Oct6100ApiBootFc1Pll( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 aulWaitTime[ 2 ]; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain local pointer to chip configuration structure. */ ++ pChipConfig = &pSharedInfo->ChipConfig; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pChipConfig->ulUserChipId; ++ ++ /* Force bist_clk also (it too is used on resetable flops). */ ++ WriteParams.ulWriteAddress = 0x160; ++ WriteParams.usWriteData = 0x0188; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Force all cpu clocks on chariot controllers. */ ++ WriteParams.ulWriteAddress = 0x182; ++ WriteParams.usWriteData = 0x0002; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x184; ++ WriteParams.usWriteData = 0x0202; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ aulWaitTime[ 0 ] = 1000; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Remove the reset on the entire chip and disable CPU access caching. */ ++ WriteParams.ulWriteAddress = 0x100; ++ WriteParams.usWriteData = 0x2003; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Remove the bist_clk. It is no longer needed.*/ ++ WriteParams.ulWriteAddress = 0x160; ++ WriteParams.usWriteData = 0x0088; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Disable all clks to prepare for bist clock switchover. */ ++ WriteParams.ulWriteAddress = 0x182; ++ WriteParams.usWriteData = 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x186; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x184; ++ WriteParams.usWriteData = 0x0101; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Deassert bist_active */ ++ WriteParams.ulWriteAddress = 0x160; ++ WriteParams.usWriteData = 0x0008; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Change CPU interface to normal mode (from boot mode). */ ++ WriteParams.ulWriteAddress = 0x154; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Give a couple of BIST clock cycles to turn off the BIST permanently. */ ++ WriteParams.ulWriteAddress = 0x160; ++ WriteParams.usWriteData = 0x0108; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Turn BIST clock off for the last time. */ ++ WriteParams.ulWriteAddress = 0x160; ++ WriteParams.usWriteData = 0x0008; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reset procedure done! */ ++ ++ /* Enable mclk for cpu interface and external memory controller. */ ++ WriteParams.ulWriteAddress = 0x186; ++ WriteParams.usWriteData = 0x0100; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiLoadImage ++ ++Description: This function writes the firmware image in the external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiLoadImage ++UINT32 Oct6100ApiLoadImage( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_BURST_PARAMS BurstParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT32 ulTempPtr; ++ UINT32 ulNumWrites; ++ PUINT16 pusSuperArray; ++ unsigned char const *pbyImageFile; ++ UINT32 ulByteCount = 0; ++ UINT16 usReadData; ++ UINT32 ulAddressOfst; ++ UINT32 i; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Breakdown image into subcomponents. */ ++ ulTempPtr = cOCT6100_IMAGE_FILE_BASE + cOCT6100_IMAGE_AF_CST_OFFSET; ++ ++ for(i=0;iImageRegion[ i ].ulPart1Size = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 0 ]; ++ pSharedInfo->ImageRegion[ i ].ulPart2Size = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 1 ]; ++ pSharedInfo->ImageRegion[ i ].ulClockInfo = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 2 ]; ++ pSharedInfo->ImageRegion[ i ].ulReserved = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 3 ]; ++ ++ if (i == 0) /* AF constant. */ ++ { ++ pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF; ++ pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = 0; ++ ++ ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 612 ); ++ } ++ else if (i == 1) /* NLP image */ ++ { ++ pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF; ++ pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = 0; ++ ++ ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 2056 ); ++ } ++ else /* Others */ ++ { ++ pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF; ++ ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 2064 ); ++ ++ pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = ulTempPtr & 0x07FFFFFF; ++ ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart2Size * 2448 ); ++ } ++ } ++ ++ /* Write the image in external memory. */ ++ ulNumWrites = pSharedInfo->ChipConfig.ulImageSize / 2; ++ ++ BurstParams.ulWriteAddress = cOCT6100_IMAGE_FILE_BASE; ++ BurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray; ++ ++ pusSuperArray = pSharedInfo->MiscVars.ausSuperArray; ++ pbyImageFile = pSharedInfo->ChipConfig.pbyImageFile; ++ ++ while ( ulNumWrites != 0 ) ++ { ++ if ( ulNumWrites >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ BurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ else ++ BurstParams.ulWriteLength = ulNumWrites; ++ ++ for ( i = 0; i < BurstParams.ulWriteLength; i++ ) ++ { ++ pusSuperArray[ i ] = ( UINT16 )(( pbyImageFile [ ulByteCount++ ]) << 8); ++ pusSuperArray[ i ] |= ( UINT16 )pbyImageFile [ ulByteCount++ ]; ++ } ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ BurstParams.ulWriteAddress += 2 * BurstParams.ulWriteLength; ++ ulNumWrites -= BurstParams.ulWriteLength; ++ } ++ ++ /* Perform a serie of reads to make sure the image was correclty written into memory. */ ++ ulAddressOfst = ( pSharedInfo->ChipConfig.ulImageSize / 2 ) & 0xFFFFFFFE; ++ while ( ulAddressOfst != 0 ) ++ { ++ ReadParams.ulReadAddress = cOCT6100_IMAGE_FILE_BASE + ulAddressOfst; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( (usReadData >> 8) != pbyImageFile[ ulAddressOfst ] ) ++ return cOCT6100_ERR_OPEN_IMAGE_WRITE_FAILED; ++ ++ ulAddressOfst = (ulAddressOfst / 2) & 0xFFFFFFFE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCpuRegisterBistReadCap ++ ++Description: Tests the operation of the CPU registers. Special Version for ++ GetCapacityPins ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++UINT32 Oct6100ApiCpuRegisterBistReadCap( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins ++ ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT16 i; ++ UINT16 usReadData; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pGetCapacityPins->ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pGetCapacityPins->ulUserChipId; ++ ++ /* Assign read data pointer that will be used throughout the function. */ ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Start with a walking bit test. */ ++ for ( i = 0; i < 16; i ++ ) ++ { ++ /* Write at address 0x150.*/ ++ WriteParams.ulWriteAddress = 0x150; ++ WriteParams.usWriteData = (UINT16)( 0x1 << i ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write at address 0x180.*/ ++ WriteParams.ulWriteAddress = 0x180; ++ WriteParams.usWriteData = (UINT16)( 0x1 << ( 15 - i ) ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now read back the two registers to make sure the acceses were successfull. */ ++ ReadParams.ulReadAddress = 0x150; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != ( 0x1 << i ) ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ ++ ReadParams.ulReadAddress = 0x180; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != ( 0x1 << ( 15 - i ) ) ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ } ++ ++ /* Write at address 0x150. */ ++ WriteParams.ulWriteAddress = 0x150; ++ WriteParams.usWriteData = 0xCAFE; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write at address 0x180. */ ++ WriteParams.ulWriteAddress = 0x180; ++ WriteParams.usWriteData = 0xDECA; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now read back the two registers to make sure the acceses were successfull. */ ++ ReadParams.ulReadAddress = 0x150; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != 0xCAFE ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ ++ ReadParams.ulReadAddress = 0x180; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != 0xDECA ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ ++ return cOCT6100_ERR_OK; ++} ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCpuRegisterBist ++ ++Description: Tests the operation of the CPU registers. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCpuRegisterBist ++UINT32 Oct6100ApiCpuRegisterBist( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT16 i; ++ UINT16 usReadData; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Assign read data pointer that will be used throughout the function. */ ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Start with a walking bit test. */ ++ for ( i = 0; i < 16; i ++ ) ++ { ++ /* Write at address 0x150.*/ ++ WriteParams.ulWriteAddress = 0x150; ++ WriteParams.usWriteData = (UINT16)( 0x1 << i ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write at address 0x180.*/ ++ WriteParams.ulWriteAddress = 0x180; ++ WriteParams.usWriteData = (UINT16)( 0x1 << ( 15 - i ) ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now read back the two registers to make sure the acceses were successfull. */ ++ ReadParams.ulReadAddress = 0x150; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != ( 0x1 << i ) ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ ++ ReadParams.ulReadAddress = 0x180; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != ( 0x1 << ( 15 - i ) ) ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ } ++ ++ /* Write at address 0x150. */ ++ WriteParams.ulWriteAddress = 0x150; ++ WriteParams.usWriteData = 0xCAFE; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write at address 0x180. */ ++ WriteParams.ulWriteAddress = 0x180; ++ WriteParams.usWriteData = 0xDECA; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now read back the two registers to make sure the acceses were successfull. */ ++ ReadParams.ulReadAddress = 0x150; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != 0xCAFE ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ ++ ReadParams.ulReadAddress = 0x180; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != 0xDECA ) ++ return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBootSdram ++ ++Description: Configure and test the SDRAM. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBootSdram ++UINT32 Oct6100ApiBootSdram( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ UINT16 usWriteData23E; ++ UINT16 usWriteData230; ++ UINT32 i; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get local pointer to the chip configuration structure.*/ ++ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ usWriteData23E = 0x0000; ++ usWriteData230 = 0x0000; ++ ++ if ( (pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) ++ { ++ /* SDRAM: */ ++ switch( pChipConfig->ulMemoryChipSize ) ++ { ++ case cOCT6100_MEMORY_CHIP_SIZE_8MB: ++ usWriteData230 |= ( cOCT6100_16MB_MEMORY_BANKS << 2 ); ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_16MB: ++ usWriteData230 |= ( cOCT6100_32MB_MEMORY_BANKS << 2 ); ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_32MB: ++ usWriteData230 |= ( cOCT6100_64MB_MEMORY_BANKS << 2 ); ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_64MB: ++ usWriteData230 |= ( cOCT6100_128MB_MEMORY_BANKS << 2 ); ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_16; ++ } ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Precharge all banks. */ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0010; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Program the mode register. */ ++ usWriteData23E = 0x0030; ++ WriteParams.usWriteData = usWriteData23E; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0000; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Do CBR refresh (twice) */ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0040; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else ++ { ++ /* DDR: */ ++ switch( pChipConfig->ulMemoryChipSize ) ++ { ++ case cOCT6100_MEMORY_CHIP_SIZE_16MB: ++ usWriteData230 |= ( cOCT6100_16MB_MEMORY_BANKS << 2 ); ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_32MB: ++ usWriteData230 |= ( cOCT6100_32MB_MEMORY_BANKS << 2 ); ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_64MB: ++ usWriteData230 |= ( cOCT6100_64MB_MEMORY_BANKS << 2 ); ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_128MB: ++ usWriteData230 |= ( cOCT6100_128MB_MEMORY_BANKS << 2 ); ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_17; ++ } ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Precharge all banks. */ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0010; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Program DDR mode register. */ ++ usWriteData23E = 0x4000; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0000; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Program SDR mode register. */ ++ usWriteData23E = 0x0161; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0000; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Precharge all banks. */ ++ usWriteData23E = 0xFFFF; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0010; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Do CBR refresh (twice) */ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0040; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle.*/ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Program SDR mode register. */ ++ usWriteData23E = 0x0061; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0000; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ usWriteData230 |= 0x0002; ++ ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x23E; ++ WriteParams.usWriteData = usWriteData23E; ++ for ( i = 0; i < 5; i++ ) ++ { ++ /* Wait cycle. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the refresh frequency. */ ++ WriteParams.ulWriteAddress = 0x242; ++ WriteParams.usWriteData = 0x0400; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x244; ++ WriteParams.usWriteData = 0x0200; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x248; ++ WriteParams.usWriteData = 0x800; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x246; ++ WriteParams.usWriteData = 0x0012; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Enable the SDRAM and refreshes. */ ++ usWriteData230 &= 0x000C; ++ usWriteData230 |= 0x0001; ++ ++ WriteParams.ulWriteAddress = 0x230; ++ WriteParams.usWriteData = usWriteData230; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x246; ++ WriteParams.usWriteData = 0x0013; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiEnableClocks ++ ++Description: This function will disable clock masking for all the modules ++ of the chip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiEnableClocks ++UINT32 Oct6100ApiEnableClocks( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Initialize the process context and user chip ID once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Enable tdmie / adpcm mclk clocks. */ ++ WriteParams.ulWriteAddress = 0x186; ++ WriteParams.usWriteData = 0x015F; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Configure the DQS register for the DDR memory */ ++ WriteParams.ulWriteAddress = 0x180; ++ WriteParams.usWriteData = 0xFF00; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Enable pgsp chariot clocks */ ++ WriteParams.ulWriteAddress = 0x182; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Enable af/mt chariot clocks */ ++ WriteParams.ulWriteAddress = 0x184; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiProgramNLP ++ ++Description: This function will write image values to configure the NLP. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiProgramNLP ++UINT32 Oct6100ApiProgramNLP( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ UINT16 usReadHighData; ++ BOOL fBitEqual; ++ UINT32 ulEgoEntry[4]; ++ UINT32 ulTempAddress; ++ UINT32 ulAfCpuUp = FALSE; ++ UINT32 i; ++ UINT32 ulLoopCounter = 0; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get local pointer to the chip configuration structure.*/ ++ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; ++ ++ /* Initialize the process context and user chip ID once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Initialize the process context and user chip ID once and for all. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) ++ { ++ UINT32 ulReadData; ++ UINT32 ulBitPattern; ++ UINT32 j, k; ++ ++ /* Since the pouch section (256 bytes) will not be tested by the firmware, */ ++ /* the API has to make sure this section is working correctly. */ ++ for ( k = 0; k < 2; k ++ ) ++ { ++ if ( k == 0 ) ++ ulBitPattern = 0x1; ++ else ++ ulBitPattern = 0xFFFFFFFE; ++ ++ for ( j = 0; j < 32; j ++ ) ++ { ++ /* Write the DWORDs. */ ++ for ( i = 0; i < 64; i ++ ) ++ { ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + i * 4, ulBitPattern << j ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Read the DWORDs. */ ++ for ( i = 0; i < 64; i ++ ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + i * 4, &ulReadData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the value matches. */ ++ if ( ( ulBitPattern << j ) != ulReadData ) ++ return cOCT6100_ERR_OPEN_PRODUCTION_BIST_POUCH_ERROR; ++ } ++ } ++ } ++ } ++ ++ /* Write the image info in the chip. */ ++ WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE; ++ WriteParams.usWriteData = (UINT16)( ( pSharedInfo->ImageRegion[ 0 ].ulPart1BaseAddress >> 16 ) & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ 0 ].ulPart1BaseAddress & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ for( i = 0; i < 8; i++ ) ++ { ++ if ( pSharedInfo->ImageRegion[ i + 2 ].ulPart1Size != 0 ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ); ++ WriteParams.usWriteData = (UINT16)(( pSharedInfo->ImageRegion[ i + 2 ].ulPart1BaseAddress >> 16 ) & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ i + 2 ].ulPart1BaseAddress & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pSharedInfo->ImageRegion[ i + 2 ].ulPart2Size != 0 ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ) + 4; ++ WriteParams.usWriteData = (UINT16)(( pSharedInfo->ImageRegion[ i + 2 ].ulPart2BaseAddress >> 16 ) & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ i + 2 ].ulPart2BaseAddress & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ) + 8; ++ WriteParams.usWriteData = 0x0000; ++ WriteParams.usWriteData |= ( pSharedInfo->ImageRegion[ i + 2 ].ulPart1Size << 8 ); ++ WriteParams.usWriteData |= pSharedInfo->ImageRegion[ i + 2 ].ulPart2Size; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = 0x0000; ++ WriteParams.usWriteData |= ( pSharedInfo->ImageRegion[ i + 2 ].ulClockInfo << 8 ); ++ WriteParams.usWriteData |= pSharedInfo->ImageRegion[ i + 2 ].ulReserved; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Put NLP in config mode. */ ++ WriteParams.ulWriteAddress = 0x2C2; ++ WriteParams.usWriteData = 0x160E; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x692; ++ WriteParams.usWriteData = 0x010A; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Upload the up to 8 NLP pages + 1 AF page (for timing reasons). */ ++ for ( i = 0; i < pSharedInfo->ImageRegion[ 1 ].ulPart1Size; i++ ) ++ { ++ ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 1 ].ulPart1BaseAddress + 1028 * ( i * 2 ), 0x1280, 1024, &(ulEgoEntry[0])); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 1 ].ulPart1BaseAddress + 1028 * (( i * 2 ) + 1 ), 0x1680, 1024, &(ulEgoEntry[2])); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Shift mt chariot memories. This process will complete by the time */ ++ /* the next LSU transfer is done. */ ++ WriteParams.ulWriteAddress = 0x692; ++ WriteParams.usWriteData = 0x010B; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiWaitForPcRegisterBit( f_pApiInstance, 0x692, 0, 0, 100000, &fBitEqual ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ if ( TRUE != fBitEqual ) ++ return cOCT6100_ERR_FATAL_1A; ++ } ++ ++ /* 1 AF page (for timing reasons). */ ++ ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 0), 0x1280, 512, &(ulEgoEntry[0])); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 1), 0x1480, 512, &(ulEgoEntry[2])); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 2), 0x1680, 512, &(ulEgoEntry[0])); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 3), 0x1880, 512, &(ulEgoEntry[2])); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write constant memory init context position in channel "672" for pgsp. */ ++ WriteParams.ulWriteAddress = 0x71A; ++ WriteParams.usWriteData = 0x8000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set fixed PGSP event_in base address to 800 on a 2k boundary */ ++ WriteParams.ulWriteAddress = 0x716; ++ WriteParams.usWriteData = 0x800 >> 11; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set fixed PGSP event_out to 0x2C0000h on a 16k boundary */ ++ WriteParams.ulWriteAddress = 0x71C; ++ WriteParams.usWriteData = 0x2C0000 >> 14; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Give chariot control of the chip. */ ++ WriteParams.ulWriteAddress = 0x712; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x2C0000 + 0xC; ++ ulTempAddress = 0x300000 + 0x0800; ++ WriteParams.usWriteData = (UINT16)( ( ulTempAddress >> 16 ) & 0x07FF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x2C0000 + 0xE; ++ WriteParams.usWriteData = (UINT16)( ( ulTempAddress >> 0 ) & 0xFF00 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write the init PGSP event in place. */ ++ WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x800; ++ WriteParams.usWriteData = 0x0200; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x802; ++ WriteParams.usWriteData = 0x02A0; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Also write the register 710, which tells PGSP how many tones are supported. */ ++ WriteParams.ulWriteAddress = 0x710; ++ WriteParams.usWriteData = 0x0000; ++ WriteParams.usWriteData |= pChipConfig->pbyImageFile[ 0x7FA ] << 8; ++ WriteParams.usWriteData |= pChipConfig->pbyImageFile[ 0x7FB ] << 0; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Start both processors in the NLP. */ ++ WriteParams.ulWriteAddress = 0x373FE; ++ WriteParams.usWriteData = 0x00FF; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x37BFE; ++ WriteParams.usWriteData = 0x00FE; /* Tell processor 1 to just go to sleep. */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x37FC6; ++ WriteParams.usWriteData = 0x8004; /* First PC.*/ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x37FD0; ++ WriteParams.usWriteData = 0x0002; /* Take out of reset. */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x37FD2; ++ WriteParams.usWriteData = 0x0002; /* Take out of reset. */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Start processor in the AF. */ ++ for ( i = 0; i < 16; i ++ ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_POUCH_BASE + ( i * 2 ); ++ if ( i == 9 ) ++ { ++ if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) ++ { ++ if (pSharedInfo->ChipConfig.ulProductionBistMode == cOCT6100_PRODUCTION_BIST_SHORT) ++ WriteParams.usWriteData = cOCT6100_PRODUCTION_SHORT_BOOT_TYPE; ++ else ++ WriteParams.usWriteData = cOCT6100_PRODUCTION_BOOT_TYPE; ++ } ++ else ++ { ++ WriteParams.usWriteData = cOCT6100_AF_BOOT_TYPE; ++ } ++ } ++ else ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Check if the production BIST mode was requested. */ ++ if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) ++ { ++ UINT32 ulTotalElements = 3; ++ UINT32 ulCrcKey; ++ UINT32 aulMessage[ 4 ]; ++ UINT32 ulWriteAddress = 0x20 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; ++ ++ /* Magic key. */ ++ aulMessage[ 0 ] = 0xCAFECAFE; ++ /* Memory size. */ ++ aulMessage[ 1 ] = pSharedInfo->MiscVars.ulTotalMemSize; ++ /* Loop count. */ ++ aulMessage[ 2 ] = pSharedInfo->ChipConfig.ulNumProductionBistLoops; ++ /* CRC initialized. */ ++ aulMessage[ 3 ] = 0; ++ ++ ulResult = Oct6100ApiProductionCrc( f_pApiInstance, aulMessage, ulTotalElements, &ulCrcKey ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ aulMessage[ 3 ] = ulCrcKey; ++ ++ /* Write the message to the external memory. */ ++ for ( i = 0; i < ulTotalElements + 1; i ++ ) ++ { ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulWriteAddress + i * 4, aulMessage[ i ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ WriteParams.ulWriteAddress = 0xFFFC6; ++ WriteParams.usWriteData = 0x1284; /* First PC.*/ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0xFFFD0; ++ WriteParams.usWriteData = 0x0002; /* Take out of reset. */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ while ( ulAfCpuUp == FALSE ) ++ { ++ if ( ulAfCpuUp == FALSE ) ++ { ++ ReadParams.ulReadAddress = cOCT6100_POUCH_BASE; ++ ReadParams.pusReadData = &usReadHighData; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ReadParams.ulReadAddress += 2; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) ++ { ++ /* Should read 0x0007 when bisting. */ ++ if ( (( usReadHighData & 0xFFFF ) == cOCT6100_PRODUCTION_BOOT_TYPE) || ++ (( usReadHighData & 0xFFFF ) == cOCT6100_PRODUCTION_SHORT_BOOT_TYPE) ) ++ { ++ /* Verify if the bist has started successfully. */ ++ if ( ( usReadData & 0xFFFF ) == 0x0002 ) ++ return cOCT6100_ERR_OPEN_PRODUCTION_BIST_CONF_FAILED; ++ else if ( ( usReadData & 0xFFFF ) != 0xEEEE ) ++ return cOCT6100_ERR_OPEN_PRODUCTION_BOOT_FAILED; ++ ++ ulAfCpuUp = TRUE; ++ } ++ } ++ else /* if ( pSharedInfo->ChipConfig.fEnableProductionBist == FALSE ) */ ++ { ++ if ( ( usReadHighData & 0xFFFF ) == cOCT6100_AF_BOOT_TYPE ) ++ { ++ /* Verify if the bist succeeded. */ ++ if ( ( usReadData & 0xFFFF ) != 0x0000 ) ++ return cOCT6100_ERR_OPEN_FUNCTIONAL_BIST_FAILED; ++ ++ ulAfCpuUp = TRUE; ++ } ++ } ++ } ++ ++ ulLoopCounter++; ++ ++ if ( ulLoopCounter == cOCT6100_MAX_LOOP_CPU_TIMEOUT ) ++ return cOCT6100_ERR_OPEN_AF_CPU_TIMEOUT; ++ } ++ ++ /* Return NLP in operationnal mode. */ ++ WriteParams.ulWriteAddress = 0x2C2; ++ WriteParams.usWriteData = 0x060E; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x692; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiSetH100Register ++ ++Description: This function will configure the H.100 registers. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiSetH100Register ++UINT32 Oct6100ApiSetH100Register( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ UINT32 i; ++ UINT32 ulOffset; ++ BOOL fAllStreamAt2Mhz = TRUE; ++ const UINT16 ausAdpcmResetContext[32] = { 0x1100, 0x0220, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0100, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0040, ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0010, 0x0000, 0x0000, 0x0000}; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get local pointer to the chip configuration structure. */ ++ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; ++ ++ /* Initialize the process context and user chip ID once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Set the Global OE bit. */ ++ WriteParams.ulWriteAddress = 0x300; ++ WriteParams.usWriteData = 0x0004; ++ ++ /* Set the number of streams. */ ++ switch( pChipConfig->byMaxTdmStreams ) ++ { ++ case 32: ++ WriteParams.usWriteData |= ( 0 << 3 ); ++ break; ++ case 16: ++ WriteParams.usWriteData |= ( 1 << 3 ); ++ break; ++ case 8: ++ WriteParams.usWriteData |= ( 2 << 3 ); ++ break; ++ case 4: ++ WriteParams.usWriteData |= ( 3 << 3 ); ++ break; ++ default: ++ break; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Configure the stream frequency. */ ++ WriteParams.ulWriteAddress = 0x330; ++ WriteParams.usWriteData = 0x0000; ++ for ( i = 0; i < (UINT32)(pChipConfig->byMaxTdmStreams / 4); i++) ++ { ++ ulOffset = i*2; ++ switch( pChipConfig->aulTdmStreamFreqs[ i ] ) ++ { ++ case cOCT6100_TDM_STREAM_FREQ_2MHZ: ++ WriteParams.usWriteData |= ( 0x0 << ulOffset ); ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_4MHZ: ++ WriteParams.usWriteData |= ( 0x1 << ulOffset ); ++ fAllStreamAt2Mhz = FALSE; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_8MHZ: ++ WriteParams.usWriteData |= ( 0x2 << ulOffset ); ++ fAllStreamAt2Mhz = FALSE; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ /* Set the stream to 16 MHz if the fast H.100 mode is selected. */ ++ if ( pChipConfig->fEnableFastH100Mode == TRUE ) ++ { ++ fAllStreamAt2Mhz = FALSE; ++ WriteParams.usWriteData = 0xFFFF; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ { ++ /* Make the chip track both clock A and B to perform fast H.100 mode. */ ++ WriteParams.ulWriteAddress = 0x322; ++ WriteParams.usWriteData = 0x0004; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Enable the fast H.100 mode. */ ++ WriteParams.ulWriteAddress = 0x332; ++ WriteParams.usWriteData = 0x0003; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ WriteParams.ulWriteAddress = 0x376; ++ WriteParams.usWriteData = (UINT16)( pSharedInfo->MiscVars.usTdmClkBoundary ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Select delay for early clock (90 and 110). */ ++ WriteParams.ulWriteAddress = 0x378; ++ if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ WriteParams.usWriteData = 0x000A; ++ else ++ { ++ /* Set the TDM sampling. */ ++ if ( pSharedInfo->ChipConfig.byTdmSampling == cOCT6100_TDM_SAMPLE_AT_RISING_EDGE ) ++ { ++ WriteParams.usWriteData = 0x0AF0; ++ } ++ else if ( pSharedInfo->ChipConfig.byTdmSampling == cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE ) ++ { ++ WriteParams.usWriteData = 0x0A0F; ++ } ++ else /* pSharedInfo->ChipConfig.ulTdmSampling == cOCT6100_TDM_SAMPLE_AT_3_QUARTERS */ ++ { ++ WriteParams.usWriteData = 0x0A08; ++ } ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Protect chip by preventing too rapid timeslot arrival (mclk == 133 MHz). */ ++ WriteParams.ulWriteAddress = 0x37A; ++ WriteParams.usWriteData = (UINT16)pSharedInfo->MiscVars.usMaxH100Speed; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Allow H.100 TS to progress. */ ++ WriteParams.ulWriteAddress = 0x382; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set by-pass mode. */ ++ WriteParams.ulWriteAddress = 0x50E; ++ WriteParams.usWriteData = 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* TDMIE bits. */ ++ WriteParams.ulWriteAddress = 0x500; ++ WriteParams.usWriteData = 0x0003; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write normal ADPCM reset values in ADPCM context 1344. */ ++ for(i=0;i<32;i++) ++ { ++ WriteParams.ulWriteAddress = 0x140000 + ( 0x40 * 1344 ) + ( i * 2 ); ++ WriteParams.usWriteData = ausAdpcmResetContext[i]; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Make sure delay flops are configured correctly if all streams are at 2 MHz. */ ++ if ( fAllStreamAt2Mhz == TRUE ) ++ { ++ /* Setup H.100 sampling to lowest value. */ ++ WriteParams.ulWriteAddress = 0x144; ++ WriteParams.usWriteData = 0x4041; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x378; ++ WriteParams.usWriteData = 0x0A00; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteMiscellaneousRegisters ++ ++Description: This function will write to various registers to activate the chip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteMiscellaneousRegisters ++UINT32 Oct6100ApiWriteMiscellaneousRegisters( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Initialize the process context and user chip ID once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Free the interrupt pin of the chip (i.e. remove minimum time requirement between interrupts). */ ++ WriteParams.ulWriteAddress = 0x214; ++ WriteParams.usWriteData = 0x0000; ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.byInterruptPolarity == cOCT6100_ACTIVE_HIGH_POLARITY ) ++ WriteParams.usWriteData |= 0x4000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write MT chariot interval */ ++ WriteParams.ulWriteAddress = 0x2C2; ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels > 640 ) ++ WriteParams.usWriteData = 0x05EA; ++ else if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels > 513 ) ++ WriteParams.usWriteData = 0x0672; ++ else /* if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels <= 513 ) */ ++ WriteParams.usWriteData = 0x0750; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write set second part5 time. */ ++ WriteParams.ulWriteAddress = 0x2C4; ++ WriteParams.usWriteData = 0x04A0; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write CPU bucket timer to guarantee 200 cycles between each CPU access. */ ++ WriteParams.ulWriteAddress = 0x234; ++ WriteParams.usWriteData = 0x0804; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x236; ++ WriteParams.usWriteData = 0x0100; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCreateSerializeObjects ++ ++Description: Creates a handle to each serialization object used by the API. ++ ++ Note that in a multi-process system the user's process context ++ structure pointer is needed by this function. Thus, the ++ pointer must be valid. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulUserChipId User chip ID for this serialization object. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCreateSerializeObjects ++UINT32 Oct6100ApiCreateSerializeObjects( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulUserChipId ) ++{ ++ tOCT6100_CREATE_SERIALIZE_OBJECT CreateSerObj; ++ UINT32 ulResult; ++ CHAR szSerObjName[ 64 ] = "Oct6100ApiXXXXXXXXApiSerObj"; ++ ++ ++ /* Set some parameters of the create structure once and for all. */ ++ CreateSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ CreateSerObj.pszSerialObjName = szSerObjName; ++ ++ /*----------------------------------------------------------------------*/ ++ /* Set the chip ID in the semaphore name. */ ++ szSerObjName[ 10 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 28 ) & 0xFF ); ++ szSerObjName[ 11 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 24 ) & 0xFF ); ++ szSerObjName[ 12 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 20 ) & 0xFF ); ++ szSerObjName[ 13 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 16 ) & 0xFF ); ++ szSerObjName[ 14 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 12 ) & 0xFF ); ++ szSerObjName[ 15 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 8 ) & 0xFF ); ++ szSerObjName[ 16 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 4 ) & 0xFF ); ++ szSerObjName[ 17 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 0 ) & 0xFF ); ++ ++ ulResult = Oct6100UserCreateSerializeObject( &CreateSerObj ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ f_pApiInstance->ulApiSerObj = CreateSerObj.ulSerialObjHndl; ++ /*----------------------------------------------------------------------*/ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiDestroySerializeObjects ++ ++Description: Destroy handles to each serialization object used by the API. ++ ++ Note that in a multi-process system the user's process context ++ structure pointer is needed by this function. Thus, the ++ pointer must be valid. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiDestroySerializeObjects ++UINT32 Oct6100ApiDestroySerializeObjects( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tOCT6100_DESTROY_SERIALIZE_OBJECT DestroySerObj; ++ UINT32 ulResult; ++ ++ /* Set some parameters of the create structure once and for all. */ ++ DestroySerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ DestroySerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ++ ulResult = Oct6100UserDestroySerializeObject( &DestroySerObj ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRunEgo ++ ++Description: Private function used to communicate with the internal processors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_fStoreFlag Type of access performed. (Load or Store) ++f_ulNumEntry Number of access. ++f_aulEntry Array of access to perform. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRunEgo ++UINT32 Oct6100ApiRunEgo( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN BOOL f_fStoreFlag, ++ IN UINT32 f_ulNumEntry, ++ OUT PUINT32 f_aulEntry ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT32 aulCpuLsuCmd[ 2 ]; ++ UINT16 usReadData; ++ UINT32 i; ++ BOOL fConditionFlag = TRUE; ++ UINT32 ulLoopCounter = 0; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get local pointer to the chip configuration structure. */ ++ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* No more than 2 entries may be requested. */ ++ if ( f_ulNumEntry > 2 ) ++ return cOCT6100_ERR_FATAL_1B; ++ ++ /* Write the requested entries at address reserved for CPU. */ ++ for( i = 0; i < f_ulNumEntry; i++ ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_PART1_API_SCRATCH_PAD + ( 0x8 * i ); ++ WriteParams.usWriteData = (UINT16)(( f_aulEntry[ i * 2 ] >> 16 ) & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( f_aulEntry[ i * 2 ] & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)(( f_aulEntry[ (i * 2) + 1] >> 16 ) & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( f_aulEntry[ (i * 2) + 1] & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Preincrement code point. */ ++ pSharedInfo->MiscVars.usCodepoint++; ++ ++ /* Create DWORD 0 of command. */ ++ aulCpuLsuCmd[0] = 0x00000000; ++ if ( f_fStoreFlag == FALSE ) ++ aulCpuLsuCmd[0] |= 0xC0000000; /* EGO load. */ ++ else ++ aulCpuLsuCmd[0] |= 0xE0000000; /* EGO store. */ ++ ++ aulCpuLsuCmd[0] |= (f_ulNumEntry - 1) << 19; ++ aulCpuLsuCmd[0] |= cOCT6100_PART1_API_SCRATCH_PAD; ++ ++ /* Create DWORD 1 of command. */ ++ aulCpuLsuCmd[1] = 0x00000000; ++ aulCpuLsuCmd[1] |= ( ( cOCT6100_PART1_API_SCRATCH_PAD + 0x10 ) & 0xFFFF ) << 16; ++ aulCpuLsuCmd[1] |= pSharedInfo->MiscVars.usCodepoint; ++ ++ /* Write the EGO command in the LSU CB. */ ++ WriteParams.ulWriteAddress = cOCT6100_PART1_CPU_LSU_CB_BASE + ((pSharedInfo->MiscVars.usCpuLsuWritePtr & 0x7) * 0x8 ); ++ WriteParams.usWriteData = (UINT16)(( aulCpuLsuCmd[ 0 ] >> 16 ) & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( aulCpuLsuCmd[ 0 ] & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)(( aulCpuLsuCmd[ 1 ] >> 16 ) & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( aulCpuLsuCmd[ 1 ] & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Post increment the write pointer. */ ++ pSharedInfo->MiscVars.usCpuLsuWritePtr++; ++ ++ /* Indicate new write pointer position to HW. */ ++ WriteParams.ulWriteAddress = cOCT6100_PART1_EGO_REG + 0x5A; ++ WriteParams.usWriteData = (UINT16)( pSharedInfo->MiscVars.usCpuLsuWritePtr & 0x7 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Wait for codepoint to be updated before returning. */ ++ while( fConditionFlag ) ++ { ++ ReadParams.ulReadAddress = cOCT6100_PART1_API_SCRATCH_PAD + 0x12; ++ usReadData = (UINT16)( pSharedInfo->MiscVars.usCodepoint ); ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData == pSharedInfo->MiscVars.usCodepoint ) ++ fConditionFlag = FALSE; ++ ++ ulLoopCounter++; ++ ++ if ( ulLoopCounter == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_OPEN_EGO_TIMEOUT; ++ } ++ ++ /* CRC error bit must be zero. */ ++ ReadParams.ulReadAddress = 0x202; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( ( usReadData & 0x0400 ) != 0 ) ++ return cOCT6100_ERR_OPEN_CORRUPTED_IMAGE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCreateEgoEntry ++ ++Description: Private function used to create an access structure to be sent ++ to the internal processors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_ulExternalAddress External memory address for the access. ++f_ulInternalAddress Which process should receive the command. ++f_ulNumBytes Number of bytes associated to the access. ++f_aulEntry Array of access to perform. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCreateEgoEntry ++UINT32 Oct6100ApiCreateEgoEntry( ++ IN UINT32 f_ulExternalAddress, ++ IN UINT32 f_ulInternalAddress, ++ IN UINT32 f_ulNumBytes, ++ OUT UINT32 f_aulEntry[ 2 ] ) ++{ ++ f_aulEntry[0] = 0x80000000; ++ f_aulEntry[0] |= f_ulExternalAddress & 0x07FFFFFC; ++ ++ f_aulEntry[1] = 0x0011C000; ++ f_aulEntry[1] |= (f_ulNumBytes / 8) << 23; ++ f_aulEntry[1] |= (f_ulInternalAddress >> 2) & 0x3FFF; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInitChannels ++ ++Description: This function will initialize all the channels to power down. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInitChannels ++UINT32 Oct6100ApiInitChannels( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 i; ++ UINT32 ulResult; ++ tOCT6100_WRITE_BURST_PARAMS BurstParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT16 usReadData; ++ UINT32 ulTempData; ++ UINT32 ulBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulMask; ++ UINT16 ausWriteData[ 4 ]; ++ UINT16 usLoopCount = 0; ++ UINT16 usWriteData = 0; ++ UINT16 usMclkRead; ++ UINT16 usLastMclkRead; ++ UINT16 usMclkDiff; ++ UINT32 ulNumberOfCycleToWait; ++ UINT32 ulTimeoutCounter; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ BurstParams.pusWriteData = ausWriteData; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Verify that the image has enough memory to work correctly. */ ++ if ( ( pSharedInfo->MiscVars.ulTotalMemSize + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) < pSharedInfo->MemoryMap.ulFreeMemBaseAddress ) ++ return cOCT6100_ERR_OPEN_INSUFFICIENT_EXTERNAL_MEMORY; ++ ++ /* Verify that the tail length is supported by the device.*/ ++ if ( pSharedInfo->ChipConfig.usTailDisplacement > pSharedInfo->ImageInfo.usMaxTailDisplacement ) ++ return cOCT6100_ERR_NOT_SUPPORTED_OPEN_TAIL_DISPLACEMENT_VALUE; ++ ++ /* Verify that acoustic echo is supported by the device. */ ++ if ( pSharedInfo->ChipConfig.fEnableAcousticEcho == TRUE && pSharedInfo->ImageInfo.fAcousticEcho == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_OPEN_ACOUSTIC_ECHO; ++ ++ /* Verify that the image supports all the requested channels. */ ++ if ( pSharedInfo->ChipConfig.usMaxChannels > pSharedInfo->ImageInfo.usMaxNumberOfChannels ) ++ return cOCT6100_ERR_NOT_SUPPORTED_OPEN_MAX_ECHO_CHANNELS_VALUE; ++ ++ /* Max number of channels the image supports + 1 for channel recording, if requested */ ++ if ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ && ( pSharedInfo->ImageInfo.usMaxNumberOfChannels < cOCT6100_MAX_ECHO_CHANNELS ) ++ && ( pSharedInfo->ChipConfig.usMaxChannels == pSharedInfo->ImageInfo.usMaxNumberOfChannels ) ) ++ return cOCT6100_ERR_NOT_SUPPORTED_OPEN_MAX_ECHO_CHANNELS_VALUE; ++ ++ /* Initialize the memory for all required channels. */ ++ for( i = 0; i < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; i++ ) ++ { ++ /*==============================================================================*/ ++ /* Configure the Global Static Configuration memory of the channel. */ ++ ++ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( i * cOCT6100_CHANNEL_ROOT_SIZE ) + cOCT6100_CHANNEL_ROOT_GLOBAL_CONF_OFFSET; ++ ++ /* Set the PGSP context base address. */ ++ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + cOCT6100_CH_MAIN_PGSP_CONTEXT_OFFSET; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_CONTEXT_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the PGSP init context base address. */ ++ ulTempData = ( cOCT6100_IMAGE_FILE_BASE + 0x200 ) & 0x07FFFFFF; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_INIT_CONTEXT_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the RIN circular buffer base address. */ ++ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst; ++ ++ /* Set the circular buffer size. */ ++ ulTempData &= 0xFFFFFF00; ++ if (( pSharedInfo->MemoryMap.ulChanMainRinCBMemSize & 0xFFFF00FF ) != 0 ) ++ return cOCT6100_ERR_CHANNEL_INVALID_RIN_CB_SIZE; ++ ulTempData |= pSharedInfo->MemoryMap.ulChanMainRinCBMemSize >> 8; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_RIN_CIRC_BUFFER_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the SIN circular buffer base address. */ ++ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SIN_CIRC_BUFFER_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the SOUT circular buffer base address. */ ++ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst;; ++ ++ WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SOUT_CIRC_BUFFER_BASE_ADD_OFFSET; ++ WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==============================================================================*/ ++ } ++ ++ /* Put all channel in powerdown mode "3". */ ++ for( i = 0; i < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; i++ ) ++ { ++ WriteParams.ulWriteAddress = 0x014000 + (i*4) + 0; ++ WriteParams.usWriteData = 0x85FF; /* TSI index 1535 reserved for power-down mode */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x014000 + (i*4) + 2; ++ WriteParams.usWriteData = 0xC5FF; /* TSI index 1535 reserved for power-down mode */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Set the maximum number of channels. */ ++ WriteParams.ulWriteAddress = 0x690; ++ if ( pSharedInfo->ImageInfo.usMaxNumberOfChannels < 384 ) ++ WriteParams.usWriteData = 384; ++ else ++ WriteParams.usWriteData = (UINT16)pSharedInfo->ImageInfo.usMaxNumberOfChannels; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set power-dowm TSI chariot memory to silence. */ ++ for( i = 0; i < 6; i++ ) ++ { ++ WriteParams.ulWriteAddress = 0x20000 + ( i * 0x1000 ) + ( 1534 * 2 ); ++ WriteParams.usWriteData = 0x3EFF; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x20000 + ( i * 0x1000 ) + ( 1535 * 2 ); ++ WriteParams.usWriteData = 0x3EFF; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Remove chariot hold. */ ++ WriteParams.ulWriteAddress = 0x500; ++ WriteParams.usWriteData = 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ for( usLoopCount = 0; usLoopCount < 4096; usLoopCount++ ) ++ { ++ if ( (usLoopCount % 16) < 8 ) ++ { ++ usWriteData = (UINT16)((usLoopCount / 16) << 7); ++ usWriteData |= (UINT16)((usLoopCount % 8)); ++ } ++ else ++ { ++ usWriteData = (UINT16)((usLoopCount / 16) << 7); ++ usWriteData |= (UINT16)((usLoopCount % 8)); ++ usWriteData |= 0x78; ++ } ++ ++ /* Set timeslot pointer. */ ++ WriteParams.ulWriteAddress = 0x50E; ++ WriteParams.usWriteData = 0x0003; ++ WriteParams.usWriteData |= usWriteData << 2; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now read the mclk counter. */ ++ ReadParams.ulReadAddress = 0x30A; ++ ReadParams.pusReadData = &usLastMclkRead; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reset loop timeout counter. */ ++ ulTimeoutCounter = 0x0; ++ ++ do { ++ ReadParams.pusReadData = &usMclkRead; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( ( usLoopCount % 16 ) != 15 ) ++ { ++ ulNumberOfCycleToWait = 133; ++ } ++ else ++ { ++ ulNumberOfCycleToWait = 20000; ++ } ++ ++ /* Evaluate the difference. */ ++ usMclkDiff = (UINT16)(( usMclkRead - usLastMclkRead ) & 0xFFFF); ++ ++ /* Check for loop timeout. Bad mclk? */ ++ ulTimeoutCounter++; ++ if ( ulTimeoutCounter == cOCT6100_MAX_LOOP_CPU_TIMEOUT ) ++ return cOCT6100_ERR_FATAL_EA; ++ ++ } while( usMclkDiff <= ulNumberOfCycleToWait ); ++ } ++ ++ /* Back to normal mode. */ ++ WriteParams.ulWriteAddress = 0x50E; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check for CRC errors. */ ++ ReadParams.pusReadData = &usReadData; ++ ReadParams.ulReadAddress = 0x202; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( (usReadData & 0x400) != 0x0000 ) ++ return cOCT6100_ERR_OPEN_CRC_ERROR; ++ ++ /* Clear the error rol raised by manually moving the clocks. */ ++ WriteParams.ulWriteAddress = 0x502; ++ WriteParams.usWriteData = 0x0002; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*======================================================================*/ ++ /* Write the tail displacement value in external memory. */ ++ ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchTailDisplOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchTailDisplOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchTailDisplOfst.byFieldSize; ++ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ &ulTempData ); ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set the tail displacement. */ ++ ulTempData |= (pSharedInfo->ChipConfig.usTailDisplacement << ulFeatureBitOffset ); ++ ++ /* Write the DWORD where the field is located. */ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Clear the pouch counter, if present. */ ++ ++ if ( pSharedInfo->DebugInfo.fPouchCounter == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byFieldSize; ++ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ &ulTempData ); ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ /* Clear counter! */ ++ ulTempData &= (~ulMask); ++ ++ /* Write the DWORD where the field is located.*/ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* The ISR has not yet been called. Set the appropriate bit in external memory. */ ++ if ( pSharedInfo->DebugInfo.fIsIsrCalledField == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byFieldSize; ++ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ &ulTempData ); ++ ++ /* Read previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ /* Toggle the bit to '1'. */ ++ ulTempData |= 1 << ulFeatureBitOffset; ++ ++ /* Write the DWORD where the field is located.*/ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInitToneInfo ++ ++Description: This function will parse the software image and retrieve ++ the information about the tones that it supports. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInitToneInfo ++UINT32 Oct6100ApiInitToneInfo( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ UINT32 ulResult; ++ ++ unsigned char const *pszToneInfoStart = NULL; ++ unsigned char const *pszToneInfoEnd = NULL; ++ ++ unsigned char const *pszCurrentInfo; ++ unsigned char const *pszNextInfo; ++ ++ UINT32 ulToneEventNumber; ++ UINT32 ulTempValue; ++ UINT32 ulNumCharForValue; ++ UINT32 ulUniqueToneId; ++ UINT32 ulToneNameSize; ++ UINT32 ulOffset = 0; ++ ++ UINT32 i; ++ ++ /* Init the tone detector parameter. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.byNumToneDetectors = 0; ++ ++ /* Find the start and the end of the tone info section. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize > 4096 ) ++ { ++ /* For performance reasons, and since the tone detector information */ ++ /* is always located at the end of the image file, try to start from the end */ ++ /* of the buffer. */ ++ ++ ulOffset = f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize - 2048; ++ pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + ulOffset, ++ (PUINT8)cOCT6100_TONE_INFO_START_STRING, ++ f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); ++ ++ /* Check if the information was found. */ ++ if ( pszToneInfoStart == NULL ) ++ { ++ /* Try again, but giving a larger string to search. */ ++ ulOffset = f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize - 4096; ++ pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + ulOffset, ++ (PUINT8)cOCT6100_TONE_INFO_START_STRING, ++ f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); ++ ++ } ++ } ++ ++ if ( pszToneInfoStart == NULL ) ++ { ++ /* Travel through the whole file buffer. */ ++ pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile, ++ (PUINT8)cOCT6100_TONE_INFO_START_STRING, ++ f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); ++ } ++ /* We have to return immediatly if no tones are found. */ ++ if ( pszToneInfoStart == NULL ) ++ return cOCT6100_ERR_OK; ++ ++ /* The end of the tone detector information is after the beginning of the tone information. */ ++ pszToneInfoEnd = Oct6100ApiStrStr( pszToneInfoStart, ++ (PUINT8)cOCT6100_TONE_INFO_STOP_STRING, ++ f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); ++ if ( pszToneInfoEnd == NULL ) ++ return cOCT6100_ERR_OPEN_TONE_INFO_STOP_TAG_NOT_FOUND; ++ ++ /* Find and process all tone events within the region. */ ++ pszCurrentInfo = Oct6100ApiStrStr( pszToneInfoStart, (PUINT8)cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd ); ++ ++ while ( pszCurrentInfo != NULL ) ++ { ++ /* Skip the string. */ ++ pszCurrentInfo += ( Oct6100ApiStrLen( (PUINT8)cOCT6100_TONE_INFO_EVENT_STRING ) ); ++ ++ /* Extract the number of char used to represent the tone event number ( 1 or 2 ). */ ++ pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo, (PUINT8)",", pszToneInfoEnd ); ++ ulNumCharForValue = (UINT32)( pszNextInfo - pszCurrentInfo ); ++ ++ /* Retreive the event number */ ++ ulToneEventNumber = 0; ++ for ( i = ulNumCharForValue; i > 0; i-- ) ++ { ++ ulResult = Oct6100ApiAsciiToHex( *pszCurrentInfo, &ulTempValue ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulToneEventNumber |= ( ulTempValue << (( i - 1) * 4 ) ); ++ pszCurrentInfo++; ++ } ++ ++ if ( ulToneEventNumber >= cOCT6100_MAX_TONE_EVENT ) ++ return cOCT6100_ERR_OPEN_INVALID_TONE_EVENT; ++ ++ /* Skip the comma and the 0x. */ ++ pszCurrentInfo += 3; ++ ++ /*======================================================================*/ ++ /* Retreive the unique tone id. */ ++ ulUniqueToneId = 0; ++ for ( i = 0; i < 8; i++ ) ++ { ++ ulResult = Oct6100ApiAsciiToHex( *pszCurrentInfo, &ulTempValue ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulOffset = 28 - ( i * 4 ); ++ ulUniqueToneId |= ( ulTempValue << ulOffset ); ++ pszCurrentInfo++; ++ } ++ ++ /*======================================================================*/ ++ ++ /* Skip the comma. */ ++ pszCurrentInfo++; ++ ++ /* Find out where the next event info starts */ ++ pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo,(PUINT8) cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd ); ++ if ( pszNextInfo == NULL ) ++ pszNextInfo = pszToneInfoEnd; ++ ++ /* Extract the name size. */ ++ ulToneNameSize = (UINT32)( pszNextInfo - pszCurrentInfo - 2 ); /* - 2 for 0x0D and 0x0A.*/ ++ ++ if ( ulToneNameSize > cOCT6100_TLV_MAX_TONE_NAME_SIZE ) ++ return cOCT6100_ERR_OPEN_INVALID_TONE_NAME; ++ ++ /* Copy the tone name into the image info structure. */ ++ ulResult = Oct6100UserMemCopy( f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].aszToneName, ++ pszCurrentInfo, ++ ulToneNameSize ); ++ ++ ++ ++ /* Update the tone info into the image info structure. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID = ulUniqueToneId; ++ /* Find out the port on which this tone detector is associated. */ ++ switch( (ulUniqueToneId >> 28) & 0xF ) ++ { ++ case 1: ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_ROUT; ++ break; ++ ++ case 2: ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_SIN; ++ break; ++ ++ case 4: ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_SOUT; ++ break; ++ ++ case 5: ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_ROUT_SOUT; ++ break; ++ ++ default: ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_INVALID_PORT; ++ break; ++ } ++ ++ /* Find out where the next event info starts */ ++ pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo,(PUINT8) cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd ); ++ /* Update the current info pointer. */ ++ pszCurrentInfo = pszNextInfo; ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.byNumToneDetectors++; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiExternalMemoryBist ++ ++Description: Tests the functionality of the external memories. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiExternalMemoryBist ++UINT32 Oct6100ApiExternalMemoryBist( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulMemSize = 0; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Test the external memory. */ ++ switch ( pSharedInfo->ChipConfig.ulMemoryChipSize ) ++ { ++ case cOCT6100_MEMORY_CHIP_SIZE_8MB: ++ ulMemSize = cOCT6100_SIZE_8M; ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_16MB: ++ ulMemSize = cOCT6100_SIZE_16M; ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_32MB: ++ ulMemSize = cOCT6100_SIZE_32M; ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_64MB: ++ ulMemSize = cOCT6100_SIZE_64M; ++ break; ++ case cOCT6100_MEMORY_CHIP_SIZE_128MB: ++ ulMemSize = cOCT6100_SIZE_128M; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_D9; ++ } ++ ++ ulMemSize *= pSharedInfo->ChipConfig.byNumMemoryChips; ++ ++ ulResult = Oct6100ApiRandomMemoryWrite( f_pApiInstance, cOCT6100_EXTERNAL_MEM_BASE_ADDRESS, ulMemSize, 16, 1000, cOCT6100_ERR_OPEN_EXTERNAL_MEM_BIST_FAILED ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Make sure the user I/O functions are working as required. */ ++ ulResult = Oct6100ApiUserIoTest( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGenerateNumber ++ ++Description: Generate a number using an index. Passing the same ++ index generates the same number. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_ulIndex Index used to generate the random number. ++f_ulDataMask Data mask to apply to generated number. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGenerateNumber ++UINT16 Oct6100ApiGenerateNumber( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulIndex, ++ IN UINT32 f_ulDataMask ) ++{ ++ UINT16 usGeneratedNumber; ++ ++ usGeneratedNumber = (UINT16)( ( ( ~( f_ulIndex - 1 ) ) & 0xFF00 ) | ( ( f_ulIndex + 1 ) & 0xFF ) ); ++ ++ return (UINT16)( usGeneratedNumber & f_ulDataMask ); ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRandomMemoryWrite ++ ++Description: Writes to f_ulNumAccesses random locations in the indicated ++ memory and read back to test the operation of that memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_ulMemBase Base address of the memory access. ++f_ulMemSize Size of the memory to be tested. ++f_ulNumDataBits Number of data bits. ++f_ulNumAccesses Number of random access to be perform. ++f_ulErrorCode Error code to be returned if the bist fails. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRandomMemoryWrite ++UINT32 Oct6100ApiRandomMemoryWrite( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulMemBase, ++ IN UINT32 f_ulMemSize, ++ IN UINT32 f_ulNumDataBits, ++ IN UINT32 f_ulNumAccesses, ++ IN UINT32 f_ulErrorCode ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulDataMask; ++ UINT32 ulResult, i, j; ++ UINT32 ulBistAddress; ++ UINT16 usReadData; ++ UINT32 aulBistAddress[20]={0x00000000, 0x00000002, 0x00000004, 0x007FFFFE, ++ 0x00900000, 0x00900006, 0x00900008, 0x009FFFFE, ++ 0x01000000, 0x0100000A, 0x0200000C, 0x01FFFFFE, ++ 0x03000000, 0x03000002, 0x04000004, 0x03FFFFFE, ++ 0x04000000, 0x05000006, 0x06000008, 0x07FFFFFE}; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Determine mask for number of data bits. */ ++ ulDataMask = (1 << f_ulNumDataBits) - 1; ++ ++ /* Write specific data to specific address */ ++ WriteParams.ulWriteAddress = f_ulMemBase | 0x00001000; ++ WriteParams.usWriteData = 0xCAFE; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ for(j=0; j<20; j++) ++ { ++ /* Change address to test lower and higher part of the 32 bit bus */ ++ ulBistAddress = aulBistAddress[j]; ++ ulBistAddress &= f_ulMemSize - 2; ++ ulBistAddress |= f_ulMemBase; ++ ++ /* Bist 16 data pins of this address */ ++ for ( i = 0; i < 16; i ++) ++ { ++ WriteParams.ulWriteAddress = ulBistAddress; ++ WriteParams.usWriteData = (UINT16)(0x1 << i); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Read back the specific data to flush the data bus.*/ ++ ReadParams.ulReadAddress = f_ulMemBase | 0x00001000; ++ ReadParams.pusReadData = &usReadData; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != 0xCAFE ) ++ return f_ulErrorCode; ++ ++ /* Read back the data written.*/ ++ ReadParams.ulReadAddress = WriteParams.ulWriteAddress; ++ ReadParams.pusReadData = &usReadData; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != (UINT16)(0x1 << i) ) ++ return f_ulErrorCode; ++ } ++ } ++ ++ /* Perform the first write at address 0 + mem base */ ++ j = 0; ++ WriteParams.ulWriteAddress = f_ulMemBase; ++ WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, j, ulDataMask ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Try each address line of the memory. */ ++ for ( i = 2, j = 1; i < f_ulMemSize; i <<= 1, j++ ) ++ { ++ WriteParams.ulWriteAddress = ( f_ulMemBase + i ); ++ WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, j, ulDataMask ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ for ( i = 0; i < j; i++ ) ++ { ++ if ( i > 0 ) ++ ReadParams.ulReadAddress = ( f_ulMemBase + ( 0x1 << i ) ); ++ else ++ ReadParams.ulReadAddress = f_ulMemBase; ++ ReadParams.pusReadData = &usReadData; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData != Oct6100ApiGenerateNumber( f_pApiInstance, i, ulDataMask ) ) ++ return f_ulErrorCode; ++ } ++ ++ /* Write to random addresses of the memory. */ ++ for ( i = 0; i < f_ulNumAccesses; i++ ) ++ { ++ ulBistAddress = (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) << 16; ++ ulBistAddress |= (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); ++ ulBistAddress &= f_ulMemSize - 2; ++ ulBistAddress |= f_ulMemBase; ++ ++ WriteParams.ulWriteAddress = ulBistAddress; ++ WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ for ( i = 0; i < f_ulNumAccesses; i++ ) ++ { ++ ulBistAddress = (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) << 16; ++ ulBistAddress |= (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); ++ ulBistAddress &= f_ulMemSize - 2; ++ ulBistAddress |= f_ulMemBase; ++ ++ ReadParams.ulReadAddress = ulBistAddress; ++ ReadParams.pusReadData = &usReadData; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( ( usReadData & ulDataMask ) != ( Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) & ulDataMask ) ) ++ return f_ulErrorCode; ++ } ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUserIoTest ++ ++Description: This function will verify the correct functionality of ++ the following user functions: ++ ++ - Oct6100UserDriverWriteBurstApi ++ - Oct6100UserDriverWriteSmearApi ++ - Oct6100UserDriverReadBurstApi ++ ++ The Oct6100UserDriverWriteApi and Oct6100UserDriverReadApi ++ functions do not need to be tested here as this has be done in ++ the external memory bisting function above. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUserIoTest ++UINT32 Oct6100ApiUserIoTest( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_BURST_PARAMS WriteBurstParams; ++ tOCT6100_WRITE_SMEAR_PARAMS WriteSmearParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_READ_BURST_PARAMS ReadBurstParams; ++ UINT32 ulResult, i; ++ UINT16 usReadData; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ /* Test what the user has specified is the maximum that can be used for a burst. */ ++ WriteBurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ WriteBurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray; ++ ++ WriteSmearParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteSmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ /* Test what the user has specified is the maximum that can be used for a smear. */ ++ WriteSmearParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ /* Test what the user has specified is the maximum that can be used for a burst. */ ++ ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ ReadBurstParams.pusReadData = pSharedInfo->MiscVars.ausSuperArray; ++ ++ ++ /*======================================================================*/ ++ /* Write burst check. */ ++ ++ WriteBurstParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; ++ /* Set the random data to be written. */ ++ for ( i = 0; i < WriteBurstParams.ulWriteLength; i++ ) ++ { ++ WriteBurstParams.pusWriteData[ i ] = Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); ++ } ++ mOCT6100_DRIVER_WRITE_BURST_API( WriteBurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Read back pattern using simple read function and make sure we are reading what's expected. */ ++ ReadParams.ulReadAddress = WriteBurstParams.ulWriteAddress; ++ for ( i = 0; i < WriteBurstParams.ulWriteLength; i++ ) ++ { ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the data matches. */ ++ if ( usReadData != WriteBurstParams.pusWriteData[ i ] ) ++ { ++ /* The values do not match. Something seems to be wrong with the WriteBurst user function. */ ++ return cOCT6100_ERR_OPEN_USER_WRITE_BURST_FAILED; ++ } ++ ++ /* Next address to check. */ ++ ReadParams.ulReadAddress += 2; ++ } ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Write smear check. */ ++ ++ WriteSmearParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + ( WriteBurstParams.ulWriteLength * 2 ); ++ /* Set the random data to be written. */ ++ WriteSmearParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, Oct6100ApiRand( 0xFFFF ), 0xFFFF ); ++ mOCT6100_DRIVER_WRITE_SMEAR_API( WriteSmearParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Read back pattern using simple read function and make sure we are reading what's expected. */ ++ ReadParams.ulReadAddress = WriteSmearParams.ulWriteAddress; ++ for ( i = 0; i < WriteSmearParams.ulWriteLength; i++ ) ++ { ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the data matches. */ ++ if ( usReadData != WriteSmearParams.usWriteData ) ++ { ++ /* The values do not match. Something seems to be wrong with the WriteSmear user function. */ ++ return cOCT6100_ERR_OPEN_USER_WRITE_SMEAR_FAILED; ++ } ++ ++ /* Next address to check. */ ++ ReadParams.ulReadAddress += 2; ++ } ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Read burst check. */ ++ ++ /* First check with what the WriteBurst function wrote. */ ++ ReadBurstParams.ulReadAddress = WriteBurstParams.ulWriteAddress; ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ for ( i = 0; i < ReadBurstParams.ulReadLength; i++ ) ++ { ++ /* Check if the data matches. */ ++ if ( ReadBurstParams.pusReadData[ i ] != Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) ) ++ { ++ /* The values do not match. Something seems to be wrong with the ReadBurst user function. */ ++ return cOCT6100_ERR_OPEN_USER_READ_BURST_FAILED; ++ } ++ } ++ ++ /* Then check with what the WriteSmear function wrote. */ ++ ReadBurstParams.ulReadAddress = WriteSmearParams.ulWriteAddress; ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ for ( i = 0; i < ReadBurstParams.ulReadLength; i++ ) ++ { ++ /* Check if the data matches. */ ++ if ( ReadBurstParams.pusReadData[ i ] != WriteSmearParams.usWriteData ) ++ { ++ /* The values do not match. Something seems to be wrong with the ReadBurst user function. */ ++ return cOCT6100_ERR_OPEN_USER_READ_BURST_FAILED; ++ } ++ } ++ ++ /*======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiExternalMemoryInit ++ ++Description: Initialize the external memory before uploading the image. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiExternalMemoryInit ++UINT32 Oct6100ApiExternalMemoryInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_SMEAR_PARAMS SmearParams; ++ UINT32 ulTotalWordToWrite; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ SmearParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ SmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Clear the first part of the memory. */ ++ ulTotalWordToWrite = 0x400; ++ SmearParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; ++ ++ while ( ulTotalWordToWrite != 0 ) ++ { ++ if ( ulTotalWordToWrite >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ SmearParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ else ++ SmearParams.ulWriteLength = ulTotalWordToWrite; ++ ++ SmearParams.usWriteData = 0x0; ++ ++ mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the number of words to write. */ ++ ulTotalWordToWrite -= SmearParams.ulWriteLength; ++ /* Update the address. */ ++ SmearParams.ulWriteAddress += ( SmearParams.ulWriteLength * 2 ); ++ } ++ ++ /* Clear the TLV flag.*/ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_TLV_BASE, 0x0 ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInitMixer ++ ++Description: This function will initialize the mixer memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInitMixer ++UINT32 Oct6100ApiInitMixer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_BURST_PARAMS BurstParams; ++ UINT16 ausWriteData[ 4 ]; ++ UINT32 ulResult; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ BurstParams.pusWriteData = ausWriteData; ++ /*======================================================================*/ ++ /* Initialize the mixer memory if required. */ ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ { ++ /* Modify the mixer pointer by adding the record event into the link list. */ ++ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; ++ pSharedInfo->MixerInfo.usLastSinCopyEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; ++ pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = pSharedInfo->MixerInfo.usRecordCopyEventIndex; ++ pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = pSharedInfo->MixerInfo.usRecordCopyEventIndex; ++ ++ /* Program the Sin copy event. */ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordSinEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ BurstParams.ulWriteLength = 4; ++ ++ ausWriteData[ 0 ] = 0x0000; ++ ausWriteData[ 1 ] = 0x0000; ++ ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_TAIL_NODE & 0x7FF); /* Head node.*/ ++ ausWriteData[ 3 ] = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Program the Sout copy event. */ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ BurstParams.ulWriteLength = 4; ++ ++ ausWriteData[ 0 ] = 0x0000; ++ ausWriteData[ 1 ] = 0x0000; ++ ausWriteData[ 2 ] = (UINT16)(pSharedInfo->MixerInfo.usRecordSinEventIndex & 0x7FF); ++ ausWriteData[ 3 ] = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Configure the head node. */ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE; ++ BurstParams.ulWriteLength = 4; ++ ++ ausWriteData[ 0 ] = 0x0000; ++ ausWriteData[ 1 ] = 0x0000; ++ ausWriteData[ 2 ] = (UINT16)(pSharedInfo->MixerInfo.usRecordCopyEventIndex & 0x7FF); ++ ausWriteData[ 3 ] = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Init the mixer pointer */ ++ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; ++ } ++ else ++ { ++ /* Configure the head node. */ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE; ++ BurstParams.ulWriteLength = 4; ++ ++ ausWriteData[ 0 ] = 0x0000; ++ ausWriteData[ 1 ] = 0x0000; ++ ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_TAIL_NODE & 0x7FF); /* Head node. */ ++ ausWriteData[ 3 ] = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Configure the tail node. */ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + 0x10; ++ BurstParams.ulWriteLength = 4; ++ ++ ausWriteData[ 0 ] = 0x0000; ++ ausWriteData[ 1 ] = 0x0000; ++ ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_HEAD_NODE & 0x7FF); /* Head node. */ ++ ausWriteData[ 3 ] = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInitRecordResources ++ ++Description: This function will initialize the resources required to ++ perform recording on a debug channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInitRecordResources ++UINT32 Oct6100ApiInitRecordResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check if recording is enabled. */ ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) ++ return cOCT6100_ERR_OK; ++ ++ if ( pSharedInfo->DebugInfo.usRecordMemIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_NOT_SUPPORTED_OPEN_DEBUG_RECORD; ++ ++ /* Check the provided recording memory index within the SSPX. */ ++ if ( pSharedInfo->DebugInfo.usRecordMemIndex != ( pSharedInfo->ImageInfo.usMaxNumberOfChannels - 1 ) ) ++ return cOCT6100_ERR_OPEN_DEBUG_MEM_INDEX; ++ ++ /* Reserve the TSI entries for the channel. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Open the debug channel. */ ++ ulResult = Oct6100ApiDebugChannelOpen( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100FreeResourcesSer ++ ++Description: This function closes all opened channels and frees all ++ specified global resources used by the chip. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pFreeResources Pointer to user structure in which to choose what ++ to free. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100FreeResourcesSer ++UINT32 Oct6100FreeResourcesSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_FREE_RESOURCES f_pFreeResources ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ ++ UINT32 ulResult; ++ UINT32 i; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Close all bidirectional channels. */ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxBiDirChannels; i ++ ) ++ { ++ tPOCT6100_API_BIDIR_CHANNEL pBiDirChanEntry; ++ ++ mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, i ); ++ ++ if ( pBiDirChanEntry->fReserved == TRUE ) ++ { ++ tOCT6100_CHANNEL_DESTROY_BIDIR DestroyBidir; ++ ++ Oct6100ChannelDestroyBiDirDef( &DestroyBidir ); ++ ++ DestroyBidir.ulBiDirChannelHndl = cOCT6100_HNDL_TAG_BIDIR_CHANNEL | (pBiDirChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i; ++ ++ ulResult = Oct6100ChannelDestroyBiDirSer( f_pApiInstance, &DestroyBidir ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Close all bridge participants. */ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i ++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, i ); ++ if ( pChanEntry->fReserved == TRUE && pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* This channel is on a bridge. */ ++ tOCT6100_CONF_BRIDGE_CHAN_REMOVE BridgeChanRemove; ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ Oct6100ConfBridgeChanRemoveDef( &BridgeChanRemove ); ++ ++ /* Obtain a pointer to the conference bridge's list entry. */ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pChanEntry->usBridgeIndex ); ++ ++ BridgeChanRemove.fRemoveAll = TRUE; ++ BridgeChanRemove.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pChanEntry->usBridgeIndex; ++ ++ ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Close all opened channels. This will bring the broadcast TSSTs with it. */ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i ++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, i ); ++ ++ if ( pChanEntry->fReserved == TRUE ) ++ { ++ tOCT6100_CHANNEL_CLOSE ChannelClose; ++ ++ /* Generate handle. */ ++ ChannelClose.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i; ++ ++ /* Call serialized close channel function. */ ++ ulResult = Oct6100ChannelCloseSer( f_pApiInstance, &ChannelClose ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /* Close all TSI connections. */ ++ if ( f_pFreeResources->fFreeTsiConnections == TRUE ) ++ { ++ tPOCT6100_API_TSI_CNCT pTsiCnct; ++ tOCT6100_TSI_CNCT_CLOSE TsiCnctClose; ++ ++ Oct6100TsiCnctCloseDef( &TsiCnctClose ); ++ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxTsiCncts; i ++ ) ++ { ++ /* Obtain a pointer to the TSI connection list entry. */ ++ mOCT6100_GET_TSI_CNCT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsiCnct, i ); ++ ++ if ( pTsiCnct->fReserved == TRUE ) ++ { ++ TsiCnctClose.ulTsiCnctHndl = cOCT6100_HNDL_TAG_TSI_CNCT | (pTsiCnct->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i; ++ ++ ulResult = Oct6100TsiCnctCloseSer( f_pApiInstance, &TsiCnctClose ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ /* Close all conference bridges. */ ++ if ( f_pFreeResources->fFreeConferenceBridges == TRUE ) ++ { ++ tPOCT6100_API_CONF_BRIDGE pConfBridge; ++ tOCT6100_CONF_BRIDGE_CLOSE ConfBridgeClose; ++ ++ Oct6100ConfBridgeCloseDef( &ConfBridgeClose ); ++ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxConfBridges; i ++ ) ++ { ++ /* Obtain a pointer to the conference bridge's list entry. */ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pConfBridge, i ); ++ ++ if ( pConfBridge->fReserved == TRUE ) ++ { ++ ConfBridgeClose.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pConfBridge->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i; ++ ++ ulResult = Oct6100ConfBridgeCloseSer( f_pApiInstance, &ConfBridgeClose ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Free all playout buffers loaded in external memory. */ ++ if ( f_pFreeResources->fFreePlayoutBuffers == TRUE ) ++ { ++ tPOCT6100_API_BUFFER pBuffer; ++ tOCT6100_BUFFER_UNLOAD BufferUnload; ++ ++ Oct6100BufferPlayoutUnloadDef( &BufferUnload ); ++ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxPlayoutBuffers; i ++ ) ++ { ++ ++ ++ /* Obtain a pointer to the buffer list entry. */ ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBuffer, i ); ++ ++ if ( pBuffer->fReserved == TRUE ) ++ { ++ BufferUnload.ulBufferIndex = i; ++ ulResult = Oct6100BufferUnloadSer( f_pApiInstance, &BufferUnload, TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Close all phasing TSSTs. */ ++ if ( f_pFreeResources->fFreePhasingTssts == TRUE ) ++ { ++ tPOCT6100_API_PHASING_TSST pPhasingTsst; ++ tOCT6100_PHASING_TSST_CLOSE PhasingTsstClose; ++ ++ Oct6100PhasingTsstCloseDef( &PhasingTsstClose ); ++ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxPhasingTssts; i ++ ) ++ { ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, i ); ++ ++ if ( pPhasingTsst->fReserved == TRUE ) ++ { ++ PhasingTsstClose.ulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingTsst->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i; ++ ++ ulResult = Oct6100PhasingTsstCloseSer( f_pApiInstance, &PhasingTsstClose ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ /* Close all ADPCM channels. */ ++ if ( f_pFreeResources->fFreeAdpcmChannels == TRUE ) ++ { ++ tPOCT6100_API_ADPCM_CHAN pAdpcmChannel; ++ tOCT6100_ADPCM_CHAN_CLOSE AdpcmChanClose; ++ ++ Oct6100AdpcmChanCloseDef( &AdpcmChanClose ); ++ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxAdpcmChannels; i ++ ) ++ { ++ mOCT6100_GET_ADPCM_CHAN_ENTRY_PNT( pSharedInfo, pAdpcmChannel, i ); ++ if ( pAdpcmChannel->fReserved == TRUE ) ++ { ++ AdpcmChanClose.ulChanHndl = cOCT6100_HNDL_TAG_ADPCM_CHANNEL | (pAdpcmChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i; ++ ++ ulResult = Oct6100AdpcmChanCloseSer( f_pApiInstance, &AdpcmChanClose ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ProductionBistSer ++ ++Description: This function returns the instantaneous production BIST status. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pProductionBist Pointer to user structure in which BIST status will ++ be returned. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ProductionBistSer ++UINT32 Oct6100ProductionBistSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PRODUCTION_BIST f_pProductionBist ) ++{ ++ UINT32 ulCalculatedCrc = cOCT6100_INVALID_VALUE; ++ UINT32 ulResult; ++ UINT32 ulLoopCnt = 0x0; ++ UINT32 i = 1; ++ UINT32 ulTotalElements = 4; ++ UINT32 ulReadAddress = cOCT6100_POUCH_BASE; ++ UINT32 aulMessage[ 5 ]; ++ ++ /* Check if the production bist has been activated. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableProductionBist == FALSE ) ++ return cOCT6100_ERR_PRODUCTION_BIST_DISABLED; ++ ++ f_pProductionBist->ulCurrentAddress = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulCurrentLoop = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulCurrentTest = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulFailedAddress = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulReadValue = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulExpectedValue = cOCT6100_INVALID_VALUE; ++ f_pProductionBist->ulBistStatus = cOCT6100_BIST_IN_PROGRESS; ++ ++ /* The API knows that the firmware might be writing a status event. */ ++ /* The firmware does write a status event every 200ms (approximately). */ ++ /* So the status is read a couple of times to make sure an event was not read while */ ++ /* it was written. */ ++ while ( ulLoopCnt != 2 ) ++ { ++ /* Read the BIST status in the external memory. */ ++ for ( i = 0; i < ulTotalElements + 1; i ++ ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ulReadAddress + i * 4, &aulMessage[ i ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Calculate the CRC of this message. */ ++ ulResult = Oct6100ApiProductionCrc( f_pApiInstance, aulMessage, ulTotalElements, &ulCalculatedCrc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* If the CRCs do match, break off the while. We have a valid status event. */ ++ if ( aulMessage[ i - 1 ] == ulCalculatedCrc ) ++ break; ++ ++ ulLoopCnt++; ++ } ++ ++ /* Check if the CRC matches */ ++ if ( aulMessage[ i - 1 ] != ulCalculatedCrc ) ++ { ++ /* Well, the exchange memory at the base of the external memory is corrupted. */ ++ /* Something very basic is not working correctly with this chip! */ ++ f_pProductionBist->ulBistStatus = cOCT6100_BIST_STATUS_CRC_FAILED; ++ } ++ else ++ { ++ /* Check for problems. */ ++ switch ( aulMessage[ 0 ] & 0xFFFF ) ++ { ++ case ( 0x2 ): ++ ++ /* The initial configuration failed. */ ++ f_pProductionBist->ulBistStatus = cOCT6100_BIST_CONFIGURATION_FAILED; ++ break; ++ ++ case ( 0x1 ): ++ ++ /* A memory location failed. Return useful information to the user. */ ++ f_pProductionBist->ulBistStatus = cOCT6100_BIST_MEMORY_FAILED; ++ ++ f_pProductionBist->ulFailedAddress = ( aulMessage[ 1 ] & ( ~0x80000000 ) ) + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; ++ f_pProductionBist->ulReadValue = aulMessage[ 2 ]; ++ f_pProductionBist->ulExpectedValue = aulMessage[ 3 ]; ++ break; ++ ++ case ( 0xFFFF ): ++ ++ /* Bist is completed! */ ++ f_pProductionBist->ulBistStatus = cOCT6100_BIST_SUCCESS; ++ break; ++ ++ default: ++ /* Bist is in progress. All seems to be working fine up to now. */ ++ ++ /* Return progress status. */ ++ f_pProductionBist->ulCurrentAddress = ( aulMessage[ 1 ] & ( ~0x80000000 ) ) + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; ++ f_pProductionBist->ulCurrentTest = aulMessage[ 2 ]; ++ f_pProductionBist->ulCurrentLoop = aulMessage[ 3 ]; ++ break; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiProductionCrc ++ ++Description: This function calculates the crc for a production BIST ++ message. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pulMessage Message to be exchanged with the firmware. The CRC ++ will be calculated on this. ++f_ulMessageLength Length of the message to be exchanged. This value ++ does not include the CRC value at the end ++f_pulCrcResult Resulting calculated CRC value. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiProductionCrc ++UINT32 Oct6100ApiProductionCrc( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulMessage, ++ IN UINT32 f_ulMessageLength, ++ OUT PUINT32 f_pulCrcResult ) ++{ ++ UINT32 ulWidth = 32; ++ UINT32 ulKey, i, j; ++ UINT32 ulRemainder = 0; ++ ++ /* CRC the message. */ ++ ulRemainder = f_pulMessage[ f_ulMessageLength - 1 ]; ++ for ( j = f_ulMessageLength - 1; j != 0xFFFFFFFF ; j-- ) ++ { ++ for ( i = 0; i < ulWidth; i++ ) ++ { ++ if ( ( ( ulRemainder >> 0x1F ) & 0x1 ) == 0x1 ) ++ { ++ /* Division is by something meaningful */ ++ ulKey = 0x8765DCBA; ++ } ++ else ++ { ++ /* Remainder is less than our divisor */ ++ ulKey = 0; ++ } ++ ulRemainder = ulRemainder ^ ulKey; ++ ++ ulRemainder = ulRemainder << 1; ++ if ( j != 0 ) ++ { ++ ulRemainder = ulRemainder | ( ( f_pulMessage[ j - 1 ] ) >> ( 0x1F - i ) ); ++ } ++ } ++ } ++ ++ *f_pulCrcResult = ulRemainder; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiClearInterrupts ++ ++Description: Called only by the Oct6100OpenChip function, this function ++ writes to all register ROLs to clear them. This is necessary ++ because some ROLs are set during the startup. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++IN f_pApiInst Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiClearInterrupts ++UINT32 Oct6100ApiClearInterrupts( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ WriteParams.ulWriteAddress = 0x102; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_102H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x202; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_202H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x302; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_302H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x502; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_502H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x702; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_702H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++ ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,441 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_stats.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to retreive the OCT6100 chip stats. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 89 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_chip_stats_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_chip_stats_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_chip_stats_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChipGetStats ++ ++Description: Retreives the chip statistics and configuration. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChipStats Pointer to a tOCT6100_CHIP_STATS structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChipGetStatsDef ++UINT32 Oct6100ChipGetStatsDef( ++ tPOCT6100_CHIP_STATS f_pChipStats ) ++{ ++ f_pChipStats->fResetChipStats = FALSE; ++ ++ f_pChipStats->ulNumberChannels = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulNumberTsiCncts = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulNumberConfBridges = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulNumberPlayoutBuffers = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulPlayoutFreeMemSize = cOCT6100_INVALID_STAT; ++ ++ f_pChipStats->ulNumberPhasingTssts = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulNumberAdpcmChannels = cOCT6100_INVALID_STAT; ++ ++ f_pChipStats->ulH100OutOfSynchCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulH100ClockABadCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulH100FrameABadCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulH100ClockBBadCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulInternalReadTimeoutCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulSdramRefreshTooLateCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulPllJitterErrorCount = cOCT6100_INVALID_STAT; ++ ++ f_pChipStats->ulOverflowToneEventsCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulSoftOverflowToneEventsCount = cOCT6100_INVALID_STAT; ++ f_pChipStats->ulSoftOverflowBufferPlayoutEventsCount = cOCT6100_INVALID_STAT; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ChipGetStats ++UINT32 Oct6100ChipGetStats( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CHIP_STATS f_pChipStats ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ChipGetStatsSer( f_pApiInstance, f_pChipStats ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChipGetImageInfo ++ ++Description: Retrieves the chip image information indicating the supported ++ features and tones. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChipImageInfo Pointer to a tPOCT6100_CHIP_IMAGE_INFO structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChipGetImageInfoDef ++UINT32 Oct6100ChipGetImageInfoDef( ++ tPOCT6100_CHIP_IMAGE_INFO f_pChipImageInfo ) ++{ ++ UINT32 i; ++ ++ Oct6100UserMemSet( f_pChipImageInfo->szVersionNumber, 0x0, cOCT6100_VERSION_NUMBER_MAX_SIZE ); ++ ++ f_pChipImageInfo->fBufferPlayout = FALSE; ++ f_pChipImageInfo->fAdaptiveNoiseReduction = FALSE; ++ f_pChipImageInfo->fSoutNoiseBleaching = FALSE; ++ f_pChipImageInfo->fConferencingNoiseReduction = FALSE; ++ f_pChipImageInfo->fAutoLevelControl = FALSE; ++ f_pChipImageInfo->fHighLevelCompensation = FALSE; ++ f_pChipImageInfo->fSilenceSuppression = FALSE; ++ ++ f_pChipImageInfo->fAdpcm = FALSE; ++ f_pChipImageInfo->fConferencing = FALSE; ++ f_pChipImageInfo->fDominantSpeaker = FALSE; ++ f_pChipImageInfo->ulMaxChannels = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulNumTonesAvailable = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulToneProfileNumber = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulMaxTailDisplacement = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulBuildId = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulMaxTailLength = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulDebugEventSize = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulMaxPlayoutEvents = cOCT6100_INVALID_VALUE; ++ f_pChipImageInfo->ulImageType = cOCT6100_INVALID_VALUE; ++ ++ f_pChipImageInfo->fAcousticEcho = FALSE; ++ f_pChipImageInfo->fAecTailLength = FALSE; ++ f_pChipImageInfo->fToneRemoval = FALSE; ++ ++ f_pChipImageInfo->fDefaultErl = FALSE; ++ f_pChipImageInfo->fNonLinearityBehaviorA = FALSE; ++ f_pChipImageInfo->fNonLinearityBehaviorB = FALSE; ++ f_pChipImageInfo->fPerChannelTailDisplacement = FALSE; ++ f_pChipImageInfo->fPerChannelTailLength = FALSE; ++ f_pChipImageInfo->fListenerEnhancement = FALSE; ++ f_pChipImageInfo->fRoutNoiseReduction = FALSE; ++ f_pChipImageInfo->fRoutNoiseReductionLevel = FALSE; ++ f_pChipImageInfo->fAnrSnrEnhancement = FALSE; ++ f_pChipImageInfo->fAnrVoiceNoiseSegregation = FALSE; ++ f_pChipImageInfo->fToneDisablerVqeActivationDelay = FALSE; ++ f_pChipImageInfo->fMusicProtection = FALSE; ++ f_pChipImageInfo->fDoubleTalkBehavior = FALSE; ++ f_pChipImageInfo->fIdleCodeDetection = TRUE; ++ f_pChipImageInfo->fSinLevel = TRUE; ++ ++ for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) ++ { ++ Oct6100UserMemSet( f_pChipImageInfo->aToneInfo[ i ].aszToneName, 0x00, cOCT6100_TLV_MAX_TONE_NAME_SIZE ); ++ f_pChipImageInfo->aToneInfo[ i ].ulDetectionPort = cOCT6100_INVALID_PORT; ++ f_pChipImageInfo->aToneInfo[ i ].ulToneID = cOCT6100_INVALID_VALUE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ChipGetImageInfo ++UINT32 Oct6100ChipGetImageInfo( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CHIP_IMAGE_INFO f_pChipImageInfo ) ++{ ++ tPOCT6100_API_IMAGE_INFO pImageInfo; ++ UINT32 i; ++ ++ /* Get local pointer(s). */ ++ pImageInfo = &f_pApiInstance->pSharedInfo->ImageInfo; ++ ++ Oct6100UserMemCopy( f_pChipImageInfo->szVersionNumber, pImageInfo->szVersionNumber, cOCT6100_VERSION_NUMBER_MAX_SIZE ); ++ ++ /* Copy the customer info. */ ++ f_pChipImageInfo->ulBuildId = pImageInfo->ulBuildId; ++ ++ /* Copy the features list. */ ++ f_pChipImageInfo->fBufferPlayout = pImageInfo->fBufferPlayout; ++ f_pChipImageInfo->fAdaptiveNoiseReduction = pImageInfo->fAdaptiveNoiseReduction; ++ f_pChipImageInfo->fSoutNoiseBleaching = pImageInfo->fSoutNoiseBleaching; ++ f_pChipImageInfo->fSilenceSuppression = pImageInfo->fSilenceSuppression; ++ ++ f_pChipImageInfo->fAdpcm = pImageInfo->fAdpcm; ++ f_pChipImageInfo->fConferencing = pImageInfo->fConferencing; ++ f_pChipImageInfo->fDominantSpeaker = pImageInfo->fDominantSpeakerEnabled; ++ f_pChipImageInfo->fConferencingNoiseReduction = pImageInfo->fConferencingNoiseReduction; ++ f_pChipImageInfo->fAcousticEcho = pImageInfo->fAcousticEcho; ++ f_pChipImageInfo->fAecTailLength = pImageInfo->fAecTailLength; ++ f_pChipImageInfo->fDefaultErl = pImageInfo->fDefaultErl; ++ f_pChipImageInfo->fToneRemoval = pImageInfo->fToneRemoval; ++ ++ f_pChipImageInfo->fNonLinearityBehaviorA = pImageInfo->fNonLinearityBehaviorA; ++ f_pChipImageInfo->fNonLinearityBehaviorB = pImageInfo->fNonLinearityBehaviorB; ++ f_pChipImageInfo->fPerChannelTailDisplacement = pImageInfo->fPerChannelTailDisplacement; ++ f_pChipImageInfo->fListenerEnhancement = pImageInfo->fListenerEnhancement; ++ f_pChipImageInfo->fRoutNoiseReduction = pImageInfo->fRoutNoiseReduction; ++ f_pChipImageInfo->fRoutNoiseReductionLevel = pImageInfo->fRoutNoiseReductionLevel; ++ f_pChipImageInfo->fAnrSnrEnhancement = pImageInfo->fAnrSnrEnhancement; ++ f_pChipImageInfo->fAnrVoiceNoiseSegregation = pImageInfo->fAnrVoiceNoiseSegregation; ++ f_pChipImageInfo->fMusicProtection = pImageInfo->fMusicProtection; ++ f_pChipImageInfo->fIdleCodeDetection = pImageInfo->fIdleCodeDetection; ++ f_pChipImageInfo->fSinLevel = pImageInfo->fSinLevel; ++ f_pChipImageInfo->fDoubleTalkBehavior = pImageInfo->fDoubleTalkBehavior; ++ f_pChipImageInfo->fHighLevelCompensation = pImageInfo->fRinHighLevelCompensation; ++ ++ if ( ( pImageInfo->fRinAutoLevelControl == TRUE ) && ( pImageInfo->fSoutAutoLevelControl == TRUE ) ) ++ f_pChipImageInfo->fAutoLevelControl = TRUE; ++ else ++ f_pChipImageInfo->fAutoLevelControl = FALSE; ++ ++ f_pChipImageInfo->ulMaxChannels = pImageInfo->usMaxNumberOfChannels; ++ f_pChipImageInfo->ulNumTonesAvailable = pImageInfo->byNumToneDetectors; ++ f_pChipImageInfo->ulToneProfileNumber = pImageInfo->ulToneProfileNumber; ++ f_pChipImageInfo->ulMaxTailDisplacement = pImageInfo->usMaxTailDisplacement; ++ f_pChipImageInfo->ulMaxTailLength = pImageInfo->usMaxTailLength; ++ f_pChipImageInfo->fPerChannelTailLength = pImageInfo->fPerChannelTailLength; ++ f_pChipImageInfo->ulDebugEventSize = f_pApiInstance->pSharedInfo->DebugInfo.ulDebugEventSize; ++ f_pChipImageInfo->fToneDisablerVqeActivationDelay = pImageInfo->fToneDisablerVqeActivationDelay; ++ f_pChipImageInfo->ulMaxPlayoutEvents = pImageInfo->byMaxNumberPlayoutEvents - 1; /* 127 or 31 */ ++ f_pChipImageInfo->ulImageType = pImageInfo->byImageType; ++ ++ for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) ++ { ++ Oct6100UserMemCopy( f_pChipImageInfo->aToneInfo[ i ].aszToneName, pImageInfo->aToneInfo[ i ].aszToneName, cOCT6100_TLV_MAX_TONE_NAME_SIZE ); ++ f_pChipImageInfo->aToneInfo[ i ].ulDetectionPort = pImageInfo->aToneInfo[ i ].ulDetectionPort; ++ f_pChipImageInfo->aToneInfo[ i ].ulToneID = pImageInfo->aToneInfo[ i ].ulToneID; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiChipStatsSwInit ++ ++Description: Initializes portions of API instance associated to chip stats. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiChipStatsSwInit ++UINT32 Oct6100ApiChipStatsSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ /* Get local pointer to shared portion of API instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Initialize chip stats. */ ++ pSharedInfo->ErrorStats.fFatalChipError = FALSE; ++ ++ pSharedInfo->ErrorStats.ulH100ClkABadCnt = 0; ++ pSharedInfo->ErrorStats.ulH100ClkBBadCnt = 0; ++ pSharedInfo->ErrorStats.ulH100FrameABadCnt = 0; ++ pSharedInfo->ErrorStats.ulH100OutOfSyncCnt = 0; ++ ++ pSharedInfo->ErrorStats.ulInternalReadTimeoutCnt = 0; ++ pSharedInfo->ErrorStats.ulSdramRefreshTooLateCnt = 0; ++ pSharedInfo->ErrorStats.ulPllJitterErrorCnt = 0; ++ pSharedInfo->ErrorStats.ulOverflowToneEventsCnt = 0; ++ ++ ++ ++ pSharedInfo->ErrorStats.ulToneDetectorErrorCnt = 0; ++ ++ /* Init the chip stats. */ ++ pSharedInfo->ChipStats.usNumberChannels = 0; ++ pSharedInfo->ChipStats.usNumberBiDirChannels = 0; ++ pSharedInfo->ChipStats.usNumberTsiCncts = 0; ++ pSharedInfo->ChipStats.usNumberConfBridges = 0; ++ pSharedInfo->ChipStats.usNumberPlayoutBuffers = 0; ++ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts = 0; ++ pSharedInfo->ChipStats.ulPlayoutMemUsed = 0; ++ pSharedInfo->ChipStats.usNumEcChanUsingMixer = 0; ++ ++ pSharedInfo->ChipStats.usNumberPhasingTssts = 0; ++ pSharedInfo->ChipStats.usNumberAdpcmChans = 0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ChipGetStatsSer ++ ++Description: Serialized function retreiving the chip statistics. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pChipStats Pointer to master mode configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ChipGetStatsSer ++UINT32 Oct6100ChipGetStatsSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_CHIP_STATS f_pChipStats ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ f_pChipStats->ulNumberChannels = pSharedInfo->ChipStats.usNumberChannels; ++ f_pChipStats->ulNumberTsiCncts = pSharedInfo->ChipStats.usNumberTsiCncts; ++ f_pChipStats->ulNumberConfBridges = pSharedInfo->ChipStats.usNumberConfBridges; ++ f_pChipStats->ulNumberPlayoutBuffers = pSharedInfo->ChipStats.usNumberPlayoutBuffers; ++ f_pChipStats->ulPlayoutFreeMemSize = ( f_pApiInstance->pSharedInfo->MiscVars.ulTotalMemSize - ( f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress - cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ) - ( pSharedInfo->ChipStats.ulPlayoutMemUsed ); ++ ++ f_pChipStats->ulNumberPhasingTssts = pSharedInfo->ChipStats.usNumberPhasingTssts; ++ f_pChipStats->ulNumberAdpcmChannels = pSharedInfo->ChipStats.usNumberAdpcmChans; ++ ++ /* Check the input parameters. */ ++ if ( f_pChipStats->fResetChipStats != TRUE && ++ f_pChipStats->fResetChipStats != FALSE ) ++ return cOCT6100_ERR_CHIP_STATS_RESET; ++ ++ if ( f_pChipStats->fResetChipStats == TRUE ) ++ { ++ pSharedInfo->ErrorStats.ulH100OutOfSyncCnt = 0; ++ pSharedInfo->ErrorStats.ulH100ClkABadCnt = 0; ++ pSharedInfo->ErrorStats.ulH100FrameABadCnt = 0; ++ pSharedInfo->ErrorStats.ulH100ClkBBadCnt = 0; ++ ++ pSharedInfo->ErrorStats.ulInternalReadTimeoutCnt = 0; ++ pSharedInfo->ErrorStats.ulPllJitterErrorCnt = 0; ++ pSharedInfo->ErrorStats.ulSdramRefreshTooLateCnt = 0; ++ ++ pSharedInfo->ErrorStats.ulOverflowToneEventsCnt = 0; ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt = 0; ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt = 0; ++ ++ ++ } ++ ++ f_pChipStats->ulH100OutOfSynchCount = pSharedInfo->ErrorStats.ulH100OutOfSyncCnt; ++ f_pChipStats->ulH100ClockABadCount = pSharedInfo->ErrorStats.ulH100ClkABadCnt; ++ f_pChipStats->ulH100FrameABadCount = pSharedInfo->ErrorStats.ulH100FrameABadCnt; ++ f_pChipStats->ulH100ClockBBadCount = pSharedInfo->ErrorStats.ulH100ClkBBadCnt; ++ ++ f_pChipStats->ulInternalReadTimeoutCount = pSharedInfo->ErrorStats.ulInternalReadTimeoutCnt; ++ f_pChipStats->ulPllJitterErrorCount = pSharedInfo->ErrorStats.ulPllJitterErrorCnt; ++ f_pChipStats->ulSdramRefreshTooLateCount = pSharedInfo->ErrorStats.ulSdramRefreshTooLateCnt; ++ ++ f_pChipStats->ulOverflowToneEventsCount = pSharedInfo->ErrorStats.ulOverflowToneEventsCnt; ++ f_pChipStats->ulSoftOverflowToneEventsCount = pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt; ++ f_pChipStats->ulSoftOverflowBufferPlayoutEventsCount = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,7683 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_conf_bridge.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains all functions related to a conference bridge. Procedures ++ needed to open/close a bridge, add/remove a participant to a conference ++ bridge, mute/unmute a participant, etc.. are all present in this source ++ file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 146 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_mixer_inst.h" ++#include "oct6100api/oct6100_conf_bridge_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_mixer_pub.h" ++#include "oct6100api/oct6100_conf_bridge_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_tsst_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_mixer_priv.h" ++#include "oct6100_conf_bridge_priv.h" ++ ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeOpen ++ ++Description: This function opens a conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeOpen Pointer to conference bridge open structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeOpenDef ++UINT32 Oct6100ConfBridgeOpenDef( ++ tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) ++{ ++ f_pConfBridgeOpen->pulConfBridgeHndl = NULL; ++ f_pConfBridgeOpen->fFlexibleConferencing = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeOpen ++UINT32 Oct6100ConfBridgeOpen( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeOpenSer( f_pApiInstance, f_pConfBridgeOpen ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeClose ++ ++Description: This function closes a conference bridge. A conference ++ bridge can only be closed if no participants are present on ++ the bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeClose Pointer to conference bridge close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeCloseDef ++UINT32 Oct6100ConfBridgeCloseDef( ++ tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) ++{ ++ f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeClose ++UINT32 Oct6100ConfBridgeClose( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeCloseSer( f_pApiInstance, f_pConfBridgeClose ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanAdd ++ ++Description: This function adds an echo channel (participant) to a ++ conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeAdd Pointer to conference bridge channel addition structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanAddDef ++UINT32 Oct6100ConfBridgeChanAddDef( ++ tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ) ++{ ++ f_pConfBridgeAdd->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; ++ f_pConfBridgeAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT; ++ f_pConfBridgeAdd->ulListenerMaskIndex = cOCT6100_INVALID_VALUE; ++ f_pConfBridgeAdd->ulListenerMask = 0; ++ f_pConfBridgeAdd->fMute = FALSE; ++ f_pConfBridgeAdd->ulTappedChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeChanAdd ++UINT32 Oct6100ConfBridgeChanAdd( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeChanAddSer( f_pApiInstance, f_pConfBridgeAdd ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanRemove ++ ++Description: This function removes an echo channel (participant) from a ++ conference bridge. All participants can be removed from ++ the bridge if a special flag (fRemoveAll) is set to TRUE. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeRemove Pointer to conference bridge channel removal structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanRemoveDef ++UINT32 Oct6100ConfBridgeChanRemoveDef( ++ tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) ++{ ++ f_pConfBridgeRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pConfBridgeRemove->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; ++ f_pConfBridgeRemove->fRemoveAll = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeChanRemove ++UINT32 Oct6100ConfBridgeChanRemove( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, f_pConfBridgeRemove ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanMute ++ ++Description: This function mutes a participant present on a conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeMute Pointer to conference bridge channel mute structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanMuteDef ++UINT32 Oct6100ConfBridgeChanMuteDef( ++ tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ) ++{ ++ f_pConfBridgeMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeChanMute ++UINT32 Oct6100ConfBridgeChanMute( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeChanMuteSer( f_pApiInstance, f_pConfBridgeMute ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanUnMute ++ ++Description: This function unmutes a channel on a bridge. The other member ++ of the conference will start to hear this participant again. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeUnMute Pointer to conference bridge channel unmute structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanUnMuteDef ++UINT32 Oct6100ConfBridgeChanUnMuteDef( ++ tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ) ++{ ++ f_pConfBridgeUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ConfBridgeChanUnMute ++UINT32 Oct6100ConfBridgeChanUnMute( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeChanUnMuteSer( f_pApiInstance, f_pConfBridgeUnMute ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeDominantSpeakerSet ++ ++Description: This function sets a participant present on a conference ++ bridge as the dominant speaker. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++ ++f_pConfBridgeDominant Pointer to conference bridge dominant speaker ++ structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeDominantSpeakerSetDef ++UINT32 Oct6100ConfBridgeDominantSpeakerSetDef( ++ tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ) ++{ ++ f_pConfBridgeDominantSpeaker->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pConfBridgeDominantSpeaker->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeDominantSpeakerSet ++UINT32 Oct6100ConfBridgeDominantSpeakerSet( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeDominantSpeakerSetSer( f_pApiInstance, f_pConfBridgeDominantSpeaker ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeMaskChange ++ ++Description: This function changes the mask of a flexible bridge participant. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++ ++f_pConfBridgeMaskChange Pointer to conference bridge change of mask ++ structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeMaskChangeDef ++UINT32 Oct6100ConfBridgeMaskChangeDef( ++ tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ) ++{ ++ f_pConfBridgeMaskChange->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pConfBridgeMaskChange->ulNewListenerMask = 0x0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeMaskChange ++UINT32 Oct6100ConfBridgeMaskChange( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeMaskChangeSer( f_pApiInstance, f_pConfBridgeMaskChange ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeGetStats ++ ++Description: This function returns the stats for a conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeStats Pointer to conference bridge channel stats structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeGetStatsDef ++UINT32 Oct6100ConfBridgeGetStatsDef( ++ tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ) ++{ ++ f_pConfBridgeStats->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; ++ f_pConfBridgeStats->ulNumChannels = cOCT6100_INVALID_STAT; ++ f_pConfBridgeStats->ulNumTappedChannels = cOCT6100_INVALID_STAT; ++ f_pConfBridgeStats->fFlexibleConferencing = cOCT6100_INVALID_STAT; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ConfBridgeGetStats ++UINT32 Oct6100ConfBridgeGetStats( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ConfBridgeGetStatsSer( f_pApiInstance, f_pConfBridgeStats ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetConfBridgeSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of conference bridges. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetConfBridgeSwSizes ++UINT32 Oct6100ApiGetConfBridgeSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Calculate memory needed for conference bridge list. */ ++ if ( f_pOpenChip->ulMaxConfBridges == 0 && f_pOpenChip->fEnableChannelRecording == TRUE ) ++ f_pOpenChip->ulMaxConfBridges = 1; ++ f_pInstSizes->ulConfBridgeList = f_pOpenChip->ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE ); ++ ++ /* Calculate memory needed for conference bridge allocation software. */ ++ if ( f_pOpenChip->ulMaxConfBridges > 0 ) ++ { ++ /* Get size of bridge allocation memory */ ++ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxConfBridges, &f_pInstSizes->ulConfBridgeAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1C; ++ ++ /* Check if the user wants to build flexible conference bridges. */ ++ if ( f_pOpenChip->ulMaxFlexibleConfParticipants > 0 ) ++ { ++ /* Allocate the lowest quantity according to what the user requested. */ ++ if ( f_pOpenChip->ulMaxFlexibleConfParticipants < ( f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) ) ++ f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxFlexibleConfParticipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ); ++ else ++ { ++ f_pOpenChip->ulMaxFlexibleConfParticipants = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ++ f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ); ++ } ++ ++ /* Get size of flexible conferencing participants allocation memory */ ++ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxFlexibleConfParticipants, &f_pInstSizes->ulFlexConfParticipantsAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1C; ++ } ++ else ++ { ++ f_pInstSizes->ulFlexConfParticipantsList = 0; ++ f_pInstSizes->ulFlexConfParticipantsAlloc = 0; ++ } ++ } ++ else ++ { ++ f_pInstSizes->ulMixerEventList = 0; ++ f_pInstSizes->ulMixerEventAlloc = 0; ++ f_pInstSizes->ulConfBridgeAlloc = 0; ++ ++ /* Make sure flexible conferencing is not used. */ ++ f_pInstSizes->ulFlexConfParticipantsList = 0; ++ f_pInstSizes->ulFlexConfParticipantsAlloc = 0; ++ } ++ ++ /* Calculate memory needed for list and allocation software serialization. */ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeAlloc, ulTempVar ) ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsAlloc, ulTempVar ) ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiConfBridgeSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to conference bridges. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiConfBridgeSwInit ++UINT32 Oct6100ApiConfBridgeSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CONF_BRIDGE pConfBridgeList; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pFlexConfParticipantList; ++ PVOID pFlexConfPartipantsAlloc; ++ UINT32 ulMaxFlexConfParicipants; ++ PVOID pConfBridgeAlloc; ++ UINT32 ulMaxConfBridges; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get the maximum number of conference bridges. */ ++ ulMaxConfBridges = pSharedInfo->ChipConfig.usMaxConfBridges; ++ ++ /*===================================================================*/ ++ /* Set all entries in the conference bridge list to unused. */ ++ ++ mOCT6100_GET_CONF_BRIDGE_LIST_PNT( pSharedInfo, pConfBridgeList ); ++ ++ /* Initialize the conference bridge allocation software to "all free". */ ++ if ( ulMaxConfBridges > 0 ) ++ { ++ /* Clear the bridge memory */ ++ Oct6100UserMemSet( pConfBridgeList, 0x00, ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE )); ++ ++ mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( pSharedInfo, pConfBridgeAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pConfBridgeAlloc, ulMaxConfBridges ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1E; ++ } ++ /*===================================================================*/ ++ ++ ++ /*===================================================================*/ ++ /* Set all entries in the flexible conferencing participant list to unused. */ ++ ++ /* Get the maximum number of flexible conferencing participants. */ ++ ulMaxFlexConfParicipants = pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_LIST_PNT( pSharedInfo, pFlexConfParticipantList ); ++ ++ /* Initialize the flexible conferencing allocation software. */ ++ if ( ulMaxFlexConfParicipants > 0 ) ++ { ++ UINT32 i, ulEventIndex; ++ ++ /* Clear the participants memory */ ++ Oct6100UserMemSet( pFlexConfParticipantList, 0x00, ulMaxFlexConfParicipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT )); ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( pSharedInfo, pFlexConfPartipantsAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pFlexConfPartipantsAlloc, ulMaxFlexConfParicipants ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1E; ++ ++ /* Initialize the conferencing indexes. */ ++ for ( i = 0; i < ulMaxFlexConfParicipants; i ++ ) ++ { ++ for ( ulEventIndex = 0; ulEventIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulEventIndex ++ ) ++ pFlexConfParticipantList[ i ].ausLoadOrAccumulateEventIndex[ ulEventIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ /*===================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeOpenSer ++ ++Description: Open a conference bridge. Note that no chip resources are ++ allocated until a channel is added to the bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeOpen Pointer to conference bridge configuration structure. ++ The handle identifying the conference bridge in all ++ future function calls is returned in this structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeOpenSer ++UINT32 Oct6100ConfBridgeOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) ++{ ++ UINT16 usBridgeIndex; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the conference bridge for errors. */ ++ ulResult = Oct6100ApiCheckBridgeParams( f_pApiInstance, f_pConfBridgeOpen ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the conference bridge. */ ++ ulResult = Oct6100ApiReserveBridgeResources( f_pApiInstance, &usBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the new conference bridge's entry in the conference bridge list. */ ++ ulResult = Oct6100ApiUpdateBridgeEntry( f_pApiInstance, f_pConfBridgeOpen, usBridgeIndex); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBridgeParams ++ ++Description: Checks the user's conference bridge open configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeOpen Pointer to conference bridge configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBridgeParams ++UINT32 Oct6100ApiCheckBridgeParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ) ++{ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ if ( f_pConfBridgeOpen->pulConfBridgeHndl == NULL ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fConferencing == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_CONF_BRIDGE; ++ ++ if ( f_pConfBridgeOpen->fFlexibleConferencing != FALSE ++ && f_pConfBridgeOpen->fFlexibleConferencing != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBridgeResources ++ ++Description: Reserves all resources needed for the new conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pusBridgeIndex Allocated entry in the API conference bridge list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBridgeResources ++UINT32 Oct6100ApiReserveBridgeResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusBridgeIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Reserve an entry in the conference bridge list. */ ++ ulResult = Oct6100ApiReserveBridgeEntry( f_pApiInstance, f_pusBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateBridgeEntry ++ ++Description: Updates the new conference bridge's entry in the conference ++ bridge list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pConfBridgeOpen Pointer to conference bridge configuration structure. ++f_usBridgeIndex Allocated entry in API conference bridge list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateBridgeEntry ++UINT32 Oct6100ApiUpdateBridgeEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen, ++ IN UINT16 f_usBridgeIndex ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; ++ ++ /*================================================================================*/ ++ /* Obtain a pointer to the new conference bridge's list entry. */ ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ) ++ ++ /* No clients are currently connected to the bridge. */ ++ pBridgeEntry->usNumClients = 0; ++ /* Nobody is tapped for now. */ ++ pBridgeEntry->usNumTappedClients = 0; ++ pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Now update the bridge pointer. */ ++ if ( f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened == 0 ) ++ { ++ pBridgeEntry->usNextBridgePtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX; ++ ++ /* Set the global first bridge to this bridge. */ ++ f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex; ++ } ++ else /* Insert this bridge at the head of the bridge list.*/ ++ { ++ if ( f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_FATAL_22; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge ) ++ ++ if ( pTempBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_FATAL_23; ++ ++ /* Modify the old first entry. */ ++ pTempBridgeEntry->usPrevBridgePtr = f_usBridgeIndex; ++ ++ /* Modify current pointer. */ ++ pBridgeEntry->usPrevBridgePtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usNextBridgePtr = f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge; ++ ++ /* Set the new first bridge of the list. */ ++ f_pApiInstance->pSharedInfo->MiscVars.usFirstBridge = f_usBridgeIndex; ++ } ++ ++ /* Form handle returned to user. */ ++ *f_pConfBridgeOpen->pulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usBridgeIndex; ++ ++ /* Remember whether or not we are a flexible conference bridge. */ ++ pBridgeEntry->fFlexibleConferencing = (UINT8)( f_pConfBridgeOpen->fFlexibleConferencing & 0xFF ); ++ ++ /* Finally, mark the conference bridge as opened. */ ++ pBridgeEntry->fReserved = TRUE; ++ ++ /* Increment the number of conference bridge opened. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberConfBridges++; ++ f_pApiInstance->pSharedInfo->MiscVars.usNumBridgesOpened++; ++ ++ /*================================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeCloseSer ++ ++Description: Closes a conference bridge. Note that no client must be present ++ on the bridge for the bridge to be closed. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeClose Pointer to conference bridge close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeCloseSer ++UINT32 Oct6100ConfBridgeCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) ++{ ++ UINT16 usBridgeIndex; ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertBridgeParams( f_pApiInstance, f_pConfBridgeClose, &usBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the conference bridge. */ ++ ulResult = Oct6100ApiReleaseBridgeResources( f_pApiInstance, usBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Invalidate the handle. */ ++ f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertBridgeParams ++ ++Description: Checks the user's conference bridge close configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeClose Pointer to conference bridge close structure. ++f_pusBridgeIndex Pointer to API instance conference bridge index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertBridgeParams ++UINT32 Oct6100ApiAssertBridgeParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose, ++ OUT PUINT16 f_pusBridgeIndex ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check the provided handle. */ ++ if ( (f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusBridgeIndex = (UINT16)( f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeClose->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( pBridgeEntry->usNumClients != 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_ACTIVE_DEPENDENCIES; ++ if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBridgeResources ++ ++Description: Release all resources reserved for the conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usBridgeIndex Allocated external memory block for the conference bridge. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBridgeResources ++UINT32 Oct6100ApiReleaseBridgeResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Release the entry from the conference bridge list. */ ++ ulResult = Oct6100ApiReleaseBridgeEntry( f_pApiInstance, f_usBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_24; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); ++ ++ /* Remove the bridge entry from the bridge list. */ ++ if ( pSharedInfo->MiscVars.usNumBridgesOpened == 1 ) ++ { ++ /* This bridge was the only one opened. */ ++ pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX; ++ } ++ else if ( pSharedInfo->MiscVars.usNumBridgesOpened > 1 ) ++ { ++ /* There are more then one bridge open, must update the list. */ ++ if ( pBridgeEntry->usPrevBridgePtr != cOCT6100_INVALID_INDEX ) ++ { ++ /* There is a valid entry before this bridge, let's update this entry. */ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usPrevBridgePtr ); ++ ++ pTempBridgeEntry->usNextBridgePtr = pBridgeEntry->usNextBridgePtr; ++ } ++ ++ if ( pBridgeEntry->usNextBridgePtr != cOCT6100_INVALID_INDEX ) ++ { ++ /* There is a valid entry after this bridge, let's update this entry. */ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usNextBridgePtr ); ++ ++ pTempBridgeEntry->usPrevBridgePtr = pBridgeEntry->usPrevBridgePtr; ++ } ++ ++ if ( pSharedInfo->MiscVars.usFirstBridge == f_usBridgeIndex ) ++ { ++ /* This entry was the first of the list, make the next one be the first now. */ ++ pSharedInfo->MiscVars.usFirstBridge = pBridgeEntry->usNextBridgePtr; ++ } ++ } ++ else ++ { ++ /* Variable has become out of sync. */ ++ return cOCT6100_ERR_FATAL_25; ++ } ++ ++ /*=============================================================*/ ++ /* Update the conference bridge's list entry. */ ++ ++ /* Mark the bridge as closed. */ ++ pBridgeEntry->fFlexibleConferencing = FALSE; ++ pBridgeEntry->fReserved = FALSE; ++ pBridgeEntry->byEntryOpenCnt++; ++ ++ /* Decrement the number of conference bridges opened. */ ++ pSharedInfo->MiscVars.usNumBridgesOpened--; ++ pSharedInfo->ChipStats.usNumberConfBridges--; ++ ++ /*=============================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanAddSer ++ ++Description: Adds an echo channel (participant) to a conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeAdd Pointer to conference bridge channel add structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanAddSer ++UINT32 Oct6100ConfBridgeChanAddSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ) ++{ ++ UINT16 usBridgeIndex; ++ UINT16 usChanIndex; ++ UINT16 usLoadEventIndex; ++ UINT16 usSubStoreEventIndex; ++ UINT16 usCopyEventIndex; ++ UINT32 ulInputPort; ++ UINT8 fFlexibleConfBridge; ++ UINT32 ulListenerMaskIndex; ++ UINT32 ulListenerMask; ++ UINT16 usTapChanIndex; ++ UINT16 usTapBridgeIndex; ++ UINT8 fMute; ++ UINT8 fTap; ++ UINT32 ulResult; ++ ++ /* Check the validity of the channel and conference bridge given. */ ++ ulResult = Oct6100ApiCheckBridgeAddParams( ++ f_pApiInstance, ++ f_pConfBridgeAdd, ++ &usBridgeIndex, ++ &usChanIndex, ++ &fMute, ++ &ulInputPort, ++ &fFlexibleConfBridge, ++ &ulListenerMaskIndex, ++ &ulListenerMask, ++ &fTap, ++ &usTapChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the conference bridge. */ ++ ulResult = Oct6100ApiReserveBridgeAddResources( ++ f_pApiInstance, ++ usBridgeIndex, ++ usChanIndex, ++ ulInputPort, ++ fFlexibleConfBridge, ++ ulListenerMaskIndex, ++ ulListenerMask, ++ fTap, ++ &usLoadEventIndex, ++ &usSubStoreEventIndex, ++ &usCopyEventIndex, ++ &usTapBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the conference bridge. */ ++ ulResult = Oct6100ApiBridgeEventAdd( ++ f_pApiInstance, ++ usBridgeIndex, ++ usChanIndex, ++ fFlexibleConfBridge, ++ usLoadEventIndex, ++ usSubStoreEventIndex, ++ usCopyEventIndex, ++ ulInputPort, ++ fMute, ++ ulListenerMaskIndex, ++ ulListenerMask, ++ fTap, ++ usTapBridgeIndex, ++ usTapChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBridgeAddParams ++ ++Description: Check the validity of the channel and conference bridge given. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pConfBridgeAdd Pointer to conference bridge channenl add structure. ++f_pusBridgeIndex Extracted bridge index where this channel should be ++ added. ++f_pusChannelIndex Extracted channel index related to the channel handle ++ to be added to the bridge. ++f_pfMute Whether to mute this channel in the bridge or not. ++f_pulInputPort Input port where the channel signal should be ++ copied from. ++f_pfFlexibleConfBridge If this is a flexible conference bridge. ++f_pulListenerMaskIndex Index of the listener in this flexible conference bridge. ++f_pulListenerMask Mask of listeners in this flexible conference bridge. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBridgeAddParams ++UINT32 Oct6100ApiCheckBridgeAddParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd, ++ OUT PUINT16 f_pusBridgeIndex, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT8 f_pfMute, ++ OUT PUINT32 f_pulInputPort, ++ OUT PUINT8 f_pfFlexibleConfBridge, ++ OUT PUINT32 f_pulListenerMaskIndex, ++ OUT PUINT32 f_pulListenerMask, ++ OUT PUINT8 f_pfTap, ++ OUT PUINT16 f_pusTapChannelIndex ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ UINT32 ulEntryOpenCnt; ++ UINT8 byTapChannelLaw; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 1 && ++ f_pApiInstance->pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ if ( f_pConfBridgeAdd->ulConfBridgeHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ if ( f_pConfBridgeAdd->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; ++ ++ if( f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_SOUT ++ && f_pConfBridgeAdd->ulInputPort != cOCT6100_CHANNEL_PORT_RIN ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_INPUT_PORT; ++ ++ if ( f_pConfBridgeAdd->fMute != TRUE && f_pConfBridgeAdd->fMute != FALSE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_MUTE; ++ ++ /*=====================================================================*/ ++ /* Check the conference bridge handle. */ ++ ++ if ( (f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusBridgeIndex = (UINT16)( f_pConfBridgeAdd->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeAdd->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /* When we a flexible conference bridge, more things need to be checked. */ ++ if ( pBridgeEntry->fFlexibleConferencing == TRUE ) ++ { ++ /* Check if flexible conferencing has been activated. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_DISABLED; ++ ++ /* Check the number of clients on the bridge. */ ++ if ( pBridgeEntry->usNumClients >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) ++ return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_PARTICIPANT_CNT; ++ ++ /* Check if the listener index in a flexible bridge is valid. */ ++ if ( f_pConfBridgeAdd->ulListenerMaskIndex == cOCT6100_INVALID_VALUE ++ || f_pConfBridgeAdd->ulListenerMaskIndex >= cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) ++ return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_MASK_INDEX; ++ } ++ ++ if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE ) ++ { ++ if ( pBridgeEntry->fFlexibleConferencing == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_TAP_NOT_SUPPORTED; ++ } ++ ++ /*=====================================================================*/ ++ ++ ++ /*=====================================================================*/ ++ /* Check the channel handle. */ ++ ++ if ( (f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; ++ ++ *f_pusChannelIndex = (UINT16)( f_pConfBridgeAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ if ( pEchoChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ALREADY_ON_BRIDGE; ++ if ( pEchoChanEntry->fBiDirChannel == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_BIDIR; ++ /* Law conversion is not allowed on a conference bridge. */ ++ if ( ( pEchoChanEntry->TdmConfig.usRinTimeslot != cOCT6100_UNASSIGNED ) ++ && ( pEchoChanEntry->TdmConfig.usRoutTimeslot != cOCT6100_UNASSIGNED ) ) ++ { ++ if ( pEchoChanEntry->TdmConfig.byRinPcmLaw != pEchoChanEntry->TdmConfig.byRoutPcmLaw ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION; ++ } ++ if ( ( pEchoChanEntry->TdmConfig.usSinTimeslot != cOCT6100_UNASSIGNED ) ++ && ( pEchoChanEntry->TdmConfig.usSoutTimeslot != cOCT6100_UNASSIGNED ) ) ++ { ++ if ( pEchoChanEntry->TdmConfig.bySinPcmLaw != pEchoChanEntry->TdmConfig.bySoutPcmLaw ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_LAW_CONVERSION; ++ } ++ if ( pEchoChanEntry->fRinRoutCodecActive == TRUE || pEchoChanEntry->fSinSoutCodecActive == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_CODEC_ACTIVE; ++ if ( pEchoChanEntry->fEnableExtToneDetection == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_EXT_TONE_ENABLED; ++ if ( pEchoChanEntry->usCopyEventCnt != 0x0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_COPY_EVENTS; ++ ++ /* If the bridge is flexible, few more things need to be checked. */ ++ if ( pBridgeEntry->fFlexibleConferencing == TRUE ) ++ { ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT16 usChannelIndex; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check if the listener index has been used by another channel in the specified bridge. */ ++ for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != ( *f_pusChannelIndex ) ) && ( pEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pEchoChanEntry->usBridgeIndex == ( *f_pusBridgeIndex ) ) ++ { ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if this participant has the same listener index. */ ++ if ( f_pConfBridgeAdd->ulListenerMaskIndex == pCurrentParticipant->ulListenerMaskIndex ) ++ return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_LISTENER_INDEX_USED; ++ } ++ } ++ } ++ } ++ ++ if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE ) ++ { ++ /* For internal logic, make sure the mute flag is set to false. */ ++ f_pConfBridgeAdd->fMute = FALSE; ++ ++ /* Force input port to Sout for logic below. */ ++ f_pConfBridgeAdd->ulInputPort = cOCT6100_CHANNEL_PORT_SOUT; ++ ++ /* Keep law to check for conversion. */ ++ /* Check if the same law. */ ++ byTapChannelLaw = pEchoChanEntry->TdmConfig.bySoutPcmLaw; ++ ++ /* Check the tap handle. */ ++ if ( (f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE; ++ ++ *f_pusTapChannelIndex = (UINT16)( f_pConfBridgeAdd->ulTappedChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusTapChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusTapChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeAdd->ulTappedChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_TAP_HANDLE; ++ if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_BRIDGE; ++ if ( pEchoChanEntry->usBridgeIndex != *f_pusBridgeIndex ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_NOT_ON_SAME_BRIDGE; ++ ++ /* We can only tap a channel added on the Sout port. */ ++ if ( pEchoChanEntry->usSinCopyEventIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_TAP_SOUT_ONLY; ++ ++ /* Check if already tapped. */ ++ if ( pEchoChanEntry->fBeingTapped == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_ALREADY_TAPPED; ++ } ++ ++ /*=====================================================================*/ ++ ++ /* Return the tap flag. */ ++ if ( f_pConfBridgeAdd->ulTappedChannelHndl != cOCT6100_INVALID_HANDLE ) ++ { ++ *f_pfTap = TRUE; ++ } ++ else ++ { ++ *f_pfTap = FALSE; ++ } ++ ++ /* Return the mute config specified. */ ++ *f_pfMute = (UINT8)( f_pConfBridgeAdd->fMute & 0xFF ); ++ ++ /* Return the input port specified. */ ++ *f_pulInputPort = f_pConfBridgeAdd->ulInputPort; ++ ++ /* Return whether we are in the flexible conference bridge case. */ ++ *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; ++ ++ /* Return the listener mask index as specified. */ ++ *f_pulListenerMaskIndex = f_pConfBridgeAdd->ulListenerMaskIndex; ++ ++ /* Return the listener mask as specified. */ ++ *f_pulListenerMask = f_pConfBridgeAdd->ulListenerMask; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBridgeAddResources ++ ++Description: Reserves all resources needed for the addition of a channel to ++ the conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_usBridgeIndex Bridge index of the bridge where this channel is added. ++f_usChanIndex Channel index of the channel to be added to the bridge. ++f_ulInputPort Input port where to copy samples from. ++f_fFlexibleConfBridge If this is a flexible conference bridge. ++f_ulListenerMaskIndex Index of the listener in this flexible conference bridge. ++f_ulListenerMask Mask of listeners in this flexible conference bridge. ++f_pusLoadEventIndex Load event index within the API's list of mixer event. ++f_pusSubStoreEventIndex Sub-Store event index within the API's list of mixer event. ++f_pusCopyEventIndex Copy event index within the API's list of mixer event. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBridgeAddResources ++UINT32 Oct6100ApiReserveBridgeAddResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT32 f_ulInputPort, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT32 f_ulListenerMaskIndex, ++ IN UINT32 f_ulListenerMask, ++ IN UINT8 f_fTap, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT16 f_pusCopyEventIndex, ++ OUT PUINT16 f_pusTapBridgeIndex ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ UINT32 ulResult; ++ UINT32 ulTempVar; ++ UINT16 usChannelIndex; ++ BOOL fLoadEventReserved = FALSE; ++ BOOL fStoreEventReserved = FALSE; ++ BOOL fCopyEventReserved = FALSE; ++ BOOL fExtraSinTsiReserved = FALSE; ++ BOOL fExtraRinTsiReserved = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ /* Resources must be reserved according to the type of bridge we are adding to. */ ++ if ( f_fFlexibleConfBridge == TRUE ) ++ { ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant; ++ ++ /*========================================================================*/ ++ /* If we are in the flexible conferencing case, things are a little */ ++ /* different. We create a mixer for every participant instead of the */ ++ /* usual same mixer for everyone. For example, if we have 3 participants */ ++ /* of type client - agent - coach, we build the mixers as follows: */ ++ /* */ ++ /* Client: - Load Agent */ ++ /* - Store */ ++ /* */ ++ /* Agent: - Load Client */ ++ /* - Accumulate Coach */ ++ /* - Store */ ++ /* */ ++ /* Coach: - Load Client */ ++ /* - Accumulate Agent */ ++ /* - Store */ ++ /* */ ++ /*========================================================================*/ ++ ++ /* First reserve a flexible conferencing participant entry. */ ++ ulResult = Oct6100ApiReserveFlexConfParticipantEntry( f_pApiInstance, &pChanEntry->usFlexConfParticipantIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Reserve an entry for the store event in the mixer memory. */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* If using the SOUT port, we must copy this entry */ ++ if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ /* Reserve an entry for the copy event in the Mixer memory. */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fCopyEventReserved = TRUE; ++ ++ /* Reserve a SIN copy entry if none were reserved before.*/ ++ if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* Reserve an entry for the extra tsi chariot memory. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ &pChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fExtraSinTsiReserved = TRUE; ++ } ++ } ++ } ++ else /* if( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ ++ { ++ /* Reserve a RIN copy entry if none were reserved before.*/ ++ if ( pChanEntry->usExtraRinTsiMemIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* Reserve an entry for the extra tsi chariot memory. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ &pChanEntry->usExtraRinTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fExtraRinTsiReserved = TRUE; ++ } ++ } ++ ++ /* Must travel all clients of this conference and reserve a load or accumulate event for */ ++ /* all participants which can hear us. */ ++ ++ /* Search through the list of API channel entry for the ones on to this bridge.*/ ++ for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can hear this participant. */ ++ if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ { ++ /* Must reserve a load or accumulate entry mixer event here! */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Most probably, the hardware is out of mixer events. */ ++ break; ++ } ++ } ++ ++ /* Check if this participant can hear us. */ ++ if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) ++ { ++ /* Must reserve a load or accumulate entry mixer event here! */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Most probably, the hardware is out of mixer events. */ ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ /* If an error is returned, make sure everything is cleaned up properly. */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Release the flexible conferencing participant entry. */ ++ ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Release the substore event in the mixer memory. */ ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ if ( fCopyEventReserved == TRUE ) ++ { ++ /* Release the copy event in the mixer memory. */ ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fExtraSinTsiReserved == TRUE ) ++ { ++ /* Release the extra Sin TSI in TSI memory. */ ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ if ( fExtraRinTsiReserved == TRUE ) ++ { ++ /* Release the extra Rin TSI in TSI memory. */ ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraRinTsiMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Search through the list of API channel entry for the ones on to this bridge. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can hear this participant. */ ++ if ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ { ++ /* If the load or event entry in the mixer memory was reserved. */ ++ if ( pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ /* Must release the load or accumulate entry mixer event. */ ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ /* Check this participant can hear us. */ ++ if ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) ++ { ++ /* If the load or event entry in the mixer memory was reserved. */ ++ if ( pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ /* Must release the load or accumulate entry mixer event. */ ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ } ++ } ++ ++ return ulResult; ++ } ++ } ++ else /* if ( ulResult != cOCT6100_ERR_OK ) */ ++ { ++ ulTempVar = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pChanEntry->usFlexConfParticipantIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Return the error code to the user. The mixer event allocation failed. */ ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ } ++ else /* if ( f_fFlexibleConfBridge == FALSE ) */ ++ { ++ /*=======================================================================*/ ++ /* Normal conferencing. */ ++ ++ /* Reserve an entry for the load event in the mixer memory. */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusLoadEventIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fLoadEventReserved = TRUE; ++ /* Reserve an entry for the substract and store event in the mixer memory. */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusSubStoreEventIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fStoreEventReserved = TRUE; ++ ++ /* If using the SOUT port, we must copy this entry */ ++ if( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ /* Reserve an entry for the copy event in the mixer memory. */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, f_pusCopyEventIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fCopyEventReserved = TRUE; ++ ++ /* Reserve a SIN copy entry if none were reserved before. */ ++ if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* Reserve an entry for the extra tsi chariot memory. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, ++ &pChanEntry->usExtraSinTsiMemIndex ); ++ ++ if ( ulResult == cOCT6100_ERR_OK ) ++ fExtraSinTsiReserved = TRUE; ++ } ++ } ++ } ++ } ++ } ++ ++ if ( ( ulResult == cOCT6100_ERR_OK ) && ( f_fTap == TRUE ) ) ++ { ++ /* Reserve a "tap" bridge. */ ++ tOCT6100_CONF_BRIDGE_OPEN ConfBridgeOpen; ++ UINT32 ulTapBridgeHndl = 0; ++ ++ Oct6100ConfBridgeOpenDef( &ConfBridgeOpen ); ++ ++ ConfBridgeOpen.pulConfBridgeHndl = &ulTapBridgeHndl; ++ ++ ulResult = Oct6100ConfBridgeOpenSer( f_pApiInstance, &ConfBridgeOpen ); ++ ++ *f_pusTapBridgeIndex = (UINT16)( ulTapBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); ++ } ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( fLoadEventReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusLoadEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fStoreEventReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusSubStoreEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fCopyEventReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, *f_pusCopyEventIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if ( fExtraSinTsiReserved == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBridgeEventAdd ++ ++Description: Add the event into the global event list of the chip and update ++ the bridge and channel structures. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++f_usBridgeIndex Index of the current bridge in the API list. ++f_usChanIndex Index of the current channel in the API list. ++f_fFlexibleConfBridge If this is a flexible conference bridge. ++f_usLoadEventIndex Allocated entry for the Load event of the ++ channel. ++f_usSubStoreEventIndex Allocated entry for the substract and store ++ event of the channel. ++f_usCopyEventIndex Allocated entry for the copy event of the ++ channel. ++f_ulInputPort Input port where to copy samples from. ++f_fMute Mute flag indicating if the channel is added in ++ a mute state. ++f_ulListenerMaskIndex Index of the listener in this flexible conference bridge. ++f_ulListenerMask Mask of listeners in this flexible conference bridge. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBridgeEventAdd ++UINT32 Oct6100ApiBridgeEventAdd( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT32 f_ulInputPort, ++ IN UINT8 f_fMute, ++ IN UINT32 f_ulListenerMaskIndex, ++ IN UINT32 f_ulListenerMask, ++ IN UINT8 f_fTap, ++ IN UINT16 f_usTapBridgeIndex, ++ IN UINT16 f_usTapChanIndex ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ tPOCT6100_API_MIXER_EVENT pLoadEventEntry; ++ tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEntry; ++ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_API_CHANNEL pTapEchoChanEntry = NULL; ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ ++ UINT32 ulResult; ++ UINT16 usChannelIndex; ++ UINT16 usLastSubStoreEventIndex; ++ UINT16 usLastLoadEventIndex; ++ ++ BOOL fAddSinCopy = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Get the bridge and channel entries of interest. */ ++ if ( f_fTap == FALSE ) ++ { ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex ); ++ } ++ else ++ { ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usTapBridgeIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTapEchoChanEntry, f_usTapChanIndex ); ++ } ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ ++ if ( f_fFlexibleConfBridge == TRUE ) ++ { ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pNewParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pCurrentParticipant; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pNewParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Search through the list of API channel entry for the ones onto this bridge. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pCurrentParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can hear this participant. */ ++ if ( ( pTempEchoChanEntry->fMute == FALSE ) && ( ( f_ulListenerMask & ( 0x1 << pCurrentParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) ++ { ++ /* First create/update the current channel's mixer. */ ++ ulResult = Oct6100ApiBridgeAddParticipantToChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ usChannelIndex, ++ f_usChanIndex, ++ pNewParticipant->ausLoadOrAccumulateEventIndex[ pCurrentParticipant->ulListenerMaskIndex ], ++ f_usSubStoreEventIndex, ++ f_usCopyEventIndex, ++ pCurrentParticipant->ulInputPort, ++ f_ulInputPort ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Check if this participant can hear us. */ ++ if ( ( f_fMute == FALSE ) && ( ( pCurrentParticipant->ulListenerMask & ( 0x1 << f_ulListenerMaskIndex ) ) == 0x0 ) ) ++ { ++ /* Then create/update this channel's mixer. */ ++ ulResult = Oct6100ApiBridgeAddParticipantToChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ f_usChanIndex, ++ usChannelIndex, ++ pCurrentParticipant->ausLoadOrAccumulateEventIndex[ f_ulListenerMaskIndex ], ++ pTempEchoChanEntry->usSubStoreEventIndex, ++ pTempEchoChanEntry->usSinCopyEventIndex, ++ f_ulInputPort, ++ pCurrentParticipant->ulInputPort ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the Rin silence event can be cleared now that the */ ++ /* channel has been added to a conference. */ ++ if ( ( pCurrentParticipant->fFlexibleMixerCreated == TRUE ) ++ && ( pTempEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) ++ { ++ /* Remove the event from the list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pTempEchoChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempEchoChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_DF; ++ ++ pTempEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ } ++ } ++ ++ /* Check if the mixer for the destination channel has been created. */ ++ if ( pNewParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /* Save store event index that might be used for next channel added. */ ++ pEchoChanEntry->usSubStoreEventIndex = f_usSubStoreEventIndex; ++ } ++ else ++ { ++ /* Check if the Rin silence event can be cleared now that the */ ++ /* channel has been added to a conference. */ ++ if ( pEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pEchoChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_DF; ++ ++ pEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ pNewParticipant->ulListenerMaskIndex = f_ulListenerMaskIndex; ++ pNewParticipant->ulListenerMask = f_ulListenerMask; ++ ++ /* Remember this channel's input port. */ ++ pNewParticipant->ulInputPort = f_ulInputPort; ++ ++ /*=======================================================================*/ ++ } ++ else /* if ( f_fFlexibleConfBridge == FALSE ) */ ++ { ++ /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */ ++ if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) ) ++ { ++ if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pEchoChanEntry->usSinTsstIndex, ++ pEchoChanEntry->usExtraSinTsiMemIndex, ++ pEchoChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If the silence TSI is loaded on this port, update with the extra sin TSI. */ ++ if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pEchoChanEntry->usExtraSinTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); ++ ++ /*=======================================================================*/ ++ /* Program the Load event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ if ( ( f_fMute == FALSE ) || ( f_fTap == TRUE ) ) ++ { ++ if ( pBridgeEntry->usLoadIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ ++ /* Set the event type. */ ++ pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ ++ if ( f_fTap == TRUE ) ++ return cOCT6100_ERR_FATAL_D1; ++ } ++ else /* pBridgeEntry->usLoadIndex == cOCT6100_INVALID_INDEX */ ++ { ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ ++ /* Modify the bridge entry to show store the new load index.*/ ++ pBridgeEntry->usLoadIndex = f_usLoadEventIndex; ++ ++ /* Set the event type.*/ ++ pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ } ++ ++ /* Select the TSI memory index according to the source port. */ ++ if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ if ( f_fTap == FALSE ) ++ { ++ WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; ++ } ++ else ++ { ++ tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; ++ UINT16 usTempWriteData; ++ UINT32 ulTempWriteAddress; ++ ++ /* Save temp write data before trying to clear the Rin TSST. */ ++ usTempWriteData = WriteParams.usWriteData; ++ ulTempWriteAddress = WriteParams.ulWriteAddress; ++ ++ /* Clear the Rin TSST if used. */ ++ if ( pTapEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Deactivate the TSST entry.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pTapEchoChanEntry->usRinTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Reassign write data that might have been cleared by write above. */ ++ WriteParams.usWriteData = usTempWriteData; ++ WriteParams.ulWriteAddress = ulTempWriteAddress; ++ WriteParams.usWriteData |= pTapEchoChanEntry->usRinRoutTsiMemIndex; ++ ++ /* Remember that this channel is being tapped by us. */ ++ pTapEchoChanEntry->fBeingTapped = TRUE; ++ pTapEchoChanEntry->usTapChanIndex = f_usChanIndex; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex ); ++ ++ pTempBridgeEntry->usNumTappedClients++; ++ } ++ } ++ else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ ++ { ++ WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; ++ } ++ } ++ else /* f_fMute == TRUE */ ++ { ++ /* Do not load the sample if the channel is muted. */ ++ if ( pBridgeEntry->usNumClients == 0 ) ++ { ++ /* If the participant to be added is muted, and it would cause the conference to */ ++ /* be completely muted, load the silence TSI. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */ ++ ++ /* We know for sure that the load of the bridge will be the silence one. */ ++ pBridgeEntry->usSilenceLoadEventPtr = f_usLoadEventIndex; ++ } ++ else ++ { ++ /* Do nothing! */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ } ++ ++ /* Set the event type. */ ++ pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Program the Substract and store event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ if ( ( f_fMute == FALSE ) && ( f_fTap == FALSE ) ) ++ { ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; ++ /* Select the TSI memory index and PCM law according to the source port. */ ++ if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; ++ } ++ else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ ++ { ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; ++ } ++ ++ /* Set the event type. */ ++ pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; ++ } ++ else /* f_fMute == TRUE */ ++ { ++ /* Do not substore the sample if the channel is muted. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE; ++ ++ /* Select the PCM law according to the source port. */ ++ if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ } ++ else /* if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ ++ { ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ } ++ /* Set the event type. */ ++ pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pEchoChanEntry->usRinRoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Program the Copy event - if using the SOUT port */ ++ if ( ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( f_fTap == FALSE ) ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= pEchoChanEntry->usExtraSinTsiMemIndex; ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set add copy event flag. */ ++ fAddSinCopy = TRUE; ++ ++ /* For sure. */ ++ pEchoChanEntry->fCopyEventCreated = TRUE; ++ } ++ else if ( f_fTap == TRUE ) ++ { ++ /* Accumulate the tapped channel's voice instead of building a copy event. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ WriteParams.usWriteData |= pTapEchoChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Link to next operation. */ ++ WriteParams.ulWriteAddress += 4; ++ WriteParams.usWriteData = f_usSubStoreEventIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the software model. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, f_usCopyEventIndex ); ++ ++ pTempEntry->usSourceChanIndex = f_usTapChanIndex; ++ pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ pTempEntry->usNextEventPtr = f_usSubStoreEventIndex; ++ pTempEntry->usDestinationChanIndex = cOCT6100_INVALID_INDEX; ++ pTempEntry->fReserved = TRUE; ++ } ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Now insert the event into the list.*/ ++ if ( pBridgeEntry->usNumClients == 0 ) ++ { ++ /* This is the first entry for this bridge. Insert the two events at the head ++ of the list just after the last sub-store event.*/ ++ if ( f_fTap == FALSE ) ++ { ++ ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usLastSubStoreEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND ) ++ { ++ if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ } ++ else ++ { ++ return cOCT6100_ERR_FATAL_26; ++ } ++ } ++ } ++ else ++ { ++ if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ } ++ ++ /* An Entry was found, now, modify it's value.*/ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex ); ++ ++ /* Set the Sub-Store event first.*/ ++ pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; ++ pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; ++ ++ /*=======================================================================*/ ++ /* Program the Sub-Store event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Set the load/accumulate event now.*/ ++ if ( f_fTap == FALSE ) ++ { ++ pLoadEventEntry->usNextEventPtr = f_usSubStoreEventIndex; ++ } ++ else ++ { ++ /* This is a little tricky, we use the copy event index for accumulating the tapped channel's voice. */ ++ pLoadEventEntry->usNextEventPtr = f_usCopyEventIndex; ++ } ++ ++ /*=======================================================================*/ ++ /* Program the load/accumulate event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Now modify the previous last Sub Store event from another bridge. */ ++ pTempEntry->usNextEventPtr = f_usLoadEventIndex; ++ ++ /*=======================================================================*/ ++ /* Modify the last node of the other bridge. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Set the event pointer info in the bridge stucture. */ ++ pBridgeEntry->usFirstLoadEventPtr = f_usLoadEventIndex; ++ pBridgeEntry->usFirstSubStoreEventPtr = f_usSubStoreEventIndex; ++ pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex; ++ ++ /* Update the global mixer pointers. */ ++ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* This bridge is the first to generate mixer event. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex; ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex; ++ } ++ else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex ) ++ { ++ /* The two entries were added at the end of the bridge section, */ ++ /* change only the last pointer. */ ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex; ++ } ++ else if ( usLastSubStoreEventIndex == cOCT6100_MIXER_HEAD_NODE || ++ usLastSubStoreEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) ++ { ++ /* The two entries were added at the start of the bridge section, */ ++ /* change only the first pointer. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadEventIndex; ++ } ++ } ++ else /* pBridgeEntry->usNumClients != 0 */ ++ { ++ /* For sanity. */ ++ if ( f_fTap == TRUE ) ++ return cOCT6100_ERR_FATAL_D2; ++ ++ /*=======================================================================*/ ++ /* Program the Load event. */ ++ ++ /* Now find the last load entry of this bridge. */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, pBridgeEntry->usFirstSubStoreEventPtr, 0, &usLastLoadEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Add the load/accumulate event to the list. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastLoadEventIndex ); ++ ++ /* Set the load event now. */ ++ pLoadEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Modify the previous last load event. */ ++ ++ /* Now modify the previous last load event. */ ++ pTempEntry->usNextEventPtr = f_usLoadEventIndex; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Program the Sub-Store event. */ ++ ++ usLastSubStoreEventIndex = pBridgeEntry->usLastSubStoreEventPtr; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex ); ++ ++ /* Set the Sub-Store event first. */ ++ pSubStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pSubStoreEventEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Modify the previous last sub store event of the bridge. */ ++ ++ /* Now modify the last Load event of the bridge. */ ++ pTempEntry->usNextEventPtr = f_usSubStoreEventIndex; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Update the bridge pointers. */ ++ pBridgeEntry->usLastSubStoreEventPtr = f_usSubStoreEventIndex; ++ ++ /* Check if modification to the global mixer pointer are required. */ ++ if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex ) ++ { ++ /* We have a new last bridge pointer. */ ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usSubStoreEventIndex; ++ } ++ } ++ ++ if ( f_fTap == TRUE ) ++ { ++ if ( pEchoChanEntry->usRinTsstIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* Remove the mute on the Rin port. */ ++ ++ UINT32 ulTempData; ++ UINT32 ulMask; ++ UINT32 ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChanIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ /* Configure the level control. */ ++ ++ UINT32 ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.usDwordOffset * 4; ++ UINT32 ulFeatureBitOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.byBitOffset; ++ UINT32 ulFeatureFieldLength = pSharedInfo->MemoryMap.RinLevelControlOfst.byFieldSize; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pEchoChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ++ /* Set the DC filter to pass through.*/ ++ ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset ); ++ ++ /* First read the DWORD where the field is located. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Set the event entries as reserved. */ ++ pLoadEventEntry->fReserved = TRUE; ++ pSubStoreEventEntry->fReserved = TRUE; ++ ++ /* Store the event indexes into the channel structure. */ ++ pEchoChanEntry->usLoadEventIndex = f_usLoadEventIndex; ++ pEchoChanEntry->usSubStoreEventIndex = f_usSubStoreEventIndex; ++ ++ /* Check if must insert the Sin copy event in the list. */ ++ if ( fAddSinCopy == TRUE ) ++ { ++ /* Now insert the Sin copy event into the list. */ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_usCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY, ++ f_usChanIndex ); ++ } ++ ++ /* Check if the Rin silence event can be cleared now that the */ ++ /* channel has been added to a conference. */ ++ if ( ( f_fTap == FALSE ) && ( pEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) ++ { ++ /* Remove the event from the list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pEchoChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_DF; ++ ++ pEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ /* Configure the RIN copy mixer entry and memory - if using the RIN port. */ ++ if ( ( f_fFlexibleConfBridge == TRUE ) && ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) ) ++ { ++ if ( pEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pEchoChanEntry->usRinTsstIndex, ++ pEchoChanEntry->usExtraRinTsiMemIndex, ++ pEchoChanEntry->TdmConfig.byRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ if ( pBridgeEntry->fDominantSpeakerSet == TRUE ) ++ { ++ /* Dominant speaker is another channel. Set accordingly for this new conference channel. */ ++ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, pBridgeEntry->usDominantSpeakerChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ /* No dominant speaker set on this bridge yet. */ ++ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Update the bridge entry. */ ++ pBridgeEntry->usNumClients++; ++ ++ /* Store the bridge index into the channel structure. */ ++ pEchoChanEntry->usBridgeIndex = f_usBridgeIndex; ++ ++ /* Store the copy event index into the channel structure. */ ++ if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ pEchoChanEntry->usSinCopyEventIndex = f_usCopyEventIndex; ++ } ++ else ++ { ++ pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Remember if the channel is muted in the conference. */ ++ pEchoChanEntry->fMute = f_fMute; ++ ++ /* Remember if the channel is a tap in a conference. */ ++ pEchoChanEntry->fTap = f_fTap; ++ ++ /* We start by not being tapped. */ ++ pEchoChanEntry->fBeingTapped = FALSE; ++ pEchoChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Remember the tap bridge index if necessary. */ ++ if ( pEchoChanEntry->fTap == TRUE ) ++ { ++ pEchoChanEntry->usTapBridgeIndex = f_usTapBridgeIndex; ++ } ++ else ++ { ++ pEchoChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Indicate that the extra SIN TSI is currently in used by the conference bridge. */ ++ if ( f_ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ pEchoChanEntry->usExtraSinTsiDependencyCnt++; ++ } ++ ++ /* Indicate that the extra RIN TSI is currently in used by the conference bridge. */ ++ if ( ( f_fFlexibleConfBridge == TRUE ) && ( f_ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) ) ++ { ++ pEchoChanEntry->usExtraRinTsiDependencyCnt++; ++ } ++ ++ /* Update the chip stats structure. */ ++ pSharedInfo->ChipStats.usNumEcChanUsingMixer++; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBridgeAddParticipantToChannel ++ ++Description: Used for the flexible conference bridges. Insert a participant ++ onto a channel that is on a conference. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_usBridgeIndex Bridge index where this channel is located. ++f_usSourceChannelIndex Source channel to copy voice from. ++f_usDestinationChannelIndex Destination channel to store resulting voice to. ++f_usLoadOrAccumulateEventIndex Load or Accumulate allocated event index. ++f_usStoreEventIndex Store allocated event index. ++f_usCopyEventIndex Copy allocated event index. ++f_ulSourceInputPort Source input port of the conference for this channel. ++f_ulDestinationInputPort Destination input port of the conference for this channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBridgeAddParticipantToChannel ++UINT32 Oct6100ApiBridgeAddParticipantToChannel( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usSourceChannelIndex, ++ IN UINT16 f_usDestinationChannelIndex, ++ IN UINT16 f_usLoadOrAccumulateEventIndex, ++ IN UINT16 f_usStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT32 f_ulSourceInputPort, ++ IN UINT32 f_ulDestinationInputPort ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ tPOCT6100_API_MIXER_EVENT pLoadEventEntry; ++ tPOCT6100_API_MIXER_EVENT pStoreEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEntry; ++ ++ tPOCT6100_API_CHANNEL pSourceChanEntry; ++ tPOCT6100_API_CHANNEL pDestinationChanEntry; ++ ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pSourceParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pDestinationParticipant; ++ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ ++ UINT32 ulResult; ++ UINT16 usLastSubStoreEventIndex; ++ UINT16 usLastLoadEventIndex; ++ BOOL fInsertCopy = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceChanEntry, f_usSourceChannelIndex ); ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceParticipant, pSourceChanEntry->usFlexConfParticipantIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationChanEntry, f_usDestinationChannelIndex ); ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationParticipant, pDestinationChanEntry->usFlexConfParticipantIndex ); ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadOrAccumulateEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pStoreEventEntry, f_usStoreEventIndex ); ++ ++ /* Check if we are creating the first event for this channel. */ ++ if ( pDestinationParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /*=======================================================================*/ ++ /* Before creating the participant's flexible mixer, make sure the extra Sin */ ++ /* mixer event is programmed correctly for sending the voice stream to the right place. */ ++ ++ /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */ ++ if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ if ( pDestinationChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pDestinationChanEntry->usSinTsstIndex, ++ pDestinationChanEntry->usExtraSinTsiMemIndex, ++ pDestinationChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If the silence TSI is loaded on this port, update with the extra sin TSI. */ ++ if ( pDestinationChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pDestinationChanEntry->usExtraSinTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Program the load event. This is the first event for this new destination channel. */ ++ ++ /* First set the TSI buffer where the resulting stream should be written to. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ /* For sure, we are loading. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ ++ /* Select the TSI memory index according to the source port. */ ++ if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ WriteParams.usWriteData |= pSourceChanEntry->usSinSoutTsiMemIndex; ++ } ++ else /* if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ ++ { ++ WriteParams.usWriteData |= pSourceChanEntry->usExtraRinTsiMemIndex; ++ } ++ ++ /* Set the event type. */ ++ pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ ++ /* Set the source channel index. */ ++ pLoadEventEntry->usSourceChanIndex = f_usSourceChannelIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ ++ /*=======================================================================*/ ++ /* Program the store event. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE; ++ ++ /* Select the TSI memory index and PCM law according to the source port. */ ++ if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ WriteParams.usWriteData |= pDestinationChanEntry->usSinSoutTsiMemIndex; ++ } ++ else /* if ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ ++ { ++ WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ WriteParams.usWriteData |= pDestinationChanEntry->usRinRoutTsiMemIndex; ++ } ++ ++ /* Set the event type. */ ++ pStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE; ++ ++ /* Set the destination channel index. */ ++ pStoreEventEntry->usDestinationChanIndex = f_usDestinationChannelIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pDestinationChanEntry->usRinRoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ ++ /*=======================================================================*/ ++ /* Program the Copy event - if using the SOUT port */ ++ ++ if ( ( f_ulDestinationInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pDestinationChanEntry->fCopyEventCreated == FALSE ) ) ++ { ++ /* The copy event has not been created, create it once for the life of the participant on the bridge. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= pDestinationChanEntry->usExtraSinTsiMemIndex; ++ WriteParams.usWriteData |= pDestinationChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pDestinationChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pDestinationChanEntry->fCopyEventCreated = TRUE; ++ ++ /* Set insert copy flag. */ ++ fInsertCopy = TRUE; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ ++ /*=======================================================================*/ ++ /*=======================================================================*/ ++ /* Now, insert the events into the current list. */ ++ /*=======================================================================*/ ++ /*=======================================================================*/ ++ ++ /* This is the first entry for this channel. Insert the two events at the head */ ++ /* of the list just after the last Sub-Store or Store event. */ ++ ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, f_usLoadOrAccumulateEventIndex, &usLastSubStoreEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND ) ++ { ++ if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ usLastSubStoreEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ usLastSubStoreEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ } ++ else ++ { ++ return cOCT6100_ERR_FATAL_26; ++ } ++ } ++ ++ /* An entry was found, now, modify it's value. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastSubStoreEventIndex ); ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Link the store event first. */ ++ ++ pStoreEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; ++ ++ /* Link the store event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ WriteParams.usWriteData = (UINT16)( pStoreEventEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Link the load event now.*/ ++ ++ pLoadEventEntry->usNextEventPtr = f_usStoreEventIndex; ++ ++ /* Link the load event.*/ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Now modify the previous last Sub-Store or Store event from another bridge, */ ++ /* such that it links to us. */ ++ ++ pTempEntry->usNextEventPtr = f_usLoadOrAccumulateEventIndex; ++ ++ /* Modify the last node of the other bridge. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Set the event pointer info in the bridge stucture. */ ++ ++ if ( pBridgeEntry->usFirstLoadEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* We only do this once in case of the flexible conference bridges. */ ++ pBridgeEntry->usFirstLoadEventPtr = f_usLoadOrAccumulateEventIndex; ++ pBridgeEntry->usFirstSubStoreEventPtr = f_usStoreEventIndex; ++ } ++ ++ pBridgeEntry->usLastSubStoreEventPtr = f_usStoreEventIndex; ++ ++ /* Update the global mixer pointers. */ ++ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* This bridge is the first to generate mixer event. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadOrAccumulateEventIndex; ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usStoreEventIndex; ++ } ++ else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == usLastSubStoreEventIndex ) ++ { ++ /* The two entries were added at the end of the bridge section, */ ++ /* change only the last pointer. */ ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = f_usStoreEventIndex; ++ } ++ else if ( usLastSubStoreEventIndex == cOCT6100_MIXER_HEAD_NODE || ++ usLastSubStoreEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) ++ { ++ /* The two entries were added at the start of the bridge section, */ ++ /* change only the first pointer.*/ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = f_usLoadOrAccumulateEventIndex; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Insert the copy event if needed in the mixer's list. */ ++ ++ if ( fInsertCopy == TRUE ) ++ { ++ /* Now insert the Sin copy event into the list. */ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_usCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY, ++ f_usDestinationChannelIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Update the status of the instance structures. */ ++ ++ pDestinationParticipant->fFlexibleMixerCreated = TRUE; ++ ++ /* Set the event entries as reserved. */ ++ pLoadEventEntry->fReserved = TRUE; ++ pStoreEventEntry->fReserved = TRUE; ++ ++ /* Store the event indexes into the channel structure. */ ++ pDestinationChanEntry->usLoadEventIndex = f_usLoadOrAccumulateEventIndex; ++ pDestinationChanEntry->usSubStoreEventIndex = f_usStoreEventIndex; ++ ++ /*=======================================================================*/ ++ } ++ else /* if ( pDestinationChanEntry->fFlexibleMixerCreated == TRUE ) */ ++ { ++ /*=======================================================================*/ ++ /* Program the Accumulate event. */ ++ ++ /* First set the TSI buffer where the resulting stream should be written to. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ /* For sure, we are accumulating. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ ++ /* Select the TSI memory index according to the source port. */ ++ if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ WriteParams.usWriteData |= pSourceChanEntry->usSinSoutTsiMemIndex; ++ } ++ else /* if ( f_ulSourceInputPort == cOCT6100_CHANNEL_PORT_RIN ) */ ++ { ++ WriteParams.usWriteData |= pSourceChanEntry->usExtraRinTsiMemIndex; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ ++ /*=======================================================================*/ ++ /*=======================================================================*/ ++ /* Now, insert the Accumulate event into the current list. */ ++ /*=======================================================================*/ ++ /*=======================================================================*/ ++ ++ /* Use the Load entry of this channel. */ ++ usLastLoadEventIndex = pDestinationChanEntry->usLoadEventIndex; ++ ++ /* Add the Accumulate event to the list. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usLastLoadEventIndex ); ++ ++ /* Set the accumulate event now. */ ++ pLoadEventEntry->usNextEventPtr = pTempEntry->usNextEventPtr; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadOrAccumulateEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pLoadEventEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ ++ /*=======================================================================*/ ++ /* Modify the previous Load event. */ ++ ++ /* Now modify the previous Load event. */ ++ pTempEntry->usNextEventPtr = f_usLoadOrAccumulateEventIndex; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ ++ /*=======================================================================*/ ++ /* Update the status of the instance structures. */ ++ ++ /* Set the Accumulate event entry as reserved. */ ++ pLoadEventEntry->fReserved = TRUE; ++ /* Set the Event type. */ ++ pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ /* Set the source channel index. */ ++ pLoadEventEntry->usSourceChanIndex = f_usSourceChannelIndex; ++ ++ /*=======================================================================*/ ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanRemoveSer ++ ++Description: Removes an echo channel from a conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeRemove Pointer to conference bridge channel remove structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanRemoveSer ++UINT32 Oct6100ConfBridgeChanRemoveSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) ++{ ++ UINT16 usBridgeIndex; ++ UINT16 usChanIndex = 0; ++ UINT16 usLoadEventIndex; ++ UINT16 usSubStoreEventIndex; ++ UINT16 usCopyEventIndex; ++ UINT32 ulResult; ++ UINT8 fFlexibleConfBridge; ++ UINT8 fTap; ++ ++ /* Check the validity of the channel and conference bridge given. */ ++ ulResult = Oct6100ApiCheckChanRemoveParams( ++ f_pApiInstance, ++ f_pConfBridgeRemove, ++ &usBridgeIndex, ++ &usChanIndex, ++ &fFlexibleConfBridge, ++ &fTap, ++ &usLoadEventIndex, ++ &usSubStoreEventIndex, ++ &usCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources reserved for the conference bridge. */ ++ ulResult = Oct6100ApiReleaseChanEventResources( ++ f_pApiInstance, ++ f_pConfBridgeRemove, ++ usBridgeIndex, ++ usChanIndex, ++ fFlexibleConfBridge, ++ usLoadEventIndex, ++ usSubStoreEventIndex, ++ usCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear the memory entry for this channel within the bridge. */ ++ ulResult = Oct6100ApiBridgeEventRemove( ++ f_pApiInstance, ++ f_pConfBridgeRemove, ++ usBridgeIndex, ++ usChanIndex, ++ fFlexibleConfBridge, ++ usLoadEventIndex, ++ usSubStoreEventIndex, ++ usCopyEventIndex, ++ fTap ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckChanRemoveParams ++ ++Description: Check the validity of the channel and conference bridge given. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pConfBridgeRemove Pointer to conference bridge channenl add structure. ++f_pusBridgeIndex Pointer to the bridge index. ++f_pfFlexibleConfBridge If this is a flexible conference bridge ++f_pusChannelIndex Pointer to the channel index to be added to the bridge. ++f_pusLoadEventIndex Pointer to the load mixer event. ++f_pusSubStoreEventIndex Pointer to the sub-store mixer event. ++f_pusCopyEventIndex Pointer to the copy mixer event. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckChanRemoveParams ++UINT32 Oct6100ApiCheckChanRemoveParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, ++ OUT PUINT16 f_pusBridgeIndex, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT8 f_pfFlexibleConfBridge, ++ OUT PUINT8 f_pfTap, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT16 f_pusCopyEventIndex ) ++{ ++ UINT32 ulEntryOpenCnt; ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ /* Verify if the remove all flag is valid. */ ++ if ( f_pConfBridgeRemove->fRemoveAll != TRUE && ++ f_pConfBridgeRemove->fRemoveAll != FALSE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_REMOVE_ALL; ++ ++ /* Check the channel handle only if the remove all flag is set to FALSE. */ ++ if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) ++ { ++ /*=====================================================================*/ ++ /* Check the channel handle. */ ++ ++ if ( (f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusChannelIndex = (UINT16)( f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeRemove->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ if ( pEchoChanEntry->fBeingTapped == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY; ++ ++ /*=====================================================================*/ ++ ++ *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex; ++ *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex; ++ *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex; ++ *f_pusCopyEventIndex = pEchoChanEntry->usSinCopyEventIndex; ++ ++ /* Check if the channel is really part of the bridge. */ ++ if ( *f_pusBridgeIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) ++ ++ /* Return whether this is a flexible bridge or not. */ ++ *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; ++ ++ /* Return whether this is a tap or not. */ ++ *f_pfTap = pEchoChanEntry->fTap; ++ } ++ else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ ++ { ++ /* Check the provided handle. */ ++ if ( (f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusBridgeIndex = (UINT16)( f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeRemove->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /* This information is not currently available. */ ++ *f_pusLoadEventIndex = cOCT6100_INVALID_INDEX; ++ *f_pusSubStoreEventIndex = cOCT6100_INVALID_INDEX; ++ *f_pusCopyEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Return whether this is a flexible bridge or not. */ ++ *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; ++ ++ *f_pfTap = FALSE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseChanEventResources ++ ++Description: Release all resources reserved to the channel part of the ++ conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pConfBridgeRemove Pointer to conference bridge channel add structure. ++f_usBridgeIndex Index of the bridge structure within the API's bridge list. ++f_usChanIndex Index of the channel structure within the API's channel list ++f_fFlexibleConfBridge If this is a flexible conference bridge. ++f_usLoadEventIndex Index of the load mixer event. ++f_usSubStoreEventIndex Index of the sub-store mixer event. ++f_usCopyEventIndex Index of the copy mixer event. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseChanEventResources ++UINT32 Oct6100ApiReleaseChanEventResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ UINT32 ulResult; ++ UINT32 i; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ if ( f_fFlexibleConfBridge == TRUE ) ++ { ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; ++ ++ if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) ++ { ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Release an entry for the store event in the mixer memory. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /* Release an entry for the Sin copy event in the mixer memory. */ ++ /* This value can be invalid if the Rin port was used - no need to release. */ ++ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* This value can be 0 if the Rin port was used - no need to release. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /* Release the extra TSI entry.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* This value can be 0 if the Sout port was used - no need to release. */ ++ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) ++ { ++ /* Release the extra TSI entry.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* Must travel all clients of this conference and release the load or accumulate events for */ ++ /* all participants which can hear us and vice versa. */ ++ ++ /* Search through the list of API channel entry for the ones on to this bridge. */ ++ for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, i ); ++ ++ /* Channel reserved? */ ++ if ( ( i != f_usChanIndex ) && pTempEchoChanEntry->fReserved == TRUE ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can hear this participant. */ ++ if ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ { ++ /* Must release the allocated mixer event. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Check if this participant can hear us. */ ++ if ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ { ++ /* Must release the allocated mixer event. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ } ++ } ++ else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ ++ { ++ UINT32 ulListenerMaskIndex; ++ ++ ulResult = cOCT6100_ERR_OK; ++ ++ /* Search through the list of API channel entry for the ones on to this bridge.*/ ++ for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); ++ ++ /* Channel reserved? */ ++ if ( pEchoChanEntry->fReserved == TRUE ) ++ { ++ /* On current bridge? */ ++ if ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Release an entry for the Store event in the Mixer memory. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSubStoreEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /* Release an entry for the Sin copy event in the Mixer memory. */ ++ /* This value can be invalid if the Rin port was used - no need to release. */ ++ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* This value can be 0 if the Rin port was used - no need to release. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /* Release the extra TSI entry.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* This value can be 0 if the Sout port was used - no need to release. */ ++ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) ++ { ++ /* Release the extra TSI entry.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* Check if something can be freed. */ ++ for ( ulListenerMaskIndex = 0; ulListenerMaskIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulListenerMaskIndex ++ ) ++ { ++ if ( pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ /* Must release the allocated mixer event. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ } ++ } ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else /* if ( f_fFlexibleConfBridge == FALSE ) */ ++ { ++ if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ ++ /* Release the entry for the load event in the mixer memory. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usLoadEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /* Release an entry for the substract and store event in the mixer memory. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /* Release an entry for the Sin copy event in the Mixer memory. */ ++ /* This value can be invalid if the Rin port was used - no need to release. */ ++ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* This value can be 0 if the Rin port was used - no need to release. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /* Release the extra TSI entry. */ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ } ++ else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ ++ { ++ /* Search through the list of API channel entry for the ones on to the specified bridge.*/ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); ++ ++ if ( pEchoChanEntry->fReserved == TRUE ) ++ { ++ if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) ++ { ++ /* Release the entry for the load event in the mixer memory. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, ++ pEchoChanEntry->usLoadEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /* Release an entry for the substract and store event in the Mixer memory. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, ++ pEchoChanEntry->usSubStoreEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /* Release an entry for the Sin copy event in the Mixer memory. */ ++ /* This value can be invalid if the Rin port was used - no need to release. */ ++ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, ++ pEchoChanEntry->usSinCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ ++ /* This value can be 0 if the Rin port was used - no need to release. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ /* Release the extra TSI entry.*/ ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBridgeEventRemove ++ ++Description: Remove the event from the global event list of the chip and ++ update the bridge and channel structures. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pConfBridgeRemove Pointer to a conference bridge channel remove structure. ++f_usBridgeIndex Index of the current bridge in the API list. ++f_usChanIndex Index of the current channel in the API list. ++f_fFlexibleConfBridge If this is a flexible conference bridge. ++f_usLoadEventIndex Allocated entry for the Load event of the channel. ++f_usSubStoreEventIndex Allocated entry for the substract and store event of the channel. ++f_usCopyEventIndex Allocated entry for the copy event of the channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBridgeEventRemove ++UINT32 Oct6100ApiBridgeEventRemove ( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT8 f_fTap ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ tPOCT6100_API_MIXER_EVENT pLoadEventEntry; ++ tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; ++ tPOCT6100_API_MIXER_EVENT pCopyEventEntry = NULL; ++ tPOCT6100_API_MIXER_EVENT pTempEntry; ++ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ ++ UINT32 ulResult; ++ UINT16 usPreviousEventIndex; ++ UINT16 usTempEventIndex; ++ UINT32 ulLoopCount = 0; ++ UINT16 usReadData; ++ UINT16 usChannelIndex; ++ UINT32 i; ++ ++ BOOL fRemoveSinCopy = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex ); ++ ++ /* If no client on the bridge, and the remove all option is specified, return here. */ ++ if ( ( pBridgeEntry->usNumClients == 0 ) && ( f_pConfBridgeRemove->fRemoveAll == TRUE ) ) ++ return cOCT6100_ERR_OK; ++ ++ /* Make sure the dominant speaker feature is disabled first. */ ++ if ( pBridgeEntry->fDominantSpeakerSet == TRUE ) ++ { ++ /* If all channels are to be removed or if the dominant speaker is the current channel to be removed. */ ++ if ( ( f_pConfBridgeRemove->fRemoveAll == TRUE ) ++ || ( ( f_pConfBridgeRemove->fRemoveAll == FALSE ) && ( pBridgeEntry->usDominantSpeakerChanIndex == f_usChanIndex ) ) ) ++ { ++ /* Disable on all channels part of this conference. */ ++ ++ /* Search through the list of API channel entry for the ones on to this bridge. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ if ( pTempEchoChanEntry->fReserved == TRUE ) ++ { ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, usChannelIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Save this in the conference bridge structure. */ ++ pBridgeEntry->fDominantSpeakerSet = FALSE; ++ pBridgeEntry->usDominantSpeakerChanIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ /* Only disable this current channel. */ ++ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ if ( f_fFlexibleConfBridge == TRUE ) ++ { ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; ++ UINT16 ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; ++ UINT32 ulMutePortChannelIndex; ++ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX; ++ ++ if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) ++ { ++ /* The channel index is valid. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Search through the list of API channel entry for the ones on to this bridge. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can hear this participant. */ ++ if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( pParticipant->fFlexibleMixerCreated == TRUE ) ++ && ( pTempEchoChanEntry->fMute == FALSE ) ) ++ { ++ /* First update the current channel's mixer. */ ++ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ usChannelIndex, ++ f_usChanIndex, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Check if this participant can hear us. */ ++ if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) ++ && ( pEchoChanEntry->fMute == FALSE ) ) ++ { ++ /* Then update this channel's mixer. */ ++ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ f_usChanIndex, ++ usChannelIndex, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Remember to mute the port on this channel. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usChannelIndex ) ++ { ++ break; ++ } ++ else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) ++ { ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usChannelIndex; ++ break; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ /* Check if must manually clear the Sin copy event. */ ++ if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ && ( pEchoChanEntry->fCopyEventCreated == TRUE ) ) ++ { ++ /* Transform event into no-operation. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now remove the copy event from the event list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pEchoChanEntry->fCopyEventCreated = FALSE; ++ } ++ ++ /* Release an entry for the participant. */ ++ ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ /* Update the event and channel API structure */ ++ pEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Indicate that the extra SIN TSI is not needed anymore by the mixer. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ /* Decrement the dependency count, but do not clear the mem index. */ ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ } ++ ++ /* Indicate that the extra RIN TSI is not needed anymore by the mixer. */ ++ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) ++ { ++ pEchoChanEntry->usExtraRinTsiDependencyCnt--; ++ pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Update the chip stats structure. */ ++ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; ++ ++ pBridgeEntry->usNumClients--; ++ ++ /* For sure we have to mute the ports of this channel to be removed. */ ++ ulResult = Oct6100ApiMutePorts( ++ f_pApiInstance, ++ f_usChanIndex, ++ pEchoChanEntry->usRinTsstIndex, ++ pEchoChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /* Check if the Rin port must be muted on this channel. */ ++ ulResult = Oct6100ApiMutePorts( ++ f_pApiInstance, ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ], ++ pTempEchoChanEntry->usRinTsstIndex, ++ pTempEchoChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ ++ { ++ /* No more channels to check for muting. */ ++ break; ++ } ++ } ++ } ++ else /* if ( f_pConfBridgeRemove->fRemoveAll == TRUE ) */ ++ { ++ UINT16 usMainChannelIndex; ++ ++ for ( usMainChannelIndex = 0 ; usMainChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ; usMainChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usMainChannelIndex ); ++ ++ /* If this channel is on the bridge we are closing all the channels. */ ++ if ( ( pEchoChanEntry->fReserved == TRUE ) && ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ) ++ { ++ /* Remember to mute the port on this channel. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usMainChannelIndex ) ++ { ++ break; ++ } ++ else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) ++ { ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usMainChannelIndex; ++ break; ++ } ++ } ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Search through the list of API channel entry for the ones on to this bridge. */ ++ for ( usChannelIndex = (UINT16)( usMainChannelIndex + 1 ); usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ if ( pTempEchoChanEntry->fReserved == TRUE ) ++ { ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Everyone that we can hear must be removed. */ ++ if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( pParticipant->fFlexibleMixerCreated == TRUE ) ++ && ( pTempEchoChanEntry->fMute == FALSE ) ) ++ { ++ /* First update the current channel's mixer. */ ++ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ usChannelIndex, ++ usMainChannelIndex, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Check if this participant can hear us. */ ++ if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) ++ && ( pEchoChanEntry->fMute == FALSE ) ) ++ { ++ /* Then update this channel's mixer. */ ++ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ usMainChannelIndex, ++ usChannelIndex, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ } ++ ++ /* Check if must manually clear the Sin copy event. */ ++ if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ && ( pEchoChanEntry->fCopyEventCreated == TRUE ) ) ++ { ++ /* Transform event into no-operation. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now remove the copy event from the event list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pEchoChanEntry->fCopyEventCreated = FALSE; ++ } ++ ++ /* Release an entry for the participant. */ ++ ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ /* Update the event and channel API structure */ ++ ++ pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; ++ ++ pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ /* Decrement the dependency count, but do not clear the mem index. */ ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ } ++ ++ /* Indicate that the Extra RIN TSI is not needed anymore by the mixer. */ ++ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) ++ { ++ pEchoChanEntry->usExtraRinTsiDependencyCnt--; ++ pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Update the chip stats structure. */ ++ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; ++ } ++ } ++ ++ /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /* Check if the Rin port must be muted on this channel. */ ++ ulResult = Oct6100ApiMutePorts( ++ f_pApiInstance, ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ], ++ pTempEchoChanEntry->usRinTsstIndex, ++ pTempEchoChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ ++ { ++ /* No more channels to check for muting. */ ++ break; ++ } ++ ++ /* Clear the flexible conf bridge participant index. */ ++ pTempEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* No more clients on bridge. */ ++ pBridgeEntry->usNumClients = 0; ++ } ++ } ++ else /* if ( f_fFlexibleConfBridge == FALSE ) */ ++ { ++ if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) ++ { ++ /* The channel index is valid. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ ++ if ( f_fTap == TRUE ) ++ { ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, pEchoChanEntry->usTapBridgeIndex ); ++ } ++ ++ /* Get a pointer to the event entry. */ ++ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, f_usCopyEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); ++ ++ /*=======================================================================*/ ++ /* Check if have to modify the silence load event. */ ++ ++ if ( pBridgeEntry->usNumClients != 1 ) ++ { ++ if ( pBridgeEntry->usSilenceLoadEventPtr != cOCT6100_INVALID_INDEX ) ++ { ++ if ( pBridgeEntry->usSilenceLoadEventPtr == f_usLoadEventIndex ) ++ { ++ /* Make sure the next event becomes the silence event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadEventEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */ ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the software model to remember the silence load. */ ++ pBridgeEntry->usSilenceLoadEventPtr = pLoadEventEntry->usNextEventPtr; ++ } ++ else ++ { ++ /* Somebody else is the silence event, no need to worry. */ ++ } ++ } ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Clear the Load event. */ ++ ++ /* First verify if the event to be removed was a load event. */ ++ if ( f_usLoadEventIndex == pBridgeEntry->usLoadIndex ) ++ { ++ /* Change the next entry if one is present to a load event to keep the bridge alive. */ ++ if ( pBridgeEntry->usNumClients == 1 ) ++ { ++ /* There is no other entry on the bridge, no need to search for an Accumulate event. */ ++ pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Clear the silence event, for sure it's invalid. */ ++ pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ /* Search for an accumulate event to tranform into a Load event. */ ++ usTempEventIndex = pLoadEventEntry->usNextEventPtr; ++ ulLoopCount = 0; ++ ++ /* Find the copy entry before the entry to remove. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && ++ pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) ++ { ++ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) ++ { ++ /* Change this entry into a load event. */ ++ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set this entry as the load index. */ ++ pBridgeEntry->usLoadIndex = usTempEventIndex; ++ ++ /* Update the software model. */ ++ pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ ++ /* Stop searching. */ ++ break; ++ } ++ ++ /* Go to the next entry into the list. */ ++ usTempEventIndex = pTempEntry->usNextEventPtr; ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ ulLoopCount++; ++ if ( ulLoopCount == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_FATAL_9B; ++ } ++ } ++ } ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Clear the substract and store event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Clear the Copy event - if needed. */ ++ ++ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Transform event into no-operation. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( f_fTap == FALSE ) ++ { ++ /* Set remove Sin copy event flag to remove the event from the mixer's list. */ ++ fRemoveSinCopy = TRUE; ++ ++ /* Clear the copy event created flag. */ ++ pEchoChanEntry->fCopyEventCreated = FALSE; ++ } ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Now remove the event from the event list. */ ++ ++ /* Look for the entry that is pointing at the first entry of our bridge. */ ++ if ( f_fTap == FALSE ) ++ { ++ ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); ++ } ++ else ++ { ++ ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, pEchoChanEntry->usTapBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); ++ } ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* If the entry was not found, we now check for the Sout copy event section/list. */ ++ if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND ) ++ { ++ if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* No Sout copy, it has to be the head node. */ ++ usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ /* Use the last Sout copy event. */ ++ usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ } ++ else ++ { ++ return cOCT6100_ERR_FATAL_27; ++ } ++ } ++ ++ if ( pBridgeEntry->usNumClients == 1 ) ++ { ++ /* An entry was found, now, modify it's value. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); ++ ++ /* Now modify the previous last Sub Store event from another bridge. */ ++ pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; ++ ++ /*=======================================================================*/ ++ /* Modify the last node of the previous bridge to point to the next bridge. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Set the event pointer info in the bridge stucture. */ ++ pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; ++ ++ /*=======================================================================*/ ++ /* Update the global mixer pointers. */ ++ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex && ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) ++ { ++ /* There is no more bridge entry in the mixer link list. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex ) ++ { ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pSubStoreEventEntry->usNextEventPtr; ++ } ++ else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) ++ { ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; ++ } ++ /*=======================================================================*/ ++ ++ if ( f_fTap == TRUE ) ++ { ++ /* The channel being tapped is not tapped anymore. */ ++ /* There is no direct way of finding the tap, so loop through all channels and find the */ ++ /* tapped channel index. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ if ( pTempEchoChanEntry->usTapChanIndex == f_usChanIndex ) ++ { ++ tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; ++ ++ pTempEchoChanEntry->fBeingTapped = FALSE; ++ pTempEchoChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex ); ++ ++ pTempBridgeEntry->usNumTappedClients--; ++ ++ /* Re-assign Rin TSST for tapped channel. */ ++ if ( pTempEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pTempEchoChanEntry->usRinTsstIndex, ++ pTempEchoChanEntry->usRinRoutTsiMemIndex, ++ pTempEchoChanEntry->TdmConfig.byRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ break; ++ } ++ } ++ ++ /* Check if our model is broken. */ ++ if ( usChannelIndex == pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_FATAL_D3; ++ } ++ } ++ else /* pBridgeEntry->usNumClients > 1 */ ++ { ++ if ( pBridgeEntry->usFirstLoadEventPtr != f_usLoadEventIndex ) ++ { ++ /* Now find the load entry of this bridge pointing at this load event */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usLoadEventIndex, 0, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Remove the load event to the list. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); ++ ++ /* Now modify the previous last Sub Store event from another bridge. */ ++ pTempEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr; ++ ++ /*=======================================================================*/ ++ /* Modify the previous node. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Now find the last load entry of this bridge ( the one pointing at the first sub-store event ). */ ++ if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex ) ++ { ++ /* Must start with the first load to get the entry before the first sub store. */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else ++ { ++ /* Must start with the first load to get the entry before the first sub store. */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstSubStoreEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); ++ ++ /* Now modify the last load event of the bridge. */ ++ pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; ++ ++ /*=======================================================================*/ ++ /* Modify the last node of the other bridge. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Update the bridge pointers. */ ++ ++ if ( pBridgeEntry->usFirstLoadEventPtr == f_usLoadEventIndex ) ++ pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr; ++ ++ if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex ) ++ pBridgeEntry->usFirstSubStoreEventPtr = pSubStoreEventEntry->usNextEventPtr; ++ ++ if ( pBridgeEntry->usLastSubStoreEventPtr == f_usSubStoreEventIndex ) ++ pBridgeEntry->usLastSubStoreEventPtr = usPreviousEventIndex; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Update the global mixer pointers. */ ++ ++ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex ) ++ { ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr; ++ } ++ ++ if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) ++ { ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; ++ } ++ /*=======================================================================*/ ++ ++ } ++ ++ /* Check if must remove the Sin copy event from the event list. */ ++ if ( fRemoveSinCopy == TRUE ) ++ { ++ /* Now remove the copy event from the event list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, f_usCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Get the channel. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ ++ /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released. */ ++ if ( ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fTap == FALSE ) ) ++ { ++ if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pEchoChanEntry->usSinTsstIndex, ++ pEchoChanEntry->usSinSoutTsiMemIndex, ++ pEchoChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If the silence TSI is loaded on this port, update with the original sin TSI. */ ++ if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ /* Set the event entries as free. */ ++ pLoadEventEntry->fReserved = FALSE; ++ pLoadEventEntry->usEventType = cOCT6100_INVALID_INDEX; ++ pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pSubStoreEventEntry->fReserved = FALSE; ++ pSubStoreEventEntry->usEventType = cOCT6100_INVALID_INDEX; ++ pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ if ( pCopyEventEntry != NULL ) ++ { ++ pCopyEventEntry->fReserved = FALSE; ++ pCopyEventEntry->usEventType = cOCT6100_INVALID_INDEX; ++ pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ ++ pBridgeEntry->usNumClients--; ++ ++ /*=======================================================================*/ ++ /* Update the event and channel API structure */ ++ pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ /* Decrement the dependency count, but do not clear the mem index. */ ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ } ++ ++ /* Update the chip stats structure. */ ++ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; ++ ++ if ( f_fTap == TRUE ) ++ { ++ /* Can now close the bridge. */ ++ tOCT6100_CONF_BRIDGE_CLOSE BridgeClose; ++ ++ Oct6100ConfBridgeCloseDef( &BridgeClose ); ++ ++ BridgeClose.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapBridgeIndex; ++ ++ ulResult = Oct6100ConfBridgeCloseSer( f_pApiInstance, &BridgeClose ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pEchoChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->fTap = FALSE; ++ } ++ ++ /* Check if the Rin port must be muted. */ ++ ulResult = Oct6100ApiMutePorts( ++ f_pApiInstance, ++ f_usChanIndex, ++ pEchoChanEntry->usRinTsstIndex, ++ pEchoChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ } ++ else /* f_ulBridgeChanRemove->fRemoveAll == TRUE ) */ ++ { ++ UINT16 usNextEventPtr; ++ ++ /* Save the next event pointer before invalidating everything. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pBridgeEntry->usLastSubStoreEventPtr ); ++ ++ usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; ++ ++ /* Search through the list of API channel entry for the ones on to the specified bridge. */ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); ++ ++ if ( pEchoChanEntry->fReserved == TRUE ) ++ { ++ if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) ++ { ++ /* Check if we are being tapped. If so, remove the channel that taps us from the conference. */ ++ /* The removal of the channel will make sure the Rin TSST is re-assigned. */ ++ if ( pEchoChanEntry->fBeingTapped == TRUE ) ++ { ++ tOCT6100_CONF_BRIDGE_CHAN_REMOVE ChanRemove; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, pEchoChanEntry->usTapChanIndex ); ++ ++ ulResult = Oct6100ConfBridgeChanRemoveDef( &ChanRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pTempEchoChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapChanIndex; ++ ++ ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &ChanRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ /* Clear the Load event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Clear the Substract and store event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Clear the SIN copy event.*/ ++ ++ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Transform event into no-operation. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Get a pointer to the event entry. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pEchoChanEntry->usSinCopyEventIndex ); ++ ++ /* Update the next event pointer if required. */ ++ if ( usNextEventPtr == pEchoChanEntry->usSinCopyEventIndex ) ++ usNextEventPtr = pCopyEventEntry->usNextEventPtr; ++ ++ /* Now remove the copy event from the event list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear the copy event created flag. */ ++ pEchoChanEntry->fCopyEventCreated = FALSE; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Update the event and channel API structure */ ++ ++ /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released.*/ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pEchoChanEntry->usSinTsstIndex, ++ pEchoChanEntry->usSinSoutTsiMemIndex, ++ pEchoChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If the silence TSI is loaded on this port, update with the original Sin TSI. */ ++ if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, pEchoChanEntry->usLoadEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pEchoChanEntry->usSubStoreEventIndex ); ++ ++ /* Set the event entries as free. */ ++ pLoadEventEntry->fReserved = FALSE; ++ pLoadEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pSubStoreEventEntry->fReserved = FALSE; ++ pSubStoreEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ if ( pCopyEventEntry != NULL ) ++ { ++ pCopyEventEntry->fReserved = FALSE; ++ pCopyEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ ++ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ /* Decrement the dependency count, but do not clear the mem index. */ ++ pEchoChanEntry->usExtraSinTsiDependencyCnt--; ++ } ++ ++ /* Invalidate the channel entry. */ ++ pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; ++ pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Update the chip stats structure. */ ++ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; ++ ++ /*=======================================================================*/ ++ } ++ } ++ } ++ ++ ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND == ulResult ) ++ { ++ if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ } ++ else ++ { ++ return cOCT6100_ERR_FATAL_28; ++ } ++ } ++ ++ /* An Entry was found, now, modify it's value. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); ++ ++ /* Now modify the previous last Sub Store event from another bridge.*/ ++ /* It will now point at the next bridge, or copy events. */ ++ pTempEntry->usNextEventPtr = usNextEventPtr; ++ ++ /*=======================================================================*/ ++ /* Modify the last node of the other bridge. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = pTempEntry->usNextEventPtr; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Update the global mixer pointers. */ ++ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr && ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr == pBridgeEntry->usLastSubStoreEventPtr ) ++ { ++ /* This bridge was the only one with event in the list. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr ) ++ { ++ /* This bridge was the first bridge. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = usNextEventPtr; ++ } ++ else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pBridgeEntry->usLastSubStoreEventPtr ) ++ { ++ /* This bridge was the last bridge.*/ ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; ++ } ++ /*=======================================================================*/ ++ ++ /* Set the event pointer info in the bridge stucture. */ ++ pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; ++ ++ pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; ++ ++ /* Set the number of clients to 0. */ ++ pBridgeEntry->usNumClients = 0; ++ ++ /* Search through the list of API channel entry for the ones on to the specified bridge. */ ++ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); ++ ++ if ( pEchoChanEntry->fReserved == TRUE ) ++ { ++ if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) ++ { ++ pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Check if the Rin port must be muted. */ ++ ulResult = Oct6100ApiMutePorts( ++ f_pApiInstance, ++ (UINT16)( i & 0xFFFF ), ++ pEchoChanEntry->usRinTsstIndex, ++ pEchoChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBridgeRemoveParticipantFromChannel ++ ++Description: This will remove a flexible conference participant from ++ a channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_usBridgeIndex Bridge index where this channel is located. ++f_usSourceChannelIndex Source channel to copy voice from. ++f_usDestinationChannelIndex Destination channel to store resulting voice to. ++f_fRemovePermanently Whether to remove permanently this participant. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBridgeRemoveParticipantFromChannel ++UINT32 Oct6100ApiBridgeRemoveParticipantFromChannel( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usSourceChannelIndex, ++ IN UINT16 f_usDestinationChannelIndex, ++ IN UINT8 f_fRemovePermanently ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ tPOCT6100_API_MIXER_EVENT pLoadEventEntry; ++ tPOCT6100_API_MIXER_EVENT pStoreEventEntry; ++ tPOCT6100_API_MIXER_EVENT pCopyEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEntry; ++ tPOCT6100_API_MIXER_EVENT pLoadTempEntry; ++ tPOCT6100_API_MIXER_EVENT pLastEventEntry; ++ tPOCT6100_API_MIXER_EVENT pLastLoadOrAccumulateEventEntry; ++ ++ tPOCT6100_API_CHANNEL pSourceChanEntry; ++ tPOCT6100_API_CHANNEL pDestinationChanEntry; ++ ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pSourceParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pDestinationParticipant; ++ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ ++ UINT32 ulResult; ++ UINT32 ulLoopCount; ++ UINT16 usLastLoadEventIndex; ++ UINT16 usLoadOrAccumulateEventIndex; ++ UINT16 usTempEventIndex; ++ UINT16 usPreviousEventIndex; ++ UINT16 usLastEventIndex; ++ ++ UINT16 usReadData; ++ BOOL fLastEvent = FALSE; ++ BOOL fSoutCopyEvent = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceChanEntry, f_usSourceChannelIndex ); ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceParticipant, pSourceChanEntry->usFlexConfParticipantIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationChanEntry, f_usDestinationChannelIndex ); ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationParticipant, pDestinationChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if the mixer has been created on this channel. */ ++ if ( pDestinationParticipant->fFlexibleMixerCreated == TRUE ) ++ { ++ /*=======================================================================*/ ++ /* Clear the Load or Accumulate event.*/ ++ ++ usTempEventIndex = pDestinationChanEntry->usLoadEventIndex; ++ ulLoopCount = 0; ++ ++ /* Find the Load or Accumulate event entry. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usTempEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pStoreEventEntry, pDestinationChanEntry->usSubStoreEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ pLastEventEntry = pLoadEventEntry; ++ pLastLoadOrAccumulateEventEntry = pLoadEventEntry; ++ usLastLoadEventIndex = usTempEventIndex; ++ usLastEventIndex = usTempEventIndex; ++ ++ while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && ++ pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) ++ { ++ /* If this is the entry we are looking for. */ ++ if ( pTempEntry->usSourceChanIndex == f_usSourceChannelIndex ) ++ { ++ /* Check if this is a Load or Accumulate event. */ ++ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD ) ++ { ++ /* This is the first entry. Check if next entry is an accumulate. */ ++ pLoadTempEntry = pTempEntry; ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, pTempEntry->usNextEventPtr ); ++ ++ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) ++ { ++ /* Change this entry into a Load event. */ ++ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadTempEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the channel information with this new load event. */ ++ pDestinationChanEntry->usLoadEventIndex = pLoadTempEntry->usNextEventPtr; ++ ++ /* Update the software model. */ ++ pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ ++ /* Get the previous event. */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); ++ usLastEventIndex = usPreviousEventIndex; ++ ++ /* Stop searching. */ ++ break; ++ } ++ else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE ) ++ { ++ /* Get back the event to remove. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ /* This is the only event on this channel so we can clear everything up. */ ++ fLastEvent = TRUE; ++ ++ /* Get the previous event. */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); ++ usLastEventIndex = usPreviousEventIndex; ++ ++ /* Stop searching. */ ++ break; ++ } ++ else ++ { ++ /* Software model is broken. */ ++ return cOCT6100_ERR_FATAL_C5; ++ } ++ ++ } ++ else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) ++ { ++ /* Simply remove the entry. */ ++ ++ /* Get the previous event. */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); ++ usLastEventIndex = usPreviousEventIndex; ++ ++ /* Stop searching. */ ++ break; ++ } ++ else ++ { ++ /* Software model is broken. */ ++ return cOCT6100_ERR_FATAL_C6; ++ } ++ } ++ ++ pLastLoadOrAccumulateEventEntry = pTempEntry; ++ usLastLoadEventIndex = usTempEventIndex; ++ ++ /* Go to the next entry into the list. */ ++ usTempEventIndex = pTempEntry->usNextEventPtr; ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ ulLoopCount++; ++ if ( ulLoopCount == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_FATAL_C8; ++ } ++ ++ /* Check if we found what we were looking for. */ ++ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE ++ || pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE ) ++ { ++ /* Software model is broken. */ ++ return cOCT6100_ERR_FATAL_C7; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Clear the Store event - if needed. */ ++ ++ if ( fLastEvent == TRUE ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Clear the Load or Accumulate event. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save this event index. It's the Load or Accumulate we want to remove from the list later. */ ++ usLoadOrAccumulateEventIndex = usTempEventIndex; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Clear the Copy event - if needed. */ ++ ++ if ( ( fLastEvent == TRUE ) && ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) ) ++ { ++ /* Transform event into no-operation. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* The event remove from the list will be done below. */ ++ ++ /* Clear the copy event created flag. */ ++ pDestinationChanEntry->fCopyEventCreated = FALSE; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /*=======================================================================*/ ++ /* Remove the events from the mixer event list.*/ ++ /*=======================================================================*/ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Remove the Load or Accumulate event from the event list. */ ++ ++ if ( fLastEvent == FALSE ) ++ { ++ /*=======================================================================*/ ++ /* Remove the Accumulate event from the event list. */ ++ ++ /* We saved the Load or Accumulate event above. We also saved the previous event. Use those. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usLoadOrAccumulateEventIndex ); ++ ++ /* Now modify the previous last event. */ ++ pLastEventEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr; ++ ++ /* Modify the previous node. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = pLastEventEntry->usNextEventPtr; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if this is the first load event on the bridge. */ ++ if ( pBridgeEntry->usFirstLoadEventPtr == usLoadOrAccumulateEventIndex ) ++ { ++ pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr; ++ } ++ ++ /* Check if this was the first load of all bridges. */ ++ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex ) ++ { ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr; ++ } ++ ++ /*=======================================================================*/ ++ } ++ else /* if ( fLastEvent == TRUE ) */ ++ { ++ /*=======================================================================*/ ++ /* Remove the Load event from the event list. */ ++ ++ /* Look for the entry that is pointing at the first entry of our mixer. */ ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usLoadOrAccumulateEventIndex, 0, &usPreviousEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* An Entry was found, now, modify it's value. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); ++ ++ /* Check if this is a Sout copy event. */ ++ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_COPY ) ++ { ++ /* No more previous bridges. */ ++ fSoutCopyEvent = TRUE; ++ } ++ ++ /* Now modify the previous last Store or Sub-Store or Head-Node event from another bridge/channel. */ ++ pTempEntry->usNextEventPtr = pStoreEventEntry->usNextEventPtr; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Modify the last node of the previous bridge/channel to point to the next bridge. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ ++ WriteParams.usWriteData = pTempEntry->usNextEventPtr; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Set the event pointer info in the bridge stucture. */ ++ ++ if ( pBridgeEntry->usFirstLoadEventPtr == pDestinationChanEntry->usLoadEventIndex ) ++ { ++ UINT16 usChannelIndex; ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ ++ pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; ++ pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; ++ ++ /* Find the next channel in this conference that could give us valid values. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ if ( ( usChannelIndex != f_usDestinationChannelIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ if ( pTempParticipant->fFlexibleMixerCreated == TRUE ) ++ { ++ pBridgeEntry->usFirstSubStoreEventPtr = pTempEchoChanEntry->usSubStoreEventIndex; ++ pBridgeEntry->usFirstLoadEventPtr = pTempEchoChanEntry->usLoadEventIndex; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ /* Reprogram the TSST entry correctly if the extra SIN TSI entry was released. */ ++ if ( ( pDestinationChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) ) ++ { ++ if ( pDestinationChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pDestinationChanEntry->usSinTsstIndex, ++ pDestinationChanEntry->usSinSoutTsiMemIndex, ++ pDestinationChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If the silence TSI is loaded on this port, update with the original sin TSI. */ ++ if ( pDestinationChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pDestinationChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Reprogram the TSST entry correctly if the extra RIN TSI entry was released. */ ++ if ( ( pDestinationChanEntry->usExtraRinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) ) ++ { ++ if ( pDestinationChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pDestinationChanEntry->usRinTsstIndex, ++ pDestinationChanEntry->usRinRoutTsiMemIndex, ++ pDestinationChanEntry->TdmConfig.byRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /*=======================================================================*/ ++ /* Update the global mixer pointers. */ ++ ++ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex && ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr == pDestinationChanEntry->usSubStoreEventIndex ) ++ { ++ /* There is no more bridge entry in the mixer link list. */ ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex ) ++ { ++ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pStoreEventEntry->usNextEventPtr; ++ } ++ else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pDestinationChanEntry->usSubStoreEventIndex ) ++ { ++ pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Check if must remove the Sin copy event from the list. */ ++ ++ if ( ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) ) ++ { ++ /* Now remove the copy event from the event list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pDestinationChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ ++ /*=======================================================================*/ ++ ++ if ( f_fRemovePermanently == TRUE ) ++ { ++ /* Set the event entries as free. */ ++ pLoadEventEntry->fReserved = FALSE; ++ pLoadEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ pStoreEventEntry->fReserved = FALSE; ++ pStoreEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ if ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pDestinationChanEntry->usSinCopyEventIndex ); ++ ++ pCopyEventEntry->fReserved = FALSE; ++ pCopyEventEntry->usEventType = cOCT6100_INVALID_EVENT; ++ pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ /* Flexible mixer for this channel not created anymore. */ ++ pDestinationParticipant->fFlexibleMixerCreated = FALSE; ++ ++ /*=======================================================================*/ ++ } ++ ++ /*=======================================================================*/ ++ } ++ else /* if ( pDestinationChanEntry->fFlexibleMixerCreated == FALSE ) */ ++ { ++ /* This point should never be reached. */ ++ return cOCT6100_ERR_FATAL_C9; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanMuteSer ++ ++Description: Mute an echo channel present on a conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeMute Pointer to conference bridge mute structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanMuteSer ++UINT32 Oct6100ConfBridgeChanMuteSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ) ++{ ++ UINT16 usChanIndex; ++ UINT16 usLoadEventIndex; ++ UINT16 usSubStoreEventIndex; ++ UINT32 ulResult; ++ UINT8 fFlexibleConferencing; ++ ++ /* Check the validity of the channel and conference bridge given. */ ++ ulResult = Oct6100ApiCheckBridgeMuteParams( ++ f_pApiInstance, ++ f_pConfBridgeMute, ++ &usChanIndex, ++ &usLoadEventIndex, ++ &usSubStoreEventIndex, ++ &fFlexibleConferencing ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Modify all resources needed by the conference bridge. */ ++ ulResult = Oct6100ApiUpdateBridgeMuteResources( ++ f_pApiInstance, ++ usChanIndex, ++ usLoadEventIndex, ++ usSubStoreEventIndex, ++ fFlexibleConferencing ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBridgeMuteParams ++ ++Description: Check the validity of the channel and conference bridge given. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeMute Pointer to conference bridge channel mute structure. ++f_pusChannelIndex Pointer to a channel index. ++f_pusLoadEventIndex Pointer to a load mixer event index. ++f_pusSubStoreEventIndex Pointer to a sub-store mixer event index. ++f_pfFlexibleConfBridge If this is a flexible conference bridge. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBridgeMuteParams ++UINT32 Oct6100ApiCheckBridgeMuteParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT8 f_pfFlexibleConfBridge ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ if ( f_pConfBridgeMute->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle.*/ ++ ++ if ( (f_pConfBridgeMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusChannelIndex = (UINT16)( f_pConfBridgeMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /* Check if the channel is bound to a conference bridge. */ ++ if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; ++ ++ /* Check if channel is already muted. */ ++ if ( pEchoChanEntry->fMute == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_ALREADY_MUTED; ++ ++ /* Check if this is a tap channel, which is always mute. */ ++ if ( pEchoChanEntry->fTap == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_ALWAYS_MUTE; ++ ++ /*=====================================================================*/ ++ ++ /*=====================================================================*/ ++ /* Check the conference bridge handle. */ ++ ++ if ( pEchoChanEntry->usBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ ++ if ( pBridgeEntry->fFlexibleConferencing == FALSE ) ++ { ++ /* Check the event entries.*/ ++ if ( pEchoChanEntry->usLoadEventIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; ++ ++ if ( pEchoChanEntry->usSubStoreEventIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; ++ } ++ ++ /*=====================================================================*/ ++ ++ /* Return the config of the channel and all other important information. */ ++ *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex; ++ *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex; ++ *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateBridgeMuteResources ++ ++Description: Modify the conference bridge entry for this channel in order ++ to mute the specified channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usChanIndex Index of the channel to be muted. ++f_usLoadEventIndex Allocated entry for the Load event of the channel. ++f_usSubStoreEventIndex Allocated entry for the substract and store event of the channel. ++f_fFlexibleConfBridge If this is a flexible conference bridge. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateBridgeMuteResources ++UINT32 Oct6100ApiUpdateBridgeMuteResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT8 f_fFlexibleConfBridge ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ tPOCT6100_API_MIXER_EVENT pLoadEventEntry; ++ tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEntry; ++ UINT32 ulResult; ++ UINT16 usTempEventIndex; ++ UINT32 ulLoopCount; ++ UINT16 usReadData; ++ ++ BOOL fCreateSilenceLoad = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) ++ ++ if ( f_fFlexibleConfBridge == TRUE ) ++ { ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ UINT16 usChannelIndex; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; ++ ++ UINT16 ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; ++ UINT32 ulMutePortChannelIndex; ++ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Search through the list of API channel entry for the ones on to this bridge. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ if ( pTempEchoChanEntry->usBridgeIndex == pEchoChanEntry->usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if this participant can hear us. */ ++ if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) ) ++ { ++ /* Then update this channel's mixer. */ ++ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( ++ f_pApiInstance, ++ pEchoChanEntry->usBridgeIndex, ++ f_usChanIndex, ++ usChannelIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /* Remember to mute the port on this channel. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usChannelIndex ) ++ { ++ break; ++ } ++ else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) ++ { ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usChannelIndex; ++ break; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /* Check if the Rin port must be muted on this channel. */ ++ ulResult = Oct6100ApiMutePorts( ++ f_pApiInstance, ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ], ++ pTempEchoChanEntry->usRinTsstIndex, ++ pTempEchoChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_MIXER_ALL_MIXER_EVENT_ENTRY_OPENED ) ++ { ++ UINT32 ulTempResult; ++ ++ /* Cleanup resources, unmute channel... */ ++ ulTempResult = Oct6100ApiUpdateBridgeUnMuteResources( ++ f_pApiInstance, ++ f_usChanIndex, ++ f_usLoadEventIndex, ++ f_usSubStoreEventIndex, ++ TRUE ); ++ if ( ulTempResult != cOCT6100_ERR_OK ) ++ return ulTempResult; ++ else ++ return ulResult; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ } ++ } ++ else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ ++ { ++ /* No more channels to check for muting. */ ++ break; ++ } ++ } ++ } ++ else /* if ( f_fFlexibleConfBridge == FALSE ) */ ++ { ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); ++ ++ /*=======================================================================*/ ++ /* Program the Load event. */ ++ ++ /* Create silence load if this is the first event of the bridge. */ ++ if ( f_usLoadEventIndex == pBridgeEntry->usFirstLoadEventPtr ) ++ fCreateSilenceLoad = TRUE; ++ ++ /* First check if this event was a load or an accumulate event, if it's a load */ ++ /* we need to find a new load. */ ++ if ( f_usLoadEventIndex == pBridgeEntry->usLoadIndex ) ++ { ++ /* Change the next entry if one is present to a load event to keep the bridge alive. */ ++ if ( pBridgeEntry->usNumClients == 1 ) ++ { ++ /* There is no other entry on the bridge, no need to search for an Accumulate event. */ ++ pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ /* Search for an accumulate event to tranform into a Load event. */ ++ usTempEventIndex = pLoadEventEntry->usNextEventPtr; ++ ulLoopCount = 0; ++ ++ /* Find the copy entry before the entry to remove. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && ++ pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) ++ { ++ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) ++ { ++ /* Change this entry into a load event. */ ++ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set this entry as the load index. */ ++ pBridgeEntry->usLoadIndex = usTempEventIndex; ++ ++ /* Update the software model. */ ++ pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ ++ /* Stop searching. */ ++ break; ++ } ++ ++ /* Go to the next entry into the list. */ ++ usTempEventIndex = pTempEntry->usNextEventPtr; ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ ulLoopCount++; ++ if ( ulLoopCount == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_FATAL_9B; ++ } ++ } ++ } ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ /* Do not load the sample if the channel is muted. */ ++ if ( fCreateSilenceLoad == TRUE ) ++ { ++ if ( pBridgeEntry->usSilenceLoadEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* Instead of No-oping, load the silence TSI, to make sure the other conferences before us are not heard. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */ ++ ++ /* Remember the silence load event. */ ++ pBridgeEntry->usSilenceLoadEventPtr = f_usLoadEventIndex; ++ } ++ else ++ { ++ /* Do nothing. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ } ++ } ++ else ++ { ++ /* Do nothing. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the software model. */ ++ pLoadEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Program the Substract and store event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ /* Do not load the sample if the channel is muted. */ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_STORE; ++ ++ /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */ ++ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Sout input. */ ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ } ++ else /* if ( pEchoChanEntry->usSinCopyEventIndex == cOCT6100_INVALID_INDEX ) */ ++ { ++ /* Rin input. */ ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the software model. */ ++ pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_STORE; ++ ++ /*=======================================================================*/ ++ } ++ ++ /* Update the channel entry API structure */ ++ pEchoChanEntry->fMute = TRUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeChanUnMuteSer ++ ++Description: UnMute an echo channel present on a conference bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeUnMute Pointer to conference bridge channel unmute structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeChanUnMuteSer ++UINT32 Oct6100ConfBridgeChanUnMuteSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ) ++{ ++ UINT16 usChanIndex; ++ UINT16 usLoadEventIndex; ++ UINT16 usSubStoreEventIndex; ++ UINT8 fFlexibleConfBridge; ++ UINT32 ulResult; ++ ++ /* Check the validity of the channel and conference bridge given. */ ++ ulResult = Oct6100ApiCheckBridgeUnMuteParams( ++ f_pApiInstance, ++ f_pConfBridgeUnMute, ++ &usChanIndex, ++ &usLoadEventIndex, ++ &usSubStoreEventIndex, ++ &fFlexibleConfBridge ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Modify all resources needed by the conference bridge. */ ++ ulResult = Oct6100ApiUpdateBridgeUnMuteResources( ++ f_pApiInstance, ++ usChanIndex, ++ usLoadEventIndex, ++ usSubStoreEventIndex, ++ fFlexibleConfBridge ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBridgeUnMuteParams ++ ++Description: Check the validity of the channel and conference bridge given. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeUnMute Pointer to conference bridge channel unmute structure. ++f_pusChannelIndex Pointer to the channel index fo the channel to be unmuted. ++f_pusLoadEventIndex Pointer to the load index of the channel. ++f_pusSubStoreEventIndex Pointer to the sub-store event of the channel. ++f_pfFlexibleConfBridge If this is a flexible conference bridge. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBridgeUnMuteParams ++UINT32 Oct6100ApiCheckBridgeUnMuteParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT8 f_pfFlexibleConfBridge ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ if ( f_pConfBridgeUnMute->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_ADD_INVALID_HANDLE; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle.*/ ++ ++ if ( (f_pConfBridgeUnMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusChannelIndex = (UINT16)( f_pConfBridgeUnMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeUnMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /* Check if the channel is bound to a conference bridge.*/ ++ if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; ++ ++ /* Check if channel is already muted.*/ ++ if ( pEchoChanEntry->fMute == FALSE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_NOT_MUTED; ++ ++ /*=====================================================================*/ ++ ++ /*=====================================================================*/ ++ /* Check the conference bridge handle. */ ++ ++ if ( pEchoChanEntry->usBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ ++ /* Check the event entries.*/ ++ if ( pBridgeEntry->fFlexibleConferencing == FALSE ) ++ { ++ if ( pEchoChanEntry->usLoadEventIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; ++ ++ /* Check the event entries.*/ ++ if ( pEchoChanEntry->usSubStoreEventIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_MUTE_INVALID_HANDLE; ++ } ++ ++ /*=====================================================================*/ ++ ++ /* Return the config of the channel and all other important information.*/ ++ *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex; ++ *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex; ++ *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateBridgeUnMuteResources ++ ++Description: Modify the conference bridge entry for this channel in order ++ to un-mute the specified channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usChanIndex Index of the channel to be unmuted. ++f_usLoadEventIndex Allocated entry for the Load event of the channel. ++f_usSubStoreEventIndex Allocated entry for the substract and store event of the channel. ++f_fFlexibleConfBridge If this is a flexible conference bridge. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateBridgeUnMuteResources ++UINT32 Oct6100ApiUpdateBridgeUnMuteResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT8 f_fFlexibleConfBridge ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ ++ tPOCT6100_API_MIXER_EVENT pLoadEventEntry; ++ tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEntry; ++ UINT32 ulResult; ++ UINT16 usTempEventIndex; ++ UINT32 ulLoopCount; ++ UINT16 usReadData; ++ ++ UINT16 usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ UINT16 usPreviousLoadIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pEchoChanEntry->usBridgeIndex ) ++ ++ if ( f_fFlexibleConfBridge == TRUE ) ++ { ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ UINT16 usChannelIndex; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Before doing anything, check if the copy events must be created. */ ++ if ( ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChanEntry->fCopyEventCreated == FALSE ) ) ++ { ++ /* The copy event has not been created, create it once for the life of the participant on the bridge. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ WriteParams.usWriteData |= pEchoChanEntry->usExtraSinTsiMemIndex; ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now insert the Sin copy event into the list. */ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ pEchoChanEntry->usSinCopyEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY, ++ f_usChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pEchoChanEntry->fCopyEventCreated = TRUE; ++ } ++ ++ /* Search through the list of API channel entry for the ones onto this bridge. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == pEchoChanEntry->usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if this participant can hear us. */ ++ if ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ { ++ /* Then create/update this channel's mixer. */ ++ ulResult = Oct6100ApiBridgeAddParticipantToChannel( ++ f_pApiInstance, ++ pEchoChanEntry->usBridgeIndex, ++ f_usChanIndex, ++ usChannelIndex, ++ pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ], ++ pTempEchoChanEntry->usSubStoreEventIndex, ++ pTempEchoChanEntry->usSinCopyEventIndex, ++ pParticipant->ulInputPort, ++ pTempParticipant->ulInputPort ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the Rin silence event can be cleared now that the */ ++ /* channel has unmuted. */ ++ if ( ( pTempParticipant->fFlexibleMixerCreated == TRUE ) ++ && ( pTempEchoChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) ++ { ++ /* Remove the event from the list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pTempEchoChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempEchoChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_DF; ++ ++ pTempEchoChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ } ++ } ++ } ++ else /* if ( f_fFlexibleConfBridge == FALSE ) */ ++ { ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); ++ ++ /*=======================================================================*/ ++ /* Program the Load event. */ ++ ++ /* Before reactivating this event, check what type of event this event must be. */ ++ if ( f_usLoadEventIndex == pBridgeEntry->usFirstLoadEventPtr || ++ pBridgeEntry->usLoadIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* This event must become a Load event. */ ++ usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ pBridgeEntry->usLoadIndex = f_usLoadEventIndex; ++ } ++ ++ usTempEventIndex = pBridgeEntry->usFirstLoadEventPtr; ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ ulLoopCount = 0; ++ ++ while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && ++ pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) ++ { ++ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD ) ++ { ++ usPreviousLoadIndex = usTempEventIndex; ++ } ++ ++ /* Check if the previous load event is before or after the event about to be unmuted. */ ++ if ( pTempEntry->usNextEventPtr == f_usLoadEventIndex ) ++ { ++ if ( usPreviousLoadIndex == cOCT6100_INVALID_INDEX ) ++ { ++ /* We did not find a load event before our node, this mean this one */ ++ /* is about to become the new load event. */ ++ usLoadEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; ++ } ++ } ++ ++ /* Go to the next entry into the list. */ ++ usTempEventIndex = pTempEntry->usNextEventPtr; ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ++ ++ ulLoopCount++; ++ if ( ulLoopCount == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_FATAL_9B; ++ } ++ ++ /* Now program the current event node. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = usLoadEventType; ++ ++ /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */ ++ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Sout source */ ++ WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; ++ } ++ else ++ { ++ /* Rin source */ ++ WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the software event to reflect the hardware. */ ++ pLoadEventEntry->usEventType = usLoadEventType; ++ ++ /* Check if we need to change another node. */ ++ if ( usLoadEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD ) ++ { ++ if ( usPreviousLoadIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Now program the old load event. */ ++ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousLoadIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the software event to reflect the hardware. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousLoadIndex ); ++ pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE; ++ } ++ } ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Program the Substract and store event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; ++ /* If we have an extra Sin copy event, we know we are using the Sout port as a source. */ ++ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Sout port source */ ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.bySoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ WriteParams.usWriteData |= pEchoChanEntry->usSinSoutTsiMemIndex; ++ } ++ else ++ { ++ /* Rin port source */ ++ WriteParams.usWriteData |= pEchoChanEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ WriteParams.usWriteData |= pEchoChanEntry->usRinRoutTsiMemIndex; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pEchoChanEntry->usRinRoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the software event to reflect the hardware. */ ++ pSubStoreEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_SUB_STORE; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Check if have to remove silence load event. */ ++ ++ if ( pBridgeEntry->usSilenceLoadEventPtr != cOCT6100_INVALID_INDEX ) ++ { ++ if ( pBridgeEntry->usSilenceLoadEventPtr == f_usLoadEventIndex ) ++ { ++ /* Clear the silence load event ptr. */ ++ pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ ++ /* Update the channel entry API structure */ ++ pEchoChanEntry->fMute = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeDominantSpeakerSetSer ++ ++Description: This function sets the dominant speaker of a bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++ ++f_pConfBridgeDominant Pointer to conference bridge dominant speaker ++ structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeDominantSpeakerSetSer ++UINT32 Oct6100ConfBridgeDominantSpeakerSetSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ) ++{ ++ UINT16 usChanIndex; ++ UINT16 usBridgeIndex; ++ UINT32 ulResult; ++ ++ /* Check the validity of the channel handle given. */ ++ ulResult = Oct6100ApiCheckBridgeDominantSpeakerParams( f_pApiInstance, f_pConfBridgeDominantSpeaker, &usChanIndex, &usBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Modify all resources needed by the conference bridge. */ ++ ulResult = Oct6100ApiUpdateBridgeDominantSpeakerResources( f_pApiInstance, usChanIndex, usBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBridgeDominantSpeakerParams ++ ++Description: Check the validity of the channel given for setting the ++ dominant speaker. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pConfBridgeDominant Pointer to conference bridge channel dominant speaker structure. ++f_pusChannelIndex Pointer to a channel index. ++f_pusChannelIndex Pointer to a bridge index. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBridgeDominantSpeakerParams ++UINT32 Oct6100ApiCheckBridgeDominantSpeakerParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusBridgeIndex ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ UINT32 ulEntryOpenCnt; ++ BOOL fCheckEntryOpenCnt = FALSE; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ if ( f_pConfBridgeDominantSpeaker->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle. */ ++ ++ if ( f_pConfBridgeDominantSpeaker->ulChannelHndl != cOCT6100_CONF_NO_DOMINANT_SPEAKER_HNDL ) ++ { ++ if ( (f_pConfBridgeDominantSpeaker->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusChannelIndex = (UINT16)( f_pConfBridgeDominantSpeaker->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeDominantSpeaker->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /* Check if the channel is bound to a conference bridge. */ ++ if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE; ++ ++ /* Check if the NLP is enabled on this channel. */ ++ if ( pEchoChanEntry->VqeConfig.fEnableNlp == FALSE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NLP_MUST_BE_ENABLED; ++ ++ /* Check if conferencing noise reduction is enabled on this channel. */ ++ if ( pEchoChanEntry->VqeConfig.fSoutConferencingNoiseReduction == FALSE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CNR_MUST_BE_ENABLED; ++ ++ /* Check if this is a tap channel. If it is, it will never be the dominant speaker! */ ++ if ( pEchoChanEntry->fTap == TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_ALWAYS_MUTE; ++ ++ /* Set the bridge index. */ ++ *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex; ++ } ++ else ++ { ++ /* Set this such that there is no dominant speaker on this conference bridge. */ ++ *f_pusChannelIndex = cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED; ++ ++ /* Check the conference bridge handle. */ ++ if ( (f_pConfBridgeDominantSpeaker->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /* Set the bridge index. */ ++ *f_pusBridgeIndex = (UINT16)( f_pConfBridgeDominantSpeaker->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeDominantSpeaker->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ fCheckEntryOpenCnt = TRUE; ++ } ++ ++ /*=====================================================================*/ ++ ++ /*=====================================================================*/ ++ ++ if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( fCheckEntryOpenCnt == TRUE ) ++ { ++ if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ } ++ ++ /*=====================================================================*/ ++ /* Check if dominant speaker is supported in this firmware version. */ ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_DOMINANT_SPEAKER; ++ ++ /*=====================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateBridgeDominantSpeakerResources ++ ++Description: Modify the conference bridge such that the new dominant ++ speaker is the one specified by the index. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usChanIndex Index of the channel to be set as the dominant speaker. ++f_usBridgeIndex Index of the bridge where this channel is on. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateBridgeDominantSpeakerResources ++UINT32 Oct6100ApiUpdateBridgeDominantSpeakerResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usBridgeIndex ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ UINT16 usChannelIndex; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get the bridge entry for this channel. */ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ) ++ ++ /* Set the dominant speaker index for all channels in this conference. */ ++ ++ /* Search through the list of API channel entry for the ones on to this bridge.*/ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usChannelIndex ); ++ ++ if ( pEchoChanEntry->fReserved == TRUE ) ++ { ++ if ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ /* If we are unsetting the dominant speaker, of if it is not our channel index. */ ++ if ( ( f_usChanIndex == cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ) ++ || ( f_usChanIndex != usChannelIndex ) ) ++ { ++ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, usChannelIndex, f_usChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ } ++ ++ /* Make sure this channel is disabled. */ ++ if ( f_usChanIndex != cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ) ++ { ++ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Save this in the conference bridge structure. */ ++ /* This will be needed later when removing the channel. */ ++ pBridgeEntry->fDominantSpeakerSet = TRUE; ++ pBridgeEntry->usDominantSpeakerChanIndex = f_usChanIndex; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeMaskChangeSer ++ ++Description: This function changes the mask of flexible bridge ++ participant. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++ ++f_pConfBridgeMaskChange Pointer to conference bridge participant mask ++ change structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeMaskChangeSer ++UINT32 Oct6100ConfBridgeMaskChangeSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ) ++{ ++ UINT16 usChanIndex; ++ UINT16 usBridgeIndex; ++ UINT32 ulResult; ++ UINT32 ulNewParticipantMask; ++ ++ /* Check the validity of the channel handle given. */ ++ ulResult = Oct6100ApiCheckBridgeMaskChangeParams( f_pApiInstance, f_pConfBridgeMaskChange, &usChanIndex, &usBridgeIndex, &ulNewParticipantMask ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update all resources needed by the new mask. */ ++ ulResult = Oct6100ApiUpdateMaskModifyResources( f_pApiInstance, usBridgeIndex, usChanIndex, ulNewParticipantMask ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Commit the changes to the chip's internal memories. */ ++ ulResult = Oct6100ApiBridgeUpdateMask( f_pApiInstance, usBridgeIndex, usChanIndex, ulNewParticipantMask ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBridgeMaskChangeParams ++ ++Description: Check the validity of the channel given for setting the ++ mask. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeMaskChange Pointer to conference bridge channel mask change structure. ++f_pusChannelIndex Pointer to a channel index. ++f_pusBridgeIndex Pointer to a bridge index. ++f_pulNewParticipantMask New mask to apply for this participant. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBridgeMaskChangeParams ++UINT32 Oct6100ApiCheckBridgeMaskChangeParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusBridgeIndex, ++ OUT PUINT32 f_pulNewParticipantMask ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ if ( f_pConfBridgeMaskChange->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle.*/ ++ ++ if ( (f_pConfBridgeMaskChange->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ *f_pusChannelIndex = (UINT16)( f_pConfBridgeMaskChange->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeMaskChange->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /* Check if the channel is bound to a conference bridge. */ ++ if ( pEchoChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE; ++ ++ /* Set the bridge index. */ ++ *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex; ++ ++ /*=====================================================================*/ ++ ++ /*=====================================================================*/ ++ ++ if ( ( *f_pusBridgeIndex == cOCT6100_INVALID_INDEX ) ++ || ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ ++ /* Check if this is bridge is a flexible conference bridge. */ ++ if ( pBridgeEntry->fFlexibleConferencing == FALSE ) ++ return cOCT6100_ERR_CONF_BRIDGE_SIMPLE_BRIDGE; ++ ++ /*=====================================================================*/ ++ ++ /* Return new mask to apply. */ ++ *f_pulNewParticipantMask = f_pConfBridgeMaskChange->ulNewListenerMask; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateMaskModifyResources ++ ++Description: Modify/reserve all resources needed for the modification of ++ the participant's mask. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usBridgeIndex Bridge index of the bridge where this channel is residing. ++f_usChanIndex Channel index of the channel to be modified. ++f_ulNewListenerMask New mask to apply to the selected participant. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateMaskModifyResources ++UINT32 Oct6100ApiUpdateMaskModifyResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT32 f_ulNewListenerMask ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; ++ ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 ulTempVar; ++ UINT32 ulOldListenerMask; ++ UINT16 usChannelIndex; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Must travel all clients of this conference and reserve a load or accumulate event for */ ++ /* all participants which could not hear us but now can. While at it, check for events that */ ++ /* could be released, for example a participant that we cannot hear anymore. */ ++ ++ ulOldListenerMask = pParticipant->ulListenerMask; ++ ++ /* Search through the list of API channel entry for the ones on to this bridge.*/ ++ for ( usChannelIndex = 0; ( usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ) ; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can now hear this participant, but could not before. */ ++ if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ) ++ { ++ /* Must reserve a load or accumulate entry mixer event here! */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Most probably, the hardware is out of mixer events. */ ++ break; ++ } ++ } ++ ++ /* Check if we can now NOT hear this participant, but could before. */ ++ if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ++ && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) ++ { ++ /* Must release the load or accumulate entry mixer event. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ /* If an error is returned, make sure everything is cleaned up properly. */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Search through the list of API channel entry for the ones on to this bridge.*/ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can now hear this participant, but could not before. */ ++ if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ) ++ { ++ /* If the load or event entry in the mixer memory was reserved. */ ++ if ( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ /* Must release the load or accumulate entry mixer event. */ ++ ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ } ++ ++ /* Check if we can now NOT hear this participant, but could before. */ ++ if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ++ && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) ++ { ++ /* If the load or event entry in the mixer memory was reserved. */ ++ if ( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] == cOCT6100_INVALID_INDEX ) ++ { ++ /* Must release the load or accumulate entry mixer event. */ ++ ulTempVar = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &( pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ) ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ } ++ } ++ } ++ } ++ ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBridgeUpdateMask ++ ++Description: Update the participant's mask. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_usBridgeIndex Bridge index of the bridge where this channel is residing. ++f_usChanIndex Channel index of the channel to be modified. ++f_ulNewListenerMask New mask to apply to the selected participant. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBridgeUpdateMask ++UINT32 Oct6100ApiBridgeUpdateMask( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT32 f_ulNewListenerMask ) ++{ ++ tPOCT6100_API_CHANNEL pChanEntry; ++ tPOCT6100_API_CHANNEL pTempEchoChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; ++ tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ ++ UINT32 ulResult; ++ UINT32 ulOldListenerMask; ++ UINT16 usChannelIndex; ++ ++ UINT16 ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; ++ UINT32 ulMutePortChannelIndex; ++ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pChanEntry->usFlexConfParticipantIndex ); ++ ++ ulOldListenerMask = pParticipant->ulListenerMask; ++ ++ /* Search through the list of API channel entry for the ones onto this bridge. */ ++ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); ++ ++ /* Channel reserved? */ ++ if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) ++ { ++ /* On current bridge? */ ++ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ++ { ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ /* Check if we can now hear this participant, but could not before. */ ++ if ( ( pTempEchoChanEntry->fMute == FALSE ) ++ && ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ) ++ { ++ /* First create/update the current channel's mixer. */ ++ ulResult = Oct6100ApiBridgeAddParticipantToChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ usChannelIndex, ++ f_usChanIndex, ++ pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ], ++ pChanEntry->usSubStoreEventIndex, ++ pChanEntry->usSinCopyEventIndex, ++ pTempParticipant->ulInputPort, ++ pParticipant->ulInputPort ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( pParticipant->fFlexibleMixerCreated == TRUE ) ++ { ++ /* Check if the Rin silence event can be cleared now that the */ ++ /* channel has been added to a conference. */ ++ if ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Remove the event from the list.*/ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ pChanEntry->usRinSilenceEventIndex, ++ cOCT6100_EVENT_TYPE_SOUT_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_DF; ++ ++ pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ ++ /* Check if we can now NOT hear this participant, but could before. */ ++ if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ++ && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ++ && ( pParticipant->fFlexibleMixerCreated == TRUE ) ++ && ( pTempEchoChanEntry->fMute == FALSE ) ) ++ { ++ /* First update the current channel's mixer. */ ++ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( ++ f_pApiInstance, ++ f_usBridgeIndex, ++ usChannelIndex, ++ f_usChanIndex, ++ TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( pParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /* Remember to mute the port on this channel. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == f_usChanIndex ) ++ { ++ break; ++ } ++ else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) ++ { ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = f_usChanIndex; ++ break; ++ } ++ } ++ } ++ } ++ ++ /* Clear the load or accumulate event index for this participant. */ ++ if ( ( ( f_ulNewListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) != 0x0 ) ++ && ( ( ulOldListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) ) ++ { ++ pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; ++ } ++ } ++ } ++ ++ /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ ++ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ++ { ++ if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); ++ ++ if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) ++ { ++ /* Check if the Rin port must be muted on this channel. */ ++ ulResult = Oct6100ApiMutePorts( ++ f_pApiInstance, ++ ausMutePortChannelIndexes[ ulMutePortChannelIndex ], ++ pTempEchoChanEntry->usRinTsstIndex, ++ pTempEchoChanEntry->usSinTsstIndex, ++ FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ ++ { ++ /* No more channels to check for muting. */ ++ break; ++ } ++ } ++ } ++ ++ /* Configure the SIN copy mixer entry and memory - if using the SOUT port. */ ++ if ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ { ++ if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usSinTsstIndex, ++ pChanEntry->usExtraSinTsiMemIndex, ++ pChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If the silence TSI is loaded on this port, update with the extra sin TSI. */ ++ if ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = pChanEntry->usExtraSinTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Configure the RIN copy mixer entry and memory - if using the RIN port. */ ++ if ( pParticipant->ulInputPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usRinTsstIndex, ++ pChanEntry->usExtraRinTsiMemIndex, ++ pChanEntry->TdmConfig.byRinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Save the new mask permanently in the API instance. */ ++ pParticipant->ulListenerMask = f_ulNewListenerMask; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ConfBridgeGetStatsSer ++ ++Description: This function returns the statistics from the specified bridge. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pConfBridgeStats Pointer to conference bridge stats structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ConfBridgeGetStatsSer ++UINT32 Oct6100ConfBridgeGetStatsSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ UINT16 usConfBridgeIndex; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges == 0 ) ++ return cOCT6100_ERR_CONF_BRIDGE_DISABLED; ++ ++ /*=====================================================================*/ ++ /* Check the conference bridge handle. */ ++ ++ /* Check the provided handle. */ ++ if ( (f_pConfBridgeStats->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ usConfBridgeIndex = (UINT16)( f_pConfBridgeStats->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( usConfBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, usConfBridgeIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pConfBridgeStats->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pBridgeEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; ++ if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; ++ ++ /*=====================================================================*/ ++ ++ /* Return the stats.*/ ++ f_pConfBridgeStats->ulNumChannels = pBridgeEntry->usNumClients; ++ f_pConfBridgeStats->ulNumTappedChannels = pBridgeEntry->usNumTappedClients; ++ f_pConfBridgeStats->fFlexibleConferencing = pBridgeEntry->fFlexibleConferencing; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBridgeEntry ++ ++Description: Reserves a free entry in the Bridge list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pusBridgeIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBridgeEntry ++UINT32 Oct6100ApiReserveBridgeEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusBridgeIndex ) ++{ ++ PVOID pBridgeAlloc; ++ UINT32 ulResult; ++ UINT32 ulBridgeIndex; ++ ++ mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBridgeAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pBridgeAlloc, &ulBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_CONF_BRIDGE_ALL_BUFFERS_OPEN; ++ else ++ return cOCT6100_ERR_FATAL_29; ++ } ++ ++ *f_pusBridgeIndex = (UINT16)( ulBridgeIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBridgeEntry ++ ++Description: Release an entry from the bridge list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usBridgeIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBridgeEntry ++UINT32 Oct6100ApiReleaseBridgeEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex ) ++{ ++ PVOID pBridgeAlloc; ++ UINT32 ulResult; ++ ++ mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBridgeAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pBridgeAlloc, f_usBridgeIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_2A; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetPrevLastSubStoreEvent ++ ++Description: This function will search for the first valid LastSubStoreEvent ++ in a bridge located before the current bridge in the bridge ++ link list. ++ ++ If the function does not find an event before reaching the end ++ of the mixers list, then the event head node will be used as the ++ last Store or SubStore event. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pusBridgeEntry Bridge entry. ++f_usBridgeFirstLoadEventPtr Load index to check against. ++First valid sub store index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetPrevLastSubStoreEvent ++UINT32 Oct6100ApiGetPrevLastSubStoreEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usBridgeFirstLoadEventPtr, ++ OUT PUINT16 f_pusLastSubStoreEventIndex ) ++{ ++ tPOCT6100_API_CONF_BRIDGE pBridgeEntry; ++ tPOCT6100_API_MIXER_EVENT pTempMixerEntry; ++ UINT16 usNextEventPtr; ++ UINT16 usHeadEventPtr; ++ UINT16 usLastSubStoreEventPtr; ++ UINT32 ulLoopCount = 0; ++ UINT16 usCurrentPtr; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ ++ /* Get current entry to obtain the link to the previous entry.*/ ++ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); ++ ++ /* Since we have flexible bridges, we have to */ ++ /* run down the list and check for the appropriate event. */ ++ ++ /* Travel down the list for the last Store or Sub/Store event before the bridge. */ ++ ++ if ( f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* The only node in the list then is the head node.*/ ++ usHeadEventPtr = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ usHeadEventPtr = f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usHeadEventPtr ); ++ usLastSubStoreEventPtr = usHeadEventPtr; ++ usNextEventPtr = pTempMixerEntry->usNextEventPtr; ++ usCurrentPtr = usHeadEventPtr; ++ while( usCurrentPtr != f_usBridgeFirstLoadEventPtr ) ++ { ++ if ( ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE ) ++ || ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE ) ) ++ { ++ usLastSubStoreEventPtr = usNextEventPtr; ++ } ++ ++ /* Next pointer. */ ++ usCurrentPtr = usNextEventPtr; ++ usNextEventPtr = pTempMixerEntry->usNextEventPtr; ++ ++ /* Check if next event pointer is valid. */ ++ if ( ( ( f_usBridgeFirstLoadEventPtr != usCurrentPtr ) ++ && ( pTempMixerEntry->usNextEventPtr == cOCT6100_INVALID_INDEX ) ) ++ || ( pTempMixerEntry->usNextEventPtr == cOCT6100_MIXER_HEAD_NODE ) ) ++ return cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND; ++ ++ if ( usNextEventPtr != cOCT6100_INVALID_INDEX ) ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usNextEventPtr ); ++ ++ ulLoopCount++; ++ if ( ulLoopCount == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_FATAL_CA; ++ } ++ ++ /* Return the result to the user. */ ++ *f_pusLastSubStoreEventIndex = usLastSubStoreEventPtr; ++ ++ return ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetPreviousEvent ++ ++Description: This is a recursive function, it requires an entry event index and ++ will run down the list until it finds the node just before the one ++ required. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usEntryIndex Event entry index. ++f_pusBridgeEntry Bridge entry. ++f_pusPreviousIndex Previous index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetPreviousEvent ++UINT32 Oct6100ApiGetPreviousEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEntryIndex, ++ IN UINT16 f_usSearchedIndex, ++ IN UINT16 f_usLoopCnt, ++ OUT PUINT16 f_pusPreviousIndex ) ++{ ++ tPOCT6100_API_MIXER_EVENT pCurrentEntry; ++ UINT32 ulResult; ++ ++ /* Get current entry to obtain the link to the previous entry. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pCurrentEntry, f_usEntryIndex ); ++ ++ /* Avoid stack overflows. */ ++ if ( f_usLoopCnt == cOCT6100_MAX_MIXER_EVENTS ) ++ return cOCT6100_ERR_FATAL_E3; ++ ++ if ( pCurrentEntry->usNextEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* Event not found. */ ++ ulResult = cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND; ++ } ++ else if ( pCurrentEntry->usNextEventPtr == f_usSearchedIndex ) ++ { ++ /* We found our node. */ ++ *f_pusPreviousIndex = f_usEntryIndex; ++ ulResult = cOCT6100_ERR_OK; ++ } ++ else ++ { ++ /* Keep searching.*/ ++ f_usLoopCnt++; ++ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pCurrentEntry->usNextEventPtr, f_usSearchedIndex, f_usLoopCnt, f_pusPreviousIndex ); ++ } ++ ++ return ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBridgeSetDominantSpeaker ++ ++Description: This function will set the index of the dominant speaker ++ for the channel index specified. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++ ++f_usChannelIndex Index of the channel where the API must set the ++ current dominant speaker for the conference. ++f_usDominantSpeakerIndex Index of the channel which is the dominant ++ speaker in the conference. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBridgeSetDominantSpeaker ++UINT32 Oct6100ApiBridgeSetDominantSpeaker( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChannelIndex, ++ IN UINT16 f_usDominantSpeakerIndex ) ++{ ++ UINT32 ulBaseAddress; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ UINT32 ulMask; ++ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, f_usChannelIndex ); ++ ++ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byBitOffset; ++ ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byFieldSize; ++ ++ /* Retrieve the current configuration. */ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pEchoChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear previous value set in the feature field.*/ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ ulTempData &= (~ulMask); ++ ulTempData |= ( ( f_usDominantSpeakerIndex ) << ulFeatureBitOffset ); ++ ++ /* Save the new dominant speaker. */ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChanEntry, ++ ulBaseAddress + ulFeatureBytesOffset, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveFlexConfParticipantEntry ++ ++Description: Reserves a free entry in the participant list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++f_pusParticipantIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveFlexConfParticipantEntry ++UINT32 Oct6100ApiReserveFlexConfParticipantEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusParticipantIndex ) ++{ ++ PVOID pParticipantAlloc; ++ UINT32 ulResult; ++ UINT32 ulParticipantIndex; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pParticipantAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pParticipantAlloc, &ulParticipantIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_CONF_BRIDGE_FLEX_CONF_ALL_BUFFERS_OPEN; ++ else ++ return cOCT6100_ERR_FATAL_29; ++ } ++ ++ *f_pusParticipantIndex = (UINT16)( ulParticipantIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseFlexConfParticipantEntry ++ ++Description: Release an entry from the flexible conferencing participant ++ list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usParticipantIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseFlexConfParticipantEntry ++UINT32 Oct6100ApiReleaseFlexConfParticipantEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usParticipantIndex ) ++{ ++ PVOID pParticipantAlloc; ++ UINT32 ulResult; ++ ++ mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pParticipantAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pParticipantAlloc, f_usParticipantIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_2A; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_debug.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_debug.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_debug.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_debug.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1278 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_debug.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to debug the OCT6100. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 65 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_debug_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_debug_priv.h" ++#include "oct6100_version.h" ++ ++ ++/**************************** PUBLIC FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100DebugSelectChannel ++ ++Description: This function sets the current debug channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pSelectDebugChan Pointer to select debug channel structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100DebugSelectChannelDef ++UINT32 Oct6100DebugSelectChannelDef( ++ tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan ) ++{ ++ f_pSelectDebugChan->ulChannelHndl = cOCT6100_INVALID_VALUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100DebugSelectChannel ++UINT32 Oct6100DebugSelectChannel( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100DebugSelectChannelSer( f_pApiInstance, f_pSelectDebugChan, TRUE ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100DebugGetData ++ ++Description: This function retrieves the last recorded debug data. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pGetData Pointer to debug get data structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100DebugGetDataDef ++UINT32 Oct6100DebugGetDataDef( ++ tPOCT6100_DEBUG_GET_DATA f_pGetData ) ++{ ++ f_pGetData->ulGetDataMode = cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE; ++ f_pGetData->ulGetDataContent = cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE; ++ f_pGetData->ulRemainingNumBytes = cOCT6100_INVALID_VALUE; ++ f_pGetData->ulTotalNumBytes = cOCT6100_INVALID_VALUE; ++ f_pGetData->ulMaxBytes = cOCT6100_INVALID_VALUE; ++ f_pGetData->ulValidNumBytes = cOCT6100_INVALID_VALUE; ++ f_pGetData->pbyData = NULL; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100DebugGetData ++UINT32 Oct6100DebugGetData( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_DEBUG_GET_DATA f_pGetData ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100DebugGetDataSer( f_pApiInstance, f_pGetData ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100DebugSelectChannelSer ++ ++Description: This function sets the debug channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pSelectDebugChan Pointer to a tOCT6100_DEBUG_SELECT_CHANNEL structure. ++f_fCheckChannelRecording Check if channel recording is enabled or not. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100DebugSelectChannelSer ++UINT32 Oct6100DebugSelectChannelSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan, ++ IN BOOL f_fCheckChannelRecording ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry = NULL; ++ tPOCT6100_API_CHANNEL pTempChanEntry; ++ tOCT6100_CHANNEL_OPEN TempChanOpen; ++ tOCT6100_WRITE_BURST_PARAMS BurstParams; ++ UINT16 usChanIndex = 0; ++ UINT32 ulEntryOpenCnt; ++ UINT16 ausWriteData[ 2 ]; ++ UINT32 ulResult; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ BurstParams.pusWriteData = ausWriteData; ++ ++ /* First release the resources reserved for the channel that was previously debugged. */ ++ if ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex != cOCT6100_INVALID_INDEX && ++ pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ { ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempChanEntry, pSharedInfo->DebugInfo.usCurrentDebugChanIndex ) ++ ++ /* Release the extra TSI memory entry and reprogram the TSST control memory if required. */ ++ if ( pTempChanEntry->usExtraSinTsiDependencyCnt >= 1 ) ++ { ++ /*=======================================================================*/ ++ /* Clear memcpy operations. */ ++ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ BurstParams.ulWriteLength = 2; ++ ++ ausWriteData[ 0 ] = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ausWriteData[ 1 ] = 0x0; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordSinEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* If we are the last dependency using the extra Sin TSI, release it */ ++ if ( pTempChanEntry->usExtraSinTsiDependencyCnt == 1 ) ++ { ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pTempChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Do not forget to reprogram the TSST control memory. */ ++ if ( pTempChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pTempChanEntry->usSinTsstIndex, ++ pTempChanEntry->usSinSoutTsiMemIndex, ++ pTempChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ pTempChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; ++ ++ /* XXX: What about the silence TSI usSinSilenceEventIndex ?? */ ++ } ++ ++ pTempChanEntry->usExtraSinTsiDependencyCnt--; ++ ++ } ++ } ++ ++ /* Set the new parameters. */ ++ if ( f_pSelectDebugChan->ulChannelHndl != cOCT6100_INVALID_HANDLE ) ++ { ++ /* Check the provided handle. */ ++ if ( (f_pSelectDebugChan->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_DEBUG_CHANNEL_INVALID_HANDLE; ++ ++ usChanIndex = (UINT16)( f_pSelectDebugChan->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( usChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_DEBUG_CHANNEL_INVALID_HANDLE; ++ ++ if ( f_fCheckChannelRecording == TRUE ) ++ { ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) ++ return cOCT6100_ERR_DEBUG_CHANNEL_RECORDING_DISABLED; ++ } ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, usChanIndex ); ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pSelectDebugChan->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pChanEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ /* First program the mixer entry if the user wants to record. */ ++ /* Check if the API needs to reserve an extra TSI memory to load the SIN signal. */ ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ { ++ /* Reserve the extra Sin TSI memory if it was not already reserved. */ ++ if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pChanEntry->usExtraSinTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reprogram the TSST control memory accordingly. */ ++ if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ pChanEntry->usSinTsstIndex, ++ pChanEntry->usExtraSinTsiMemIndex, ++ pChanEntry->TdmConfig.bySinPcmLaw ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* XXX: What about the silence TSI usSinSilenceEventIndex ?? */ ++ } ++ ++ ++ /*=======================================================================*/ ++ /* Program the Sout Copy event. */ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ BurstParams.ulWriteLength = 2; ++ ++ ausWriteData[ 0 ] = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ ausWriteData[ 0 ] |= pChanEntry->usSinSoutTsiMemIndex; ++ ausWriteData[ 0 ] |= pChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ausWriteData[ 1 ] = (UINT16)( pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex ); ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Program the Sin copy event. */ ++ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordSinEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ BurstParams.ulWriteLength = 2; ++ ++ ausWriteData[ 0 ] = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ ausWriteData[ 0 ] |= pChanEntry->usExtraSinTsiMemIndex; ++ ausWriteData[ 0 ] |= pChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ ausWriteData[ 1 ] = pChanEntry->usSinSoutTsiMemIndex; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*=======================================================================*/ ++ ++ pChanEntry->usExtraSinTsiDependencyCnt++; ++ } ++ } ++ else ++ { ++ /* Set the index to invalid to deactivate the recording. */ ++ usChanIndex = cOCT6100_INVALID_INDEX; ++ } ++ ++ /* Set law of newly selected hot channel. */ ++ if ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ && ( f_pSelectDebugChan->ulChannelHndl != cOCT6100_INVALID_HANDLE ) ++ && ( pChanEntry != NULL ) ) ++ { ++ /* Set the PCM law of the debug channel. */ ++ /* Let's program the channel memory. */ ++ Oct6100ChannelOpenDef( &TempChanOpen ); ++ ++ TempChanOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_HT_RESET; /* Activate the channel. */ ++ TempChanOpen.VqeConfig.fEnableNlp = FALSE; ++ TempChanOpen.VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; ++ TempChanOpen.VqeConfig.fSinDcOffsetRemoval = FALSE; ++ TempChanOpen.VqeConfig.fRinDcOffsetRemoval = FALSE; ++ TempChanOpen.VqeConfig.lDefaultErlDb = 0; ++ ++ /* Use the law of the channel being recorded. */ ++ TempChanOpen.TdmConfig.ulRinPcmLaw = pChanEntry->TdmConfig.byRinPcmLaw; ++ TempChanOpen.TdmConfig.ulSinPcmLaw = pChanEntry->TdmConfig.bySinPcmLaw; ++ TempChanOpen.TdmConfig.ulRoutPcmLaw = pChanEntry->TdmConfig.byRoutPcmLaw; ++ TempChanOpen.TdmConfig.ulSoutPcmLaw = pChanEntry->TdmConfig.bySoutPcmLaw; ++ ++ ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, ++ &TempChanOpen.TdmConfig, ++ &TempChanOpen.VqeConfig, ++ &TempChanOpen, ++ pSharedInfo->DebugInfo.usRecordChanIndex, ++ pSharedInfo->DebugInfo.usRecordMemIndex, ++ pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex, ++ pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ ausWriteData[ 0 ] = 0x0; ++ ausWriteData[ 1 ] = (UINT16)(( usChanIndex >> 0) & 0xFFFF); ++ ++ /* Write the channel number into the Matrix hot channel field.*/ ++ BurstParams.ulWriteAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; ++ BurstParams.pusWriteData = ausWriteData; ++ BurstParams.ulWriteLength = 2; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pSharedInfo->DebugInfo.usCurrentDebugChanIndex = usChanIndex; ++ ++ /* Cancel data dump request, if there was one. */ ++ pSharedInfo->DebugInfo.fDebugDataBeingDumped = FALSE; ++ pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes = cOCT6100_INVALID_VALUE; ++ ++ /* Call from remote client. */ ++ if ( f_fCheckChannelRecording == FALSE ) ++ { ++ /* If the user has not activated recording, let the remote client know. */ ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) ++ return cOCT6100_ERR_DEBUG_RC_CHANNEL_RECORDING_DISABLED; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100DebugGetDataSer ++ ++Description: This function retrieves the latest recorded debug data. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pGetData Pointer to a tOCT6100_DEBUG_GET_DATA structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100DebugGetDataSer ++UINT32 Oct6100DebugGetDataSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_DEBUG_GET_DATA f_pGetData ) ++{ ++ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pChanEntry = NULL; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_BURST_PARAMS ReadBurstParams; ++ tOCT6100_WRITE_BURST_PARAMS WriteBurstParams; ++ ++ UINT16 ausWriteData[ 2 ]; ++ UINT16 usReadData; ++ UINT16 usDebugEventReadPtr; ++ UINT16 usTempNumEvents; ++ ++ UINT32 ulResult; ++ UINT32 ulToneEventIndex; ++ UINT32 ulReadPointer; ++ UINT32 ulUserBufWriteIndex = 0; ++ UINT32 ulTimestamp; ++ UINT32 ulDebugEventIndex = 0; ++ UINT32 ulStreamIndex; ++ UINT32 ulPcmSampleIndex; ++ UINT32 ulNumAfEvents; ++ UINT32 ulNumReads = 0; ++ UINT32 ulTempIndex; ++ UINT32 ulCopyIndex; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulStreamIndexMin; ++ UINT32 ulStreamIndexMax; ++ UINT32 ulTempData; ++ UINT32 ulMask; ++ BOOL fResetRemainingDataFlag = FALSE; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ WriteBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Check all user parameters. */ ++ ++ /* Check if channel recording is enabled. */ ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) ++ return cOCT6100_ERR_DEBUG_CHANNEL_RECORDING_DISABLED; ++ ++ /* Check if a current debugging channel has been selected. */ ++ /* If not, the user has not yet called Oct6100DebugSelectChannel. */ ++ if ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex == cOCT6100_INVALID_INDEX ) ++ return cOCT6100_ERR_DEBUG_RECORD_NO_CHAN_SELECTED; ++ ++ /* Check that the user supplied a valid max bytes value. */ ++ if ( f_pGetData->ulMaxBytes == cOCT6100_INVALID_VALUE ) ++ return cOCT6100_ERR_DEBUG_GET_DATA_MAX_BYTES; ++ ++ /* Data buffer must be aligned on 1024 bytes. */ ++ if ( ( f_pGetData->ulMaxBytes % 1024 ) != 0 ) ++ return cOCT6100_ERR_DEBUG_GET_DATA_MAX_BYTES; ++ ++ /* Check that the user provided the required memory to transfer the information. */ ++ if ( f_pGetData->pbyData == NULL ) ++ return cOCT6100_ERR_DEBUG_GET_DATA_PTR_INVALID; ++ ++ /* Check dump type. */ ++ if ( ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_16S_LITE ) ++ && ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE ) ++ && ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_16S ) ++ && ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ++ return cOCT6100_ERR_DEBUG_GET_DATA_MODE; ++ ++ /* Check dump content. */ ++ if ( ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ && ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM ) ++ && ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM ) ++ && ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM ) ) ++ return cOCT6100_ERR_DEBUG_GET_DATA_CONTENT; ++ ++ /* Check if can accomodate the 120 seconds dump. */ ++ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ++ { ++ if ( pSharedInfo->DebugInfo.ulDebugEventSize != 0x100 ) ++ return cOCT6100_ERR_NOT_SUPPORTED_DEBUG_DATA_MODE_120S; ++ } ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, pSharedInfo->DebugInfo.usCurrentDebugChanIndex ) ++ ++ /* Lets go dump the requested data. */ ++ ++ usDebugEventReadPtr = 0; ++ ++ /* Check if this is the first time this function is called since the hot channel was set. */ ++ if ( pSharedInfo->DebugInfo.fDebugDataBeingDumped == FALSE ) ++ { ++ /* Check that the channel is not in POWER_DOWN. When the channel is in POWER_DOWN, */ ++ /* the debug events are not recorded correctly in external memory. */ ++ if ( pChanEntry->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN ) ++ return cOCT6100_ERR_DEBUG_CHANNEL_IN_POWER_DOWN; ++ ++ pSharedInfo->DebugInfo.fDebugDataBeingDumped = TRUE; ++ ++ /* Flag the hot channel that it must stop recording. The data is being transfered. */ ++ /* This also tells the remote client not to do anything right now. */ ++ ++ ReadBurstParams.ulReadAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; ++ ReadBurstParams.ulReadLength = 2; ++ ReadBurstParams.pusReadData = pSharedInfo->DebugInfo.ausHotChannelData; ++ ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteBurstParams.pusWriteData = ausWriteData; ++ WriteBurstParams.ulWriteAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; ++ WriteBurstParams.ulWriteLength = 2; ++ ++ WriteBurstParams.pusWriteData[ 0 ] = 0xFFFF; ++ WriteBurstParams.pusWriteData[ 1 ] = 0xFFFF; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( WriteBurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Get the maximum number of events this firmware supports from the TLVs. */ ++ pSharedInfo->DebugInfo.usMatrixCBMask = (UINT16)( pSharedInfo->DebugInfo.ulDebugEventSize & 0xFFFF ); ++ pSharedInfo->DebugInfo.usMatrixCBMask -= 1; ++ ++ /* Find out the chip log write pointer. */ ++ ++ /* Now get the current write pointer for matrix events. */ ++ ReadParams.pusReadData = &pSharedInfo->DebugInfo.usChipDebugEventWritePtr; ++ ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixWpBaseAddress + 2; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ReadParams.pusReadData = &usReadData; ++ ++ /* This write pointer might have wrapped, but we don't know for sure. */ ++ /* To be confident, the chip frame timestamp is read. */ ++ ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixTimestampBaseAddress; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulTimestamp = usReadData << 16; ++ ++ ReadParams.ulReadAddress += 2; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulTimestamp |= usReadData; ++ ++ ulTimestamp >>= 12; /* TDM time for 1 event (512 ms) */ ++ ++ /* There is a probability here (once very 6.2 days) that the timestamp is close */ ++ /* to 0, because it has wrapped. But still, we need a way to workaround the highly */ ++ /* occuring case of the chip just being opened. This will fix this problem. */ ++ if ( ulTimestamp < (UINT32)( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) ) ++ { ++ if ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr >= 2 ) ++ { ++ /* Must trash the first 2 events. The chip is not yet ready. */ ++ pSharedInfo->DebugInfo.usNumEvents = (UINT16)( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - 2 ); ++ } ++ else ++ { ++ pSharedInfo->DebugInfo.usNumEvents = 0x0; ++ } ++ } ++ else ++ { ++ pSharedInfo->DebugInfo.usNumEvents = (UINT16)( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ); ++ ++ /* Account for event being created right now while the chip is running. */ ++ /* The event at the write pointer will be discarded. */ ++ if ( pSharedInfo->DebugInfo.usNumEvents > 0 ) ++ pSharedInfo->DebugInfo.usNumEvents--; ++ } ++ ++ ++ /* If the user only requested the last 16 seconds, cap the number of events. */ ++ if ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ++ || f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S_LITE ) ++ { ++ /* x events to get the last 16 seconds. */ ++ if ( pSharedInfo->DebugInfo.usNumEvents > ( 16000 / ( pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize / 8 ) ) ) ++ pSharedInfo->DebugInfo.usNumEvents = (UINT16)( ( 16000 / ( pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize / 8 ) ) & 0xFFFF ); ++ } ++ ++ /* Make sure that all the events are pertaining to the current hot channel. */ ++ /* Calculate the event read pointer. */ ++ ulReadPointer = ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - pSharedInfo->DebugInfo.usNumEvents ) & pSharedInfo->DebugInfo.usMatrixCBMask ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; ++ ulReadPointer %= ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); ++ ++ /* Travel through the events and throw away the bad events. */ ++ usTempNumEvents = pSharedInfo->DebugInfo.usNumEvents; ++ pSharedInfo->DebugInfo.usNumEvents = 0; ++ for ( ulDebugEventIndex = 0; ulDebugEventIndex < usTempNumEvents; ulDebugEventIndex ++ ) ++ { ++ /* The HOT channel index for the event is stored at offset 0xF2 (word offset) */ ++ ++ ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixBaseAddress + ulReadPointer; ++ ReadParams.ulReadAddress += 0xF2 * sizeof(UINT16); ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the current debug index is the same as the one found in the event. */ ++ if ( usReadData != pSharedInfo->DebugInfo.usCurrentDebugChanIndex ) ++ pSharedInfo->DebugInfo.usNumEvents = 0; /* As soon as we hit another channel, we reset the number of valid events. */ ++ else ++ pSharedInfo->DebugInfo.usNumEvents++; ++ ++ /* Increment read pointer to get next event. */ ++ ulReadPointer = ( ulReadPointer + pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ) % ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); ++ } ++ ++ /* In heavy mode, the AF log pointer is retrieved. */ ++ if ( ( pSharedInfo->DebugInfo.usNumEvents >= 2 ) ++ && ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ) ++ { ++ /* The latest AF log write pointer is at the latest matrix event. */ ++ ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixBaseAddress + ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr & pSharedInfo->DebugInfo.usMatrixCBMask ) * 1024 ); ++ ++ /* To get the AF log write pointer, which is at offset pSharedInfo->ImageInfo.ulAfWritePtrByteOffset. */ ++ ReadParams.ulReadAddress += pSharedInfo->DebugInfo.ulAfWritePtrByteOffset; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pSharedInfo->DebugInfo.usAfLogWritePtr = usReadData; ++ ++ /* The AF event read pointer is the AF write pointer +4096 */ ++ /* This will make sure we do not get mixed up and fetch events that have */ ++ /* just been written, but we think are old. */ ++ ++ /* To get the exact AF log pointer, the API would have to wait 512 milliseconds to make */ ++ /* sure logging had stopped. This is not required since missing a few last events is not */ ++ /* important at this point (the user knows that valid data has already been recorded). */ ++ pSharedInfo->DebugInfo.usLastAfLogReadPtr = (UINT16)( ( pSharedInfo->DebugInfo.usAfLogWritePtr + 4096 ) & 0xFFFF ); ++ ++ /* Note that if the chip has just been booted, some of the AF events might not be initialized. */ ++ } ++ else ++ { ++ pSharedInfo->DebugInfo.usLastAfLogReadPtr = 0; ++ pSharedInfo->DebugInfo.usAfLogWritePtr = 0; ++ } ++ ++ /* To be aligned correctly for the bursts. */ ++ while ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) != 0 ) ++ pSharedInfo->DebugInfo.usLastAfLogReadPtr++; ++ ++ /* Remember the data mode for later checks. Also, the user cannot change this "mode". */ ++ pSharedInfo->DebugInfo.ulCurrentGetDataMode = f_pGetData->ulGetDataMode; ++ } ++ else ++ { ++ /* Check that the user did not change the current data mode. */ ++ if ( pSharedInfo->DebugInfo.ulCurrentGetDataMode != f_pGetData->ulGetDataMode ) ++ return cOCT6100_ERR_DEBUG_GET_DATA_MODE_CANNOT_CHANGE; ++ } ++ ++ /* Check if this is the first pass here. */ ++ if ( pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes == cOCT6100_INVALID_VALUE ) ++ { ++ /* Calculate how many bytes of data will be returned with respect to the selected data content. */ ++ ++ /* Check what content type the user requested. */ ++ if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ { ++ /* Remember first AF Event Read Pointer. */ ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr ) & 0xFF ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr >> 8 ) & 0xFF ); ++ ++ /* Remember the AF Event Write Pointer. */ ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usAfLogWritePtr ) & 0xFF ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usAfLogWritePtr >> 8 ) & 0xFF ); ++ ++ /* Remember law and hot channel */ ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( pChanEntry->TdmConfig.bySinPcmLaw | ( ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex >> 2 ) & 0xFE ) ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( pChanEntry->TdmConfig.bySoutPcmLaw ); ++ ++ /* Insert light or heavy mode in array. */ ++ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S_LITE ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE ) ) ++ { ++ f_pGetData->pbyData[ ulUserBufWriteIndex - 1 ] |= 0x80; ++ } ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( pChanEntry->TdmConfig.byRinPcmLaw | ( ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex & 0x1F ) << 3 ) ); ++ ++ /* Remember usNumEvents */ ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usNumEvents ) & 0xFF ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usNumEvents >> 8 ) & 0xFF ); ++ } ++ ++ /* Last indexes set to '0'! */ ++ pSharedInfo->DebugInfo.usLastDebugEventIndex = 0; ++ pSharedInfo->DebugInfo.ulLastPcmSampleIndex = 0; ++ ++ /* No tone event has been retrieved. */ ++ pSharedInfo->DebugInfo.usLastToneEventIndex = 0; ++ ++ /* The version strings have not yet been copied. */ ++ pSharedInfo->DebugInfo.fImageVersionCopied = FALSE; ++ pSharedInfo->DebugInfo.fApiVersionCopied = FALSE; ++ ++ /* Estimate the total size of the buffer that will be returned. */ ++ f_pGetData->ulTotalNumBytes = ulUserBufWriteIndex; ++ ++ /* If the full content is requested, add all the debug data. */ ++ if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ { ++ /* Add the matrix events. */ ++ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ++ { ++ /* Heavy mode! Grab everything! */ ++ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; ++ } ++ else ++ { ++ /* Lite mode! Only the most important stuff. */ ++ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize; ++ } ++ ++ /* Add the PCM samples. */ ++ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize * 3; ++ ++ /* If requested, add the AF log events. */ ++ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ++ { ++ f_pGetData->ulTotalNumBytes += (UINT32)( ( pSharedInfo->DebugInfo.usAfLogWritePtr - pSharedInfo->DebugInfo.usLastAfLogReadPtr ) & 0xFFFF ) * 16; ++ } ++ ++ /* Add the tone events strings. */ ++ f_pGetData->ulTotalNumBytes += cOCT6100_TLV_MAX_TONE_NAME_SIZE * pSharedInfo->ImageInfo.byNumToneDetectors; ++ ++ /* Add the image version string. */ ++ f_pGetData->ulTotalNumBytes += 512; ++ ++ /* Add the API version string. */ ++ f_pGetData->ulTotalNumBytes += sizeof( cOCT6100_API_VERSION ); ++ } ++ else /* if ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) */ ++ { ++ /* Add one PCM stream. */ ++ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize; ++ } ++ ++ /* Save this in the instance for further calls. */ ++ pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes = f_pGetData->ulTotalNumBytes; ++ ++ /* Calculate remaining bytes. All the bytes for now! */ ++ f_pGetData->ulRemainingNumBytes = f_pGetData->ulTotalNumBytes; ++ ++ /* Save this in the instance for the next calls. */ ++ pSharedInfo->DebugInfo.ulDebugDataRemainingNumBytes = f_pGetData->ulRemainingNumBytes; ++ } ++ else ++ { ++ f_pGetData->ulTotalNumBytes = pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes; ++ } ++ ++ /* Calculate the event read pointer. */ ++ ulReadPointer = ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - pSharedInfo->DebugInfo.usNumEvents ) & pSharedInfo->DebugInfo.usMatrixCBMask ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; ++ ++ ulReadPointer += pSharedInfo->DebugInfo.ulDebugChanStatsByteSize * pSharedInfo->DebugInfo.usLastDebugEventIndex; ++ ulReadPointer %= ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); ++ ++ if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ { ++ /* Copy the debug events in the user buffer. */ ++ for( ulDebugEventIndex = pSharedInfo->DebugInfo.usLastDebugEventIndex; ulDebugEventIndex < pSharedInfo->DebugInfo.usNumEvents; ulDebugEventIndex ++ ) ++ { ++ ReadBurstParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixBaseAddress + ulReadPointer; ++ ++ /* Check if we are in light or heavy mode. The burst size is not the same. */ ++ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ++ { ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ) ++ ulNumReads = pSharedInfo->DebugInfo.ulDebugChanStatsByteSize / 2; ++ else ++ break; ++ } ++ else ++ { ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize ) ++ ulNumReads = pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize / 2; ++ else ++ break; ++ } ++ ++ ulTempIndex = 0; ++ while ( ulNumReads != 0 ) ++ { ++ if ( ulNumReads >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ else ++ ReadBurstParams.ulReadLength = ulNumReads; ++ ++ /* Set pointer where to write data. */ ++ ReadBurstParams.pusReadData = pSharedInfo->MiscVars.ausSuperArray; ++ ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Copy data byte per byte to avoid endianess problems. */ ++ for ( ulCopyIndex = 0; ulCopyIndex < ReadBurstParams.ulReadLength; ulCopyIndex ++ ) ++ { ++ f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex + ( 2 * ulCopyIndex ) ] = (UINT8)( ReadBurstParams.pusReadData[ ulCopyIndex ] & 0xFF ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex + ( 2 * ulCopyIndex ) + 1 ] = (UINT8)( ( ReadBurstParams.pusReadData[ ulCopyIndex ] >> 8 ) & 0xFF ); ++ } ++ ++ /* Update indexes, temp variables, addresses. */ ++ ulNumReads -= ReadBurstParams.ulReadLength; ++ ulTempIndex += ReadBurstParams.ulReadLength * 2; ++ ReadBurstParams.ulReadAddress += ReadBurstParams.ulReadLength * 2; ++ } ++ ++ /* Store register 0x202 in the event structure. */ ++ f_pGetData->pbyData[ ulUserBufWriteIndex + 255 ] = (UINT8)( pSharedInfo->IntrptManage.usRegister202h & 0xFF ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex + 256 ] = (UINT8)( ( pSharedInfo->IntrptManage.usRegister202h >> 8 ) & 0xFF ); ++ ++ /* Increment index. */ ++ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ++ { ++ ulUserBufWriteIndex += pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; ++ } ++ else ++ { ++ ulUserBufWriteIndex += pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize; ++ } ++ ++ /* Increment read pointer to get next event. */ ++ ulReadPointer = ( ulReadPointer + pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ) % ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); ++ ++ /* Save in the instance that one of the events was dumped. */ ++ pSharedInfo->DebugInfo.usLastDebugEventIndex ++; ++ } ++ } ++ ++ /* Check if all debug events have been transfered. */ ++ if ( ( ulDebugEventIndex == pSharedInfo->DebugInfo.usNumEvents ) ++ || ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ) ++ { ++ /* Fetch all streams per event. */ ++ for ( ulPcmSampleIndex = pSharedInfo->DebugInfo.ulLastPcmSampleIndex; ulPcmSampleIndex < ( (UINT32)pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ); ulPcmSampleIndex ++ ) ++ { ++ /* Check if enough room for this sample. */ ++ if ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ { ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < 1 ) ++ break; ++ } ++ else /* if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) */ ++ { ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < 3 ) ++ break; ++ } ++ ++ /* Check if must retrieve data from external memory. */ ++ if ( ( ulPcmSampleIndex % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE * 2 ) ) == 0x0 ) ++ { ++ ulReadPointer = ( ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - pSharedInfo->DebugInfo.usNumEvents ) * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) & ( pSharedInfo->DebugInfo.usMatrixCBMask * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) ); ++ ulReadPointer += ( ulPcmSampleIndex / pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize; ++ ulReadPointer &= ( pSharedInfo->DebugInfo.usMatrixCBMask * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ); ++ ulReadPointer += ulPcmSampleIndex % pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize; ++ ++ /* Retrieve more data from external memory. */ ++ switch ( f_pGetData->ulGetDataContent ) ++ { ++ case cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM: ++ ulStreamIndexMin = 0; ++ ulStreamIndexMax = 1; ++ break; ++ case cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM: ++ ulStreamIndexMin = 1; ++ ulStreamIndexMax = 2; ++ break; ++ case cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM: ++ ulStreamIndexMin = 2; ++ ulStreamIndexMax = 3; ++ break; ++ case cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE: ++ default: ++ ulStreamIndexMin = 0; ++ ulStreamIndexMax = 3; ++ break; ++ } ++ ++ for ( ulStreamIndex = ulStreamIndexMin; ulStreamIndex < ulStreamIndexMax; ulStreamIndex ++ ) ++ { ++ ReadBurstParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase; ++ /* To get right channel information. */ ++ ReadBurstParams.ulReadAddress += ( ( pSharedInfo->DebugInfo.usRecordMemIndex + 2 ) * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->DebugInfo.ulAfEventCbByteSize; ++ /* To get correct stream. */ ++ ReadBurstParams.ulReadAddress += ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize * ulStreamIndex ); ++ /* PCM sample pointer in that stream. */ ++ ReadBurstParams.ulReadAddress += ulReadPointer; ++ ++ /* As much as we can for the burst. */ ++ ulTempIndex = 0; ++ ulNumReads = cOCT6100_INTERNAL_SUPER_ARRAY_SIZE; ++ while ( ulNumReads != 0 ) ++ { ++ if ( ulNumReads >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ else ++ ReadBurstParams.ulReadLength = ulNumReads; ++ ++ /* Set pointer where to write data. */ ++ if ( ulStreamIndex == 0 ) ++ ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray[ ulTempIndex ]; ++ else if ( ulStreamIndex == 1 ) ++ ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray1[ ulTempIndex ]; ++ else /* if ( ulStreamIndex == 2 ) */ ++ ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray2[ ulTempIndex ]; ++ ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update indexes, temp variables, addresses. */ ++ ulNumReads -= ReadBurstParams.ulReadLength; ++ ulTempIndex += ReadBurstParams.ulReadLength; ++ ReadBurstParams.ulReadAddress += ReadBurstParams.ulReadLength * 2; ++ } ++ } ++ } ++ ++ /* We now have the stream data for all streams for 1 event. */ ++ /* Return what we can to the user. */ ++ if ( ( ulPcmSampleIndex % 2 ) == 0 ) ++ { ++ if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM ) ) ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 8 ) & 0xFF ); ++ ++ if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM ) ) ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray1[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 8 ) & 0xFF ); ++ ++ if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM ) ) ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray2[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 8 ) & 0xFF ); ++ } ++ else /* if ( ulPcmSampleIndex % 2 == 1 ) */ ++ { ++ if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM ) ) ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 0 ) & 0xFF ); ++ ++ if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM ) ) ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray1[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 0 ) & 0xFF ); ++ ++ if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM ) ) ++ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray2[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 0 ) & 0xFF ); ++ } ++ ++ pSharedInfo->DebugInfo.ulLastPcmSampleIndex++; ++ } ++ ++ /* Check if we are done dumping the PCM samples! */ ++ if ( pSharedInfo->DebugInfo.ulLastPcmSampleIndex == ( (UINT32)pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) ) ++ { ++ if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ++ { ++ ++ /* Go for the AF events. The AF events are only copied in heavy mode. */ ++ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) ++ || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) ++ { ++ while ( pSharedInfo->DebugInfo.usLastAfLogReadPtr != pSharedInfo->DebugInfo.usAfLogWritePtr ) ++ { ++ /* Check if enough room for an event. */ ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < 16 ) ++ break; ++ ++ /* Check if must fill our buffer. */ ++ if ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) == 0x0 ) ++ { ++ ulNumAfEvents = ( pSharedInfo->DebugInfo.usAfLogWritePtr - pSharedInfo->DebugInfo.usLastAfLogReadPtr ) & 0xFFFF; ++ ++ /* Check for the size of the available buffer. */ ++ if ( ulNumAfEvents > ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) ++ ulNumAfEvents = ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ); ++ ++ /* Start at channel main base address. */ ++ ReadBurstParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase; ++ /* To get right channel information. */ ++ ReadBurstParams.ulReadAddress += ( ( pSharedInfo->DebugInfo.usRecordMemIndex + 2 ) * pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ /* To get the right AF log. */ ++ ReadBurstParams.ulReadAddress += ( pSharedInfo->DebugInfo.usLastAfLogReadPtr * 16 ); ++ ++ ulTempIndex = 0; ++ ulNumReads = ulNumAfEvents * 8; ++ ++ while ( ulNumReads != 0 ) ++ { ++ if ( ulNumReads >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ else ++ ReadBurstParams.ulReadLength = ulNumReads; ++ ++ /* Set pointer where to write data. */ ++ ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray[ ulTempIndex ]; ++ ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update indexes, temp variables, addresses. */ ++ ulNumReads -= ReadBurstParams.ulReadLength; ++ ulTempIndex += ReadBurstParams.ulReadLength; ++ ReadBurstParams.ulReadAddress += ReadBurstParams.ulReadLength * 2; ++ } ++ } ++ ++ /* Copy data byte per byte to avoid endianess problems. */ ++ for ( ulCopyIndex = 0; ulCopyIndex < 8; ulCopyIndex ++ ) ++ { ++ f_pGetData->pbyData[ ulUserBufWriteIndex + ( 2 * ulCopyIndex ) ] = (UINT8)( pSharedInfo->MiscVars.ausSuperArray[ ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) * 8 ) + ulCopyIndex ] & 0xFF ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex + ( 2 * ulCopyIndex ) + 1 ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) * 8 ) + ulCopyIndex ] >> 8 ) & 0xFF ); ++ } ++ ++ ulUserBufWriteIndex += 16; ++ ++ /* Increment AF log read ptr. */ ++ pSharedInfo->DebugInfo.usLastAfLogReadPtr = (UINT16)(( pSharedInfo->DebugInfo.usLastAfLogReadPtr + 1 ) & 0xFFFF ); ++ } ++ } ++ ++ /* Check if we are done with the AF events. */ ++ if ( pSharedInfo->DebugInfo.usLastAfLogReadPtr == pSharedInfo->DebugInfo.usAfLogWritePtr ) ++ { ++ /* Insert the tone event information. */ ++ for ( ulToneEventIndex = pSharedInfo->DebugInfo.usLastToneEventIndex; ulToneEventIndex < pSharedInfo->ImageInfo.byNumToneDetectors; ulToneEventIndex++ ) ++ { ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < cOCT6100_TLV_MAX_TONE_NAME_SIZE ) ++ break; ++ ++ Oct6100UserMemCopy( &f_pGetData->pbyData[ ulUserBufWriteIndex ], pSharedInfo->ImageInfo.aToneInfo[ ulToneEventIndex ].aszToneName, cOCT6100_TLV_MAX_TONE_NAME_SIZE ); ++ ++ ulUserBufWriteIndex += cOCT6100_TLV_MAX_TONE_NAME_SIZE; ++ ++ pSharedInfo->DebugInfo.usLastToneEventIndex++; ++ } ++ ++ /* If all the tone information has been copied. */ ++ if ( ulToneEventIndex == pSharedInfo->ImageInfo.byNumToneDetectors ) ++ { ++ /* Copy the image version. */ ++ if ( pSharedInfo->DebugInfo.fImageVersionCopied == FALSE ) ++ { ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= 512 ) ++ { ++ Oct6100UserMemCopy( &f_pGetData->pbyData[ ulUserBufWriteIndex ], pSharedInfo->ImageInfo.szVersionNumber, 512 ); ++ ++ /* Get PLL jitter count from external memory. */ ++ if ( pSharedInfo->DebugInfo.fPouchCounter == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byFieldSize; ++ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ &ulTempData ); ++ ++ /* Create the mask to retrieve the appropriate value. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ /* Mask data. */ ++ ulTempData &= ulMask; ++ /* Move to right position. */ ++ ulTempData = ulTempData >> ulFeatureBitOffset; ++ ++ f_pGetData->pbyData[ ulUserBufWriteIndex + 510 ] = (UINT8)( ( ulTempData >> 8 ) & 0xFF ); ++ f_pGetData->pbyData[ ulUserBufWriteIndex + 511 ] = (UINT8)( ( ulTempData >> 0 ) & 0xFF ); ++ } ++ ++ /* Add "ISR is not called" bit. */ ++ if ( pSharedInfo->IntrptManage.fIsrCalled == FALSE ) ++ { ++ f_pGetData->pbyData[ ulUserBufWriteIndex + 510 ] |= 0x80; ++ } ++ ++ ulUserBufWriteIndex += 512; ++ ++ /* The version has been copied. */ ++ pSharedInfo->DebugInfo.fImageVersionCopied = TRUE; ++ } ++ } ++ ++ /* If the image version has been copied, proceed with the API version. */ ++ if ( pSharedInfo->DebugInfo.fImageVersionCopied == TRUE ) ++ { ++ if ( pSharedInfo->DebugInfo.fApiVersionCopied == FALSE ) ++ { ++ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= sizeof(cOCT6100_API_VERSION) ) ++ { ++ Oct6100UserMemCopy( &f_pGetData->pbyData[ ulUserBufWriteIndex ], cOCT6100_API_VERSION, sizeof(cOCT6100_API_VERSION) ); ++ ulUserBufWriteIndex += sizeof(cOCT6100_API_VERSION); ++ ++ /* The API version has been copied. */ ++ pSharedInfo->DebugInfo.fApiVersionCopied = TRUE; ++ } ++ } ++ } ++ } ++ ++ /* Check if we are done! */ ++ if ( pSharedInfo->DebugInfo.fApiVersionCopied == TRUE ) ++ { ++ /* Done dumping. */ ++ ++ /* Reset data being dumpped flag. */ ++ pSharedInfo->DebugInfo.fDebugDataBeingDumped = FALSE; ++ ++ /* Reset data recording in the chip. */ ++ WriteBurstParams.ulWriteAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; ++ WriteBurstParams.ulWriteLength = 2; ++ WriteBurstParams.pusWriteData = pSharedInfo->DebugInfo.ausHotChannelData; ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( WriteBurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ fResetRemainingDataFlag = TRUE; ++ } ++ } ++ } ++ else /* if ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) */ ++ { ++ fResetRemainingDataFlag = TRUE; ++ } ++ } ++ } ++ ++ /* Return number of valid bytes in buffer to user. */ ++ f_pGetData->ulValidNumBytes = ulUserBufWriteIndex; ++ ++ /* Update remaining bytes. */ ++ pSharedInfo->DebugInfo.ulDebugDataRemainingNumBytes -= ulUserBufWriteIndex; ++ ++ /* Return remaining bytes. */ ++ f_pGetData->ulRemainingNumBytes = pSharedInfo->DebugInfo.ulDebugDataRemainingNumBytes; ++ ++ /* Return total number of bytes. */ ++ f_pGetData->ulTotalNumBytes = pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes; ++ ++ /* Check if we are done dump the requested content. */ ++ if ( fResetRemainingDataFlag == TRUE ) ++ pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes = cOCT6100_INVALID_VALUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_events.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_events.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_events.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_events.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1379 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_events.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to retrieve tone and playout events. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 81 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_events_inst.h" ++#include "oct6100api/oct6100_tone_detection_inst.h" ++#include "oct6100api/oct6100_playout_buf_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_events_pub.h" ++#include "oct6100api/oct6100_tone_detection_pub.h" ++#include "oct6100api/oct6100_playout_buf_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_events_priv.h" ++#include "oct6100_tone_detection_priv.h" ++#include "oct6100_playout_buf_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100EventGetTone ++ ++Description: Retreives an array of tone events. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pEventGetTone Pointer to structure used to store the Tone events. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100EventGetToneDef ++UINT32 Oct6100EventGetToneDef( ++ tPOCT6100_EVENT_GET_TONE f_pEventGetTone ) ++{ ++ f_pEventGetTone->pToneEvent = NULL; ++ f_pEventGetTone->ulMaxToneEvent = 1; ++ f_pEventGetTone->ulNumValidToneEvent = cOCT6100_INVALID_VALUE; ++ f_pEventGetTone->fMoreEvents = FALSE; ++ f_pEventGetTone->fResetBufs = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100EventGetTone ++UINT32 Oct6100EventGetTone( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_EVENT_GET_TONE f_pEventGetTone ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100EventGetToneSer( f_pApiInstance, f_pEventGetTone ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutGetEvent ++ ++Description: Retrieves an array of playout stop events. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pBufPlayoutGetEvent Pointer to structure used to store the playout events. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutGetEventDef ++UINT32 Oct6100BufferPlayoutGetEventDef( ++ tPOCT6100_BUFFER_PLAYOUT_GET_EVENT f_pBufPlayoutGetEvent ) ++{ ++ f_pBufPlayoutGetEvent->pBufferPlayoutEvent = NULL; ++ f_pBufPlayoutGetEvent->ulMaxEvent = 1; ++ f_pBufPlayoutGetEvent->ulNumValidEvent = cOCT6100_INVALID_VALUE; ++ f_pBufPlayoutGetEvent->fMoreEvents = FALSE; ++ f_pBufPlayoutGetEvent->fResetBufs = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100BufferPlayoutGetEvent ++UINT32 Oct6100BufferPlayoutGetEvent( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_PLAYOUT_GET_EVENT f_pBufPlayoutGetEvent ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferPlayoutGetEventSer( f_pApiInstance, f_pBufPlayoutGetEvent ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetEventsSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of the tone events and playout events ++ software buffers. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetEventsSwSizes ++UINT32 Oct6100ApiGetEventsSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ ++ { ++ UINT32 ulTempVar; ++ ++ /* Memory needed by soft tone event buffers. */ ++ ++ /* Add 1 to the circular buffer such that all user requested events can fit in the circular queue. */ ++ f_pInstSizes->ulSoftToneEventsBuffer = ( f_pOpenChip->ulSoftToneEventsBufSize + 1 ) * sizeof( tOCT6100_API_TONE_EVENT ); ++ ++ /* Round off the sizes of the soft buffers above. */ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulSoftToneEventsBuffer, ulTempVar ) ++ } ++ ++ { ++ UINT32 ulTempVar; ++ ++ /* Memory needed by soft playout stop event buffers. */ ++ if ( f_pOpenChip->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE ) ++ { ++ f_pInstSizes->ulSoftBufPlayoutEventsBuffer = ( f_pOpenChip->ulSoftBufferPlayoutEventsBufSize + 1 ) * sizeof( tOCT6100_API_BUFFER_PLAYOUT_EVENT ); ++ ++ /* Round off the sizes of the soft buffers above. */ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulSoftBufPlayoutEventsBuffer, ulTempVar ) ++ } ++ else /* if ( f_pInstSizes->ulSoftBufferPlayoutEventsBufSize == cOCT6100_INVALID_VALUE ) */ ++ { ++ f_pInstSizes->ulSoftBufPlayoutEventsBuffer = 0; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100EventGetToneSer ++ ++Description: Retreives an array of tone event from the software event buffer. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pEventGetTone Pointer to structure which will contain the retreived ++ events. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100EventGetToneSer ++UINT32 Oct6100EventGetToneSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_EVENT_GET_TONE f_pEventGetTone ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_TONE_EVENT pSoftEvent; ++ UINT32 ulSoftReadPnt; ++ UINT32 ulSoftWritePnt; ++ UINT32 ulSoftBufSize; ++ UINT32 ulNumEventsReturned; ++ UINT32 ulResult; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the parameters given by the user. */ ++ if ( f_pEventGetTone->fResetBufs != TRUE && ++ f_pEventGetTone->fResetBufs != FALSE ) ++ return cOCT6100_ERR_EVENTS_GET_TONE_RESET_BUFS; ++ ++ /* Check max tones. */ ++ if ( f_pEventGetTone->ulMaxToneEvent > pSharedInfo->ChipConfig.ulSoftToneEventsBufSize ) ++ return cOCT6100_ERR_EVENTS_MAX_TONES; ++ ++ if ( f_pEventGetTone->fResetBufs == FALSE ) ++ { ++ /* Check if the events need to be fetched from the chip buffer. */ ++ ulSoftReadPnt = pSharedInfo->SoftBufs.ulToneEventBufferReadPtr; ++ ulSoftWritePnt = pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ++ ++ if ( ulSoftReadPnt == ulSoftWritePnt ) ++ { ++ ulResult = Oct6100ApiTransferToneEvents( f_pApiInstance, f_pEventGetTone->fResetBufs ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If there are no events in the soft buffer then there are none in the chip */ ++ /* either, so return the empty case. Else, return the events in the buffer. */ ++ ulSoftReadPnt = pSharedInfo->SoftBufs.ulToneEventBufferReadPtr; ++ ulSoftWritePnt = pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ++ ulSoftBufSize = pSharedInfo->SoftBufs.ulToneEventBufferSize; ++ ++ if ( ulSoftReadPnt != ulSoftWritePnt ) ++ { ++ ulNumEventsReturned = 0; ++ ++ while( (ulSoftReadPnt != ulSoftWritePnt) && ( ulNumEventsReturned != f_pEventGetTone->ulMaxToneEvent) ) ++ { ++ /* Get a pointer to the first event in the buffer. */ ++ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += ulSoftReadPnt; ++ ++ f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulChannelHndl = pSoftEvent->ulChannelHandle; ++ f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulUserChanId = pSoftEvent->ulUserChanId; ++ f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulTimestamp = pSoftEvent->ulTimestamp; ++ f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulEventType = pSoftEvent->ulEventType; ++ f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulToneDetected = pSoftEvent->ulToneDetected; ++ f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulExtToneDetectionPort = pSoftEvent->ulExtToneDetectionPort; ++ ++ /* Update the pointers of the soft buffer. */ ++ ulSoftReadPnt++; ++ if ( ulSoftReadPnt == ulSoftBufSize ) ++ ulSoftReadPnt = 0; ++ ++ ulNumEventsReturned++; ++ } ++ ++ pSharedInfo->SoftBufs.ulToneEventBufferReadPtr = ulSoftReadPnt; ++ ++ /* Detemine if there are more events pending in the soft buffer. */ ++ if ( ulSoftReadPnt != ulSoftWritePnt ) ++ f_pEventGetTone->fMoreEvents = TRUE; ++ else /* ( ulSoftReadPnt == ulSoftWritePnt ) */ ++ { ++ f_pEventGetTone->fMoreEvents = FALSE; ++ ++ /* Remember this state in the interrupt manager. */ ++ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; ++ } ++ ++ f_pEventGetTone->ulNumValidToneEvent = ulNumEventsReturned; ++ } ++ else ++ { ++ /* No valid tone.*/ ++ f_pEventGetTone->ulNumValidToneEvent = 0; ++ f_pEventGetTone->fMoreEvents = FALSE; ++ ++ /* Remember this state in the interrupt manager. */ ++ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; ++ ++ return cOCT6100_ERR_EVENTS_TONE_BUF_EMPTY; ++ } ++ } ++ else /* ( f_pEventGetTone->fResetBufs == TRUE ) */ ++ { ++ /* Empty the hardware buffer. */ ++ ulResult = Oct6100ApiTransferToneEvents( f_pApiInstance, f_pEventGetTone->fResetBufs ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* If the buffers are to be reset then update the pointers and full flag. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferReadPtr = 0; ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; ++ ++ f_pEventGetTone->fMoreEvents = FALSE; ++ f_pEventGetTone->ulNumValidToneEvent = 0; ++ ++ /* Remember this state in the interrupt manager. */ ++ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiTransferToneEvents ++ ++Description: Transfers all tone events from the PGSP event out chip buffer ++ to the soft buffer. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulResetBuf Reset flag. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiTransferToneEvents ++UINT32 Oct6100ApiTransferToneEvents( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulResetBuf ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_TONE_EVENT pSoftEvent; ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_READ_BURST_PARAMS BurstParams; ++ UINT32 ulChipBufFill; ++ UINT32 ulChipWritePtr = 0; ++ UINT32 ulChipReadPtr = 0; ++ ++ UINT32 usChannelIndex; ++ UINT32 ulBaseTimestamp; ++ UINT32 ulToneCnt; ++ UINT32 ulNumWordsToRead; ++ UINT32 ulEventCode; ++ ++ UINT32 ulResult; ++ UINT32 i, j; ++ UINT16 usReadData; ++ UINT16 ausReadData[ cOCT6100_NUM_WORDS_PER_TONE_EVENT ]; ++ ++ UINT32 ulExtToneDetectionPort; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* If the buffer is to be reset then clear the overflow flag. */ ++ if ( f_ulResetBuf == TRUE ) ++ { ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt = 0; ++ } ++ ++ /* Set some parameters of read struct. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Get the current read pointer of the chip buffer. */ ++ ReadParams.ulReadAddress = cOCT6100_TONE_EVENT_READ_PTR_REG; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulChipReadPtr = usReadData; ++ ++ /* Now get the current write pointer. */ ++ ReadParams.ulReadAddress = cOCT6100_TONE_EVENT_WRITE_PTR_REG; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulChipWritePtr = usReadData; ++ ++ ulChipBufFill = (( ulChipWritePtr - ulChipReadPtr ) & ( cOCT6100_NUM_PGSP_EVENT_OUT - 1 )); ++ ++ /* Set some parameters of write structs. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Read in the tone event one at a time. */ ++ for ( i = 0; i < ulChipBufFill; i++ ) ++ { ++ /* Skip the event processing if the buffer is to be reset. */ ++ if ( f_ulResetBuf == TRUE ) ++ { ++ /* Update the control variables of the buffer. */ ++ ulChipReadPtr++; ++ if ( cOCT6100_NUM_PGSP_EVENT_OUT == ulChipReadPtr ) ++ ulChipReadPtr = 0; ++ } ++ else ++ { ++ /* Read in the event only if there's enough room in the soft buffer, and */ ++ /* the chip buffer is NOT to be reset. */ ++ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ++ ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) ++ { ++ BurstParams.ulReadAddress = cOCT6100_PGSP_EVENT_OUT_BASE + ( ulChipReadPtr * cOCT6100_PGSP_TONE_EVENT_SIZE ); ++ BurstParams.pusReadData = ausReadData; ++ ++ ulNumWordsToRead = cOCT6100_PGSP_TONE_EVENT_SIZE / 2; ++ ++ while ( ulNumWordsToRead > 0 ) ++ { ++ if ( ulNumWordsToRead > pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ { ++ BurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ } ++ else ++ { ++ BurstParams.ulReadLength = ulNumWordsToRead; ++ } ++ ++ mOCT6100_DRIVER_READ_BURST_API( BurstParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ BurstParams.pusReadData += BurstParams.ulReadLength; ++ BurstParams.ulReadAddress += BurstParams.ulReadLength * 2; ++ ++ ulNumWordsToRead -= BurstParams.ulReadLength; ++ } ++ ++ /* Verify if the event is valid. */ ++ if ( ( ausReadData[ 0 ] & cOCT6100_VALID_TONE_EVENT ) == 0x0 ) ++ return cOCT6100_ERR_FATAL_2D; ++ ++ /* First extract the channel number of the tone event. */ ++ usChannelIndex = ausReadData[ 1 ] & 0x3FF; ++ ++ /* Now the timestamp. */ ++ ulBaseTimestamp = ausReadData[ 2 ] << 16; ++ ulBaseTimestamp |= ausReadData[ 3 ]; ++ ++ /* This timestamp is 256 in adwance, must remove 256 frames. */ ++ ulBaseTimestamp -= 256; ++ ++ /* Fetch the channel stucture to validate which event can be reported. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, usChannelIndex ); ++ ++ if ( pEchoChannel->fReserved != TRUE ) ++ { ++ /* Update the control variables of the buffer. */ ++ ulChipReadPtr++; ++ if ( ulChipReadPtr == cOCT6100_NUM_PGSP_EVENT_OUT ) ++ ulChipReadPtr = 0; ++ ++ /* This channel has been closed since the generation of the event. */ ++ continue; ++ } ++ ++ /* Extract the extended tone detection port if available. */ ++ if ( pEchoChannel->ulExtToneChanMode == cOCT6100_API_EXT_TONE_SIN_PORT_MODE ) ++ { ++ ulExtToneDetectionPort = cOCT6100_CHANNEL_PORT_SIN; ++ } ++ else if ( pEchoChannel->ulExtToneChanMode == cOCT6100_API_EXT_TONE_RIN_PORT_MODE ) ++ { ++ ulExtToneDetectionPort = cOCT6100_CHANNEL_PORT_RIN; ++ ++ /* Modify the channel index. */ ++ usChannelIndex = pEchoChannel->usExtToneChanIndex; ++ ++ /* Change the channel entry to the original one for statistical purposes. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, usChannelIndex ); ++ ++ } ++ else /* pEchoChannel->ulExtToneChanMode == cOCT6100_API_EXT_TONE_DISABLED */ ++ { ++ ulExtToneDetectionPort = cOCT6100_INVALID_VALUE; ++ } ++ ++ ulToneCnt = 0; ++ /* Verify all the possible events that might have been detected. */ ++ for ( j = 4; j < cOCT6100_NUM_WORDS_PER_TONE_EVENT; j++ ) ++ { ++ ulEventCode = ( ausReadData[ j ] >> 8 ) & 0x7; ++ ++ if ( ulEventCode != 0x0 ) ++ { ++ /* This tone generated an event, now check if event is masked for the channel. */ ++ if ((( pEchoChannel->aulToneConf[ ulToneCnt / 32 ] >> ( 31 - ( ulToneCnt % 32 ))) & 0x1) == 1 ) ++ { ++ BOOL f2100Tone; ++ ++ /* Check if it is a 2100 Tone STOP and if the user wants receive those events*/ ++ ulResult = Oct6100ApiIs2100Tone(f_pApiInstance, ++ pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID, ++ &f2100Tone); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( (f2100Tone == FALSE) || ++ ( (f2100Tone == TRUE) && (ulEventCode != 2) ) || ++ ( (f2100Tone == TRUE) && pSharedInfo->ChipConfig.fEnable2100StopEvent == TRUE ) ) ++ { ++ ++ /* If enough space. */ ++ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ++ ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) ++ { ++ /* The tone event is not masked, The API can create a soft tone event. */ ++ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ++ ++ /* Decode the event type. */ ++ switch( ulEventCode ) ++ { ++ case 1: ++ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; ++ break; ++ case 2: ++ pSoftEvent->ulEventType = cOCT6100_TONE_STOP; ++ break; ++ case 3: ++ /* This one is a little tricky. We first */ ++ /* generate the "PRESENT" event and then generate the "STOP" event. */ ++ ++ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; ++ pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; ++ pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; ++ pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; ++ /* We want the timestamp not to be equal to the "STOP" event, so we subtract one to the detector's value. */ ++ pSoftEvent->ulTimestamp = ( ulBaseTimestamp + ((( ausReadData[ j ] >> 13 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ) ) - 1; ++ pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; ++ ++ /* Update the control variables of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; ++ if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; ++ ++ /* If enough space for the "STOP" event. */ ++ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ++ ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) ++ { ++ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ++ ++ pSoftEvent->ulEventType = cOCT6100_TONE_STOP; ++ } ++ else ++ { ++ /* Set the overflow flag of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; ++ ++ /* We continue in the loop in order to empty the hardware buffer. */ ++ continue; ++ } ++ ++ break; ++ case 4: ++ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; ++ break; ++ default: ++ pSharedInfo->ErrorStats.ulToneDetectorErrorCnt++; ++ /* do not process this packet*/ ++ continue; ++ } ++ ++ pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; ++ pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; ++ pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; ++ pSoftEvent->ulTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 13 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); ++ pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; ++ ++ /* Update the control variables of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; ++ if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; ++ ++ /* Set the interrupt manager such that the user knows that some tone events */ ++ /* are pending in the software Q. */ ++ pSharedInfo->IntrptManage.fToneEventsPending = TRUE; ++ } ++ else ++ { ++ /* Set the overflow flag of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; ++ ++ /* We continue in the loop in order to empty the hardware buffer. */ ++ } ++ } ++ } ++ else ++ { ++ BOOL fSSTone; ++ ++ ulResult = Oct6100ApiIsSSTone( ++ f_pApiInstance, ++ pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID, ++ &fSSTone ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( fSSTone == TRUE ) ++ { ++ /* Check if this is a "PRESENT" or "STOP" event */ ++ switch( ulEventCode ) ++ { ++ case 1: ++ /* This is a signaling system present event. Keep this in the instance memory. */ ++ pEchoChannel->ulLastSSToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; ++ pEchoChannel->ulLastSSToneTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 13 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); ++ break; ++ case 2: ++ /* This is the "STOP" event, invalidate the last value. The user does not want to know about this. */ ++ pEchoChannel->ulLastSSToneDetected = (PTR_TYPE)cOCT6100_INVALID_VALUE; ++ pEchoChannel->ulLastSSToneTimestamp = (PTR_TYPE)cOCT6100_INVALID_VALUE; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ } ++ ulToneCnt++; ++ ++ /* Check the other tone of this word. */ ++ ulEventCode = ausReadData[ j ] & 0x7; ++ ++ if ( ulEventCode != 0x0 ) ++ { ++ if ((( pEchoChannel->aulToneConf[ ulToneCnt / 32 ] >> ( 31 - ( ulToneCnt % 32 ))) & 0x1) == 1 ) ++ { ++ BOOL f2100Tone; ++ ++ /* Check if it is a 2100 Tone STOP and if the user wants receive those events*/ ++ ulResult = Oct6100ApiIs2100Tone(f_pApiInstance, ++ pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID, ++ &f2100Tone); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( (f2100Tone == FALSE) || ++ ( (f2100Tone == TRUE) && (ulEventCode != 2) ) || ++ ( (f2100Tone == TRUE) && pSharedInfo->ChipConfig.fEnable2100StopEvent == TRUE ) ) ++ { ++ ++ /* If enough space. */ ++ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ++ ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) ++ { ++ /* The tone event is not masked, The API can create a soft tone event. */ ++ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ++ ++ /* Decode the event type. */ ++ switch( ulEventCode ) ++ { ++ case 1: ++ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; ++ break; ++ case 2: ++ pSoftEvent->ulEventType = cOCT6100_TONE_STOP; ++ break; ++ case 3: ++ /* This one is a little tricky. We first */ ++ /* generate the "PRESENT" event and then generate the "STOP" event. */ ++ ++ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; ++ pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; ++ pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; ++ pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; ++ /* We want the timestamp not to be equal to the "STOP" event, so we subtract one to the detector's value. */ ++ pSoftEvent->ulTimestamp = ( ulBaseTimestamp + ((( ausReadData[ j ] >> 5 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ) ) - 1; ++ pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; ++ ++ /* Update the control variables of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; ++ if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; ++ ++ /* If enough space for the "STOP" event. */ ++ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ++ ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) ++ { ++ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ++ ++ pSoftEvent->ulEventType = cOCT6100_TONE_STOP; ++ } ++ else ++ { ++ /* Set the overflow flag of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; ++ ++ /* We continue in the loop in order to empty the hardware buffer. */ ++ continue; ++ } ++ ++ break; ++ case 4: ++ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; ++ break; ++ default: ++ pSharedInfo->ErrorStats.ulToneDetectorErrorCnt++; ++ /* Do not process this packet. */ ++ continue; ++ } ++ ++ pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; ++ pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; ++ pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; ++ pSoftEvent->ulTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 5 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); ++ pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; ++ ++ /* Update the control variables of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; ++ if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; ++ ++ /* Set the interrupt manager such that the user knows that some tone events */ ++ /* are pending in the software Q. */ ++ pSharedInfo->IntrptManage.fToneEventsPending = TRUE; ++ ++ } ++ else ++ { ++ /* Set the overflow flag of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; ++ ++ /* We continue in the loop in order to empty the hardware buffer. */ ++ } ++ } ++ } ++ else ++ { ++ BOOL fSSTone; ++ ++ ulResult = Oct6100ApiIsSSTone( ++ f_pApiInstance, ++ pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID, ++ &fSSTone ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( fSSTone == TRUE ) ++ { ++ /* Check if this is a "PRESENT" event. */ ++ switch ( ulEventCode ) ++ { ++ case 1: ++ /* This is a signaling system present event. Keep this in the instance memory. */ ++ pEchoChannel->ulLastSSToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; ++ pEchoChannel->ulLastSSToneTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 5 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); ++ break; ++ case 2: ++ /* This is the "STOP" event, invalidate the last value. The user does not want to know about this. */ ++ pEchoChannel->ulLastSSToneDetected = (PTR_TYPE)cOCT6100_INVALID_VALUE; ++ pEchoChannel->ulLastSSToneTimestamp = (PTR_TYPE)cOCT6100_INVALID_VALUE; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ } ++ ulToneCnt++; ++ } ++ } ++ else ++ { ++ /* Set the overflow flag of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; ++ ++ /* We continue in the loop in order to empty the hardware buffer. */ ++ } ++ ++ /* Update the control variables of the buffer. */ ++ ulChipReadPtr++; ++ if ( ulChipReadPtr == cOCT6100_NUM_PGSP_EVENT_OUT ) ++ ulChipReadPtr = 0; ++ } ++ } ++ ++ /* Write the value of the new Read pointer.*/ ++ WriteParams.ulWriteAddress = cOCT6100_TONE_EVENT_READ_PTR_REG; ++ WriteParams.usWriteData = (UINT16)( ulChipReadPtr ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutGetEventSer ++ ++Description: Retreives an array of buffer playout event from the software ++ event buffer. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pEventGetPlayoutStop Pointer to structure which will contain the retreived ++ events. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutGetEventSer ++UINT32 Oct6100BufferPlayoutGetEventSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_GET_EVENT f_pBufPlayoutGetEvent ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER_PLAYOUT_EVENT pSoftEvent; ++ UINT32 ulSoftReadPnt; ++ UINT32 ulSoftWritePnt; ++ UINT32 ulSoftBufSize; ++ UINT32 ulNumEventsReturned; ++ UINT32 ulResult; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the parameters past by the user. */ ++ if ( f_pBufPlayoutGetEvent->fResetBufs != TRUE && ++ f_pBufPlayoutGetEvent->fResetBufs != FALSE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_RESET; ++ ++ /* Check if software buffer has been allocated and thus enabled. */ ++ if ( pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize == 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_DISABLED; ++ ++ /* Checking max playout events. */ ++ if ( f_pBufPlayoutGetEvent->ulMaxEvent > pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_MAX_EVENT; ++ ++ if ( f_pBufPlayoutGetEvent->fResetBufs == FALSE ) ++ { ++ /* Check if events need to be fetched from the chip. */ ++ ulSoftReadPnt = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr; ++ ulSoftWritePnt = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr; ++ ++ if ( ulSoftReadPnt == ulSoftWritePnt ) ++ { ++ ulResult = Oct6100BufferPlayoutTransferEvents( f_pApiInstance, f_pBufPlayoutGetEvent->fResetBufs ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* If there are no events in the soft buffer then there are none in the chip */ ++ /* either, so return the empty case. Else, return the events in the buffer. */ ++ ulSoftReadPnt = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr; ++ ulSoftWritePnt = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr; ++ ulSoftBufSize = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize; ++ ++ if ( ulSoftReadPnt != ulSoftWritePnt ) ++ { ++ ulNumEventsReturned = 0; ++ ++ while( (ulSoftReadPnt != ulSoftWritePnt) && ( ulNumEventsReturned != f_pBufPlayoutGetEvent->ulMaxEvent) ) ++ { ++ /* Get a pointer to the first event in the buffer. */ ++ mOCT6100_GET_BUFFER_PLAYOUT_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += ulSoftReadPnt; ++ ++ f_pBufPlayoutGetEvent->pBufferPlayoutEvent[ ulNumEventsReturned ].ulChannelHndl = pSoftEvent->ulChannelHandle; ++ f_pBufPlayoutGetEvent->pBufferPlayoutEvent[ ulNumEventsReturned ].ulUserChanId = pSoftEvent->ulUserChanId; ++ f_pBufPlayoutGetEvent->pBufferPlayoutEvent[ ulNumEventsReturned ].ulChannelPort = pSoftEvent->ulChannelPort; ++ f_pBufPlayoutGetEvent->pBufferPlayoutEvent[ ulNumEventsReturned ].ulUserEventId = pSoftEvent->ulUserEventId; ++ f_pBufPlayoutGetEvent->pBufferPlayoutEvent[ ulNumEventsReturned ].ulEventType = pSoftEvent->ulEventType; ++ f_pBufPlayoutGetEvent->pBufferPlayoutEvent[ ulNumEventsReturned ].ulTimestamp = pSoftEvent->ulTimestamp; ++ ++ /* Update the pointers of the soft buffer. */ ++ ulSoftReadPnt++; ++ if ( ulSoftReadPnt == ulSoftBufSize ) ++ ulSoftReadPnt = 0; ++ ++ ulNumEventsReturned++; ++ } ++ ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr = ulSoftReadPnt; ++ ++ /* Detemine if there are more events pending in the soft buffer. */ ++ if ( ulSoftReadPnt != ulSoftWritePnt ) ++ f_pBufPlayoutGetEvent->fMoreEvents = TRUE; ++ else /* ( ulSoftReadPnt == ulSoftWritePnt ) */ ++ { ++ f_pBufPlayoutGetEvent->fMoreEvents = FALSE; ++ ++ /* Remember this state in the interrupt manager. */ ++ pSharedInfo->IntrptManage.fBufferPlayoutEventsPending = FALSE; ++ } ++ ++ f_pBufPlayoutGetEvent->ulNumValidEvent = ulNumEventsReturned; ++ } ++ else /* if ( ulSoftReadPnt == ulSoftWritePnt ) */ ++ { ++ /* No valid buffer playout events. */ ++ f_pBufPlayoutGetEvent->ulNumValidEvent = 0; ++ f_pBufPlayoutGetEvent->fMoreEvents = FALSE; ++ ++ /* Remember this state in the interrupt manager. */ ++ pSharedInfo->IntrptManage.fBufferPlayoutEventsPending = FALSE; ++ ++ return cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_BUF_EMPTY; ++ } ++ } ++ else /* ( f_pEventGetPlayoutStop->fResetBufs == TRUE ) */ ++ { ++ /* Check with the hardware first. */ ++ ulResult = Oct6100BufferPlayoutTransferEvents( f_pApiInstance, f_pBufPlayoutGetEvent->fResetBufs ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* If the buffers are to be reset, then update the pointers and full flag. */ ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr = 0; ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr = 0; ++ ++ f_pBufPlayoutGetEvent->fMoreEvents = FALSE; ++ f_pBufPlayoutGetEvent->ulNumValidEvent = 0; ++ ++ /* Remember this state in the interrupt manager. */ ++ pSharedInfo->IntrptManage.fBufferPlayoutEventsPending = FALSE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutTransferEvents ++ ++Description: Check all channels that are currently playing a buffer and ++ generate an event if a buffer has stopped playing. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulResetBuf Reset flag. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutTransferEvents ++UINT32 Oct6100BufferPlayoutTransferEvents( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulResetBuf ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ ++ UINT32 ulChannelIndex; ++ UINT32 ulResult; ++ UINT32 ulLastBufPlayoutEventBufferOverflowCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* If the buffer is to be reset then clear the overflow flag. */ ++ if ( f_ulResetBuf == TRUE ) ++ { ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt = 0; ++ /* We are done for now. */ ++ /* No need to check for new events since the user requested to empty the soft buffer. */ ++ return cOCT6100_ERR_OK; ++ } ++ ++ /* Check if buffer playout has been activated on some ports. */ ++ if ( pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts == 0 ) ++ { ++ /* Buffer playout has not been activated on any channel, */ ++ /* let's not waste time here. */ ++ return cOCT6100_ERR_OK; ++ } ++ ++ /* Save the current overflow count. We want to know if an overflow occured to get out of the loop. */ ++ ulLastBufPlayoutEventBufferOverflowCnt = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt; ++ ++ /* Search through the list of API channel entry for the ones that need playout event checking. */ ++ for ( ulChannelIndex = 0; ulChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; ulChannelIndex++ ) ++ { ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, ulChannelIndex ); ++ ++ /* Check if buffer playout is active on this channel, using the optimization flag. */ ++ /* This flag is redundant of other flags used for playout, but will make the above loop */ ++ /* much faster. This is needed since this function is called very frequently on systems */ ++ /* which use buffer playout stop events. */ ++ if ( pEchoChannel->fBufPlayoutActive == TRUE ) ++ { ++ /* Read in the event only if there's enough room in the soft buffer. */ ++ if ( ulLastBufPlayoutEventBufferOverflowCnt == pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) ++ { ++ /* Check Rout buffer playout first. */ ++ if ( ( pEchoChannel->fRinBufPlayoutNotifyOnStop == TRUE ) ++ && ( pEchoChannel->fRinBufPlaying == TRUE ) ) ++ { ++ ulResult = Oct6100BufferPlayoutCheckForSpecificEvent( f_pApiInstance, ulChannelIndex, cOCT6100_CHANNEL_PORT_ROUT, TRUE, NULL ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else /* if ( ulLastBufPlayoutEventBufferOverflowCnt != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) */ ++ { ++ /* Get out of the loop, no more events can be inserted in the soft buffer. */ ++ break; ++ } ++ ++ /* An overflow might have been detected in the lower level function. */ ++ /* Check the overflow count once again to make sure there might be room for a next event. */ ++ if ( ulLastBufPlayoutEventBufferOverflowCnt == pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) ++ { ++ /* Check Sout buffer playout. */ ++ if ( ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == TRUE ) ++ && ( pEchoChannel->fSoutBufPlaying == TRUE ) ) ++ { ++ ulResult = Oct6100BufferPlayoutCheckForSpecificEvent( f_pApiInstance, ulChannelIndex, cOCT6100_CHANNEL_PORT_SOUT, TRUE, NULL ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ else /* if ( ulLastBufPlayoutEventBufferOverflowCnt != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) */ ++ { ++ /* Get out of the loop, no more events can be inserted in the soft buffer. */ ++ break; ++ } ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutCheckForSpecificEvent ++ ++Description: Check a specific channel/port for playout buffer events. ++ If asked to, save this event to the software event buffer. ++ Return a flag specifying whether the event was detected or not. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulChannelIndex Index of the channel to be checked. ++f_ulChannelPort Port of the channel to be checked. ++f_fSaveToSoftBuffer Save event to software buffer. ++f_pfEventDetected Whether or not an event was detected. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutCheckForSpecificEvent ++UINT32 Oct6100BufferPlayoutCheckForSpecificEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulChannelPort, ++ IN BOOL f_fSaveToSoftBuffer, ++ OUT PBOOL f_pfEventDetected ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER_PLAYOUT_EVENT pSoftEvent; ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_GET_TIME GetTimeParms; ++ ++ UINT32 ulResult; ++ UINT16 usReadData; ++ UINT32 ulReadPtrBytesOfst; ++ UINT32 ulReadPtrBitOfst; ++ UINT32 ulReadPtrFieldSize; ++ ++ UINT32 ulWritePtrBytesOfst; ++ UINT32 ulWritePtrBitOfst; ++ UINT32 ulWritePtrFieldSize; ++ ++ UINT32 ulPlayoutBaseAddress; ++ UINT32 ulTempData; ++ UINT32 ulReadPtr; ++ UINT32 ulMask; ++ UINT32 ulWritePtr; ++ UINT32 ulUserEventId; ++ UINT32 ulEventType; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Compare the read and write pointers for matching. If they matched, playout stopped. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); ++ ++ /* Set the playout feature base address. */ ++ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ if ( f_ulChannelPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ /* Check on the Rout port. */ ++ ulUserEventId = pEchoChannel->ulRinUserBufPlayoutEventId; ++ ulEventType = pEchoChannel->byRinPlayoutStopEventType; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4; ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset; ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize; ++ ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize; ++ } ++ else /* if ( f_ulChannelPort == cOCT6100_CHANNEL_PORT_SOUT ) */ ++ { ++ /* Check on the Sout port. */ ++ ulUserEventId = pEchoChannel->ulSoutUserBufPlayoutEventId; ++ ulEventType = pEchoChannel->bySoutPlayoutStopEventType; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4; ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset; ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize; ++ ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize; ++ } ++ ++ /* Retrieve the current write pointer. */ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulPlayoutBaseAddress + ulWritePtrBytesOfst, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); ++ ++ /* Store the write pointer.*/ ++ ulWritePtr = ( ulTempData & ulMask ) >> ulWritePtrBitOfst; ++ ++ /* Read the read pointer.*/ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ /* Must read in memory directly since this value is changed by hardware */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); ++ ++ /* Store the read pointer. */ ++ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; ++ ++ /* Playout has finished when the read pointer reaches the write pointer. */ ++ if ( ulReadPtr != ulWritePtr ) ++ { ++ /* Still playing -- do not generate an event. */ ++ if ( f_pfEventDetected != NULL ) ++ *f_pfEventDetected = FALSE; ++ } ++ else ++ { ++ /* Buffer stopped playing, generate an event here, if asked. */ ++ if ( ( f_fSaveToSoftBuffer == TRUE ) ++ && ( ( pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr ) ++ && ( ( pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize || pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr != 0 ) ) ++ { ++ /* The API can create a soft buffer playout event. */ ++ mOCT6100_GET_BUFFER_PLAYOUT_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr; ++ ++ pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_ulChannelIndex; ++ pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; ++ pSoftEvent->ulUserEventId = ulUserEventId; ++ pSoftEvent->ulChannelPort = f_ulChannelPort; ++ /* For now, only this type of event is available. */ ++ pSoftEvent->ulEventType = ulEventType; ++ ++ /* Generate millisecond timestamp. */ ++ GetTimeParms.pProcessContext = f_pApiInstance->pProcessContext; ++ ulResult = Oct6100UserGetTime( &GetTimeParms ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ pSoftEvent->ulTimestamp = ( GetTimeParms.aulWallTimeUs[ 0 ] / 1000 ); ++ pSoftEvent->ulTimestamp += ( GetTimeParms.aulWallTimeUs[ 1 ] ) * ( 0xFFFFFFFF / 1000 ); ++ ++ /* Update the control variables of the buffer. */ ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr++; ++ if ( pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr == pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize ) ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr = 0; ++ ++ /* Set the interrupt manager such that the user knows that some playout events */ ++ /* are pending in the software Q. */ ++ pSharedInfo->IntrptManage.fBufferPlayoutEventsPending = TRUE; ++ } ++ else if ( f_fSaveToSoftBuffer == TRUE ) ++ { ++ /* Set the overflow flag of the buffer. */ ++ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt++; ++ } ++ ++ /* Update the channel entry to set the playing flag to FALSE. */ ++ ++ /* Select the port of interest. */ ++ if ( f_ulChannelPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ /* Decrement the number of active buffer playout ports. */ ++ /* No need to check anything here, it's been done in the calling function. */ ++ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; ++ ++ pEchoChannel->fRinBufPlaying = FALSE; ++ pEchoChannel->fRinBufPlayoutNotifyOnStop = FALSE; ++ ++ /* Clear optimization flag if possible. */ ++ if ( ( pEchoChannel->fSoutBufPlaying == FALSE ) ++ && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == FALSE ) ) ++ { ++ /* Buffer playout is no more active on this channel. */ ++ pEchoChannel->fBufPlayoutActive = FALSE; ++ } ++ } ++ else /* f_ulChannelPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ /* Decrement the number of active buffer playout ports. */ ++ /* No need to check anything here, it's been done in the calling function. */ ++ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; ++ ++ pEchoChannel->fSoutBufPlaying = FALSE; ++ pEchoChannel->fSoutBufPlayoutNotifyOnStop = FALSE; ++ ++ /* Clear optimization flag if possible. */ ++ if ( ( pEchoChannel->fRinBufPlaying == FALSE ) ++ && ( pEchoChannel->fRinBufPlayoutNotifyOnStop == FALSE ) ) ++ { ++ /* Buffer playout is no more active on this channel. */ ++ pEchoChannel->fBufPlayoutActive = FALSE; ++ } ++ } ++ ++ /* Return that an event was detected. */ ++ if ( f_pfEventDetected != NULL ) ++ *f_pfEventDetected = TRUE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,2012 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_interrupts.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the API's interrupt service routine and all of its ++ sub-functions. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 81 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_events_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_channel_inst.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_events_priv.h" ++#include "oct6100_interrupts_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100InterruptConfigure ++ ++Description: Configure the operation of all possible interrupt sources. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntrptConfig Pointer to interrupt configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100InterruptConfigureDef ++UINT32 Oct6100InterruptConfigureDef( ++ tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig ) ++{ ++ f_pIntrptConfig->ulFatalGeneralConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pIntrptConfig->ulFatalMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ ++ f_pIntrptConfig->ulErrorMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pIntrptConfig->ulErrorOverflowToneEventsConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ f_pIntrptConfig->ulErrorH100Config = cOCT6100_INTERRUPT_NO_TIMEOUT; ++ ++ f_pIntrptConfig->ulFatalMemoryTimeout = 100; ++ ++ f_pIntrptConfig->ulErrorMemoryTimeout = 100; ++ f_pIntrptConfig->ulErrorOverflowToneEventsTimeout = 100; ++ f_pIntrptConfig->ulErrorH100Timeout = 100; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100InterruptConfigure ++UINT32 Oct6100InterruptConfigure( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulResult; ++ UINT32 ulFncRes; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Create serialization object for ISR. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulResult = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Call serialized sub-function. */ ++ ulFncRes = Oct6100InterruptConfigureSer( f_pApiInstance, f_pIntrptConfig, TRUE ); ++ /* Release serialization object. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulResult = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if an error occured in sub-function. */ ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100InterruptServiceRoutine ++ ++Description: The API's interrupt service routine. This function clears all ++ register ROLs which have generated an interrupt and report the ++ events in the user supplied structure. Also, the tone event ++ and/or playout event buffer will be emptied if valid events ++ are present. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntFlags Pointer to structure containing event flags returned ++ to user. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100InterruptServiceRoutineDef ++UINT32 Oct6100InterruptServiceRoutineDef( ++ tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) ++{ ++ f_pIntFlags->fFatalGeneral = FALSE; ++ f_pIntFlags->ulFatalGeneralFlags = 0x0; ++ f_pIntFlags->fFatalReadTimeout = FALSE; ++ ++ f_pIntFlags->fErrorRefreshTooLate = FALSE; ++ f_pIntFlags->fErrorPllJitter = FALSE; ++ ++ f_pIntFlags->fErrorOverflowToneEvents = FALSE; ++ ++ f_pIntFlags->fErrorH100OutOfSync = FALSE; ++ f_pIntFlags->fErrorH100ClkA = FALSE; ++ f_pIntFlags->fErrorH100ClkB = FALSE; ++ f_pIntFlags->fErrorH100FrameA = FALSE; ++ ++ f_pIntFlags->fToneEventsPending = FALSE; ++ f_pIntFlags->fBufferPlayoutEventsPending = FALSE; ++ ++ f_pIntFlags->fApiSynch = FALSE; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100InterruptServiceRoutine ++UINT32 Oct6100InterruptServiceRoutine( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulResult; ++ UINT32 ulFncRes; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize the serialization object for the ISR. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulResult = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized sub-function. */ ++ ulFncRes = Oct6100InterruptServiceRoutineSer( f_pApiInstance, f_pIntFlags ); ++ } ++ else ++ { ++ return ulResult; ++ } ++ ++ /* Release the serialization object. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulResult = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check for an error in the sub-function. */ ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiIsrSwInit ++ ++Description: Initializes portions of API instance associated to the API's ++ interrupt service routine. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiIsrSwInit ++UINT32 Oct6100ApiIsrSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the state of each interrupt group to disabled. The state will */ ++ /* be updated to the true configuration once the configure interrupts function is called. */ ++ pSharedInfo->IntrptManage.byFatalGeneralState = cOCT6100_INTRPT_DISABLED; ++ pSharedInfo->IntrptManage.byFatalMemoryState = cOCT6100_INTRPT_DISABLED; ++ pSharedInfo->IntrptManage.byErrorMemoryState = cOCT6100_INTRPT_DISABLED; ++ pSharedInfo->IntrptManage.byErrorH100State = cOCT6100_INTRPT_DISABLED; ++ pSharedInfo->IntrptManage.byErrorOverflowToneEventsState = cOCT6100_INTRPT_DISABLED; ++ ++ /* Indicate that the mclk interrupt is not active at the moment. */ ++ pSharedInfo->IntrptManage.fMclkIntrptActive = FALSE; ++ ++ /* Indicate that no buffer playout events are pending for the moment. */ ++ pSharedInfo->IntrptManage.fBufferPlayoutEventsPending = FALSE; ++ ++ /* Indicate that no tone events are pending for the moment. */ ++ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; ++ ++ /* The ISR has never been called. */ ++ pSharedInfo->IntrptManage.fIsrCalled = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiIsrHwInit ++ ++Description: Initializes the chip's interrupt registers. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntrptConfig Pointer to structure defining how the interrupts ++ should be configured. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiIsrHwInit ++UINT32 Oct6100ApiIsrHwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Set some parameters of write struct. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*==================================================================================*/ ++ /* Enable all the interrupts */ ++ ++ WriteParams.ulWriteAddress = 0x104; ++ WriteParams.usWriteData = 0x0001; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x204; ++ WriteParams.usWriteData = 0x1C05; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x304; ++ WriteParams.usWriteData = 0xFFFF; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x504; ++ WriteParams.usWriteData = 0x0002; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x704; ++ WriteParams.usWriteData = 0x0007; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==================================================================================*/ ++ ++ /* Calculate the number of mclk cycles in 1 ms. */ ++ f_pApiInstance->pSharedInfo->IntrptManage.ulNumMclkCyclesIn1Ms = f_pApiInstance->pSharedInfo->MiscVars.ulMclkFreq / 1000; ++ ++ /* Configure the interrupt registers as requested by the user. */ ++ ulResult = Oct6100InterruptConfigureSer( f_pApiInstance, f_pIntrptConfig, TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100InterruptConfigureSer ++ ++Description: Configure the operation of interrupt groups. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntrptConfig Pointer to interrupt configuration structure. ++f_fCheckParams Check parameter enable flag. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100InterruptConfigureSer ++UINT32 Oct6100InterruptConfigureSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig, ++ IN BOOL f_fCheckParams ) ++{ ++ tPOCT6100_API_INTRPT_CONFIG pIntrptConfig; ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ UINT32 ulResult; ++ ++ /* Check for errors. */ ++ if ( f_fCheckParams == TRUE ) ++ { ++ if ( f_pIntrptConfig->ulFatalGeneralConfig != cOCT6100_INTERRUPT_DISABLE && ++ f_pIntrptConfig->ulFatalGeneralConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ return cOCT6100_ERR_INTRPTS_FATAL_GENERAL_CONFIG; ++ if ( f_pIntrptConfig->ulFatalMemoryConfig != cOCT6100_INTERRUPT_DISABLE && ++ f_pIntrptConfig->ulFatalMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pIntrptConfig->ulFatalMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ return cOCT6100_ERR_INTRPTS_FATAL_MEMORY_CONFIG; ++ if ( f_pIntrptConfig->ulErrorMemoryConfig != cOCT6100_INTERRUPT_DISABLE && ++ f_pIntrptConfig->ulErrorMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pIntrptConfig->ulErrorMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ return cOCT6100_ERR_INTRPTS_DATA_ERR_MEMORY_CONFIG; ++ if ( f_pIntrptConfig->ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_DISABLE && ++ f_pIntrptConfig->ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pIntrptConfig->ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ return cOCT6100_ERR_INTRPTS_OVERFLOW_TONE_EVENTS_CONFIG; ++ if ( f_pIntrptConfig->ulErrorH100Config != cOCT6100_INTERRUPT_DISABLE && ++ f_pIntrptConfig->ulErrorH100Config != cOCT6100_INTERRUPT_TIMEOUT && ++ f_pIntrptConfig->ulErrorH100Config != cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ return cOCT6100_ERR_INTRPTS_H100_ERROR_CONFIG; ++ ++ if ( f_pIntrptConfig->ulFatalMemoryTimeout < 10 || ++ f_pIntrptConfig->ulFatalMemoryTimeout > 10000 ) ++ return cOCT6100_ERR_INTRPTS_FATAL_MEMORY_TIMEOUT; ++ if ( f_pIntrptConfig->ulErrorMemoryTimeout < 10 || ++ f_pIntrptConfig->ulErrorMemoryTimeout > 10000 ) ++ return cOCT6100_ERR_INTRPTS_DATA_ERR_MEMORY_TIMEOUT; ++ if ( f_pIntrptConfig->ulErrorOverflowToneEventsTimeout < 10 || ++ f_pIntrptConfig->ulErrorOverflowToneEventsTimeout > 10000 ) ++ return cOCT6100_ERR_INTRPTS_OVERFLOW_TONE_EVENTS_TIMEOUT; ++ if ( f_pIntrptConfig->ulErrorH100Timeout < 10 || ++ f_pIntrptConfig->ulErrorH100Timeout > 10000 ) ++ return cOCT6100_ERR_INTRPTS_H100_ERROR_TIMEOUT; ++ } ++ ++ /* Copy the configuration to the API instance. */ ++ pIntrptConfig = &f_pApiInstance->pSharedInfo->IntrptConfig; ++ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; ++ ++ pIntrptConfig->byFatalGeneralConfig = (UINT8)( f_pIntrptConfig->ulFatalGeneralConfig & 0xFF ); ++ pIntrptConfig->byFatalMemoryConfig = (UINT8)( f_pIntrptConfig->ulFatalMemoryConfig & 0xFF ); ++ pIntrptConfig->byErrorMemoryConfig = (UINT8)( f_pIntrptConfig->ulErrorMemoryConfig & 0xFF ); ++ pIntrptConfig->byErrorOverflowToneEventsConfig = (UINT8)( f_pIntrptConfig->ulErrorOverflowToneEventsConfig & 0xFF ); ++ pIntrptConfig->byErrorH100Config = (UINT8)( f_pIntrptConfig->ulErrorH100Config & 0xFF ); ++ ++ f_pIntrptConfig->ulFatalMemoryTimeout = ((f_pIntrptConfig->ulFatalMemoryTimeout + 9) / 10) * 10; ++ pIntrptConfig->ulFatalMemoryTimeoutMclk = f_pIntrptConfig->ulFatalMemoryTimeout * pIntrptManage->ulNumMclkCyclesIn1Ms; ++ ++ f_pIntrptConfig->ulErrorMemoryTimeout = ((f_pIntrptConfig->ulErrorMemoryTimeout + 9) / 10) * 10; ++ pIntrptConfig->ulErrorMemoryTimeoutMclk = f_pIntrptConfig->ulErrorMemoryTimeout * pIntrptManage->ulNumMclkCyclesIn1Ms; ++ ++ f_pIntrptConfig->ulErrorOverflowToneEventsTimeout = ((f_pIntrptConfig->ulErrorOverflowToneEventsTimeout + 9) / 10) * 10; ++ pIntrptConfig->ulErrorOverflowToneEventsTimeoutMclk = f_pIntrptConfig->ulErrorOverflowToneEventsTimeout * pIntrptManage->ulNumMclkCyclesIn1Ms; ++ ++ f_pIntrptConfig->ulErrorH100Timeout = ((f_pIntrptConfig->ulErrorH100Timeout + 9) / 10) * 10; ++ pIntrptConfig->ulErrorH100TimeoutMclk = f_pIntrptConfig->ulErrorH100Timeout * pIntrptManage->ulNumMclkCyclesIn1Ms; ++ ++ ++ /*Clear all interrupts that were already enabled*/ ++ ulResult = Oct6100ApiClearEnabledInterrupts( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Before writing the new configuration to the chip's registers, make sure that any */ ++ /* interrupts which are either disabled or have no timeout period are not on the */ ++ /* disabled interrupt list. */ ++ ++ /*==================================================================================*/ ++ if ( pIntrptConfig->byFatalGeneralConfig == cOCT6100_INTERRUPT_DISABLE ) ++ pIntrptManage->byFatalGeneralState = cOCT6100_INTRPT_DISABLED; ++ else /* pIntrptConfig->byFatalGeneralConfig == cOCT6100_INTERRUPT_NO_TIMEOUT */ ++ pIntrptManage->byFatalGeneralState = cOCT6100_INTRPT_ACTIVE; ++ ++ /*==================================================================================*/ ++ if ( pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_DISABLE ) ++ pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_DISABLED; ++ else if ( pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_ACTIVE; ++ else /* ( pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT ) */ ++ { ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_DISABLED ) ++ pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_ACTIVE; ++ } ++ ++ /*==================================================================================*/ ++ if ( pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_DISABLE ) ++ pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_DISABLED; ++ else if ( pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_ACTIVE; ++ else /* (pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT ) */ ++ { ++ if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_DISABLED ) ++ pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_ACTIVE; ++ } ++ ++ /*==================================================================================*/ ++ if ( pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_DISABLE ) ++ pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_DISABLED; ++ else if ( pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_ACTIVE; ++ else /* (pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_TIMEOUT ) */ ++ { ++ if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_DISABLED ) ++ pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_ACTIVE; ++ } ++ ++ /*==================================================================================*/ ++ if ( pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_DISABLE ) ++ pIntrptManage->byErrorH100State = cOCT6100_INTRPT_DISABLED; ++ else if ( pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_NO_TIMEOUT ) ++ pIntrptManage->byErrorH100State = cOCT6100_INTRPT_ACTIVE; ++ else /* (pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_TIMEOUT ) */ ++ { ++ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_DISABLED ) ++ pIntrptManage->byErrorH100State = cOCT6100_INTRPT_ACTIVE; ++ } ++ ++ ++ /* Write to the interrupt registers to update the state of each interrupt group. */ ++ ulResult = Oct6100ApiWriteIeRegs( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiClearEnabledInterrupts ++ ++Description: Disabled interruption are not reported but still available. This ++ function will clear the interrupts that were disabled and wish ++ to enable now. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntrptConfig Pointer to interrupt configuration structure. ++f_pIntrptManage Pointer to interrupt manager structure. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#if !SKIP_Oct6100ApiClearEnabledInterrupts ++UINT32 Oct6100ApiClearEnabledInterrupts( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tPOCT6100_API_INTRPT_CONFIG pIntrptConfig; ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Copy the configuration to the API instance. */ ++ pIntrptConfig = &f_pApiInstance->pSharedInfo->IntrptConfig; ++ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; ++ ++ if ( pIntrptConfig->byFatalGeneralConfig != cOCT6100_INTERRUPT_DISABLE && ++ pIntrptManage->byFatalGeneralState != cOCT6100_INTRPT_DISABLED ) ++ { ++ WriteParams.ulWriteAddress = 0x102; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_102H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x202; ++ WriteParams.usWriteData = 0x1800; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x502; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_502H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pIntrptConfig->byErrorMemoryConfig != cOCT6100_INTERRUPT_DISABLE && ++ pIntrptManage->byErrorMemoryState != cOCT6100_INTRPT_DISABLED ) ++ { ++ WriteParams.ulWriteAddress = 0x202; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_202H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pIntrptConfig->byErrorH100Config != cOCT6100_INTERRUPT_DISABLE && ++ pIntrptManage->byErrorH100State != cOCT6100_INTRPT_DISABLED ) ++ { ++ WriteParams.ulWriteAddress = 0x302; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_302H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ if ( pIntrptConfig->byErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_DISABLE && ++ pIntrptManage->byErrorOverflowToneEventsState != cOCT6100_INTRPT_DISABLED ) ++ { ++ WriteParams.ulWriteAddress = 0x702; ++ WriteParams.usWriteData = cOCT6100_INTRPT_MASK_REG_702H; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ ++ return cOCT6100_ERR_OK; ++ ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100InterruptServiceRoutineSer ++ ++Description: Serialized sub-function of API's interrupt service routine. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntFlags Pointer to structure containing event flags returned ++ to user. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100InterruptServiceRoutineSer ++UINT32 Oct6100InterruptServiceRoutineSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulRegister210h; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Must update the statistics. Set parameters in read and write structs. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Set all the flags to default values to make sure the variables are initialized. */ ++ f_pIntFlags->fFatalGeneral = FALSE; ++ f_pIntFlags->ulFatalGeneralFlags = 0x0; ++ f_pIntFlags->fFatalReadTimeout = FALSE; ++ ++ f_pIntFlags->fErrorRefreshTooLate = FALSE; ++ f_pIntFlags->fErrorPllJitter = FALSE; ++ ++ f_pIntFlags->fErrorH100OutOfSync = FALSE; ++ f_pIntFlags->fErrorH100ClkA = FALSE; ++ f_pIntFlags->fErrorH100ClkB = FALSE; ++ f_pIntFlags->fErrorH100FrameA = FALSE; ++ f_pIntFlags->fApiSynch = FALSE; ++ ++ f_pIntFlags->fErrorOverflowToneEvents = FALSE; ++ ++ /* Start by reading registers 210h to determine if any modules have flagged an interrupt. */ ++ ReadParams.ulReadAddress = 0x210; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ulRegister210h = usReadData; ++ ++ /* Update the extended mclk counter. */ ++ ulResult = Oct6100ApiReadChipMclkTime( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* If the mclk interrupt is active then check which interrupt timeout periods have expired. */ ++ ReadParams.ulReadAddress = 0x302; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ if ( (usReadData & 0x1) != 0 && pSharedInfo->IntrptManage.fMclkIntrptActive == TRUE ) ++ { ++ /* Update timeout periods. */ ++ ulResult = Oct6100ApiUpdateIntrptTimeouts( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ f_pIntFlags->fApiSynch = TRUE; ++ ++ /* Read registers 210h and 212h again to determine if any modules have flagged an interrupt. */ ++ ReadParams.ulReadAddress = 0x210; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ulRegister210h = usReadData; ++ } ++ ++ /* Read the interrupt registers to determine what interrupt conditions have occured. */ ++ ulResult = Oct6100ApiReadIntrptRegs( f_pApiInstance, f_pIntFlags, ulRegister210h ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Empty the tone buffer if any events are pending. */ ++ ulResult = Oct6100ApiTransferToneEvents( f_pApiInstance, FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the tone events pending flag. */ ++ f_pIntFlags->fToneEventsPending = pSharedInfo->IntrptManage.fToneEventsPending; ++ ++ /* Check for buffer playout events and insert in the software queue -- if activated. */ ++ if ( pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize != 0 ) ++ { ++ ulResult = Oct6100BufferPlayoutTransferEvents( f_pApiInstance, FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the buffer playout events pending flag. */ ++ f_pIntFlags->fBufferPlayoutEventsPending = pSharedInfo->IntrptManage.fBufferPlayoutEventsPending; ++ } ++ else ++ { ++ f_pIntFlags->fBufferPlayoutEventsPending = FALSE; ++ } ++ ++ /* Update the states of each interrupt group. */ ++ ulResult = Oct6100ApiUpdateIntrptStates( f_pApiInstance, f_pIntFlags ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check the state of the NLP timestamp if required.*/ ++ ulResult = Oct6100ApiCheckProcessorState( f_pApiInstance, f_pIntFlags ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write to the necessary IE registers. */ ++ ulResult = Oct6100ApiWriteIntrptRegs( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Schedule the next mclk interrupt, if one is needed. */ ++ ulResult = Oct6100ApiScheduleNextMclkIntrptSer( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Free the interrupt pin of the chip (i.e. remove minimum time requirement between interrupts). */ ++ WriteParams.ulWriteAddress = 0x214; ++ WriteParams.usWriteData = 0x0000; ++ if ( pSharedInfo->ChipConfig.byInterruptPolarity == cOCT6100_ACTIVE_HIGH_POLARITY ) ++ WriteParams.usWriteData |= 0x4000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Indicate that the interrupt ROLs have been treated. */ ++ WriteParams.ulWriteAddress = 0x212; ++ WriteParams.usWriteData = 0x8000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReadIntrptRegs ++ ++Description: Reads the interrupt registers of all modules currently ++ indicating an interrupt condition. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntFlags Pointer to an interrupt flag structure. ++f_ulRegister210h Value of register 0x210. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReadIntrptRegs ++UINT32 Oct6100ApiReadIntrptRegs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags, ++ IN UINT32 f_ulRegister210h ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_ERROR_STATS pErrorStats; ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ ++ UINT32 ulResult; ++ UINT16 usReadData; ++ UINT32 ulFeatureBytesOffset; ++ UINT32 ulFeatureBitOffset; ++ UINT32 ulFeatureFieldLength; ++ UINT32 ulTempData; ++ UINT32 ulCounterValue; ++ UINT32 ulMask; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ pErrorStats = &pSharedInfo->ErrorStats; ++ pIntrptManage = &pSharedInfo->IntrptManage; ++ ++ /* Set some parameters of read struct. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Set some parameters of write struct. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ++ ++ /* CPU registers. */ ++ if ( (f_ulRegister210h & 0x00001) != 0 ) ++ { ++ /*=======================================================================*/ ++ /* Read registers of this module. */ ++ ReadParams.ulReadAddress = 0x102; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check which interrupt(s) were set. */ ++ if ( (usReadData & 0x0001) != 0 ) ++ { ++ f_pIntFlags->fFatalReadTimeout = TRUE; ++ pErrorStats->ulInternalReadTimeoutCnt++; ++ } ++ ++ pIntrptManage->usRegister102h = usReadData; ++ /*=======================================================================*/ ++ } ++ else ++ { ++ pIntrptManage->usRegister102h = 0x0; ++ } ++ ++ /* MAIN registers. */ ++ if ( (f_ulRegister210h & 0x00002) != 0 ) ++ { ++ /*=======================================================================*/ ++ /* Read registers of this module. */ ++ ReadParams.ulReadAddress = 0x202; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save current value in instance. */ ++ pIntrptManage->usRegister202h = usReadData; ++ ++ /* Check which interrupts were set. */ ++ if ( (usReadData & 0x0001) != 0 ) ++ { ++ f_pIntFlags->fErrorRefreshTooLate = TRUE; ++ pErrorStats->ulSdramRefreshTooLateCnt++; ++ } ++ if ( (usReadData & 0x0800) != 0 ) ++ { ++ f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_1; ++ f_pIntFlags->fFatalGeneral = TRUE; ++ pErrorStats->fFatalChipError = TRUE; ++ } ++ if ( (usReadData & 0x1000) != 0 ) ++ { ++ f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_2; ++ f_pIntFlags->fFatalGeneral = TRUE; ++ pErrorStats->fFatalChipError = TRUE; ++ } ++ if ( (usReadData & 0x0400) != 0 ) ++ { ++ f_pIntFlags->fErrorPllJitter = TRUE; ++ pErrorStats->ulPllJitterErrorCnt++; ++ ++ /* Update the PLL jitter error count here. */ ++ if ( pSharedInfo->DebugInfo.fPouchCounter == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byFieldSize; ++ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ &ulTempData ); ++ ++ /* Read previous value set in the feature field. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ /* Update counter. */ ++ ulCounterValue = ulTempData & ulMask; ++ ulCounterValue = ulCounterValue >> ulFeatureBitOffset; ++ ulCounterValue ++; ++ /* Handle wrap around case. */ ++ ulCounterValue &= ( 1 << ulFeatureFieldLength ) - 1; ++ ++ /* Clear old counter value. */ ++ ulTempData &= (~ulMask); ++ ulTempData |= ulCounterValue << ulFeatureBitOffset; ++ ++ /* Write the DWORD where the field is located.*/ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /*=======================================================================*/ ++ } ++ else ++ { ++ pIntrptManage->usRegister202h = 0x0; ++ } ++ ++ /* H.100 registers. */ ++ if ( (f_ulRegister210h & 0x00004) != 0 ) ++ { ++ /*=======================================================================*/ ++ /* Read registers of this module. */ ++ ReadParams.ulReadAddress = 0x302; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check which interrupts were set. */ ++ if ( (usReadData & 0x0100) != 0 ) ++ { ++ f_pIntFlags->fErrorH100OutOfSync = TRUE; ++ pErrorStats->ulH100OutOfSyncCnt++; ++ } ++ if ( (usReadData & 0x1000) != 0 ) ++ { ++ f_pIntFlags->fErrorH100FrameA = TRUE; ++ pErrorStats->ulH100FrameABadCnt++; ++ } ++ if ( (usReadData & 0x4000) != 0 ) ++ { ++ f_pIntFlags->fErrorH100ClkA = TRUE; ++ pErrorStats->ulH100ClkABadCnt++; ++ } ++ if ( (usReadData & 0x8000) != 0 ) ++ { ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ { ++ f_pIntFlags->fErrorH100ClkB = TRUE; ++ pErrorStats->ulH100ClkBBadCnt++; ++ } ++ } ++ ++ pIntrptManage->usRegister302h = usReadData; ++ /*=======================================================================*/ ++ } ++ else ++ { ++ pIntrptManage->usRegister302h = 0x0; ++ } ++ ++ /* TDMIE registers. */ ++ if ( (f_ulRegister210h & 0x00010) != 0 ) ++ { ++ /*=======================================================================*/ ++ /* Read register. */ ++ ReadParams.ulReadAddress = 0x502; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check which interrupts were set. */ ++ if ( (usReadData & 0x0002) != 0 ) ++ { ++ f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_3; ++ f_pIntFlags->fFatalGeneral = TRUE; ++ pErrorStats->fFatalChipError = TRUE; ++ } ++ ++ pIntrptManage->usRegister502h = usReadData; ++ /*=======================================================================*/ ++ } ++ else ++ { ++ pIntrptManage->usRegister502h = 0x0; ++ } ++ ++ /* PGSP registers. */ ++ if ( (f_ulRegister210h & 0x00080) != 0 ) ++ { ++ /*=======================================================================*/ ++ /* Read register. */ ++ ReadParams.ulReadAddress = 0x702; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check which interrupts were set. */ ++ if ( (usReadData & 0x0002) != 0 ) ++ { ++ f_pIntFlags->fErrorOverflowToneEvents = TRUE; ++ pErrorStats->ulOverflowToneEventsCnt++; ++ } ++ ++ pIntrptManage->usRegister702h = usReadData; ++ /*=======================================================================*/ ++ } ++ else ++ { ++ pIntrptManage->usRegister702h = 0x0; ++ } ++ ++ ++ ++ /* If this is the first time the ISR is called, clear the ISR is not called bit */ ++ /* in external memory to signal the remote client that we are called. */ ++ if ( pSharedInfo->IntrptManage.fIsrCalled == FALSE ) ++ { ++ /* Remember that we are being called. */ ++ pSharedInfo->IntrptManage.fIsrCalled = TRUE; ++ ++ if ( pSharedInfo->DebugInfo.fIsIsrCalledField == TRUE ) ++ { ++ ulFeatureBytesOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.usDwordOffset * 4; ++ ulFeatureBitOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byBitOffset; ++ ulFeatureFieldLength = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byFieldSize; ++ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ &ulTempData ); ++ ++ /* Read previous value set in the feature field. */ ++ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ++ ++ /* Clear the field. */ ++ ulTempData &= (~ulMask); ++ ++ /* Write the DWORD where the field is located.*/ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ++ cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ++ ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateIntrptStates ++ ++Description: Updates the state of all interrupt register groups. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntFlags Interrupt flags. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateIntrptStates ++UINT32 Oct6100ApiUpdateIntrptStates( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) ++{ ++ tPOCT6100_API_INTRPT_CONFIG pIntrptConfig; ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ ++ pIntrptConfig = &f_pApiInstance->pSharedInfo->IntrptConfig; ++ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; ++ ++ /*-----------------------------------------------------------------------*/ ++ if ( ( f_pIntFlags->fFatalReadTimeout == TRUE) && ++ pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT && ++ pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ { ++ pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_WILL_TIMEOUT; ++ pIntrptManage->ulFatalMemoryDisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; ++ pIntrptManage->ulFatalMemoryDisableMclkLow = pIntrptManage->ulRegMclkTimeLow; ++ } ++ /*-----------------------------------------------------------------------*/ ++ if ( (f_pIntFlags->fErrorRefreshTooLate == TRUE || ++ f_pIntFlags->fErrorPllJitter == TRUE ) && ++ pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT && ++ pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ { ++ pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_WILL_TIMEOUT; ++ pIntrptManage->ulErrorMemoryDisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; ++ pIntrptManage->ulErrorMemoryDisableMclkLow = pIntrptManage->ulRegMclkTimeLow; ++ } ++ /*-----------------------------------------------------------------------*/ ++ if ( (f_pIntFlags->fErrorOverflowToneEvents == TRUE) && ++ pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_TIMEOUT && ++ pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_ACTIVE ) ++ { ++ pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_WILL_TIMEOUT; ++ pIntrptManage->ulErrorOverflowToneEventsDisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; ++ pIntrptManage->ulErrorOverflowToneEventsDisableMclkLow = pIntrptManage->ulRegMclkTimeLow; ++ } ++ /*-----------------------------------------------------------------------*/ ++ if ( (f_pIntFlags->fErrorH100OutOfSync == TRUE || ++ f_pIntFlags->fErrorH100ClkA == TRUE || ++ f_pIntFlags->fErrorH100ClkB == TRUE || ++ f_pIntFlags->fErrorH100FrameA == TRUE ) && ++ pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_TIMEOUT && ++ pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) ++ { ++ pIntrptManage->byErrorH100State = cOCT6100_INTRPT_WILL_TIMEOUT; ++ pIntrptManage->ulErrorH100DisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; ++ pIntrptManage->ulErrorH100DisableMclkLow = pIntrptManage->ulRegMclkTimeLow; ++ } ++ /*-----------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteIntrptRegs ++ ++Description: Writes to interrupt registers to clear interrupt condition, and ++ writes to an interrupt's IE register if interrupt is to time ++ out. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteIntrptRegs ++UINT32 Oct6100ApiWriteIntrptRegs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ ++ UINT32 ulResult; ++ ++ /* Get some local pointers. */ ++ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; ++ ++ /* Set some parameters of write struct. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ++ ++ /*===========================================================================*/ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_WILL_TIMEOUT ) ++ { ++ WriteParams.ulWriteAddress = 0x104; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ if ( (pIntrptManage->usRegister102h & cOCT6100_INTRPT_MASK_REG_102H) != 0 ) ++ { ++ WriteParams.ulWriteAddress = 0x102; ++ WriteParams.usWriteData = pIntrptManage->usRegister102h; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ /*===========================================================================*/ ++ ++ /*===========================================================================*/ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_WILL_TIMEOUT || ++ pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_WILL_TIMEOUT ) ++ { ++ WriteParams.ulWriteAddress = 0x204; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x1800; ++ ++ if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0401; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ if ( (pIntrptManage->usRegister202h & cOCT6100_INTRPT_MASK_REG_202H) != 0 ) ++ { ++ WriteParams.ulWriteAddress = 0x202; ++ WriteParams.usWriteData = pIntrptManage->usRegister202h; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ /*===========================================================================*/ ++ ++ /*===========================================================================*/ ++ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_WILL_TIMEOUT ) ++ { ++ WriteParams.ulWriteAddress = 0x304; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->fMclkIntrptActive == TRUE ) ++ WriteParams.usWriteData |= 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ if ( (pIntrptManage->usRegister302h & cOCT6100_INTRPT_MASK_REG_302H) != 0 ) ++ { ++ WriteParams.ulWriteAddress = 0x302; ++ WriteParams.usWriteData = pIntrptManage->usRegister302h; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ /*===========================================================================*/ ++ ++ /*===========================================================================*/ ++ if ( (pIntrptManage->usRegister502h & cOCT6100_INTRPT_MASK_REG_502H) != 0 ) ++ { ++ WriteParams.ulWriteAddress = 0x502; ++ WriteParams.usWriteData = pIntrptManage->usRegister502h; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ /*===========================================================================*/ ++ ++ /*===========================================================================*/ ++ if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_WILL_TIMEOUT ) ++ { ++ WriteParams.ulWriteAddress = 0x704; ++ WriteParams.usWriteData = 0x0000; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ if ( (pIntrptManage->usRegister702h & cOCT6100_INTRPT_MASK_REG_702H) != 0 ) ++ { ++ WriteParams.ulWriteAddress = 0x702; ++ WriteParams.usWriteData = pIntrptManage->usRegister702h; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ /*===========================================================================*/ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteIeRegs ++ ++Description: Writes the IE field of each interrupt register. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteIeRegs ++UINT32 Oct6100ApiWriteIeRegs( ++ tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ ++ /* Get some local pointers. */ ++ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; ++ ++ /* Set some parameters of write struct. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ++ /* Set some parameters of read struct. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*==================================================================================*/ ++ WriteParams.ulWriteAddress = 0x104; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*==================================================================================*/ ++ ++ /*==================================================================================*/ ++ WriteParams.ulWriteAddress = 0x204; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x1800; ++ if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0401; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*==================================================================================*/ ++ ++ /*==================================================================================*/ ++ WriteParams.ulWriteAddress = 0x304; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->fMclkIntrptActive == TRUE ) ++ WriteParams.usWriteData |= 0x0001; ++ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) ++ { ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ WriteParams.usWriteData |= 0xD100; ++ else ++ WriteParams.usWriteData |= 0x5100; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*==================================================================================*/ ++ ++ /*==================================================================================*/ ++ WriteParams.ulWriteAddress = 0x504; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byFatalGeneralState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0002; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*==================================================================================*/ ++ ++ /*==================================================================================*/ ++ WriteParams.ulWriteAddress = 0x704; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0002; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*==================================================================================*/ ++ ++ ++ /*==================================================================================*/ ++ /* Enable the GLOBAL IEs for the interrupt pin. */ ++ WriteParams.ulWriteAddress = 0x218; ++ WriteParams.usWriteData = 0x00D7; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ /*==================================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReadChipMclkTime ++ ++Description: Reads the chip's mclk cycle count to construct a chip time. ++ The time is used to manage interrupts. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReadChipMclkTime ++UINT32 Oct6100ApiReadChipMclkTime( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulCheckData; ++ UINT32 ulResult; ++ UINT32 i; ++ UINT16 usReadData; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ pIntrptManage = &pSharedInfo->IntrptManage; ++ ++ /* Assign memory for read data. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Perform reads. */ ++ for ( i = 0; i < 100; i++ ) ++ { ++ ReadParams.ulReadAddress = 0x306; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ pIntrptManage->ulRegMclkTimeHigh = usReadData & 0xFF; ++ ulCheckData = usReadData; ++ ++ ReadParams.ulReadAddress = 0x308; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ pIntrptManage->ulRegMclkTimeLow = (usReadData & 0xFFFF) << 16; ++ ++ ReadParams.ulReadAddress = 0x306; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ if ( ulCheckData == usReadData ) ++ break; ++ } ++ ++ if ( i == 100 ) ++ return cOCT6100_ERR_FATAL_2F; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateIntrptTimeouts ++ ++Description: Checks which interrupt groups have finished their timeout ++ period. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateIntrptTimeouts ++UINT32 Oct6100ApiUpdateIntrptTimeouts( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulRegMclkTimePlus5MsHigh; ++ UINT32 ulRegMclkTimePlus5MsLow; ++ UINT32 ulResult; ++ BOOL fFatalMemoryChange = FALSE; ++ BOOL fDataErrMemoryChange = FALSE; ++ BOOL fErrorOverflowToneEventsChange = FALSE; ++ BOOL fH100ErrorChange = FALSE; ++ ++ /* Get local pointer to interrupt management structure. */ ++ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; ++ ++ /* Calculate mclk time + 5 ms. */ ++ ulRegMclkTimePlus5MsLow = pIntrptManage->ulRegMclkTimeLow + (5 * pIntrptManage->ulNumMclkCyclesIn1Ms); ++ if ( ulRegMclkTimePlus5MsLow < pIntrptManage->ulRegMclkTimeLow ) ++ ulRegMclkTimePlus5MsHigh = pIntrptManage->ulRegMclkTimeHigh + 1; ++ else /* ( ulRegMclkTimePlus5MsLow >= pIntrptManage->ulRegMclkTimeLow ) */ ++ ulRegMclkTimePlus5MsHigh = pIntrptManage->ulRegMclkTimeHigh; ++ ++ /* Check which interrupts are timed out and need to be reenabled now. */ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_IN_TIMEOUT ) ++ { ++ mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulFatalMemoryDisableMclkHigh, pIntrptManage->ulFatalMemoryDisableMclkLow, pIntrptManage->ulFatalMemoryEnableMclkHigh, pIntrptManage->ulFatalMemoryEnableMclkLow, pIntrptManage->byFatalMemoryState, fFatalMemoryChange ) ++ } ++ if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_IN_TIMEOUT ) ++ { ++ mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulErrorMemoryDisableMclkHigh, pIntrptManage->ulErrorMemoryDisableMclkLow, pIntrptManage->ulErrorMemoryEnableMclkHigh, pIntrptManage->ulErrorMemoryEnableMclkLow, pIntrptManage->byErrorMemoryState, fDataErrMemoryChange ) ++ } ++ if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_IN_TIMEOUT ) ++ { ++ mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulErrorOverflowToneEventsDisableMclkHigh, pIntrptManage->ulErrorOverflowToneEventsDisableMclkLow, pIntrptManage->ulErrorOverflowToneEventsEnableMclkHigh, pIntrptManage->ulErrorOverflowToneEventsEnableMclkLow, pIntrptManage->byErrorOverflowToneEventsState, fErrorOverflowToneEventsChange ) ++ } ++ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_IN_TIMEOUT ) ++ { ++ mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulErrorH100DisableMclkHigh, pIntrptManage->ulErrorH100DisableMclkLow, pIntrptManage->ulErrorH100EnableMclkHigh, pIntrptManage->ulErrorH100EnableMclkLow, pIntrptManage->byErrorH100State, fH100ErrorChange ) ++ } ++ ++ /* Set some parameters of write struct. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Write to the IE registers which have changed. */ ++ ++ /*==================================================================================*/ ++ if ( fFatalMemoryChange == TRUE ) ++ { ++ WriteParams.ulWriteAddress = 0x104; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0001; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ } ++ /*==================================================================================*/ ++ ++ /*==================================================================================*/ ++ if ( fFatalMemoryChange == TRUE || ++ fDataErrMemoryChange == TRUE ) ++ { ++ WriteParams.ulWriteAddress = 0x204; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x1800; ++ if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0401; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ } ++ /*==================================================================================*/ ++ ++ /*==================================================================================*/ ++ if ( pIntrptManage->fMclkIntrptActive == TRUE || ++ fH100ErrorChange == TRUE ) ++ { ++ WriteParams.ulWriteAddress = 0x304; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->fMclkIntrptActive == TRUE ) ++ WriteParams.usWriteData |= 0x0001; ++ ++ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) ++ { ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ WriteParams.usWriteData |= 0xD100; ++ else ++ WriteParams.usWriteData |= 0x5100; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ } ++ /*==================================================================================*/ ++ ++ ++ /*==================================================================================*/ ++ if ( fErrorOverflowToneEventsChange == TRUE ) ++ { ++ WriteParams.ulWriteAddress = 0x704; ++ WriteParams.usWriteData = 0x0000; ++ ++ if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_ACTIVE ) ++ WriteParams.usWriteData |= 0x0002; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ } ++ /*==================================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiScheduleNextMclkIntrptSer ++ ++Description: Serialized sub-function of Oct6100ApiScheduleNextMclkIntrpt. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiScheduleNextMclkIntrptSer ++UINT32 Oct6100ApiScheduleNextMclkIntrptSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_INTRPT_CONFIG pIntrptConfig; ++ tPOCT6100_API_INTRPT_MANAGE pIntrptManage; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulTimeDiff; ++ UINT32 ulRegMclkTimeHigh; ++ UINT32 ulRegMclkTimeLow; ++ UINT32 ulResult; ++ BOOL fConditionFlag = TRUE; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain temporary pointers to reduce indirection, thus speeding up processing. */ ++ pIntrptConfig = &pSharedInfo->IntrptConfig; ++ pIntrptManage = &pSharedInfo->IntrptManage; ++ ulRegMclkTimeHigh = pIntrptManage->ulRegMclkTimeHigh; ++ ulRegMclkTimeLow = pIntrptManage->ulRegMclkTimeLow; ++ ++ /* First, check if any interrupts have just been disabled. If there are any, */ ++ /* determine the time at which they should be reenabled. */ ++ pIntrptManage->ulNextMclkIntrptTimeHigh = cOCT6100_INVALID_VALUE; ++ pIntrptManage->ulNextMclkIntrptTimeLow = cOCT6100_INVALID_VALUE; ++ ++ while ( fConditionFlag ) ++ { ++ /* Indicate that no mclk interrupt is needed, yet. */ ++ ulTimeDiff = cOCT6100_INVALID_VALUE; ++ ++ /* Check each interrupt category to see if an mclk interrupt is needed to */ ++ /* reenable an interrupt at a later time. */ ++ if ( pIntrptManage->byFatalMemoryState != cOCT6100_INTRPT_ACTIVE && ++ pIntrptManage->byFatalMemoryState != cOCT6100_INTRPT_DISABLED ) ++ { ++ mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byFatalMemoryState, pIntrptManage->ulFatalMemoryEnableMclkHigh, pIntrptManage->ulFatalMemoryEnableMclkLow, pIntrptConfig->ulFatalMemoryTimeoutMclk, ulTimeDiff ) ++ } ++ if ( pIntrptManage->byErrorMemoryState != cOCT6100_INTRPT_ACTIVE && ++ pIntrptManage->byErrorMemoryState != cOCT6100_INTRPT_DISABLED ) ++ { ++ mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byErrorMemoryState, pIntrptManage->ulErrorMemoryEnableMclkHigh, pIntrptManage->ulErrorMemoryEnableMclkLow, pIntrptConfig->ulErrorMemoryTimeoutMclk, ulTimeDiff ) ++ } ++ if ( pIntrptManage->byErrorOverflowToneEventsState != cOCT6100_INTRPT_ACTIVE && ++ pIntrptManage->byErrorOverflowToneEventsState != cOCT6100_INTRPT_DISABLED ) ++ { ++ mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byErrorOverflowToneEventsState, pIntrptManage->ulErrorOverflowToneEventsEnableMclkHigh, pIntrptManage->ulErrorOverflowToneEventsEnableMclkLow, pIntrptConfig->ulErrorOverflowToneEventsTimeoutMclk, ulTimeDiff ) ++ } ++ if ( pIntrptManage->byErrorH100State != cOCT6100_INTRPT_ACTIVE && ++ pIntrptManage->byErrorH100State != cOCT6100_INTRPT_DISABLED ) ++ { ++ mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byErrorH100State, pIntrptManage->ulErrorH100EnableMclkHigh, pIntrptManage->ulErrorH100EnableMclkLow, pIntrptConfig->ulErrorH100TimeoutMclk, ulTimeDiff ) ++ } ++ ++ /* Set some parameters of write struct. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Schedule next mclk interrupt, if any is needed. */ ++ if ( ulTimeDiff != cOCT6100_INVALID_VALUE ) ++ { ++ UINT32 ulMclkTimeTest; ++ UINT32 ulAlarmTimeTest; ++ UINT32 ulTimeDiffTest; ++ BOOL fAlarmTimePassed; ++ ++ /* Indicate that an mclk interrupt is scheduled.*/ ++ pIntrptManage->fMclkIntrptActive = TRUE; ++ ++ pIntrptManage->ulNextMclkIntrptTimeLow = ulRegMclkTimeLow + ulTimeDiff; ++ if ( pIntrptManage->ulNextMclkIntrptTimeLow < ulRegMclkTimeLow ) ++ pIntrptManage->ulNextMclkIntrptTimeHigh = ulRegMclkTimeHigh + 1; ++ else /* ( pIntrptManage->ulNextMclkIntrptTimeLow >= ulRegMclkTimeLow ) */ ++ pIntrptManage->ulNextMclkIntrptTimeHigh = ulRegMclkTimeHigh; ++ ++ WriteParams.ulWriteAddress = 0x30C; ++ WriteParams.usWriteData = (UINT16)( (pIntrptManage->ulNextMclkIntrptTimeLow >> 24) & 0xFF ); ++ WriteParams.usWriteData |= (UINT16)( (pIntrptManage->ulNextMclkIntrptTimeHigh & 0xFF) << 8 ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x30E; ++ WriteParams.usWriteData = (UINT16)( (pIntrptManage->ulNextMclkIntrptTimeLow >> 8) & 0xFFFF ); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress = 0x304; ++ WriteParams.usWriteData = 0; ++ ++ if ( pIntrptManage->fMclkIntrptActive == TRUE ) ++ WriteParams.usWriteData = 0x0001; ++ ++ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) ++ { ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ WriteParams.usWriteData |= 0xD100; ++ else ++ WriteParams.usWriteData |= 0x5100; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Disable the ROL if previously set. */ ++ WriteParams.ulWriteAddress = 0x302; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if already passed the next interrupt time. */ ++ ulResult = Oct6100ApiReadChipMclkTime( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulMclkTimeTest = (pIntrptManage->ulRegMclkTimeLow >> 16) & 0xFFFF; ++ ulAlarmTimeTest = (pIntrptManage->ulNextMclkIntrptTimeLow >> 16) & 0xFFFF; ++ ++ /* Update the local Mlck timer values.*/ ++ ulRegMclkTimeHigh = pIntrptManage->ulRegMclkTimeHigh; ++ ulRegMclkTimeLow = pIntrptManage->ulRegMclkTimeLow; ++ ++ fAlarmTimePassed = FALSE; ++ ++ if ( ulMclkTimeTest > ulAlarmTimeTest ) ++ { ++ ulTimeDiffTest = ulMclkTimeTest - ulAlarmTimeTest; ++ if ( ulTimeDiffTest <= 0x8000 ) ++ fAlarmTimePassed = TRUE; ++ } ++ else /* ( ulMclkTimeTest <= ulAlarmTimeTest ) */ ++ { ++ ulTimeDiffTest = ulAlarmTimeTest - ulMclkTimeTest; ++ if ( ulTimeDiffTest > 0x8000 ) ++ fAlarmTimePassed = TRUE; ++ } ++ ++ if ( fAlarmTimePassed == TRUE ) ++ { ++ /* Passed the interrupt time. Schedule next interrupt (if needed). */ ++ ulResult = Oct6100ApiUpdateIntrptTimeouts( f_pApiInstance ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ continue; ++ } ++ else ++ { ++ fConditionFlag = FALSE; ++ } ++ } ++ else ++ { ++ /* Indicate that no mclk interrupt is scheduled. */ ++ pIntrptManage->fMclkIntrptActive = FALSE; ++ ++ /* Insure that the mclk interrupt is not enabled. */ ++ WriteParams.ulWriteAddress = 0x304; ++ WriteParams.usWriteData = 0x0000; ++ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) ++ { ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) ++ WriteParams.usWriteData |= 0xD100; ++ else ++ WriteParams.usWriteData |= 0x5100; ++ } ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ fConditionFlag = FALSE; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckProcessorState ++ ++Description: This function verifies if the NLP and AF processors are operating ++ correctly. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pIntFlags Pointer to a tOCT6100_INTERRUPT_FLAGS structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckProcessorState ++UINT32 Oct6100ApiCheckProcessorState( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_READ_BURST_PARAMS ReadBurstParams; ++ ++ UINT32 ulNlpTimestamp; ++ UINT32 ulAfTimestamp; ++ UINT32 ulTimestampDiff; ++ ++ UINT32 ulResult; ++ UINT32 i; ++ ++ UINT16 usReadData; ++ UINT16 ausReadData[ 2 ]; ++ ++ UINT32 aulWaitTime[ 2 ]; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set some parameters of write struct. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Set some parameters of write struct. */ ++ ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadBurstParams.pusReadData = ausReadData; ++ ++ /*-----------------------------------------------------------------------*/ ++ /* Check if chip is in reset. */ ++ ++ /* Read the main control register. */ ++ ReadParams.ulReadAddress = 0x100; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData == 0x0000 ) ++ { ++ /* Chip was resetted. */ ++ f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_4; ++ f_pIntFlags->fFatalGeneral = TRUE; ++ pSharedInfo->ErrorStats.fFatalChipError = TRUE; ++ } ++ ++ /*-----------------------------------------------------------------------*/ ++ ++ ++ /*-----------------------------------------------------------------------*/ ++ /* Reading the AF timestamp.*/ ++ ++ for ( i = 0; i < cOCT6100_MAX_LOOP; i++ ) ++ { ++ /* Read the timestamp.*/ ++ ReadBurstParams.ulReadAddress = 0x082E0008; ++ ReadBurstParams.ulReadLength = 2; ++ ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Read the high part again to make sure it didn't wrap. */ ++ ReadParams.ulReadAddress = 0x082E0008; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the low part wrapped. */ ++ if ( ausReadData[ 0 ] == usReadData ) ++ break; ++ } ++ ++ if ( i == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_INTRPTS_AF_TIMESTAMP_READ_TIMEOUT; ++ ++ /* Save the AF timestamp. */ ++ ulAfTimestamp = (ausReadData[ 0 ] << 16) | ausReadData[ 1 ]; ++ ++ /*-----------------------------------------------------------------------*/ ++ ++ ++ /*-----------------------------------------------------------------------*/ ++ /* Reading the NLP timestamp. */ ++ ++ for ( i = 0; i < cOCT6100_MAX_LOOP; i++ ) ++ { ++ /* Read the timestamp. */ ++ ReadBurstParams.ulReadAddress = 0x08000008; ++ ReadBurstParams.ulReadLength = 2; ++ ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Read the high part again to make sure it didn't wrap. */ ++ ReadParams.ulReadAddress = 0x08000008; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the low part wrapped. */ ++ if ( ausReadData[ 0 ] == usReadData ) ++ break; ++ } ++ ++ if ( i == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_INTRPTS_NLP_TIMESTAMP_READ_TIMEOUT; ++ ++ /* Save the NLP timestamp. */ ++ ulNlpTimestamp = (ausReadData[ 0 ] << 16) | ausReadData[ 1 ]; ++ ++ /*-----------------------------------------------------------------------*/ ++ ++ ++ /*-----------------------------------------------------------------------*/ ++ /* Check the validity of the timestamp. */ ++ ++ if ( ulAfTimestamp > ulNlpTimestamp ) ++ { ++ /* The NLP timestamp wrapped. */ ++ ulTimestampDiff = 0xFFFFFFFF - ulAfTimestamp + 1; ++ ulTimestampDiff += ulNlpTimestamp; ++ } ++ else ++ ulTimestampDiff = ulNlpTimestamp - ulAfTimestamp; ++ ++ if ( ulTimestampDiff > 0x2000 ) ++ { ++ f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_5; ++ f_pIntFlags->fFatalGeneral = TRUE; ++ pSharedInfo->ErrorStats.fFatalChipError = TRUE; ++ } ++ ++ /*Check if AF and NLP are both stuck*/ ++ if ( f_pIntFlags->fErrorH100ClkA == FALSE && ++ f_pIntFlags->fErrorH100ClkB == FALSE && ++ f_pIntFlags->fErrorH100FrameA == FALSE && ++ f_pIntFlags->fErrorH100OutOfSync == FALSE ) ++ ++ { ++ if ( ulAfTimestamp == 0 && ulNlpTimestamp == 0 ) ++ { ++ /*Give some time to the counters*/ ++ aulWaitTime[ 0 ] = 250; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*Let's read again the AF timestamp to be sure. Maybe they were at 0 at the same time*/ ++ ReadBurstParams.ulReadAddress = 0x082E0008; ++ ReadBurstParams.ulReadLength = 2; ++ ++ mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulAfTimestamp = (ausReadData[ 0 ] << 16) | ausReadData[ 1 ]; ++ ++ if ( ulAfTimestamp == 0 ) ++ { ++ /*TDM Clocks are ok but NLP and AF timestamps are both at 0*/ ++ f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_9; ++ f_pIntFlags->fFatalGeneral = TRUE; ++ pSharedInfo->ErrorStats.fFatalChipError = TRUE; ++ } ++ } ++ ++ } ++ ++ /*-----------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_memory.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_memory.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_memory.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_memory.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,831 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_memory.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the functions used to manage the allocation of memory ++ blocks in external memory. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 42 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_playout_buf_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_memory_priv.h" ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetMemorySwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of the memories. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetMemorySwSizes ++UINT32 Oct6100ApiGetMemorySwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ UINT32 ulNumTsiChariots; ++ ++ /*=========================================================================*/ ++ /* Internal memory */ ++ ++ /* Evaluate the number of available TSI memory after reserving the ones used by channels. */ ++ ulNumTsiChariots = cOCT6100_TOTAL_TSI_CONTROL_MEM_ENTRY - f_pOpenChip->ulMaxPhasingTssts - cOCT6100_TSI_MEM_FOR_TIMESTAMP; ++ ++ if ( f_pOpenChip->fEnableExtToneDetection == TRUE ) ++ ulNumTsiChariots--; ++ ++ /* Calculate memory needed for TSI memory allocation. */ ++ ulResult = OctapiLlmAllocGetSize( ulNumTsiChariots, &f_pInstSizes->ulTsiMemoryAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_94; ++ ++ /* Calculate memory needed for conversion memory allocation. */ ++ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_CONVERSION_MEMORY_BLOCKS, &f_pInstSizes->ulConversionMemoryAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_B5; ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsiMemoryAlloc, ulTempVar ); ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConversionMemoryAlloc, ulTempVar ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiMemorySwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to memories. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiMemorySwInit ++UINT32 Oct6100ApiMemorySwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pTsiMemAlloc; ++ PVOID pAllocPnt; ++ UINT32 ulResult; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /*=========================================================================*/ ++ /* Internal memory */ ++ ++ /* Initialize the TSI memory allocation structure. */ ++ pSharedInfo->MemoryMap.ulNumTsiEntries = cOCT6100_TOTAL_TSI_CONTROL_MEM_ENTRY - pSharedInfo->ChipConfig.usMaxPhasingTssts - cOCT6100_TSI_MEM_FOR_TIMESTAMP; ++ ++ if ( pSharedInfo->ChipConfig.fEnableExtToneDetection == TRUE ) ++ pSharedInfo->MemoryMap.ulNumTsiEntries--; ++ ++ mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ); ++ ++ ulResult = OctapiLlmAllocInit( &pTsiMemAlloc, pSharedInfo->MemoryMap.ulNumTsiEntries ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_95; ++ ++ /* Initialize the conversion memory allocation structure. */ ++ mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pAllocPnt ); ++ ++ ulResult = OctapiLlmAllocInit( &pAllocPnt, cOCT6100_MAX_CONVERSION_MEMORY_BLOCKS ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_B6; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiBufferPlayoutMemorySwInit ++ ++Description: Initialize the buffer playout memory allocation working ++ structures. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiBufferPlayoutMemorySwInit ++UINT32 Oct6100ApiBufferPlayoutMemorySwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNode; ++ UINT32 i; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Only if buffer playout will be used. */ ++ if ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers > 0 ) ++ { ++ mOCT6100_GET_BUFFER_MEMORY_NODE_LIST_PNT( pSharedInfo, pNode ); ++ ++ /* First node contains all free memory at beginning. This node is not used, but represents the memory. */ ++ pNode->ulSize = ( pSharedInfo->MiscVars.ulTotalMemSize + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) - pSharedInfo->MemoryMap.ulFreeMemBaseAddress; ++ pNode->ulNext = 0; ++ pNode->ulPrevious = 0; ++ pNode->fAllocated = FALSE; ++ pNode->ulStartAddress = pSharedInfo->MemoryMap.ulFreeMemBaseAddress; ++ ++ pNode++; ++ ++ /* Now create the first node of the free list, i.e. nodes that can be used later for modeling the memory. */ ++ pNode->ulSize = 0; ++ /* Next free. */ ++ pNode->ulNext = 2; ++ /* Last. */ ++ pNode->ulPrevious = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; ++ pNode->fAllocated = FALSE; ++ pNode->ulStartAddress = 0; ++ ++ pNode++; ++ ++ /* Link all the unused nodes. */ ++ for( i = 2; i < (UINT32)( ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1 ); i ++ ) ++ { ++ pNode->ulNext = i + 1; ++ pNode->ulPrevious = i - 1; ++ pNode->ulStartAddress = 0; ++ pNode->ulSize = 0; ++ pNode->fAllocated = FALSE; ++ pNode++; ++ } ++ ++ /* Last node of the unused list. */ ++ pNode->fAllocated = FALSE; ++ pNode->ulPrevious = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 2; ++ /* Free list head. */ ++ pNode->ulNext = 1; ++ pNode->ulSize = 0; ++ pNode->ulStartAddress = 0; ++ ++ /* Set roving pointer to first node ( which can be used! ) */ ++ pSharedInfo->PlayoutInfo.ulRovingNode = 0; ++ ++ /* First unused node. */ ++ pSharedInfo->PlayoutInfo.ulFirstUnusedNode = 1; ++ ++ /* Last unused node. */ ++ pSharedInfo->PlayoutInfo.ulLastUnusedNode = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; ++ ++ /* Number of unused nodes. */ ++ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; ++ } ++ else ++ { ++ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt = 0; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBufferPlayoutMemoryNode ++ ++Description: Get a free node from the unused buffer playout node list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pulNewNode The index of the node. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBufferPlayoutMemoryNode ++UINT32 Oct6100ApiReserveBufferPlayoutMemoryNode( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT32 f_pulNewNode ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNode; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check if a free block is left. */ ++ if ( pSharedInfo->PlayoutInfo.ulUnusedNodeCnt == 0 ) ++ { ++ /* This should not happen according to the allocated list from the beginning. */ ++ return cOCT6100_ERR_FATAL_CC; ++ } ++ ++ /* The new node is the first in the unused list. */ ++ *f_pulNewNode = pSharedInfo->PlayoutInfo.ulFirstUnusedNode; ++ ++ /* Unlink this new node from the unused list. */ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, *f_pulNewNode ); ++ ++ pSharedInfo->PlayoutInfo.ulFirstUnusedNode = pNode->ulNext; ++ ++ pNode->ulPrevious = pSharedInfo->PlayoutInfo.ulLastUnusedNode; ++ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, pSharedInfo->PlayoutInfo.ulLastUnusedNode ); ++ ++ pNode->ulNext = pSharedInfo->PlayoutInfo.ulFirstUnusedNode; ++ ++ /* Update unused node count. */ ++ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt--; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBufferPlayoutMemoryNode ++ ++Description: Release a node that is not used anymore. Insert this node ++ into the unused list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulOldNode The index of the node. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBufferPlayoutMemoryNode ++UINT32 Oct6100ApiReleaseBufferPlayoutMemoryNode( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulOldNode ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNode; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get the last unused node. Insert this old node at the end of the unused list. */ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, pSharedInfo->PlayoutInfo.ulLastUnusedNode ); ++ ++ /* Last node points to old node. */ ++ pNode->ulNext = f_ulOldNode; ++ ++ /* Update old node. */ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, f_ulOldNode ); ++ ++ pNode->ulPrevious = pSharedInfo->PlayoutInfo.ulLastUnusedNode; ++ pNode->ulNext = pSharedInfo->PlayoutInfo.ulFirstUnusedNode; ++ pSharedInfo->PlayoutInfo.ulLastUnusedNode = f_ulOldNode; ++ ++ /* Keep unused node count. */ ++ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt++; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBufferPlayoutMemory ++ ++Description: Try to allocate requested size. ++ Returns an error if malloc point could not be found. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulSize Needed size. ++f_pulMallocAddress Alloc point. This memory can now be used. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBufferPlayoutMemory ++UINT32 Oct6100ApiReserveBufferPlayoutMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulSize, ++ OUT PUINT32 f_pulMallocAddress ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pCurrentNode; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pTempNode; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNewNode; ++ ++ UINT32 ulCurrentBufferPlayoutMallocNode; ++ UINT32 ulNewNode; ++ BOOL fFoundMemory = FALSE; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Requested size must be divisible by 64. */ ++ if ( f_ulSize % 64 ) ++ { ++ f_ulSize = f_ulSize + ( 64 - ( f_ulSize % 64 ) ); ++ } ++ ++ /* Start with roving pointer. */ ++ ulCurrentBufferPlayoutMallocNode = pSharedInfo->PlayoutInfo.ulRovingNode; ++ ++ *f_pulMallocAddress = 0; ++ ++ /* Return an error if size requested is zero. */ ++ if ( f_ulSize == 0 ) ++ { ++ return cOCT6100_ERR_BUFFER_PLAYOUT_MALLOC_ZERO; ++ } ++ ++ do ++ { ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pCurrentNode, ulCurrentBufferPlayoutMallocNode ); ++ ++ /* Look for a free node big enough to fulfill user requested size. */ ++ if ( ( pCurrentNode->fAllocated == FALSE ) && ( pCurrentNode->ulSize >= f_ulSize ) ) ++ { ++ /* Use this node! */ ++ pCurrentNode->fAllocated = TRUE; ++ ++ if ( pCurrentNode->ulNext != 0 ) ++ { ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulNext ); ++ ++ if( ( pTempNode->fAllocated == TRUE ) && ( pCurrentNode->ulSize > f_ulSize ) ) ++ { ++ /* Fragmentation NOW! */ ++ ++ /* Allocate new node that will contain free size. */ ++ ulResult = Oct6100ApiReserveBufferPlayoutMemoryNode( f_pApiInstance, &ulNewNode ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNewNode, ulNewNode ); ++ ++ /* Can use this free node. */ ++ pNewNode->ulSize = pCurrentNode->ulSize - f_ulSize; ++ pNewNode->ulStartAddress = pCurrentNode->ulStartAddress + f_ulSize; ++ ++ /* Link new node into the list. */ ++ pNewNode->ulNext = pCurrentNode->ulNext; ++ pNewNode->ulPrevious = ulCurrentBufferPlayoutMallocNode; ++ pNewNode->fAllocated = FALSE; ++ pTempNode->ulPrevious = ulNewNode; ++ pCurrentNode->ulNext = ulNewNode; ++ } ++ } ++ else if ( pCurrentNode->ulSize > f_ulSize ) ++ { ++ /* Must allocate a new free node for the rest of the space. */ ++ ulResult = Oct6100ApiReserveBufferPlayoutMemoryNode( f_pApiInstance, &ulNewNode ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNewNode, ulNewNode ); ++ ++ pNewNode->ulNext = pCurrentNode->ulNext; ++ pCurrentNode->ulNext = ulNewNode; ++ pNewNode->ulPrevious = ulCurrentBufferPlayoutMallocNode; ++ pNewNode->fAllocated = FALSE; ++ pNewNode->ulSize = pCurrentNode->ulSize - f_ulSize; ++ pNewNode->ulStartAddress = pCurrentNode->ulStartAddress + f_ulSize; ++ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, 0 ); ++ ++ /* Check for the head node that would have to be updated. */ ++ if ( ( ulCurrentBufferPlayoutMallocNode == 0 ) && ( pTempNode->ulPrevious == 0 ) ) ++ pTempNode->ulPrevious = ulNewNode; ++ } ++ else ++ { ++ /* Perfect fit. */ ++ } ++ pCurrentNode->ulSize = f_ulSize; ++ ++ /* Update roving pointer. */ ++ pSharedInfo->PlayoutInfo.ulRovingNode = ulCurrentBufferPlayoutMallocNode; ++ *f_pulMallocAddress = pCurrentNode->ulStartAddress; ++ fFoundMemory = TRUE; ++ break; ++ } ++ ++ /* Next block! */ ++ ulCurrentBufferPlayoutMallocNode = pCurrentNode->ulNext; ++ ++ } while ( pSharedInfo->PlayoutInfo.ulRovingNode != ulCurrentBufferPlayoutMallocNode ); ++ ++ if ( fFoundMemory == FALSE ) ++ { ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NO_MEMORY; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBufferPlayoutMemory ++ ++Description: Free what was allocated at address. Free is somewhat slower ++ then Malloc. O(n), must travel through the list looking for ++ the malloc point. Return an error if alloc point was not found. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulMallocAddress Alloc point. The memory at address will be freed. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBufferPlayoutMemory ++UINT32 Oct6100ApiReleaseBufferPlayoutMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulMallocAddress ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pCurrentNode; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pTempNode; ++ tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pOldNode; ++ ++ UINT32 ulResult = cOCT6100_ERR_BUFFER_PLAYOUT_MALLOC_POINT_NOT_FOUND; ++ UINT32 ulNodeToMerge; ++ UINT32 ulNodeToRemove; ++ UINT32 ulCurrentBufferPlayoutMallocNode; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Start from the beginning and find the alloc node. */ ++ ulCurrentBufferPlayoutMallocNode = 0; ++ ++ do ++ { ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pCurrentNode, ulCurrentBufferPlayoutMallocNode ); ++ ++ if ( ( pCurrentNode->ulStartAddress == f_ulMallocAddress ) && ( pCurrentNode->fAllocated == TRUE ) ) ++ { ++ /* We found the block! */ ++ pCurrentNode->fAllocated = FALSE; ++ ++ /* Check if the next node can be merged. */ ++ if ( pCurrentNode->ulNext != 0 ) ++ { ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulNext ); ++ ++ if ( pTempNode->fAllocated == FALSE ) ++ { ++ /* Can merge this block to us. */ ++ pCurrentNode->ulSize += pTempNode->ulSize; ++ pTempNode->ulSize = 0; ++ ++ /* Unlink unused node. */ ++ ulNodeToRemove = pCurrentNode->ulNext; ++ pCurrentNode->ulNext = pTempNode->ulNext; ++ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulNext ); ++ ++ pTempNode->ulPrevious = ulCurrentBufferPlayoutMallocNode; ++ ++ ulResult = Oct6100ApiReleaseBufferPlayoutMemoryNode( f_pApiInstance, ulNodeToRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move roving pointer if have to. */ ++ if ( pSharedInfo->PlayoutInfo.ulRovingNode == ulNodeToRemove ) ++ pSharedInfo->PlayoutInfo.ulRovingNode = ulCurrentBufferPlayoutMallocNode; ++ } ++ } ++ ++ /* Check if previous node can merge. */ ++ if ( ulCurrentBufferPlayoutMallocNode != 0 ) ++ { ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulPrevious ); ++ ++ if ( pTempNode->fAllocated == FALSE ) ++ { ++ ulNodeToMerge = pCurrentNode->ulPrevious; ++ ++ /* Can merge us to this node. */ ++ pTempNode->ulSize += pCurrentNode->ulSize; ++ pCurrentNode->ulSize = 0; ++ ++ /* Unlink unused node. */ ++ ulNodeToRemove = ulCurrentBufferPlayoutMallocNode; ++ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pOldNode, ulNodeToRemove ); ++ ++ pTempNode->ulNext = pOldNode->ulNext; ++ ++ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pTempNode->ulNext ); ++ ++ pTempNode->ulPrevious = ulNodeToMerge; ++ ++ pOldNode->fAllocated = FALSE; ++ pOldNode->ulSize = 0; ++ pOldNode->ulStartAddress = 0; ++ ++ /* Move roving pointer if have to. */ ++ if ( pSharedInfo->PlayoutInfo.ulRovingNode == ulNodeToRemove ) ++ pSharedInfo->PlayoutInfo.ulRovingNode = ulNodeToMerge; ++ ++ /* Release this unused node. */ ++ ulResult = Oct6100ApiReleaseBufferPlayoutMemoryNode( f_pApiInstance, ulNodeToRemove ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* All's good! */ ++ ulResult = 0; ++ break; ++ } ++ ++ /* Next node. */ ++ ulCurrentBufferPlayoutMallocNode = pCurrentNode->ulNext; ++ ++ } while( ulCurrentBufferPlayoutMallocNode != 0 ); ++ ++ return ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveTsiMemEntry ++ ++Description: Reserves a TSI chariot memory entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pusTsiMemIndex Resulting index reserved in the TSI chariot memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveTsiMemEntry ++UINT32 Oct6100ApiReserveTsiMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusTsiMemIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pTsiMemAlloc; ++ UINT32 ulResult; ++ UINT32 ulIndex; ++ UINT32 ulNumTsiB4Timestamp; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pTsiMemAlloc, &ulIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_MEMORY_ALL_TSI_MEM_ENTRY_RESERVED; ++ else ++ return cOCT6100_ERR_FATAL_92; ++ } ++ ++ ++ if ( ulIndex >= cOCT6100_NUM_TSI_B4_PHASING ) ++ { ++ /* Evaluate the number of TSI memory before the timestamp TSI. */ ++ ulNumTsiB4Timestamp = cOCT6100_NUM_TSI_B4_PHASING + cOCT6100_MAX_TSI_B4_TIMESTAMP - pSharedInfo->ChipConfig.usMaxPhasingTssts; ++ ++ if ( ulIndex >= ulNumTsiB4Timestamp ) ++ { ++ /* + 4 for the timestamp TSI entries.*/ ++ *f_pusTsiMemIndex = (UINT16)( pSharedInfo->ChipConfig.usMaxPhasingTssts + ulIndex + cOCT6100_TSI_MEM_FOR_TIMESTAMP ); ++ } ++ else /* ulIndex < ulNumTsiB4Timestamp */ ++ { ++ *f_pusTsiMemIndex = (UINT16)( pSharedInfo->ChipConfig.usMaxPhasingTssts + ulIndex ); ++ } ++ } ++ else /* ulIndex < ulNumTsiB4Timestamp */ ++ { ++ *f_pusTsiMemIndex = (UINT16)( ulIndex ); ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseTsiMemEntry ++ ++Description: Releases a TSI chariot memory entry specified. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usTsiMemIndex Index reserved in the TSI chariot memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseTsiMemEntry ++UINT32 Oct6100ApiReleaseTsiMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsiMemIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pTsiMemAlloc; ++ UINT32 ulResult; ++ UINT32 ulIndex; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check if the entry programmed is greater then the timestamp entries. */ ++ if ( f_usTsiMemIndex > cOCT6100_TSST_CONTROL_TIMESTAMP_BASE_ENTRY ) ++ ulIndex = f_usTsiMemIndex - cOCT6100_TSI_MEM_FOR_TIMESTAMP; ++ else ++ ulIndex = f_usTsiMemIndex; ++ ++ /* Check if the entry programmed is greater then the phasing TSST entries. */ ++ if ( ulIndex > cOCT6100_TSST_CONTROL_PHASING_TSST_BASE_ENTRY ) ++ ulIndex -= pSharedInfo->ChipConfig.usMaxPhasingTssts; ++ ++ mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pTsiMemAlloc, ulIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_93; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveConversionMemEntry ++ ++Description: Reserves one of the conversion memory entry ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++ ++f_pusConversionMemIndex Resulting index reserved in the conversion memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveConversionMemEntry ++UINT32 Oct6100ApiReserveConversionMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusConversionMemIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pConversionMemAlloc; ++ UINT32 ulConversionMemIndex; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pConversionMemAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pConversionMemAlloc, &ulConversionMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_MEMORY_ALL_CONVERSION_MEM_ENTRY_RESERVED; ++ else ++ return cOCT6100_ERR_FATAL_B8; ++ } ++ ++ *f_pusConversionMemIndex = (UINT16)( ulConversionMemIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseConversionMemEntry ++ ++Description: Releases the conversion chariot memory entry specified. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to ++ keep the present state of the chip and all its ++ resources. ++ ++f_usConversionMemIndex Index reserved in the conversion chariot memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseConversionMemEntry ++UINT32 Oct6100ApiReleaseConversionMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usConversionMemIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pConversionMemAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pConversionMemAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pConversionMemAlloc, f_usConversionMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_B7; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,640 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_miscellaneous.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains miscellaneous functions used in various files. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 35 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++ ++#include "apilib/octapi_largmath.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWaitForTime ++ ++Description: Waits for the specified amount of time. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_aulWaitTime[ 2 ] The amout of time to be waited. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWaitForTime ++UINT32 Oct6100ApiWaitForTime( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_aulWaitTime[ 2 ] ) ++{ ++ tOCT6100_GET_TIME StartTime; ++ tOCT6100_GET_TIME CurrentTime; ++ UINT32 aulTimeDelta[ 2 ]; ++ UINT32 ulResult; ++ UINT16 usTempVar; ++ BOOL fConditionFlag = TRUE; ++ ++ /* Copy the process context. */ ++ StartTime.pProcessContext = f_pApiInstance->pProcessContext; ++ CurrentTime.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ulResult = Oct6100UserGetTime( &StartTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ while ( fConditionFlag ) ++ { ++ ulResult = Oct6100UserGetTime( &CurrentTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = octapi_lm_subtract( ++ CurrentTime.aulWallTimeUs, 1, ++ StartTime.aulWallTimeUs, 1, ++ aulTimeDelta, 1, ++ &usTempVar ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_37; ++ ++ if ( aulTimeDelta[ 1 ] >= f_aulWaitTime[ 1 ] && ++ aulTimeDelta[ 0 ] >= f_aulWaitTime[ 0 ] ) ++ fConditionFlag = FALSE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWaitForPcRegisterBit ++ ++Description: Polls the specified PC register bit. The function exits once ++ the bit is cleared by hardware, or when the specified timeout ++ period has been expired. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulPcRegAdd Address of the register containing the PC bit. ++f_ulPcBitNum Number of the PC bit within the register. ++f_ulValue Expected value of the bit. ++f_ulTimeoutUs The timeout period, in usec. ++f_pfBitEqual Pointer to the result of the bit comparison. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWaitForPcRegisterBit ++UINT32 Oct6100ApiWaitForPcRegisterBit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulPcRegAdd, ++ IN UINT32 f_ulPcBitNum, ++ IN UINT32 f_ulValue, ++ IN UINT32 f_ulTimeoutUs, ++ OUT PBOOL f_pfBitEqual ) ++{ ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_GET_TIME StartTime; ++ tOCT6100_GET_TIME TimeoutTime; ++ tOCT6100_GET_TIME CurrentTime; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ BOOL fConditionFlag = TRUE; ++ ++ /* Copy the process context. */ ++ StartTime.pProcessContext = f_pApiInstance->pProcessContext; ++ CurrentTime.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Get the current system time. */ ++ ulResult = Oct6100UserGetTime( &StartTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Mark the bit as not being equal, for now. */ ++ *f_pfBitEqual = FALSE; ++ ++ /* Determine the time at which the timeout has expired. */ ++ ulResult = octapi_lm_add( ++ StartTime.aulWallTimeUs, 1, ++ &f_ulTimeoutUs, 0, ++ TimeoutTime.aulWallTimeUs, 1 ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Prepare read structure. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.ulReadAddress = f_ulPcRegAdd; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Read the PC bit while the timeout period hasn't expired. */ ++ while ( fConditionFlag ) ++ { ++ /* Read the current time again to check for timeout. */ ++ ulResult = Oct6100UserGetTime( &CurrentTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ulResult = Oct6100UserDriverReadApi( &ReadParams ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( ( UINT16 )((usReadData >> f_ulPcBitNum) & 0x1) == ( UINT16 )f_ulValue ) ++ { ++ /* Mark the bit as being equal. */ ++ *f_pfBitEqual = TRUE; ++ fConditionFlag = FALSE; ++ } ++ ++ if ( CurrentTime.aulWallTimeUs[ 1 ] > TimeoutTime.aulWallTimeUs[ 1 ] || ++ (CurrentTime.aulWallTimeUs[ 1 ] == TimeoutTime.aulWallTimeUs[ 1 ] && ++ CurrentTime.aulWallTimeUs[ 0 ] >= TimeoutTime.aulWallTimeUs[ 0 ]) ) ++ fConditionFlag = FALSE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReadDword ++ ++Description: Read a DWORD at specified address in external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulAddress DWORD address where to read. ++f_pulReadData Resulting data. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReadDword ++UINT32 Oct6100ApiReadDword( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulAddress, ++ OUT PUINT32 f_pulReadData ) ++{ ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT16 usReadData; ++ ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /*==================================================================================*/ ++ /* Read the first 16 bits. */ ++ ReadParams.ulReadAddress = f_ulAddress; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTempData = usReadData << 16; ++ ++ /* Read the last 16 bits. */ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTempData |= usReadData; ++ ++ /*==================================================================================*/ ++ ++ /* Return the read value.*/ ++ *f_pulReadData = ulTempData; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteDword ++ ++Description: Write a DWORD at specified address in external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulAddress DWORD address where to write. ++f_ulWriteData DWORD data to write. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteDword ++UINT32 Oct6100ApiWriteDword( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulAddress, ++ IN UINT32 f_ulWriteData ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Write the first 16 bits. */ ++ WriteParams.ulWriteAddress = f_ulAddress; ++ WriteParams.usWriteData = (UINT16)((f_ulWriteData >> 16) & 0xFFFF); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write the last word. */ ++ WriteParams.ulWriteAddress += 2; ++ WriteParams.usWriteData = (UINT16)(f_ulWriteData & 0xFFFF); ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCreateFeatureMask ++ ++Description: ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_ulFieldSize Size of the field, in bits. ++f_ulFieldBitOffset Bit offset, from the least significant bit. ++f_pulFieldMask Resulting mask. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCreateFeatureMask ++VOID Oct6100ApiCreateFeatureMask( ++ IN UINT32 f_ulFieldSize, ++ IN UINT32 f_ulFieldBitOffset, ++ OUT PUINT32 f_pulFieldMask ) ++{ ++ UINT32 ulMask; ++ UINT32 i; ++ ++ ulMask = 0; ++ ++ /* Create the mask based on the field size. */ ++ for ( i = 0; i < f_ulFieldSize; i++ ) ++ { ++ ulMask <<= 1; ++ ulMask |= 1; ++ } ++ ++ /* Once the mask is of the desired size, offset it to fit the field */ ++ /* within the DWORD read. */ ++ ulMask <<= f_ulFieldBitOffset; ++ ++ /* Return the mask. */ ++ *f_pulFieldMask = ulMask; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiStrStr ++ ++Description: OCT6100 API version of strstr() ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pszSource Source string to analyze. ++f_pszString String to look for. ++f_pszLastCharPtr Last character in the source string. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiStrStr ++unsigned char const *Oct6100ApiStrStr( ++ IN unsigned char const *f_pszSource, ++ IN unsigned char const *f_pszString, ++ IN unsigned char const *f_pszLastCharPtr ) ++{ ++ UINT32 ulCurrentPos; ++ UINT32 ulStringLength; ++ UINT32 ulNumMatchingCharFound = 0; ++ unsigned char const *pchFirstChar = NULL; ++ UINT32 ulSourceLength; ++ ++ if ( f_pszLastCharPtr < f_pszSource ) ++ return NULL; ++ ++ ulSourceLength = (UINT32)( f_pszLastCharPtr - f_pszSource ); ++ ulStringLength = Oct6100ApiStrLen( f_pszString ); ++ ++ for ( ulCurrentPos = 0; ulCurrentPos < ulSourceLength; ulCurrentPos++ ) ++ { ++ /* Check if the character matches. */ ++ if ( f_pszSource[ ulCurrentPos ] == f_pszString[ ulNumMatchingCharFound ] ) ++ { ++ if ( ulNumMatchingCharFound == 0 ) ++ pchFirstChar = ( f_pszSource + ulCurrentPos ); ++ ++ ulNumMatchingCharFound++; ++ ++ /* Check if the whole string matched. */ ++ if ( ulNumMatchingCharFound == ulStringLength ) ++ break; ++ } ++ else if ( ulNumMatchingCharFound != 0 ) ++ { ++ ulNumMatchingCharFound = 0; ++ ++ /* Reset the search, but take a look at the current character. It might */ ++ /* be the beginning of the string we are looking for. */ ++ if ( f_pszSource[ ulCurrentPos ] == f_pszString[ ulNumMatchingCharFound ] ) ++ { ++ pchFirstChar = ( f_pszSource + ulCurrentPos ); ++ ulNumMatchingCharFound++; ++ ++ /* Check if the whole string matched. */ ++ /* This check must be done in case we have the 1 character strstr */ ++ if ( ulNumMatchingCharFound == ulStringLength ) ++ break; ++ } ++ } ++ } ++ ++ if ( ulCurrentPos == ulSourceLength ) ++ return NULL; ++ else ++ return pchFirstChar; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiStrLen ++ ++Description: OCT6100 API version of strlen() ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pszString Source string to count length of. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiStrLen ++UINT32 Oct6100ApiStrLen( ++ IN unsigned char const *f_pszString ) ++{ ++ UINT32 ulCount = 0; ++ ++ while( f_pszString[ ulCount ] != '\0' ) ++ ulCount++; ++ ++ return ulCount; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAsciiToHex ++ ++Description: Convert an ASCII character to an hexadecimal value. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_chCharacter ASCII character to convert. ++f_pulValue Resulting hexadecimal value. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAsciiToHex ++UINT32 Oct6100ApiAsciiToHex( ++ IN UINT8 f_chCharacter, ++ OUT PUINT32 f_pulValue ) ++{ ++ switch ( f_chCharacter ) ++ { ++ case '0': ++ (*f_pulValue) = 0x0; ++ break; ++ case '1': ++ (*f_pulValue) = 0x1; ++ break; ++ case '2': ++ (*f_pulValue) = 0x2; ++ break; ++ case '3': ++ (*f_pulValue) = 0x3; ++ break; ++ case '4': ++ (*f_pulValue) = 0x4; ++ break; ++ case '5': ++ (*f_pulValue) = 0x5; ++ break; ++ case '6': ++ (*f_pulValue) = 0x6; ++ break; ++ case '7': ++ (*f_pulValue) = 0x7; ++ break; ++ case '8': ++ (*f_pulValue) = 0x8; ++ break; ++ case '9': ++ (*f_pulValue) = 0x9; ++ break; ++ case 'A': ++ case 'a': ++ (*f_pulValue) = 0xA; ++ break; ++ case 'B': ++ case 'b': ++ (*f_pulValue) = 0xB; ++ break; ++ case 'C': ++ case 'c': ++ (*f_pulValue) = 0xC; ++ break; ++ case 'D': ++ case 'd': ++ (*f_pulValue) = 0xD; ++ break; ++ case 'E': ++ case 'e': ++ (*f_pulValue) = 0xE; ++ break; ++ case 'F': ++ case 'f': ++ (*f_pulValue) = 0xF; ++ break; ++ default: ++ (*f_pulValue) = 0x0; ++ return cOCT6100_ERR_MISC_ASCII_CONVERSION_FAILED; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiHexToAscii ++ ++Description: Convert an hexadecimal value to an ASCII character. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_ulNumber Hexadecimal value to convert. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiHexToAscii ++UINT8 Oct6100ApiHexToAscii( ++ IN UINT32 f_ulNumber ) ++{ ++ if ( f_ulNumber >= 0xA ) ++ return (UINT8)( 55 + f_ulNumber ); /* Hex values from 0xA to 0xF */ ++ else ++ return (UINT8)( 48 + f_ulNumber ); /* Hex values from 0x0 to 0x9 */ ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRand ++ ++Description: Random number generator. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_ulRange Range of the random number to be generated. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRand ++UINT32 Oct6100ApiRand( ++ IN UINT32 f_ulRange ) ++{ ++ static UINT32 ulRandomSeed = 0x12345678; ++ UINT32 ulBit0; ++ ++ UINT32 i, j; ++ UINT16 ulWithinRange = FALSE; ++ ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT16 ulLoop; ++ ++ UINT32 ulRangeMask; ++ UINT32 ulAddedValue; ++ ++ ++ ulRangeMask = 1; ++ ulLoop = TRUE; ++ i = 1; ++ ++ while ( ulLoop ) ++ { ++ ++ ulAddedValue = 2; ++ for ( j = 1; j < i; j++ ) ++ ulAddedValue *= 2; ++ ++ ulRangeMask = ulRangeMask + ulAddedValue; ++ ++ if ( ulRangeMask >= f_ulRange ) ++ ulLoop = FALSE; ++ ++ i++; ++ } ++ ++ while ( !ulWithinRange ) ++ { ++ ulBit0 = ((ulRandomSeed >> 19) & 0x1) ^ ((ulRandomSeed >> 16) & 0x1); ++ ulRandomSeed = ((ulRandomSeed << 1) & 0xFFFFF) | ulBit0; ++ ++ ulResult = ulRandomSeed & ulRangeMask; ++ ++ if ( ulResult <= f_ulRange ) ++ ulWithinRange = TRUE; ++ } ++ ++ return ulResult; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1586 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_mixer.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the functions used to manage the allocation of mixer ++ blocks in memories. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 42 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_mixer_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_mixer_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_mixer_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100MixerCopyEventCreate ++ ++Description: This function creates a mixer copy event used to copy ++ information from one channel port to another channel port. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pCopyEventCreate Pointer to a mixer copy event structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100MixerCopyEventCreateDef ++UINT32 Oct6100MixerCopyEventCreateDef( ++ tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate ) ++{ ++ f_pCopyEventCreate->pulCopyEventHndl = NULL; ++ ++ f_pCopyEventCreate->ulSourceChanHndl = cOCT6100_INVALID_HANDLE; ++ f_pCopyEventCreate->ulSourcePort = cOCT6100_INVALID_PORT; ++ ++ f_pCopyEventCreate->ulDestinationChanHndl = cOCT6100_INVALID_HANDLE; ++ f_pCopyEventCreate->ulDestinationPort = cOCT6100_INVALID_PORT; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100MixerCopyEventCreate ++UINT32 Oct6100MixerCopyEventCreate( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100MixerCopyEventCreateSer( f_pApiInstance, f_pCopyEventCreate ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100MixerCopyEventDestroy ++ ++Description: This function destroys a mixer copy event used to copy ++ information from one channel port to another. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pCopyEventDestroy Pointer to a destroy copy event structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100MixerCopyEventDestroyDef ++UINT32 Oct6100MixerCopyEventDestroyDef( ++ tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy ) ++{ ++ f_pCopyEventDestroy->ulCopyEventHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100MixerCopyEventDestroy ++UINT32 Oct6100MixerCopyEventDestroy( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100MixerCopyEventDestroySer( f_pApiInstance, f_pCopyEventDestroy ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetMixerSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of mixer events. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pOpenChip User chip configuration. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetMixerSwSizes ++UINT32 Oct6100ApiGetMixerSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Calculate the API memory required for the resource entry lists. */ ++ f_pInstSizes->ulMixerEventList = cOCT6100_MAX_MIXER_EVENTS * sizeof( tOCT6100_API_MIXER_EVENT ); ++ ++ /* Calculate memory needed for mixers entry allocation. */ ++ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_MIXER_EVENTS, &f_pInstSizes->ulMixerEventAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1D; ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulMixerEventList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulMixerEventAlloc, ulTempVar ) ++ ++ ++ f_pInstSizes->ulCopyEventList = cOCT6100_MAX_MIXER_EVENTS * sizeof( tOCT6100_API_COPY_EVENT ); ++ ++ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_MIXER_EVENTS, &f_pInstSizes->ulCopyEventAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1D; ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulCopyEventList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulCopyEventAlloc, ulTempVar ) ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiMixerSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to the mixer events. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This mixer is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiMixerSwInit ++UINT32 Oct6100ApiMixerSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_MIXER_EVENT pMixerEventList; ++ PVOID pMixerEventAlloc; ++ PVOID pCopyEventAlloc; ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /*===================================================================*/ ++ /* Initialize the mixer event list. */ ++ mOCT6100_GET_MIXER_EVENT_LIST_PNT( pSharedInfo, pMixerEventList ); ++ ++ /* Initialize the mixer event allocation software to "all free". */ ++ Oct6100UserMemSet( pMixerEventList, 0x00, cOCT6100_MAX_MIXER_EVENTS * sizeof( tOCT6100_API_MIXER_EVENT )); ++ ++ mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( pSharedInfo, pMixerEventAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pMixerEventAlloc, cOCT6100_MAX_MIXER_EVENTS ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_1F; ++ ++ /* Now reserve the first entry as the first node. */ ++ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulTempVar ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_20; ++ } ++ ++ /* Check that we obtain the first event. */ ++ if ( ulTempVar != 0 ) ++ return cOCT6100_ERR_FATAL_21; ++ ++ /* Now reserve the tail entry. */ ++ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulTempVar ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_AA; ++ } ++ /* Check that we obtain the first event. */ ++ if ( ulTempVar != 1 ) ++ return cOCT6100_ERR_FATAL_AB; ++ ++ /* Program the head node. */ ++ pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].fReserved = TRUE; ++ pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].usNextEventPtr = cOCT6100_MIXER_TAIL_NODE; ++ pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ /* Program the tail node. */ ++ pMixerEventList[ cOCT6100_MIXER_TAIL_NODE ].fReserved = TRUE; ++ pMixerEventList[ cOCT6100_MIXER_TAIL_NODE ].usNextEventPtr = cOCT6100_INVALID_INDEX; ++ pMixerEventList[ cOCT6100_MIXER_TAIL_NODE ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ /* Now reserve the entry used for channel recording if the feature is enabled. */ ++ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) ++ { ++ UINT32 ulAllocIndex; ++ ++ /* Reserve an entry to copy the desire SOUT signal to the SIN signal of the recording channel. */ ++ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulAllocIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_90; ++ } ++ ++ pSharedInfo->MixerInfo.usRecordCopyEventIndex = (UINT16)( ulAllocIndex & 0xFFFF ); ++ ++ /* Reserve an entry to copy the saved SIN signal of the debugged channel into it's original location. */ ++ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulAllocIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_90; ++ } ++ ++ pSharedInfo->MixerInfo.usRecordSinEventIndex = (UINT16)( ulAllocIndex & 0xFFFF ); ++ ++ /* Configure the SIN event. */ ++ pMixerEventList[ pSharedInfo->MixerInfo.usRecordSinEventIndex ].fReserved = TRUE; ++ pMixerEventList[ pSharedInfo->MixerInfo.usRecordSinEventIndex ].usNextEventPtr = cOCT6100_MIXER_TAIL_NODE; ++ pMixerEventList[ pSharedInfo->MixerInfo.usRecordSinEventIndex ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ /* Configure the SOUT copy event. */ ++ pMixerEventList[ pSharedInfo->MixerInfo.usRecordCopyEventIndex ].fReserved = TRUE; ++ pMixerEventList[ pSharedInfo->MixerInfo.usRecordCopyEventIndex ].usNextEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; ++ pMixerEventList[ pSharedInfo->MixerInfo.usRecordCopyEventIndex ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ /* Program the head node. */ ++ pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].usNextEventPtr = pSharedInfo->MixerInfo.usRecordCopyEventIndex; ++ } ++ ++ /* Initialize the copy event list. */ ++ mOCT6100_GET_COPY_EVENT_ALLOC_PNT( pSharedInfo, pCopyEventAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pCopyEventAlloc, cOCT6100_MAX_MIXER_EVENTS ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_B4; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiMixerEventAdd ++ ++Description: This function adds a mixer event event to the list of events ++ based on the event type passed to the function. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++f_usEventIndex Index of the event within the API's mixer event list. ++f_usEventType Type of mixer event. ++f_usDestinationChanIndex Index of the destination channel within the API's ++ channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiMixerEventAdd ++UINT32 Oct6100ApiMixerEventAdd( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex, ++ IN UINT16 f_usEventType, ++ IN UINT16 f_usDestinationChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_MIXER_EVENT pCurrentEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEventEntry; ++ tPOCT6100_API_CHANNEL pDestinationEntry; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ UINT16 usTempEventIndex; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Get a pointer to the event entry. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCurrentEventEntry, f_usEventIndex ); ++ ++ /* Get a pointer to the destination channel entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pDestinationEntry, f_usDestinationChanIndex ); ++ ++ /* Now proceed according to the event type. */ ++ switch ( f_usEventType ) ++ { ++ case cOCT6100_EVENT_TYPE_SOUT_COPY: ++ ++ /* Now insert the Sin copy event */ ++ if ( pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* The only node in the list before the point where the node needs to */ ++ /* be inserted is the head node. */ ++ usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ ++ /* This node will be the first one in the Sout copy section. */ ++ pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = f_usEventIndex; ++ pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = f_usEventIndex; ++ } ++ else /* pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr != cOCT6100_INVALID_INDEX */ ++ { ++ usTempEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = f_usEventIndex; ++ } ++ ++ break; ++ ++ case cOCT6100_EVENT_TYPE_SIN_COPY: ++ ++ /* Now insert the Sin copy event. */ ++ if ( pSharedInfo->MixerInfo.usFirstSinCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* This is the first Sin copy event. We must find the event that comes before */ ++ /* the event we want to add. First let's check for a bridge event. */ ++ if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* No event in the bridge section, now let's check in the Sout copy section. */ ++ if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) ++ { ++ /* The only node in the list then is the head node. */ ++ usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ usTempEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ } ++ else ++ { ++ usTempEventIndex = pSharedInfo->MixerInfo.usLastBridgeEventPtr; ++ } ++ ++ /* This node will be the first one in the Sin copy section. */ ++ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = f_usEventIndex; ++ pSharedInfo->MixerInfo.usLastSinCopyEventPtr = f_usEventIndex; ++ } ++ else /* pSharedInfo->MixerInfo.usFirstSinCopyEventPtr != cOCT6100_INVALID_INDEX */ ++ { ++ usTempEventIndex = pSharedInfo->MixerInfo.usLastSinCopyEventPtr; ++ pSharedInfo->MixerInfo.usLastSinCopyEventPtr = f_usEventIndex; ++ } ++ ++ break; ++ ++ default: ++ return cOCT6100_ERR_FATAL_AF; ++ ++ } ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); ++ ++ /*=======================================================================*/ ++ /* Program the Copy event. */ ++ ++ /* Set the Copy event first. */ ++ pCurrentEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ pCurrentEventEntry->usNextEventPtr = pTempEventEntry->usNextEventPtr; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ WriteParams.usWriteData = pCurrentEventEntry->usNextEventPtr; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Modify the previous node. */ ++ ++ /* Set the last Sub-store entry. */ ++ pTempEventEntry->usNextEventPtr = f_usEventIndex; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ WriteParams.usWriteData = f_usEventIndex; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Save the destination channel index, needed when removing the event from the mixer. */ ++ pCurrentEventEntry->usDestinationChanIndex = f_usDestinationChanIndex; ++ ++ /* Mark the entry as reserved. */ ++ pCurrentEventEntry->fReserved = TRUE; ++ ++ /* Increment the event count on that particular destination channel */ ++ pDestinationEntry->usMixerEventCnt++; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiMixerEventRemove ++ ++Description: This function removes a mixer event event from the list of events based ++ on the event type passed to the function. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usEventIndex Index of event within the API's mixer event list. ++f_usEventType Type of mixer event. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiMixerEventRemove ++UINT32 Oct6100ApiMixerEventRemove( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex, ++ IN UINT16 f_usEventType ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_MIXER_EVENT pCurrentEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEventEntry; ++ tPOCT6100_API_CHANNEL pDestinationEntry; ++ tOCT6100_WRITE_BURST_PARAMS BurstWriteParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ BOOL fFirstSinCopyEvent = FALSE; ++ UINT32 ulResult; ++ UINT16 usTempEventIndex; ++ UINT32 ulLoopCount = 0; ++ UINT16 ausWriteData[ 4 ] = { 0 }; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ BurstWriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstWriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ BurstWriteParams.pusWriteData = ausWriteData; ++ BurstWriteParams.ulWriteLength = 4; ++ ++ /* Get a pointer to the event entry. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCurrentEventEntry, f_usEventIndex ); ++ ++ /* Get the pointer to the channel entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pDestinationEntry, pCurrentEventEntry->usDestinationChanIndex ); ++ ++ /* Now proceed according to the event type. */ ++ switch ( f_usEventType ) ++ { ++ case cOCT6100_EVENT_TYPE_SOUT_COPY: ++ ++ if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr ) ++ { ++ usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ else ++ { ++ /* Now insert the Sin copy event. */ ++ usTempEventIndex = pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr; ++ } ++ ++ /* Find the copy entry before the entry to remove. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); ++ ++ while( pTempEventEntry->usNextEventPtr != f_usEventIndex ) ++ { ++ usTempEventIndex = pTempEventEntry->usNextEventPtr; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); ++ ++ ulLoopCount++; ++ if ( ulLoopCount == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_FATAL_B2; ++ } ++ ++ /*=======================================================================*/ ++ /* Update the global mixer pointers. */ ++ if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr ) ++ { ++ if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) ++ { ++ /* This event was the only of the list.*/ ++ pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = pCurrentEventEntry->usNextEventPtr; ++ } ++ } ++ else if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) ++ { ++ pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = usTempEventIndex; ++ } ++ /*=======================================================================*/ ++ ++ break; ++ ++ ++ case cOCT6100_EVENT_TYPE_SIN_COPY: ++ ++ if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSinCopyEventPtr ) ++ { ++ fFirstSinCopyEvent = TRUE; ++ ++ if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr != cOCT6100_INVALID_INDEX ) ++ { ++ usTempEventIndex = pSharedInfo->MixerInfo.usLastBridgeEventPtr; ++ } ++ else if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr != cOCT6100_INVALID_INDEX ) ++ { ++ usTempEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; ++ } ++ else ++ { ++ usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; ++ } ++ } ++ else ++ { ++ /* Now insert the Sin copy event. */ ++ usTempEventIndex = pSharedInfo->MixerInfo.usFirstSinCopyEventPtr; ++ } ++ ++ /* Find the copy entry before the entry to remove. */ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); ++ ++ /* If we are not the first event of the Sin copy list. */ ++ if ( fFirstSinCopyEvent == FALSE ) ++ { ++ while( pTempEventEntry->usNextEventPtr != f_usEventIndex ) ++ { ++ usTempEventIndex = pTempEventEntry->usNextEventPtr; ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); ++ ++ ulLoopCount++; ++ if ( ulLoopCount == cOCT6100_MAX_LOOP ) ++ return cOCT6100_ERR_FATAL_B1; ++ } ++ } ++ ++ /*=======================================================================*/ ++ /* Update the global mixer pointers. */ ++ if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSinCopyEventPtr ) ++ { ++ if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSinCopyEventPtr ) ++ { ++ /* This event was the only of the list. */ ++ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = cOCT6100_INVALID_INDEX; ++ pSharedInfo->MixerInfo.usLastSinCopyEventPtr = cOCT6100_INVALID_INDEX; ++ } ++ else ++ { ++ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = pCurrentEventEntry->usNextEventPtr; ++ } ++ } ++ else if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSinCopyEventPtr ) ++ { ++ pSharedInfo->MixerInfo.usLastSinCopyEventPtr = usTempEventIndex; ++ } ++ /*=======================================================================*/ ++ ++ break; ++ ++ default: ++ return cOCT6100_ERR_FATAL_B0; ++ ++ } ++ ++ /*=======================================================================*/ ++ /* Modify the previous event. */ ++ ++ pTempEventEntry->usNextEventPtr = pCurrentEventEntry->usNextEventPtr; ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.ulWriteAddress += 4; ++ WriteParams.usWriteData = pTempEventEntry->usNextEventPtr; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Clear the current event. */ ++ ++ BurstWriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstWriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Decrement the mixer event count active on that channel. */ ++ pDestinationEntry->usMixerEventCnt--; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ ++ /* This index of this channel is not valid anymore! */ ++ pCurrentEventEntry->usDestinationChanIndex = cOCT6100_INVALID_INDEX; ++ ++ /* Mark this entry as free. */ ++ pCurrentEventEntry->fReserved = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100MixerCopyEventCreateSer ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pCopyEventCreate Pointer to a create copy event structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100MixerCopyEventCreateSer ++UINT32 Oct6100MixerCopyEventCreateSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate ) ++{ ++ UINT16 usCopyEventIndex = 0; ++ UINT16 usMixerEventIndex = 0; ++ UINT16 usSourceChanIndex; ++ UINT16 usDestinationChanIndex; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the copy event for errors. */ ++ ulResult = Oct6100ApiCheckCopyEventCreateParams( f_pApiInstance, ++ f_pCopyEventCreate, ++ &usSourceChanIndex, ++ &usDestinationChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the copy event. */ ++ ulResult = Oct6100ApiReserveCopyEventCreateResources( f_pApiInstance, ++ &usCopyEventIndex, ++ &usMixerEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write all necessary structures to activate the echo cancellation channel. */ ++ ulResult = Oct6100ApiWriteCopyEventCreateStructs( f_pApiInstance, ++ f_pCopyEventCreate, ++ usMixerEventIndex, ++ usSourceChanIndex, ++ usDestinationChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the new echo cancellation channels's entry in the ECHO channel list. */ ++ ulResult = Oct6100ApiUpdateCopyEventCreateEntry( f_pApiInstance, ++ f_pCopyEventCreate, ++ usCopyEventIndex, ++ usMixerEventIndex, ++ usSourceChanIndex, ++ usDestinationChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckCopyEventCreateParams ++ ++Description: Checks the user's parameter passed to the create ++ copy event function. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pCopyEventCreate Pointer to a create copy event structure. ++f_pusSourceChanIndex Pointer to the index of the input channel. ++f_pusDestinationChanIndex Pointer to the index of the output channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckCopyEventCreateParams ++UINT32 Oct6100ApiCheckCopyEventCreateParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate, ++ OUT PUINT16 f_pusSourceChanIndex, ++ OUT PUINT16 f_pusDestinationChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pSourceEntry; ++ tPOCT6100_API_CHANNEL pDestinationEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Obtain shared resources pointer. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ if ( f_pCopyEventCreate->pulCopyEventHndl == NULL ) ++ return cOCT6100_ERR_MIXER_COPY_EVENT_HANDLE; ++ ++ if ( f_pCopyEventCreate->ulSourceChanHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_MIXER_SOURCE_CHAN_HANDLE; ++ if ( f_pCopyEventCreate->ulDestinationChanHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_MIXER_DESTINATION_CHAN_HANDLE; ++ ++ if ( f_pCopyEventCreate->ulSourcePort != cOCT6100_CHANNEL_PORT_RIN && ++ f_pCopyEventCreate->ulSourcePort != cOCT6100_CHANNEL_PORT_SIN ) ++ return cOCT6100_ERR_MIXER_SOURCE_PORT; ++ ++ if ( f_pCopyEventCreate->ulDestinationPort != cOCT6100_CHANNEL_PORT_RIN && ++ f_pCopyEventCreate->ulDestinationPort != cOCT6100_CHANNEL_PORT_SIN ) ++ return cOCT6100_ERR_MIXER_DESTINATION_PORT; ++ ++ /*=======================================================================*/ ++ /* Verify the first channel handle. */ ++ ++ if ( (f_pCopyEventCreate->ulSourceChanHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_MIXER_SOURCE_CHAN_HANDLE; ++ ++ *f_pusSourceChanIndex = (UINT16)( f_pCopyEventCreate->ulSourceChanHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusSourceChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_MIXER_SOURCE_CHAN_HANDLE; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSourceEntry, *f_pusSourceChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pCopyEventCreate->ulSourceChanHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pSourceEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pSourceEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_MIXER_SOURCE_CHAN_HANDLE; ++ if ( pSourceEntry->CodecConfig.byDecoderPort == f_pCopyEventCreate->ulSourcePort ) ++ return cOCT6100_ERR_MIXER_SOURCE_ADPCM_RESOURCES_ACTIVATED; ++ ++ /*=======================================================================*/ ++ ++ /*=======================================================================*/ ++ /* Verify the second channel handle. */ ++ ++ if ( (f_pCopyEventCreate->ulDestinationChanHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_MIXER_DESTINATION_CHAN_HANDLE; ++ ++ *f_pusDestinationChanIndex = (UINT16)( f_pCopyEventCreate->ulDestinationChanHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusDestinationChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_MIXER_DESTINATION_CHAN_HANDLE; ++ ++ /* Get a pointer to the channel's list entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pDestinationEntry, *f_pusDestinationChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pCopyEventCreate->ulDestinationChanHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pDestinationEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pDestinationEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_MIXER_DESTINATION_CHAN_HANDLE; ++ if ( pDestinationEntry->CodecConfig.byDecoderPort == f_pCopyEventCreate->ulDestinationPort ) ++ return cOCT6100_ERR_MIXER_DEST_ADPCM_RESOURCES_ACTIVATED; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveCopyEventCreateResources ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pusCopyEntryIndex Pointer to the index of the copy entry within the API's list. ++f_pusCopyEventIndex Pointer to the index of the mixer copy event. ++. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveCopyEventCreateResources ++UINT32 Oct6100ApiReserveCopyEventCreateResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusCopyEntryIndex, ++ IN OUT PUINT16 f_pusCopyEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 ulTempVar; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /*===============================================================================*/ ++ /* Verify and reserve the resources that might already be allocated. */ ++ ++ ulResult = Oct6100ApiReserveCopyEventEntry( f_pApiInstance, ++ f_pusCopyEntryIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Reserve the source copy event for the first channel. */ ++ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, ++ f_pusCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Reserve the Sin copy event for the first channel. */ ++ ulTempVar = Oct6100ApiReleaseCopyEventEntry ( f_pApiInstance, ++ *f_pusCopyEntryIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteCopyEventCreateStructs ++ ++Description: Performs all the required structure writes to configure the ++ new copy event ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pCopyEventCreate Pointer to a create copy event structure. ++f_usMixerEventIndex Index of the copy event within the mixer memory. ++f_usSourceChanIndex Index of the source channel within the API's channel list. ++f_usDestinationChanIndex Index of the destination channel within the API's channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteCopyEventCreateStructs ++UINT32 Oct6100ApiWriteCopyEventCreateStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate, ++ IN UINT16 f_usMixerEventIndex, ++ IN UINT16 f_usSourceChanIndex, ++ IN UINT16 f_usDestinationChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pSourceEntry; ++ tPOCT6100_API_CHANNEL pDestinationEntry; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*==============================================================================*/ ++ /* Get a pointer to the two channel entry. */ ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pSourceEntry, f_usSourceChanIndex ); ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pDestinationEntry, f_usDestinationChanIndex ); ++ ++ /*==============================================================================*/ ++ /* Configure the TSST control memory and add the Sin copy event if necessary. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usMixerEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; ++ ++ if ( f_pCopyEventCreate->ulSourcePort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ WriteParams.usWriteData |= pSourceEntry->usRinRoutTsiMemIndex; ++ WriteParams.usWriteData |= pSourceEntry->TdmConfig.byRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ } ++ else /* f_pCopyEventCreate->ulSourcePort == cOCT6100_CHANNEL_PORT_SIN */ ++ { ++ if ( pSourceEntry->usExtraSinTsiMemIndex != cOCT6100_INVALID_INDEX ) ++ { ++ WriteParams.usWriteData |= pSourceEntry->usExtraSinTsiMemIndex; ++ } ++ else ++ { ++ WriteParams.usWriteData |= pSourceEntry->usSinSoutTsiMemIndex; ++ } ++ ++ WriteParams.usWriteData |= pSourceEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ WriteParams.ulWriteAddress += 2; ++ ++ if ( f_pCopyEventCreate->ulDestinationPort == cOCT6100_CHANNEL_PORT_RIN ) ++ { ++ WriteParams.usWriteData = (UINT16)( pDestinationEntry->usRinRoutTsiMemIndex ); ++ } ++ else /* f_pCopyEventCreate->ulDestinationPort == cOCT6100_CHANNEL_PORT_SIN */ ++ { ++ WriteParams.usWriteData = (UINT16)( pDestinationEntry->usSinSoutTsiMemIndex ); ++ } ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Now insert the event into the event list. */ ++ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, ++ f_usMixerEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY, ++ f_usDestinationChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Increment the copy event count on this channel. */ ++ pDestinationEntry->usCopyEventCnt++; ++ ++ /*==============================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateCopyEventCreateEntry ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++f_pCopyEventCreate Pointer to a create copy event structure. ++f_usCopyEventIndex Index of the copy event within the API's event list. ++f_usMixerEventIndex Index of the copy event within the mixer memory. ++f_usSourceChanIndex Index of the source channel within the API's channel list. ++f_usDestinationChanIndex Index of the destination channel within the API's channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateCopyEventCreateEntry ++UINT32 Oct6100ApiUpdateCopyEventCreateEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT16 f_usMixerEventIndex, ++ IN UINT16 f_usSourceChanIndex, ++ IN UINT16 f_usDestinationChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_COPY_EVENT pCopyEventEntry; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_COPY_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, f_usCopyEventIndex ); ++ ++ /*=======================================================================*/ ++ /* Copy the channel's configuration and allocated resources. */ ++ ++ /* Save the channel info in the copy event. */ ++ pCopyEventEntry->usSourceChanIndex = f_usSourceChanIndex; ++ pCopyEventEntry->bySourcePort = (UINT8)( f_pCopyEventCreate->ulSourcePort & 0xFF ); ++ ++ pCopyEventEntry->usDestinationChanIndex = f_usDestinationChanIndex; ++ pCopyEventEntry->byDestinationPort = (UINT8)( f_pCopyEventCreate->ulDestinationPort & 0xFF ); ++ ++ pCopyEventEntry->usMixerEventIndex = f_usMixerEventIndex; ++ ++ /*=======================================================================*/ ++ ++ /* Form handle returned to user. */ ++ *f_pCopyEventCreate->pulCopyEventHndl = cOCT6100_HNDL_TAG_COPY_EVENT | (pCopyEventEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usCopyEventIndex; ++ ++ /* Finally, mark the event as used. */ ++ pCopyEventEntry->fReserved = TRUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100MixerCopyEventDestroySer ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pCopyEventDestroy Pointer to a destroy copy event structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100MixerCopyEventDestroySer ++UINT32 Oct6100MixerCopyEventDestroySer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy ) ++{ ++ UINT16 usCopyEventIndex; ++ UINT16 usMixerEventIndex; ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertCopyEventDestroyParams( f_pApiInstance, ++ f_pCopyEventDestroy, ++ &usCopyEventIndex, ++ &usMixerEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the echo cancellation channel. */ ++ ulResult = Oct6100ApiInvalidateCopyEventStructs( f_pApiInstance, ++ usCopyEventIndex, ++ usMixerEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the echo cancellation channel. */ ++ ulResult = Oct6100ApiReleaseCopyEventResources( f_pApiInstance, ++ usCopyEventIndex, ++ usMixerEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Invalidate the handle. */ ++ f_pCopyEventDestroy->ulCopyEventHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertCopyEventDestroyParams ++ ++Description: ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pCopyEventDestroy Pointer to a destroy copy event structure. ++f_pusCopyEventIndex Pointer to the index of the copy event in the API. ++f_pusMixerEventIndex Pointer to the index of the copy event in the mixer memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertCopyEventDestroyParams ++UINT32 Oct6100ApiAssertCopyEventDestroyParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy, ++ IN OUT PUINT16 f_pusCopyEventIndex, ++ IN OUT PUINT16 f_pusMixerEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_COPY_EVENT pCopyEventEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pCopyEventDestroy->ulCopyEventHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_COPY_EVENT ) ++ return cOCT6100_ERR_MIXER_COPY_EVENT_HANDLE; ++ ++ *f_pusCopyEventIndex = (UINT16)( f_pCopyEventDestroy->ulCopyEventHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusCopyEventIndex >= cOCT6100_MAX_MIXER_EVENTS ) ++ return cOCT6100_ERR_MIXER_COPY_EVENT_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ mOCT6100_GET_COPY_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, *f_pusCopyEventIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = ( f_pCopyEventDestroy->ulCopyEventHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pCopyEventEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_MIXER_EVENT_NOT_OPEN; ++ if ( ulEntryOpenCnt != pCopyEventEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_MIXER_COPY_EVENT_HANDLE; ++ ++ /*=======================================================================*/ ++ ++ /* Return the index of the associated event. */ ++ *f_pusMixerEventIndex = pCopyEventEntry->usMixerEventIndex; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidateCopyEventStructs ++ ++Description: Destroy the link between the two channels. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usCopyEventIndex Index of the copy event in the API. ++f_usMixerEventIndex Index of the copy event in the mixer memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidateCopyEventStructs ++UINT32 Oct6100ApiInvalidateCopyEventStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT16 f_usMixerEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*=======================================================================*/ ++ /* Clear the Copy event. */ ++ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usMixerEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); ++ WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ /* Remove the event from the list. */ ++ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, ++ f_usMixerEventIndex, ++ cOCT6100_EVENT_TYPE_SIN_COPY ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseCopyEventResources ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usCopyEventIndex Index of the copy event in the API. ++f_usMixerEventIndex Index of the copy event in the mixer memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseCopyEventResources ++UINT32 Oct6100ApiReleaseCopyEventResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT16 f_usMixerEventIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHANNEL pDestinationEntry; ++ tPOCT6100_API_COPY_EVENT pCopyEventEntry; ++ tPOCT6100_API_MIXER_EVENT pTempEventEntry; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_COPY_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, f_usCopyEventIndex ); ++ ++ ulResult = Oct6100ApiReleaseCopyEventEntry( f_pApiInstance, f_usCopyEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_AC; ++ ++ /* Relese the SIN copy event. */ ++ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usMixerEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_B3; ++ ++ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, f_usMixerEventIndex ); ++ ++ /* Invalidate the entry. */ ++ pTempEventEntry->fReserved = FALSE; ++ pTempEventEntry->usEventType = cOCT6100_INVALID_INDEX; ++ pTempEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pDestinationEntry, pCopyEventEntry->usDestinationChanIndex ); ++ ++ /* Decrement the copy event count on this channel. */ ++ pDestinationEntry->usCopyEventCnt--; ++ ++ /*=======================================================================*/ ++ ++ /* Mark the event entry as unused. */ ++ pCopyEventEntry->fReserved = FALSE; ++ pCopyEventEntry->byEntryOpenCnt++; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveMixerEventEntry ++ ++Description: Reserves a free entry in the mixer event list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pusEventIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveMixerEventEntry ++UINT32 Oct6100ApiReserveMixerEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusEventIndex ) ++{ ++ PVOID pMixerEventAlloc; ++ UINT32 ulResult; ++ UINT32 ulEventIndex; ++ ++ mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pMixerEventAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_MIXER_ALL_MIXER_EVENT_ENTRY_OPENED; ++ else ++ return cOCT6100_ERR_FATAL_2B; ++ } ++ ++ *f_pusEventIndex = (UINT16)( ulEventIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseMixerEventEntry ++ ++Description: Release an entry from the mixer event list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usEventIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseMixerEventEntry ++UINT32 Oct6100ApiReleaseMixerEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex ) ++{ ++ PVOID pMixerEventAlloc; ++ UINT32 ulResult; ++ ++ mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pMixerEventAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pMixerEventAlloc, f_usEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_2C; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetFreeMixerEventCnt ++ ++Description: Retrieve the number of events left in the list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pulFreeEventCnt How many events left. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetFreeMixerEventCnt ++UINT32 Oct6100ApiGetFreeMixerEventCnt( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT32 f_pulFreeEventCnt ) ++{ ++ PVOID pMixerEventAlloc; ++ UINT32 ulResult; ++ UINT32 ulAllocatedEvents; ++ UINT32 ulAvailableEvents; ++ ++ mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pMixerEventAlloc ) ++ ++ ulResult = OctapiLlmAllocInfo( pMixerEventAlloc, &ulAllocatedEvents, &ulAvailableEvents ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_E8; ++ ++ /* Return number of free events. */ ++ *f_pulFreeEventCnt = ulAvailableEvents; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveCopyEventEntry ++ ++Description: Reserves a free entry in the copy event list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pusEventIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveCopyEventEntry ++UINT32 Oct6100ApiReserveCopyEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusEventIndex ) ++{ ++ PVOID pCopyEventAlloc; ++ UINT32 ulResult; ++ UINT32 ulEventIndex; ++ ++ mOCT6100_GET_COPY_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pCopyEventAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pCopyEventAlloc, &ulEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_MIXER_ALL_COPY_EVENT_ENTRY_OPENED; ++ else ++ return cOCT6100_ERR_FATAL_AD; ++ } ++ ++ *f_pusEventIndex = (UINT16)( ulEventIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseCopyEventEntry ++ ++Description: Release an entry from the copy event list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usEventIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseCopyEventEntry ++UINT32 Oct6100ApiReleaseCopyEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex ) ++{ ++ PVOID pCopyEventAlloc; ++ UINT32 ulResult; ++ ++ mOCT6100_GET_COPY_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pCopyEventAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pCopyEventAlloc, f_usEventIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_AE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,922 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_phasing_tsst.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to open and close phasing TSSTs. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 46 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_phasing_tsst_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_phasing_tsst_pub.h" ++#include "oct6100api/oct6100_channel_inst.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_tsst_priv.h" ++#include "oct6100_phasing_tsst_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100PhasingTsstOpen ++ ++Description: This function opens a phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstOpen Pointer to phasing TSST open structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100PhasingTsstOpenDef ++UINT32 Oct6100PhasingTsstOpenDef( ++ tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ) ++{ ++ f_pPhasingTsstOpen->pulPhasingTsstHndl = NULL; ++ ++ f_pPhasingTsstOpen->ulTimeslot = cOCT6100_INVALID_TIMESLOT; ++ f_pPhasingTsstOpen->ulStream = cOCT6100_INVALID_STREAM; ++ ++ f_pPhasingTsstOpen->ulPhasingLength = 88; ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100PhasingTsstOpen ++UINT32 Oct6100PhasingTsstOpen( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100PhasingTsstOpenSer( f_pApiInstance, f_pPhasingTsstOpen ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100PhasingTsstClose ++ ++Description: This function closes a phasing TSST ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstClose Pointer to phasing TSST close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100PhasingTsstCloseDef ++UINT32 Oct6100PhasingTsstCloseDef( ++ tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose ) ++{ ++ f_pPhasingTsstClose->ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100PhasingTsstClose ++UINT32 Oct6100PhasingTsstClose( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100PhasingTsstCloseSer( f_pApiInstance, f_pPhasingTsstClose ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetPhasingTsstSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of Phasing TSSTs. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetPhasingTsstSwSizes ++UINT32 Oct6100ApiGetPhasingTsstSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Determine the amount of memory required for the API phasing TSST list. */ ++ f_pInstSizes->ulPhasingTsstList = f_pOpenChip->ulMaxPhasingTssts * sizeof( tOCT6100_API_PHASING_TSST ); ++ ++ if ( f_pOpenChip->ulMaxPhasingTssts > 0 ) ++ { ++ /* Calculate memory needed for Phasing TSST API memory allocation */ ++ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxPhasingTssts, &f_pInstSizes->ulPhasingTsstAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_38; ++ } ++ else ++ { ++ f_pInstSizes->ulPhasingTsstAlloc = 0; ++ } ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPhasingTsstList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPhasingTsstAlloc, ulTempVar ) ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiPhasingTsstSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiPhasingTsstSwInit ++UINT32 Oct6100ApiPhasingTsstSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_PHASING_TSST pPhasingTsstList; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulMaxPhasingTssts; ++ PVOID pPhasingTsstAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Initialize the phasing TSST API list. */ ++ ulMaxPhasingTssts = pSharedInfo->ChipConfig.usMaxPhasingTssts; ++ ++ /* Set all entries in the phasing TSST list to unused. */ ++ mOCT6100_GET_PHASING_TSST_LIST_PNT( pSharedInfo, pPhasingTsstList ) ++ ++ /* Clear the memory */ ++ Oct6100UserMemSet( pPhasingTsstList, 0x00, sizeof(tOCT6100_API_PHASING_TSST) * ulMaxPhasingTssts ); ++ ++ /* Initialize the phasing TSST allocation software to "all free". */ ++ if ( ulMaxPhasingTssts > 0 ) ++ { ++ mOCT6100_GET_PHASING_TSST_ALLOC_PNT( pSharedInfo, pPhasingTsstAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pPhasingTsstAlloc, ulMaxPhasingTssts ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_39; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100PhasingTsstOpenSer ++ ++Description: Opens a phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstOpen Pointer to phasing TSST open configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100PhasingTsstOpenSer ++UINT32 Oct6100PhasingTsstOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ) ++{ ++ UINT16 usPhasingIndex; ++ UINT16 usTsstIndex; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the phasing TSST for errors. */ ++ ulResult = Oct6100ApiCheckPhasingParams( f_pApiInstance, f_pPhasingTsstOpen ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the phasing TSST. */ ++ ulResult = Oct6100ApiReservePhasingResources( f_pApiInstance, f_pPhasingTsstOpen, &usPhasingIndex, &usTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write all necessary structures to activate the phasing TSST. */ ++ ulResult = Oct6100ApiWritePhasingStructs( f_pApiInstance, f_pPhasingTsstOpen, usPhasingIndex, usTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the new phasing TSST entry in the API list. */ ++ ulResult = Oct6100ApiUpdatePhasingEntry( f_pApiInstance, f_pPhasingTsstOpen, usPhasingIndex, usTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckPhasingParams ++ ++Description: Checks the user's phasing TSST open configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstOpen Pointer to phasing TSST open configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckPhasingParams ++UINT32 Oct6100ApiCheckPhasingParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ) ++{ ++ UINT32 ulResult; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPhasingTssts == 0 ) ++ return cOCT6100_ERR_PHASING_TSST_DISABLED; ++ ++ if ( f_pPhasingTsstOpen->pulPhasingTsstHndl == NULL ) ++ return cOCT6100_ERR_PHASING_TSST_INVALID_HANDLE; ++ ++ /* Check the phasing length. */ ++ if ( f_pPhasingTsstOpen->ulPhasingLength > 240 || ++ f_pPhasingTsstOpen->ulPhasingLength < 2 ) ++ return cOCT6100_ERR_PHASING_TSST_PHASING_LENGTH; ++ ++ ++ ++ /* Check the input TDM streams, timeslots component for errors. */ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ cOCT6100_NUMBER_TSSTS_1, ++ f_pPhasingTsstOpen->ulTimeslot, ++ f_pPhasingTsstOpen->ulStream, ++ cOCT6100_INPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_PHASING_TSST_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_PHASING_TSST_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReservePhasingResources ++ ++Description: Reserves all resources needed for the new phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstOpen Pointer to phasing TSST configuration structure. ++f_pusPhasingIndex Allocated entry in Phasing TSST API list. ++f_pusTsstIndex TSST memory index of the counter. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReservePhasingResources ++UINT32 Oct6100ApiReservePhasingResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen, ++ OUT PUINT16 f_pusPhasingIndex, ++ OUT PUINT16 f_pusTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ UINT32 ulTempVar; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Reserve an entry in the phasing TSST list. */ ++ ulResult = Oct6100ApiReservePhasingEntry( f_pApiInstance, ++ f_pusPhasingIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Reserve the input TSST entry. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ f_pPhasingTsstOpen->ulTimeslot, ++ f_pPhasingTsstOpen->ulStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_INPUT_TSST, ++ f_pusTsstIndex, ++ NULL ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Release the previously reserved entries. */ ++ ulTempVar = Oct6100ApiReleasePhasingEntry( f_pApiInstance, *f_pusPhasingIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ ++ return ulResult; ++ } ++ } ++ else ++ { ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWritePhasingStructs ++ ++Description: Performs all the required structure writes to configure the ++ new phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstOpen Pointer to phasing TSST configuration structure. ++f_usPhasingIndex Allocated entry in phasing TSST API list. ++f_usTsstIndex TSST memory index of the counter. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWritePhasingStructs ++UINT32 Oct6100ApiWritePhasingStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen, ++ IN UINT16 f_usPhasingIndex, ++ IN UINT16 f_usTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulPhasingTsstChariotMemIndex; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Configure the TSST control memory of the phasing TSST. */ ++ ++ /* Find the asociated entry in the chariot memory for the phasing TSST. */ ++ ulPhasingTsstChariotMemIndex = cOCT6100_TSST_CONTROL_PHASING_TSST_BASE_ENTRY + f_usPhasingIndex; ++ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( f_usTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_INPUT_TSST; ++ WriteParams.usWriteData |= ulPhasingTsstChariotMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Write the phasing length of the TSST in the ADPCM / MIXER memory. */ ++ ++ WriteParams.ulWriteAddress = cOCT6100_CONVERSION_CONTROL_PHASE_SIZE_BASE_ADD + ( f_usPhasingIndex * 2 ); ++ WriteParams.usWriteData = (UINT16)( f_pPhasingTsstOpen->ulPhasingLength ); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdatePhasingEntry ++ ++Description: Updates the new phasing TSST in the API phasing TSST list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pPhasingTsstOpen Pointer to phasing TSST open structure. ++f_usPhasingIndex Allocated entry in phasing TSST API list. ++f_usTsstIndex TSST memory index of the counter. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdatePhasingEntry ++UINT32 Oct6100ApiUpdatePhasingEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen, ++ IN UINT16 f_usPhasingIndex, ++ IN UINT16 f_usTsstIndex ) ++{ ++ tPOCT6100_API_PHASING_TSST pPhasingTsstEntry; ++ ++ /*================================================================================*/ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingTsstEntry, f_usPhasingIndex ) ++ ++ /* Copy the phasing TSST's configuration and allocated resources. */ ++ pPhasingTsstEntry->usTimeslot = (UINT16)( f_pPhasingTsstOpen->ulTimeslot & 0xFFFF ); ++ pPhasingTsstEntry->usStream = (UINT16)( f_pPhasingTsstOpen->ulStream & 0xFFFF ); ++ ++ pPhasingTsstEntry->usPhasingLength = (UINT16)( f_pPhasingTsstOpen->ulPhasingLength & 0xFFFF ); ++ ++ /* Store hardware related information. */ ++ pPhasingTsstEntry->usPhasingTsstIndex = f_usTsstIndex; ++ ++ /* Form handle returned to user. */ ++ *f_pPhasingTsstOpen->pulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingTsstEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usPhasingIndex; ++ pPhasingTsstEntry->usDependencyCnt = 0; /* Nobody is using the phasing TSST.*/ ++ ++ /* Finally, mark the phasing TSST as open. */ ++ pPhasingTsstEntry->fReserved = TRUE; ++ ++ /* Increment the number of phasing TSSTs opened. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberPhasingTssts++; ++ ++ /*================================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100PhasingTsstCloseSer ++ ++Description: Closes a phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstClose Pointer to phasing TSST close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100PhasingTsstCloseSer ++UINT32 Oct6100PhasingTsstCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose ) ++{ ++ UINT16 usPhasingIndex; ++ UINT16 usTsstIndex; ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertPhasingParams( f_pApiInstance, f_pPhasingTsstClose, &usPhasingIndex, &usTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the phasing TSST. */ ++ ulResult = Oct6100ApiInvalidatePhasingStructs( f_pApiInstance, usTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the phasing TSST. */ ++ ulResult = Oct6100ApiReleasePhasingResources( f_pApiInstance, usPhasingIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ f_pPhasingTsstClose->ulPhasingTsstHndl = cOCT6100_INVALID_VALUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertPhasingParams ++ ++Description: Validate the handle given by the user and verify the state of ++ the phasing TSST about to be closed. Also returns all ++ required information to deactivate the phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pPhasingTsstClose Pointer to phasing TSST close structure. ++f_pusPhasingIndex Index of the phasing TSST structure in the API list. ++f_pusTsstIndex Index of the entry in the TSST control memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertPhasingParams ++UINT32 Oct6100ApiAssertPhasingParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose, ++ OUT PUINT16 f_pusPhasingIndex, ++ OUT PUINT16 f_pusTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_PHASING_TSST pPhasingEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pPhasingTsstClose->ulPhasingTsstHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_PHASING_TSST ) ++ return cOCT6100_ERR_PHASING_TSST_INVALID_HANDLE; ++ ++ *f_pusPhasingIndex = (UINT16)( f_pPhasingTsstClose->ulPhasingTsstHndl & cOCT6100_HNDL_INDEX_MASK ); ++ if ( *f_pusPhasingIndex >= pSharedInfo->ChipConfig.usMaxPhasingTssts ) ++ return cOCT6100_ERR_PHASING_TSST_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the phasing TSST's list entry. */ ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingEntry, *f_pusPhasingIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pPhasingTsstClose->ulPhasingTsstHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pPhasingEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_PHASING_TSST_NOT_OPEN; ++ if ( pPhasingEntry->usDependencyCnt != 0 ) ++ return cOCT6100_ERR_PHASING_TSST_ACTIVE_DEPENDENCIES; ++ if ( ulEntryOpenCnt != pPhasingEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_PHASING_TSST_INVALID_HANDLE; ++ ++ /* Return info needed to close the phasing TSST and release all resources. */ ++ *f_pusTsstIndex = pPhasingEntry->usPhasingTsstIndex; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidatePhasingStructs ++ ++Description: Closes a phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usTsstIndex Index of the entry in the TSST control memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidatePhasingStructs ++UINT32 Oct6100ApiInvalidatePhasingStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*------------------------------------------------------------------------------*/ ++ /* Deactivate the TSST control memory. */ ++ ++ /* Set the input TSST control entry to unused. */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( f_usTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = 0x0000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*------------------------------------------------------------------------------*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleasePhasingResources ++ ++Description: Release and clear the API entry associated to the phasing TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usPhasingIndex Index of the phasing TSST in the API list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleasePhasingResources ++UINT32 Oct6100ApiReleasePhasingResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usPhasingIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_PHASING_TSST pPhasingEntry; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingEntry, f_usPhasingIndex ); ++ ++ /* Release the entry in the phasing TSST list. */ ++ ulResult = Oct6100ApiReleasePhasingEntry( f_pApiInstance, f_usPhasingIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Release the entry. */ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pPhasingEntry->usTimeslot, ++ pPhasingEntry->usStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); /* Release the TSST entry */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL; ++ } ++ } ++ else ++ { ++ return ulResult; ++ } ++ ++ /*=============================================================*/ ++ /* Update the phasing TSST's list entry. */ ++ ++ /* Mark the entry as closed. */ ++ pPhasingEntry->fReserved = FALSE; ++ pPhasingEntry->byEntryOpenCnt++; ++ ++ /* Decrement the number of phasing TSSTs opened. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberPhasingTssts--; ++ ++ /*=============================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReservePhasingEntry ++ ++Description: Reserves a phasing TSST API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pusPhasingIndex Resulting index reserved in the phasing TSST list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReservePhasingEntry ++UINT32 Oct6100ApiReservePhasingEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusPhasingIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pPhasingAlloc; ++ UINT32 ulResult; ++ UINT32 ulPhasingIndex; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_PHASING_TSST_ALLOC_PNT( pSharedInfo, pPhasingAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pPhasingAlloc, &ulPhasingIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_PHASING_TSST_ALL_ENTRIES_ARE_OPENED; ++ else ++ return cOCT6100_ERR_FATAL_3A; ++ } ++ ++ *f_pusPhasingIndex = (UINT16)( ulPhasingIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleasePhasingEntry ++ ++Description: Releases the specified phasing TSST API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usPhasingIndex Index reserved in the phasing TSST API list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleasePhasingEntry ++UINT32 Oct6100ApiReleasePhasingEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usPhasingIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pPhasingAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_PHASING_TSST_ALLOC_PNT( pSharedInfo, pPhasingAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pPhasingAlloc, f_usPhasingIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_3B; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,3337 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_playout_buf.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to manage buffer playout. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 109 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_playout_buf_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_events_pub.h" ++#include "oct6100api/oct6100_playout_buf_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_events_priv.h" ++#include "oct6100_playout_buf_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutLoad ++ ++Description: This function loads a playout buffer into external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferLoad Pointer to buffer playout load structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutLoadDef ++UINT32 Oct6100BufferPlayoutLoadDef( ++ tPOCT6100_BUFFER_LOAD f_pBufferLoad ) ++{ ++ f_pBufferLoad->pbyBufferPattern = NULL; ++ f_pBufferLoad->ulBufferSize = 128; ++ f_pBufferLoad->ulBufferPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ f_pBufferLoad->pulBufferIndex = NULL; ++ f_pBufferLoad->pulPlayoutFreeMemSize = NULL; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100BufferPlayoutLoad ++UINT32 Oct6100BufferPlayoutLoad( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_LOAD f_pBufferLoad ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferLoadSer( f_pApiInstance, f_pBufferLoad, TRUE, cOCT6100_INVALID_INDEX ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutLoadBlockInit ++ ++Description: This function allows the user to initialize loading a buffer ++ into external memory using blocks. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pBufferLoadBlockInit Pointer to buffer playout load block init structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutLoadBlockInitDef ++UINT32 Oct6100BufferPlayoutLoadBlockInitDef( ++ tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ) ++{ ++ f_pBufferLoadBlockInit->ulBufferSize = 128; ++ f_pBufferLoadBlockInit->ulBufferPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ f_pBufferLoadBlockInit->pulBufferIndex = NULL; ++ f_pBufferLoadBlockInit->pulPlayoutFreeMemSize = NULL; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100BufferPlayoutLoadBlockInit ++UINT32 Oct6100BufferPlayoutLoadBlockInit( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure.*/ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferLoadBlockInitSer( f_pApiInstance, f_pBufferLoadBlockInit ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutLoadBlock ++ ++Description: This function allows the user to load a buffer block into ++ external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pBufferLoadBlock Pointer to buffer playout load block structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutLoadBlockDef ++UINT32 Oct6100BufferPlayoutLoadBlockDef( ++ tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ) ++{ ++ f_pBufferLoadBlock->ulBufferIndex = cOCT6100_INVALID_VALUE; ++ f_pBufferLoadBlock->ulBlockLength = cOCT6100_INVALID_VALUE; ++ f_pBufferLoadBlock->ulBlockOffset = cOCT6100_INVALID_VALUE; ++ ++ f_pBufferLoadBlock->pbyBufferPattern = NULL; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100BufferPlayoutLoadBlock ++UINT32 Oct6100BufferPlayoutLoadBlock( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferLoadBlockSer( f_pApiInstance, f_pBufferLoadBlock ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutUnload ++ ++Description: This function unloads a playout buffer from external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferUnload Pointer to buffer playout unload structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutUnloadDef ++UINT32 Oct6100BufferPlayoutUnloadDef( ++ tPOCT6100_BUFFER_UNLOAD f_pBufferUnload ) ++{ ++ f_pBufferUnload->ulBufferIndex = cOCT6100_INVALID_VALUE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100BufferPlayoutUnload ++UINT32 Oct6100BufferPlayoutUnload( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_UNLOAD f_pBufferUnload ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferUnloadSer( f_pApiInstance, f_pBufferUnload, TRUE ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutAdd ++ ++Description: This function adds a buffer to a port's playout list on the ++ selected channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutAdd Pointer to buffer playout add structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutAddDef ++UINT32 Oct6100BufferPlayoutAddDef( ++ tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ) ++{ ++ f_pBufferPlayoutAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pBufferPlayoutAdd->ulBufferIndex = cOCT6100_INVALID_VALUE; ++ ++ f_pBufferPlayoutAdd->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ++ f_pBufferPlayoutAdd->ulMixingMode = cOCT6100_MIXING_MINUS_6_DB; ++ f_pBufferPlayoutAdd->lGainDb = 0; ++ ++ f_pBufferPlayoutAdd->fRepeat = FALSE; ++ f_pBufferPlayoutAdd->ulRepeatCount = cOCT6100_REPEAT_INFINITELY; ++ ++ f_pBufferPlayoutAdd->ulDuration = cOCT6100_INVALID_VALUE; ++ ++ f_pBufferPlayoutAdd->ulBufferLength = cOCT6100_AUTO_SELECT; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100BufferPlayoutAdd ++UINT32 Oct6100BufferPlayoutAdd( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferPlayoutAddSer( f_pApiInstance, f_pBufferPlayoutAdd ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutStart ++ ++Description: This function enables playout of the specified buffer on the ++ requested channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStart Pointer to buffer playout start structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutStartDef ++UINT32 Oct6100BufferPlayoutStartDef( ++ tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart ) ++{ ++ f_pBufferPlayoutStart->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pBufferPlayoutStart->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ++ f_pBufferPlayoutStart->fNotifyOnPlayoutStop = FALSE; ++ f_pBufferPlayoutStart->ulUserEventId = cOCT6100_INVALID_VALUE; ++ f_pBufferPlayoutStart->fAllowStartWhileActive = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100BufferPlayoutStart ++UINT32 Oct6100BufferPlayoutStart( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferPlayoutStartSer( f_pApiInstance, f_pBufferPlayoutStart, cOCT6100_BUFFER_PLAYOUT_EVENT_STOP ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutStop ++ ++Description: This function disables playout of a buffer on the specified ++ channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStop Pointer to buffer playout stop structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutStopDef ++UINT32 Oct6100BufferPlayoutStopDef( ++ tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ) ++{ ++ f_pBufferPlayoutStop->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pBufferPlayoutStop->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ++ f_pBufferPlayoutStop->fStopCleanly = TRUE; ++ f_pBufferPlayoutStop->pfAlreadyStopped = NULL; ++ f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = NULL; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100BufferPlayoutStop ++UINT32 Oct6100BufferPlayoutStop( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100BufferPlayoutStopSer( f_pApiInstance, f_pBufferPlayoutStop ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetPlayoutBufferSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of playout buffers. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetPlayoutBufferSwSizes ++UINT32 Oct6100ApiGetPlayoutBufferSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Calculate memory needed for playout buffer list. */ ++ f_pInstSizes->ulPlayoutBufList = f_pOpenChip->ulMaxPlayoutBuffers * sizeof( tOCT6100_API_BUFFER ); ++ ++ f_pInstSizes->ulPlayoutBufMemoryNodeList = 0; ++ ++ /* Calculate memory needed for playout buffer allocation software. */ ++ if ( f_pOpenChip->ulMaxPlayoutBuffers > 0 ) ++ { ++ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxPlayoutBuffers, &f_pInstSizes->ulPlayoutBufAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_3C; ++ ++ f_pInstSizes->ulPlayoutBufMemoryNodeList = 2 * f_pOpenChip->ulMaxPlayoutBuffers * sizeof( tOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE ); ++ } ++ else ++ { ++ f_pInstSizes->ulPlayoutBufAlloc = 0; ++ } ++ ++ /* Calculate memory needed for list and allocation software serialization. */ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufAlloc, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufMemoryNodeList, ulTempVar ) ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiPlayoutBufferSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to playout buffers. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiPlayoutBufferSwInit ++UINT32 Oct6100ApiPlayoutBufferSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER pBufferList; ++ PVOID pBufferPlayoutAlloc; ++ UINT32 ulMaxBufferPlayout; ++ UINT32 ulResult, i; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get the maximum number of buffer playout. */ ++ ulMaxBufferPlayout = pSharedInfo->ChipConfig.usMaxPlayoutBuffers; ++ ++ /* Set all entries in the buffer playout list to unused. */ ++ mOCT6100_GET_BUFFER_LIST_PNT( pSharedInfo, pBufferList ) ++ ++ for ( i = 0; i < ulMaxBufferPlayout; i++ ) ++ { ++ pBufferList[ i ].fReserved = FALSE; ++ pBufferList[ i ].ulBufferSize = 0; ++ pBufferList[ i ].ulBufferBase = cOCT6100_INVALID_VALUE; ++ pBufferList[ i ].usDependencyCnt = 0; ++ pBufferList[ i ].byBufferPcmLaw = cOCT6100_PCM_U_LAW; ++ ++ } ++ ++ /* Initialize the buffer playout allocation software to "all free". */ ++ if ( ulMaxBufferPlayout > 0 ) ++ { ++ mOCT6100_GET_BUFFER_ALLOC_PNT( pSharedInfo, pBufferPlayoutAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pBufferPlayoutAlloc, ulMaxBufferPlayout ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_3D; ++ } ++ ++ /* Initialize the amount of free memory used by playout. */ ++ f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed = 0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferLoadSer ++ ++Description: Loads a buffer in external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferLoad Pointer to buffer configuration structure. The handle ++ identifying the buffer in all future function calls is ++ returned in this structure. ++ ++f_fReserveListStruct Flag indicating if a list structure should be reserved ++ or if the structure has been reserved before. If this ++ is set, the f_ulBufIndex variable must also be set. ++ ++f_ulBufIndex If the f_fReserveListStruct flag is set, this index ++ will identify the buffer playout list structure ++ that must be used to load the specified buffer. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferLoadSer ++UINT32 Oct6100BufferLoadSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN BOOL f_fReserveListStruct, ++ IN UINT32 f_ulBufIndex ) ++{ ++ UINT32 ulBufferIndex; ++ UINT32 ulBufferBase; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the buffer for errors. */ ++ ulResult = Oct6100ApiCheckBufferParams( f_pApiInstance, f_pBufferLoad, TRUE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the buffer. */ ++ ulResult = Oct6100ApiReserveBufferResources( f_pApiInstance, f_pBufferLoad, f_fReserveListStruct, f_ulBufIndex, &ulBufferIndex, &ulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write the buffer in external memory. */ ++ ulResult = Oct6100ApiWriteBufferInMemory( f_pApiInstance, ulBufferBase, f_pBufferLoad->ulBufferSize, f_pBufferLoad->pbyBufferPattern ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the new buffer's entry in the buffer list. */ ++ ulResult = Oct6100ApiUpdateBufferEntry( f_pApiInstance, f_pBufferLoad, ulBufferIndex, ulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferLoadBlockInitSer ++ ++Description: Reserve resources for loading a buffer into external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pBufferLoadBlockInit Pointer to buffer configuration structure. The ++ handle identifying the buffer in all future ++ function calls is returned in this structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferLoadBlockInitSer ++UINT32 Oct6100BufferLoadBlockInitSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ) ++{ ++ UINT32 ulBufferIndex; ++ UINT32 ulBufferBase; ++ UINT32 ulResult; ++ tOCT6100_BUFFER_LOAD BufferLoad; ++ ++ Oct6100BufferPlayoutLoadDef( &BufferLoad ); ++ ++ /* Not to replicate the code, we use the BufferLoad functions directly. */ ++ BufferLoad.pulBufferIndex = f_pBufferLoadBlockInit->pulBufferIndex; ++ BufferLoad.pulPlayoutFreeMemSize = f_pBufferLoadBlockInit->pulPlayoutFreeMemSize; ++ BufferLoad.ulBufferPcmLaw = f_pBufferLoadBlockInit->ulBufferPcmLaw; ++ BufferLoad.ulBufferSize = f_pBufferLoadBlockInit->ulBufferSize; ++ BufferLoad.pbyBufferPattern = NULL; /* Must not check this for now */ ++ ++ /* Check the user's configuration of the buffer for errors, but do */ ++ /* not check if the buffer pointer is NULL. It is NULL for sure! */ ++ ulResult = Oct6100ApiCheckBufferParams( f_pApiInstance, &BufferLoad, FALSE ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the buffer. */ ++ ulResult = Oct6100ApiReserveBufferResources( f_pApiInstance, &BufferLoad, TRUE, cOCT6100_INVALID_INDEX, &ulBufferIndex, &ulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the new buffer's entry in the buffer list. */ ++ ulResult = Oct6100ApiUpdateBufferEntry( f_pApiInstance, &BufferLoad, ulBufferIndex, ulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferLoadBlockSer ++ ++Description: Loads a buffer in external memory using blocks. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pBufferLoadBlock Pointer to buffer block to be loaded into external ++ memory descriptor. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferLoadBlockSer ++UINT32 Oct6100BufferLoadBlockSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ) ++{ ++ UINT32 ulBufferBase; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration for errors. */ ++ ulResult = Oct6100ApiCheckBufferLoadBlockParams( f_pApiInstance, f_pBufferLoadBlock, &ulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write the buffer in external memory at the appropriate offset - must do some pointer arithmetic. */ ++ ulResult = Oct6100ApiWriteBufferInMemory( f_pApiInstance, ulBufferBase + f_pBufferLoadBlock->ulBlockOffset, ++ f_pBufferLoadBlock->ulBlockLength, f_pBufferLoadBlock->pbyBufferPattern + f_pBufferLoadBlock->ulBlockOffset ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBufferParams ++ ++Description: Checks the user's buffer playout load configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferLoad Pointer to buffer configuration structure. ++f_fCheckBufferPtr Check if the buffer pointer is NULL or not. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBufferParams ++UINT32 Oct6100ApiCheckBufferParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN BOOL f_fCheckBufferPtr ) ++{ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fBufferPlayout == FALSE ) ++ return cOCT6100_ERR_NOT_SUPPORTED_BUFFER_PLAYOUT; ++ ++ if ( f_pBufferLoad->pulBufferIndex == NULL ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; ++ ++ if( f_fCheckBufferPtr ) ++ { ++ if ( f_pBufferLoad->pbyBufferPattern == NULL ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_PATTERN; ++ } ++ ++ if ( f_pBufferLoad->ulBufferSize < cOCT6100_MINIMUM_BUFFER_SIZE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_TOO_SMALL; ++ ++ if ( ( f_pBufferLoad->ulBufferSize % cOCT6100_BUFFER_SIZE_GRANULARITY ) != 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; ++ ++ if ( f_pBufferLoad->ulBufferPcmLaw != cOCT6100_PCM_U_LAW && ++ f_pBufferLoad->ulBufferPcmLaw != cOCT6100_PCM_A_LAW ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_PCM_LAW; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckBufferLoadBlockParams ++ ++Description: Checks the user's buffer playout load block configuration for ++ errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferLoadBlock Pointer to buffer block descriptor. ++f_pulBufferBase Pointer to the base address of the buffer in external ++ memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckBufferLoadBlockParams ++UINT32 Oct6100ApiCheckBufferLoadBlockParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock, ++ OUT PUINT32 f_pulBufferBase ) ++{ ++ /* Check for errors. */ ++ tPOCT6100_API_BUFFER pBufEntry; ++ ++ if ( f_pBufferLoadBlock->ulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; ++ ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_pBufferLoadBlock->ulBufferIndex ) ++ ++ if ( pBufEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN; ++ ++ if ( ( f_pBufferLoadBlock->ulBlockLength % 2 ) != 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_LENGTH_INVALID; ++ ++ if ( ( f_pBufferLoadBlock->ulBlockOffset % 2 ) != 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_OFFSET_INVALID; ++ ++ if ( f_pBufferLoadBlock->pbyBufferPattern == NULL ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_PATTERN; ++ ++ /* Check boundaries */ ++ if ( ( f_pBufferLoadBlock->ulBlockLength + f_pBufferLoadBlock->ulBlockOffset ) > pBufEntry->ulBufferSize ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; ++ ++ *f_pulBufferBase = pBufEntry->ulBufferBase; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBufferResources ++ ++Description: Reserves all resources needed for the new buffer. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferLoad Pointer to buffer configuration structure. ++ ++f_fReserveListStruct Flag indicating if a list structure should be reserved ++ or if the structure has been reserved before. ++ ++f_ulBufIndex If the f_fReserveListStruct flag is set, this index ++ will identifying the buffer playout list structure ++ that must be used to load the specified buffer. ++ ++f_pulBufferIndex Allocated entry in buffer playout list. ++ ++f_pulBufferBase Allocated external memory block for the buffer. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBufferResources ++UINT32 Oct6100ApiReserveBufferResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN BOOL f_fReserveListStruct, ++ IN UINT32 f_ulBufIndex, ++ OUT PUINT32 f_pulBufferIndex, ++ OUT PUINT32 f_pulBufferBase ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 ulTempVar; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Reserve an entry in the buffer list. */ ++ if ( f_fReserveListStruct == TRUE ) ++ { ++ ulResult = Oct6100ApiReserveBufPlayoutListEntry( f_pApiInstance, f_pulBufferIndex ); ++ } ++ else ++ { ++ *f_pulBufferIndex = f_ulBufIndex; ++ } ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Find a free block to store the buffer. */ ++ ulResult = Oct6100ApiReserveBufferPlayoutMemory( f_pApiInstance, f_pBufferLoad->ulBufferSize, f_pulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Release the list entry. */ ++ if ( f_fReserveListStruct == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseBufPlayoutListEntry( f_pApiInstance, *f_pulBufferIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ } ++ } ++ ++ return ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteBufferInMemory ++ ++Description: Writes the buffer in external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulBufferBase Allocated external memory address for the buffer. ++ ++f_ulBufferLength Length in bytes of the buffer to be copied in memory. ++ ++f_pbyBuffer Address where the buffer should be copied from. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteBufferInMemory ++UINT32 Oct6100ApiWriteBufferInMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulBufferBase, ++ IN UINT32 f_ulBufferLength, ++ IN PUINT8 f_pbyBuffer ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_BURST_PARAMS BurstParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ UINT32 ulNumWrites; ++ PUINT16 pusSuperArray; ++ PUINT8 pbyPlayoutBuffer; ++ UINT32 ulByteCount = 0; ++ UINT32 i; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context and user chip ID parameters once and for all. */ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Write the buffer in external memory. */ ++ ulNumWrites = f_ulBufferLength / 2; ++ ++ BurstParams.ulWriteAddress = f_ulBufferBase; ++ BurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray; ++ ++ pusSuperArray = pSharedInfo->MiscVars.ausSuperArray; ++ pbyPlayoutBuffer = f_pbyBuffer; ++ ++ /* Check if we can maximize the bandwidth through the CPU port. */ ++ if ( f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels == 0 ) ++ { ++ WriteParams.ulWriteAddress = 0x234; ++ WriteParams.usWriteData = 0x08ff; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ while ( ulNumWrites != 0 ) ++ { ++ if ( ulNumWrites >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ BurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ++ else ++ BurstParams.ulWriteLength = ulNumWrites; ++ ++ for ( i = 0; i < BurstParams.ulWriteLength; i++ ) ++ { ++ pusSuperArray[ i ] = ( UINT16 )(( pbyPlayoutBuffer [ ulByteCount++ ]) << 8); ++ pusSuperArray[ i ] |= ( UINT16 )pbyPlayoutBuffer [ ulByteCount++ ]; ++ } ++ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ BurstParams.ulWriteAddress += 2 * BurstParams.ulWriteLength; ++ ulNumWrites -= BurstParams.ulWriteLength; ++ ++ } ++ ++ /* Make sure we revert back the changes made to the CPU bandwidth register. */ ++ if ( f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels == 0 ) ++ { ++ WriteParams.ulWriteAddress = 0x234; ++ WriteParams.usWriteData = 0x0804; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateBufferEntry ++ ++Description: Updates the new buffer's entry in the buffer playout list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pBufferLoad Pointer to buffer configuration structure. ++f_ulBufferIndex Allocated entry in buffer playout list. ++f_ulBufferBase Allocated external memory block for the buffer. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateBufferEntry ++UINT32 Oct6100ApiUpdateBufferEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN UINT32 f_ulBufferIndex, ++ IN UINT32 f_ulBufferBase ) ++{ ++ tPOCT6100_API_BUFFER pBufEntry; ++ UINT32 ulBufferSize = f_pBufferLoad->ulBufferSize; ++ ++ /* Obtain a pointer to the new buffer's list entry. */ ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_ulBufferIndex ) ++ ++ /* Copy the buffer's configuration and allocated resources. */ ++ pBufEntry->ulBufferSize = f_pBufferLoad->ulBufferSize; ++ pBufEntry->byBufferPcmLaw = (UINT8)( f_pBufferLoad->ulBufferPcmLaw & 0xFF ); ++ pBufEntry->ulBufferBase = f_ulBufferBase; ++ ++ /* Update the entries flags. */ ++ pBufEntry->usDependencyCnt = 0; ++ ++ /* Mark the buffer as opened. */ ++ pBufEntry->fReserved = TRUE; ++ ++ /* Increment the number of buffer loaded into the chip.*/ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberPlayoutBuffers++; ++ ++ /* Refresh the amount of memory used by buffer playout. */ ++ ++ /* Reserved size is divisible by 64. */ ++ if ( ulBufferSize % 64 ) ++ ulBufferSize = ulBufferSize + ( 64 - ( ulBufferSize % 64 ) ); ++ f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed += ulBufferSize; ++ ++ /* Return the buffer index to the user. */ ++ *f_pBufferLoad->pulBufferIndex = f_ulBufferIndex; ++ ++ /* Return the amount of free memory left in the chip. */ ++ /* Note that this value does not give the "fragmentation" state of the available memory. */ ++ /* This value only gives the amount of free memory */ ++ if( f_pBufferLoad->pulPlayoutFreeMemSize ) ++ *f_pBufferLoad->pulPlayoutFreeMemSize = ( f_pApiInstance->pSharedInfo->MiscVars.ulTotalMemSize - ( f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress - cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ) - ( f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferUnloadSer ++ ++Description: Unloads a buffer from external memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferUnload Pointer to buffer unload structure. ++f_fReleaseListStruct Whether to release the buffer playout list structure ++ or not. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferUnloadSer ++UINT32 Oct6100BufferUnloadSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_UNLOAD f_pBufferUnload, ++ IN BOOL f_fReleaseListStruct ) ++{ ++ UINT32 ulBufferIndex; ++ UINT32 ulBufferBase; ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertBufferParams( f_pApiInstance, f_pBufferUnload, &ulBufferIndex, &ulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the unloaded buffer. */ ++ ulResult = Oct6100ApiReleaseBufferResources( f_pApiInstance, ulBufferIndex, ulBufferBase, f_fReleaseListStruct ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertBufferParams ++ ++Description: Checks the buffer playout unload configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferUnload Pointer to buffer unload structure. ++f_pulBufferIndex Pointer to the index of the buffer in the API's buffers list. ++f_pulBufferBase Pointer to the base address of the buffer in external memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertBufferParams ++UINT32 Oct6100ApiAssertBufferParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_UNLOAD f_pBufferUnload, ++ OUT PUINT32 f_pulBufferIndex, ++ OUT PUINT32 f_pulBufferBase ) ++{ ++ tPOCT6100_API_BUFFER pBufEntry; ++ ++ *f_pulBufferIndex = f_pBufferUnload->ulBufferIndex; ++ ++ if ( *f_pulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; ++ ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, *f_pulBufferIndex ) ++ ++ /* Check for errors. */ ++ if ( pBufEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN; ++ if ( pBufEntry->usDependencyCnt != 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ACTIVE_DEPENDENCIES; ++ ++ /* Return all info needed to invalidate buffer. */ ++ *f_pulBufferBase = pBufEntry->ulBufferBase; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBufferResources ++ ++Description: Release resources needed by the buffer. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulBufferIndex Allocated entry in buffer playout list. ++f_ulBufferBase Allocated external memory block for the buffer. ++f_fReleaseListStruct Free the list structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBufferResources ++UINT32 Oct6100ApiReleaseBufferResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulBufferIndex, ++ IN UINT32 f_ulBufferBase, ++ IN BOOL f_fReleaseListStruct ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_BUFFER pBufEntry; ++ UINT32 ulResult; ++ UINT32 ulBufferSize; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Free the external memory reserved for the buffer. */ ++ ulResult = Oct6100ApiReleaseBufferPlayoutMemory( f_pApiInstance, f_ulBufferBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_3E; ++ ++ /* Release the entry from the buffer list. */ ++ if ( f_fReleaseListStruct == TRUE ) ++ ulResult = Oct6100ApiReleaseBufPlayoutListEntry( f_pApiInstance, f_ulBufferIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_ulBufferIndex ); ++ ++ /* Save buffer size before releasing that entry, will be needed to calculate the amount of */ ++ /* free memory left for the user. */ ++ ulBufferSize = pBufEntry->ulBufferSize; ++ ++ /* Flag the buffer entry as free. */ ++ pBufEntry->fReserved = FALSE; ++ ++ /* Decrement the number of buffer loaded into the chip. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberPlayoutBuffers--; ++ ++ /* Refresh the amount of memory used by buffer playout. */ ++ /* Reserved size is divisible by 64. */ ++ if ( ulBufferSize % 64 ) ++ ulBufferSize = ulBufferSize + ( 64 - ( ulBufferSize % 64 ) ); ++ f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed -= ulBufferSize; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutAddSer ++ ++Description: This function adds a buffer to a channel buffer list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutAdd Pointer to buffer playout add structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutAddSer ++UINT32 Oct6100BufferPlayoutAddSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ) ++{ ++ UINT32 ulBufferIndex; ++ UINT32 ulChannelIndex; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the buffer for errors. */ ++ ulResult = Oct6100ApiCheckPlayoutAddParams( f_pApiInstance, f_pBufferPlayoutAdd, &ulChannelIndex, &ulBufferIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write to all resources needed to activate buffer playout. */ ++ ulResult = Oct6100ApiWriteBufferAddStructs( f_pApiInstance, f_pBufferPlayoutAdd, ulChannelIndex, ulBufferIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckPlayoutAddParams ++ ++Description: Check the validity of the channel and buffer requested. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutAdd Pointer to buffer playout add structure. ++f_pulChannelIndex Pointer to the channel index of the selected channel. ++f_pulBufferIndex Pointer to the buffer index within the API's buffer list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckPlayoutAddParams ++UINT32 Oct6100ApiCheckPlayoutAddParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulBufferIndex ) ++{ ++ tPOCT6100_API_BUFFER pBufferEntry; ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; ++ ++ if ( f_pBufferPlayoutAdd->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ if ( f_pBufferPlayoutAdd->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT && ++ f_pBufferPlayoutAdd->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT; ++ ++ if ( f_pBufferPlayoutAdd->fRepeat != TRUE && f_pBufferPlayoutAdd->fRepeat != FALSE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT; ++ ++ if ( f_pBufferPlayoutAdd->fRepeat == TRUE ) ++ { ++ if ( f_pBufferPlayoutAdd->ulRepeatCount != cOCT6100_REPEAT_INFINITELY ) ++ { ++ if ( f_pBufferPlayoutAdd->ulRepeatCount == 0x0 ++ || f_pBufferPlayoutAdd->ulRepeatCount > cOCT6100_REPEAT_MAX) ++ { ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT_COUNT; ++ } ++ } ++ } ++ ++ if ( f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_0_DB && ++ f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MINUS_6_DB && ++ f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MINUS_12_DB && ++ f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MUTE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_MIXING; ++ ++ if ( ( f_pBufferPlayoutAdd->lGainDb < -24 ) ++ || ( f_pBufferPlayoutAdd->lGainDb > 24 ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_GAIN_DB; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle. */ ++ ++ if ( (f_pBufferPlayoutAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ *f_pulChannelIndex = f_pBufferPlayoutAdd->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; ++ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pBufferPlayoutAdd->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChannel->fReserved != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ /* Check if repeat flag has been used for this port. */ ++ if ( ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinBufPlayoutRepeatUsed == TRUE ) ) ++ || ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutBufPlayoutRepeatUsed == TRUE ) ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_REPEAT_USED; ++ ++ /*=====================================================================*/ ++ ++ /*=====================================================================*/ ++ /* Check the buffer information. */ ++ ++ *f_pulBufferIndex = f_pBufferPlayoutAdd->ulBufferIndex; ++ if ( *f_pulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; ++ ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, *f_pulBufferIndex ) ++ ++ if ( pBufferEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN; ++ ++ /* Check if the play length is not larger then the currently uploaded buffer. */ ++ if ( ( f_pBufferPlayoutAdd->ulBufferLength > pBufferEntry->ulBufferSize ) && ++ ( f_pBufferPlayoutAdd->ulBufferLength != cOCT6100_AUTO_SELECT ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; ++ ++ if( f_pBufferPlayoutAdd->ulBufferLength != cOCT6100_AUTO_SELECT ) ++ { ++ if ( f_pBufferPlayoutAdd->ulBufferLength < cOCT6100_MINIMUM_BUFFER_SIZE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_TOO_SMALL; ++ ++ if ( ( f_pBufferPlayoutAdd->ulBufferLength % cOCT6100_BUFFER_SIZE_GRANULARITY ) != 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; ++ } ++ ++ /*=====================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteBufferAddStructs ++ ++Description: Write the buffer playout event in the channel's port playout ++ circular buffer. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutAdd Pointer to buffer playout add structure. ++f_ulChannelIndex Index of the channel on which the buffer is to be added. ++f_ulBufferIndex Index of the buffer structure within the API's buffer list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteBufferAddStructs ++UINT32 Oct6100ApiWriteBufferAddStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulBufferIndex ) ++{ ++ tPOCT6100_API_BUFFER pBufferEntry; ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT32 ulTempData; ++ UINT32 ulEventBuffer; ++ ++ UINT32 ulReadPtrBytesOfst; ++ UINT32 ulReadPtrBitOfst; ++ UINT32 ulReadPtrFieldSize; ++ ++ UINT32 ulWritePtrBytesOfst; ++ UINT32 ulWritePtrBitOfst; ++ UINT32 ulWritePtrFieldSize; ++ ++ UINT32 ulWritePtr; ++ UINT32 ulReadPtr; ++ ++ UINT32 ulPlayoutBaseAddress; ++ UINT32 ulAddress; ++ UINT32 ulEventIndex; ++ UINT32 ulMask; ++ ++ UINT32 ulRepeatCount = 0; ++ BOOL fRepeatCountSet = FALSE; ++ UINT32 ulDurationModulo = 0; ++ UINT32 ulEventsToCreate = 1; ++ UINT32 ulBufferDurationMs; ++ ++ UINT32 ulBufferLength; ++ UINT16 usTempData = 0; ++ ++ UINT16 usReadData; ++ UINT32 ulChipWritePtr; ++ UINT32 ulReadData; ++ UINT32 ulLoopCnt = 0; ++ BOOL fStillPlaying = TRUE; ++ BOOL fCheckHardStop = FALSE; ++ BOOL fOldBufferPlayoutVersion = FALSE; ++ ++ UINT32 aulWaitTime[ 2 ]; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, f_ulBufferIndex ); ++ ++ /* Select the buffer of interest. */ ++ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst; ++ ulWritePtr = pEchoChannel->ulRinBufWritePtr; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4; ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset; ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize; ++ ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize; ++ } ++ else /* f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst; ++ ulWritePtr = pEchoChannel->ulSoutBufWritePtr; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4; ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset; ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize; ++ ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize; ++ } ++ ++ /*=======================================================================*/ ++ /* Calculate the repeat count. */ ++ ++ /* The buffer length is either the total buffer size or the value specified by the user */ ++ if ( f_pBufferPlayoutAdd->ulBufferLength == cOCT6100_AUTO_SELECT ) ++ { ++ ulBufferLength = pBufferEntry->ulBufferSize; ++ } ++ else ++ { ++ ulBufferLength = f_pBufferPlayoutAdd->ulBufferLength; ++ } ++ ++ if ( f_pBufferPlayoutAdd->ulDuration != cOCT6100_INVALID_VALUE ) ++ { ++ /* With duration and buffer length, we can find the number of times we must repeat playing this buffer. */ ++ ulBufferDurationMs = ulBufferLength / cOCT6100_SAMPLES_PER_MS; ++ ulRepeatCount = f_pBufferPlayoutAdd->ulDuration / ulBufferDurationMs; ++ fRepeatCountSet = TRUE; ++ ++ /* Check if buffer is larger then asked duration. */ ++ if ( ulRepeatCount != 0x0 ) ++ { ++ /* We might have to create more then 1 event to accomodate for the repeat-max limit. */ ++ ulEventsToCreate = ( ulRepeatCount / cOCT6100_REPEAT_MAX ) + 1; ++ } ++ else ++ { ++ /* No repeat event. Maybe only the duration modulo! */ ++ ulEventsToCreate = 0x0; ++ } ++ ++ /* Check if must create a second event for a buffer that cannot be played completely. */ ++ ulDurationModulo = f_pBufferPlayoutAdd->ulDuration % ulBufferDurationMs; ++ if ( ulDurationModulo != 0x0 ) ++ { ++ ulDurationModulo *= cOCT6100_SAMPLES_PER_MS; ++ if ( ulDurationModulo / cOCT6100_BUFFER_SIZE_GRANULARITY ) ++ { ++ /* Round the modulo to be on a buffer size granularity. */ ++ /* This will round down. */ ++ ulDurationModulo = ( ulDurationModulo / cOCT6100_BUFFER_SIZE_GRANULARITY ) * cOCT6100_BUFFER_SIZE_GRANULARITY; ++ ++ /* If the event about to be created is smaller then the minimum buffer size, */ ++ /* round up to the minimum required by the hardware. */ ++ if ( ulDurationModulo < cOCT6100_MINIMUM_BUFFER_SIZE ) ++ ulDurationModulo = cOCT6100_MINIMUM_BUFFER_SIZE; ++ ulEventsToCreate++; ++ } ++ else ++ { ++ /* The modulo is too small to be played. Skip. */ ++ ulDurationModulo = 0; ++ } ++ } ++ } ++ else if ( f_pBufferPlayoutAdd->fRepeat == TRUE ++ && f_pBufferPlayoutAdd->ulRepeatCount != cOCT6100_REPEAT_INFINITELY ) ++ { ++ /* The repeat count is set directly from the user. */ ++ ulRepeatCount = f_pBufferPlayoutAdd->ulRepeatCount; ++ fRepeatCountSet = TRUE; ++ } ++ ++ /*=======================================================================*/ ++ ++ /* Set the playout feature base address. */ ++ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ /* Read the read pointer. */ ++ ulAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; ++ ++ /* Must read in memory directly since this value is changed by hardware. */ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ulAddress, &ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); ++ ++ /* Store the read pointer. */ ++ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; ++ ++ /* Compare the pointers... Are they different? If so, there is something already in the list. */ ++ if ( ulReadPtr != ulWritePtr ) ++ { ++ /* Check if there is enough room for the playout events. */ ++ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) ++ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) ++ { ++ /* 127 or 31 events image. */ ++ if ( (UINT8)( ( ulWritePtr - ulReadPtr ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ) ) >= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - (UINT8)ulEventsToCreate ) ) ++ fCheckHardStop = TRUE; ++ } ++ else ++ { ++ /* Old 31 events image. */ ++ if ( ( ( ulWritePtr - ulReadPtr ) & 0x1F ) >= ( 0x20 - ulEventsToCreate ) ) ++ fCheckHardStop = TRUE; ++ ++ fOldBufferPlayoutVersion = TRUE; ++ } ++ ++ if ( fCheckHardStop == TRUE ) ++ { ++ /* Ok. From what was read, the list is full. But we might still have a chance if the hard-stop */ ++ /* version was used. In this case, some of the buffers in the list might */ ++ /* become free in a couple of milliseconds, so try to wait for this. */ ++ ++ if ( ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinHardStop == TRUE ) ) ++ || ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutHardStop == TRUE ) ) ) ++ { ++ /* Read the 'chip' write pointer in the hardware. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; ++ ++ /* Get the write pointer in the chip. */ ++ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst; ++ ++ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulReadData, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); ++ ++ /* Store the write pointer. */ ++ ulChipWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ while( fStillPlaying == TRUE ) ++ { ++ /* Read the read pointer until equals to the write pointer. */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); ++ ++ /* Store the read pointer.*/ ++ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; ++ ++ /* Playout has finished when the read pointer reaches the write pointer. */ ++ if ( ulReadPtr == ulChipWritePtr ) ++ break; ++ ++ ulLoopCnt++; ++ if ( ulLoopCnt > cOCT6100_MAX_LOOP ) ++ { ++ return cOCT6100_ERR_FATAL_E7; ++ } ++ ++ aulWaitTime[ 0 ] = 100; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /* Clear hard-stop flag. */ ++ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ /* No hard stop for now. */ ++ pEchoChannel->fRinHardStop = FALSE; ++ } ++ else /* if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ ++ { ++ /* No hard stop for now. */ ++ pEchoChannel->fSoutHardStop = FALSE; ++ } ++ ++ /* Now check again if the event can be added... */ ++ if ( fOldBufferPlayoutVersion == FALSE ) ++ { ++ if ( (UINT8)( ( ulWritePtr - ulReadPtr ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ) ) >= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - (UINT8)ulEventsToCreate ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL; ++ } ++ else /* if ( fOldBufferPlayoutVersion == TRUE ) */ ++ { ++ /* Old 31 events image. */ ++ if ( ( ( ulWritePtr - ulReadPtr ) & 0x1F ) >= ( 0x20 - ulEventsToCreate ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL; ++ } ++ ++ /* Good, at least another buffer can be added! Add the buffer to the list. */ ++ } ++ else ++ { ++ /* Well the list is full! */ ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL; ++ } ++ } ++ } ++ ++ /*=======================================================================*/ ++ /* Write the events. */ ++ ++ for ( ulEventIndex = 0; ulEventIndex < ulEventsToCreate; ulEventIndex ++ ) ++ { ++ /* Set the playout event base address. */ ++ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) ++ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) ++ { ++ /* 127 or 31 events image. */ ++ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + (f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * (ulWritePtr & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ))); ++ } ++ else ++ { ++ /* Old 31 events image. */ ++ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + (f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * (ulWritePtr & 0x1F)); ++ } ++ ++ /* EVENT BASE + 0 */ ++ /* Make sure the xIS and xHS bits are cleared. */ ++ ulTempData = 0; ++ ++ /* Set the repeat count. */ ++ if ( fRepeatCountSet == TRUE ) ++ { ++ if ( ( ulRepeatCount != 0x0 ) && ( ulRepeatCount <= cOCT6100_REPEAT_MAX ) ) ++ { ++ /* Use repeat count directly. */ ++ ulTempData |= ulRepeatCount; ++ ++ /* Will be used later when creating the duration modulo event. */ ++ ulRepeatCount = 0; ++ } ++ else if ( ulRepeatCount != 0x0 ) ++ { ++ /* Get ready for next event. */ ++ ulRepeatCount -= cOCT6100_REPEAT_MAX; ++ ++ /* Set maximum for this event. */ ++ ulTempData |= cOCT6100_REPEAT_MAX; ++ } ++ else ++ { ++ /* Duration modulo case. Nothing to set here. */ ++ } ++ } ++ else /* if ( fRepeatCountSet != TRUE ) */ ++ { ++ /* Repeat only once. */ ++ ulTempData |= 0x1; ++ } ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* EVENT BASE + 4 */ ++ /* Set the buffer base address and playout configuration. */ ++ ulAddress += 4; ++ ulTempData = pBufferEntry->ulBufferBase & 0x07FFFFFF; ++ ++ /* Set play indefinitely or loop N times. */ ++ if ( ( fRepeatCountSet == FALSE ) && ( f_pBufferPlayoutAdd->fRepeat == TRUE ) ) ++ { ++ /* Repeat indefinitely. */ ++ ulTempData |= 0x1 << cOCT6100_PLAYOUT_EVENT_REPEAT_OFFSET; ++ ++ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ pEchoChannel->fRinBufPlayoutRepeatUsed = TRUE; ++ else /* if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ ++ pEchoChannel->fSoutBufPlayoutRepeatUsed = TRUE; ++ } ++ ++ /* Use loop N times feature. */ ++ ulTempData |= 0x1 << cOCT6100_PLAYOUT_EVENT_LOOP_TIMES_OFFSET; ++ ++ /* Set the law.*/ ++ ulTempData |= ( pBufferEntry->byBufferPcmLaw << cOCT6100_PLAYOUT_EVENT_LAW_OFFSET ); ++ ++ /* Set the mixing configuration.*/ ++ ulTempData |= f_pBufferPlayoutAdd->ulMixingMode << cOCT6100_PLAYOUT_EVENT_MIX_OFFSET; ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ ++ /* EVENT BASE + 8 */ ++ /* Set the buffer size and playout gain. */ ++ ulAddress += 4; ++ ++ /* Check if we are setting the duration modulo. This would be the last event and this */ ++ /* event is of a very specific size. */ ++ if ( ( fRepeatCountSet == TRUE ) ++ && ( ulEventIndex == ( ulEventsToCreate - 1 ) ) ++ && ( ulDurationModulo != 0x0 ) ) ++ { ++ /* The duration modulo variable contains all that is needed here. */ ++ ulBufferLength = ulDurationModulo; ++ } ++ ulTempData = ulBufferLength; ++ ++ /* Adjust playout gain. */ ++ if ( f_pBufferPlayoutAdd->lGainDb != 0 ) ++ { ++ /* Convert the dB value into OctFloat format. */ ++ usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pBufferPlayoutAdd->lGainDb ); ++ ulTempData |= ( usTempData & 0xFF00 ) << 16; ++ } ++ else ++ { ++ ulTempData |= cOCT6100_PLAYOUT_GAIN; ++ } ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* EVENT BASE + 0xC */ ++ ulAddress += 4; ++ ulTempData = ( ulBufferLength - 1 ) & 0xFFFFFFC0; /* Must be multiple of 64 bytes */ ++ ++ /* Adjust playout gain. */ ++ if ( f_pBufferPlayoutAdd->lGainDb != 0 ) ++ { ++ ulTempData |= ( usTempData & 0xFF ) << 24; ++ } ++ ++ ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Next event. */ ++ ulWritePtr++; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Increment the write pointer to make it point to the next empty entry. */ ++ ++ if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ pEchoChannel->ulRinBufWritePtr = ( pEchoChannel->ulRinBufWritePtr + ulEventsToCreate ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ); ++ /* Remember that a buffer was added on the rin port. */ ++ pEchoChannel->fRinBufAdded = TRUE; ++ } ++ else /* f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ pEchoChannel->ulSoutBufWritePtr = ( pEchoChannel->ulSoutBufWritePtr + ulEventsToCreate ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ); ++ /* Remember that a buffer was added on the sout port. */ ++ pEchoChannel->fSoutBufAdded = TRUE; ++ } ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutStartSer ++ ++Description: Starts buffer playout on a channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStart Pointer to buffer playout start structure. ++ ++f_ulPlayoutStopEventType Playout stop event type to be generated if required. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutStartSer ++UINT32 Oct6100BufferPlayoutStartSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, ++ IN UINT32 f_ulPlayoutStopEventType ) ++{ ++ UINT32 ulBufferIndex = 0; ++ UINT32 ulChannelIndex; ++ BOOL fNotifyOnPlayoutStop; ++ UINT32 ulUserEventId; ++ BOOL fAddToCurrentlyPlayingList; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the buffer for errors. */ ++ ulResult = Oct6100ApiCheckPlayoutStartParams( f_pApiInstance, f_pBufferPlayoutStart, &ulChannelIndex, &ulBufferIndex, &fNotifyOnPlayoutStop, &ulUserEventId, &fAddToCurrentlyPlayingList ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write to all resources needed to activate buffer playout. */ ++ ulResult = Oct6100ApiWriteChanPlayoutStructs( f_pApiInstance, f_pBufferPlayoutStart, ulChannelIndex, ulBufferIndex, fNotifyOnPlayoutStop, ulUserEventId, fAddToCurrentlyPlayingList, f_ulPlayoutStopEventType ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckPlayoutStartParams ++ ++Description: Check the validity of the channel and buffer requested. ++ Check the validity of the flags requested. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStart Pointer to buffer playout start structure. ++f_pulChannelIndex Pointer to the channel index of the selected channel. ++f_pulBufferIndex Pointer to the buffer index within the API's buffer list. ++f_pfNotifyOnPlayoutStop Pointer to the notify on playout stop flag. ++f_pulUserEventId Pointer to the user event id specified. ++f_pfAllowStartIfActive Pointer to the add to currently playing list flag. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckPlayoutStartParams ++UINT32 Oct6100ApiCheckPlayoutStartParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulBufferIndex, ++ OUT PBOOL f_pfNotifyOnPlayoutStop, ++ OUT PUINT32 f_pulUserEventId, ++ OUT PBOOL f_pfAllowStartIfActive ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; ++ ++ if ( f_pBufferPlayoutStart->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ if ( f_pBufferPlayoutStart->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT && ++ f_pBufferPlayoutStart->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT; ++ ++ if ( f_pBufferPlayoutStart->fNotifyOnPlayoutStop != FALSE ++ && f_pBufferPlayoutStart->fNotifyOnPlayoutStop != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NOTIFY_ON_STOP; ++ ++ if ( f_pBufferPlayoutStart->fAllowStartWhileActive != FALSE ++ && f_pBufferPlayoutStart->fAllowStartWhileActive != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ALLOW_ACTIVE; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle. */ ++ ++ if ( (f_pBufferPlayoutStart->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ *f_pulChannelIndex = f_pBufferPlayoutStart->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; ++ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pBufferPlayoutStart->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChannel->fReserved != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ /* The channel cannot be in POWER_DOWN or HT_FREEZE to start the playout. */ ++ if ( ( pEchoChannel->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN ) ++ || ( pEchoChannel->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_HT_FREEZE ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ECHO_OP_MODE; ++ ++ /* The channel's NLP must be enabled for playout to occur. */ ++ if ( pEchoChannel->VqeConfig.fEnableNlp == FALSE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NLP_DISABLED; ++ ++ /*=====================================================================*/ ++ ++ /*=====================================================================*/ ++ /* Check if the user activated the buffer playout events. */ ++ ++ if ( f_pBufferPlayoutStart->fNotifyOnPlayoutStop == TRUE ++ && f_pApiInstance->pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize == 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_DISABLED; ++ ++ /*=====================================================================*/ ++ ++ /*=====================================================================*/ ++ /* Check if there is actually a buffer added in the list. */ ++ ++ if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ if ( pEchoChannel->fRinBufAdded == FALSE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_LIST_EMPTY; ++ } ++ else /* if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ ++ { ++ if ( pEchoChannel->fSoutBufAdded == FALSE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_LIST_EMPTY; ++ } ++ ++ /*=====================================================================*/ ++ ++ /* Return the requested information. */ ++ *f_pfNotifyOnPlayoutStop = f_pBufferPlayoutStart->fNotifyOnPlayoutStop; ++ *f_pulUserEventId = f_pBufferPlayoutStart->ulUserEventId; ++ *f_pfAllowStartIfActive = f_pBufferPlayoutStart->fAllowStartWhileActive; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteChanPlayoutStructs ++ ++Description: Write the buffer playout event in the channel main structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStart Pointer to buffer playout start structure. ++f_ulChannelIndex Index of the channel within the API's channel list. ++f_ulBufferIndex Index of the buffer within the API's buffer list. ++f_fNotifyOnPlayoutStop Flag for the notify on playout stop. ++f_ulUserEventId User event id passed to the user when a playout event is generated. ++f_fAllowStartIfActive Add to currently playing list flag. ++f_ulPlayoutStopEventType Playout stop event type to be generated if required. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteChanPlayoutStructs ++UINT32 Oct6100ApiWriteChanPlayoutStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulBufferIndex, ++ IN BOOL f_fNotifyOnPlayoutStop, ++ IN UINT32 f_ulUserEventId, ++ IN BOOL f_fAllowStartIfActive, ++ IN UINT32 f_ulPlayoutStopEventType ) ++{ ++ tPOCT6100_API_BUFFER pBufferEntry; ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ ++ UINT32 ulResult; ++ ++ UINT32 ulWritePtr; ++ UINT32 ulChipWritePtr; ++ PUINT32 pulSkipPtr; ++ UINT32 ulWritePtrBytesOfst; ++ UINT32 ulSkipPtrBytesOfst; ++ UINT32 ulWritePtrBitOfst; ++ UINT32 ulSkipPtrBitOfst; ++ UINT32 ulWritePtrFieldSize; ++ UINT32 ulSkipPtrFieldSize; ++ ++ UINT32 ulIgnoreBytesOfst; ++ UINT32 ulIgnoreBitOfst; ++ UINT32 ulIgnoreFieldSize; ++ ++ UINT32 ulHardSkipBytesOfst; ++ UINT32 ulHardSkipBitOfst; ++ UINT32 ulHardSkipFieldSize; ++ ++ UINT32 ulReadPtrBytesOfst; ++ UINT32 ulReadPtrBitOfst; ++ UINT32 ulReadPtrFieldSize; ++ ++ UINT32 ulPlayoutBaseAddress; ++ UINT32 ulAddress; ++ UINT32 ulTempData; ++ UINT32 ulMask; ++ UINT32 ulReadData; ++ UINT32 ulReadPtr; ++ UINT32 ulLoopCnt = 0; ++ ++ UINT16 usReadData; ++ ++ BOOL fBufferPlayoutStopDetected; ++ BOOL fWriteSkipPtr = FALSE; ++ BOOL fStillPlaying = TRUE; ++ ++ UINT32 aulWaitTime[ 2 ]; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); ++ mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, f_ulBufferIndex ); ++ ++ /* First off, check for buffer playout events, if requested for this channel/port. */ ++ /* At the same time, if requested, check that the playout has stopped for this channel/port. */ ++ if ( ( ( pEchoChannel->fRinBufPlaying == TRUE ) ++ && ( ( pEchoChannel->fRinBufPlayoutNotifyOnStop == TRUE ) || ( f_fAllowStartIfActive == FALSE ) ) ++ && ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ) ++ || ( ( ( pEchoChannel->fSoutBufPlaying == TRUE ) || ( f_fAllowStartIfActive == FALSE ) ) ++ && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == TRUE ) ++ && ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) ) ) ++ { ++ /* Buffer playout might still be going on for this channel/port. */ ++ ulResult = Oct6100BufferPlayoutCheckForSpecificEvent( f_pApiInstance, ++ f_ulChannelIndex, ++ f_pBufferPlayoutStart->ulPlayoutPort, ++ pEchoChannel->fRinBufPlayoutNotifyOnStop, ++ &fBufferPlayoutStopDetected ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check if the user requested to only start if playout is over. Return an error if */ ++ /* buffer playout is still going on on this channel/port. */ ++ if ( ( f_fAllowStartIfActive == FALSE ) && ( fBufferPlayoutStopDetected == FALSE ) ) ++ { ++ /* No go! User should wait for the current list to stop, or call the */ ++ /* Oct6100BufferPlayoutStop function. */ ++ return cOCT6100_ERR_BUFFER_PLAYOUT_STILL_ACTIVE; ++ } ++ } ++ ++ /* Select the buffer of interest. */ ++ if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ ulWritePtr = pEchoChannel->ulRinBufWritePtr; ++ pulSkipPtr = &pEchoChannel->ulRinBufSkipPtr; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4; ++ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.usDwordOffset * 4; ++ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.usDwordOffset * 4; ++ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.usDwordOffset * 4; ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4; ++ ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset; ++ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byBitOffset; ++ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byBitOffset; ++ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byBitOffset; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset; ++ ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize; ++ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byFieldSize; ++ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byFieldSize; ++ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byFieldSize; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize; ++ } ++ else /* f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ ulWritePtr = pEchoChannel->ulSoutBufWritePtr; ++ pulSkipPtr = &pEchoChannel->ulSoutBufSkipPtr; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4; ++ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.usDwordOffset * 4; ++ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.usDwordOffset * 4; ++ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.usDwordOffset * 4; ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4; ++ ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset; ++ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byBitOffset; ++ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byBitOffset; ++ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byBitOffset; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset; ++ ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize; ++ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byFieldSize; ++ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byFieldSize; ++ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byFieldSize; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize; ++ } ++ ++ ++ ++ /* Set the playout feature base address. */ ++ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ /* Check if we must wait for stop to complete before starting a new list. */ ++ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) ++ { ++ if ( ( ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinHardStop == TRUE ) ) ++ || ( ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutHardStop == TRUE ) ) ) ++ { ++ /* Read the read pointer. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; ++ ++ /* Get the write pointer in the chip. */ ++ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst; ++ ++ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulReadData, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); ++ ++ /* Store the write pointer. */ ++ ulChipWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ while( fStillPlaying == TRUE ) ++ { ++ /* Read the read pointer until equals to the write pointer. */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); ++ ++ /* Store the read pointer. */ ++ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; ++ ++ /* Playout has finished when the read pointer reaches the write pointer. */ ++ if ( ulReadPtr == ulChipWritePtr ) ++ break; ++ ++ ulLoopCnt++; ++ if( ulLoopCnt > cOCT6100_MAX_LOOP ) ++ { ++ return cOCT6100_ERR_FATAL_E6; ++ } ++ ++ aulWaitTime[ 0 ] = 100; ++ aulWaitTime[ 1 ] = 0; ++ ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ ++ /* Check if must clear the skip bit. */ ++ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) ++ { ++ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) ++ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) ++ { ++ /* Make sure the skip bit is cleared to start playout! */ ++ ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst; ++ ++ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask ); ++ ++ /* Cleared! */ ++ ulTempData &= ( ~ulMask ); ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Make sure the hard skip bit is cleared to start playout! */ ++ ulAddress = ulPlayoutBaseAddress + ulHardSkipBytesOfst; ++ ++ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ &ulTempData, ++ ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulHardSkipBitOfst, &ulMask ); ++ ++ /* Cleared! */ ++ ulTempData &= ( ~ulMask ); ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Write the skip and write pointer to activate buffer playout. */ ++ ++ /* Update the skip pointer. */ ++ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == FALSE ) ++ || ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == FALSE ) ) ++ { ++ /* Old 31 events image. */ ++ if ( ( ( ulWritePtr - *pulSkipPtr ) & 0x7F ) > 63 ) ++ { ++ *pulSkipPtr = ( ulWritePtr - 63 ) & 0x7F; ++ fWriteSkipPtr = TRUE; ++ } ++ } ++ else ++ { ++ /* No need to update the skip pointer, a bit needs to be set when skipping. */ ++ /* fWriteSkipPtr set to FALSE from variable declaration. */ ++ } ++ ++ if ( fWriteSkipPtr == TRUE ) ++ { ++ /*=======================================================================*/ ++ /* Fetch and modify the skip pointer. */ ++ ++ ulAddress = ulPlayoutBaseAddress + ulSkipPtrBytesOfst; ++ ++ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ &ulTempData, ++ ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulSkipPtrFieldSize, ulSkipPtrBitOfst, &ulMask ); ++ ++ ulTempData &= ( ~ulMask ); ++ ulTempData |= *pulSkipPtr << ulSkipPtrBitOfst; ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ } ++ ++ ++ /*=======================================================================*/ ++ /* Fetch and modify the write pointer. */ ++ ++ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst; ++ ++ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ &ulTempData, ++ ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); ++ ++ ulTempData &= ( ~ulMask ); ++ ulTempData |= ulWritePtr << ulWritePtrBitOfst; ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Now update the state of the channel stating that the buffer playout is activated. */ ++ ++ /* Select the buffer of interest.*/ ++ if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ /* Check if the global ports active stat must be incremented. */ ++ if ( pEchoChannel->fRinBufPlaying == FALSE ) ++ { ++ /* Increment the number of active buffer playout ports. */ ++ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts++; ++ } ++ ++ pEchoChannel->fRinBufPlaying = TRUE; ++ /* Keep the new notify on event flag. */ ++ pEchoChannel->fRinBufPlayoutNotifyOnStop = (UINT8)( f_fNotifyOnPlayoutStop & 0xFF ); ++ /* Keep the specified user event id. */ ++ pEchoChannel->ulRinUserBufPlayoutEventId = f_ulUserEventId; ++ /* Keep type of event to be generated. */ ++ pEchoChannel->byRinPlayoutStopEventType = (UINT8)( f_ulPlayoutStopEventType & 0xFF ); ++ /* No hard stop for now. */ ++ pEchoChannel->fRinHardStop = FALSE; ++ /* No buffer added in the rin list for now. */ ++ pEchoChannel->fRinBufAdded = FALSE; ++ /* Buffer playout is active on this channel. */ ++ pEchoChannel->fBufPlayoutActive = TRUE; ++ } ++ else /* f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ /* Check if the global ports active stat must be incremented. */ ++ if ( pEchoChannel->fSoutBufPlaying == FALSE ) ++ { ++ /* Increment the number of active buffer playout ports. */ ++ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts++; ++ } ++ ++ pEchoChannel->fSoutBufPlaying = TRUE; ++ /* Keep the new notify on event flag. */ ++ pEchoChannel->fSoutBufPlayoutNotifyOnStop = (UINT8)( f_fNotifyOnPlayoutStop & 0xFF ); ++ /* Keep the specified user event id. */ ++ pEchoChannel->ulSoutUserBufPlayoutEventId = f_ulUserEventId; ++ /* Keep type of event to be generated. */ ++ pEchoChannel->bySoutPlayoutStopEventType = (UINT8)( f_ulPlayoutStopEventType & 0xFF ); ++ /* No hard stop for now. */ ++ pEchoChannel->fSoutHardStop = FALSE; ++ /* No buffer added in the sout list for now. */ ++ pEchoChannel->fSoutBufAdded = FALSE; ++ /* Buffer playout is active on this channel. */ ++ pEchoChannel->fBufPlayoutActive = TRUE; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100BufferPlayoutStopSer ++ ++Description: Stops buffer playout on a channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStop Pointer to buffer playout stop structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100BufferPlayoutStopSer ++UINT32 Oct6100BufferPlayoutStopSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ) ++{ ++ UINT32 ulChannelIndex; ++ UINT16 usEchoMemIndex; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the buffer for errors. */ ++ ulResult = Oct6100ApiAssertPlayoutStopParams( ++ f_pApiInstance, ++ f_pBufferPlayoutStop, ++ &ulChannelIndex, ++ &usEchoMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write to all resources needed to deactivate buffer playout. */ ++ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( ++ f_pApiInstance, ++ f_pBufferPlayoutStop, ++ ulChannelIndex, ++ usEchoMemIndex ++ ++ ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertPlayoutStopParams ++ ++Description: Check the validity of the channel and buffer requested. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStop Pointer to buffer playout stop structure. ++f_pulChannelIndex Pointer to the channel index on which playout is to be stopped. ++f_pusEchoMemIndex Pointer to the echo mem index on which playout is to be stopped. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertPlayoutStopParams ++UINT32 Oct6100ApiAssertPlayoutStopParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT16 f_pusEchoMemIndex ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; ++ ++ if ( f_pBufferPlayoutStop->ulChannelHndl == cOCT6100_INVALID_HANDLE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ if ( f_pBufferPlayoutStop->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT && ++ f_pBufferPlayoutStop->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT; ++ ++ if ( f_pBufferPlayoutStop->fStopCleanly != TRUE && f_pBufferPlayoutStop->fStopCleanly != FALSE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_STOP_CLEANLY; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle. */ ++ ++ if ( (f_pBufferPlayoutStop->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ *f_pulChannelIndex = f_pBufferPlayoutStop->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; ++ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pBufferPlayoutStop->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChannel->fReserved != TRUE ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; ++ ++ /* Return echo memory index. */ ++ *f_pusEchoMemIndex = pEchoChannel->usEchoMemIndex; ++ ++ /* Check if buffer playout is active for the selected port. */ ++ if ( ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ && ( pEchoChannel->fRinBufPlaying == FALSE ) ++ && ( pEchoChannel->fRinBufAdded == FALSE ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_STARTED; ++ ++ if ( ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) ++ && ( pEchoChannel->fSoutBufPlaying == FALSE ) ++ && ( pEchoChannel->fSoutBufAdded == FALSE ) ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_STARTED; ++ ++ /*=====================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidateChanPlayoutStructs ++ ++Description: Write the buffer playout event in the channel main structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pBufferPlayoutStop Pointer to buffer playout stop structure. ++f_ulChannelIndex Index of the channel within the API's channel list. ++f_usEchoMemIndex Index of the echo channel in hardware memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidateChanPlayoutStructs ++UINT32 Oct6100ApiInvalidateChanPlayoutStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT16 f_usEchoMemIndex ++ ++ ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ ++ UINT32 ulResult; ++ ++ UINT32 ulWritePtrBytesOfst; ++ UINT32 ulWritePtrBitOfst; ++ UINT32 ulWritePtrFieldSize; ++ UINT32 ulSkipPtrBytesOfst; ++ UINT32 ulSkipPtrBitOfst; ++ UINT32 ulSkipPtrFieldSize; ++ UINT32 ulIgnoreBytesOfst; ++ UINT32 ulIgnoreBitOfst; ++ UINT32 ulIgnoreFieldSize; ++ UINT32 ulHardSkipBytesOfst; ++ UINT32 ulHardSkipBitOfst; ++ UINT32 ulHardSkipFieldSize; ++ UINT32 ulReadPtrBytesOfst; ++ UINT32 ulReadPtrBitOfst; ++ UINT32 ulReadPtrFieldSize; ++ ++ UINT32 ulSkipPtr; ++ UINT32 ulWritePtr; ++ UINT32 ulReadPtr = 0; ++ UINT32 ulCurrentPtr; ++ ++ UINT32 ulPlayoutBaseAddress; ++ UINT32 ulAddress; ++ UINT32 ulTempData; ++ UINT32 ulMask; ++ UINT32 ulReadData; ++ ++ UINT16 usReadData; ++ BOOL fCheckStop = FALSE; ++ ++ UINT32 ulEventBuffer; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); ++ ++ /* Select the port of interest. */ ++ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ ulWritePtr = pEchoChannel->ulRinBufWritePtr; ++ ulSkipPtr = ulWritePtr; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4; ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset; ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize; ++ ++ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.usDwordOffset * 4; ++ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byBitOffset; ++ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byFieldSize; ++ ++ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.usDwordOffset * 4; ++ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byBitOffset; ++ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byFieldSize; ++ ++ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.usDwordOffset * 4; ++ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byBitOffset; ++ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byFieldSize; ++ ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize; ++ } ++ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ ulWritePtr = pEchoChannel->ulSoutBufWritePtr; ++ ulSkipPtr = ulWritePtr; ++ ++ ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4; ++ ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset; ++ ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize; ++ ++ ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.usDwordOffset * 4; ++ ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byBitOffset; ++ ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byFieldSize; ++ ++ ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.usDwordOffset * 4; ++ ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byBitOffset; ++ ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byFieldSize; ++ ++ ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.usDwordOffset * 4; ++ ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byBitOffset; ++ ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byFieldSize; ++ ++ ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4; ++ ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset; ++ ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize; ++ } ++ ++ /* Set the playout feature base address. */ ++ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ++ ++ /* Check if something is currently playing. */ ++ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ if ( pEchoChannel->fRinBufPlaying == TRUE ) ++ { ++ /* Check if we are stopping it or if it stopped by itself. */ ++ fCheckStop = TRUE; ++ } ++ else ++ { ++ /* Not playing! */ ++ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL ) ++ *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE; ++ } ++ } ++ else /* if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ ++ { ++ if ( pEchoChannel->fSoutBufPlaying == TRUE ) ++ { ++ /* Check if we are stopping it or if it stopped by itself. */ ++ fCheckStop = TRUE; ++ } ++ else ++ { ++ /* Not playing! */ ++ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL ) ++ *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE; ++ } ++ } ++ ++ if ( ( fCheckStop == TRUE ) || ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) ) ++ { ++ /* Read the read pointer. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; ++ ++ /* Optimize this access by only reading the word we are interested in. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ReadParams.ulReadAddress += 2; ++ ++ /* Must read in memory directly since this value is changed by hardware */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Move data at correct position according to what was read. */ ++ if ( ulReadPtrBitOfst < 16 ) ++ ulTempData = usReadData; ++ else ++ ulTempData = usReadData << 16; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); ++ ++ /* Store the read pointer. */ ++ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; ++ ++ /* Playout has finished when the read pointer reaches the write pointer. */ ++ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL ) ++ { ++ if ( ulReadPtr != ulWritePtr ) ++ *f_pBufferPlayoutStop->pfAlreadyStopped = FALSE; ++ else /* if ( ulReadPtr == ulWritePtr ) */ ++ *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE; ++ } ++ } ++ ++ /* If the skip bits are located in the event itself, the playout is stopped by setting the */ ++ /* skip pointer to the hardware chip write pointer. Read it directly from the NLP configuration. */ ++ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) ++ { ++ if ( ulReadPtr != ulWritePtr ) ++ { ++ /* Get the write pointer in the chip. */ ++ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, pEchoChannel, ulAddress, &ulReadData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); ++ ++ /* Store the write pointer. */ ++ ulWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst; ++ ulSkipPtr = ulWritePtr; ++ } ++ } ++ ++ /* Check if must clear repeat bit. */ ++ if ( ( ( pEchoChannel->fRinBufPlayoutRepeatUsed == TRUE ) && ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ) ++ || ( ( pEchoChannel->fSoutBufPlayoutRepeatUsed == TRUE ) && ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) ) ) ++ { ++ if ( ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) ++ || ( ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) ++ && ( ulWritePtr != ulReadPtr ) ) ) ++ { ++ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst; ++ } ++ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst; ++ } ++ ++ /* Set the playout event base address. */ ++ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) ++ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) ++ { ++ /* 127 or 31 events image. */ ++ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ( ( ulWritePtr - 1 ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ))); ++ } ++ else ++ { ++ /* Old 31 events image. */ ++ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ( ( ulWritePtr - 1 ) & 0x1F)); ++ } ++ ++ /* EVENT BASE + 4 */ ++ /* Playout configuration. */ ++ ulAddress += 4; ++ ++ ReadParams.ulReadAddress = ulAddress; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Read-clear-write the new repeat bit. */ ++ usReadData &= 0x7FFF; ++ ++ WriteParams.ulWriteAddress = ulAddress; ++ WriteParams.usWriteData = usReadData; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /* Write the skip to the value of the write pointer to stop buffer playout. */ ++ ++ /*=======================================================================*/ ++ /* First set the ignore skip clean bit if required. */ ++ ++ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == FALSE ) ++ || ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == FALSE ) ) ++ { ++ ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask ); ++ ++ ulTempData &= ( ~ulMask ); ++ ++ /* Check if the skip need to be clean or not. */ ++ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) ++ ulTempData |= 0x1 << ulIgnoreBitOfst; ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Fetch and modify the write pointer. */ ++ ++ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, pEchoChannel, ulAddress, &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); ++ ++ ulTempData &= ( ~ulMask ); ++ ulTempData |= ulWritePtr << ulWritePtrBitOfst; ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* Fetch and modify the skip pointer. */ ++ ++ ulAddress = ulPlayoutBaseAddress + ulSkipPtrBytesOfst; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulSkipPtrFieldSize, ulSkipPtrBitOfst, &ulMask ); ++ ++ ulTempData &= ( ~ulMask ); ++ ulTempData |= ulSkipPtr << ulSkipPtrBitOfst; ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* If in the new buffer playout case, things are in a different order. */ ++ ++ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) ++ { ++ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) ++ && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) ++ { ++ ulAddress = ulPlayoutBaseAddress + ulHardSkipBytesOfst; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulHardSkipFieldSize, ulHardSkipBitOfst, &ulMask ); ++ ++ ulTempData &= ( ~ulMask ); ++ ++ /* Check if the skip need to be clean or not. */ ++ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) ++ ulTempData |= 0x1 << ulHardSkipBitOfst; ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Now is the appropriate time to skip! */ ++ ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst; ++ ++ ulResult = oct6100_retrieve_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ &ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask ); ++ ++ ulTempData &= ( ~ulMask ); ++ ++ /* Set the skip bit. */ ++ ulTempData |= 0x1 << ulIgnoreBitOfst; ++ ++ ulResult = oct6100_save_nlp_conf_dword(f_pApiInstance, ++ pEchoChannel, ++ ulAddress, ++ ulTempData); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ /*=======================================================================*/ ++ /* The API must set the skip bit in all the events that are queued. */ ++ ++ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) ++ { ++ if ( fCheckStop == TRUE ) ++ { ++ if ( ulReadPtr != ulWritePtr ) ++ { ++ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst; ++ } ++ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst; ++ } ++ ++ for ( ulCurrentPtr = ulReadPtr; ulCurrentPtr != ulWritePtr; ) ++ { ++ /* Set the playout event base address. */ ++ ++ /* 127 or 31 events image. */ ++ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + ( cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ulCurrentPtr ); ++ ulCurrentPtr++; ++ ulCurrentPtr &= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ); ++ ++ /* EVENT BASE + 0 playout configuration. */ ++ WriteParams.ulWriteAddress = ulAddress; ++ ++ /* Set skip bit + hard-skip bit. */ ++ WriteParams.usWriteData = 0x8000; ++ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) ++ WriteParams.usWriteData |= 0x4000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ } ++ } ++ ++ /*=======================================================================*/ ++ /* If stop immediatly, wait the stop before leaving the function. */ ++ ++ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) ++ { ++ /* Remember that an "hard stop" was used for the next start. */ ++ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ pEchoChannel->fRinHardStop = TRUE; ++ else /* if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ ++ pEchoChannel->fSoutHardStop = TRUE; ++ } ++ ++ /*=======================================================================*/ ++ /* Update the channel entry to set the playing flag to FALSE. */ ++ ++ /* Select the port of interest. */ ++ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ++ { ++ /* Check if the global ports active stat must be decremented. */ ++ if ( pEchoChannel->fRinBufPlaying == TRUE ) ++ { ++ /* Decrement the number of active buffer playout ports. */ ++ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; ++ } ++ ++ pEchoChannel->fRinBufPlaying = FALSE; ++ ++ /* Return user information. */ ++ if ( f_pBufferPlayoutStop->pfNotifyOnPlayoutStop != NULL ) ++ *f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = pEchoChannel->fRinBufPlayoutNotifyOnStop; ++ ++ /* Make sure no new event is recorded for this channel/port. */ ++ pEchoChannel->fRinBufPlayoutNotifyOnStop = FALSE; ++ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) ++ { ++ pEchoChannel->ulRinBufSkipPtr = ulSkipPtr; ++ pEchoChannel->ulRinBufWritePtr = ulWritePtr; ++ } ++ else /* if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) */ ++ pEchoChannel->ulRinBufSkipPtr = pEchoChannel->ulRinBufWritePtr; ++ ++ /* The repeat flag can now be used. */ ++ pEchoChannel->fRinBufPlayoutRepeatUsed = FALSE; ++ ++ /* For sure, all buffers have now been cleared on the Rin port. */ ++ pEchoChannel->fRinBufAdded = FALSE; ++ ++ /* Clear optimization flag if possible. */ ++ if ( ( pEchoChannel->fSoutBufPlaying == FALSE ) ++ && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == FALSE ) ) ++ { ++ /* Buffer playout is no more active on this channel. */ ++ pEchoChannel->fBufPlayoutActive = FALSE; ++ } ++ } ++ else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ ++ { ++ /* Check if the global ports active stat must be decremented. */ ++ if ( pEchoChannel->fSoutBufPlaying == TRUE ) ++ { ++ /* Decrement the number of active buffer playout ports. */ ++ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; ++ } ++ ++ pEchoChannel->fSoutBufPlaying = FALSE; ++ ++ /* Return user information. */ ++ if ( f_pBufferPlayoutStop->pfNotifyOnPlayoutStop != NULL ) ++ *f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = pEchoChannel->fSoutBufPlayoutNotifyOnStop; ++ ++ /* Make sure no new event is recorded for this channel/port. */ ++ pEchoChannel->fSoutBufPlayoutNotifyOnStop = FALSE; ++ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) ++ { ++ pEchoChannel->ulSoutBufSkipPtr = ulSkipPtr; ++ pEchoChannel->ulSoutBufWritePtr = ulWritePtr; ++ } ++ else /* if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) */ ++ pEchoChannel->ulSoutBufSkipPtr = pEchoChannel->ulSoutBufWritePtr; ++ ++ /* The repeat flag can now be used. */ ++ pEchoChannel->fSoutBufPlayoutRepeatUsed = FALSE; ++ ++ /* For sure, all buffers have now been cleared on the Sout port. */ ++ pEchoChannel->fSoutBufAdded = FALSE; ++ ++ /* Clear optimization flag if possible. */ ++ if ( ( pEchoChannel->fRinBufPlaying == FALSE ) ++ && ( pEchoChannel->fRinBufPlayoutNotifyOnStop == FALSE ) ) ++ { ++ /* Buffer playout is no more active on this channel. */ ++ pEchoChannel->fBufPlayoutActive = FALSE; ++ } ++ } ++ ++ /*=======================================================================*/ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveBufPlayoutListEntry ++ ++Description: Reserves a free entry in the Buffer playout list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pulBufferIndex List entry reserved. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveBufPlayoutListEntry ++UINT32 Oct6100ApiReserveBufPlayoutListEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT32 f_pulBufferIndex ) ++{ ++ PVOID pBufPlayoutAlloc; ++ UINT32 ulResult; ++ ++ mOCT6100_GET_BUFFER_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBufPlayoutAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pBufPlayoutAlloc, f_pulBufferIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_BUFFER_PLAYOUT_ALL_BUFFERS_OPEN; ++ else ++ return cOCT6100_ERR_FATAL_40; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseBufPlayoutListEntry ++ ++Description: Release an entry from the Buffer playout list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulBufferIndex List entry to be freed. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseBufPlayoutListEntry ++UINT32 Oct6100ApiReleaseBufPlayoutListEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulBufferIndex ) ++{ ++ PVOID pBufPlayoutAlloc; ++ UINT32 ulResult; ++ ++ mOCT6100_GET_BUFFER_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBufPlayoutAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pBufPlayoutAlloc, f_ulBufferIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_41; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1598 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_remote_debug.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the routines used for remote debugging. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 35 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++ ++#include "apilib/octapi_bt0.h" ++#include "apilib/octapi_largmath.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_debug_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_remote_debug_pub.h" ++ ++#include "octrpc/rpc_protocol.h" ++#include "octrpc/oct6100_rpc_protocol.h" ++ ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_debug_priv.h" ++#include "oct6100_remote_debug_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100RemoteDebug ++ ++Description: This function interprets the remote debugging packets received ++ by the user’s software. Commands contained in the packet are ++ executed by the API. In addition, a response packet is ++ constructed and returned by the function. It is the responsibility ++ of the user’s software to transmit the response packet back to ++ the source of the debugging packet. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pRemoteDebug Pointer to a remote debug structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100RemoteDebugDef ++UINT32 Oct6100RemoteDebugDef( ++ tPOCT6100_REMOTE_DEBUG f_pRemoteDebug ) ++{ ++ f_pRemoteDebug->pulReceivedPktPayload = NULL; ++ f_pRemoteDebug->ulReceivedPktLength = 0; ++ f_pRemoteDebug->pulResponsePktPayload = NULL; ++ f_pRemoteDebug->ulMaxResponsePktLength = 0; ++ f_pRemoteDebug->ulResponsePktLength = 0; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100RemoteDebug ++UINT32 Oct6100RemoteDebug( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_REMOTE_DEBUG f_pRemoteDebug ) ++{ ++ tPOCTRPC_OGRDTP_HEADER pOgrdtpHeader; ++ tPOCTRPC_INTERFACE_HEADER pInterfaceHeader; ++ tPOCTRPC_COMMAND_HEADER pRspCmndHeader; ++ PUINT32 pulRcvPktPayload; ++ PUINT32 pulRspPktPayload; ++ UINT32 ulPktLengthDword; ++ UINT32 ulSessionIndex; ++ UINT32 ulChecksum; ++ UINT32 ulResult; ++ ++ /* Check for errors. */ ++ if ( f_pRemoteDebug->pulReceivedPktPayload == NULL ) ++ return cOCT6100_ERR_REMOTEDEBUG_RECEIVED_PKT_PAYLOAD; ++ if ( f_pRemoteDebug->pulResponsePktPayload == NULL ) ++ return cOCT6100_ERR_REMOTEDEBUG_RESPONSE_PKT_PAYLOAD; ++ if ( f_pRemoteDebug->ulReceivedPktLength < cOCTRPC_MIN_PACKET_BYTE_LENGTH ) ++ return cOCT6100_ERR_REMOTEDEBUG_RECEIVED_PKT_LENGTH; ++ if ( f_pRemoteDebug->ulReceivedPktLength > cOCTRPC_MAX_PACKET_BYTE_LENGTH ) ++ return cOCT6100_ERR_REMOTEDEBUG_RECEIVED_PKT_LENGTH; ++ if ( f_pRemoteDebug->ulMaxResponsePktLength < f_pRemoteDebug->ulReceivedPktLength ) ++ return cOCT6100_ERR_REMOTEDEBUG_RESPONSE_PKT_LENGTH; ++ if ( (f_pRemoteDebug->ulReceivedPktLength % 4) != 0 ) ++ return cOCT6100_ERR_REMOTEDEBUG_RECEIVED_PKT_LENGTH; ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxRemoteDebugSessions == 0 ) ++ return cOCT6100_ERR_REMOTEDEBUG_DISABLED; ++ ++ /* Set response length as received length. */ ++ f_pRemoteDebug->ulResponsePktLength = f_pRemoteDebug->ulReceivedPktLength; ++ ++ /* Typecast the packet payload to local pointers. */ ++ pOgrdtpHeader = ( tPOCTRPC_OGRDTP_HEADER )f_pRemoteDebug->pulReceivedPktPayload; ++ pInterfaceHeader = ( tPOCTRPC_INTERFACE_HEADER )(f_pRemoteDebug->pulReceivedPktPayload + (sizeof( tOCTRPC_OGRDTP_HEADER ) / 4)); ++ ++ /* Get local pointer to received and response packet payloads. */ ++ pulRcvPktPayload = f_pRemoteDebug->pulReceivedPktPayload; ++ pulRspPktPayload = f_pRemoteDebug->pulResponsePktPayload; ++ ++ /* Get the length of the packet in UINT32s. */ ++ ulPktLengthDword = f_pRemoteDebug->ulReceivedPktLength / 4; ++ ++ /* Check the endian detection field to determine if the payload must be */ ++ /* swapped to account for different endian formats. */ ++ ulResult = Oct6100ApiCheckEndianDetectField( pOgrdtpHeader, ulPktLengthDword ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Check the packet's length. */ ++ if ( pOgrdtpHeader->ulPktByteSize != f_pRemoteDebug->ulReceivedPktLength ) ++ return cOCT6100_ERR_REMOTEDEBUG_RECEIVED_PKT_LENGTH; ++ ++ /* Perform the sum of each word in the packet and compare to checksum. */ ++ Oct6100ApiCalculateChecksum( pulRcvPktPayload, ulPktLengthDword, &ulChecksum ); ++ if ( ulChecksum != pOgrdtpHeader->ulChecksum ) ++ return cOCT6100_ERR_REMOTEDEBUG_CHECKSUM; ++ ++ /* Check if the packet's session number has a corresponding entry in the API table. ++ If not then close an entry which has timed out, and allocate the entry to the ++ new session number. */ ++ ulResult = Oct6100ApiCheckSessionNum( f_pApiInstance, pOgrdtpHeader, &ulSessionIndex ); ++ if ( ulResult == cOCT6100_ERR_REMOTEDEBUG_ALL_SESSIONS_OPEN ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, FALSE, FALSE, FALSE, FALSE, cOCT6100_INVALID_VALUE, cOCTRPC_RDBGERR_ALL_SESSIONS_OPEN, cOCT6100_INVALID_VALUE, ulChecksum ); ++ return cOCT6100_ERR_OK; ++ } ++ else if ( ulResult == cOCT6100_ERR_REMOTEDEBUG_TRANSACTION_ANSWERED ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, TRUE, FALSE, FALSE, FALSE, ulSessionIndex, cOCT6100_INVALID_VALUE, cOCT6100_INVALID_VALUE, ulChecksum ); ++ return cOCT6100_ERR_OK; ++ } ++ else if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return ulResult; ++ } ++ ++ /* Check if an echo packet. If so then there's no need to check the rest of ++ the packet. Simply copy the packet back to the output buffer, enter the ++ protocol number supported by this API compilation, and recalculate the ++ checksum. If the packet is not an echo packet and the protocol version ++ does not correspond to this compiled version then return the supported ++ protocol version. */ ++ if ( pOgrdtpHeader->ulRpcProtocolNum == cOCTRPC_ECHO_PROTOCOL ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, FALSE, TRUE, FALSE, FALSE, ulSessionIndex, cOCT6100_INVALID_VALUE, cOCT6100_INVALID_VALUE, ulChecksum ); ++ return cOCT6100_ERR_OK; ++ } ++ else if ( pOgrdtpHeader->ulRpcProtocolNum != cOCTRPC_PROTOCOL_V1_1 ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, FALSE, TRUE, FALSE, FALSE, ulSessionIndex, cOCTRPC_RDBGERR_PROTOCOL_NUMBER, cOCT6100_INVALID_VALUE, ulChecksum ); ++ return cOCT6100_ERR_OK; ++ } ++ else if ( f_pRemoteDebug->ulReceivedPktLength <= cOCTRPC_FIRST_COMMAND_BYTE_OFFSET ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, FALSE, FALSE, FALSE, FALSE, ulSessionIndex, cOCTRPC_RDBGERR_NO_COMMAND_HEADER, cOCT6100_INVALID_VALUE, ulChecksum ); ++ return cOCT6100_ERR_OK; ++ } ++ ++ ++ /* Check the packet's RPC interface type and version. If either does not match then ++ return the packet with the supported interface type and version of this compilation. */ ++ if ( pInterfaceHeader->ulInterfaceVersion != cOCTRPC_INTERFACE_VERSION ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, FALSE, FALSE, TRUE, TRUE, ulSessionIndex, cOCTRPC_RDBGERR_INTERFACE_VERSION, cOCT6100_INVALID_VALUE, ulChecksum ); ++ return cOCT6100_ERR_OK; ++ } ++ if ( pInterfaceHeader->ulInterfaceType != cOCTRPC_OCT6100_INTERFACE ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, FALSE, FALSE, TRUE, TRUE, ulSessionIndex, cOCTRPC_RDBGERR_INTERFACE_TYPE, cOCT6100_INVALID_VALUE, ulChecksum ); ++ return cOCT6100_ERR_OK; ++ } ++ ++ /* Check each command header to make sure the indicated command and length agree. If ++ there is an error in the packet's commands then the response packet will be ++ constructed by the function. */ ++ ulResult = Oct6100ApiCheckPktCommands( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulSessionIndex, ulPktLengthDword, ulChecksum ); ++ if ( ulResult == cOCT6100_ERR_REMOTE_DEBUG_PARSING_ERROR ) ++ return cOCT6100_ERR_OK; ++ ++ /* The packet's fields are valid. Each command must now be extracted and executed. */ ++ Oct6100ApiExecutePktCommands( f_pApiInstance, pulRcvPktPayload, ulPktLengthDword ); ++ ++ pRspCmndHeader = ( tPOCTRPC_COMMAND_HEADER )(( PUINT32 )pulRspPktPayload + ((sizeof( tOCTRPC_OGRDTP_HEADER ) + sizeof( tOCTRPC_INTERFACE_HEADER )) / 4)); ++ ++ /* Verify if the new method of using the protocol is the selected case. */ ++ /* All commands have been executed. Calculate the packet's new checksum ++ and copy the packet to user provided buffer for response packet. */ ++ Oct6100ApiCalculateChecksum( pulRcvPktPayload, ulPktLengthDword, &ulChecksum ); ++ ++ /* Send response packet. */ ++ Oct6100ApiFormResponsePkt( f_pApiInstance, pulRcvPktPayload, pulRspPktPayload, ulPktLengthDword, FALSE, FALSE, FALSE, FALSE, ulSessionIndex, cOCTRPC_RDBGERR_OK, cOCT6100_INVALID_VALUE, ulChecksum ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetRemoteDebugSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of remote debugging. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pChipOpen Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetRemoteDebugSwSizes ++UINT32 Oct6100ApiGetRemoteDebugSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pChipOpen, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Memory needed for remote debugging sessions. */ ++ if ( f_pChipOpen->ulMaxRemoteDebugSessions > 0 ) ++ { ++ f_pInstSizes->ulRemoteDebugList = f_pChipOpen->ulMaxRemoteDebugSessions * sizeof( tOCT6100_API_REMOTE_DEBUG_SESSION ); ++ ++ ulResult = octapi_bt0_get_size( f_pChipOpen->ulMaxRemoteDebugSessions, 4, 4, &f_pInstSizes->ulRemoteDebugTree ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_41; ++ ++ f_pInstSizes->ulRemoteDebugPktCache = cOCTRPC_MAX_PACKET_BYTE_LENGTH * f_pChipOpen->ulMaxRemoteDebugSessions; ++ f_pInstSizes->ulRemoteDebugDataBuf = cOCTRPC_MAX_PACKET_BYTE_LENGTH * 4; ++ } ++ else ++ { ++ f_pInstSizes->ulRemoteDebugList = 0; ++ f_pInstSizes->ulRemoteDebugTree = 0; ++ f_pInstSizes->ulRemoteDebugPktCache = 0; ++ f_pInstSizes->ulRemoteDebugDataBuf = 0; ++ } ++ ++ /* Round off the size. */ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugTree, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugPktCache, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugDataBuf, ulTempVar ) ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRemoteDebuggingSwInit ++ ++Description: Initializes all portions of the API instance associated to ++ remote debugging. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRemoteDebuggingSwInit ++UINT32 Oct6100ApiRemoteDebuggingSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pSessionTree; ++ UINT32 ulResult; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ pSharedInfo->RemoteDebugInfo.ulNumSessionsOpen = 0; ++ pSharedInfo->RemoteDebugInfo.ulMaxSessionsOpen = pSharedInfo->ChipConfig.usMaxRemoteDebugSessions; ++ pSharedInfo->RemoteDebugInfo.ulSessionListHead = cOCT6100_INVALID_VALUE; ++ pSharedInfo->RemoteDebugInfo.ulSessionListTail = cOCT6100_INVALID_VALUE; ++ ++ if ( pSharedInfo->ChipConfig.usMaxRemoteDebugSessions > 0 ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_TREE_PNT( pSharedInfo, pSessionTree ) ++ ++ ulResult = octapi_bt0_init( ( ( PVOID* )&pSessionTree ), pSharedInfo->ChipConfig.usMaxRemoteDebugSessions, 4, 4 ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_42; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckEndianDetectField ++ ++Description: Checks the endian field of a packet and performs a swap of ++ the packet data if deemed necessary. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulPktLengthDword Length of the packet in dwords. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckEndianDetectField ++UINT32 Oct6100ApiCheckEndianDetectField( ++ IN OUT tPOCTRPC_OGRDTP_HEADER f_pOgrdtpHeader, ++ IN UINT32 f_ulPktLengthDword ) ++{ ++ PUINT32 pulPktPayload; ++ UINT32 ulBytePositionW = cOCT6100_INVALID_VALUE; ++ UINT32 ulBytePositionX = cOCT6100_INVALID_VALUE; ++ UINT32 ulBytePositionY = cOCT6100_INVALID_VALUE; ++ UINT32 ulBytePositionZ = cOCT6100_INVALID_VALUE; ++ UINT32 ulTempVar; ++ UINT32 i; ++ ++ /* Bytes in dword are labeled as Z Y X W. */ ++ ++ /* Only swap if necessary. */ ++ if ( f_pOgrdtpHeader->ulEndianDetect != cOCTRPC_ENDIAN_DETECT ) ++ { ++ /* Find the position of each byte. */ ++ for ( i = 0; i < 4; i++ ) ++ { ++ ulTempVar = (f_pOgrdtpHeader->ulEndianDetect >> (8 * i)) & 0xFF; ++ switch ( ulTempVar ) ++ { ++ case cOCTRPC_ENDIAN_DETECT_BYTE_W: ++ ulBytePositionW = i * 8; ++ break; ++ case cOCTRPC_ENDIAN_DETECT_BYTE_X: ++ ulBytePositionX = i * 8; ++ break; ++ case cOCTRPC_ENDIAN_DETECT_BYTE_Y: ++ ulBytePositionY = i * 8; ++ break; ++ case cOCTRPC_ENDIAN_DETECT_BYTE_Z: ++ ulBytePositionZ = i * 8; ++ break; ++ default: ++ return cOCT6100_ERR_REMOTEDEBUG_INVALID_PACKET; ++ } ++ } ++ ++ /* Make sure all bytes of the endian detect field were found. */ ++ if ( ulBytePositionW == cOCT6100_INVALID_VALUE || ++ ulBytePositionX == cOCT6100_INVALID_VALUE || ++ ulBytePositionY == cOCT6100_INVALID_VALUE || ++ ulBytePositionZ == cOCT6100_INVALID_VALUE ) ++ return cOCT6100_ERR_REMOTEDEBUG_INVALID_PACKET; ++ ++ /* Swap the bytes of each dword of the packet. */ ++ pulPktPayload = ( PUINT32 )f_pOgrdtpHeader; ++ for ( i = 0; i < f_ulPktLengthDword; i++ ) ++ { ++ ulTempVar = pulPktPayload[ i ]; ++ pulPktPayload[ i ] = ((ulTempVar >> ulBytePositionZ) & 0xFF) << 24; ++ pulPktPayload[ i ] |= ((ulTempVar >> ulBytePositionY) & 0xFF) << 16; ++ pulPktPayload[ i ] |= ((ulTempVar >> ulBytePositionX) & 0xFF) << 8; ++ pulPktPayload[ i ] |= ((ulTempVar >> ulBytePositionW) & 0xFF) << 0; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCalculateChecksum ++ ++Description: Calculates the checksum of the given packet payload. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pulPktPayload Pointer to the payload of the packet. ++f_ulPktLengthDword Length of the packet in dwords. ++f_pulChecksum Pointer to the checksum of the packet. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCalculateChecksum ++VOID Oct6100ApiCalculateChecksum( ++ IN PUINT32 f_pulPktPayload, ++ IN UINT32 f_ulPktLengthDword, ++ OUT PUINT32 f_pulChecksum ) ++{ ++ tPOCTRPC_OGRDTP_HEADER pOgrdtpHeader; ++ UINT32 i; ++ ++ for ( i = 0, *f_pulChecksum = 0; i < f_ulPktLengthDword; i++ ) ++ { ++ *f_pulChecksum += (f_pulPktPayload[ i ] >> 16) & 0xFFFF; ++ *f_pulChecksum += (f_pulPktPayload[ i ] >> 0) & 0xFFFF; ++ } ++ ++ pOgrdtpHeader = ( tPOCTRPC_OGRDTP_HEADER )f_pulPktPayload; ++ *f_pulChecksum -= (pOgrdtpHeader->ulChecksum >> 16) & 0xFFFF; ++ *f_pulChecksum -= (pOgrdtpHeader->ulChecksum >> 0) & 0xFFFF; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiFormResponsePkt ++ ++Description: Modifies the values of the indicated receive packet, update ++ the checksum field, and copy the receive packet to the ++ response packet. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pulRcvPktPayload Pointer to the payload of the received packet. ++f_pulRspPktPayload Pointer to the payload of the response packet. ++f_ulPktLengthDword Length of the packet in dwords. ++f_fRetryPktResponse Flag indicating if the received packet was a retry packet. ++f_fReplaceProtocolNum Flag indicating if the protocol number must be replaced. ++f_fReplaceInterfaceType Flag indicating if the interface type must be replaced. ++f_fReplaceInterfaceVersion Flag indicating if the interface version must be replaced. ++f_ulSessionIndex Index of the remote debug session within the API' session list. ++f_ulParsingErrorValue Parsing error value. ++f_ulPayloadDwordIndex Index in the packet where the payload starts. ++f_ulChecksum Checksum of the packet. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiFormResponsePkt ++VOID Oct6100ApiFormResponsePkt( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulRcvPktPayload, ++ OUT PUINT32 f_pulRspPktPayload, ++ IN UINT32 f_ulPktLengthDword, ++ IN BOOL f_fRetryPktResponse, ++ IN BOOL f_fReplaceProtocolNum, ++ IN BOOL f_fReplaceInterfaceType, ++ IN BOOL f_fReplaceInterfaceVersion, ++ IN UINT32 f_ulSessionIndex, ++ IN UINT32 f_ulParsingErrorValue, ++ IN UINT32 f_ulPayloadDwordIndex, ++ IN UINT32 f_ulChecksum ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCTRPC_OGRDTP_HEADER pOgrdtpHeader; ++ tPOCTRPC_INTERFACE_HEADER pInterfaceHeader; ++ PUINT32 pulPktCache; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Typecast pointer to OGRDTP packet header. */ ++ pOgrdtpHeader = ( tPOCTRPC_OGRDTP_HEADER )f_pulRcvPktPayload; ++ ++ /* Check if a response to a retry packet. */ ++ if ( f_fRetryPktResponse == TRUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_SESSION_PKT_CACHE_PNT( pSharedInfo, pulPktCache, f_ulSessionIndex ) ++ ++ Oct6100UserMemCopy( f_pulRspPktPayload, pulPktCache, f_ulPktLengthDword * 4 ); ++ return; ++ } ++ ++ /* Replace all packet header fields which must be changed. */ ++ if ( f_ulParsingErrorValue != cOCT6100_INVALID_VALUE ) ++ { ++ f_ulChecksum -= (pOgrdtpHeader->ulParsingError >> 16) & 0xFFFF; ++ f_ulChecksum -= (pOgrdtpHeader->ulParsingError >> 0) & 0xFFFF; ++ ++ pOgrdtpHeader->ulParsingError = f_ulParsingErrorValue; ++ ++ f_ulChecksum += (pOgrdtpHeader->ulParsingError >> 16) & 0xFFFF; ++ f_ulChecksum += (pOgrdtpHeader->ulParsingError >> 0) & 0xFFFF; ++ } ++ ++ if ( f_fReplaceProtocolNum == TRUE ) ++ { ++ f_ulChecksum -= (pOgrdtpHeader->ulRpcProtocolNum >> 16) & 0xFFFF; ++ f_ulChecksum -= (pOgrdtpHeader->ulRpcProtocolNum >> 0) & 0xFFFF; ++ ++ pOgrdtpHeader->ulRpcProtocolNum = cOCTRPC_PROTOCOL_V1_1; ++ ++ f_ulChecksum += (pOgrdtpHeader->ulRpcProtocolNum >> 16) & 0xFFFF; ++ f_ulChecksum += (pOgrdtpHeader->ulRpcProtocolNum >> 0) & 0xFFFF; ++ } ++ ++ if ( f_fReplaceInterfaceType == TRUE ) ++ { ++ pInterfaceHeader = ( tPOCTRPC_INTERFACE_HEADER )(f_pulRcvPktPayload + (sizeof( tOCTRPC_OGRDTP_HEADER ) / 4)); ++ ++ f_ulChecksum -= (pInterfaceHeader->ulInterfaceType >> 16) & 0xFFFF; ++ f_ulChecksum -= (pInterfaceHeader->ulInterfaceType >> 0) & 0xFFFF; ++ ++ pInterfaceHeader->ulInterfaceType = cOCTRPC_OCT6100_INTERFACE; ++ ++ f_ulChecksum += (pInterfaceHeader->ulInterfaceType >> 16) & 0xFFFF; ++ f_ulChecksum += (pInterfaceHeader->ulInterfaceType >> 0) & 0xFFFF; ++ } ++ ++ if ( f_fReplaceInterfaceVersion == TRUE ) ++ { ++ pInterfaceHeader = ( tPOCTRPC_INTERFACE_HEADER )(f_pulRcvPktPayload + (sizeof( tOCTRPC_OGRDTP_HEADER ) / 4)); ++ ++ f_ulChecksum -= (pInterfaceHeader->ulInterfaceVersion >> 16) & 0xFFFF; ++ f_ulChecksum -= (pInterfaceHeader->ulInterfaceVersion >> 0) & 0xFFFF; ++ ++ pInterfaceHeader->ulInterfaceVersion = cOCTRPC_INTERFACE_VERSION; ++ ++ f_ulChecksum += (pInterfaceHeader->ulInterfaceVersion >> 16) & 0xFFFF; ++ f_ulChecksum += (pInterfaceHeader->ulInterfaceVersion >> 0) & 0xFFFF; ++ } ++ ++ if ( f_ulPayloadDwordIndex != cOCT6100_INVALID_VALUE ) ++ { ++ f_pulRcvPktPayload += f_ulPayloadDwordIndex; ++ ++ f_ulChecksum -= (*f_pulRcvPktPayload >> 16) & 0xFFFF; ++ f_ulChecksum -= (*f_pulRcvPktPayload >> 0) & 0xFFFF; ++ ++ *f_pulRcvPktPayload = cOCTRPC_UNKNOWN_COMMAND_NUM; ++ ++ f_ulChecksum += (*f_pulRcvPktPayload >> 16) & 0xFFFF; ++ f_ulChecksum += (*f_pulRcvPktPayload >> 0) & 0xFFFF; ++ ++ f_pulRcvPktPayload -= f_ulPayloadDwordIndex; ++ } ++ ++ /* Replace checksum. */ ++ pOgrdtpHeader->ulChecksum = f_ulChecksum; ++ ++ /* Copy the modified receive packet payload to the response packet. */ ++ Oct6100UserMemCopy( f_pulRspPktPayload, f_pulRcvPktPayload, f_ulPktLengthDword * 4 ); ++ ++ /* Copy the response packet to the session's packet cache. */ ++ if ( f_ulSessionIndex != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_SESSION_PKT_CACHE_PNT( pSharedInfo, pulPktCache, f_ulSessionIndex ) ++ ++ Oct6100UserMemCopy( pulPktCache, f_pulRspPktPayload, f_ulPktLengthDword * 4 ); ++ } ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckPktCommands ++ ++Description: Checks the commands contained in the packet for errors in size. ++ Also checks for unknown commands. If an error is encountered ++ then the function will construct the response packet. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pulRcvPktPayload Pointer to the payload of the received packet. ++f_pulRspPktPayload Pointer to the payload of the response packet. ++f_ulPktLengthDword Length of the packet in dwords. ++f_ulSessionIndex Index of the remote debug session within the API' session list. ++f_ulChecksum Checksum of the packet. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckPktCommands ++UINT32 Oct6100ApiCheckPktCommands( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulRcvPktPayload, ++ IN OUT PUINT32 f_pulRspPktPayload, ++ IN UINT32 f_ulSessionIndex, ++ IN UINT32 f_ulPktLengthDword, ++ IN UINT32 f_ulChecksum ) ++{ ++ tPOCTRPC_COMMAND_HEADER pCmndHeader; ++ UINT32 ulNumDwordsLeft; ++ UINT32 ulNumDwordsNeeded = 0; ++ UINT32 ulRpcCmndSizeDword; ++ BOOL fCmndIdentified; ++ BOOL fCmndHeaderPresent; ++ ++ pCmndHeader = ( tPOCTRPC_COMMAND_HEADER )(f_pulRcvPktPayload + ((sizeof( tOCTRPC_OGRDTP_HEADER ) + sizeof( tOCTRPC_INTERFACE_HEADER )) / 4)); ++ ulNumDwordsLeft = f_ulPktLengthDword - ((sizeof( tOCTRPC_OGRDTP_HEADER ) + sizeof( tOCTRPC_INTERFACE_HEADER )) / 4); ++ ulRpcCmndSizeDword = sizeof( tOCTRPC_COMMAND_HEADER ) / 4; ++ fCmndIdentified = TRUE; ++ ++ while ( ulNumDwordsLeft != 0 ) ++ { ++ if ( ulNumDwordsLeft < ulRpcCmndSizeDword ) ++ { ++ fCmndHeaderPresent = FALSE; ++ } ++ else ++ { ++ fCmndHeaderPresent = TRUE; ++ ++ switch ( pCmndHeader->ulRpcCommandNum ) ++ { ++ case cOCT6100_RPC_READ_WORD: ++ { ++ ulNumDwordsNeeded = sizeof( tOCT6100_RPC_READ_WORD ) / 4; ++ } ++ break; ++ case cOCT6100_RPC_READ_BURST: ++ { ++ tPOCT6100_RPC_READ_BURST pBurstHeader; ++ ++ ulNumDwordsNeeded = (sizeof( tOCT6100_RPC_READ_BURST ) - sizeof( UINT32 )) / 4; ++ pBurstHeader = ( tPOCT6100_RPC_READ_BURST )(( PUINT32 )pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ulNumDwordsNeeded += (pBurstHeader->ulBurstLength + 1) / 2; ++ } ++ break; ++ case cOCT6100_RPC_WRITE_WORD: ++ { ++ ulNumDwordsNeeded = sizeof( tOCT6100_RPC_WRITE_WORD ) / 4; ++ } ++ break; ++ case cOCT6100_RPC_WRITE_SMEAR: ++ { ++ ulNumDwordsNeeded = sizeof( tOCT6100_RPC_WRITE_SMEAR ) / 4; ++ } ++ break; ++ case cOCT6100_RPC_WRITE_INC: ++ { ++ ulNumDwordsNeeded = sizeof( tOCT6100_RPC_WRITE_INC ) / 4; ++ } ++ break; ++ case cOCT6100_RPC_READ_ARRAY: ++ { ++ tPOCT6100_RPC_READ_ARRAY pArrayHeader; ++ ++ ulNumDwordsNeeded = (sizeof( tOCT6100_RPC_READ_ARRAY ) - sizeof( UINT32 )) / 4; ++ pArrayHeader = ( tPOCT6100_RPC_READ_ARRAY )(( PUINT32 )pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ulNumDwordsNeeded += pArrayHeader->ulArrayLength; ++ ulNumDwordsNeeded += (pArrayHeader->ulArrayLength + 1) / 2; ++ } ++ break; ++ case cOCT6100_RPC_WRITE_BURST: ++ { ++ tPOCT6100_RPC_WRITE_BURST pBurstHeader; ++ ++ ulNumDwordsNeeded = (sizeof( tOCT6100_RPC_WRITE_BURST ) - sizeof( UINT32 )) / 4; ++ pBurstHeader = ( tPOCT6100_RPC_WRITE_BURST )(( PUINT32 )pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ulNumDwordsNeeded += (pBurstHeader->ulBurstLength + 1) / 2; ++ } ++ break; ++ case cOCT6100_RPC_SET_HOT_CHANNEL: ++ { ++ ulNumDwordsNeeded = sizeof( tOCT6100_RPC_SET_HOT_CHANNEL ) / 4; ++ } ++ break; ++ case cOCT6100_RPC_GET_DEBUG_CHAN_INDEX: ++ { ++ ulNumDwordsNeeded = sizeof( tOCT6100_RPC_GET_DEBUG_CHAN_INDEX ) / 4; ++ } ++ break; ++ case cOCT6100_RPC_API_DISCONNECT: ++ { ++ /* There is no parameter to the disconnect command. */ ++ ulNumDwordsNeeded = 0; ++ } ++ break; ++ default: ++ fCmndIdentified = FALSE; ++ } ++ ++ ulNumDwordsNeeded += sizeof( tOCTRPC_COMMAND_HEADER ) / 4; ++ } ++ ++ if ( fCmndHeaderPresent != TRUE ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, f_pulRcvPktPayload, f_pulRspPktPayload, f_ulPktLengthDword, FALSE, FALSE, FALSE, FALSE, f_ulSessionIndex, cOCTRPC_RDBGERR_INVALID_PACKET_LENGTH, cOCT6100_INVALID_VALUE, f_ulChecksum ); ++ return cOCT6100_ERR_REMOTE_DEBUG_PARSING_ERROR; ++ } ++ if ( fCmndIdentified != TRUE ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, f_pulRcvPktPayload, f_pulRspPktPayload, f_ulPktLengthDword, FALSE, FALSE, FALSE, FALSE, f_ulSessionIndex, cOCTRPC_RDBGERR_INVALID_COMMAND_NUMBER, f_ulPktLengthDword - ulNumDwordsLeft, f_ulChecksum ); ++ return cOCT6100_ERR_REMOTE_DEBUG_PARSING_ERROR; ++ } ++ ++ if ( ulNumDwordsNeeded != (pCmndHeader->ulCommandByteSize / 4) || ++ ulNumDwordsNeeded > ulNumDwordsLeft ) ++ { ++ Oct6100ApiFormResponsePkt( f_pApiInstance, f_pulRcvPktPayload, f_pulRspPktPayload, f_ulPktLengthDword, FALSE, FALSE, FALSE, FALSE, f_ulSessionIndex, cOCTRPC_RDBGERR_INVALID_COMMAND_LENGTH, cOCT6100_INVALID_VALUE, f_ulChecksum ); ++ return cOCT6100_ERR_REMOTE_DEBUG_PARSING_ERROR; ++ } ++ ++ pCmndHeader = ( tPOCTRPC_COMMAND_HEADER )(( PUINT32 )pCmndHeader + ulNumDwordsNeeded); ++ ulNumDwordsLeft -= ulNumDwordsNeeded; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiExecutePktCommands ++ ++Description: Executes the commands contained in the received packet. The ++ received packet payload buffer is modified but NOT copied to ++ the response packet buffer. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pulRcvPktPayload Pointer to the payload of the received packet. ++f_ulPktLengthDword Length of the packet in dwords. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiExecutePktCommands ++VOID Oct6100ApiExecutePktCommands( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulRcvPktPayload, ++ IN UINT32 f_ulPktLengthDword ) ++{ ++ tPOCTRPC_COMMAND_HEADER pReqCmndHeader; ++ tPOCTRPC_OGRDTP_HEADER pReqPktHeader; ++ UINT32 ulNumDwordsLeft; ++ UINT32 ulRpcCmndSizeDword; ++ ++ pReqPktHeader = ( tPOCTRPC_OGRDTP_HEADER )(f_pulRcvPktPayload); ++ pReqCmndHeader = ( tPOCTRPC_COMMAND_HEADER )(( PUINT32 )f_pulRcvPktPayload + ((sizeof( tOCTRPC_OGRDTP_HEADER ) + sizeof( tOCTRPC_INTERFACE_HEADER )) / 4)); ++ ulNumDwordsLeft = f_ulPktLengthDword - ((sizeof( tOCTRPC_OGRDTP_HEADER ) + sizeof( tOCTRPC_INTERFACE_HEADER )) / 4); ++ ulRpcCmndSizeDword = sizeof( tOCTRPC_COMMAND_HEADER ) / 4; ++ ++ while ( ulNumDwordsLeft != 0 ) ++ { ++ /* Switch on command number. */ ++ switch ( pReqCmndHeader->ulRpcCommandNum ) ++ { ++ case cOCT6100_RPC_READ_WORD: ++ Oct6100ApiRpcReadWord( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_READ_BURST: ++ Oct6100ApiRpcReadBurst( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_READ_ARRAY: ++ Oct6100ApiRpcReadArray( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_WRITE_WORD: ++ Oct6100ApiRpcWriteWord( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_WRITE_SMEAR: ++ Oct6100ApiRpcWriteSmear( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_WRITE_BURST: ++ Oct6100ApiRpcWriteBurst( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_SET_HOT_CHANNEL: ++ Oct6100ApiRpcSetHotChannel( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_GET_DEBUG_CHAN_INDEX: ++ Oct6100ApiRpcGetDebugChanIndex( f_pApiInstance, pReqCmndHeader ); ++ break; ++ case cOCT6100_RPC_API_DISCONNECT: ++ Oct6100ApiRpcDisconnect( f_pApiInstance, pReqCmndHeader, pReqPktHeader->ulDebugSessionNum ); ++ break; ++ default: ++ pReqCmndHeader->ulFunctionResult = cOCT6100_ERR_REMOTEDEBUG_INVALID_RPC_COMMAND_NUM; ++ break; ++ } ++ ++ /* Insert the result of the operation in the command header. */ ++ if ( pReqCmndHeader->ulFunctionResult != cOCT6100_ERR_OK ) ++ break; ++ ++ /* Decrement the number of DWORDs left in the packet. */ ++ ulNumDwordsLeft -= pReqCmndHeader->ulCommandByteSize / 4; ++ ++ /* Point to the next command in the packet. */ ++ pReqCmndHeader = ( tPOCTRPC_COMMAND_HEADER )(( PUINT32 )pReqCmndHeader + (pReqCmndHeader->ulCommandByteSize / 4)); ++ } ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckSessionNum ++ ++Description: Checks if there is a session list entry open for the session ++ number received. If not, a free one is reserved if one is ++ available. If none are free, one which has timed-out is ++ released. If none are timed out then an error is returned. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pOgrdtpHeader Pointer to the header of the packet. ++f_pulSessionIndex Pointer to the remote debugging session within the ++ API's session list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckSessionNum ++UINT32 Oct6100ApiCheckSessionNum( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCTRPC_OGRDTP_HEADER f_pOgrdtpHeader, ++ OUT PUINT32 f_pulSessionIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_REMOTE_DEBUG_INFO pRemoteDebugInfo; ++ tPOCT6100_API_REMOTE_DEBUG_SESSION pSessionEntry; ++ tPOCT6100_API_REMOTE_DEBUG_SESSION pSessionLink; ++ tOCT6100_GET_TIME GetTime; ++ PVOID pSessionTree; ++ PUINT32 pulTreeData; ++ UINT32 ulNewSessionIndex; ++ UINT32 aulTimeDiff[ 2 ]; ++ UINT32 ulResult; ++ UINT16 usNegative; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Set the process context of GetTime. */ ++ GetTime.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Get the current system time. */ ++ ulResult = Oct6100UserGetTime( &GetTime ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Get a local pointer to the remote debugging info. */ ++ pRemoteDebugInfo = &pSharedInfo->RemoteDebugInfo; ++ ++ /* Check if the session number has an associated session list entry. */ ++ mOCT6100_GET_REMOTE_DEBUG_TREE_PNT( pSharedInfo, pSessionTree ) ++ ++ ulResult = octapi_bt0_query_node( pSessionTree, ( ( PVOID )(&f_pOgrdtpHeader->ulDebugSessionNum) ), ( ( PVOID* )&pulTreeData ) ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Return session index. */ ++ *f_pulSessionIndex = *pulTreeData; ++ ++ /* A session list entry is associated, so update the entries last packet time, ++ transaction number and packet retry number, and position in the linked list. */ ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, *pulTreeData, pSessionEntry ) ++ ++ pSessionEntry->aulLastPktTime[ 0 ] = GetTime.aulWallTimeUs[ 0 ]; ++ pSessionEntry->aulLastPktTime[ 1 ] = GetTime.aulWallTimeUs[ 1 ]; ++ pSessionEntry->ulPktRetryNum = f_pOgrdtpHeader->ulPktRetryNum; ++ ++ /* Remove the node from its current place in the linked-list and add it to the end. */ ++ if ( pRemoteDebugInfo->ulSessionListTail != *pulTreeData ) ++ { ++ /* Obtain local pointer to the session list entry to be moved. */ ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, *pulTreeData, pSessionEntry ) ++ ++ /* Update link of previous session in list. */ ++ if ( pSessionEntry->ulBackwardLink != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulBackwardLink, pSessionLink ) ++ pSessionLink->ulForwardLink = pSessionEntry->ulForwardLink; ++ } ++ else ++ { ++ pRemoteDebugInfo->ulSessionListHead = pSessionEntry->ulForwardLink; ++ } ++ ++ /* Update link of next session in list. */ ++ if ( pSessionEntry->ulForwardLink != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulForwardLink, pSessionLink ) ++ pSessionLink->ulBackwardLink = pSessionEntry->ulBackwardLink; ++ } ++ else ++ { ++ pRemoteDebugInfo->ulSessionListTail = pSessionEntry->ulBackwardLink; ++ } ++ ++ /* Place session at the end of the list. */ ++ pSessionEntry->ulBackwardLink = pRemoteDebugInfo->ulSessionListTail; ++ pSessionEntry->ulForwardLink = cOCT6100_INVALID_VALUE; ++ ++ pRemoteDebugInfo->ulSessionListTail = *pulTreeData; ++ ++ if ( pRemoteDebugInfo->ulSessionListHead == cOCT6100_INVALID_VALUE ) ++ { ++ pRemoteDebugInfo->ulSessionListHead = *pulTreeData; ++ } ++ else ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulBackwardLink, pSessionLink ) ++ pSessionLink->ulForwardLink = *pulTreeData; ++ } ++ } ++ ++ /* Check if packet should be interpreted based on transaction number. */ ++ if ( f_pOgrdtpHeader->ulPktRetryNum != 0 && ++ pSessionEntry->ulTransactionNum == f_pOgrdtpHeader->ulTransactionNum && ++ pSessionEntry->ulPktByteSize == f_pOgrdtpHeader->ulPktByteSize ) ++ return cOCT6100_ERR_REMOTEDEBUG_TRANSACTION_ANSWERED; ++ ++ /* Update transaction number since packet will be interpreted. */ ++ pSessionEntry->ulTransactionNum = f_pOgrdtpHeader->ulTransactionNum; ++ pSessionEntry->ulPktByteSize = f_pOgrdtpHeader->ulPktByteSize; ++ ++ return cOCT6100_ERR_OK; ++ } ++ else if ( ulResult == OCTAPI_BT0_KEY_NOT_IN_TREE ) ++ { ++ /* If there is a free entry in the session list then seize it. Else, try to ++ find an entry which has timed out. If there are none then return an error. */ ++ if ( pRemoteDebugInfo->ulNumSessionsOpen < pRemoteDebugInfo->ulMaxSessionsOpen ) ++ { ++ ulNewSessionIndex = pRemoteDebugInfo->ulNumSessionsOpen; ++ } ++ else /* ( pRemoteDebugInfo->ulNumSessionsOpen == pRemoteDebugInfo->ulMaxSessionsOpen ) */ ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pRemoteDebugInfo->ulSessionListHead, pSessionEntry ) ++ ++ ulResult = octapi_lm_subtract( GetTime.aulWallTimeUs, 1, pSessionEntry->aulLastPktTime, 1, aulTimeDiff, 1, &usNegative ); ++ if ( ulResult != cOCT6100_ERR_OK || usNegative != FALSE ) ++ return cOCT6100_ERR_FATAL_43; ++ ++ /* If there are no session list entries available then return the packet with ++ a parsing error. */ ++ if ( aulTimeDiff[ 1 ] == 0 && aulTimeDiff[ 0 ] < (cOCTRPC_SESSION_TIMEOUT * 1000000) ) ++ return cOCT6100_ERR_REMOTEDEBUG_ALL_SESSIONS_OPEN; ++ ++ ulNewSessionIndex = pRemoteDebugInfo->ulSessionListHead; ++ ++ /* Remove old session index. */ ++ ulResult = octapi_bt0_remove_node( pSessionTree, ( ( PVOID )&pSessionEntry->ulSessionNum ) ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_44; ++ ++ if ( pSessionEntry->ulBackwardLink != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulBackwardLink, pSessionLink ) ++ pSessionLink->ulForwardLink = pSessionEntry->ulForwardLink; ++ } ++ else ++ { ++ pRemoteDebugInfo->ulSessionListHead = pSessionEntry->ulForwardLink; ++ } ++ ++ if ( pSessionEntry->ulForwardLink != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulForwardLink, pSessionLink ) ++ pSessionLink->ulBackwardLink = pSessionEntry->ulBackwardLink; ++ } ++ else ++ { ++ pRemoteDebugInfo->ulSessionListTail = pSessionEntry->ulBackwardLink; ++ } ++ ++ /* Decrement number of open sessions. */ ++ pRemoteDebugInfo->ulNumSessionsOpen--; ++ } ++ ++ /* Add new session. */ ++ ulResult = octapi_bt0_add_node( pSessionTree, ( ( PVOID )&f_pOgrdtpHeader->ulDebugSessionNum ), ( ( PVOID* )&pulTreeData ) ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_45; ++ *pulTreeData = ulNewSessionIndex; ++ ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, ulNewSessionIndex, pSessionEntry ) ++ ++ pSessionEntry->aulLastPktTime[ 0 ] = GetTime.aulWallTimeUs[ 0 ]; ++ pSessionEntry->aulLastPktTime[ 1 ] = GetTime.aulWallTimeUs[ 1 ]; ++ pSessionEntry->ulSessionNum = f_pOgrdtpHeader->ulDebugSessionNum; ++ pSessionEntry->ulTransactionNum = f_pOgrdtpHeader->ulTransactionNum; ++ pSessionEntry->ulPktRetryNum = f_pOgrdtpHeader->ulPktRetryNum; ++ ++ pSessionEntry->ulBackwardLink = pRemoteDebugInfo->ulSessionListTail; ++ pSessionEntry->ulForwardLink = cOCT6100_INVALID_VALUE; ++ ++ pRemoteDebugInfo->ulSessionListTail = ulNewSessionIndex; ++ if ( pRemoteDebugInfo->ulSessionListHead == cOCT6100_INVALID_VALUE ) ++ pRemoteDebugInfo->ulSessionListHead = ulNewSessionIndex; ++ ++ if ( pSessionEntry->ulBackwardLink != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulBackwardLink, pSessionLink ) ++ pSessionLink->ulForwardLink = ulNewSessionIndex; ++ } ++ ++ *f_pulSessionIndex = ulNewSessionIndex; ++ ++ /* Increment number of open sessions. */ ++ pRemoteDebugInfo->ulNumSessionsOpen++; ++ ++ return cOCT6100_ERR_OK; ++ } ++ else ++ { ++ return cOCT6100_ERR_FATAL_46; ++ } ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcReadWord ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_READ_WORD command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcReadWord ++VOID Oct6100ApiRpcReadWord( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_READ_WORD pReadCommand; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ ++ /* Get pointer to command arguments. */ ++ pReadCommand = ( tPOCT6100_RPC_READ_WORD )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ /* Set some read structure parameters. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Copy parameters from packet payload to local read structure. */ ++ ReadParams.ulReadAddress = pReadCommand->ulAddress; ++ ++ /* Supply memory for read data. */ ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Perform read access. */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ ++ usReadData &= 0xFFFF; ++ ++ /* Return read data and result. */ ++ pReadCommand->ulReadData = (usReadData << 16) | usReadData; ++ f_pCmndHeader->ulFunctionResult = ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcReadBurst ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_READ_BURST command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcReadBurst ++VOID Oct6100ApiRpcReadBurst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_READ_BURST pBurstCommand; ++ tOCT6100_READ_BURST_PARAMS BurstParams; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 ulTempVar; ++ UINT32 i; ++ PUINT16 pusReadData; ++ UINT32 ulNumWordsToRead; ++ ++ /* Get local pointer to remote debugging read data buffer. */ ++ mOCT6100_GET_REMOTE_DEBUG_DATA_BUF_PNT( f_pApiInstance->pSharedInfo, pusReadData ) ++ ++ /* Get pointer to command arguments. */ ++ pBurstCommand = ( tPOCT6100_RPC_READ_BURST )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ /* Set some read structure parameters. */ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Copy parameters from packet payload to local read structure. */ ++ BurstParams.ulReadAddress = pBurstCommand->ulAddress; ++ ++ ++ /* Supply memory for read data. */ ++ BurstParams.pusReadData = pusReadData; ++ ++ ulNumWordsToRead = pBurstCommand->ulBurstLength; ++ while( ulNumWordsToRead > 0) ++ { ++ if ( ulNumWordsToRead <= f_pApiInstance->pSharedInfo->ChipConfig.usMaxRwAccesses ) ++ BurstParams.ulReadLength = ulNumWordsToRead; ++ else ++ BurstParams.ulReadLength = f_pApiInstance->pSharedInfo->ChipConfig.usMaxRwAccesses; ++ ++ /* Perform read access. */ ++ mOCT6100_DRIVER_READ_BURST_API( BurstParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ f_pCmndHeader->ulFunctionResult = ulResult; ++ return; ++ } ++ ++ BurstParams.ulReadAddress += BurstParams.ulReadLength * 2; ++ BurstParams.pusReadData += BurstParams.ulReadLength; ++ ++ /* Update the number of dword to read. */ ++ ulNumWordsToRead -= BurstParams.ulReadLength; ++ } ++ ++ /* Return read data. */ ++ ulTempVar = (pBurstCommand->ulBurstLength + 1) / 2; ++ for ( i = 0; i < ulTempVar; i++ ) ++ { ++ pBurstCommand->aulReadData[ i ] = (*pusReadData & 0xFFFF) << 16; ++ pusReadData++; ++ pBurstCommand->aulReadData[ i ] |= (*pusReadData & 0xFFFF) << 0; ++ pusReadData++; ++ } ++ ++ /* Return result. */ ++ f_pCmndHeader->ulFunctionResult = ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcReadArray ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_READ_ARRAY command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcReadArray ++VOID Oct6100ApiRpcReadArray( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_READ_ARRAY pArrayCommand; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 i; ++ PUINT32 pulAddressArray; ++ PUINT32 pulDataArray; ++ UINT16 usReadData; ++ ++ ++ /* Get pointer to command arguments. */ ++ pArrayCommand = ( tPOCT6100_RPC_READ_ARRAY )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ /* Set some read structure parameters. */ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Supply memory for read data. */ ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Get pointers to array of addresses and data. */ ++ pulAddressArray = pArrayCommand->aulArrayData; ++ pulDataArray = pArrayCommand->aulArrayData + pArrayCommand->ulArrayLength; ++ ++ for ( i = 0; i < pArrayCommand->ulArrayLength; i++ ) ++ { ++ /* Copy parameters from packet payload to local read structure. */ ++ ReadParams.ulReadAddress = pulAddressArray[ i ]; ++ ++ /* Perform read access. */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) ++ if ( ulResult != cOCT6100_ERR_OK ) ++ break; ++ ++ /* Return read data. */ ++ if ( (i % 2) == 0 ) ++ pulDataArray[ i / 2 ] = (usReadData & 0xFFFF) << 16; ++ else /* ( (i % 2) == 1 ) */ ++ pulDataArray[ i / 2 ] |= (usReadData & 0xFFFF) << 0; ++ } ++ ++ /* Return result. */ ++ f_pCmndHeader->ulFunctionResult = ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcWriteWord ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_WRITE_WORD command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcWriteWord ++VOID Oct6100ApiRpcWriteWord( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_WRITE_WORD pWriteCommand; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Get pointer to command arguments. */ ++ pWriteCommand = ( tPOCT6100_RPC_WRITE_WORD )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ /* Set some read structure parameters. */ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Copy parameters from packet payload to local read structure. */ ++ WriteParams.ulWriteAddress = pWriteCommand->ulAddress; ++ WriteParams.usWriteData = (UINT16)pWriteCommand->ulWriteData; ++ ++ /* Perform write access. */ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) ++ ++ /* Return result. */ ++ f_pCmndHeader->ulFunctionResult = ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcWriteSmear ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_WRITE_SMEAR command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcWriteSmear ++VOID Oct6100ApiRpcWriteSmear( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_WRITE_SMEAR pSmearCommand; ++ tOCT6100_WRITE_SMEAR_PARAMS SmearParams; ++ UINT32 ulResult; ++ ++ /* Get pointer to command arguments. */ ++ pSmearCommand = ( tPOCT6100_RPC_WRITE_SMEAR )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ /* Set the smear structure parameters. */ ++ SmearParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ SmearParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Copy parameters from packet payload to local read structure. */ ++ SmearParams.ulWriteAddress = pSmearCommand->ulAddress; ++ SmearParams.usWriteData = (UINT16)pSmearCommand->ulWriteData; ++ SmearParams.ulWriteLength = pSmearCommand->ulSmearLength; ++ ++ /* Perform write access. */ ++ mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ) ++ ++ /* Return result. */ ++ f_pCmndHeader->ulFunctionResult = ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcWriteBurst ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_WRITE_BURST command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcWriteBurst ++VOID Oct6100ApiRpcWriteBurst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_WRITE_BURST pBurstCommand; ++ tOCT6100_WRITE_BURST_PARAMS BurstParams; ++ UINT32 ulResult; ++ UINT32 ulTempVar; ++ UINT32 i, j; ++ PUINT16 pusWriteData; ++ ++ /* Get local pointer to remote debugging write data buffer. */ ++ mOCT6100_GET_REMOTE_DEBUG_DATA_BUF_PNT( f_pApiInstance->pSharedInfo, pusWriteData ) ++ ++ /* Get pointer to command arguments. */ ++ pBurstCommand = ( tPOCT6100_RPC_WRITE_BURST )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ ulTempVar = (pBurstCommand->ulBurstLength + 1) / 2; ++ for ( i = 0, j = 0; i < ulTempVar; i++ ) ++ { ++ pusWriteData[ j++ ] = (UINT16)((pBurstCommand->aulWriteData[ i ] >> 16) & 0xFFFF); ++ pusWriteData[ j++ ] = (UINT16)((pBurstCommand->aulWriteData[ i ] >> 0) & 0xFFFF); ++ } ++ ++ /* Set some structure parameters. */ ++ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /* Copy parameters from packet payload to local read structure. */ ++ BurstParams.ulWriteAddress = pBurstCommand->ulAddress; ++ BurstParams.ulWriteLength = pBurstCommand->ulBurstLength; ++ BurstParams.pusWriteData = pusWriteData; ++ ++ /* Perform write access. */ ++ mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ) ++ ++ /* Return result. */ ++ f_pCmndHeader->ulFunctionResult = ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcSetHotChannel ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_SET_HOT_CHANNEL command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcSetHotChannel ++VOID Oct6100ApiRpcSetHotChannel( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_SET_HOT_CHANNEL pHotChanCommand; ++ tOCT6100_DEBUG_SELECT_CHANNEL DebugSelectChannel; ++ tPOCT6100_API_CHANNEL pChanEntry; ++ UINT32 ulResult; ++ ++ pHotChanCommand = ( tPOCT6100_RPC_SET_HOT_CHANNEL )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ /* Verify if the hot channel index is valid. */ ++ if ( pHotChanCommand->ulHotChannel >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ { ++ f_pCmndHeader->ulFunctionResult = cOCT6100_ERR_REMOTEDEBUG_INVALID_HOT_CHAN_INDEX; ++ return; ++ } ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, pHotChanCommand->ulHotChannel ); ++ ++ DebugSelectChannel.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pHotChanCommand->ulHotChannel; ++ ++ /* The PCM law parameter is now obsolete. */ ++ /* The instance knows the law of the channel being recorded! */ ++ ++ /* Call the function. */ ++ ulResult = Oct6100DebugSelectChannelSer( f_pApiInstance, &DebugSelectChannel, FALSE ); ++ ++ /* Return result. */ ++ f_pCmndHeader->ulFunctionResult = ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcGetDebugChanIndex ++ ++Description: Checks the provided portion of an OCTRPC packet and interprets ++ it as an cOCT6100_RPC_GET_DEBUG_CHAN_INDEX command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcGetDebugChanIndex ++VOID Oct6100ApiRpcGetDebugChanIndex( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ) ++{ ++ tPOCT6100_RPC_GET_DEBUG_CHAN_INDEX pDebugChanCommand; ++ ++ pDebugChanCommand = ( tPOCT6100_RPC_GET_DEBUG_CHAN_INDEX )(( PUINT32 )f_pCmndHeader + (sizeof( tOCTRPC_COMMAND_HEADER ) / 4)); ++ ++ /* Set the debug channel index of the structure. */ ++ pDebugChanCommand->ulDebugChanIndex = f_pApiInstance->pSharedInfo->DebugInfo.usRecordMemIndex; ++ ++ /* Return result. */ ++ f_pCmndHeader->ulFunctionResult = cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiRpcDisconnect ++ ++Description: Destroy the current session. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pCmndHeader Pointer to RPC command structure. ++f_ulSessionNumber Session number of the current remote debugging session. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiRpcDisconnect ++VOID Oct6100ApiRpcDisconnect( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader, ++ IN UINT32 f_ulSessionNumber ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_REMOTE_DEBUG_INFO pRemoteDebugInfo; ++ tPOCT6100_API_REMOTE_DEBUG_SESSION pSessionEntry; ++ tPOCT6100_API_REMOTE_DEBUG_SESSION pSessionTempEntry; ++ PVOID pSessionTree; ++ UINT32 ulResult; ++ PUINT32 pulTreeData; ++ UINT32 ulSessionIndex; ++ ++ f_pCmndHeader->ulFunctionResult = cOCT6100_ERR_OK; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Get a local pointer to the remote debugging info. */ ++ pRemoteDebugInfo = &pSharedInfo->RemoteDebugInfo; ++ ++ /* Check if the session number has an associated session list entry. */ ++ mOCT6100_GET_REMOTE_DEBUG_TREE_PNT( pSharedInfo, pSessionTree ) ++ ++ ulResult = octapi_bt0_query_node( pSessionTree, ( ( PVOID )(&f_ulSessionNumber) ), ( ( PVOID* )&pulTreeData ) ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ f_pCmndHeader->ulFunctionResult = cOCT6100_ERR_REMOTEDEBUG_INAVLID_SESSION_NUMBER; ++ ++ /* Return session index. */ ++ ulSessionIndex= *pulTreeData; ++ ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, ulSessionIndex, pSessionEntry ); ++ ++ /* Clear the entry of the session. */ ++ pSessionEntry->aulLastPktTime[ 0 ] = 0; ++ pSessionEntry->aulLastPktTime[ 1 ] = 0; ++ pSessionEntry->ulSessionNum = cOCT6100_INVALID_VALUE; ++ pSessionEntry->ulTransactionNum = cOCT6100_INVALID_VALUE; ++ pSessionEntry->ulPktRetryNum = cOCT6100_INVALID_VALUE; ++ ++ /* Update the other entry before removing the node. */ ++ pSessionEntry->ulBackwardLink = pRemoteDebugInfo->ulSessionListTail; ++ pSessionEntry->ulForwardLink = cOCT6100_INVALID_VALUE; ++ ++ if ( pSessionEntry->ulBackwardLink != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulBackwardLink, pSessionTempEntry ); ++ pSessionTempEntry->ulForwardLink = pSessionEntry->ulForwardLink; ++ } ++ else /* pSessionEntry->ulBackwardLink == cOCT6100_INVALID_VALUE */ ++ { ++ pRemoteDebugInfo->ulSessionListHead = pSessionEntry->ulForwardLink; ++ } ++ ++ if ( pSessionEntry->ulForwardLink != cOCT6100_INVALID_VALUE ) ++ { ++ mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, pSessionEntry->ulForwardLink, pSessionTempEntry ); ++ pSessionTempEntry->ulBackwardLink = pSessionEntry->ulBackwardLink; ++ } ++ else /* pSessionEntry->ulForwardLink == cOCT6100_INVALID_VALUE */ ++ { ++ pRemoteDebugInfo->ulSessionListTail = pSessionEntry->ulBackwardLink; ++ } ++ ++ /* Invalidate the pointer. */ ++ pSessionEntry->ulBackwardLink = cOCT6100_INVALID_VALUE; ++ pSessionEntry->ulForwardLink = cOCT6100_INVALID_VALUE; ++ ++ /* Remove the session. */ ++ ulResult = octapi_bt0_remove_node( pSessionTree, ( ( PVOID )&f_ulSessionNumber ) ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ f_pCmndHeader->ulFunctionResult = cOCT6100_ERR_FATAL_47; ++ ++ /* Increment number of open sessions. */ ++ pRemoteDebugInfo->ulNumSessionsOpen--; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,2056 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tlv.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the functions used to read information allowing the ++ API to know where all the features supported by this API version are ++ located in the chip's external memory. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 113 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++ ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_inst.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_tlv_priv.h" ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiProcessTlvRegion ++ ++Description: This function will read and interpret the TLV memory of the chip ++ to obtain memory offsets and features available of the image ++ loaded into the chip. ++ ++ The API will read this region until it finds a TLV type of 0 with ++ a length of 0. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiProcessTlvRegion ++UINT32 Oct6100ApiProcessTlvRegion( ++ tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT16 usReadData; ++ UINT32 ulResult; ++ ++ UINT32 ulTlvTypeField; ++ UINT32 ulTlvLengthField; ++ UINT32 ulTlvWritingTimeoutCount = 0; ++ UINT32 ulConditionFlag = TRUE; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Set the address of the first TLV type. */ ++ ReadParams.ulReadAddress = cOCT6100_TLV_BASE; ++ ReadParams.ulReadAddress += 2; ++ ++ /* Wait for the TLV configuration to be configured in memory. */ ++ while ( ulConditionFlag ) ++ { ++ /* Read the TLV write done flag. */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( usReadData & 0x1 ) ++ break; ++ ++ ulTlvWritingTimeoutCount++; ++ if ( ulTlvWritingTimeoutCount == 0x100000 ) ++ return cOCT6100_ERR_TLV_TIMEOUT; ++ } ++ ++ /*======================================================================*/ ++ /* Read the first 16 bits of the TLV type. */ ++ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvTypeField = usReadData << 16; ++ ++ /* Read the last word of the TLV type. */ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvTypeField |= usReadData; ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Now, read the TLV field length. */ ++ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvLengthField = usReadData << 16; ++ ++ /* Read the last word of the TLV length. */ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvLengthField |= usReadData; ++ ++ /* Modify the address to point at the TLV value field. */ ++ ReadParams.ulReadAddress += 2; ++ ++ /*======================================================================*/ ++ ++ /* Read the TLV value until the end of TLV region is reached. */ ++ while( !((ulTlvTypeField == 0) && (ulTlvLengthField == 0)) ) ++ { ++ ulResult = Oct6100ApiInterpretTlvEntry( f_pApiInstance, ++ ulTlvTypeField, ++ ulTlvLengthField, ++ ReadParams.ulReadAddress ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the address to after the TLV value. */ ++ ReadParams.ulReadAddress += ulTlvLengthField; ++ ++ /*======================================================================*/ ++ /* Read the first 16 bits of the TLV type. */ ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvTypeField = usReadData << 16; ++ ++ /* Read the last word of the TLV type. */ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvTypeField |= usReadData; ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Now, read the TLV field length. */ ++ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvLengthField = usReadData << 16; ++ ++ /* Read the last word of the TLV length. */ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulTlvLengthField |= usReadData; ++ ++ ReadParams.ulReadAddress += 2; ++ ++ /*======================================================================*/ ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInterpretTlvEntry ++ ++Description: This function will interpret a TLV entry from the chip. All ++ known TLV types by the API are exhaustively listed here. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulTlvFieldType Type of the TLV field to interpret. ++f_ulTlvFieldLength Byte length of the TLV field. ++f_ulTlvValueAddress Address where the data of the TLV block starts. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInterpretTlvEntry ++UINT32 Oct6100ApiInterpretTlvEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulTlvFieldType, ++ IN UINT32 f_ulTlvFieldLength, ++ IN UINT32 f_ulTlvValueAddress ) ++{ ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT16 usReadData; ++ UINT32 i; ++ UINT32 ulTempValue = 0; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /* Find out how to interpret the TLV value according to the TLV type. */ ++ switch( f_ulTlvFieldType ) ++ { ++ case cOCT6100_TLV_TYPE_VERSION_NUMBER: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_VERSION_NUMBER, ++ cOCT6100_TLV_MAX_LENGTH_VERSION_NUMBER ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ReadParams.ulReadAddress = f_ulTlvValueAddress; ++ ++ for( i = 0; i < (f_ulTlvFieldLength/2); i++ ) ++ { ++ /* Perform the actual read. */ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.szVersionNumber[ (i * 2) ] = (UINT8)((usReadData >> 8) & 0xFF); ++ f_pApiInstance->pSharedInfo->ImageInfo.szVersionNumber[ (i * 2) + 1 ] = (UINT8)((usReadData >> 0) & 0xFF); ++ ++ /* Modify the address. */ ++ ReadParams.ulReadAddress += 2; ++ } ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CUSTOMER_PROJECT_ID: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CUSTOMER_PROJECT_ID, ++ cOCT6100_TLV_MAX_LENGTH_CUSTOMER_PROJECT_ID ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Perform the actual read. */ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->ImageInfo.ulBuildId ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH0_MAIN_BASE_ADDRESS: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH0_MAIN_BASE_ADDRESS, ++ cOCT6100_TLV_MAX_LENGTH_CH0_MAIN_BASE_ADDRESS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase &= 0x0FFFFFFF; ++ ++ /* Modify the base address to incorporate the external memory offset. */ ++ f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase += cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_IO_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_IO_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_IO_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_ZCB_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_ZCB_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_ZCB_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_ZCB_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_ZCB_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_ZCB_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinCBMemSize ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_XCB_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_XCB_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_XCB_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_XCB_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_XCB_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_XCB_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSinCBMemSize ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_YCB_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_YCB_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_YCB_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_MAIN_YCB_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_MAIN_YCB_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_CH_MAIN_YCB_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutCBMemSize ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_FREE_MEM_BASE_ADDRESS: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_FREE_MEM_BASE_ADDRESS, ++ cOCT6100_TLV_MAX_LENGTH_FREE_MEM_BASE_ADDRESS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress &= 0x0FFFFFFF; ++ ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CHAN_MAIN_IO_STATS_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CHAN_MAIN_IO_STATS_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_CHAN_MAIN_IO_STATS_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsOfst ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CHAN_MAIN_IO_STATS_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CHAN_MAIN_IO_STATS_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_CHAN_MAIN_IO_STATS_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsSize ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CH_ROOT_CONF_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CH_ROOT_CONF_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_CH_ROOT_CONF_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ ++ case cOCT6100_TLV_TYPE_POA_CH_MAIN_ZPO_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_ZPO_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_ZPO_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_CH_MAIN_ZPO_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_ZPO_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_ZPO_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemSize ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_CH_MAIN_YPO_OFFSET: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_YPO_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_YPO_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_CH_MAIN_YPO_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_YPO_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_YPO_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemSize ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RW_ZWP: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZWP, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZWP ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RW_ZIS: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZIS, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZIS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RW_ZSP: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZSP, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZSP ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RW_YWP: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YWP, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YWP ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RW_YIS: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YIS, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YIS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RW_YSP: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YSP, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YSP ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RO_ZRP: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RO_ZRP, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RO_ZRP ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_POA_BOFF_RO_YRP: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RO_YRP, ++ cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RO_YRP ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CNR_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CNR_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_CNR_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_ANR_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_ANR_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_ANR_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_HZ_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_HZ_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_HZ_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst ); ++ } ++ /* Set flag indicating that the feature is present.*/ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRinDcOffsetRemoval = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_HX_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_HX_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_HX_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst ); ++ } ++ /* Set flag indicating that the feature is present.*/ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSinDcOffsetRemoval = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_LCA_Z_CONF_BOFF_RW_GAIN: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_LCA_Z_CONF_BOFF_RW_GAIN, ++ cOCT6100_TLV_MAX_LENGTH_LCA_Z_CONF_BOFF_RW_GAIN ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinLevelControlOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_LCA_Y_CONF_BOFF_RW_GAIN: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_LCA_Y_CONF_BOFF_RW_GAIN, ++ cOCT6100_TLV_MAX_LENGTH_LCA_Y_CONF_BOFF_RW_GAIN ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SoutLevelControlOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_CNA_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CNA_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_CNA_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ComfortNoiseModeOfst ); ++ } ++ /* Set flag indicating that the feature is present.*/ ++ f_pApiInstance->pSharedInfo->ImageInfo.fComfortNoise = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_NOA_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_NOA_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_NOA_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.NlpControlFieldOfst ); ++ } ++ /* Set flag indicating that the feature is present.*/ ++ f_pApiInstance->pSharedInfo->ImageInfo.fNlpControl = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_VFA_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_VFA_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_VFA_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.VadControlFieldOfst ); ++ } ++ /* Set flag indicating that the feature is present.*/ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSilenceSuppression = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_TLA_MAIN_IO_BOFF_RW_TAIL_DISP: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_TLA_MAIN_IO_BOFF_RW_TAIL_DISP, ++ cOCT6100_TLV_MAX_LENGTH_TLA_MAIN_IO_BOFF_RW_TAIL_DISP ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PouchTailDisplOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_BOOTA_POUCH_BOFF_RW_BOOT_INST: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_INST, ++ cOCT6100_TLV_MAX_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_INST ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PouchBootInstructionOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_BOOTA_POUCH_BOFF_RW_BOOT_RESULT: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_RESULT, ++ cOCT6100_TLV_MAX_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_RESULT ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PouchBootResultOfst ); ++ } ++ break; ++ ++ case cOCT6100_TLV_TYPE_TDM_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_TDM_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_TDM_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ToneDisablerControlOfst ); ++ } ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fToneDisabler = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_DIS_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DIS_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_DIS_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.TailDisplEnableOfst ); ++ } ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fTailDisplacement = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_NT_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_NT_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_NT_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.NlpTrivialFieldOfst ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_DEBUG_CHAN_INDEX_VALUE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_INDEX_VALUE, ++ cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_INDEX_VALUE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ } ++ ++ f_pApiInstance->pSharedInfo->DebugInfo.usRecordMemIndex = (UINT16)( ulTempValue & 0xFFFF ); ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_ADPCM_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_ADPCM_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_ADPCM_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ } ++ ++ if ( ulTempValue == 0 ) ++ f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm = FALSE; ++ else ++ f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm = TRUE; ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_CONFERENCING_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CONFERENCING_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_CONFERENCING_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ } ++ ++ if ( ulTempValue == 0 ) ++ f_pApiInstance->pSharedInfo->ImageInfo.fConferencing = FALSE; ++ else ++ f_pApiInstance->pSharedInfo->ImageInfo.fConferencing = TRUE; ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_TONE_DETECTOR_PROFILE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_TONE_DETECTOR_PROFILE, ++ cOCT6100_TLV_MIN_LENGTH_TONE_DETECTOR_PROFILE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->ImageInfo.ulToneProfileNumber ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MAX_TAIL_DISPLACEMENT: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MAX_TAIL_DISPLACEMENT, ++ cOCT6100_TLV_MAX_LENGTH_MAX_TAIL_DISPLACEMENT ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ UINT32 ulTailDispTempValue; ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTailDispTempValue ); ++ ++ ulTailDispTempValue += 1; /* Convert the value into milliseconds.*/ ++ ulTailDispTempValue *= 16; /* value was given in multiple of 16 ms. */ ++ ++ if ( ulTailDispTempValue >= 128 ) ++ f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailDisplacement = (UINT16)( ulTailDispTempValue - 128 ); ++ else ++ f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailDisplacement = 0; ++ ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_AEC_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_AEC_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_AEC_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AecFieldOfst ); ++ } ++ ++ /* Set the flag. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAecEnabled = TRUE; ++ ++ /* Acoustic echo cancellation available! */ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAcousticEcho = TRUE; ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_PCM_LEAK_CONF_BOFF_RW: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_PCM_LEAK_CONF_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_PCM_LEAK_CONF_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PcmLeakFieldOfst ); ++ } ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fNonLinearityBehaviorA = TRUE; ++ break; ++ ++ case cOCT6100_TLV_TYPE_DEFAULT_ERL_CONF_BOFF_RW: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DEFAULT_ERL_CONF_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_DEFAULT_ERL_CONF_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.DefaultErlFieldOfst ); ++ } ++ ++ /* Set the flag. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.fDefaultErl = TRUE; ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_TONE_REM_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_TONE_REM_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_TONE_REM_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ToneRemovalFieldOfst ); ++ } ++ ++ /* Set the flag. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.fToneRemoval = TRUE; ++ ++ break; ++ ++ ++ ++ case cOCT6100_TLV_TYPE_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT, ++ cOCT6100_TLV_MAX_LENGTH_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst ); ++ } ++ ++ /* Set the flag. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.fMaxEchoPoint = TRUE; ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_NLP_CONV_CAP_CONF_BOFF_RW: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_NLP_CONV_CAP_CONF_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_NLP_CONV_CAP_CONF_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.NlpConvCapFieldOfst ); ++ } ++ ++ /* Set the flag. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.fNonLinearityBehaviorB = TRUE; ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MATRIX_EVENT_SIZE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MATRIX_EVENT_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_MATRIX_EVENT_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulDebugEventSize ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_CNR_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CNR_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_CNR_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fConferencingNoiseReduction = (UINT8)( ulTempValue & 0xFF ); ++ ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.fConferencingNoiseReduction == TRUE ) ++ { ++ /* Set flag indicating that the dominant speaker feature is present. */ ++ f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled = TRUE; ++ } ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MAX_TAIL_LENGTH_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MAX_TAIL_LENGTH_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_MAX_TAIL_LENGTH_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailLength = (UINT16)( ulTempValue & 0xFFFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MAX_NUMBER_OF_CHANNELS: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MAX_NUMBER_OF_CHANNELS, ++ cOCT6100_TLV_MAX_LENGTH_MAX_NUMBER_OF_CHANNELS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels = (UINT16)( ulTempValue & 0xFFFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_PLAYOUT_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_PLAYOUT_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_PLAYOUT_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Set flag indicating that the feature is present. */ ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ f_pApiInstance->pSharedInfo->ImageInfo.fBufferPlayout = (UINT8)( ulTempValue & 0xFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_DOMINANT_SPEAKER_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DOMINANT_SPEAKER_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_DOMINANT_SPEAKER_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_TAIL_DISP_CONF_BOFF_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_TAIL_DISP_CONF_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_TAIL_DISP_CONF_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fPerChannelTailDisplacement = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_ANR_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_ANR_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_ANR_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAdaptiveNoiseReduction = (UINT8)( ulTempValue & 0xFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MUSIC_PROTECTION_RW_ENABLE: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MUSIC_PROTECTION_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_MUSIC_PROTECTION_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fMusicProtection = (UINT8)( ulTempValue & 0xFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_AEC_DEFAULT_ERL_BOFF: ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_AEC_DEFAULT_ERL_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_AEC_DEFAULT_ERL_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AecDefaultErlFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAecDefaultErl = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_Z_ALC_TARGET_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_Z_ALC_TARGET_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_Z_ALC_TARGET_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRinAutoLevelControl = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_Y_ALC_TARGET_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_Y_ALC_TARGET_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_Y_ALC_TARGET_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSoutAutoLevelControl = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_Z_HLC_TARGET_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_Z_HLC_TARGET_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_Z_HLC_TARGET_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRinHighLevelCompensation = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_Y_HLC_TARGET_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_Y_HLC_TARGET_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_Y_HLC_TARGET_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSoutHighLevelCompensation = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_ALC_HLC_STATUS_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_ALC_HLC_STATUS_BOFF_RW_ENABLE, ++ cOCT6100_TLV_MAX_LENGTH_ALC_HLC_STATUS_BOFF_RW_ENABLE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AlcHlcStatusOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAlcHlcStatus = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_Z_PLAYOUT_HARD_SKIP_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_Z_PLAYOUT_HARD_SKIP_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_Z_PLAYOUT_HARD_SKIP_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_Y_PLAYOUT_HARD_SKIP_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_Y_PLAYOUT_HARD_SKIP_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_Y_PLAYOUT_HARD_SKIP_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_AFT_FIELD_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_AFT_FIELD_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_AFT_FIELD_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AftControlOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAftControl = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_VOICE_DETECTED_STAT_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_VOICE_DETECTED_STAT_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_VOICE_DETECTED_STAT_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSinVoiceDetectedStat = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_GAIN_APPLIED_RIN_STAT_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_GAIN_APPLIED_RIN_STAT_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_GAIN_APPLIED_RIN_STAT_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRinAppliedGainStat = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_GAIN_APPLIED_SOUT_STAT_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_GAIN_APPLIED_SOUT_STAT_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_GAIN_APPLIED_SOUT_STAT_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSoutAppliedGainStat = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MAX_ADAPT_ALE_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MAX_ADAPT_ALE_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_MAX_ADAPT_ALE_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AdaptiveAleOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fListenerEnhancement = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_RIN_ANR_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_RIN_ANR_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_RIN_ANR_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinAnrOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRoutNoiseReduction = TRUE; ++ } ++ ++ break; ++ case cOCT6100_TLV_TYPE_RIN_ANR_VALUE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_RIN_ANR_VALUE_RW, ++ cOCT6100_TLV_MAX_LENGTH_RIN_ANR_VALUE_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinAnrValOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRoutNoiseReductionLevel = TRUE; ++ } ++ ++ break; ++ case cOCT6100_TLV_TYPE_RIN_MUTE_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_RIN_MUTE_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_RIN_MUTE_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinMuteOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRinMute = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_SIN_MUTE_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_SIN_MUTE_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_SIN_MUTE_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SinMuteOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSinMute = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_NUMBER_PLAYOUT_EVENTS: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_NUMBER_PLAYOUT_EVENTS, ++ cOCT6100_TLV_MAX_LENGTH_NUMBER_PLAYOUT_EVENTS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents = (UINT8)( ulTempValue & 0xFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_ANR_SNR_IMPROVEMENT_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_ANR_SNR_IMPROVEMENT_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_ANR_SNR_IMPROVEMENT_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AnrSnrEnhancementOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAnrSnrEnhancement = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_ANR_AGRESSIVITY_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_ANR_AGRESSIVITY_BOFF_RW, ++ cOCT6100_TLV_MAX_LENGTH_ANR_AGRESSIVITY_BOFF_RW ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_CHAN_TAIL_LENGTH_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CHAN_TAIL_LENGTH_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_CHAN_TAIL_LENGTH_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fPerChannelTailLength = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_CHAN_VQE_TONE_DISABLING_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_CHAN_VQE_TONE_DIS_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_CHAN_VQE_TONE_DIS_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_AF_TAIL_DISP_VALUE_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_AF_TAIL_DISP_VALUE_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_AF_TAIL_DISP_VALUE_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAfTailDisplacement = TRUE; ++ } ++ ++ break; ++ ++ ++ case cOCT6100_TLV_TYPE_POUCH_COUNTER_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_POUCH_COUNTER_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_POUCH_COUNTER_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.PouchCounterFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->DebugInfo.fPouchCounter = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_AEC_TAIL_LENGTH_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_AEC_TAIL_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_AEC_TAIL_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.AecTailLengthFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fAecTailLength = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MATRIX_DWORD_BASE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MATRIX_DWORD_BASE, ++ cOCT6100_TLV_MAX_LENGTH_MATRIX_DWORD_BASE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixBaseAddress ); ++ ++ /* Mask the upper bits set by the firmware. */ ++ f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixBaseAddress &= 0x0FFFFFFF; ++ ++ /* Modify the base address to incorporate the external memory offset. */ ++ f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixBaseAddress += cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_DEBUG_CHAN_STATS_BYTE_SIZE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_STATS_BYTE_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_STATS_BYTE_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_DEBUG_CHAN_LITE_STATS_BYTE_SIZE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_LITE_STATS_BYTE_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_LITE_STATS_BYTE_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_HOT_CHANNEL_SELECT_DWORD_BASE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_HOT_CHANNEL_SELECT_DWORD_BASE, ++ cOCT6100_TLV_MAX_LENGTH_HOT_CHANNEL_SELECT_DWORD_BASE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MATRIX_TIMESTAMP_DWORD_BASE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_TIMESTAMP_DWORD_BASE, ++ cOCT6100_TLV_MAX_LENGTH_TIMESTAMP_DWORD_BASE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixTimestampBaseAddress ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MATRIX_WP_DWORD_BASE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MATRIX_WP_DWORD_BASE, ++ cOCT6100_TLV_MAX_LENGTH_MATRIX_WP_DWORD_BASE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixWpBaseAddress ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_AF_WRITE_PTR_BYTE_OFFSET: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_AF_WRITE_PTR_BYTE_OFFSET, ++ cOCT6100_TLV_MAX_LENGTH_AF_WRITE_PTR_BYTE_OFFSET ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulAfWritePtrByteOffset ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_RECORDED_PCM_EVENT_BYTE_SIZE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_RECORDED_PCM_EVENT_BYTE_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_RECORDED_PCM_EVENT_BYTE_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_IS_ISR_CALLED_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_IS_ISR_CALLED_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_IS_ISR_CALLED_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.IsIsrCalledFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->DebugInfo.fIsIsrCalledField = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MUSIC_PROTECTION_ENABLE_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MUSIC_PROTECTION_ENABLE_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_MUSIC_PROTECTION_ENABLE_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.MusicProtectionFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fMusicProtectionConfiguration = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_IDLE_CODE_DETECTION_ENABLE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_IDLE_CODE_DETECTION, ++ cOCT6100_TLV_MAX_LENGTH_IDLE_CODE_DETECTION ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fIdleCodeDetection = (UINT8)( ulTempValue & 0xFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_IDLE_CODE_DETECTION_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_IDLE_CODE_DETECTION_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_IDLE_CODE_DETECTION_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_IMAGE_TYPE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_IMAGE_TYPE, ++ cOCT6100_TLV_MAX_LENGTH_IMAGE_TYPE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ /* Check if read image type value is what's expected. */ ++ if ( ( ulTempValue != cOCT6100_IMAGE_TYPE_WIRELINE ) ++ && ( ulTempValue != cOCT6100_IMAGE_TYPE_COMBINED ) ) ++ return cOCT6100_ERR_FATAL_E9; ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.byImageType = (UINT8)( ulTempValue & 0xFF ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_MAX_WIRELINE_CHANNELS: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_MAX_WIRELINE_CHANNELS, ++ cOCT6100_TLV_MAX_LENGTH_MAX_WIRELINE_CHANNELS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_AF_EVENT_CB_SIZE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_AF_EVENT_CB_BYTE_SIZE, ++ cOCT6100_TLV_MAX_LENGTH_AF_EVENT_CB_BYTE_SIZE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->DebugInfo.ulAfEventCbByteSize ); ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_BUFFER_PLAYOUT_SKIP_IN_EVENTS: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_BUFFER_PLAYOUT_SKIP_IN_EVENTS, ++ cOCT6100_TLV_MAX_LENGTH_BUFFER_PLAYOUT_SKIP_IN_EVENTS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_ZZ_ENERGY_CHAN_STATS_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_ZZ_ENERGY_CHAN_STATS_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_ZZ_ENERGY_CHAN_STATS_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fRinEnergyStat = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_YY_ENERGY_CHAN_STATS_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_YY_ENERGY_CHAN_STATS_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_YY_ENERGY_CHAN_STATS_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fSoutEnergyStat = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_DOUBLE_TALK_BEH_MODE: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DOUBLE_TALK_BEH_MODE, ++ cOCT6100_TLV_MAX_LENGTH_DOUBLE_TALK_BEH_MODE ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ if ( ulTempValue != 0 ) ++ f_pApiInstance->pSharedInfo->ImageInfo.fDoubleTalkBehavior = TRUE; ++ else ++ f_pApiInstance->pSharedInfo->ImageInfo.fDoubleTalkBehavior = FALSE; ++ ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_DOUBLE_TALK_BEH_MODE_BOFF: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DOUBLE_TALK_BEH_MODE_BOFF, ++ cOCT6100_TLV_MAX_LENGTH_DOUBLE_TALK_BEH_MODE_BOFF ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &f_pApiInstance->pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst ); ++ ++ f_pApiInstance->pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst = TRUE; ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_SOUT_NOISE_BLEACHING: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_SOUT_NOISE_BLEACHING, ++ cOCT6100_TLV_MAX_LENGTH_SOUT_NOISE_BLEACHING ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ if ( ulTempValue != 0 ) ++ f_pApiInstance->pSharedInfo->ImageInfo.fSoutNoiseBleaching = TRUE; ++ else ++ f_pApiInstance->pSharedInfo->ImageInfo.fSoutNoiseBleaching = FALSE; ++ ++ } ++ ++ break; ++ ++ case cOCT6100_TLV_TYPE_NLP_STATISTICS: ++ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_NLP_STATISTICS, ++ cOCT6100_TLV_MAX_LENGTH_NLP_STATISTICS ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReadDword( f_pApiInstance, ++ f_ulTlvValueAddress, ++ &ulTempValue ); ++ ++ if ( ulTempValue != 0 ) ++ f_pApiInstance->pSharedInfo->ImageInfo.fSinLevel = TRUE; ++ else ++ f_pApiInstance->pSharedInfo->ImageInfo.fSinLevel = FALSE; ++ ++ } ++ ++ break; ++ ++ default: ++ /* Unknown TLV type field... check default length and nothing else. */ ++ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, ++ cOCT6100_TLV_MIN_LENGTH_DEFAULT, ++ cOCT6100_TLV_MAX_LENGTH_DEFAULT ); ++ break; ++ } ++ ++ return ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiTlvCheckLengthField ++ ++Description: This function validates the TLV length field. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_ulTlvFieldLength Length field read from the TLV. ++f_ulMinLengthValue Minimum value supported for the TLV. ++f_ulMaxLengthValue Maximum value supported for the TLV. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiTlvCheckLengthField ++UINT32 Oct6100ApiTlvCheckLengthField( ++ IN UINT32 f_ulTlvFieldLength, ++ IN UINT32 f_ulMinLengthValue, ++ IN UINT32 f_ulMaxLengthValue ) ++{ ++ /* Check if the value is too small. */ ++ if ( f_ulTlvFieldLength < f_ulMinLengthValue ) ++ return ( cOCT6100_ERR_FATAL_59 ); ++ ++ /* Check if the value is too big. */ ++ if ( f_ulTlvFieldLength > f_ulMaxLengthValue ) ++ return ( cOCT6100_ERR_FATAL_5A ); ++ ++ /* Check if the value is dword aligned. */ ++ if ( ( f_ulTlvFieldLength % 4 ) != 0 ) ++ return ( cOCT6100_ERR_OPEN_INVALID_TLV_LENGTH ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiTlvReadBitOffsetStruct ++ ++Description: This function extracts a bit offset structure from the TLV. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulAddress Address where the read the TLV information. ++f_pBitOffsetStruct Pointer to a bit offset stucture. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiTlvReadBitOffsetStruct ++UINT32 Oct6100ApiTlvReadBitOffsetStruct( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulAddress, ++ OUT tPOCT6100_TLV_OFFSET f_pBitOffsetStruct ) ++{ ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT16 usReadData; ++ ++ UINT32 ulResult; ++ UINT32 ulOffsetValue; ++ UINT32 ulSizeValue; ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ /*======================================================================*/ ++ /* Read the first 16 bits of the TLV field. */ ++ ++ ReadParams.ulReadAddress = f_ulAddress; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulOffsetValue = usReadData << 16; ++ ++ /* Read the last word of the TLV type. */ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulOffsetValue |= usReadData; ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Read the first 16 bits of the TLV field. */ ++ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulSizeValue = usReadData << 16; ++ ++ /* Read the last word of the TLV type. */ ++ ReadParams.ulReadAddress += 2; ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Save data. */ ++ ulSizeValue |= usReadData; ++ ++ /*======================================================================*/ ++ ++ /* Set the structure fields. */ ++ f_pBitOffsetStruct->usDwordOffset = (UINT16)(ulOffsetValue / 32); ++ f_pBitOffsetStruct->byBitOffset = (UINT8) (32 - (ulOffsetValue % 32) - ulSizeValue); ++ f_pBitOffsetStruct->byFieldSize = (UINT8) (ulSizeValue); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1088 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tone_detection.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to enable and disable tone detection on ++ an echo channel. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 51 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_tone_detection_inst.h" ++#include "oct6100api/oct6100_events_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_tone_detection_pub.h" ++#include "oct6100api/oct6100_events_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_tone_detection_priv.h" ++#include "oct6100_events_priv.h" ++ ++ ++/**************************** PUBLIC FUNCTIONS *****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ToneDetectionEnable ++ ++Description: This function enables the generation of event for a selected ++ tone on the specified channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pToneDetectEnable Pointer to tone detection enable structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ToneDetectionEnableDef ++UINT32 Oct6100ToneDetectionEnableDef( ++ tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable ) ++{ ++ f_pToneDetectEnable->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pToneDetectEnable->ulToneNumber = cOCT6100_INVALID_TONE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100ToneDetectionEnable ++UINT32 Oct6100ToneDetectionEnable( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ToneDetectionEnableSer( f_pApiInstance, f_pToneDetectEnable ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ToneDetectionDisable ++ ++Description: This function disables the detection of a tone for a specific ++ channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pToneDetectDisable Pointer to tone detection disable structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ToneDetectionDisableDef ++UINT32 Oct6100ToneDetectionDisableDef( ++ tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable ) ++{ ++ f_pToneDetectDisable->ulChannelHndl = cOCT6100_INVALID_HANDLE; ++ f_pToneDetectDisable->ulToneNumber = cOCT6100_INVALID_VALUE; ++ f_pToneDetectDisable->fDisableAll = FALSE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++#if !SKIP_Oct6100ToneDetectionDisable ++UINT32 Oct6100ToneDetectionDisable( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100ToneDetectionDisableSer( f_pApiInstance, f_pToneDetectDisable ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ToneDetectionEnableSer ++ ++Description: Activate the detection of a tone on the specified channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pToneDetectEnable Pointer to tone detect enable structure. This structure ++ contains, among other things, the tone ID to enable ++ and the channel handle where detection should be ++ enabled. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ToneDetectionEnableSer ++UINT32 Oct6100ToneDetectionEnableSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable ) ++{ ++ UINT32 ulChanIndex; ++ UINT32 ulExtToneChanIndex; ++ UINT32 ulToneEventNumber = 0; ++ ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the tone detection for errors. */ ++ ulResult = Oct6100ApiCheckToneEnableParams( ++ f_pApiInstance, ++ f_pToneDetectEnable, ++ &ulChanIndex, ++ &ulToneEventNumber, ++ ++ &ulExtToneChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write to all resources needed to enable tone detection. */ ++ ulResult = Oct6100ApiWriteToneDetectEvent( ++ f_pApiInstance, ++ ulChanIndex, ++ ulToneEventNumber, ++ ++ ulExtToneChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the channel entry to indicate that a new tone has been activated. */ ++ ulResult = Oct6100ApiUpdateChanToneDetectEntry( ++ f_pApiInstance, ++ ulChanIndex, ++ ulToneEventNumber, ++ ulExtToneChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckToneEnableParams ++ ++Description: Check the validity of the channel and tone requested. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pToneDetectEnable Pointer to tone detection enable structure. ++f_pulChannelIndex Pointer to the channel index. ++f_pulToneEventNumber Pointer to the Index of the tone associated to the requested tone. ++f_pulExtToneChanIndex Pointer to the index of the extended channel index. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckToneEnableParams ++UINT32 Oct6100ApiCheckToneEnableParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulToneEventNumber, ++ ++ OUT PUINT32 f_pulExtToneChanIndex ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ UINT32 ulEntryOpenCnt; ++ UINT32 i; ++ ++ /*=====================================================================*/ ++ /* Check the channel handle. */ ++ ++ if ( (f_pToneDetectEnable->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; ++ ++ *f_pulChannelIndex = f_pToneDetectEnable->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; ++ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pToneDetectEnable->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChannel->fReserved != TRUE ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; ++ ++ /* Set the extended tone detection info if it is activated on the channel. */ ++ *f_pulExtToneChanIndex = pEchoChannel->usExtToneChanIndex; ++ ++ /*=====================================================================*/ ++ /* Check the tone information. */ ++ ++ /* Find out if the tone is present in the build. */ ++ for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) ++ { ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ i ].ulToneID == f_pToneDetectEnable->ulToneNumber ) ++ { ++ *f_pulToneEventNumber = i; ++ break; ++ } ++ } ++ ++ /* Check if tone is present. */ ++ if ( i == cOCT6100_MAX_TONE_EVENT ) ++ return cOCT6100_ERR_NOT_SUPPORTED_TONE_NOT_PRESENT_IN_FIRMWARE; ++ ++ /* Check if the requested tone is actually detected. */ ++ if ((( pEchoChannel->aulToneConf[ *f_pulToneEventNumber / 32 ] >> ( 31 - ( *f_pulToneEventNumber % 32 ))) & 0x1) == 1 ) ++ return cOCT6100_ERR_TONE_DETECTION_TONE_ACTIVATED; ++ ++ ++ ++ /*=====================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteToneDetectEvent ++ ++Description: Write the tone detection event in the channel main structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulChannelIndex Index of the channel within the API's channel list. ++f_ulToneEventNumber Event number of the tone to be activated. ++f_ulExtToneChanIndex Index of the extended tone detection channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteToneDetectEvent ++UINT32 Oct6100ApiWriteToneDetectEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ ++ IN UINT32 f_ulExtToneChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 ulResult; ++ UINT16 usReadData; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*=======================================================================*/ ++ /* Read the current event config about to be modified. */ ++ ++ ReadParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ReadParams.ulReadAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ++ ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ /* Set the tone event in the channel main memory for the requested direction. */ ++ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = usReadData; ++ WriteParams.usWriteData |= ( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 ))); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*=======================================================================*/ ++ /* Also program the extended channel if one is present. */ ++ ++ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Read the current event config about to be modified. */ ++ ReadParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulExtToneChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ReadParams.ulReadAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ++ ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write the tone event in the channel main memory for the requested direction. */ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = usReadData; ++ WriteParams.usWriteData |= ( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 ))); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateChanToneDetectEntry ++ ++Description: Update the echo channel entry to store the info about the tone ++ being configured to generate detection events. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulChannelIndex Index of the channel within the API's channel list. ++f_ulToneEventNumber Enabled tone event number. ++f_ulExtToneChanIndex Index of the extended tone detection channel. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateChanToneDetectEntry ++UINT32 Oct6100ApiUpdateChanToneDetectEntry ( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ IN UINT32 f_ulExtToneChanIndex ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulToneEntry; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Update the channel entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulChannelIndex ); ++ ++ /* Set the corresponding bit in the channel array. */ ++ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; ++ ++ /* Modify the entry. */ ++ ulToneEntry |= ( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 ))); ++ ++ /* Copy back the new value. */ ++ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; ++ ++ /* Configure also the extended channel if necessary. */ ++ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Update the channel entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulExtToneChanIndex ); ++ ++ /* Set the corresponding bit in the channel array. */ ++ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; ++ ++ /* Modify the entry. */ ++ ulToneEntry |= ( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 ))); ++ ++ /* Copy back the new value. */ ++ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; ++ } ++ ++ /* Check for the SS tone events that could have been generated before. */ ++ if ( f_ulExtToneChanIndex == cOCT6100_INVALID_INDEX ) ++ { ++ BOOL fSSTone; ++ UINT32 ulResult; ++ ++ ulResult = Oct6100ApiIsSSTone( f_pApiInstance, pSharedInfo->ImageInfo.aToneInfo[ f_ulToneEventNumber ].ulToneID, &fSSTone ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Is this a signaling system tone? */ ++ if ( fSSTone == TRUE ) ++ { ++ /* Check if must generate an event for the last detected SS tone. */ ++ if ( ( pEchoChanEntry->ulLastSSToneDetected != cOCT6100_INVALID_INDEX ) ++ && ( pEchoChanEntry->ulLastSSToneDetected == pSharedInfo->ImageInfo.aToneInfo[ f_ulToneEventNumber ].ulToneID ) ) ++ { ++ /* Must write an event for this. */ ++ tPOCT6100_API_TONE_EVENT pSoftEvent; ++ ++ /* If enough space. */ ++ if ( ( ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr ) && ++ ( ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0 ) ) ++ { ++ /* Form the event for this captured tone. */ ++ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) ++ pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ++ ++ pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_ulChannelIndex; ++ pSoftEvent->ulUserChanId = pEchoChanEntry->ulUserChanId; ++ pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ f_ulToneEventNumber ].ulToneID; ++ pSoftEvent->ulTimestamp = pEchoChanEntry->ulLastSSToneTimestamp; ++ pSoftEvent->ulExtToneDetectionPort = cOCT6100_INVALID_VALUE; ++ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; ++ ++ /* Update the control variables of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; ++ if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) ++ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; ++ ++ /* Set the interrupt manager such that the user knows that some tone events */ ++ /* are pending in the software Q. */ ++ pSharedInfo->IntrptManage.fToneEventsPending = TRUE; ++ } ++ else ++ { ++ /* Set the overflow flag of the buffer. */ ++ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; ++ } ++ } ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ToneDetectionDisableSer ++ ++Description: Disable the generation of events for a selected tone on the ++ specified channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pToneDetectDisable Pointer to tOCT6100_TONE_DETECTION_DISABLE structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ToneDetectionDisableSer ++UINT32 Oct6100ToneDetectionDisableSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable ) ++{ ++ UINT32 ulChanIndex; ++ UINT32 ulExtToneChanIndex; ++ UINT32 ulToneEventNumber = 0; ++ UINT32 ulResult; ++ BOOL fDisableAll; ++ ++ ++ /* Check the user's configuration of the tone detection disable structure for errors. */ ++ ulResult = Oct6100ApiAssertToneDetectionParams( ++ f_pApiInstance, ++ f_pToneDetectDisable, ++ &ulChanIndex, ++ &ulToneEventNumber, ++ &ulExtToneChanIndex, ++ ++ &fDisableAll ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear the event to detect the specified tone. */ ++ ulResult = Oct6100ApiClearToneDetectionEvent( ++ f_pApiInstance, ++ ulChanIndex, ++ ulToneEventNumber, ++ ulExtToneChanIndex, ++ ++ fDisableAll ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the channel structure to indicate that the tone is no longer detected. */ ++ ulResult = Oct6100ApiReleaseToneDetectionEvent( ++ f_pApiInstance, ++ ulChanIndex, ++ ulToneEventNumber, ++ ulExtToneChanIndex, ++ fDisableAll ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertToneDetectionParams ++ ++Description: Check the validity of the tone detection disable command. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pToneDetectDisable Pointer to tone detection disable structure. ++f_pulChannelIndex Pointer to the channel index ++f_pulToneEventNumber Pointer to the tone event number. ++f_pulExtToneChanIndex Pointer to the extended channel index. ++f_pfDisableAll Pointer to the flag specifying whether all tones ++ should be disabled. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertToneDetectionParams ++UINT32 Oct6100ApiAssertToneDetectionParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulToneEventNumber, ++ OUT PUINT32 f_pulExtToneChanIndex, ++ ++ OUT PBOOL f_pfDisableAll ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChannel; ++ UINT32 ulEntryOpenCnt; ++ UINT32 i; ++ ++ /*=====================================================================*/ ++ /* Check the echo channel handle. */ ++ ++ if ( (f_pToneDetectDisable->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; ++ ++ *f_pulChannelIndex = f_pToneDetectDisable->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; ++ if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; ++ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pToneDetectDisable->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pEchoChannel->fReserved != TRUE ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_NOT_OPEN; ++ if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) ++ return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; ++ ++ /* Return the extended channel index. */ ++ *f_pulExtToneChanIndex = pEchoChannel->usExtToneChanIndex; ++ ++ /* Check the disable all flag. */ ++ if ( f_pToneDetectDisable->fDisableAll != TRUE && f_pToneDetectDisable->fDisableAll != FALSE ) ++ return cOCT6100_ERR_TONE_DETECTION_DISABLE_ALL; ++ ++ /*=====================================================================*/ ++ /* Check the tone information. */ ++ ++ /* Find out if the tone is present in the build. */ ++ if ( f_pToneDetectDisable->fDisableAll == FALSE ) ++ { ++ for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) ++ { ++ if ( f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ i ].ulToneID == f_pToneDetectDisable->ulToneNumber ) ++ { ++ *f_pulToneEventNumber = i; ++ break; ++ } ++ } ++ ++ /* Check if tone is present. */ ++ if ( i == cOCT6100_MAX_TONE_EVENT ) ++ return cOCT6100_ERR_NOT_SUPPORTED_TONE_NOT_PRESENT_IN_FIRMWARE; ++ ++ ++ ++ /* Check if the requested tone is actually detected. */ ++ if ((( pEchoChannel->aulToneConf[ *f_pulToneEventNumber / 32 ] >> ( 31 - ( *f_pulToneEventNumber % 32 ))) & 0x1) == 0 ) ++ return cOCT6100_ERR_TONE_DETECTION_TONE_NOT_ACTIVATED; ++ } ++ ++ ++ /*=====================================================================*/ ++ ++ /* Return the disable all flag as requested. */ ++ *f_pfDisableAll = f_pToneDetectDisable->fDisableAll; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiClearToneDetectionEvent ++ ++Description: Clear the buffer playout event in the channel main structure. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulChannelIndex Index of the channel within the API's channel list. ++f_ulToneEventNumber Tone event number to be deactivated. ++f_ulExtToneChanIndex Index of the extended tone detection channel. ++f_fDisableAll Clear all activated tones. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiClearToneDetectionEvent ++UINT32 Oct6100ApiClearToneDetectionEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ IN UINT32 f_ulExtToneChanIndex, ++ ++ IN BOOL f_fDisableAll ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ tOCT6100_WRITE_SMEAR_PARAMS SmearParams; ++ UINT32 ulResult; ++ UINT32 ulToneEventBaseAddress; ++ UINT16 usReadData; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ ++ ++ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ReadParams.pusReadData = &usReadData; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ SmearParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ SmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*=======================================================================*/ ++ /* Read the current event config about to be modified. */ ++ ++ ulToneEventBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ulToneEventBaseAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ++ ++ /* Check if must disable all tone events or not. */ ++ if ( f_fDisableAll == FALSE ) ++ { ++ ReadParams.ulReadAddress = ulToneEventBaseAddress; ++ ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear the event in the channel main memory.*/ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = usReadData; ++ WriteParams.usWriteData &= (~( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 )))); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else /* if ( f_fDisableAll == TRUE ) */ ++ { ++ /* Clear all events in the channel main memory. */ ++ SmearParams.ulWriteLength = 4; ++ SmearParams.usWriteData = 0x0000; ++ SmearParams.ulWriteAddress = ulToneEventBaseAddress; ++ mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ ++ /*=======================================================================*/ ++ /* Also program the extended channel if one is present. */ ++ ++ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) ++ { ++ ulToneEventBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulExtToneChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ++ ulToneEventBaseAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ++ ++ /* Check if must disable all tone events or not. */ ++ if ( f_fDisableAll == FALSE ) ++ { ++ /* Read the current event config about to be modified. */ ++ ReadParams.ulReadAddress = ulToneEventBaseAddress; ++ ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; ++ ++ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Clear the event in the channel main memory.*/ ++ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; ++ WriteParams.usWriteData = usReadData; ++ WriteParams.usWriteData &= (~( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 )))); ++ ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ else /* if ( f_fDisableAll == TRUE ) */ ++ { ++ /* Clear all events in the channel main memory.*/ ++ SmearParams.ulWriteLength = 4; ++ SmearParams.usWriteData = 0x0000; ++ SmearParams.ulWriteAddress = ulToneEventBaseAddress; ++ mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseToneDetectionEvent ++ ++Description: Clear the entry made for this tone in the channel tone ++ enable array. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulChannelIndex Index of the channel within the API's channel list. ++f_ulToneEventNumber Tone event number to be deactivated. ++f_ulExtToneChanIndex Index of the extended tone detection channel. ++f_fDisableAll Release all activated tones. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseToneDetectionEvent ++UINT32 Oct6100ApiReleaseToneDetectionEvent ( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ IN UINT32 f_ulExtToneChanIndex, ++ IN BOOL f_fDisableAll ) ++{ ++ tPOCT6100_API_CHANNEL pEchoChanEntry; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulToneEntry; ++ UINT32 ulResult; ++ UINT32 ulToneEventNumber; ++ BOOL fSSTone; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Update the channel entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulChannelIndex ); ++ ++ /* Check if must release all tone events. */ ++ if ( f_fDisableAll == FALSE ) ++ { ++ /* Set the corresponding bit in the channel array. */ ++ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; ++ ++ /* Modify the entry. */ ++ ulToneEntry &= (~( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 )))); ++ ++ /* Copy back the new value. */ ++ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; ++ } ++ else /* if ( f_fDisableAll == TRUE ) */ ++ { ++ /* Clear all events. */ ++ Oct6100UserMemSet( pEchoChanEntry->aulToneConf, 0x00, sizeof( pEchoChanEntry->aulToneConf ) ); ++ } ++ ++ /* Configure also the extended channel if necessary. */ ++ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) ++ { ++ /* Update the channel entry. */ ++ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulExtToneChanIndex ); ++ ++ /* Check if must release all tone events. */ ++ if ( f_fDisableAll == FALSE ) ++ { ++ /* Set the corresponding bit in the channel array. */ ++ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; ++ ++ /* Modify the entry. */ ++ ulToneEntry &= (~( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 )))); ++ ++ /* Copy back the new value. */ ++ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; ++ } ++ else /* if ( f_fDisableAll == TRUE ) */ ++ { ++ /* Clear all events. */ ++ Oct6100UserMemSet( pEchoChanEntry->aulToneConf, 0x00, sizeof( pEchoChanEntry->aulToneConf ) ); ++ } ++ } ++ ++ /* Re-enable the SS7 tones */ ++ for ( ulToneEventNumber = 0; ulToneEventNumber < cOCT6100_MAX_TONE_EVENT; ulToneEventNumber++ ) ++ { ++ /* Check if the current tone is a SS tone. */ ++ ulResult = Oct6100ApiIsSSTone( ++ f_pApiInstance, ++ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID, ++ &fSSTone ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ if ( fSSTone == TRUE ) ++ { ++ /* Write to all resources needed to activate tone detection on this SS tone. */ ++ ulResult = Oct6100ApiWriteToneDetectEvent( ++ f_pApiInstance, ++ f_ulChannelIndex, ++ ulToneEventNumber, ++ ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiIsSSTone ++ ++Description: Check if specified tone number is a special signaling ++ system tone. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulToneEventNumber Tone event number to be checked against. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiIsSSTone ++UINT32 Oct6100ApiIsSSTone( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulToneEventNumber, ++ OUT PBOOL f_fSSTone ) ++{ ++ *f_fSSTone = FALSE; ++ ++ switch( f_ulToneEventNumber ) ++ { ++ case cOCT6100_TONE_SIN_SYSTEM7_2000 : ++ case cOCT6100_TONE_SIN_SYSTEM7_1780 : ++ case cOCT6100_TONE_ROUT_G168_2100GB_ON : ++ case cOCT6100_TONE_ROUT_G168_2100GB_WSPR : ++ case cOCT6100_TONE_ROUT_G168_1100GB_ON : ++ case cOCT6100_TONE_ROUT_G168_2100GB_ON_WIDE_A : ++ case cOCT6100_TONE_ROUT_G168_2100GB_ON_WIDE_B : ++ case cOCT6100_TONE_ROUT_G168_2100GB_WSPR_WIDE : ++ case cOCT6100_TONE_SOUT_G168_2100GB_ON : ++ case cOCT6100_TONE_SOUT_G168_2100GB_WSPR : ++ case cOCT6100_TONE_SOUT_G168_1100GB_ON : ++ case cOCT6100_TONE_SOUT_G168_2100GB_ON_WIDE_A : ++ case cOCT6100_TONE_SOUT_G168_2100GB_ON_WIDE_B : ++ case cOCT6100_TONE_SOUT_G168_2100GB_WSPR_WIDE : ++ case cOCT6100_TONE_SIN_SYSTEM5_2400 : ++ case cOCT6100_TONE_SIN_SYSTEM5_2600 : ++ case cOCT6100_TONE_SIN_SYSTEM5_2400_2600 : ++ *f_fSSTone = TRUE; ++ break; ++ default: ++ break; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiIsSSTone ++ ++Description: Check if specified tone number is a 2100 special signaling ++ system tone. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_ulToneEventNumber Tone event number to be checked against. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiIs2100Tone ++UINT32 Oct6100ApiIs2100Tone( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulToneEventNumber, ++ OUT PBOOL f_fIs2100Tone ) ++{ ++ *f_fIs2100Tone = FALSE; ++ ++ switch( f_ulToneEventNumber ) ++ { ++ case cOCT6100_TONE_ROUT_G168_2100GB_ON : ++ case cOCT6100_TONE_ROUT_G168_2100GB_WSPR : ++ case cOCT6100_TONE_ROUT_G168_2100GB_ON_WIDE_A : ++ case cOCT6100_TONE_ROUT_G168_2100GB_ON_WIDE_B : ++ case cOCT6100_TONE_ROUT_G168_2100GB_WSPR_WIDE : ++ case cOCT6100_TONE_SOUT_G168_2100GB_ON : ++ case cOCT6100_TONE_SOUT_G168_2100GB_WSPR : ++ case cOCT6100_TONE_SOUT_G168_2100GB_ON_WIDE_A : ++ case cOCT6100_TONE_SOUT_G168_2100GB_ON_WIDE_B : ++ case cOCT6100_TONE_SOUT_G168_2100GB_WSPR_WIDE : ++ *f_fIs2100Tone = TRUE; ++ break; ++ default: ++ break; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1023 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tsi_cnct.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains functions used to open and close TSI connections ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 38 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_apiud.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_channel_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_tsi_cnct_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_tsi_cnct_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_miscellaneous_priv.h" ++#include "oct6100_memory_priv.h" ++#include "oct6100_tsst_priv.h" ++#include "oct6100_channel_priv.h" ++#include "oct6100_tsi_cnct_priv.h" ++ ++/**************************** PUBLIC FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100TsiCnctOpen ++ ++Description: This function opens a TSI connection between two TDM timeslots. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctOpen Pointer to TSI connection open structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100TsiCnctOpenDef ++UINT32 Oct6100TsiCnctOpenDef( ++ tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ) ++{ ++ f_pTsiCnctOpen->pulTsiCnctHndl = NULL; ++ ++ f_pTsiCnctOpen->ulInputTimeslot = cOCT6100_INVALID_TIMESLOT; ++ f_pTsiCnctOpen->ulInputStream = cOCT6100_INVALID_STREAM; ++ f_pTsiCnctOpen->ulOutputTimeslot = cOCT6100_INVALID_TIMESLOT; ++ f_pTsiCnctOpen->ulOutputStream = cOCT6100_INVALID_STREAM; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100TsiCnctOpen ++UINT32 Oct6100TsiCnctOpen( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100TsiCnctOpenSer( f_pApiInstance, f_pTsiCnctOpen ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100TsiCnctClose ++ ++Description: This function closes a TSI connection. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctClose Pointer to TSI connection close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100TsiCnctCloseDef ++UINT32 Oct6100TsiCnctCloseDef( ++ tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose ) ++{ ++ f_pTsiCnctClose->ulTsiCnctHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++#if !SKIP_Oct6100TsiCnctClose ++UINT32 Oct6100TsiCnctClose( ++ tPOCT6100_INSTANCE_API f_pApiInstance, ++ tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose ) ++{ ++ tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; ++ tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; ++ UINT32 ulSerRes = cOCT6100_ERR_OK; ++ UINT32 ulFncRes = cOCT6100_ERR_OK; ++ ++ /* Set the process context of the serialize structure. */ ++ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ /* Seize all list semaphores needed by this function. */ ++ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ++ ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); ++ if ( ulSerRes == cOCT6100_ERR_OK ) ++ { ++ /* Call the serialized function. */ ++ ulFncRes = Oct6100TsiCnctCloseSer( f_pApiInstance, f_pTsiCnctClose ); ++ } ++ else ++ { ++ return ulSerRes; ++ } ++ ++ /* Release the seized semaphores. */ ++ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ++ ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); ++ ++ /* If an error occured then return the error code. */ ++ if ( ulSerRes != cOCT6100_ERR_OK ) ++ return ulSerRes; ++ if ( ulFncRes != cOCT6100_ERR_OK ) ++ return ulFncRes; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetTsiCnctSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management the TSI memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pOpenChip Pointer to chip configuration struct. ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetTsiCnctSwSizes ++UINT32 Oct6100ApiGetTsiCnctSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Determine the amount of memory required for the API TSI connection list. */ ++ f_pInstSizes->ulTsiCnctList = f_pOpenChip->ulMaxTsiCncts * sizeof( tOCT6100_API_TSI_CNCT ); ++ ++ if ( f_pOpenChip->ulMaxTsiCncts > 0 ) ++ { ++ /* Calculate memory needed for TSI memory allocation. */ ++ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxTsiCncts, &f_pInstSizes->ulTsiCnctAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_48; ++ } ++ else ++ { ++ f_pInstSizes->ulTsiCnctAlloc = 0; ++ } ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsiCnctList, ulTempVar ) ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsiCnctAlloc, ulTempVar ) ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiTsiCnctSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to the TSI memory. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiTsiCnctSwInit ++UINT32 Oct6100ApiTsiCnctSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_API_TSI_CNCT pChannelsTsiList; ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulMaxTsiChannels; ++ PVOID pTsiChannelsAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Initialize the TSI connections API list. */ ++ ulMaxTsiChannels = pSharedInfo->ChipConfig.usMaxTsiCncts; ++ ++ mOCT6100_GET_TSI_CNCT_LIST_PNT( pSharedInfo, pChannelsTsiList ) ++ ++ /* Clear the memory. */ ++ Oct6100UserMemSet( pChannelsTsiList, 0x00, sizeof(tOCT6100_API_TSI_CNCT) * ulMaxTsiChannels ); ++ ++ /* Set all entries in the TSI connections list to unused. */ ++ if ( ulMaxTsiChannels > 0 ) ++ { ++ mOCT6100_GET_TSI_CNCT_ALLOC_PNT( pSharedInfo, pTsiChannelsAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pTsiChannelsAlloc, ulMaxTsiChannels ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_49; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100TsiCnctOpenSer ++ ++Description: Opens a TSI connection. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctOpen Pointer to a tOCT6100_TSI_CNCT_OPEN structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100TsiCnctOpenSer ++UINT32 Oct6100TsiCnctOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ) ++{ ++ UINT16 usTsiChanIndex; ++ UINT16 usTsiMemIndex; ++ UINT16 usInputTsstIndex; ++ UINT16 usOutputTsstIndex; ++ UINT32 ulResult; ++ ++ /* Check the user's configuration of the TSI connection open structure for errors. */ ++ ulResult = Oct6100ApiCheckTsiParams( f_pApiInstance, f_pTsiCnctOpen ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Reserve all resources needed by the TSI connection. */ ++ ulResult = Oct6100ApiReserveTsiResources( f_pApiInstance, f_pTsiCnctOpen, &usTsiChanIndex, &usTsiMemIndex, &usInputTsstIndex, &usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Write all necessary structures to activate the TSI connection. */ ++ ulResult = Oct6100ApiWriteTsiStructs( f_pApiInstance, f_pTsiCnctOpen, usTsiMemIndex, usInputTsstIndex, usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Update the TSI connection entry in the API list. */ ++ ulResult = Oct6100ApiUpdateTsiEntry( f_pApiInstance, f_pTsiCnctOpen, usTsiChanIndex, usTsiMemIndex, usInputTsstIndex, usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiCheckTsiParams ++ ++Description: Checks the user's TSI connection open configuration for errors. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctOpen Pointer to TSI connection open configuration structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiCheckTsiParams ++UINT32 Oct6100ApiCheckTsiParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ) ++{ ++ UINT32 ulResult; ++ ++ /* Check for errors. */ ++ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxTsiCncts == 0 ) ++ return cOCT6100_ERR_TSI_CNCT_DISABLED; ++ ++ if ( f_pTsiCnctOpen->pulTsiCnctHndl == NULL ) ++ return cOCT6100_ERR_TSI_CNCT_INVALID_HANDLE; ++ ++ /* Check the input TDM streams, timeslots component for errors. */ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ cOCT6100_NUMBER_TSSTS_1, ++ f_pTsiCnctOpen->ulInputTimeslot, ++ f_pTsiCnctOpen->ulInputStream, ++ cOCT6100_INPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_TSI_CNCT_INPUT_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_TSI_CNCT_INPUT_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ ++ /* Check the output TDM streams, timeslots component for errors. */ ++ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ++ cOCT6100_NUMBER_TSSTS_1, ++ f_pTsiCnctOpen->ulOutputTimeslot, ++ f_pTsiCnctOpen->ulOutputStream, ++ cOCT6100_OUTPUT_TSST ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) ++ { ++ return cOCT6100_ERR_TSI_CNCT_OUTPUT_TIMESLOT; ++ } ++ else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) ++ { ++ return cOCT6100_ERR_TSI_CNCT_OUTPUT_STREAM; ++ } ++ else ++ { ++ return ulResult; ++ } ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveTsiResources ++ ++Description: Reserves all resources needed for the new TSI connection. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctOpen Pointer to tsi channel configuration structure. ++f_pusTsiChanIndex Allocated entry in TSI channel list. ++f_pusTsiMemIndex Allocated entry in the TSI control memory. ++f_pusInputTsstIndex TSST memory index of the input samples. ++f_pusOutputTsstIndex TSST memory index of the output samples. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveTsiResources ++UINT32 Oct6100ApiReserveTsiResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen, ++ OUT PUINT16 f_pusTsiChanIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ UINT32 ulResult; ++ UINT32 ulTempVar; ++ BOOL fTsiChanEntry = FALSE; ++ BOOL fTsiMemEntry = FALSE; ++ BOOL fInputTsst = FALSE; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Reserve an entry in the TSI connection list. */ ++ ulResult = Oct6100ApiReserveTsiCnctEntry( f_pApiInstance, f_pusTsiChanIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fTsiChanEntry = TRUE; ++ ++ /* Find a TSI memory entry. */ ++ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, f_pusTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fTsiMemEntry = TRUE; ++ ++ /* Reserve the input TSST entry. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ f_pTsiCnctOpen->ulInputTimeslot, ++ f_pTsiCnctOpen->ulInputStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_INPUT_TSST, ++ f_pusInputTsstIndex, ++ NULL ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ fInputTsst = TRUE; ++ ++ /* Reserve the output TSST entry. */ ++ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, ++ f_pTsiCnctOpen->ulOutputTimeslot, ++ f_pTsiCnctOpen->ulOutputStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_OUTPUT_TSST, ++ f_pusOutputTsstIndex, ++ NULL ); ++ } ++ } ++ else ++ { ++ /* Return an error other then a fatal. */ ++ ulResult = cOCT6100_ERR_TSI_CNCT_NO_MORE_TSI_AVAILABLE; ++ } ++ } ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if( fTsiChanEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiCnctEntry( f_pApiInstance, *f_pusTsiChanIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fTsiMemEntry == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, *f_pusTsiMemIndex ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ if( fInputTsst == TRUE ) ++ { ++ ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, ++ f_pTsiCnctOpen->ulInputTimeslot, ++ f_pTsiCnctOpen->ulInputStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulTempVar != cOCT6100_ERR_OK ) ++ return ulTempVar; ++ } ++ ++ return ulResult; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiWriteTsiStructs ++ ++Description: Performs all the required structure writes to configure the ++ new TSI connection. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctOpen Pointer to tsi connection open structure. ++f_usTsiMemIndex Allocated entry in the TSI control memory. ++f_usInputTsstIndex TSST memory index of the input samples. ++f_usOutputTsstIndex TSST memory index of the output samples. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiWriteTsiStructs ++UINT32 Oct6100ApiWriteTsiStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*==================================================================================*/ ++ /* Configure the TSST control memory.*/ ++ ++ /* Set the input TSST control entry.*/ ++ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, ++ f_usInputTsstIndex, ++ f_usTsiMemIndex, ++ cOCT6100_PCM_U_LAW ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the output TSST control entry. */ ++ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, ++ f_usOutputTsstIndex, ++ cOCT6100_ADPCM_IN_LOW_BITS, ++ 1, ++ f_usTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==================================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiUpdateTsiEntry ++ ++Description: Updates the new TSI connection in the TSI connection list. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pTsiCnctOpen Pointer to TSI connection open configuration structure. ++f_usTsiMemIndex Allocated entry in TSI chariot memory. ++f_usTsiChanIndex Allocated entry in the TSI channel list. ++f_usInputTsstIndex TSST control memory index of the input TSST. ++f_usOutputTsstIndex TSST control memory index of the output TSST. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiUpdateTsiEntry ++UINT32 Oct6100ApiUpdateTsiEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen, ++ IN UINT16 f_usTsiChanIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ) ++{ ++ tPOCT6100_API_TSI_CNCT pTsiCnctEntry; ++ ++ /*================================================================================*/ ++ /* Obtain a pointer to the new TSI connection's list entry. */ ++ ++ mOCT6100_GET_TSI_CNCT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsiCnctEntry, f_usTsiChanIndex ) ++ ++ /* Copy the TSI's configuration and allocated resources. */ ++ pTsiCnctEntry->usInputTimeslot = (UINT16)( f_pTsiCnctOpen->ulInputTimeslot & 0xFFFF ); ++ pTsiCnctEntry->usInputStream = (UINT16)( f_pTsiCnctOpen->ulInputStream & 0xFFFF ); ++ ++ pTsiCnctEntry->usOutputTimeslot = (UINT16)( f_pTsiCnctOpen->ulOutputTimeslot & 0xFFFF ); ++ pTsiCnctEntry->usOutputStream = (UINT16)( f_pTsiCnctOpen->ulOutputStream & 0xFFFF ); ++ ++ /* Store hardware related information. */ ++ pTsiCnctEntry->usTsiMemIndex = f_usTsiMemIndex; ++ pTsiCnctEntry->usInputTsstIndex = f_usInputTsstIndex; ++ pTsiCnctEntry->usOutputTsstIndex = f_usOutputTsstIndex; ++ ++ /* Form handle returned to user. */ ++ *f_pTsiCnctOpen->pulTsiCnctHndl = cOCT6100_HNDL_TAG_TSI_CNCT | (pTsiCnctEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_usTsiChanIndex; ++ ++ /* Finally, mark the connection as opened. */ ++ pTsiCnctEntry->fReserved = TRUE; ++ ++ /* Increment the number of TSI connection opened. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberTsiCncts++; ++ ++ /*================================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100TsiCnctCloseSer ++ ++Description: Closes a TSI connection. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctClose Pointer to TSI connection close structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100TsiCnctCloseSer ++UINT32 Oct6100TsiCnctCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose ) ++{ ++ UINT16 usTsiChanIndex; ++ UINT16 usTsiMemIndex; ++ UINT16 usInputTsstIndex; ++ UINT16 usOutputTsstIndex; ++ UINT32 ulResult; ++ ++ /* Verify that all the parameters given match the state of the API. */ ++ ulResult = Oct6100ApiAssertTsiParams( f_pApiInstance, f_pTsiCnctClose, &usTsiChanIndex, &usTsiMemIndex, &usInputTsstIndex, &usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the TSI channel. */ ++ ulResult = Oct6100ApiInvalidateTsiStructs( f_pApiInstance, usInputTsstIndex, usOutputTsstIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Release all resources associated to the TSI connection. */ ++ ulResult = Oct6100ApiReleaseTsiResources( f_pApiInstance, usTsiChanIndex, usTsiMemIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Invalidate the handle. */ ++ f_pTsiCnctClose->ulTsiCnctHndl = cOCT6100_INVALID_HANDLE; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiAssertTsiParams ++ ++Description: Validate the handle given by the user and verify the state of ++ the TSI connection about to be closed. ++ Also returns all required information to deactivate the connection. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_pTsiCnctClose Pointer to TSI connection close structure. ++f_pusTsiChanIndex Index of the TSI connection structure in the API list. ++f_pusTsiMemIndex Index of the TSI entry within the TSI chariot memory ++f_pusInputTsstIndex Index of the input entry in the TSST control memory. ++f_pusOutputTsstIndex Index of the output entry in the TSST control memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiAssertTsiParams ++UINT32 Oct6100ApiAssertTsiParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose, ++ OUT PUINT16 f_pusTsiChanIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_TSI_CNCT pTsiEntry; ++ UINT32 ulEntryOpenCnt; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Check the provided handle. */ ++ if ( (f_pTsiCnctClose->ulTsiCnctHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_TSI_CNCT ) ++ return cOCT6100_ERR_TSI_CNCT_INVALID_HANDLE; ++ ++ *f_pusTsiChanIndex = (UINT16)( f_pTsiCnctClose->ulTsiCnctHndl & cOCT6100_HNDL_INDEX_MASK ); ++ ++ if ( *f_pusTsiChanIndex >= pSharedInfo->ChipConfig.usMaxTsiCncts ) ++ return cOCT6100_ERR_TSI_CNCT_INVALID_HANDLE; ++ ++ /*=======================================================================*/ ++ /* Get a pointer to the channel's list entry. */ ++ ++ mOCT6100_GET_TSI_CNCT_ENTRY_PNT( pSharedInfo, pTsiEntry, *f_pusTsiChanIndex ) ++ ++ /* Extract the entry open count from the provided handle. */ ++ ulEntryOpenCnt = (f_pTsiCnctClose->ulTsiCnctHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; ++ ++ /* Check for errors. */ ++ if ( pTsiEntry->fReserved != TRUE ) ++ return cOCT6100_ERR_TSI_CNCT_NOT_OPEN; ++ if ( ulEntryOpenCnt != pTsiEntry->byEntryOpenCnt ) ++ return cOCT6100_ERR_TSI_CNCT_INVALID_HANDLE; ++ ++ /* Return info needed to close the channel and release all resources. */ ++ *f_pusInputTsstIndex = pTsiEntry->usInputTsstIndex; ++ *f_pusOutputTsstIndex = pTsiEntry->usOutputTsstIndex; ++ *f_pusTsiMemIndex = pTsiEntry->usTsiMemIndex; ++ ++ /*=======================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiInvalidateTsiStructs ++ ++Description: This function closes a TSI connection. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usInputTsstIndex Index of the input entry in the TSST control memory. ++f_usOutputTsstIndex Index of the output entry in the TSST control memory. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiInvalidateTsiStructs ++UINT32 Oct6100ApiInvalidateTsiStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tOCT6100_WRITE_PARAMS WriteParams; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; ++ ++ WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ++ ++ /*==================================================================================*/ ++ /* Deactivate the TSST control memory. */ ++ ++ /* Set the input TSST control entry to unused. */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( f_usInputTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = 0x0000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /* Set the output TSST control entry to unused. */ ++ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( f_usOutputTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); ++ ++ WriteParams.usWriteData = 0x0000; ++ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return ulResult; ++ ++ /*==================================================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseTsiResources ++ ++Description: Release and clear the API entry associated to the TSI channel. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep the ++ present state of the chip and all its resources. ++ ++f_usTsiChanIndex Index of the TSI connection in the API list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseTsiResources ++UINT32 Oct6100ApiReleaseTsiResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsiChanIndex, ++ IN UINT16 f_usTsiMemIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_TSI_CNCT pTsiEntry; ++ UINT32 ulResult; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_TSI_CNCT_ENTRY_PNT( pSharedInfo, pTsiEntry, f_usTsiChanIndex ); ++ ++ /* Release the entry in the TSI connection list. */ ++ ulResult = Oct6100ApiReleaseTsiCnctEntry( f_pApiInstance, f_usTsiChanIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, f_usTsiMemIndex ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Release the input entry. */ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTsiEntry->usInputTimeslot, ++ pTsiEntry->usInputStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_INPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ if ( ulResult == cOCT6100_ERR_OK ) ++ { ++ /* Release the output TSST entry. */ ++ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ++ pTsiEntry->usOutputTimeslot, ++ pTsiEntry->usOutputStream, ++ cOCT6100_NUMBER_TSSTS_1, ++ cOCT6100_OUTPUT_TSST, ++ cOCT6100_INVALID_INDEX ); ++ } ++ } ++ } ++ ++ /* Check if an error occured while releasing the reserved resources. */ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult >= cOCT6100_ERR_FATAL ) ++ return ulResult; ++ else ++ return cOCT6100_ERR_FATAL_4A; ++ } ++ ++ /*=============================================================*/ ++ /* Update the TSI connection's list entry. */ ++ ++ /* Mark the connection as closed. */ ++ pTsiEntry->fReserved = FALSE; ++ pTsiEntry->byEntryOpenCnt++; ++ ++ /* Decrement the number of TSI connection opened. */ ++ f_pApiInstance->pSharedInfo->ChipStats.usNumberTsiCncts--; ++ ++ /*=============================================================*/ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveTsiCnctEntry ++ ++Description: Reserves one of the TSI connection API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_pusTsiChanIndex Resulting index reserved in the TSI channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveTsiCnctEntry ++UINT32 Oct6100ApiReserveTsiCnctEntry( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusTsiChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pTsiChanAlloc; ++ UINT32 ulResult; ++ UINT32 ulTsiIndex; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_TSI_CNCT_ALLOC_PNT( pSharedInfo, pTsiChanAlloc ) ++ ++ ulResult = OctapiLlmAllocAlloc( pTsiChanAlloc, &ulTsiIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ return cOCT6100_ERR_TSI_CNCT_ALL_CHANNELS_ARE_OPENED; ++ else ++ return cOCT6100_ERR_FATAL_4B; ++ } ++ ++ *f_pusTsiChanIndex = (UINT16)( ulTsiIndex & 0xFFFF ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseTsiCnctEntry ++ ++Description: Releases the specified TSI connection API entry. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This memory is used to keep ++ the present state of the chip and all its resources. ++ ++f_usTsiChanIndex Index reserved in the TSI channel list. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseTsiCnctEntry ++UINT32 Oct6100ApiReleaseTsiCnctEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsiChanIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pTsiChanAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_TSI_CNCT_ALLOC_PNT( pSharedInfo, pTsiChanAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pTsiChanAlloc, f_usTsiChanIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_4C; ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,575 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tsst.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the functions used to manage the allocation of TSST ++ control structures in internal memory. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 39 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "octdef.h" ++ ++#include "oct6100api/oct6100_defines.h" ++#include "oct6100api/oct6100_errors.h" ++ ++#include "apilib/octapi_llman.h" ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_tlv_inst.h" ++#include "oct6100api/oct6100_chip_open_inst.h" ++#include "oct6100api/oct6100_chip_stats_inst.h" ++#include "oct6100api/oct6100_interrupts_inst.h" ++#include "oct6100api/oct6100_remote_debug_inst.h" ++#include "oct6100api/oct6100_debug_inst.h" ++#include "oct6100api/oct6100_api_inst.h" ++#include "oct6100api/oct6100_tsst_inst.h" ++ ++#include "oct6100api/oct6100_interrupts_pub.h" ++#include "oct6100api/oct6100_channel_pub.h" ++#include "oct6100api/oct6100_chip_open_pub.h" ++ ++#include "oct6100_chip_open_priv.h" ++#include "oct6100_tsst_priv.h" ++ ++ ++/**************************** PRIVATE FUNCTIONS ****************************/ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiGetTsstSwSizes ++ ++Description: Gets the sizes of all portions of the API instance pertinent ++ to the management of TSSTs. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pInstSizes Pointer to struct containing instance sizes. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiGetTsstSwSizes ++UINT32 Oct6100ApiGetTsstSwSizes( ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) ++{ ++ UINT32 ulTempVar; ++ UINT32 ulResult; ++ ++ /* Determine amount of TSST needed for TSST allocation table. */ ++ f_pInstSizes->ulTsstAlloc = 4096 / 8; ++ ++ /* Calculate the API memory required for the TSST entry list. */ ++ f_pInstSizes->ulTsstEntryList = cOCT6100_MAX_TSSTS * sizeof( tOCT6100_API_TSST_ENTRY ); ++ ++ /* Calculate memory needed for TSST entry allocation. */ ++ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_TSSTS, &f_pInstSizes->ulTsstEntryAlloc ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_4D; ++ ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsstAlloc, ulTempVar ); ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsstEntryList, ulTempVar ); ++ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsstEntryAlloc, ulTempVar ); ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiTsstSwInit ++ ++Description: Initializes all elements of the instance structure associated ++ to the TSST control entries. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This tsst is used to keep ++ the present state of the chip and all its resources. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiTsstSwInit ++UINT32 Oct6100ApiTsstSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_TSST_ENTRY pTsstList; ++ PUINT32 pulTsstAlloc; ++ PVOID pTsstListAlloc; ++ UINT32 ulResult; ++ ++ /* Get local pointer(s). */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ /* Initialize the TSST allocation table to "all free". */ ++ mOCT6100_GET_TSST_ALLOC_PNT( pSharedInfo, pulTsstAlloc ); ++ Oct6100UserMemSet( pulTsstAlloc, 0x00, 512 ); ++ ++ /* Initialize all the TSST list entries. */ ++ mOCT6100_GET_TSST_LIST_PNT( pSharedInfo, pTsstList ); ++ Oct6100UserMemSet( pTsstList, 0xFF, cOCT6100_MAX_TSSTS * sizeof(tOCT6100_API_TSST_ENTRY) ); ++ ++ /* Initialize the allocation list to manage the TSST entries.*/ ++ mOCT6100_GET_TSST_LIST_ALLOC_PNT( pSharedInfo, pTsstListAlloc ) ++ ++ ulResult = OctapiLlmAllocInit( &pTsstListAlloc, cOCT6100_MAX_TSSTS ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_FATAL_4E; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiValidateTsst ++ ++Description: Validates a timeslot, stream combination. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This tsst is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulTimeslot Timeslot component of the TDM TSST. ++f_ulStream Stream component of the TDM TSST. ++f_ulNumTssts Number of TSST required. ++f_ulDirection Direction of the TSST (Input or Output). ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiValidateTsst ++UINT32 Oct6100ApiValidateTsst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulNumTssts, ++ IN UINT32 f_ulTimeslot, ++ IN UINT32 f_ulStream, ++ IN UINT32 f_ulDirection ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ tPOCT6100_API_CHIP_CONFIG pChipConfig; ++ PUINT32 pulTsstAlloc; ++ ++ /* Obtain local pointer to shared portion of instance. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_TSST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pulTsstAlloc ); ++ ++ /* Obtain local pointer to chip configuration. */ ++ pChipConfig = &pSharedInfo->ChipConfig; ++ ++ /* Check the TDM streams, timeslots component for errors. */ ++ if ( f_ulTimeslot == cOCT6100_UNASSIGNED && ++ f_ulStream != cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_TSST_TIMESLOT; ++ ++ if ( f_ulTimeslot != cOCT6100_UNASSIGNED && ++ f_ulStream == cOCT6100_UNASSIGNED ) ++ return cOCT6100_ERR_TSST_STREAM; ++ ++ if ( f_ulStream >= pChipConfig->byMaxTdmStreams ) ++ return cOCT6100_ERR_TSST_STREAM; ++ ++ /* Check timeslot value based on the frequenccy of the selected stream. */ ++ switch ( pChipConfig->aulTdmStreamFreqs[ f_ulStream / 4 ] ) ++ { ++ case cOCT6100_TDM_STREAM_FREQ_2MHZ: ++ if ( f_ulTimeslot >= 32 ) ++ return cOCT6100_ERR_TSST_TIMESLOT; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_4MHZ: ++ if ( f_ulTimeslot >= 64 ) ++ return cOCT6100_ERR_TSST_TIMESLOT; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_8MHZ: ++ if ( f_ulTimeslot >= 128 ) ++ return cOCT6100_ERR_TSST_TIMESLOT; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_16MHZ: ++ if ( f_ulTimeslot >= 256 ) ++ return cOCT6100_ERR_TSST_TIMESLOT; ++ ++ /* Check the stream value based on the direction. */ ++ if ( f_ulDirection == cOCT6100_INPUT_TSST && f_ulStream >= 16 ) ++ { ++ return cOCT6100_ERR_TSST_STREAM; ++ } ++ else if( f_ulDirection == cOCT6100_OUTPUT_TSST && f_ulStream < 16 ) ++ { ++ return cOCT6100_ERR_TSST_STREAM; ++ } ++ ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_DC; ++ } ++ ++ /* Stream must be odd if two TSSTs are required. */ ++ if ( f_ulNumTssts == 2 && ( ( f_ulStream & 0x1) != 0x1 ) ) ++ return cOCT6100_ERR_TSST_STREAM; ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReserveTsst ++ ++Description: Reserves a TSST, only one TSI entry can access a TSST at any one ++ time. ++ If the pointer f_pulTsstListIndex is set to NULL, no TSST list ++ entry will be reserved. ++ ++ The index in TSST control memory returned is based on the frequency ++ of the streams where the TSST is located and on the direction of ++ the TSST ( input or output ). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This tsst is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulTimeslot Timeslot component of the TDM TSST. ++f_ulNumTssts Number of TSSTs required. ++f_ulStream Stream component of the TDM TSST. ++f_ulDirection Whether the TSST in and input TSST or output TSST. ++f_pusTsstMemIndex Index of the resulting TSST in the TSST control memory. ++f_pusTsstListIndex Index in the TSST list of the current entry. ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReserveTsst ++UINT32 Oct6100ApiReserveTsst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulTimeslot, ++ IN UINT32 f_ulStream, ++ IN UINT32 f_ulNumTsst, ++ IN UINT32 f_ulDirection, ++ OUT PUINT16 f_pusTsstMemIndex, ++ OUT PUINT16 f_pusTsstListIndex ) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PVOID pTsstListAlloc; ++ PUINT32 pulTsstAlloc; ++ UINT32 ulResult = cOCT6100_ERR_OK; ++ UINT32 ulStream; ++ UINT32 ulTimeslot; ++ ++ /* Get local pointer to shared portion of API instance structure. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ mOCT6100_GET_TSST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pulTsstAlloc ); ++ ++ /*==================================================================================*/ ++ /* Now make the proper conversion to obtain the TSST value. */ ++ ++ /* Save the timeslot and stream value received. */ ++ ulStream = f_ulStream; ++ ulTimeslot = f_ulTimeslot; ++ ++ /* Set the TSST index associated to this stream, timeslot combination. */ ++ switch ( f_pApiInstance->pSharedInfo->ChipConfig.aulTdmStreamFreqs[ f_ulStream / 4 ] ) ++ { ++ case cOCT6100_TDM_STREAM_FREQ_16MHZ: ++ if ( f_ulDirection == cOCT6100_INPUT_TSST ) ++ { ++ ulStream = f_ulStream + ( f_ulTimeslot % 2 ) * 16; ++ ulTimeslot = f_ulTimeslot / 2; ++ } ++ else /* f_ulDirection == cOCT6100_OUTPUT_TSST */ ++ { ++ ulStream = ( f_ulStream - 16 ) + ( f_ulTimeslot % 2 ) * 16; ++ ++ if ( f_ulStream < 28 && ((f_ulTimeslot % 2) == 1) ) ++ { ++ ulTimeslot = ((f_ulTimeslot / 2) + 4) % 128; ++ } ++ else ++ { ++ ulTimeslot = f_ulTimeslot / 2 ; ++ } ++ } ++ ++ *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 + ulStream ); ++ break; ++ ++ case cOCT6100_TDM_STREAM_FREQ_8MHZ: ++ *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 + ulStream ); ++ break; ++ ++ case cOCT6100_TDM_STREAM_FREQ_4MHZ: ++ *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 * 2 ); ++ if ( f_ulDirection == cOCT6100_OUTPUT_TSST ) ++ { ++ *f_pusTsstMemIndex = (UINT16)( *f_pusTsstMemIndex + ulStream ); ++ } ++ else /* if ( f_ulDirection == cOCT6100_INPUT_TSST ) */ ++ { ++ *f_pusTsstMemIndex = (UINT16)( ( 1 * 32 + ulStream ) + *f_pusTsstMemIndex ); ++ } ++ break; ++ ++ case cOCT6100_TDM_STREAM_FREQ_2MHZ: ++ *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 * 4 ); ++ if ( f_ulDirection == cOCT6100_OUTPUT_TSST ) ++ { ++ *f_pusTsstMemIndex = (UINT16)( ulStream + *f_pusTsstMemIndex ); ++ } ++ else /* if ( f_ulDirection == cOCT6100_INPUT_TSST ) */ ++ { ++ *f_pusTsstMemIndex = (UINT16)( ( 3 * 32 + ulStream ) + *f_pusTsstMemIndex ); ++ } ++ break; ++ ++ default: ++ ulResult = cOCT6100_ERR_FATAL_8B; ++ } ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* First reserve the TSST. */ ++ ++ /* Get local pointer to TSST's entry in allocation table. */ ++ switch ( pSharedInfo->ChipConfig.aulTdmStreamFreqs[ ulStream / 4 ] ) ++ { ++ case cOCT6100_TDM_STREAM_FREQ_2MHZ: ++ ulTimeslot *= 4; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_4MHZ: ++ ulTimeslot *= 2; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_8MHZ: ++ ulTimeslot *= 1; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_16MHZ: ++ ulTimeslot *= 1; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_DD; ++ } ++ ++ /* Check if entry is already reserved. */ ++ if ( ((pulTsstAlloc[ ulTimeslot ] >> ulStream) & 0x1) == 0x1 ) ++ return cOCT6100_ERR_TSST_TSST_RESERVED; ++ ++ /* Check and reserve the associated TSST if required. */ ++ if ( f_ulNumTsst == 2 ) ++ { ++ /* Check if entry is already reserved. */ ++ if ( ((pulTsstAlloc[ ulTimeslot ] >> (ulStream - 1) ) & 0x1) == 0x1 ) ++ return cOCT6100_ERR_TSST_ASSOCIATED_TSST_RESERVED; ++ ++ /* The entry is free, it won't anymore. */ ++ pulTsstAlloc[ ulTimeslot ] |= (0x1 << (ulStream - 1)); ++ } ++ ++ /* The entry is free, it won't anymore.*/ ++ pulTsstAlloc[ ulTimeslot ] |= (0x1 << ulStream); ++ ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Now reserve a TSST entry if requested. */ ++ ++ if ( f_pusTsstListIndex != NULL && ulResult == cOCT6100_ERR_OK ) ++ { ++ UINT32 ulTsstListIndex; ++ ++ /* Reserve a TSST entry in the API TSST list. */ ++ mOCT6100_GET_TSST_LIST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pTsstListAlloc ); ++ ++ ulResult = OctapiLlmAllocAlloc( pTsstListAlloc, &ulTsstListIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ++ ulResult = cOCT6100_ERR_TSST_ALL_TSSTS_ARE_OPENED; ++ else ++ ulResult = cOCT6100_ERR_FATAL_52; ++ } ++ ++ *f_pusTsstListIndex = (UINT16)( ulTsstListIndex & 0xFFFF ); ++ } ++ /*======================================================================*/ ++ ++ ++ /*======================================================================*/ ++ /* Check the result of the TSST list reservation. */ ++ ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ /* Release the previously reserved TSST. */ ++ if ( f_ulNumTsst == 2 ) ++ { ++ /* Clear the entry. */ ++ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << (ulStream - 1) ); ++ ++ } ++ ++ /* Clear the entry. */ ++ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << ulStream); ++ } ++ ++ /*======================================================================*/ ++ ++ return ulResult; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100ApiReleaseTsst ++ ++Description: Releases a TSST. ++ ++ If f_usTsstListIndex is set to cOCT6100_INVALID_INDEX, the API ++ will assume that no TSST list entry was reserved for this TSST. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pApiInstance Pointer to API instance. This tsst is used to keep ++ the present state of the chip and all its resources. ++ ++f_ulNumTssts Number of TSSTs to be released. ++f_ulStream Stream component of the TDM TSST. ++f_ulTimeslot Timeslot component of the TDM TSST. ++f_ulDirection Whether the TSST is an input TSST or output TSST. ++f_usTsstListIndex Index in the TSST list of the current entry. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100ApiReleaseTsst ++UINT32 Oct6100ApiReleaseTsst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulTimeslot, ++ IN UINT32 f_ulStream, ++ IN UINT32 f_ulNumTsst, ++ IN UINT32 f_ulDirection, ++ IN UINT16 f_usTsstListIndex) ++{ ++ tPOCT6100_SHARED_INFO pSharedInfo; ++ PUINT32 pulTsstAlloc; ++ PVOID pTsstListAlloc; ++ UINT32 ulResult; ++ UINT32 ulStream; ++ UINT32 ulTimeslot; ++ ++ /* Get local pointer to shared portion of API instance structure. */ ++ pSharedInfo = f_pApiInstance->pSharedInfo; ++ ++ if ( f_usTsstListIndex != cOCT6100_INVALID_INDEX ) ++ { ++ mOCT6100_GET_TSST_LIST_ALLOC_PNT( pSharedInfo, pTsstListAlloc ) ++ ++ ulResult = OctapiLlmAllocDealloc( pTsstListAlloc, f_usTsstListIndex ); ++ if ( ulResult != cOCT6100_ERR_OK ) ++ { ++ return cOCT6100_ERR_FATAL_53; ++ } ++ } ++ ++ mOCT6100_GET_TSST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pulTsstAlloc ); ++ ++ /*==================================================================================*/ ++ /* Now make the proper conversion to obtain the TSST value. */ ++ ++ /* Save the timeslot and stream value received. */ ++ ulStream = f_ulStream; ++ ulTimeslot = f_ulTimeslot; ++ ++ /* Set the TSST index associated to this stream, timeslot combination. */ ++ if ( pSharedInfo->ChipConfig.aulTdmStreamFreqs[ f_ulStream / 4 ] == cOCT6100_TDM_STREAM_FREQ_16MHZ ) ++ { ++ if ( f_ulDirection == cOCT6100_INPUT_TSST ) ++ { ++ ulStream = f_ulStream + ( f_ulTimeslot % 2 ) * 16; ++ ulTimeslot = f_ulTimeslot / 2; ++ } ++ else /* f_ulDirection == cOCT6100_OUTPUT_TSST */ ++ { ++ ulStream = ( f_ulStream - 16 ) + ( f_ulTimeslot % 2 ) * 16; ++ ++ if ( f_ulStream < 28 && ((f_ulTimeslot % 2) == 1) ) ++ { ++ ulTimeslot = ((f_ulTimeslot / 2) + 4) % 128; ++ } ++ else ++ { ++ ulTimeslot = f_ulTimeslot / 2 ; ++ } ++ } ++ } ++ ++ /* Get local pointer to TSST's entry in allocation table. */ ++ switch ( pSharedInfo->ChipConfig.aulTdmStreamFreqs[ ulStream / 4 ] ) ++ { ++ case cOCT6100_TDM_STREAM_FREQ_2MHZ: ++ ulTimeslot *= 4; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_4MHZ: ++ ulTimeslot *= 2; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_8MHZ: ++ ulTimeslot *= 1; ++ break; ++ case cOCT6100_TDM_STREAM_FREQ_16MHZ: ++ ulTimeslot *= 1; ++ break; ++ default: ++ return cOCT6100_ERR_FATAL_DE; ++ } ++ ++ /* Check if entry is actualy reserved. */ ++ if ( ((pulTsstAlloc[ ulTimeslot ] >> ulStream) & 0x1) != 0x1 ) ++ return cOCT6100_ERR_FATAL_55; ++ ++ /*==================================================================================*/ ++ ++ /* Clear the entry. */ ++ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << ulStream); ++ ++ /* Check and release the associated TSST if required. */ ++ if ( f_ulNumTsst == 2 ) ++ { ++ /* Check if entry is actualy reserved. */ ++ if ( ((pulTsstAlloc[ ulTimeslot ] >> ( ulStream - 1)) & 0x1) != 0x1 ) ++ return cOCT6100_ERR_FATAL_54; ++ ++ /* Clear the entry. */ ++ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << (ulStream - 1)); ++ ++ } ++ ++ return cOCT6100_ERR_OK; ++} ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_user.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_user.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_user.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_user.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,508 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_user.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the functions provided by the user. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 28 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_errors.h" ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserGetTime ++ ++Description: Returns the system time in us. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pTime Pointer to structure in which the time is returned. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserGetTime ++UINT32 Oct6100UserGetTime( ++ IN OUT tPOCT6100_GET_TIME f_pTime ) ++{ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserMemSet ++ ++Description: Sets f_ulLength bytes pointed to by f_pAddress to f_ulPattern. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pAddress Address in host memory where data should be set. ++f_ulPattern Pattern to apply at the address. This value will never ++ exceed 0xFF. ++f_ulLength Length in bytes to set. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserMemSet ++UINT32 Oct6100UserMemSet( ++ IN PVOID f_pAddress, ++ IN UINT32 f_ulPattern, ++ IN UINT32 f_ulLength ) ++{ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserMemCopy ++ ++Description: Copy f_ulLength bytes from f_pSource to f_pDestination. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++ ++f_pDestination Host data destination address. ++f_pSource Host data source address. ++f_ulLength Length in bytes to copy. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserMemCopy ++UINT32 Oct6100UserMemCopy( ++ IN PVOID f_pDestination, ++ IN const void *f_pSource, ++ IN UINT32 f_ulLength ) ++{ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserCreateSerializeObject ++ ++Description: Creates a serialization object. The serialization object is ++ seized via the Oct6100UserSeizeSerializeObject function. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pCreate Pointer to structure in which the serialization object's ++ handle is returned. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserCreateSerializeObject ++UINT32 Oct6100UserCreateSerializeObject( ++ IN OUT tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDestroySerializeObject ++ ++Description: Destroys the indicated serialization object. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pDestroy Pointer to structure containing the handle of the ++ serialization object. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDestroySerializeObject ++UINT32 Oct6100UserDestroySerializeObject( ++ IN tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserSeizeSerializeObject ++ ++Description: Seizes the indicated serialization object. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pSeize Pointer to structure containing the handle of the ++ serialization object. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserSeizeSerializeObject ++UINT32 Oct6100UserSeizeSerializeObject( ++ IN tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserReleaseSerializeObject ++ ++Description: Releases the indicated serialization object. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pRelease Pointer to structure containing the handle of the ++ serialization object. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserReleaseSerializeObject ++UINT32 Oct6100UserReleaseSerializeObject( ++ IN tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverWriteApi ++ ++Description: Performs a write access to the chip. This function is ++ accessible only from the API code entity (i.e. not from the ++ APIMI code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pWriteParams Pointer to structure containing the Params to the ++ write function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverWriteApi ++UINT32 Oct6100UserDriverWriteApi( ++ IN tPOCT6100_WRITE_PARAMS f_pWriteParams ) ++{ ++ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverWriteOs ++ ++Description: Performs a write access to the chip. This function is ++ accessible only from the APIMI code entity (i.e. not from the ++ API code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pWriteParams Pointer to structure containing the Params to the ++ write function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverWriteOs ++UINT32 Oct6100UserDriverWriteOs( ++ IN tPOCT6100_WRITE_PARAMS f_pWriteParams ) ++{ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverWriteSmearApi ++ ++Description: Performs a series of write accesses to the chip. The same data ++ word is written to a series of addresses. The writes begin at ++ the start address, and the address is incremented by the ++ indicated amount for each subsequent write. This function is ++ accessible only from the API code entity (i.e. not from the ++ APIMI code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pSmearParams Pointer to structure containing the parameters to the ++ write smear function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverWriteSmearApi ++UINT32 Oct6100UserDriverWriteSmearApi( ++ IN tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams ) ++{ ++ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverWriteSmearOs ++ ++Description: Performs a series of write accesses to the chip. The same data ++ word is written to a series of addresses. The writes begin at ++ the start address, and the address is incremented by the ++ indicated amount for each subsequent write. This function is ++ accessible only from the APIMI code entity (i.e. not from the ++ API code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pSmearParams Pointer to structure containing the parameters to the ++ write smear function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverWriteSmearOs ++UINT32 Oct6100UserDriverWriteSmearOs( ++ IN tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverWriteBurstApi ++ ++Description: Performs a series of write accesses to the chip. An array of ++ data words is written to a series of consecutive addresses. ++ The writes begin at the start address with element 0 of the ++ provided array as the data word. The address is incremented by ++ two for each subsequent write. This function is accessible only ++ from the API code entity (i.e. not from the APIMI code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pBurstParams Pointer to structure containing the parameters to the ++ write burst function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverWriteBurstApi ++UINT32 Oct6100UserDriverWriteBurstApi( ++ IN tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams ) ++{ ++ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverWriteBurstOs ++ ++Description: Performs a series of write accesses to the chip. An array of ++ data words is written to a series of consecutive addresses. ++ The writes begin at the start address with element 0 of the ++ provided array as the data word. The address is incremented by ++ two for each subsequent write. This function is accessible only ++ from the API code entity (i.e. not from the APIMI code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pBurstParams Pointer to structure containing the parameters to the ++ write burst function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverWriteBurstOs ++UINT32 Oct6100UserDriverWriteBurstOs( ++ IN tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverReadApi ++ ++Description: Performs a read access to the chip. This function is accessible ++ only from the API code entity (i.e. not from the APIMI code ++ entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pReadParams Pointer to structure containing the parameters to the ++ read function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverReadApi ++UINT32 Oct6100UserDriverReadApi( ++ IN OUT tPOCT6100_READ_PARAMS f_pReadParams ) ++{ ++ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverReadOs ++ ++Description: Performs a read access to the chip. This function is accessible ++ only from the APIMI code entity (i.e. not from the API code ++ entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pReadParams Pointer to structure containing the parameters to the ++ read function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverReadOs ++UINT32 Oct6100UserDriverReadOs( ++ IN OUT tPOCT6100_READ_PARAMS f_pReadParams ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverReadBurstApi ++ ++Description: Performs a burst of read accesses to the chip. The first read ++ is performed at the start address, and the address is ++ incremented by two for each subsequent read. The data is ++ retunred in an array provided by the user. This function is ++ accessible only from the API code entity (i.e. not from the ++ APIMI code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pBurstParams Pointer to structure containing the parameters to the ++ read burst function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverReadBurstApi ++UINT32 Oct6100UserDriverReadBurstApi( ++ IN OUT tPOCT6100_READ_BURST_PARAMS f_pBurstParams ) ++{ ++ ++ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100UserDriverReadBurstOs ++ ++Description: Performs a burst of read accesses to the chip. The first read ++ is performed at the start address, and the address is ++ incremented by two for each subsequent read. The data is ++ retunred in an array provided by the user. This function is ++ accessible only from the APIMI code entity (i.e. not from the ++ API code entity). ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pBurstParams Pointer to structure containing the parameters to the ++ read burst function. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++#if !SKIP_Oct6100UserDriverReadBurstOs ++UINT32 Oct6100UserDriverReadBurstOs( ++ IN OUT tPOCT6100_READ_BURST_PARAMS f_pBurstParams ) ++{ ++ ++ ++ return cOCT6100_ERR_OK; ++} ++#endif ++ ++ ++ ++ ++ ++ ++ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_apimi/oct6100_mask_interrupts.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_apimi/oct6100_mask_interrupts.c +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_apimi/oct6100_mask_interrupts.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_apimi/oct6100_mask_interrupts.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,116 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_mask_interrupts.c ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the mask interrupts function. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 8 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++#include "oct6100api/oct6100_apimi.h" ++#include "oct6100api/oct6100_apiud.h" ++#include "oct6100api/oct6100_errors.h" ++#include "oct6100api/oct6100_defines.h" ++ ++ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++Function: Oct6100InterruptMask ++ ++Description: The function is used to mask out the interrupt pin of the chip. ++ This function is used when a deferred procedure call treats the ++ interrupt (new interrupts must not be generated until the ++ signaled interrupt is treated). Which chip is to have its ++ interrupts masked is determined by the mask structure, ++ f_pInterruptMask. ++ ++------------------------------------------------------------------------------- ++| Argument | Description ++------------------------------------------------------------------------------- ++f_pInterruptMask Pointer to the interrupt masking structure. ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++UINT32 Oct6100InterruptMaskDef( ++ OUT tPOCT6100_INTERRUPT_MASK f_pInterruptMask ) ++{ ++ f_pInterruptMask->ulUserChipIndex = cOCT6100_INVALID_VALUE; ++ f_pInterruptMask->pProcessContext = NULL; ++ ++ ++ return cOCT6100_ERR_OK; ++} ++ ++UINT32 Oct6100InterruptMask( ++ IN tPOCT6100_INTERRUPT_MASK f_pInterruptMask ) ++{ ++ tOCT6100_WRITE_PARAMS WriteParams; ++ tOCT6100_READ_PARAMS ReadParams; ++ UINT32 result; ++ UINT16 usReadData; ++ ++ /* Determine if the chip's interrupt pin is active.*/ ++ ReadParams.ulReadAddress = 0x210; ++ ReadParams.pusReadData = &usReadData; ++ ReadParams.pProcessContext = f_pInterruptMask->pProcessContext; ++ ++ ReadParams.ulUserChipId = f_pInterruptMask->ulUserChipIndex; ++ ++ result = Oct6100UserDriverReadOs( &ReadParams ); ++ if ( result != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_INTRPTS_RW_ERROR; ++ ++ if ( (usReadData & 0xFFFF) != 0 ) ++ { ++ /* Chip's interrupt pin is active, so mask interrupt pin. */ ++ ReadParams.ulReadAddress = 0x214; ++ result = Oct6100UserDriverReadOs( &ReadParams ); ++ if ( result != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_INTRPTS_RW_ERROR; ++ ++ /* Determine if the chip's interrupt pin is active. */ ++ WriteParams.pProcessContext = f_pInterruptMask->pProcessContext; ++ ++ WriteParams.ulUserChipId = f_pInterruptMask->ulUserChipIndex; ++ WriteParams.ulWriteAddress = 0x214; ++ WriteParams.usWriteData = (UINT16)( (usReadData & 0xC000) | 0x3FFF ); ++ ++ result = Oct6100UserDriverWriteOs( &WriteParams ); ++ if ( result != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_INTRPTS_RW_ERROR; ++ ++ WriteParams.ulWriteAddress = 0x212; ++ WriteParams.usWriteData = 0x8000; ++ ++ result = Oct6100UserDriverWriteOs( &WriteParams ); ++ if ( result != cOCT6100_ERR_OK ) ++ return cOCT6100_ERR_INTRPTS_RW_ERROR; ++ ++ return cOCT6100_ERR_OK; ++ } ++ ++ return cOCT6100_ERR_INTRPTS_NOT_ACTIVE; ++} +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_channel_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_channel_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_channel_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_channel_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,529 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_channel_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_channel.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_channel_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 62 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHANNEL_PRIV_H__ ++#define __OCT6100_CHANNEL_PRIV_H__ ++ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++/* ECHO channel list pointer macros. */ ++#define mOCT6100_GET_CHANNEL_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_CHANNEL )(( PUINT8 )pSharedInfo + pSharedInfo->ulChannelListOfst ); ++ ++#define mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_CHANNEL )(( PUINT8 )pSharedInfo + pSharedInfo->ulChannelListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulChannelAllocOfst); ++ ++#define mOCT6100_GET_BIDIR_CHANNEL_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_BIDIR_CHANNEL )(( PUINT8 )pSharedInfo + pSharedInfo->ulBiDirChannelListOfst ); ++ ++#define mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_BIDIR_CHANNEL )(( PUINT8 )pSharedInfo + pSharedInfo->ulBiDirChannelListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulBiDirChannelAllocOfst ); ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_ECHO_CHAN_INDEX_ ++{ ++ /* Index of the channel in the API echo channel list.*/ ++ UINT16 usEchoChanIndex; ++ ++ /* TSI chariot memory entry for the Rin/Rout stream. */ ++ UINT16 usRinRoutTsiMemIndex; ++ ++ /* TSI chariot memory entry for the Sin/Sout stream. */ ++ UINT16 usSinSoutTsiMemIndex; ++ ++ /* SSPX memory entry. */ ++ UINT16 usEchoMemIndex; ++ ++ /* TDM sample conversion control memory entry. */ ++ UINT16 usRinRoutConversionMemIndex; ++ UINT16 usSinSoutConversionMemIndex; ++ ++ /* Internal info for quick access to structures associated to this TSI cnct. */ ++ UINT16 usRinTsstIndex; ++ UINT16 usSinTsstIndex; ++ UINT16 usRoutTsstIndex; ++ UINT16 usSoutTsstIndex; ++ ++ /* Index of the phasing TSST */ ++ UINT16 usPhasingTsstIndex; ++ ++ UINT8 fSinSoutCodecActive; ++ UINT8 fRinRoutCodecActive; ++ ++ ++ /* Extended Tone Detection resources.*/ ++ UINT16 usExtToneChanIndex; ++ UINT16 usExtToneMixerIndex; ++ UINT16 usExtToneTsiIndex; ++} tOCT6100_API_ECHO_CHAN_INDEX, *tPOCT6100_API_ECHO_CHAN_INDEX; ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetChannelsEchoSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiChannelsEchoSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ChannelOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ); ++ ++UINT32 Oct6100ApiCheckChannelParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ); ++ ++UINT32 Oct6100ApiReserveChannelResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ); ++ ++UINT32 Oct6100ApiWriteChannelStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ); ++ ++UINT32 Oct6100ApiUpdateChannelEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ); ++ ++UINT32 Oct6100ChannelCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose ); ++ ++UINT32 Oct6100ApiAssertChannelParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_CLOSE f_pChannelClose, ++ ++ IN OUT PUINT16 f_pusChanIndex ); ++ ++UINT32 Oct6100ApiInvalidateChannelStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ IN UINT16 f_usChanIndex ); ++ ++UINT32 Oct6100ApiReleaseChannelResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChannelIndex ); ++ ++UINT32 Oct6100ChannelModifySer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify ); ++ ++UINT32 Oct6100ApiCheckChannelModify( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pTempChanOpen, ++ OUT PUINT16 f_pusNewPhasingTsstIndex, ++ OUT PUINT16 f_pusChanIndex ); ++ ++UINT32 Oct6100ApiModifyChannelResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN UINT16 f_usChanIndex, ++ OUT PUINT16 f_pusNewRinTsstIndex, ++ OUT PUINT16 f_pusNewSinTsstIndex, ++ OUT PUINT16 f_pusNewRoutTsstIndex, ++ OUT PUINT16 f_pusNewSoutTsstIndex ); ++ ++UINT32 Oct6100ApiModifyChannelStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewPhasingTsstIndex, ++ OUT PUINT8 f_pfSinSoutCodecActive, ++ OUT PUINT8 f_pfRinRoutCodecActive, ++ IN UINT16 f_usNewRinTsstIndex, ++ IN UINT16 f_uslNewSinTsstIndex, ++ IN UINT16 f_usNewRoutTsstIndex, ++ IN UINT16 f_usNewSoutTsstIndex ); ++ ++UINT32 Oct6100ApiModifyChannelEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewPhasingTsstIndex, ++ IN UINT8 f_fSinSoutCodecActive, ++ IN UINT8 f_fRinRoutCodecActive, ++ IN UINT16 f_usNewRinTsstIndex, ++ IN UINT16 f_usNewSinTsstIndex, ++ IN UINT16 f_usNewRoutTsstIndex, ++ IN UINT16 f_usNewSoutTsstIndex ); ++ ++UINT32 Oct6100ChannelBroadcastTsstAddSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstAdd ); ++ ++UINT32 Oct6100ApiCheckChanTsstAddParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstRemove, ++ OUT PUINT16 f_pusChanIndex ); ++ ++UINT32 Oct6100ApiReserveTsstAddResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstRemove, ++ IN UINT16 f_usChanIndex, ++ OUT PUINT16 f_pusNewTsstIndex, ++ OUT PUINT16 f_pusNewTsstEntry ); ++ ++UINT32 Oct6100ApiWriteTsstAddStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstRemove, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewTsstIndex ); ++ ++UINT32 Oct6100ApiUpdateTsstAddChanEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_ADD f_pChannelTsstRemove, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usNewTsstIndex, ++ IN UINT16 f_usNewTsstEntry ); ++ ++UINT32 Oct6100ChannelBroadcastTsstRemoveSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove); ++ ++UINT32 Oct6100ApiAssertChanTsstRemoveParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, ++ OUT PUINT16 f_pusChanIndex, ++ OUT PUINT16 f_pusTsstIndex, ++ OUT PUINT16 f_pusTsstEntry, ++ OUT PUINT16 f_pusPrevTsstEntry ); ++ ++UINT32 Oct6100ApiInvalidateTsstRemoveStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usTsstIndex, ++ IN UINT32 f_ulPort, ++ IN BOOL f_fRemoveAll ); ++ ++UINT32 Oct6100ApiReleaseTsstRemoveResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usTsstIndex, ++ IN UINT16 f_usTsstEntry, ++ IN UINT16 f_usPrevTsstEntry ); ++ ++UINT32 Oct6100ApiChannelGetStatsSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_STATS f_pChannelStats ); ++ ++UINT32 Oct6100ApiReserveEchoEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusEchoIndex ); ++ ++UINT32 Oct6100ApiReleaseEchoEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEchoChanIndex ); ++ ++UINT32 Oct6100ApiCheckTdmConfig( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig ); ++ ++UINT32 Oct6100ApiCheckVqeConfig( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN BOOL f_fEnableToneDisabler ); ++ ++UINT32 Oct6100ApiCheckCodecConfig( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_CODEC f_pCodecConfig, ++ IN UINT32 f_ulDecoderNumTssts, ++ OUT PUINT16 f_pusPhasingTsstIndex ); ++ ++UINT32 Oct6100ApiWriteInputTsstControlMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsstIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT32 f_ulTsstInputLaw ); ++ ++UINT32 Oct6100ApiWriteOutputTsstControlMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsstIndex, ++ IN UINT32 f_ulAdpcmNibblePosition, ++ IN UINT32 f_ulNumTssts, ++ IN UINT16 f_usTsiMemIndex ); ++ ++UINT32 Oct6100ApiWriteEncoderMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulEncoderIndex, ++ IN UINT32 f_ulCompType, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT32 f_ulEnableSilenceSuppression, ++ IN UINT32 f_ulAdpcmNibblePosition, ++ IN UINT16 f_usPhasingTsstIndex, ++ IN UINT32 f_ulPhasingType, ++ IN UINT32 f_ulPhase ); ++ ++UINT32 Oct6100ApiWriteDecoderMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usDecoderIndex, ++ IN UINT32 f_ulCompType, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT32 f_ulPcmLaw, ++ IN UINT32 f_ulAdpcmNibblePosition ); ++ ++ ++UINT32 Oct6100ApiClearConversionMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usConversionMemIndex ); ++ ++UINT32 Oct6100ApiWriteVqeMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearPlayoutPointers, ++ IN BOOL f_fModifyOnly ); ++ ++UINT32 Oct6100ApiWriteVqeNlpMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearPlayoutPointers, ++ IN BOOL f_fModifyOnly ); ++ ++UINT32 Oct6100ApiWriteVqeAfMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearPlayoutPointers, ++ IN BOOL f_fModifyOnly ); ++ ++UINT32 Oct6100ApiWriteEchoMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usEchoIndex, ++ IN UINT16 f_usRinRoutTsiIndex, ++ IN UINT16 f_usSinSoutTsiIndex ); ++ ++UINT32 Oct6100ApiUpdateOpenStruct( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MODIFY f_pChanModify, ++ IN OUT tPOCT6100_CHANNEL_OPEN f_pChanOpen, ++ IN tPOCT6100_API_CHANNEL f_pChanEntry ); ++ ++ ++ ++ ++ ++UINT32 Oct6100ApiRetrieveNlpConfDword( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_CHANNEL f_pChanEntry, ++ IN UINT32 f_ulAddress, ++ OUT PUINT32 f_pulConfigDword ); ++ ++UINT32 Oct6100ApiSaveNlpConfDword( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_CHANNEL f_pChanEntry, ++ IN UINT32 f_ulAddress, ++ IN UINT32 f_ulConfigDword ); ++ ++UINT32 Oct6100ChannelCreateBiDirSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT IN OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir ); ++ ++UINT32 Oct6100ApiCheckChannelCreateBiDirParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir, ++ OUT PUINT16 f_pusFirstChanIndex, ++ OUT PUINT16 f_pusFirstChanExtraTsiIndex, ++ OUT PUINT16 f_pusFirstChanSinCopyEventIndex, ++ OUT PUINT16 f_pusSecondChanIndex, ++ OUT PUINT16 f_pusSecondChanExtraTsiIndex, ++ OUT PUINT16 f_pusSecondChanSinCopyEventIndex ++ ++ ); ++ ++UINT32 Oct6100ApiReserveChannelCreateBiDirResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ OUT PUINT16 f_pusBiDirChanIndex, ++ IN OUT PUINT16 f_pusFirstChanExtraTsiIndex, ++ IN OUT PUINT16 f_pusFirstChanSinCopyEventIndex, ++ OUT PUINT16 f_pusFirstChanSoutCopyEventIndex, ++ IN OUT PUINT16 f_pusSecondChanExtraTsiIndex, ++ IN OUT PUINT16 f_pusSecondChanSinCopyEventIndex, ++ OUT PUINT16 f_pusSecondChanSoutCopyEventIndex ); ++ ++UINT32 Oct6100ApiWriteChannelCreateBiDirStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usFirstChanExtraTsiIndex, ++ IN UINT16 f_usFirstChanSinCopyEventIndex, ++ IN UINT16 f_usFirstChanSoutCopyEventIndex, ++ IN UINT16 f_usSecondChanIndex, ++ IN UINT16 f_usSecondChanExtraTsiIndex, ++ IN UINT16 f_usSecondChanSinCopyEventIndex, ++ IN UINT16 f_usSecondChanSoutCopyEventIndex ); ++ ++UINT32 Oct6100ApiUpdateBiDirChannelEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_CHANNEL_CREATE_BIDIR f_pChannelCreateBiDir, ++ IN UINT16 f_usBiDirChanIndex, ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usFirstChanExtraTsiIndex, ++ IN UINT16 f_usFirstChanSinCopyEventIndex, ++ IN UINT16 f_usFirstChanSoutCopyEventIndex, ++ IN UINT16 f_usSecondChanIndex, ++ IN UINT16 f_usSecondChanExtraTsiIndex, ++ IN UINT16 f_usSecondChanSinCopyEventIndex, ++ IN UINT16 f_usSecondChanSoutCopyEventIndex ); ++ ++UINT32 Oct6100ChannelDestroyBiDirSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir ); ++ ++UINT32 Oct6100ApiAssertDestroyBiDirChanParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_DESTROY_BIDIR f_pChannelDestroyBiDir, ++ IN OUT PUINT16 f_pusBiDirChanIndex, ++ ++ IN OUT PUINT16 f_pusFirstChanIndex, ++ IN OUT PUINT16 f_pusSecondChanIndex ); ++ ++UINT32 Oct6100ApiInvalidateBiDirChannelStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usSecondChanIndex ); ++ ++UINT32 Oct6100ApiReleaseBiDirChannelResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usBiDirChanIndex, ++ ++ IN UINT16 f_usFirstChanIndex, ++ IN UINT16 f_usSecondChanIndex ); ++ ++UINT32 Oct6100ApiWriteDebugChanMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN UINT16 f_usRinRoutTsiIndex, ++ IN UINT16 f_usSinSoutTsiIndex ); ++ ++UINT32 Oct6100ApiDebugChannelOpen( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiMutePorts( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEchoIndex, ++ IN UINT16 f_usRinTsstIndex, ++ IN UINT16 f_usSinTsstIndex, ++ IN BOOL f_fCheckBridgeIndex ); ++ ++UINT32 Oct6100ApiSetChannelLevelControl( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fClearAlcHlcStatusBit ); ++ ++UINT32 Oct6100ApiSetChannelTailConfiguration( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usEchoMemIndex, ++ IN BOOL f_fModifyOnly ); ++ ++UINT32 Oct6100ChannelMuteSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MUTE f_pChannelMute ); ++ ++UINT32 Oct6100ApiAssertChannelMuteParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_MUTE f_pChannelMute, ++ OUT PUINT16 f_pusChanIndex, ++ OUT PUINT16 f_pusPorts ); ++ ++UINT32 Oct6100ChannelUnMuteSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ); ++ ++UINT32 Oct6100ApiAssertChannelUnMuteParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute, ++ OUT PUINT16 f_pusChanIndex, ++ OUT PUINT16 f_pusPorts ); ++ ++UINT32 Oct6100ApiMuteSinWithFeatures( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN BOOL f_fEnableSinWithFeatures ); ++ ++UINT32 Oct6100ApiMuteChannelPorts( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usPortMask, ++ IN BOOL f_fMute ); ++ ++INT32 Oct6100ApiOctFloatToDbEnergyByte( ++ IN UINT8 x ); ++ ++INT32 Oct6100ApiOctFloatToDbEnergyHalf( ++ IN UINT16 x ); ++ ++UINT16 Oct6100ApiDbAmpHalfToOctFloat( ++ IN INT32 x ); ++ ++#endif /* __OCT6100_CHANNEL_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_open_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_open_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_open_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_open_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,264 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_open_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_chip_open.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_chip_open_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 63 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHIP_OPEN_PRIV_H__ ++#define __OCT6100_CHIP_OPEN_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++typedef struct _OCT6100_API_INSTANCE_SIZES_ ++{ ++ /* Each of the following elements indicates the size of the instance memory */ ++ /* needed by the corresponding API module. All sizes are in bytes. */ ++ UINT32 ulChannelList; ++ UINT32 ulChannelAlloc; ++ ++ UINT32 ulTsiCnctList; ++ UINT32 ulTsiCnctAlloc; ++ ++ UINT32 ulMixerEventList; ++ UINT32 ulMixerEventAlloc; ++ ++ UINT32 ulBiDirChannelList; ++ UINT32 ulBiDirChannelAlloc; ++ ++ UINT32 ulAdpcmChannelList; ++ UINT32 ulAdpcmChannelAlloc; ++ ++ UINT32 ulSoftBufPlayoutEventsBuffer; ++ ++ UINT32 ulCopyEventList; ++ UINT32 ulCopyEventAlloc; ++ ++ UINT32 ulConfBridgeList; ++ UINT32 ulConfBridgeAlloc; ++ ++ UINT32 ulFlexConfParticipantsList; ++ UINT32 ulFlexConfParticipantsAlloc; ++ ++ UINT32 ulPlayoutBufList; ++ UINT32 ulPlayoutBufAlloc; ++ UINT32 ulPlayoutBufMemoryNodeList; ++ ++ ++ ++ UINT32 ulSoftToneEventsBuffer; ++ ++ UINT32 ulPhasingTsstList; ++ UINT32 ulPhasingTsstAlloc; ++ ++ UINT32 ulConversionMemoryAlloc; ++ ++ UINT32 ulTsiMemoryAlloc; ++ UINT32 ulTsstAlloc; ++ ++ UINT32 ulTsstEntryList; ++ UINT32 ulTsstEntryAlloc; ++ ++ UINT32 ulRemoteDebugList; ++ UINT32 ulRemoteDebugTree; ++ UINT32 ulRemoteDebugPktCache; ++ UINT32 ulRemoteDebugDataBuf; ++ ++ /* Memory consumed by static members of API instance. */ ++ UINT32 ulApiInstStatic; ++ ++ /* Total memory size for API instance. */ ++ UINT32 ulApiInstTotal; ++ ++} tOCT6100_API_INSTANCE_SIZES, *tPOCT6100_API_INSTANCE_SIZES; ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiCheckChipConfiguration( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip ); ++ ++UINT32 Oct6100ApiCheckImageFileHeader( ++ IN tPOCT6100_CHIP_OPEN f_pChipOpen ); ++ ++UINT32 Oct6100ApiCopyChipConfiguration( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip ); ++ ++UINT32 Oct6100ApiInitializeMiscellaneousVariables( ++ IN OUT tPOCT6100_INSTANCE_API f_pInstance ); ++ ++UINT32 Oct6100ApiCalculateInstanceSizes( ++ IN OUT tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstanceSizes ); ++ ++UINT32 Oct6100ApiAllocateInstanceMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pInstance, ++ IN tPOCT6100_API_INSTANCE_SIZES f_pInstanceSizes ); ++ ++UINT32 Oct6100ApiInitializeInstanceMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pInstance ); ++ ++UINT32 Oct6100ApiGetChipRevisionNum( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiMapExternalMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiDecodeKeyAndBist( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiBootFc2Pll( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiProgramFc1Pll( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiBootFc1Pll( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiWriteH100Registers( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiExternalMemoryBist( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiExternalMemoryInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiLoadImage( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiCpuRegisterBist( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiBootSdram( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiEnableClocks( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiProgramNLP( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiSetH100Register( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiWriteMiscellaneousRegisters( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT16 Oct6100ApiGenerateNumber( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulIndex, ++ IN UINT32 f_ulDataMask ); ++ ++UINT32 Oct6100ApiRandomMemoryWrite( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulMemBase, ++ IN UINT32 f_ulMemSize, ++ IN UINT32 f_ulNumDataBits, ++ IN UINT32 f_ulNumAccesses, ++ IN UINT32 f_ulErrorCode ); ++ ++UINT32 Oct6100ApiUserIoTest( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiCreateSerializeObjects( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulUserChipId ); ++ ++UINT32 Oct6100ApiDestroySerializeObjects( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiRunEgo( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN BOOL f_fStoreFlag, ++ IN UINT32 f_ulNumEntry, ++ OUT PUINT32 f_aulEntry ); ++ ++UINT32 Oct6100ApiCreateEgoEntry( ++ IN OUT UINT32 f_ulExternalAddress, ++ IN UINT32 f_ulInternalAddress, ++ IN UINT32 f_ulNumBytes, ++ IN UINT32 f_aulEntry[ 2 ] ); ++ ++ ++ ++ ++ ++UINT32 Oct6100ApiInitChannels( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiInitMixer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiInitRecordResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100FreeResourcesSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_FREE_RESOURCES f_pFreeResources ); ++ ++UINT32 Oct6100ProductionBistSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PRODUCTION_BIST f_pProductionBist ); ++ ++UINT32 Oct6100ApiProductionCrc( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulMessage, ++ IN UINT32 f_ulMessageLength, ++ OUT PUINT32 f_pulCrcResult ); ++ ++UINT32 Oct6100ApiReadCapacity( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins ); ++ ++UINT32 Oct6100ApiCpuRegisterBistReadCap( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins ); ++ ++UINT32 Oct6100ApiBootFc2PllReadCap( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins ); ++ ++UINT32 Oct6100ApiProgramFc1PllReadCap( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_API_GET_CAPACITY_PINS f_pGetCapacityPins ); ++ ++UINT32 Oct6100ApiInitToneInfo( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiClearInterrupts( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++#endif /* __OCT6100_CHIP_OPEN_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_stats_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_stats_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_stats_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_chip_stats_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,55 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_chip_stats_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_chip_stats.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_chip_stats_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 8 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CHIP_STATS_PRIV_H__ ++#define __OCT6100_CHIP_STATS_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiChipStatsSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ChipGetStatsSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_CHIP_STATS f_pChipStats ); ++ ++#endif /* __OCT6100_CHIP_STATS_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_conf_bridge_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_conf_bridge_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_conf_bridge_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_conf_bridge_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,318 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_conf_bridge_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_conf_bridge.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_conf_bridge_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 30 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_CONF_BRIDGE_PRIV_H__ ++#define __OCT6100_CONF_BRIDGE_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++#define mOCT6100_GET_CONF_BRIDGE_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_CONF_BRIDGE )(( PUINT8 )pSharedInfo + pSharedInfo->ulConfBridgeListOfst); ++ ++#define mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_CONF_BRIDGE )(( PUINT8 )pSharedInfo + pSharedInfo->ulConfBridgeListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulConfBridgeAllocOfst); ++ ++#define mOCT6100_GET_FLEX_CONF_PARTICIPANT_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_FLEX_CONF_PARTICIPANT )(( PUINT8 )pSharedInfo + pSharedInfo->ulFlexConfParticipantListOfst); ++ ++#define mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_FLEX_CONF_PARTICIPANT )(( PUINT8 )pSharedInfo + pSharedInfo->ulFlexConfParticipantListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulFlexConfParticipantAllocOfst); ++ ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetConfBridgeSwSizes( ++ IN OUT tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiConfBridgeSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst ); ++ ++UINT32 Oct6100ConfBridgeOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ); ++ ++UINT32 Oct6100ApiCheckBridgeParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen ); ++ ++UINT32 Oct6100ApiReserveBridgeResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ OUT PUINT16 f_pusBridgeIndex ); ++ ++UINT32 Oct6100ApiUpdateBridgeEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_OPEN f_pConfBridgeOpen, ++ IN UINT16 f_usBridgeIndex ); ++ ++UINT32 Oct6100ConfBridgeCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ); ++ ++UINT32 Oct6100ApiAssertBridgeParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose, ++ OUT PUINT16 f_pusBridgeIndex ); ++ ++UINT32 Oct6100ApiReleaseBridgeResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex ); ++ ++UINT32 Oct6100ConfBridgeChanAddSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd ); ++ ++UINT32 Oct6100ApiCheckBridgeAddParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_ADD f_pConfBridgeAdd, ++ OUT PUINT16 f_pusBridgeIndex, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT8 f_pfMute, ++ OUT PUINT32 f_pulInputPort, ++ OUT PUINT8 f_pfFlexibleConfBridge, ++ OUT PUINT32 f_pulListenerMaskIndex, ++ OUT PUINT32 f_pulListenerMask, ++ OUT PUINT8 f_pfTap, ++ OUT PUINT16 f_pusTapChannelIndex ); ++ ++UINT32 Oct6100ApiReserveBridgeAddResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT32 f_ulInputPort, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT32 f_ulListenerMaskIndex, ++ IN UINT32 f_ulListenerMask, ++ IN UINT8 f_fTap, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT16 f_pusCopyEventIndex, ++ OUT PUINT16 f_pusTapBridgeIndex ); ++ ++UINT32 Oct6100ApiBridgeEventAdd( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChannelIndex, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT32 f_ulInputPort, ++ IN UINT8 f_fMute, ++ IN UINT32 f_ulListenerMaskIndex, ++ IN UINT32 f_ulListenerMask, ++ IN UINT8 f_fTap, ++ IN UINT16 f_usTapBridgeIndex, ++ IN UINT16 f_usTapChanIndex ); ++ ++UINT32 Oct6100ApiBridgeAddParticipantToChannel( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usSourceChannelIndex, ++ IN UINT16 f_usDestinationChannelIndex, ++ IN UINT16 f_usLoadOrAccumulateEventIndex, ++ IN UINT16 f_usStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT32 f_ulSourceInputPort, ++ IN UINT32 f_ulDestinationInputPort ); ++ ++UINT32 Oct6100ConfBridgeChanRemoveSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ); ++ ++UINT32 Oct6100ApiCheckChanRemoveParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, ++ OUT PUINT16 f_pusBridgeIndex, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT8 f_pfFlexibleConfBridge, ++ OUT PUINT8 f_pfTap, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT16 f_pusCopyEventIndex ); ++ ++UINT32 Oct6100ApiReleaseChanEventResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex ); ++ ++UINT32 Oct6100ApiBridgeEventRemove ( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChannelIndex, ++ IN UINT8 f_fFlexibleConfBridge, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT8 f_fTap ); ++ ++UINT32 Oct6100ApiBridgeRemoveParticipantFromChannel( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usSourceChannelIndex, ++ IN UINT16 f_usDestinationChannelIndex, ++ IN UINT8 f_fRemovePermanently ); ++ ++UINT32 Oct6100ConfBridgeChanMuteSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute ); ++ ++UINT32 Oct6100ApiUpdateBridgeMuteResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT8 f_fFlexibleConfBridge ); ++ ++UINT32 Oct6100ApiCheckBridgeMuteParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_MUTE f_pConfBridgeMute, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT8 f_pfFlexibleConfBridge ); ++ ++UINT32 Oct6100ConfBridgeChanUnMuteSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute ); ++ ++UINT32 Oct6100ApiCheckBridgeUnMuteParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_CHAN_UNMUTE f_pConfBridgeUnMute, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusLoadEventIndex, ++ OUT PUINT16 f_pusSubStoreEventIndex, ++ OUT PUINT8 f_pfFlexibleConfBridge ); ++ ++UINT32 Oct6100ApiUpdateBridgeUnMuteResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usLoadEventIndex, ++ IN UINT16 f_usSubStoreEventIndex, ++ IN UINT8 f_fFlexibleConfBridge ); ++ ++UINT32 Oct6100ConfBridgeDominantSpeakerSetSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker ); ++ ++UINT32 Oct6100ApiCheckBridgeDominantSpeakerParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_DOMINANT_SPEAKER_SET f_pConfBridgeDominantSpeaker, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusBridgeIndex ); ++ ++UINT32 Oct6100ApiUpdateBridgeDominantSpeakerResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usChanIndex, ++ IN UINT16 f_usBridgeIndex ); ++ ++UINT32 Oct6100ConfBridgeMaskChangeSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange ); ++ ++UINT32 Oct6100ApiCheckBridgeMaskChangeParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN tPOCT6100_CONF_BRIDGE_MASK_CHANGE f_pConfBridgeMaskChange, ++ OUT PUINT16 f_pusChannelIndex, ++ OUT PUINT16 f_pusBridgeIndex, ++ OUT PUINT32 f_pulNewParticipantMask ); ++ ++UINT32 Oct6100ApiUpdateMaskModifyResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT32 f_ulNewListenerMask ); ++ ++UINT32 Oct6100ApiBridgeUpdateMask( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usChanIndex, ++ IN UINT32 f_ulNewListenerMask ); ++ ++UINT32 Oct6100ConfBridgeGetStatsSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN OUT tPOCT6100_CONF_BRIDGE_STATS f_pConfBridgeStats ); ++ ++UINT32 Oct6100ApiReserveBridgeEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ OUT PUINT16 f_pusConfBridgeIndex ); ++ ++UINT32 Oct6100ApiReleaseBridgeEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usConfBridgeIndex ); ++ ++UINT32 Oct6100ApiGetPrevLastSubStoreEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usBridgeIndex, ++ IN UINT16 f_usBridgeFirstLoadEventPtr, ++ OUT PUINT16 f_pusLastSubStoreEventIndex ); ++ ++UINT32 Oct6100ApiGetPreviousEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usStartIndex, ++ IN UINT16 f_usSearchedIndex, ++ IN UINT16 f_usLoopCnt, ++ OUT PUINT16 f_pusPreviousIndex ); ++ ++UINT32 Oct6100ApiBridgeSetDominantSpeaker( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usChannelIndex, ++ IN UINT16 f_usDominantSpeakerIndex ); ++ ++UINT32 Oct6100ApiReserveFlexConfParticipantEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ OUT PUINT16 f_pusParticipantIndex ); ++ ++UINT32 Oct6100ApiReleaseFlexConfParticipantEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInst, ++ IN UINT16 f_usParticipantIndex ); ++ ++#endif /* __OCT6100_CONF_BRIDGE_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_debug_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_debug_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_debug_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_debug_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,58 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_debug_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_debug.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_debug_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 12 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_DEBUG_PRIV_H__ ++#define __OCT6100_DEBUG_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++ ++UINT32 Oct6100DebugSelectChannelSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan, ++ IN BOOL f_fCheckChannelRecording ); ++ ++UINT32 Oct6100DebugGetDataSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_DEBUG_GET_DATA f_pGetData ); ++ ++#endif /* __OCT6100_DEBUG_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_events_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_events_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_events_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_events_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,82 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_events_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_events.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_events_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 14 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_EVENTS_PRIV_H__ ++#define __OCT6100_EVENTS_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++#define mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftBuf ) \ ++ pSoftBuf = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->SoftBufs.ulToneEventBufferMemOfst ); ++ ++#define mOCT6100_GET_BUFFER_PLAYOUT_EVENT_BUF_PNT( pSharedInfo, pSoftBuf ) \ ++ pSoftBuf = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->SoftBufs.ulBufPlayoutEventBufferMemOfst ); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetEventsSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100EventGetToneSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_EVENT_GET_TONE f_pEventGetTone ); ++ ++UINT32 Oct6100ApiTransferToneEvents( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulResetBuf ); ++ ++ ++ ++UINT32 Oct6100BufferPlayoutGetEventSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_GET_EVENT f_pBufPlayoutGetEvent ); ++ ++UINT32 Oct6100BufferPlayoutTransferEvents( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulResetBuf ); ++ ++UINT32 Oct6100BufferPlayoutCheckForSpecificEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulChannelPort, ++ IN BOOL f_fSaveToSoftBuffer, ++ OUT PBOOL f_pfEventDetected ); ++ ++#endif /* __OCT6100_EVENTS_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_interrupts_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_interrupts_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_interrupts_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_interrupts_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,158 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_interrupts_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_interrupts.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_interrupts_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 11 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_INTERRUPTS_PRIV_H__ ++#define __OCT6100_INTERRUPTS_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++#define mOCT6100_GET_INTRPT_ENABLE_TIME( \ ++ ulRegMclkTimeHigh, \ ++ ulRegMclkTimeLow, \ ++ ulIntrptState, \ ++ ulIntrptEnableMclkHigh, \ ++ ulIntrptEnableMclkLow, \ ++ ulIntrptTimeoutMclk, \ ++ ulTimeDiff ) \ ++ if ( ulIntrptState == cOCT6100_INTRPT_WILL_TIMEOUT ) \ ++ { \ ++ ulIntrptEnableMclkLow = ulRegMclkTimeLow + ulIntrptTimeoutMclk; \ ++ if ( ulIntrptEnableMclkLow < ulRegMclkTimeLow ) \ ++ ulIntrptEnableMclkHigh = (ulRegMclkTimeHigh + 1) & 0xFF; \ ++ else \ ++ ulIntrptEnableMclkHigh = ulRegMclkTimeHigh; \ ++ \ ++ ulIntrptState = cOCT6100_INTRPT_IN_TIMEOUT; \ ++ } \ ++ \ ++ if ( ulIntrptEnableMclkLow < ulRegMclkTimeLow ) \ ++ { \ ++ ulTimeDiff = (cOCT6100_FFFFFFFF - ulRegMclkTimeLow - 1) + ulIntrptEnableMclkLow; \ ++ } \ ++ else \ ++ { \ ++ ulTimeDiff = ulIntrptEnableMclkLow - ulRegMclkTimeLow; \ ++ } ++ ++#define mOCT6100_CHECK_INTRPT_TIMEOUT( \ ++ ulRegMclkTimePlus5MsHigh, \ ++ ulRegMclkTimePlus5MsLow, \ ++ ulIntrptDisableMclkHigh, \ ++ ulIntrptDisableMclkLow, \ ++ ulIntrptEnableMclkHigh, \ ++ ulIntrptEnableMclkLow, \ ++ ulIntrptState, \ ++ fIntrptChange ) \ ++ /* Branch depending on whether the disable time is lesser or greater than the timeout time. */ \ ++ if ( ulIntrptDisableMclkLow < ulIntrptEnableMclkLow ) \ ++ { \ ++ /* Disable period is over if mclk is greater than timeout time or less than disabled time. */ \ ++ if ( ulRegMclkTimePlus5MsLow > ulIntrptEnableMclkLow || \ ++ ulRegMclkTimePlus5MsLow < ulIntrptDisableMclkLow || \ ++ ulRegMclkTimePlus5MsHigh != ulIntrptEnableMclkHigh ) \ ++ { \ ++ fIntrptChange = TRUE; \ ++ ulIntrptState = cOCT6100_INTRPT_ACTIVE; \ ++ } \ ++ } \ ++ else \ ++ { \ ++ /* Disable period is over if mclk is lesser than disable time and greater than timeout. */ \ ++ if ( (ulRegMclkTimePlus5MsLow > ulIntrptEnableMclkLow && ulRegMclkTimePlus5MsLow < ulIntrptDisableMclkLow) || \ ++ (ulRegMclkTimePlus5MsHigh != ulIntrptDisableMclkHigh && ulRegMclkTimePlus5MsHigh != ulIntrptEnableMclkHigh) ) \ ++ { \ ++ fIntrptChange = TRUE; \ ++ ulIntrptState = cOCT6100_INTRPT_ACTIVE; \ ++ } \ ++ } ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiIsrSwInit( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiIsrHwInit( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig ); ++ ++UINT32 Oct6100InterruptConfigureSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig, ++ IN BOOL f_fCheckParams ); ++ ++UINT32 Oct6100ApiClearEnabledInterrupts( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100InterruptServiceRoutineSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ); ++ ++UINT32 Oct6100ApiWriteIeRegs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiReadIntrptRegs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags, ++ IN UINT32 f_ulRegister210h ); ++ ++UINT32 Oct6100ApiUpdateIntrptStates( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ); ++ ++UINT32 Oct6100ApiWriteIntrptRegs( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiReadChipMclkTime( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiUpdateIntrptTimeouts( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiScheduleNextMclkIntrpt( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulIntrptToSet ); ++ ++UINT32 Oct6100ApiScheduleNextMclkIntrptSer( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiCheckProcessorState( ++ IN tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ); ++ ++#endif /* __OCT6100_INTERRUPTS_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_memory_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_memory_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_memory_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_memory_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,97 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_memory_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_memory.c. All elements defined in this ++ file are for private usage of the API. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 17 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_MEMORY_PRIV_H__ ++#define __OCT6100_MEMORY_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++/* TSI allocation pointer macros. */ ++#define mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsiMemoryAllocOfst ); ++ ++/* Conversion memory allocation pointer macros. */ ++#define mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulConversionMemoryAllocOfst ); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetMemorySwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiMemorySwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiBufferPlayoutMemorySwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiReserveBufferPlayoutMemoryNode( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT32 f_pulNewNode ); ++ ++UINT32 Oct6100ApiReleaseBufferPlayoutMemoryNode( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulOldNode ); ++ ++UINT32 Oct6100ApiReserveBufferPlayoutMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulSize, ++ OUT PUINT32 f_pulMallocAddress ); ++ ++UINT32 Oct6100ApiReleaseBufferPlayoutMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulMallocAddress ); ++ ++UINT32 Oct6100ApiReserveTsiMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusTsiMemIndex ); ++ ++UINT32 Oct6100ApiReleaseTsiMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsiMemIndex ); ++ ++UINT32 Oct6100ApiReserveConversionMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusConversionMemIndex ); ++ ++UINT32 Oct6100ApiReleaseConversionMemEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usConversionMemIndex ); ++ ++#endif /* __OCT6100_MEMORY_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_miscellaneous_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_miscellaneous_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_miscellaneous_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_miscellaneous_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,279 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_miscellaneous_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_miscellaneous.c. All elements defined in ++ this file are for private usage of the API. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 20 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_MISCELLANEOUS_PRIV_H__ ++#define __OCT6100_MISCELLANEOUS_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/*---------------------------------------------------------------------------*\ ++ Macros used to shell the user function calls. These macros are used to ++ assert that the user does not change any of the members of the function's ++ parameter structure, as required and indicated in the API specification. ++ Ofcourse, these macros make the code heavier and thus slower. That is why ++ there is a compile option for disabling the extra checking. These can be ++ very helpful tools in debugging. ++\*---------------------------------------------------------------------------*/ ++ ++#ifndef cOCT6100_REMOVE_USER_FUNCTION_CHECK ++#define mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) \ ++{ \ ++ PVOID _pProcessContext; \ ++ UINT32 _ulUserChipId; \ ++ UINT32 _ulWriteAddress; \ ++ UINT16 _usWriteData; \ ++ \ ++ /* Store the data that is to be passed to the user. */ \ ++ _pProcessContext = WriteParams.pProcessContext; \ ++ _ulUserChipId = WriteParams.ulUserChipId; \ ++ _ulWriteAddress = WriteParams.ulWriteAddress; \ ++ _usWriteData = WriteParams.usWriteData; \ ++ \ ++ /* Call user function. */ \ ++ ulResult = Oct6100UserDriverWriteApi( &WriteParams ); \ ++ \ ++ /* Check if user changed members of function's parameter structure. */ \ ++ if ( WriteParams.pProcessContext != _pProcessContext || \ ++ WriteParams.ulUserChipId != _ulUserChipId || \ ++ WriteParams.ulWriteAddress != _ulWriteAddress || \ ++ WriteParams.ulWriteAddress != _ulWriteAddress || \ ++ WriteParams.usWriteData != _usWriteData ) \ ++ ulResult = cOCT6100_ERR_FATAL_DRIVER_WRITE_API; \ ++} ++#else ++#define mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) \ ++ ulResult = Oct6100UserDriverWriteApi( &WriteParams ); ++#endif /* cOCT6100_REMOVE_USER_FUNCTION_CHECK */ ++ ++ ++#ifndef cOCT6100_REMOVE_USER_FUNCTION_CHECK ++#define mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ) \ ++{ \ ++ PVOID _pProcessContext; \ ++ UINT32 _ulUserChipId; \ ++ UINT32 _ulWriteAddress; \ ++ UINT16 _usWriteData; \ ++ UINT32 _ulWriteLength; \ ++ \ ++ /* Store the data that is to be passed to the user. */ \ ++ _pProcessContext = SmearParams.pProcessContext; \ ++ _ulUserChipId = SmearParams.ulUserChipId; \ ++ _ulWriteAddress = SmearParams.ulWriteAddress; \ ++ _usWriteData = SmearParams.usWriteData; \ ++ _ulWriteLength = SmearParams.ulWriteLength; \ ++ \ ++ /* Call user function. */ \ ++ ulResult = Oct6100UserDriverWriteSmearApi( &SmearParams ); \ ++ \ ++ /* Check if user changed members of function's paraeter structure. */ \ ++ if ( SmearParams.pProcessContext != _pProcessContext || \ ++ SmearParams.ulUserChipId != _ulUserChipId || \ ++ SmearParams.usWriteData != _usWriteData || \ ++ SmearParams.ulWriteLength != _ulWriteLength) \ ++ ulResult = cOCT6100_ERR_FATAL_DRIVER_WRITE_SMEAR_API; \ ++} ++#else ++#define mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ) \ ++ ulResult = Oct6100UserDriverWriteSmearApi( &SmearParams ); ++#endif /* cOCT6100_REMOVE_USER_FUNCTION_CHECK */ ++ ++ ++#ifndef cOCT6100_REMOVE_USER_FUNCTION_CHECK ++#define mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ) \ ++{ \ ++ PVOID _pProcessContext; \ ++ UINT32 _ulUserChipId; \ ++ UINT32 _ulWriteAddress; \ ++ PUINT16 _pusWriteData; \ ++ UINT32 _ulWriteLength; \ ++ \ ++ /* Store the data that is to be passed to the user. */ \ ++ _pProcessContext = BurstParams.pProcessContext; \ ++ _ulUserChipId = BurstParams.ulUserChipId; \ ++ _ulWriteAddress = BurstParams.ulWriteAddress; \ ++ _pusWriteData = BurstParams.pusWriteData; \ ++ _ulWriteLength = BurstParams.ulWriteLength; \ ++ \ ++ /* Call user function. */ \ ++ ulResult = Oct6100UserDriverWriteBurstApi( &BurstParams ); \ ++ \ ++ /* Check if user changed members of function's parameter structure. */ \ ++ if ( BurstParams.pProcessContext != _pProcessContext || \ ++ BurstParams.ulUserChipId != _ulUserChipId || \ ++ BurstParams.ulWriteAddress != _ulWriteAddress || \ ++ BurstParams.pusWriteData != _pusWriteData || \ ++ BurstParams.ulWriteLength != _ulWriteLength ) \ ++ ulResult = cOCT6100_ERR_FATAL_DRIVER_WRITE_BURST_API; \ ++} ++#else ++#define mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ) \ ++ ulResult = Oct6100UserDriverWriteBurstApi( &BurstParams ); ++#endif /* cOCT6100_REMOVE_USER_FUNCTION_CHECK */ ++ ++ ++#ifndef cOCT6100_REMOVE_USER_FUNCTION_CHECK ++#define mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) \ ++{ \ ++ PVOID _pProcessContext; \ ++ UINT32 _ulUserChipId; \ ++ UINT32 _ulReadAddress; \ ++ PUINT16 _pusReadData; \ ++ \ ++ /* Store the data that is to be passed to the user. */ \ ++ _pProcessContext = ReadParams.pProcessContext; \ ++ _ulUserChipId = ReadParams.ulUserChipId; \ ++ _ulReadAddress = ReadParams.ulReadAddress; \ ++ _pusReadData = ReadParams.pusReadData; \ ++ \ ++ /* Call user function. */ \ ++ ulResult = Oct6100UserDriverReadApi( &ReadParams ); \ ++ \ ++ /* Check if user changed members of function's parameter structure. */ \ ++ if ( ReadParams.pProcessContext != _pProcessContext || \ ++ ReadParams.ulUserChipId != _ulUserChipId || \ ++ ReadParams.ulReadAddress != _ulReadAddress || \ ++ ReadParams.pusReadData != _pusReadData ) \ ++ ulResult = cOCT6100_ERR_FATAL_DRIVER_READ_API; \ ++} ++#else ++#define mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) \ ++ ulResult = Oct6100UserDriverReadApi( &ReadParams ); ++#endif /* cOCT6100_REMOVE_USER_FUNCTION_CHECK */ ++ ++ ++#ifndef cOCT6100_REMOVE_USER_FUNCTION_CHECK ++#define mOCT6100_DRIVER_READ_BURST_API( BurstParams, ulResult ) \ ++{ \ ++ PVOID _pProcessContext; \ ++ UINT32 _ulUserChipId; \ ++ UINT32 _ulReadAddress; \ ++ PUINT16 _pusReadData; \ ++ UINT32 _ulReadLength; \ ++ \ ++ /* Store the data that is to be passed to the user. */ \ ++ _pProcessContext = BurstParams.pProcessContext; \ ++ _ulUserChipId = BurstParams.ulUserChipId; \ ++ _ulReadAddress = BurstParams.ulReadAddress; \ ++ _pusReadData = BurstParams.pusReadData; \ ++ _ulReadLength = BurstParams.ulReadLength; \ ++ \ ++ /* Call user function. */ \ ++ ulResult = Oct6100UserDriverReadBurstApi( &BurstParams ); \ ++ \ ++ /* Check if user changed members of function's parameter structure. */ \ ++ if ( BurstParams.pProcessContext != _pProcessContext || \ ++ BurstParams.ulUserChipId != _ulUserChipId || \ ++ BurstParams.ulReadAddress != _ulReadAddress || \ ++ BurstParams.pusReadData != _pusReadData || \ ++ BurstParams.ulReadLength != _ulReadLength ) \ ++ ulResult = cOCT6100_ERR_FATAL_DRIVER_READ_BURST_API; \ ++} ++#else ++#define mOCT6100_DRIVER_READ_BURST_API( BurstParams, ulResult ) \ ++ ulResult = Oct6100UserDriverReadBurstApi( &BurstParams ); ++#endif /* cOCT6100_REMOVE_USER_FUNCTION_CHECK */ ++ ++#define mOCT6100_ASSIGN_USER_READ_WRITE_OBJ( f_pApiInst, Params ) ++ ++#define mOCT6100_CREATE_FEATURE_MASK( f_ulFieldSize, f_ulFieldBitOffset, f_pulFieldMask ) \ ++{ \ ++ (*f_pulFieldMask) = ( 1 << f_ulFieldSize ); \ ++ (*f_pulFieldMask) --; \ ++ (*f_pulFieldMask) <<= f_ulFieldBitOffset; \ ++} ++ ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiWaitForTime( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_aulWaitTime[ 2 ] ); ++ ++UINT32 Oct6100ApiWaitForPcRegisterBit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulPcRegAdd, ++ IN UINT32 f_ulPcBitNum, ++ IN UINT32 f_ulValue, ++ IN UINT32 f_ulTimeoutUs, ++ OUT PBOOL f_pfBitEqual ); ++ ++UINT32 Oct6100ApiWriteDword( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulAddress, ++ IN UINT32 f_ulWriteData ); ++ ++UINT32 Oct6100ApiReadDword( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulAddress, ++ OUT PUINT32 f_pulReadData ); ++ ++VOID Oct6100ApiCreateFeatureMask( ++ IN UINT32 f_ulFieldSize, ++ IN UINT32 f_ulFieldBitOffset, ++ OUT PUINT32 f_pulFieldMask ); ++ ++unsigned char const *Oct6100ApiStrStr( ++ IN unsigned char const *f_pszSource, ++ IN unsigned char const *f_pszString, ++ IN unsigned char const *f_pszLastCharPtr ); ++ ++UINT32 Oct6100ApiStrLen( ++ IN unsigned char const *f_pszString ); ++ ++UINT32 Oct6100ApiAsciiToHex( ++ IN UINT8 f_chCharacter, ++ IN PUINT32 f_pulValue ); ++ ++UINT8 Oct6100ApiHexToAscii( ++ IN UINT32 f_ulNumber ); ++ ++UINT32 Oct6100ApiRand( ++ IN UINT32 f_ulRange ); ++ ++UINT32 oct6100_retrieve_nlp_conf_dword(tPOCT6100_INSTANCE_API f_pApiInst, ++ tPOCT6100_API_CHANNEL f_pChanEntry, ++ UINT32 f_ulAddress, ++ UINT32 *f_pulConfigDword); ++ ++UINT32 oct6100_save_nlp_conf_dword(tPOCT6100_INSTANCE_API f_pApiInst, ++ tPOCT6100_API_CHANNEL f_pChanEntry, ++ UINT32 f_ulAddress, ++ UINT32 f_ulConfigDword); ++ ++#endif /* __OCT6100_MISCELLANEOUS_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_mixer_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_mixer_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_mixer_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_mixer_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,150 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_mixer_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_mixer.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_mixer_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 18 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_MIXER_PRIV_H__ ++#define __OCT6100_MIXER_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++#define mOCT6100_GET_MIXER_EVENT_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_MIXER_EVENT )(( PUINT8 )pSharedInfo + pSharedInfo->ulMixerEventListOfst); ++ ++#define mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_MIXER_EVENT )(( PUINT8 )pSharedInfo + pSharedInfo->ulMixerEventListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulMixerEventAllocOfst); ++ ++#define mOCT6100_GET_COPY_EVENT_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_COPY_EVENT )(( PUINT8 )pSharedInfo + pSharedInfo->ulCopyEventListOfst); ++ ++#define mOCT6100_GET_COPY_EVENT_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_COPY_EVENT )(( PUINT8 )pSharedInfo + pSharedInfo->ulCopyEventListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_COPY_EVENT_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulCopyEventAllocOfst); ++ ++/***************************** TYPES ***************************************/ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetMixerSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiMixerSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiMixerEventAdd( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex, ++ IN UINT16 f_usEventType, ++ IN UINT16 f_usDestinationChanIndex ); ++ ++UINT32 Oct6100ApiMixerEventRemove( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex, ++ IN UINT16 f_usEventType ); ++ ++UINT32 Oct6100MixerCopyEventCreateSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate ); ++ ++UINT32 Oct6100ApiCheckCopyEventCreateParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate, ++ OUT PUINT16 f_pusSourceChanIndex, ++ OUT PUINT16 f_pusDestinationChanIndex ); ++ ++UINT32 Oct6100ApiReserveCopyEventCreateResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusCopyEntryIndex, ++ IN OUT PUINT16 f_pusCopyEventIndex ); ++ ++UINT32 Oct6100ApiWriteCopyEventCreateStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate, ++ IN UINT16 f_usMixerEventIndex, ++ IN UINT16 f_usSourceChanIndex, ++ IN UINT16 f_usDestinationChanIndex ); ++ ++UINT32 Oct6100ApiUpdateCopyEventCreateEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_COPY_EVENT_CREATE f_pCopyEventCreate, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT16 f_usMixerEventIndex, ++ IN UINT16 f_usSourceChanIndex, ++ IN UINT16 f_usDestinationChanIndex ); ++ ++UINT32 Oct6100MixerCopyEventDestroySer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy ); ++ ++UINT32 Oct6100ApiAssertCopyEventDestroyParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_COPY_EVENT_DESTROY f_pCopyEventDestroy, ++ IN OUT PUINT16 f_pusCopyEventIndex, ++ IN OUT PUINT16 f_pusMixerEventIndex ); ++ ++UINT32 Oct6100ApiInvalidateCopyEventStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT16 f_usMixerEventIndex ); ++ ++UINT32 Oct6100ApiReleaseCopyEventResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usCopyEventIndex, ++ IN UINT16 f_usMixerEventIndex ); ++ ++UINT32 Oct6100ApiReserveMixerEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusEventIndex ); ++ ++UINT32 Oct6100ApiReleaseMixerEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex ); ++ ++UINT32 Oct6100ApiGetFreeMixerEventCnt( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT32 f_pulFreeEventCnt ); ++ ++UINT32 Oct6100ApiReserveCopyEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusEventIndex ); ++ ++UINT32 Oct6100ApiReleaseCopyEventEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usEventIndex ); ++#endif /* __OCT6100_MIXER_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_phasing_tsst_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_phasing_tsst_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_phasing_tsst_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_phasing_tsst_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,114 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_phasing_tsst_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_phasing_tsst.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_phasing_tsst_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 12 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_PHASING_TSST_PRIV_H__ ++#define __OCT6100_PHASING_TSST_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++#define mOCT6100_GET_PHASING_TSST_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_PHASING_TSST )(( PUINT8 )pSharedInfo + pSharedInfo->ulPhasingTsstListOfst); ++ ++#define mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_PHASING_TSST )(( PUINT8 )pSharedInfo + pSharedInfo->ulPhasingTsstListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_PHASING_TSST_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulPhasingTsstAllocOfst); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetPhasingTsstSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiPhasingTsstSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100PhasingTsstOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ); ++ ++UINT32 Oct6100ApiCheckPhasingParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen ); ++ ++UINT32 Oct6100ApiReservePhasingResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen, ++ OUT PUINT16 f_pusPhasingIndex, ++ OUT PUINT16 f_pusTsstIndex ); ++ ++UINT32 Oct6100ApiWritePhasingStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen, ++ IN UINT16 f_usPhasingIndex, ++ IN UINT16 f_usTsstIndex ); ++ ++UINT32 Oct6100ApiUpdatePhasingEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_OPEN f_pPhasingTsstOpen, ++ IN UINT16 f_usPhasingIndex, ++ IN UINT16 f_usTsstIndex ); ++ ++UINT32 Oct6100PhasingTsstCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose ); ++ ++UINT32 Oct6100ApiAssertPhasingParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_PHASING_TSST_CLOSE f_pPhasingTsstClose, ++ OUT PUINT16 f_pusPhasingIndex, ++ OUT PUINT16 f_pusTsstIndex ); ++ ++UINT32 Oct6100ApiInvalidatePhasingStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsstIndex ); ++ ++UINT32 Oct6100ApiReleasePhasingResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT UINT16 f_usPhasingIndex ); ++ ++UINT32 Oct6100ApiReservePhasingEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusPhasingIndex ); ++ ++UINT32 Oct6100ApiReleasePhasingEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usPhasingIndex ); ++ ++#endif /* #ifndef cOCT6100_REMOVE_PHASING_TSST */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_playout_buf_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_playout_buf_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_playout_buf_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_playout_buf_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,201 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_playout_buf_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_playout_buf.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_playout_buf_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 22 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_PLAYOUT_BUF_PRIV_H__ ++#define __OCT6100_PLAYOUT_BUF_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/* Playout buffer list pointer macros. */ ++#define mOCT6100_GET_BUFFER_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_BUFFER )(( PUINT8 )pSharedInfo + pSharedInfo->ulPlayoutBufListOfst ); ++ ++#define mOCT6100_GET_BUFFER_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_BUFFER )(( PUINT8 )pSharedInfo + pSharedInfo->ulPlayoutBufListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_BUFFER_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulPlayoutBufAllocOfst); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetPlayoutBufferSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiPlayoutBufferSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100BufferLoadSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN BOOL f_fReserveListStruct, ++ IN UINT32 f_ulBufIndex ); ++ ++UINT32 Oct6100BufferLoadBlockInitSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ); ++ ++UINT32 Oct6100BufferLoadBlockSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ); ++ ++UINT32 Oct6100ApiCheckBufferParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN BOOL f_fCheckBufferPtr ); ++ ++UINT32 Oct6100ApiCheckBufferLoadBlockParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock, ++ OUT PUINT32 f_pulBufferBase ); ++ ++UINT32 Oct6100ApiReserveBufferResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN BOOL f_fReserveListStruct, ++ IN UINT32 f_ulBufIndex, ++ OUT PUINT32 f_pulBufIndex, ++ OUT PUINT32 f_pulBufBase ); ++ ++UINT32 Oct6100ApiWriteBufferInMemory( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulBufferBase, ++ IN UINT32 f_ulBufferLength, ++ IN PUINT8 f_pbyBuffer ); ++ ++UINT32 Oct6100ApiUpdateBufferEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, ++ IN UINT32 f_ulBufIndex, ++ IN UINT32 f_ulBufBase ); ++ ++UINT32 Oct6100BufferUnloadSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_UNLOAD f_pBufferUnload, ++ IN BOOL f_fReleaseListStruct ); ++ ++UINT32 Oct6100ApiAssertBufferParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_UNLOAD f_pBufferUnload, ++ OUT PUINT32 f_pulBufIndex, ++ OUT PUINT32 f_pulBufBase ); ++ ++UINT32 Oct6100ApiReleaseBufferResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulBufIndex, ++ IN UINT32 f_ulBufBase, ++ IN BOOL f_fReleaseListStruct ); ++ ++UINT32 Oct6100BufferPlayoutAddSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ); ++ ++UINT32 Oct6100ApiCheckPlayoutAddParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulBufferIndex ); ++ ++UINT32 Oct6100ApiWriteBufferAddStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulBufferIndex ); ++ ++UINT32 Oct6100BufferPlayoutStartSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, ++ IN UINT32 f_ulPlayoutStopEventType ); ++ ++UINT32 Oct6100ApiCheckPlayoutStartParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulBufferIndex, ++ OUT PBOOL f_pfNotifyOnPlayoutStop, ++ OUT PUINT32 f_pulUserEventId, ++ OUT PBOOL f_pfAllowStartIfActive ); ++ ++UINT32 Oct6100ApiWriteChanPlayoutStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulBufferIndex, ++ IN BOOL f_fNotifyOnPlayoutStop, ++ IN UINT32 f_ulUserEventId, ++ IN BOOL f_fAllowStartIfActive, ++ IN UINT32 f_ulPlayoutStopEventType ); ++ ++UINT32 Oct6100ApiUpdateChanPlayoutEntry ( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulBufferIndex ); ++ ++UINT32 Oct6100BufferPlayoutStopSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ); ++ ++UINT32 Oct6100ApiAssertPlayoutStopParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT16 f_pusEchoMemIndex ); ++ ++UINT32 Oct6100ApiInvalidateChanPlayoutStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT16 f_usEchoMemIndex ++ ++ ); ++ ++UINT32 Oct6100ApiReleaseChanPlayoutResources ( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop, ++ IN UINT32 f_ulChannelIndex ); ++ ++UINT32 Oct6100ApiReserveBufPlayoutListEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT32 f_pulBufIndex ); ++ ++UINT32 Oct6100ApiReleaseBufPlayoutListEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulBufIndex ); ++ ++#endif /* __OCT6100_PLAYOUT_BUF_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_remote_debug_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_remote_debug_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_remote_debug_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_remote_debug_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,144 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_remote_debug_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_remote_debug.c. All elements defined in this ++ file are for private usage of the API. All public elements are defined ++ in the oct6100_remote_debug_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 13 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_REMOTE_DEBUG_PRIV_H__ ++#define __OCT6100_REMOTE_DEBUG_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++#define mOCT6100_GET_REMOTE_DEBUG_LIST_ENTRY_PNT( pSharedInfo, ulIndex, pEntry ) \ ++ pEntry = ( tPOCT6100_API_REMOTE_DEBUG_SESSION )(( PUINT8 )pSharedInfo + pSharedInfo->RemoteDebugInfo.ulSessionListOfst) + ulIndex; ++ ++#define mOCT6100_GET_REMOTE_DEBUG_TREE_PNT( pSharedInfo, pList ) \ ++ pList = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->RemoteDebugInfo.ulSessionTreeOfst); ++ ++#define mOCT6100_GET_REMOTE_DEBUG_DATA_BUF_PNT( pSharedInfo, pulDataBuf ) \ ++ pulDataBuf = ( PUINT16 )(( PUINT8 )pSharedInfo + pSharedInfo->RemoteDebugInfo.ulDataBufOfst); ++ ++#define mOCT6100_GET_REMOTE_DEBUG_SESSION_PKT_CACHE_PNT( pSharedInfo, pulPktCache, ulSessionIndex ) \ ++ pulPktCache = ( PUINT32 )(( PUINT8 )pSharedInfo + pSharedInfo->RemoteDebugInfo.ulPktCacheOfst) + (ulSessionIndex * (cOCTRPC_MAX_PACKET_BYTE_LENGTH / 4)); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetRemoteDebugSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiRemoteDebuggingSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiCheckEndianDetectField( ++ IN tPOCTRPC_OGRDTP_HEADER f_pOgrdtpHeader, ++ IN UINT32 f_ulPktLengthDword ); ++ ++VOID Oct6100ApiCalculateChecksum( ++ IN PUINT32 f_pulPktPayload, ++ IN UINT32 f_ulPktLengthDword, ++ OUT PUINT32 f_pulChecksum ); ++ ++VOID Oct6100ApiFormResponsePkt( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulRcvPktPayload, ++ IN OUT PUINT32 f_pulRspPktPayload, ++ IN UINT32 f_ulPktLengthDword, ++ IN BOOL f_fRetryPktResponse, ++ IN BOOL f_fReplaceProtocolNum, ++ IN BOOL f_fReplaceInterfaceType, ++ IN BOOL f_fReplaceInterfaceVersion, ++ IN UINT32 f_ulSessionIndex, ++ IN UINT32 f_ulParsingErrorValue, ++ IN UINT32 f_ulPayloadDwordIndex, ++ IN UINT32 f_ulChecksum ); ++ ++UINT32 Oct6100ApiCheckPktCommands( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulRcvPktPayload, ++ IN OUT PUINT32 f_pulRspPktPayload, ++ IN UINT32 f_ulSessionIndex, ++ IN UINT32 f_ulPktLengthDword, ++ IN UINT32 f_ulChecksum ); ++ ++VOID Oct6100ApiExecutePktCommands( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN PUINT32 f_pulRcvPktPayload, ++ IN UINT32 f_ulPktLengthDword ); ++ ++UINT32 Oct6100ApiCheckSessionNum( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCTRPC_OGRDTP_HEADER f_pOgrdtpHeader, ++ OUT PUINT32 f_pulSessionIndex ); ++ ++VOID Oct6100ApiRpcReadWord( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcReadBurst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcReadArray( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcWriteWord( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcWriteSmear( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcWriteBurst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcSetHotChannel( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcGetDebugChanIndex( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader ); ++ ++VOID Oct6100ApiRpcDisconnect( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCTRPC_COMMAND_HEADER f_pCmndHeader, ++ IN OUT UINT32 f_ulSessionNumber ); ++ ++#endif /* __OCT6100_REMOTE_DEBUG_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tlv_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tlv_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tlv_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tlv_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,515 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tlv_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_tlv.c. All elements defined in this ++ file are for private usage of the API. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 58 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TLV_PRIV_H__ ++#define __OCT6100_TLV_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++/* List of TLV types supported by this API. */ ++#define cOCT6100_TLV_TYPE_VERSION_NUMBER 0 ++#define cOCT6100_TLV_TYPE_CUSTOMER_PROJECT_ID 2 ++ ++#define cOCT6100_TLV_TYPE_POUCH_BASE_ADDRESS 3 ++#define cOCT6100_TLV_TYPE_CH0_MAIN_BASE_ADDRESS 4 ++#define cOCT6100_TLV_TYPE_CH_MAIN_SIZE 5 ++#define cOCT6100_TLV_TYPE_CH_MAIN_IO_OFFSET 6 ++#define cOCT6100_TLV_TYPE_CH_MAIN_ZCB_OFFSET 7 ++#define cOCT6100_TLV_TYPE_CH_MAIN_ZCB_SIZE 8 ++#define cOCT6100_TLV_TYPE_CH_MAIN_XCB_OFFSET 9 ++#define cOCT6100_TLV_TYPE_CH_MAIN_XCB_SIZE 10 ++#define cOCT6100_TLV_TYPE_CH_MAIN_YCB_OFFSET 11 ++#define cOCT6100_TLV_TYPE_CH_MAIN_YCB_SIZE 12 ++#define cOCT6100_TLV_TYPE_FREE_MEM_BASE_ADDRESS 13 ++#define cOCT6100_TLV_TYPE_CH_ROOT_CONF_OFFSET 14 ++ ++#define cOCT6100_TLV_TYPE_POA_CH_MAIN_ZPO_OFFSET 15 ++#define cOCT6100_TLV_TYPE_POA_CH_MAIN_ZPO_SIZE 16 ++#define cOCT6100_TLV_TYPE_POA_CH_MAIN_YPO_OFFSET 17 ++#define cOCT6100_TLV_TYPE_POA_CH_MAIN_YPO_SIZE 18 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RW_ZWP 19 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RW_ZIS 20 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RW_ZSP 21 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RW_YWP 22 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RW_YIS 23 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RW_YSP 24 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RO_ZRP 25 ++#define cOCT6100_TLV_TYPE_POA_BOFF_RO_YRP 26 ++ ++#define cOCT6100_TLV_TYPE_CNR_CONF_BOFF_RW_ENABLE 27 ++#define cOCT6100_TLV_TYPE_ANR_CONF_BOFF_RW_ENABLE 28 ++ ++#define cOCT6100_TLV_TYPE_HZ_CONF_BOFF_RW_ENABLE 29 ++#define cOCT6100_TLV_TYPE_HX_CONF_BOFF_RW_ENABLE 30 ++ ++#define cOCT6100_TLV_TYPE_LCA_Z_CONF_BOFF_RW_GAIN 31 ++#define cOCT6100_TLV_TYPE_LCA_Y_CONF_BOFF_RW_GAIN 32 ++ ++#define cOCT6100_TLV_TYPE_CNA_CONF_BOFF_RW_ENABLE 33 ++ ++#define cOCT6100_TLV_TYPE_NOA_CONF_BOFF_RW_ENABLE 34 ++ ++#define cOCT6100_TLV_TYPE_VFA_CONF_BOFF_RW_ENABLE 35 ++ ++#define cOCT6100_TLV_TYPE_TLA_MAIN_IO_BOFF_RW_TAIL_DISP 37 ++ ++#define cOCT6100_TLV_TYPE_STATSA_MAIN_IO_BOFF_RO_EPC 38 ++#define cOCT6100_TLV_TYPE_BOOTA_POUCH_BOFF_RW_BOOT_INST 39 ++#define cOCT6100_TLV_TYPE_BOOTA_POUCH_BOFF_RW_BOOT_RESULT 40 ++ ++#define cOCT6100_TLV_TYPE_DIS_CONF_BOFF_RW_ENABLE 41 ++#define cOCT6100_TLV_TYPE_TDM_CONF_BOFF_RW_ENABLE 42 ++#define cOCT6100_TLV_TYPE_NT_CONF_BOFF_RW_ENABLE 43 ++#define cOCT6100_TLV_TYPE_AEC_CONF_BOFF_RW_ENABLE 44 ++ ++#define cOCT6100_TLV_TYPE_PCM_LEAK_CONF_BOFF_RW 45 ++#define cOCT6100_TLV_TYPE_DEFAULT_ERL_CONF_BOFF_RW 46 ++#define cOCT6100_TLV_TYPE_TONE_REM_CONF_BOFF_RW_ENABLE 47 ++ ++#define cOCT6100_TLV_TYPE_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT 48 ++ ++#define cOCT6100_TLV_TYPE_NLP_CONV_CAP_CONF_BOFF_RW 49 ++#define cOCT6100_TLV_TYPE_MATRIX_EVENT_SIZE 50 ++#define cOCT6100_TLV_TYPE_CNR_RW_ENABLE 51 ++#define cOCT6100_TLV_TYPE_MAX_TAIL_LENGTH_RW_ENABLE 52 ++ ++#define cOCT6100_TLV_TYPE_PLAYOUT_ENABLE 53 ++#define cOCT6100_TLV_TYPE_DOMINANT_SPEAKER_BOFF_RW_ENABLE 54 ++ ++#define cOCT6100_TLV_TYPE_ANR_RW_ENABLE 57 ++#define cOCT6100_TLV_TYPE_TONE_REMOVAL_ENABLE 58 ++#define cOCT6100_TLV_TYPE_MUSIC_PROTECTION_RW_ENABLE 59 ++#define cOCT6100_TLV_TYPE_TAIL_DISP_CONF_BOFF_RW_ENABLE 60 ++#define cOCT6100_TLV_TYPE_IDLE_CODE_DETECTION_ENABLE 62 ++ ++#define cOCT6100_TLV_TYPE_AEC_DEFAULT_ERL_BOFF 64 ++ ++#define cOCT6100_TLV_TYPE_Z_ALC_TARGET_BOFF 65 ++#define cOCT6100_TLV_TYPE_Y_ALC_TARGET_BOFF 66 ++#define cOCT6100_TLV_TYPE_Z_HLC_TARGET_BOFF 67 ++#define cOCT6100_TLV_TYPE_Y_HLC_TARGET_BOFF 68 ++#define cOCT6100_TLV_TYPE_ALC_HLC_STATUS_BOFF 69 ++ ++#define cOCT6100_TLV_TYPE_Z_PLAYOUT_HARD_SKIP_BOFF 70 ++#define cOCT6100_TLV_TYPE_Y_PLAYOUT_HARD_SKIP_BOFF 71 ++ ++#define cOCT6100_TLV_TYPE_AFT_FIELD_BOFF 72 ++ ++#define cOCT6100_TLV_TYPE_VOICE_DETECTED_STAT_BOFF 73 ++ ++#define cOCT6100_TLV_TYPE_GAIN_APPLIED_RIN_STAT_BOFF 74 ++#define cOCT6100_TLV_TYPE_GAIN_APPLIED_SOUT_STAT_BOFF 75 ++ ++#define cOCT6100_TLV_TYPE_MAX_ADAPT_ALE_BOFF 77 ++#define cOCT6100_TLV_TYPE_RIN_ANR_BOFF 78 ++ ++#define cOCT6100_TLV_TYPE_NUMBER_PLAYOUT_EVENTS 79 ++ ++#define cOCT6100_TLV_TYPE_RIN_MUTE_BOFF 80 ++#define cOCT6100_TLV_TYPE_SIN_MUTE_BOFF 81 ++ ++#define cOCT6100_TLV_TYPE_CHAN_TAIL_LENGTH_BOFF 82 ++ ++#define cOCT6100_TLV_TYPE_CHAN_VQE_TONE_DISABLING_BOFF 83 ++ ++#define cOCT6100_TLV_TYPE_ANR_SNR_IMPROVEMENT_BOFF 84 ++#define cOCT6100_TLV_TYPE_ANR_AGRESSIVITY_BOFF 85 ++ ++#define cOCT6100_TLV_TYPE_RIN_TONE_REM_CONF_BOFF_RW_ENABLE 86 ++#define cOCT6100_TLV_TYPE_RIN_TONE_REM_COUNTER_BOFF 87 ++ ++#define cOCT6100_TLV_TYPE_AF_TAIL_DISP_VALUE_BOFF 88 ++ ++#define cOCT6100_TLV_TYPE_POUCH_COUNTER_BOFF 89 ++ ++#define cOCT6100_TLV_TYPE_AEC_TAIL_LENGTH_BOFF 90 ++ ++#define cOCT6100_TLV_TYPE_MATRIX_DWORD_BASE 91 ++#define cOCT6100_TLV_TYPE_DEBUG_CHAN_STATS_BYTE_SIZE 92 ++#define cOCT6100_TLV_TYPE_RECORDED_PCM_EVENT_BYTE_SIZE 93 ++#define cOCT6100_TLV_TYPE_HOT_CHANNEL_SELECT_DWORD_BASE 94 ++#define cOCT6100_TLV_TYPE_IS_ISR_CALLED_BOFF 95 ++ ++#define cOCT6100_TLV_TYPE_MATRIX_TIMESTAMP_DWORD_BASE 96 ++ ++#define cOCT6100_TLV_TYPE_CHAN_MAIN_IO_STATS_OFFSET 100 ++#define cOCT6100_TLV_TYPE_CHAN_MAIN_IO_STATS_SIZE 101 ++ ++#define cOCT6100_TLV_TYPE_AF_WRITE_PTR_BYTE_OFFSET 104 ++#define cOCT6100_TLV_TYPE_MATRIX_WP_DWORD_BASE 105 ++#define cOCT6100_TLV_TYPE_DEBUG_CHAN_LITE_STATS_BYTE_SIZE 106 ++ ++#define cOCT6100_TLV_TYPE_MUSIC_PROTECTION_ENABLE_BOFF 107 ++ ++#define cOCT6100_TLV_TYPE_IMAGE_TYPE 108 ++#define cOCT6100_TLV_TYPE_MAX_WIRELINE_CHANNELS 111 ++ ++#define cOCT6100_TLV_TYPE_AF_EVENT_CB_SIZE 112 ++ ++#define cOCT6100_TLV_TYPE_ZZ_ENERGY_CHAN_STATS_BOFF 116 ++#define cOCT6100_TLV_TYPE_YY_ENERGY_CHAN_STATS_BOFF 117 ++ ++#define cOCT6100_TLV_TYPE_BUFFER_PLAYOUT_SKIP_IN_EVENTS 119 ++ ++#define cOCT6100_TLV_TYPE_SOUT_NOISE_BLEACHING 121 ++ ++#define cOCT6100_TLV_TYPE_DOUBLE_TALK_BEH_MODE 124 ++#define cOCT6100_TLV_TYPE_DOUBLE_TALK_BEH_MODE_BOFF 125 ++ ++#define cOCT6100_TLV_TYPE_IDLE_CODE_DETECTION_BOFF 136 ++ ++#define cOCT6100_TLV_TYPE_NLP_STATISTICS 138 ++ ++#define cOCT6100_TLV_TYPE_RIN_ANR_VALUE 147 ++ ++#define cOCT6100_TLV_TYPE_ADPCM_ENABLE 150 ++#define cOCT6100_TLV_TYPE_NUM_TONE_DETECTOR 151 ++#define cOCT6100_TLV_TYPE_CONFERENCING_ENABLE 152 ++#define cOCT6100_TLV_TYPE_MAX_NUMBER_OF_CHANNELS 153 ++#define cOCT6100_TLV_TYPE_DEBUG_CHAN_INDEX_VALUE 154 ++#define cOCT6100_TLV_TYPE_TONE_DETECTOR_PROFILE 155 ++#define cOCT6100_TLV_TYPE_TEST_MODE_ENABLE 156 ++#define cOCT6100_TLV_TYPE_MAX_TAIL_DISPLACEMENT 157 ++ ++ ++/* TLV length defines. */ ++#define cOCT6100_TLV_MIN_LENGTH_DEFAULT 4 ++#define cOCT6100_TLV_MAX_LENGTH_DEFAULT 0xFFFFFFFF ++ ++#define cOCT6100_TLV_MIN_LENGTH_VERSION_NUMBER 4 ++#define cOCT6100_TLV_MAX_LENGTH_VERSION_NUMBER 1016 ++#define cOCT6100_TLV_MIN_LENGTH_CUSTOMER_PROJECT_ID 4 ++#define cOCT6100_TLV_MAX_LENGTH_CUSTOMER_PROJECT_ID 4 ++ ++ ++#define cOCT6100_TLV_MIN_LENGTH_CH0_MAIN_BASE_ADDRESS 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH0_MAIN_BASE_ADDRESS 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_IO_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_IO_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_ZCB_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_ZCB_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_ZCB_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_ZCB_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_XCB_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_XCB_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_XCB_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_XCB_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_YCB_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_YCB_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_MAIN_YCB_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_MAIN_YCB_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_FREE_MEM_BASE_ADDRESS 4 ++#define cOCT6100_TLV_MAX_LENGTH_FREE_MEM_BASE_ADDRESS 4 ++#define cOCT6100_TLV_MIN_LENGTH_CH_ROOT_CONF_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_CH_ROOT_CONF_OFFSET 4 ++ ++#define cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_ZPO_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_ZPO_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_ZPO_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_ZPO_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_YPO_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_YPO_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_YPO_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_YPO_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZWP 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZWP 8 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZIS 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZIS 8 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZSP 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZSP 8 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YWP 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YWP 8 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YIS 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YIS 8 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YSP 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YSP 8 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RO_ZRP 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RO_ZRP 8 ++#define cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RO_YRP 8 ++#define cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RO_YRP 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_CNR_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_CNR_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_ANR_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_ANR_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_HZ_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_HZ_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_HX_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_HX_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_LCA_Z_CONF_BOFF_RW_GAIN 8 ++#define cOCT6100_TLV_MAX_LENGTH_LCA_Z_CONF_BOFF_RW_GAIN 8 ++#define cOCT6100_TLV_MIN_LENGTH_LCA_Y_CONF_BOFF_RW_GAIN 8 ++#define cOCT6100_TLV_MAX_LENGTH_LCA_Y_CONF_BOFF_RW_GAIN 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_CNA_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_CNA_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_NOA_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_NOA_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_VFA_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_VFA_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_TLA_MAIN_IO_BOFF_RW_TAIL_DISP 8 ++#define cOCT6100_TLV_MAX_LENGTH_TLA_MAIN_IO_BOFF_RW_TAIL_DISP 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_STATSA_MAIN_IO_BOFF_RO_EPC 8 ++#define cOCT6100_TLV_MAX_LENGTH_STATSA_MAIN_IO_BOFF_RO_EPC 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_INST 8 ++#define cOCT6100_TLV_MAX_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_INST 8 ++#define cOCT6100_TLV_MIN_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_RESULT 8 ++#define cOCT6100_TLV_MAX_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_RESULT 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_CHAN_MAIN_IO_STATS_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_CHAN_MAIN_IO_STATS_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_CHAN_MAIN_IO_STATS_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_CHAN_MAIN_IO_STATS_SIZE 4 ++ ++#define cOCT6100_TLV_MIN_LENGTH_CDA_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_CDA_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_TDM_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_TDM_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_DIS_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_DIS_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_NT_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_NT_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_AEC_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_AEC_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_PCM_LEAK_CONF_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_PCM_LEAK_CONF_BOFF_RW 8 ++#define cOCT6100_TLV_MIN_LENGTH_DEFAULT_ERL_CONF_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_DEFAULT_ERL_CONF_BOFF_RW 8 ++#define cOCT6100_TLV_MIN_LENGTH_TONE_REM_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_TONE_REM_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_NLP_CONV_CAP_CONF_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_NLP_CONV_CAP_CONF_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT 8 ++#define cOCT6100_TLV_MAX_LENGTH_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_DOMINANT_SPEAKER_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_DOMINANT_SPEAKER_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_TAIL_DISP_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_TAIL_DISP_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_AEC_DEFAULT_ERL_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_AEC_DEFAULT_ERL_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_Z_ALC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_Z_ALC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_Y_ALC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_Y_ALC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_Z_HLC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_Z_HLC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_Y_HLC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_Y_HLC_TARGET_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MIN_LENGTH_ALC_HLC_STATUS_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_ALC_HLC_STATUS_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_Z_PLAYOUT_HARD_SKIP_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_Z_PLAYOUT_HARD_SKIP_BOFF_RW 8 ++#define cOCT6100_TLV_MIN_LENGTH_Y_PLAYOUT_HARD_SKIP_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_Y_PLAYOUT_HARD_SKIP_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_AFT_FIELD_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_AFT_FIELD_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_VOICE_DETECTED_STAT_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_VOICE_DETECTED_STAT_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_GAIN_APPLIED_RIN_STAT_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_GAIN_APPLIED_RIN_STAT_BOFF_RW 8 ++#define cOCT6100_TLV_MIN_LENGTH_GAIN_APPLIED_SOUT_STAT_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_GAIN_APPLIED_SOUT_STAT_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_MAX_ADAPT_ALE_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_MAX_ADAPT_ALE_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_RIN_ANR_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_RIN_ANR_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_RIN_ANR_VALUE_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_RIN_ANR_VALUE_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_RIN_MUTE_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_RIN_MUTE_BOFF_RW 8 ++#define cOCT6100_TLV_MIN_LENGTH_SIN_MUTE_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_SIN_MUTE_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_ANR_SNR_IMPROVEMENT_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_ANR_SNR_IMPROVEMENT_BOFF_RW 8 ++#define cOCT6100_TLV_MIN_LENGTH_ANR_AGRESSIVITY_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_ANR_AGRESSIVITY_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_CHAN_TAIL_LENGTH_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_CHAN_TAIL_LENGTH_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_CHAN_VQE_TONE_DIS_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_CHAN_VQE_TONE_DIS_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_RIN_TONE_REM_CONF_BOFF_RW_ENABLE 8 ++#define cOCT6100_TLV_MAX_LENGTH_RIN_TONE_REM_CONF_BOFF_RW_ENABLE 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_RIN_TONE_REM_COUNTER_BOFF_RW 8 ++#define cOCT6100_TLV_MAX_LENGTH_RIN_TONE_REM_COUNTER_BOFF_RW 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_AF_TAIL_DISP_VALUE_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_AF_TAIL_DISP_VALUE_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_POUCH_COUNTER_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_POUCH_COUNTER_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_AEC_TAIL_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_AEC_TAIL_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_IS_ISR_CALLED_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_IS_ISR_CALLED_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_MUSIC_PROTECTION_ENABLE_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_MUSIC_PROTECTION_ENABLE_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_ZZ_ENERGY_CHAN_STATS_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_ZZ_ENERGY_CHAN_STATS_BOFF 8 ++#define cOCT6100_TLV_MIN_LENGTH_YY_ENERGY_CHAN_STATS_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_YY_ENERGY_CHAN_STATS_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_DOUBLE_TALK_BEH_MODE_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_DOUBLE_TALK_BEH_MODE_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_IDLE_CODE_DETECTION_BOFF 8 ++#define cOCT6100_TLV_MAX_LENGTH_IDLE_CODE_DETECTION_BOFF 8 ++ ++#define cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_INDEX_VALUE 4 ++#define cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_INDEX_VALUE 4 ++#define cOCT6100_TLV_MIN_LENGTH_ADPCM_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_ADPCM_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_NUM_TONE_DETECTOR 4 ++#define cOCT6100_TLV_MAX_LENGTH_NUM_TONE_DETECTOR 4 ++#define cOCT6100_TLV_MIN_LENGTH_CONFERENCING_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_CONFERENCING_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_MAX_NUMBER_OF_CHANNELS 4 ++#define cOCT6100_TLV_MAX_LENGTH_MAX_NUMBER_OF_CHANNELS 4 ++#define cOCT6100_TLV_MIN_LENGTH_TONE_DETECTOR_PROFILE 4 ++#define cOCT6100_TLV_MAX_LENGTH_TONE_DETECTOR_PROFILE 4 ++#define cOCT6100_TLV_MIN_LENGTH_TEST_MODE_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_TEST_MODE_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_MAX_TAIL_DISPLACEMENT 4 ++#define cOCT6100_TLV_MAX_LENGTH_MAX_TAIL_DISPLACEMENT 4 ++#define cOCT6100_TLV_MIN_LENGTH_MATRIX_EVENT_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_MATRIX_EVENT_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_CNR_RW_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_CNR_RW_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_ANR_RW_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_ANR_RW_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_MAX_TAIL_LENGTH_RW_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_MAX_TAIL_LENGTH_RW_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_PLAYOUT_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_PLAYOUT_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_MUSIC_PROTECTION_RW_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_MUSIC_PROTECTION_RW_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_TONE_REMOVAL_ENABLE 4 ++#define cOCT6100_TLV_MAX_LENGTH_TONE_REMOVAL_ENABLE 4 ++#define cOCT6100_TLV_MIN_LENGTH_NUMBER_PLAYOUT_EVENTS 4 ++#define cOCT6100_TLV_MAX_LENGTH_NUMBER_PLAYOUT_EVENTS 4 ++#define cOCT6100_TLV_MIN_LENGTH_MATRIX_DWORD_BASE 4 ++#define cOCT6100_TLV_MAX_LENGTH_MATRIX_DWORD_BASE 4 ++#define cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_STATS_BYTE_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_STATS_BYTE_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_HOT_CHANNEL_SELECT_DWORD_BASE 4 ++#define cOCT6100_TLV_MAX_LENGTH_HOT_CHANNEL_SELECT_DWORD_BASE 4 ++#define cOCT6100_TLV_MIN_LENGTH_TIMESTAMP_DWORD_BASE 4 ++#define cOCT6100_TLV_MAX_LENGTH_TIMESTAMP_DWORD_BASE 4 ++#define cOCT6100_TLV_MIN_LENGTH_AF_WRITE_PTR_BYTE_OFFSET 4 ++#define cOCT6100_TLV_MAX_LENGTH_AF_WRITE_PTR_BYTE_OFFSET 4 ++#define cOCT6100_TLV_MIN_LENGTH_RECORDED_PCM_EVENT_BYTE_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_RECORDED_PCM_EVENT_BYTE_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_MATRIX_WP_DWORD_BASE 4 ++#define cOCT6100_TLV_MAX_LENGTH_MATRIX_WP_DWORD_BASE 4 ++#define cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_LITE_STATS_BYTE_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_LITE_STATS_BYTE_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_IMAGE_TYPE 4 ++#define cOCT6100_TLV_MAX_LENGTH_IMAGE_TYPE 4 ++#define cOCT6100_TLV_MIN_LENGTH_MAX_WIRELINE_CHANNELS 4 ++#define cOCT6100_TLV_MAX_LENGTH_MAX_WIRELINE_CHANNELS 4 ++#define cOCT6100_TLV_MIN_LENGTH_AF_EVENT_CB_BYTE_SIZE 4 ++#define cOCT6100_TLV_MAX_LENGTH_AF_EVENT_CB_BYTE_SIZE 4 ++#define cOCT6100_TLV_MIN_LENGTH_BUFFER_PLAYOUT_SKIP_IN_EVENTS 4 ++#define cOCT6100_TLV_MAX_LENGTH_BUFFER_PLAYOUT_SKIP_IN_EVENTS 4 ++#define cOCT6100_TLV_MIN_LENGTH_DOUBLE_TALK_BEH_MODE 4 ++#define cOCT6100_TLV_MAX_LENGTH_DOUBLE_TALK_BEH_MODE 4 ++#define cOCT6100_TLV_MIN_LENGTH_SOUT_NOISE_BLEACHING 4 ++#define cOCT6100_TLV_MAX_LENGTH_SOUT_NOISE_BLEACHING 4 ++#define cOCT6100_TLV_MIN_LENGTH_IDLE_CODE_DETECTION 4 ++#define cOCT6100_TLV_MAX_LENGTH_IDLE_CODE_DETECTION 4 ++#define cOCT6100_TLV_MIN_LENGTH_NLP_STATISTICS 4 ++#define cOCT6100_TLV_MAX_LENGTH_NLP_STATISTICS 4 ++ ++ ++/***************************** TYPES ***************************************/ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiProcessTlvRegion( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiInterpretTlvEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulTlvFieldType, ++ IN UINT32 f_ulTlvFieldLength, ++ IN UINT32 f_ulTlvValueAddress ); ++ ++UINT32 Oct6100ApiTlvCheckLengthField( ++ IN OUT UINT32 f_ulTlvFieldLength, ++ IN UINT32 f_ulMinLengthValue, ++ IN UINT32 f_ulMaxLengthValue ); ++ ++UINT32 Oct6100ApiTlvReadDword( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulAddress, ++ OUT PUINT32 f_pulReadData ); ++ ++UINT32 Oct6100ApiTlvReadBitOffsetStruct( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulAddress, ++ OUT tPOCT6100_TLV_OFFSET f_pBitOffsetStruct ); ++ ++#endif /* __OCT6100_TLV_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tone_detection_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tone_detection_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tone_detection_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tone_detection_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,111 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tone_detection_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_tone_detection.c. All elements defined in ++ this file are for private usage of the API. All public elements are ++ defined in the oct6100_tone_detection_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 14 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TONE_DETECTION_PRIV_H__ ++#define __OCT6100_TONE_DETECTION_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ToneDetectionEnableSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable ); ++ ++UINT32 Oct6100ApiCheckToneEnableParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulToneEventNumber, ++ ++ OUT PUINT32 f_pulExtToneChanIndex ); ++ ++UINT32 Oct6100ApiWriteToneDetectEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ ++ IN UINT32 f_ulExtToneChanIndex ); ++ ++UINT32 Oct6100ApiUpdateChanToneDetectEntry ( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ IN UINT32 f_ulExtToneChanIndex ); ++ ++UINT32 Oct6100ToneDetectionDisableSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable ); ++ ++UINT32 Oct6100ApiAssertToneDetectionParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable, ++ OUT PUINT32 f_pulChannelIndex, ++ OUT PUINT32 f_pulToneEventNumber, ++ OUT PUINT32 f_pulExtToneChanIndex, ++ ++ OUT PBOOL f_pfDisableAll ); ++ ++UINT32 Oct6100ApiClearToneDetectionEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ IN UINT32 f_ulExtToneChanIndex, ++ ++ IN BOOL f_fDisableAll ); ++ ++UINT32 Oct6100ApiReleaseToneDetectionEvent( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulChannelIndex, ++ IN UINT32 f_ulToneEventNumber, ++ IN UINT32 f_ulExtToneChanIndex, ++ IN BOOL f_fDisableAll ); ++ ++UINT32 Oct6100ApiIsSSTone( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulToneEventNumber, ++ OUT PBOOL f_fSSTone ); ++ ++UINT32 Oct6100ApiIs2100Tone( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulToneEventNumber, ++ OUT PBOOL f_fIs2100Tone ); ++ ++#endif /* __OCT6100_TONE_DETECTION_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsi_cnct_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsi_cnct_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsi_cnct_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsi_cnct_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,126 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tsi_cnct_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_tsi_cnct.c. All elements defined in ++ this file are for private usage of the API. All public elements are ++ defined in the oct6100_tsi_cnct_pub.h file. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 14 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TSI_CNCT_PRIV_H__ ++#define __OCT6100_TSI_CNCT_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++/***************************** DEFINES *************************************/ ++ ++/* TSI connection list pointer macros. */ ++#define mOCT6100_GET_TSI_CNCT_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_TSI_CNCT )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsiCnctListOfst ); ++ ++#define mOCT6100_GET_TSI_CNCT_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_TSI_CNCT )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsiCnctListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_TSI_CNCT_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsiCnctAllocOfst); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetTsiCnctSwSizes( ++ IN tPOCT6100_CHIP_OPEN f_pOpenChip, ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiTsiCnctSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++ ++UINT32 Oct6100TsiCnctOpenSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ); ++ ++UINT32 Oct6100ApiCheckTsiParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen ); ++ ++UINT32 Oct6100ApiReserveTsiResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen, ++ OUT PUINT16 f_pusTsiChanIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ); ++ ++UINT32 Oct6100ApiWriteTsiStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ); ++ ++UINT32 Oct6100ApiUpdateTsiEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_OPEN f_pTsiCnctOpen, ++ IN UINT16 f_usTsiChanIndex, ++ IN UINT16 f_usTsiMemIndex, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ); ++ ++ ++UINT32 Oct6100TsiCnctCloseSer( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN OUT tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose ); ++ ++UINT32 Oct6100ApiAssertTsiParams( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN tPOCT6100_TSI_CNCT_CLOSE f_pTsiCnctClose, ++ OUT PUINT16 f_pusTsiChanIndex, ++ OUT PUINT16 f_pusTsiMemIndex, ++ OUT PUINT16 f_pusInputTsstIndex, ++ OUT PUINT16 f_pusOutputTsstIndex ); ++ ++UINT32 Oct6100ApiInvalidateTsiStructs( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usInputTsstIndex, ++ IN UINT16 f_usOutputTsstIndex ); ++ ++UINT32 Oct6100ApiReleaseTsiResources( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsiChanIndex, ++ IN UINT16 f_usTsiMemIndex ); ++ ++UINT32 Oct6100ApiReserveTsiCnctEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ OUT PUINT16 f_pusTsiChanIndex ); ++ ++UINT32 Oct6100ApiReleaseTsiCnctEntry( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT16 f_usTsiChanIndex ); ++ ++#endif /* __OCT6100_TSI_CNCT_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsst_priv.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsst_priv.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsst_priv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tsst_priv.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,89 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_tsst_priv.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ File containing all private defines, macros, structures and prototypes ++ pertaining to the file oct6100_tsst.c. All elements defined in ++ this file are for private usage of the API. ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 14 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_TSST_PRIV_H__ ++#define __OCT6100_TSST_PRIV_H__ ++ ++/***************************** INCLUDE FILES *******************************/ ++ ++ ++/***************************** DEFINES *************************************/ ++ ++/* TSST allocation and serialization pointer macros. */ ++#define mOCT6100_GET_TSST_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PUINT32 )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsstAllocOfst); ++ ++#define mOCT6100_GET_TSST_LIST_PNT( pSharedInfo, pList ) \ ++ pList = ( tPOCT6100_API_TSST_ENTRY )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsstListOfst ); ++ ++#define mOCT6100_GET_TSST_LIST_ENTRY_PNT( pSharedInfo, pEntry, ulIndex ) \ ++ pEntry = (( tPOCT6100_API_TSST_ENTRY )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsstListOfst)) + ulIndex; ++ ++#define mOCT6100_GET_TSST_LIST_ALLOC_PNT( pSharedInfo, pAlloc ) \ ++ pAlloc = ( PVOID )(( PUINT8 )pSharedInfo + pSharedInfo->ulTsstListAllocOfst); ++ ++/***************************** TYPES ***************************************/ ++ ++ ++/************************** FUNCTION PROTOTYPES *****************************/ ++ ++UINT32 Oct6100ApiGetTsstSwSizes( ++ OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ); ++ ++UINT32 Oct6100ApiTsstSwInit( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ); ++ ++UINT32 Oct6100ApiValidateTsst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulNumTssts, ++ IN UINT32 f_ulTimeslot, ++ IN UINT32 f_ulStream, ++ IN UINT32 f_ulDirection ); ++ ++UINT32 Oct6100ApiReserveTsst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulTimeslot, ++ IN UINT32 f_ulStream, ++ IN UINT32 f_ulNumTsst, ++ IN UINT32 f_ulDirection, ++ OUT PUINT16 f_pusTsstMemIndex, ++ OUT PUINT16 f_pusTsstListIndex ); ++ ++UINT32 Oct6100ApiReleaseTsst( ++ IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, ++ IN UINT32 f_ulTimeslot, ++ IN UINT32 f_ulStream, ++ IN UINT32 f_ulNumTsst, ++ IN UINT32 f_ulDirection, ++ IN UINT16 f_usTsstListIndex ); ++ ++#endif /* __OCT6100_TSST_PRIV_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_version.h linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_version.h +--- linux-source-4.19/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_version.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_version.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,39 @@ ++/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ ++ ++File: oct6100_version.h ++ ++ Copyright (c) 2001-2007 Octasic Inc. ++ ++Description: ++ ++ This file contains the version of API. To obtain that version ++ number, the user must call the API function Oct6100ApiGetVersion(). ++ ++This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is ++free software; you can redistribute it and/or modify it under the terms of ++the GNU General Public License as published by the Free Software Foundation; ++either version 2 of the License, or (at your option) any later version. ++ ++The OCT6100 GPL API 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 the OCT6100 GPL API; if not, write to the Free Software ++Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++$Octasic_Release: OCT612xAPI-01.00-PR49 $ ++ ++$Octasic_Revision: 52 $ ++ ++\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ ++ ++#ifndef __OCT6100_VERSION_H__ ++#define __OCT6100_VERSION_H__ ++ ++/* String version of the OCT6100 API.*/ ++ ++#define cOCT6100_API_VERSION "OCT6100API-01.00-PR49" ++ ++#endif /* __OCT6100_VERSION_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/oct612x/test.c linux-source-4.19-dahdi/drivers/dahdi/oct612x/test.c +--- linux-source-4.19/drivers/dahdi/oct612x/test.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/oct612x/test.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,46 @@ ++/* ++ NOTE: This is not intended to be a functional program. Its only purpose ++ is to act as a tool to find out what portions of the Octasic API kit we ++ actually need to link into our drivers. As such, it references every API ++ call that the actual drivers use, and we let the compiler and linker tell ++ us what parts of each API module are actually needed to successfully ++ build this program. ++ */ ++#include "oct6100api/oct6100_api.h" ++ ++int main(int argc, char **argv) ++{ ++ tPOCT6100_INSTANCE_API pApiInstance; ++ UINT32 ulResult; ++ tOCT6100_CHANNEL_MODIFY modify; ++ tOCT6100_INTERRUPT_FLAGS InterruptFlags; ++ tOCT6100_TONE_EVENT tonefound; ++ tOCT6100_EVENT_GET_TONE tonesearch; ++ tOCT6100_CHIP_OPEN ChipOpen; ++ tOCT6100_GET_INSTANCE_SIZE InstanceSize; ++ tOCT6100_CHANNEL_OPEN ChannelOpen; ++ tOCT6100_TONE_DETECTION_ENABLE enable; ++ tOCT6100_CHIP_CLOSE ChipClose; ++ tOCT6100_API_GET_CAPACITY_PINS CapacityPins; ++ ++ Oct6100ChannelModifyDef(&modify); ++ ulResult = Oct6100ChannelModify(pApiInstance, &modify); ++ Oct6100InterruptServiceRoutineDef(&InterruptFlags); ++ Oct6100InterruptServiceRoutine(pApiInstance, &InterruptFlags); ++ Oct6100EventGetToneDef(&tonesearch); ++ ulResult = Oct6100EventGetTone(pApiInstance, &tonesearch); ++ Oct6100ChipOpenDef(&ChipOpen); ++ Oct6100GetInstanceSizeDef(&InstanceSize); ++ ulResult = Oct6100GetInstanceSize(&ChipOpen, &InstanceSize); ++ ulResult = Oct6100ChipOpen(pApiInstance, &ChipOpen); ++ Oct6100ChannelOpenDef(&ChannelOpen); ++ ulResult = Oct6100ChannelOpen(pApiInstance, &ChannelOpen); ++ Oct6100ToneDetectionEnableDef(&enable); ++ Oct6100ToneDetectionEnable(pApiInstance, &enable); ++ Oct6100ChipCloseDef(&ChipClose); ++ ulResult = Oct6100ChipClose(pApiInstance, &ChipClose); ++ Oct6100ApiGetCapacityPinsDef(&CapacityPins); ++ ulResult = Oct6100ApiGetCapacityPins(&CapacityPins); ++ ++ return 0; ++} +diff -Nru linux-source-4.19/drivers/dahdi/proslic.h linux-source-4.19-dahdi/drivers/dahdi/proslic.h +--- linux-source-4.19/drivers/dahdi/proslic.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/proslic.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,220 @@ ++/* ++ * 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. ++ */ ++ ++// ProSlic Header File ++ ++typedef struct { ++ unsigned char address; ++ unsigned char altaddr; ++ char *name; ++ unsigned short initial; ++} alpha; ++ ++typedef struct { ++ unsigned char chip_number; ++ unsigned char DTMF_digit; ++ unsigned char interrupt_line; ++ unsigned char hook_status; ++ unsigned long half_pulses[20]; // Contains the time stamps of incomming half pulses. ++ unsigned char half_pulses_detected; // Contains the number of half pulses detected. ++ unsigned char Pulse_digit; ++ unsigned long On_Hook_time; ++ unsigned long Off_Hook_time; ++} chipStruct; ++ ++// Defines ++#define LPT 0X378 ++ ++/* Proslic Linefeed options for register 64 - Linefeed Control */ ++#define SLIC_LF_OPEN 0x0 ++#define SLIC_LF_ACTIVE_FWD 0x1 ++#define SLIC_LF_OHTRAN_FWD 0x2 /* Forward On Hook Transfer */ ++#define SLIC_LF_TIP_OPEN 0x3 ++#define SLIC_LF_RINGING 0x4 ++#define SLIC_LF_ACTIVE_REV 0x5 ++#define SLIC_LF_OHTRAN_REV 0x6 /* Reverse On Hook Transfer */ ++#define SLIC_LF_RING_OPEN 0x7 ++ ++#define SLIC_LF_SETMASK 0x7 ++#define SLIC_LF_OPPENDING 0x10 ++ ++/* Mask used to reverse the linefeed mode between forward and ++ * reverse polarity. */ ++#define SLIC_LF_REVMASK 0x4 ++ ++#define IDA_LO 28 ++#define IDA_HI 29 ++ ++#define IAA 30 ++#define ID_ACCES_STATUS 31 ++#define IAS_BIT 1 ++ ++#define I_STATUS 31 ++ ++#define SPI_MODE 0 ++#define PCM_MODE 1 ++#define PCM_XMIT_START_COUNT_LSB 2 ++#define PCM_XMIT_START_COUNT_MSB 3 ++#define PCM_RCV_START_COUNT_LSB 4 ++#define PCM_RCV_START_COUNT_MSB 5 ++#define DIO 6 ++ ++#define AUDIO_LOOPBACK 8 ++#define AUDIO_GAIN 9 ++#define LINE_IMPEDANCE 10 ++#define HYBRID 11 ++#define RESERVED12 12 ++#define RESERVED13 13 ++#define PWR_DOWN1 14 ++#define PWR_DOWN2 15 ++#define RESERVED16 16 ++#define RESERVED17 17 ++#define INTRPT_STATUS1 18 ++#define INTRPT_STATUS2 19 ++#define INTRPT_STATUS3 20 ++#define INTRPT_MASK1 21 ++#define INTRPT_MASK2 22 ++#define INTRPT_MASK3 23 ++#define DTMF_DIGIT 24 ++#define RESERVED25 25 ++#define RESERVED26 26 ++#define RESERVED27 27 ++#define I_DATA_LOW 28 ++#define I_DATA_HIGH 29 ++#define I_ADDRESS 30 ++#define I_STATUS 31 ++#define OSC1 32 ++#define OSC2 33 ++#define RING_OSC_CTL 34 ++#define PULSE_OSC 35 ++#define OSC1_ON__LO 36 ++#define OSC1_ON_HI 37 ++#define OSC1_OFF_LO 38 ++#define OSC1_OFF_HI 39 ++#define OSC2_ON__LO 40 ++#define OSC2_ON_HI 41 ++#define OSC2_OFF_LO 42 ++#define OSC2_OFF_HI 43 ++#define PULSE_ON__LO 44 ++#define PULSE_ON_HI 45 ++#define PULSE_OFF_LO 46 ++#define PULSE_OFF_HI 47 ++#define RING_ON__LO 48 ++#define RING_ON_HI 49 ++#define RING_OFF_LO 50 ++#define RING_OFF_HI 51 ++#define RESERVED52 52 ++#define RESERVED53 53 ++#define RESERVED54 54 ++#define RESERVED55 55 ++#define RESERVED56 56 ++#define RESERVED57 57 ++#define RESERVED58 58 ++#define RESERVED59 59 ++#define RESERVED60 60 ++#define RESERVED61 61 ++#define RESERVED62 62 ++#define RESERVED63 63 ++#define LINE_STATE 64 ++#define ACTIVATE_LINE 0x11 ++#define RING_LINE 0x44 ++#define BIAS_SQUELCH 65 ++#define BAT_FEED 66 ++#define AUTO_STATE 67 ++#define LOOP_STAT 68 ++#define LOOP_DEBOUCE 69 ++#define RT_DEBOUCE 70 ++#define LOOP_I_LIMIT 71 ++#define OFF_HOOK_V 72 ++#define COMMON_V 73 ++#define BAT_V_HI 74 ++#define BAT_V_LO 75 ++#define PWR_STAT_DEV 76 ++#define PWR_STAT 77 ++#define LOOP_V_SENSE 78 ++#define LOOP_I_SENSE 79 ++#define TIP_V_SENSE 80 ++#define RING_V_SENSE 81 ++#define BAT_V_HI_SENSE 82 ++#define BAT_V_LO_SENSE 83 ++#define IQ1 84 ++#define IQ2 85 ++#define IQ3 86 ++#define IQ4 87 ++#define IQ5 88 ++#define IQ6 89 ++#define RESERVED90 90 ++#define RESERVED91 91 ++#define DCDC_PWM_OFF 92 ++#define DCDC 93 ++#define DCDC_PW_OFF 94 ++#define RESERVED95 95 ++#define CALIBR1 96 ++#define CALIBRATE_LINE 0x78 ++#define NORMAL_CALIBRATION_COMPLETE 0x20 ++#define CALIBR2 97 ++#define RING_GAIN_CAL 98 ++#define TIP_GAIN_CAL 99 ++#define DIFF_I_CAL 100 ++#define COMMON_I_CAL 101 ++#define I_LIMIT_GAIN_CAL 102 ++#define ADC_OFFSET_CAL 103 ++#define DAC_ADC_OFFSET 104 ++#define DAC_OFFSET_CAL 105 ++#define COMMON_BAL_CAL 106 ++#define DC_PEAK_CAL 107 ++ ++// Indirect Register (decimal) ++#define DTMF_ROW_0_PEAK 0 ++#define DTMF_ROW_1_PEAK 1 ++#define DTMF_ROW2_PEAK 2 ++#define DTMF_ROW3_PEAK 3 ++#define DTMF_COL1_PEAK 4 ++#define DTMF_FWD_TWIST 5 ++#define DTMF_RVS_TWIST 6 ++#define DTMF_ROW_RATIO_THRESH 7 ++#define DTMF_COL_RATIO_THRESH 8 ++#define DTMF_ROW_2ND_HARM 9 ++#define DTMF_COL_2ND_HARM 10 ++#define DTMF_PWR_MIN_THRESH 11 ++#define DTMF_HOT_LIM_THRESH 12 ++#define OSC1_COEF 13 ++#define OSC1X 14 ++#define OSC1Y 15 ++#define OSC2_COEF 16 ++#define OSC2X 17 ++#define OSC2Y 18 ++#define RING_V_OFF 19 ++#define RING_OSC_COEF 20 ++#define RING_X 21 ++#define RING_Y 22 ++#define PULSE_ENVEL 23 ++#define PULSE_X 24 ++#define PULSE_Y 25 ++#define RECV_DIGITAL_GAIN 26 ++#define XMIT_DIGITAL_GAIN 27 ++#define LOOP_CLOSE_THRESH 28 ++#define RING_TRIP_THRESH 29 ++#define COMMON_MIN_THRESH 30 ++#define COMMON_MAX_THRESH 31 ++#define PWR_ALARM_Q1Q2 32 ++#define PWR_ALARM_Q3Q4 33 ++#define PWR_ALARM_Q5Q6 34 ++#define LOOP_CLOSURE_FILTER 35 ++#define RING_TRIP_FILTER 36 ++#define THERM_LP_POLE_Q1Q2 37 ++#define THERM_LP_POLE_Q3Q4 38 ++#define THERM_LP_POLE_Q5Q6 39 ++#define CM_BIAS_RINGING 40 ++#define DCDC_MIN_V 41 ++#define DCDC_XTRA 42 +diff -Nru linux-source-4.19/drivers/dahdi/voicebus/GpakApi.c linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakApi.c +--- linux-source-4.19/drivers/dahdi/voicebus/GpakApi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakApi.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1729 @@ ++/* ++ * 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); ++} ++ ++static int CheckDspReset( ++ int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ ++ ) ++{ ++ int ret; ++ int retries = 20; ++ while (--retries) { ++ ret = __CheckDspReset(DspId); ++ if (-1 != ret) ++ return ret; ++ msleep(5); ++ } ++ return ret; ++} ++ ++/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * 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; ++ ++ MsgBuffer[38] = (DSP_WORD) ++ pChanConfig->EcanParametersA.EcanSaturationLevel; ++ MsgBuffer[39] = (DSP_WORD) ++ pChanConfig->EcanParametersB.EcanSaturationLevel; ++ MsgBuffer[40] = (DSP_WORD) ++ pChanConfig->EcanParametersA.EcanNLPSaturationThreshold; ++ MsgBuffer[41] = (DSP_WORD) ++ pChanConfig->EcanParametersB.EcanNLPSaturationThreshold; ++ MsgLength = 84; /* byte number == 42*2 */ ++ break; ++ ++ /* PCM to Packet channel type. */ ++ case tdmToTdmDebug: ++ ++ 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; ++ ++ MsgBuffer[38] = (DSP_WORD) ++ pChanConfig->EcanParametersA.EcanSaturationLevel; ++ MsgBuffer[39] = (DSP_WORD) ++ pChanConfig->EcanParametersB.EcanSaturationLevel; ++ MsgBuffer[40] = (DSP_WORD) ++ pChanConfig->EcanParametersA.EcanNLPSaturationThreshold; ++ MsgBuffer[41] = (DSP_WORD) ++ pChanConfig->EcanParametersB.EcanNLPSaturationThreshold; ++ MsgBuffer[42] = (DSP_WORD) ++ pChanConfig->ChannelId_tobe_Debug; ++ ++ MsgLength = 86; /* byte number == 43*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 != 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 */ ++ ++ memset(MsgBuffer, 0, sizeof(MsgBuffer)); ++ ++ /* 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 -Nru linux-source-4.19/drivers/dahdi/voicebus/GpakApi.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakApi.h +--- linux-source-4.19/drivers/dahdi/voicebus/GpakApi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakApi.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,627 @@ ++/* ++ * 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 GpakEcanParms ++{ ++ 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 ++ short int EcanSaturationLevel; /* Far end input level above which significant saturation/nonlinearity may be expected. */ ++ short int EcanNLPSaturationThreshold; /* NLP threshold under conditions of possible saturation */ ++} 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 ++ unsigned short int ChannelId_tobe_Debug; /* Channel Id of the channel that we'd like to debug */ ++ /* (0 to MaxChannels-1), only used for tdmToTdmDebug */ ++ ++} 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 -Nru linux-source-4.19/drivers/dahdi/voicebus/GpakCust.c linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakCust.c +--- linux-source-4.19/drivers/dahdi/voicebus/GpakCust.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakCust.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,1004 @@ ++/* ++ * Copyright (c) 2005, Adaptive Digital Technologies, Inc. ++ * Copyright (c) 2005-2010, 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 ++#include ++ ++#include ++#include ++ ++#include "GpakCust.h" ++#include "GpakApi.h" ++ ++#include "adt_lec.h" ++#include "voicebus.h" ++#include "vpmadtreg.h" ++ ++static DEFINE_SPINLOCK(ifacelock); ++static struct vpmadt032 *ifaces[MAX_DSP_CORES]; ++ ++#define vpm_info(vpm, format, arg...) \ ++ dev_info(&vpm->vb->pdev->dev , format , ## arg) ++ ++static inline struct vpmadt032 *find_iface(const unsigned short dspid) ++{ ++ struct vpmadt032 *ret; ++ ++ spin_lock(&ifacelock); ++ if (ifaces[dspid]) { ++ ret = ifaces[dspid]; ++ } else { ++ ret = NULL; ++ } ++ spin_unlock(&ifacelock); ++ return ret; ++} ++ ++static struct vpmadt032_cmd *vpmadt032_get_free_cmd(struct vpmadt032 *vpm) ++{ ++ struct vpmadt032_cmd *cmd; ++ might_sleep(); ++ cmd = kmalloc(sizeof(struct vpmadt032_cmd), GFP_KERNEL); ++ if (unlikely(!cmd)) ++ return NULL; ++ memset(cmd, 0, sizeof(*cmd)); ++ 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. */ ++static int vpmadt032_getreg_full_return(struct vpmadt032 *vpm, int pagechange, ++ u16 addr, u16 *outbuf, struct vpmadt032_cmd *cmd) ++{ ++ unsigned long flags; ++ unsigned long ret; ++ BUG_ON(!cmd); ++ ++ /* We'll wait for 2s */ ++ ret = wait_for_completion_timeout(&cmd->complete, HZ*2); ++ if (unlikely(!ret)) { ++ spin_lock_irqsave(&vpm->list_lock, flags); ++ list_del(&cmd->node); ++ spin_unlock_irqrestore(&vpm->list_lock, flags); ++ kfree(cmd); ++ return -EIO; ++ } ++ ++ if (cmd->desc & __VPM150M_FIN) { ++ *outbuf = cmd->data; ++ cmd->desc = 0; ++ ret = 0; ++ } ++ ++ list_del(&cmd->node); ++ kfree(cmd); ++ return 0; ++} ++ ++/* 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; ++} ++ ++struct change_order { ++ struct list_head node; ++ unsigned int channel; ++ struct adt_lec_params params; ++}; ++ ++static struct change_order *alloc_change_order(void) ++{ ++ return kzalloc(sizeof(struct change_order), GFP_ATOMIC); ++} ++ ++static void free_change_order(struct change_order *order) ++{ ++ kfree(order); ++} ++ ++static int vpmadt032_control(struct vpmadt032 *vpm, unsigned short int channel, ++ GpakAlgCtrl_t control_code, ++ GPAK_AlgControlStat_t *pstatus) ++{ ++ gpakAlgControlStat_t stat; ++ int retry = 4; ++ while (retry--) { ++ stat = gpakAlgControl(vpm->dspid, channel, ++ control_code, pstatus); ++ ++ if (AcDspCommFailure == stat) ++ msleep(5); ++ else ++ break; ++ } ++ ++ return stat; ++} ++ ++static int vpmadt032_enable_ec(struct vpmadt032 *vpm, int channel, ++ enum adt_companding companding) ++{ ++ int res; ++ GPAK_AlgControlStat_t pstatus; ++ GpakAlgCtrl_t control; ++ ++ control = (ADT_COMP_ALAW == companding) ? EnableALawSwCompanding : ++ EnableMuLawSwCompanding; ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) { ++ const char *law; ++ law = (control == EnableMuLawSwCompanding) ? "MuLaw" : "ALaw"; ++ vpm_info(vpm, "Enabling ecan on channel: %d (%s)\n", ++ channel, law); ++ } ++ res = vpmadt032_control(vpm, channel, control, &pstatus); ++ if (res) { ++ vpm_info(vpm, "Unable to set SW Companding on " ++ "channel %d (reason %d)\n", channel, res); ++ } ++ res = vpmadt032_control(vpm, channel, EnableEcanA, &pstatus); ++ return res; ++} ++ ++static int vpmadt032_disable_ec(struct vpmadt032 *vpm, int channel) ++{ ++ int res; ++ GPAK_AlgControlStat_t pstatus; ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) ++ vpm_info(vpm, "Disabling ecan on channel: %d\n", channel); ++ ++ res = vpmadt032_control(vpm, channel, BypassSwCompanding, &pstatus); ++ if (res) { ++ vpm_info(vpm, "Unable to disable sw companding on " ++ "echo cancellation channel %d (reason %d)\n", ++ channel, res); ++ } ++ res = vpmadt032_control(vpm, channel, BypassEcanA, &pstatus); ++ return res; ++} ++ ++static struct change_order *get_next_order(struct vpmadt032 *vpm) ++{ ++ struct change_order *order; ++ ++ spin_lock(&vpm->change_list_lock); ++ if (!list_empty(&vpm->change_list)) { ++ order = list_entry(vpm->change_list.next, ++ struct change_order, node); ++ list_del(&order->node); ++ } else { ++ order = NULL; ++ } ++ spin_unlock(&vpm->change_list_lock); ++ ++ return order; ++} ++ ++static int nlp_settings_changed(const struct adt_lec_params *a, ++ const struct adt_lec_params *b) ++{ ++ return ((a->nlp_type != b->nlp_type) || ++ (a->nlp_threshold != b->nlp_threshold) || ++ (a->nlp_max_suppress != b->nlp_max_suppress)); ++} ++ ++static int echocan_on(const struct adt_lec_params *new, ++ const struct adt_lec_params *old) ++{ ++ return ((new->tap_length != old->tap_length) && ++ (new->tap_length > 0)); ++} ++ ++static int echocan_off(const struct adt_lec_params *new, ++ const struct adt_lec_params *old) ++{ ++ return ((new->tap_length != old->tap_length) && ++ (0 == new->tap_length)); ++} ++ ++static void update_channel_config(struct vpmadt032 *vpm, unsigned int channel, ++ struct adt_lec_params *desired) ++{ ++ int res; ++ GPAK_AlgControlStat_t pstatus; ++ GPAK_ChannelConfigStat_t cstatus; ++ GPAK_TearDownChanStat_t tstatus; ++ GpakChannelConfig_t chanconfig; ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) { ++ vpm_info(vpm, "Reconfiguring chan %d for nlp %d, " ++ "nlp_thresh %d, and max_supp %d\n", channel + 1, ++ desired->nlp_type, desired->nlp_threshold, ++ desired->nlp_max_suppress); ++ } ++ ++ vpm->setchanconfig_from_state(vpm, channel, &chanconfig); ++ ++ res = gpakTearDownChannel(vpm->dspid, channel, &tstatus); ++ if (res) ++ return; ++ ++ res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm, ++ &chanconfig, &cstatus); ++ if (res) ++ return; ++ ++ if (!desired->tap_length) { ++ res = vpmadt032_control(vpm, channel, ++ BypassSwCompanding, &pstatus); ++ if (res) { ++ vpm_info(vpm, "Unable to disable sw companding on " ++ "echo cancellation channel %d (reason %d)\n", ++ channel, res); ++ } ++ vpmadt032_control(vpm, channel, BypassEcanA, &pstatus); ++ } ++ ++ return; ++} ++ ++/** ++ * 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. ++ */ ++static void vpmadt032_bh(struct work_struct *data) ++{ ++ struct vpmadt032 *vpm = container_of(data, struct vpmadt032, work); ++ struct change_order *order; ++ ++ while ((order = get_next_order(vpm))) { ++ ++ struct adt_lec_params *old; ++ struct adt_lec_params *new; ++ unsigned int channel; ++ ++ channel = order->channel; ++ BUG_ON(channel >= ARRAY_SIZE(vpm->curecstate)); ++ old = &vpm->curecstate[channel]; ++ new = &order->params; ++ ++ if (nlp_settings_changed(new, old)) ++ update_channel_config(vpm, channel, new); ++ else if (echocan_on(new, old)) ++ vpmadt032_enable_ec(vpm, channel, new->companding); ++ else if (echocan_off(new, old)) ++ vpmadt032_disable_ec(vpm, channel); ++ ++ *old = order->params; ++ free_change_order(order); ++ } ++} ++ ++#include "adt_lec.c" ++static void vpmadt032_check_and_schedule_update(struct vpmadt032 *vpm, ++ struct change_order *order) ++{ ++ struct change_order *cur; ++ struct change_order *n; ++ ++ INIT_LIST_HEAD(&order->node); ++ spin_lock(&vpm->change_list_lock); ++ list_for_each_entry_safe(cur, n, &vpm->change_list, node) { ++ if (cur->channel == order->channel) { ++ list_replace(&cur->node, &order->node); ++ free_change_order(cur); ++ break; ++ } ++ } ++ if (list_empty(&order->node)) ++ list_add_tail(&order->node, &vpm->change_list); ++ spin_unlock(&vpm->change_list_lock); ++ ++ queue_work(vpm->wq, &vpm->work); ++} ++int vpmadt032_echocan_create(struct vpmadt032 *vpm, int channo, ++ enum adt_companding companding, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p) ++{ ++ unsigned int ret; ++ struct change_order *order = alloc_change_order(); ++ if (!order) ++ return -ENOMEM; ++ ++ memcpy(&order->params, &vpm->curecstate[channo], sizeof(order->params)); ++ ret = adt_lec_parse_params(&order->params, ecp, p); ++ if (ret) { ++ free_change_order(order); ++ return ret; ++ } ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) { ++ vpm_info(vpm, "Channel is %d length %d\n", ++ channo, ecp->tap_length); ++ } ++ ++ /* The driver cannot control the number of taps on the VPMADT032 ++ * module. Instead, it uses tap_length to enable or disable the echo ++ * cancellation. */ ++ order->params.tap_length = (ecp->tap_length) ? 1 : 0; ++ order->params.companding = companding; ++ order->channel = channo; ++ ++ vpmadt032_check_and_schedule_update(vpm, order); ++ return 0; ++} ++EXPORT_SYMBOL(vpmadt032_echocan_create); ++ ++void vpmadt032_echocan_free(struct vpmadt032 *vpm, int channo, ++ struct dahdi_echocan_state *ec) ++{ ++ struct change_order *order; ++ order = alloc_change_order(); ++ WARN_ON(!order); ++ if (!order) ++ return; ++ ++ adt_lec_init_defaults(&order->params, 0); ++ order->params.nlp_type = vpm->options.vpmnlptype; ++ order->params.nlp_threshold = vpm->options.vpmnlpthresh; ++ order->params.nlp_max_suppress = vpm->options.vpmnlpmaxsupp; ++ order->channel = channo; ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) ++ vpm_info(vpm, "Channel is %d length 0\n", channo); ++ ++ vpmadt032_check_and_schedule_update(vpm, order); ++} ++EXPORT_SYMBOL(vpmadt032_echocan_free); ++ ++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); ++ spin_lock_init(&vpm->change_list_lock); ++ INIT_LIST_HEAD(&vpm->change_list); ++ INIT_LIST_HEAD(&vpm->pending_cmds); ++ INIT_LIST_HEAD(&vpm->active_cmds); ++ sema_init(&vpm->sem, 1); ++ vpm->curpage = 0x80; ++ vpm->dspid = -1; ++ INIT_WORK(&vpm->work, vpmadt032_bh); ++ ++ /* Do not use the global workqueue for processing these events. Some of ++ * the operations can take 100s of ms, most of that time spent sleeping. ++ * On single CPU systems, this unduly serializes operations accross ++ * multiple vpmadt032 instances. */ ++ vpm->wq = create_singlethread_workqueue("vpmadt032"); ++ if (!vpm->wq) { ++ kfree(vpm); ++ return NULL; ++ } ++ ++ /* Place this structure in the ifaces array so that the DspId from the ++ * Gpak Library can be used to locate it. */ ++ spin_lock(&ifacelock); ++ for (i=0; idspid = i; ++ break; ++ } ++ } ++ spin_unlock(&ifacelock); ++ ++ if (-1 == vpm->dspid) { ++ kfree(vpm); ++ dev_notice(&vpm->vb->pdev->dev, "Unable to initialize another vpmadt032 modules\n"); ++ vpm = NULL; ++ } ++ ++ return vpm; ++} ++EXPORT_SYMBOL(vpmadt032_alloc); ++ ++int vpmadt032_reset(struct vpmadt032 *vpm) ++{ ++ int res; ++ gpakPingDspStat_t pingstatus; ++ u16 version; ++ unsigned long stoptime; ++ struct device *const dev = &vpm->vb->pdev->dev; ++ ++ might_sleep(); ++ ++ set_bit(VPM150M_HPIRESET, &vpm->control); ++ msleep(2000); ++ /* It should never take longer than 5 seconds. */ ++ stoptime = jiffies + 3*HZ; ++ while (test_bit(VPM150M_HPIRESET, &vpm->control) && ++ time_before(jiffies, stoptime)) ++ msleep(1); ++ ++ if (time_after(jiffies, stoptime)) { ++ dev_dbg(dev, "Detected failure to clear HPIRESET.\n"); ++ return -EIO; ++ } ++ ++ /* Set us up to page 0 */ ++ vpmadt032_setpage(vpm, 0); ++ ++ res = vpmadtreg_loadfirmware(vpm->vb); ++ if (res) { ++ dev_err(dev, "Failed to load VPMADT032 firmware.\n"); ++ return res; ++ } ++ vpm->curpage = -1; ++ ++ stoptime = jiffies + 3*HZ; ++ set_bit(VPM150M_SWRESET, &vpm->control); ++ while (test_bit(VPM150M_SWRESET, &vpm->control) && ++ time_before(jiffies, stoptime)) ++ msleep(1); ++ ++ if (time_after(jiffies, stoptime)) { ++ dev_dbg(dev, "Detected failure to clear SWRESET.\n"); ++ return -EIO; ++ } ++ ++ ++ /* Set us up to page 0 */ ++ pingstatus = gpakPingDsp(vpm->dspid, &version); ++ if (!pingstatus) { ++ vpm_info(vpm, "VPM present and operational " ++ "(Firmware version %x)\n", version); ++ vpm->version = version; ++ res = 0; ++ } else { ++ res = -EIO; ++ } ++ return res; ++} ++EXPORT_SYMBOL(vpmadt032_reset); ++ ++/** ++ * vpmadt032_test - Check if there is a VPMADT032 present on voicebus device. ++ * @vpm: Allocated with vpmadt032_alloc previously. ++ * @vb: Voicebus structure to test on. ++ * ++ * Returns 0 if there is a device, otherwise -ENODEV. ++ * ++ */ ++int vpmadt032_test(struct vpmadt032 *vpm, struct voicebus *vb) ++{ ++ u8 reg; ++ int i, x; ++ struct device *dev = &vb->pdev->dev; ++ ++ vpm->vb = vb; ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) ++ dev_info(dev, "VPMADT032 Testing page access: "); ++ ++ for (i = 0; i < 0xf; i++) { ++ for (x = 0; x < 3; x++) { ++ vpmadt032_setpage(vpm, i); ++ reg = vpmadt032_getpage(vpm); ++ if (reg != i) { ++ if (vpm->options.debug & ++ DEBUG_VPMADT032_ECHOCAN) { ++ dev_err(dev, "Failed: Sent %x != %x " \ ++ "VPMADT032 Failed HI page " \ ++ "test\n", i, reg); ++ } ++ return -ENODEV; ++ } ++ } ++ } ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) ++ dev_info(dev, "Passed\n"); ++ ++ return 0; ++} ++EXPORT_SYMBOL(vpmadt032_test); ++ ++/** ++ * vpmadt032_init - Initialize and load VPMADT032 firmware. ++ * @vpm: Allocated with vpmadt032_alloc previously. ++ * ++ * Returns 0 on success. This must be called after vpmadt032_test already ++ * checked if there appears to be a VPMADT032 installed on the board. ++ * ++ */ ++int vpmadt032_init(struct vpmadt032 *vpm) ++{ ++ int i; ++ u16 reg; ++ int res = -EFAULT; ++ unsigned long stoptime; ++ struct device *dev; ++ gpakPingDspStat_t pingstatus; ++ ++ BUG_ON(!vpm->setchanconfig_from_state); ++ BUG_ON(!vpm->wq); ++ BUG_ON(!vpm->vb); ++ ++ might_sleep(); ++ ++ dev = &vpm->vb->pdev->dev; ++ ++ stoptime = jiffies + 3*HZ; ++ set_bit(VPM150M_HPIRESET, &vpm->control); ++ while (test_bit(VPM150M_HPIRESET, &vpm->control) && ++ time_before(jiffies, stoptime)) ++ msleep(1); ++ ++ if (time_after(jiffies, stoptime)) { ++ dev_dbg(dev, "Detected failure to clear HPIRESET.\n"); ++ res = -EIO; ++ goto failed_exit; ++ } ++ msleep(250); ++ ++ /* Set us up to page 0 */ ++ vpmadt032_setpage(vpm, 0); ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) ++ dev_info(&vpm->vb->pdev->dev, "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(KERN_CONT "VPMADT032 Failed address test\n"); ++ res = -EIO; ++ } ++ } ++ } ++ ++ if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN) ++ printk(KERN_CONT "Passed\n"); ++ ++ stoptime = jiffies + 3*HZ; ++ set_bit(VPM150M_HPIRESET, &vpm->control); ++ while (test_bit(VPM150M_HPIRESET, &vpm->control) && ++ time_before(jiffies, stoptime)) ++ msleep(1); ++ ++ if (time_after(jiffies, stoptime)) { ++ dev_dbg(dev, "Detected failure to clear SWRESET.\n"); ++ res = -EIO; ++ goto failed_exit; ++ } ++ ++ res = vpmadtreg_loadfirmware(vpm->vb); ++ if (res) { ++ dev_info(&vpm->vb->pdev->dev, "Failed to load the firmware.\n"); ++ return res; ++ } ++ vpm->curpage = -1; ++ ++ dev_info(&vpm->vb->pdev->dev, "Booting VPMADT032\n"); ++ ++ stoptime = jiffies + 3*HZ; ++ set_bit(VPM150M_SWRESET, &vpm->control); ++ while (test_bit(VPM150M_SWRESET, &vpm->control) && ++ time_before(jiffies, stoptime)) ++ msleep(1); ++ ++ if (time_after(jiffies, stoptime)) { ++ dev_dbg(dev, "Detected failure to clear SWRESET.\n"); ++ res = -EIO; ++ goto failed_exit; ++ } ++ ++ pingstatus = gpakPingDsp(vpm->dspid, &vpm->version); ++ ++ if (!pingstatus) { ++ dev_info(&vpm->vb->pdev->dev, "VPM present and operational " ++ "(Firmware version %x)\n", vpm->version); ++ } else { ++ dev_notice(&vpm->vb->pdev->dev, "VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); ++ res = -EIO; ++ goto failed_exit; ++ } ++ ++ return 0; ++ ++failed_exit: ++ return res; ++} ++EXPORT_SYMBOL(vpmadt032_init); ++ ++ ++void vpmadt032_get_default_parameters(struct GpakEcanParms *p) ++{ ++ memset(p, 0, sizeof(*p)); ++ ++ p->EcanTapLength = 1024; ++ p->EcanNlpType = DEFAULT_NLPTYPE; ++ p->EcanAdaptEnable = 1; ++ ++#ifdef CONFIG_DAHDI_NO_ECHOCAN_DISABLE ++ p->EcanG165DetEnable = 0; ++#else ++ p->EcanG165DetEnable = 1; ++#endif ++ ++ p->EcanDblTalkThresh = 6; ++ p->EcanMaxDoubleTalkThres = 40; ++ p->EcanNlpThreshold = DEFAULT_NLPTHRESH; ++ p->EcanNlpConv = 18; ++ p->EcanNlpUnConv = 12; ++ p->EcanNlpMaxSuppress = DEFAULT_NLPMAXSUPP; ++ p->EcanCngThreshold = 43; ++ p->EcanAdaptLimit = 25; ++ p->EcanCrossCorrLimit = 15; ++ p->EcanNumFirSegments = 3; ++ p->EcanFirSegmentLen = 48; ++ p->EcanReconvergenceCheckEnable = 1; ++ p->EcanTandemOperationEnable = 0; ++ p->EcanMixedFourWireMode = 0; ++ p->EcanSaturationLevel = 3; ++ p->EcanNLPSaturationThreshold = 6; ++} ++EXPORT_SYMBOL(vpmadt032_get_default_parameters); ++ ++void vpmadt032_free(struct vpmadt032 *vpm) ++{ ++ unsigned long flags; ++ struct vpmadt032_cmd *cmd; ++ struct change_order *order; ++ LIST_HEAD(local_list); ++ ++ if (!vpm) ++ return; ++ ++ BUG_ON(!vpm->wq); ++ ++ destroy_workqueue(vpm->wq); ++ ++ /* 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); ++ 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); ++ } ++ ++ spin_lock(&vpm->change_list_lock); ++ list_splice(&vpm->change_list, &local_list); ++ spin_unlock(&vpm->change_list_lock); ++ ++ while (!list_empty(&local_list)) { ++ order = list_entry(local_list.next, struct change_order, node); ++ list_del(&order->node); ++ kfree(order); ++ } ++ ++ BUG_ON(ifaces[vpm->dspid] != vpm); ++ spin_lock(&ifacelock); ++ ifaces[vpm->dspid] = NULL; ++ spin_unlock(&ifacelock); ++ kfree(vpm); ++} ++EXPORT_SYMBOL(vpmadt032_free); ++ ++/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * 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]; ++ memset(cmds, 0, sizeof(cmds)); ++ 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; ivb->pdev->dev, "Writing %d words to memory\n", NumWords); ++ if (vpm) { ++ for (i = 0; i < NumWords; ++i) { ++ vpmadt032_setreg(vpm, DspAddress + i, pWordValues[i]); ++ } ++#if 0 ++ for (i = 0; i < NumWords; i++) { ++ if (wctdm_vpmadt032_getreg(wc, DspAddress + i) != pWordValues[i]) { ++ dev_notice(&vpm->vb->pdev->dev, "Error in write. Address %x is not %x\n", DspAddress + i, pWordValues[i]); ++ } ++ } ++#endif ++ } ++ return; ++ ++} ++ ++ ++/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * gpakHostDelay - Delay for a fixed time interval. ++ * ++ * FUNCTION ++ * This function delays for a fixed time interval before returning. The time ++ * interval is the Host Port Interface sampling period when polling a DSP for ++ * replies to command messages. ++ * ++ * RETURNS ++ * nothing ++ * ++ */ ++void gpakHostDelay(void) ++{ ++} ++ ++ ++/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * gpakLockAccess - Lock access to the specified DSP. ++ * ++ * FUNCTION ++ * This function aquires exclusive access to the specified DSP. ++ * ++ * RETURNS ++ * nothing ++ * ++ */ ++void gpakLockAccess(unsigned short DspId) ++{ ++ struct vpmadt032 *vpm; ++ ++ vpm = find_iface(DspId); ++ ++ if (!vpm) ++ return; ++ ++ down(&vpm->sem); ++ return; ++} ++ ++ ++/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * gpakUnlockAccess - Unlock access to the specified DSP. ++ * ++ * FUNCTION ++ * This function releases exclusive access to the specified DSP. ++ * ++ * RETURNS ++ * nothing ++ * ++ */ ++void gpakUnlockAccess(unsigned short DspId) ++{ ++ struct vpmadt032 *vpm; ++ ++ vpm = find_iface(DspId); ++ ++ if (vpm) { ++ up(&vpm->sem); ++ } ++} ++ ++ ++/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * gpakReadFile - Read a block of bytes from a G.PAK Download file. ++ * ++ * FUNCTION ++ * This function reads a contiguous block of bytes from a G.PAK Download file ++ * starting at the current file position. ++ * ++ * RETURNS ++ * The number of bytes read from the file. ++ * -1 indicates an error occurred. ++ * 0 indicates all bytes have been read (end of file) ++ * ++ */ ++int gpakReadFile( ++ GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ ++ unsigned char *pBuffer, /* pointer to buffer for storing bytes */ ++ unsigned int NumBytes /* number of bytes to read */ ++ ) ++{ ++ /* The firmware is loaded into the part by a closed-source firmware ++ * loader, and therefore this function should never be called. */ ++ WARN_ON(1); ++ return -1; ++} +diff -Nru linux-source-4.19/drivers/dahdi/voicebus/GpakCust.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakCust.h +--- linux-source-4.19/drivers/dahdi/voicebus/GpakCust.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakCust.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,295 @@ ++/* ++ * 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 ++#include ++#include ++#include ++ ++#include "gpakenum.h" ++#include "adt_lec.h" ++ ++#define DEBUG_VPMADT032_ECHOCAN (1 << 4) ++ ++/* 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_HPIRESET 1 ++#define VPM150M_SWRESET 2 ++#define VPM150M_ACTIVE 4 ++ ++#define NLPTYPE_NONE 0 ++#define NLPTYPE_MUTE 1 ++#define NLPTYPE_RANDOM_NOISE 2 ++#define HOTH_NOISE_NLPTYPE 3 ++#define NLPTYPE_SUPPRESS 4 ++#define NLPTYPE_RESERVED 5 ++#define NLPTYPE_AUTOSUPPRESS 6 ++#define DEFAULT_NLPTYPE NLPTYPE_AUTOSUPPRESS ++ ++/* This is the threshold (in dB) for enabling and disabling of the NLP */ ++#define DEFAULT_NLPTHRESH 22 ++#define DEFAULT_NLPMAXSUPP 10 ++ ++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; ++ ++struct vpmadt032 { ++ struct voicebus *vb; ++ struct work_struct work; ++ struct workqueue_struct *wq; ++ int dspid; ++ struct semaphore sem; ++ unsigned long control; ++ unsigned char curpage; ++ unsigned short version; ++ struct adt_lec_params curecstate[MAX_CHANNELS]; ++ spinlock_t change_list_lock; ++ struct list_head change_list; ++ spinlock_t list_lock; ++ /* 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; ++ struct vpmadt032_options options; ++ void (*setchanconfig_from_state)(struct vpmadt032 *vpm, int channel, struct GpakChannelConfig *chanconfig); ++}; ++ ++struct voicebus; ++struct dahdi_chan; ++struct dahdi_echocanparams; ++struct dahdi_echocanparam; ++struct dahdi_echocan_state; ++ ++char vpmadt032tone_to_zaptone(GpakToneCodes_t tone); ++int vpmadt032_test(struct vpmadt032 *vpm, struct voicebus *vb); ++int vpmadt032_init(struct vpmadt032 *vpm); ++int vpmadt032_reset(struct vpmadt032 *vpm); ++struct vpmadt032 *vpmadt032_alloc(struct vpmadt032_options *options); ++void vpmadt032_free(struct vpmadt032 *vpm); ++int vpmadt032_echocan_create(struct vpmadt032 *vpm, int channo, ++ enum adt_companding companding, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p); ++void vpmadt032_echocan_free(struct vpmadt032 *vpm, int channo, ++ struct dahdi_echocan_state *ec); ++ ++struct GpakEcanParms; ++void vpmadt032_get_default_parameters(struct GpakEcanParms *p); ++ ++/* If there is a command ready to go to the VPMADT032, return it, otherwise ++ * NULL. Call with local interrupts disabled. */ ++static inline struct vpmadt032_cmd *vpmadt032_get_ready_cmd(struct vpmadt032 *vpm) ++{ ++ struct vpmadt032_cmd *cmd; ++ ++ spin_lock(&vpm->list_lock); ++ if (list_empty(&vpm->pending_cmds)) { ++ spin_unlock(&vpm->list_lock); ++ return NULL; ++ } ++ cmd = list_entry(vpm->pending_cmds.next, struct vpmadt032_cmd, node); ++ list_move_tail(&cmd->node, &vpm->active_cmds); ++ spin_unlock(&vpm->list_lock); ++ return cmd; ++} ++ ++/** ++ * call with local interrupts disabled. ++ */ ++static inline void vpmadt032_resend(struct vpmadt032 *vpm) ++{ ++ struct vpmadt032_cmd *cmd, *temp; ++ ++ /* By moving the commands back to the pending list, they will be ++ * transmitted when room is available */ ++ spin_lock(&vpm->list_lock); ++ list_for_each_entry_safe(cmd, temp, &vpm->active_cmds, node) { ++ cmd->desc &= ~(__VPM150M_TX); ++ list_move_tail(&cmd->node, &vpm->pending_cmds); ++ } ++ spin_unlock(&vpm->list_lock); ++} ++ ++ ++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 -Nru linux-source-4.19/drivers/dahdi/voicebus/GpakHpi.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakHpi.h +--- linux-source-4.19/drivers/dahdi/voicebus/GpakHpi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/GpakHpi.h 2020-10-28 00:17:08.671192284 +0100 +@@ -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 -Nru linux-source-4.19/drivers/dahdi/voicebus/Kbuild linux-source-4.19-dahdi/drivers/dahdi/voicebus/Kbuild +--- linux-source-4.19/drivers/dahdi/voicebus/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/Kbuild 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,18 @@ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += dahdi_voicebus.o ++ ++dahdi_voicebus-objs := voicebus.o GpakCust.o GpakApi.o voicebus_net.o vpmoct.o ++ ++FIRM_DIR := ../firmware ++ ++ifneq ($(HOTPLUG_FIRMWARE),yes) ++dahdi_voicebus-objs += $(FIRM_DIR)/dahdi-fw-vpmoct032.o ++$(warning WARNING: You are compiling firmware into voicebus.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.) ++else ++ EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE ++endif ++ ++EXTRA_CFLAGS += -I$(src)/.. -Wno-undef ++ ++$(obj)/$(FIRM_DIR)/dahdi-fw-vpmoct032.o: $(obj)/voicebus.o ++ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-vpmoct032.o ++ +diff -Nru linux-source-4.19/drivers/dahdi/voicebus/gpakErrs.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/gpakErrs.h +--- linux-source-4.19/drivers/dahdi/voicebus/gpakErrs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/gpakErrs.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,156 @@ ++/* ++ * 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. */ ++ Cc_PortDmaNotStarted = 54, /* SerialPort not ready */ ++ Cc_ChannelDebugActive = 55, /* Debug Channel is not active */ ++ Cc_ChannelDebugEnabled = 56 /* Channel already been debugged */ ++} 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 -Nru linux-source-4.19/drivers/dahdi/voicebus/gpakenum.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/gpakenum.h +--- linux-source-4.19/drivers/dahdi/voicebus/gpakenum.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/gpakenum.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,192 @@ ++/* ++ * 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 */ ++ tdmToTdmDebug = 2 /* 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 -Nru linux-source-4.19/drivers/dahdi/voicebus/voicebus.c linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus.c +--- linux-source-4.19/drivers/dahdi/voicebus/voicebus.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,2017 @@ ++/* ++ * VoiceBus(tm) Interface Library. ++ * ++ * Written by Shaun Ruffell ++ * and based on previous work by Mark Spencer , ++ * Matthew Fredrickson , and ++ * Michael Spiceland ++ * ++ * Copyright (C) 2007-2010 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 ++#include "voicebus.h" ++#include "voicebus_net.h" ++#include "vpmadtreg.h" ++#include "GpakCust.h" ++ ++#if VOICEBUS_DEFERRED == TIMER ++#if HZ < 1000 ++/* \todo Put an error message here. */ ++#endif ++#endif ++ ++/* 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_COMMON_INTERRUPTS (CSR7_TCIE|CSR7_TPSIE|CSR7_RUIE|CSR7_RSIE|\ ++ CSR7_FBEIE|CSR7_AIE|CSR7_NIE) ++ ++#define DEFAULT_NORMAL_INTERRUPTS (DEFAULT_COMMON_INTERRUPTS|CSR7_TDUIE) ++ ++#define DEFAULT_NO_IDLE_INTERRUPTS (DEFAULT_COMMON_INTERRUPTS|CSR7_RCIE) ++ ++#define CSR9 0x0048 ++#define CSR9_MDC 0x00010000 ++#define CSR9_MDO 0x00020000 ++#define CSR9_MMC 0x00040000 ++#define CSR9_MDI 0x00080000 ++ ++#define OWN_BIT cpu_to_le32(1 << 31) ++ ++#ifdef CONFIG_VOICEBUS_ECREFERENCE ++ ++/* ++ * These dahdi_fifo_xxx functions are currently only used by the voicebus ++ * drivers, but are named more generally to facilitate moving out in the ++ * future. They probably also could stand to be changed in order to use a ++ * kfifo implementation from the kernel if one is available. ++ * ++ */ ++ ++struct dahdi_fifo { ++ size_t total_size; ++ u32 start; ++ u32 end; ++ u8 data[0]; ++}; ++ ++static unsigned int dahdi_fifo_used_space(struct dahdi_fifo *fifo) ++{ ++ return (fifo->end >= fifo->start) ? fifo->end - fifo->start : ++ fifo->total_size - fifo->start + fifo->end; ++} ++ ++unsigned int __dahdi_fifo_put(struct dahdi_fifo *fifo, u8 *data, size_t size) ++{ ++ int newinsertposition; ++ int cpy_one_len, cpy_two_len; ++ ++ if ((size + dahdi_fifo_used_space(fifo)) > (fifo->total_size - 1)) ++ return -1; ++ ++ if ((fifo->end + size) >= fifo->total_size) { ++ cpy_one_len = fifo->total_size - fifo->end; ++ cpy_two_len = fifo->end + size - fifo->total_size; ++ newinsertposition = cpy_two_len; ++ } else { ++ cpy_one_len = size; ++ cpy_two_len = 0; ++ newinsertposition = fifo->end + size; ++ } ++ ++ memcpy(&fifo->data[fifo->end], data, cpy_one_len); ++ ++ if (cpy_two_len) ++ memcpy(&fifo->data[0], &data[cpy_one_len], cpy_two_len); ++ ++ fifo->end = newinsertposition; ++ ++ return size; ++} ++EXPORT_SYMBOL(__dahdi_fifo_put); ++ ++unsigned int __dahdi_fifo_get(struct dahdi_fifo *fifo, u8 *data, size_t size) ++{ ++ int newbegin; ++ int cpy_one_len, cpy_two_len; ++ ++ if (size > dahdi_fifo_used_space(fifo)) ++ return 0; ++ ++ if ((fifo->start + size) >= fifo->total_size) { ++ cpy_one_len = fifo->total_size - fifo->start; ++ cpy_two_len = fifo->start + size - fifo->total_size; ++ newbegin = cpy_two_len; ++ } else { ++ cpy_one_len = size; ++ cpy_two_len = 0; ++ newbegin = fifo->start + size; ++ } ++ ++ memcpy(&data[0], &fifo->data[fifo->start], cpy_one_len); ++ ++ if (cpy_two_len) ++ memcpy(&data[cpy_one_len], &fifo->data[0], cpy_two_len); ++ ++ fifo->start = newbegin; ++ ++ return size; ++} ++EXPORT_SYMBOL(__dahdi_fifo_get); ++ ++void dahdi_fifo_free(struct dahdi_fifo *fifo) ++{ ++ kfree(fifo); ++} ++EXPORT_SYMBOL(dahdi_fifo_free); ++ ++struct dahdi_fifo *dahdi_fifo_alloc(u32 maxsize, gfp_t alloc_flags) ++{ ++ struct dahdi_fifo *fifo; ++ ++ fifo = kmalloc(maxsize + sizeof(*fifo) + 1, alloc_flags); ++ ++ if (!fifo) ++ return NULL; ++ ++ fifo->start = fifo->end = 0; ++ fifo->total_size = maxsize + 1; ++ ++ return fifo; ++} ++EXPORT_SYMBOL(dahdi_fifo_alloc); ++#endif /* CONFIG_VOICEBUS_ECREFERENCE */ ++ ++ ++/* In memory structure shared by the host and the adapter. */ ++struct voicebus_descriptor { ++ volatile __le32 des0; ++ volatile __le32 des1; ++ volatile __le32 buffer1; ++ volatile __le32 container; /* Unused */ ++} __attribute__((packed)); ++ ++static inline void ++handle_transmit(struct voicebus *vb, struct list_head *buffers) ++{ ++ vb->ops->handle_transmit(vb, buffers); ++} ++ ++static inline void ++handle_receive(struct voicebus *vb, struct list_head *buffers) ++{ ++ vb->ops->handle_receive(vb, buffers); ++} ++ ++static inline struct voicebus_descriptor * ++vb_descriptor(const struct voicebus_descriptor_list *dl, ++ const unsigned 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; ++ u8 cacheline_size; ++ ++ BUG_ON(!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 (pci_read_config_byte(vb->pdev, PCI_CACHE_LINE_SIZE, ++ &cacheline_size)) { ++ dev_err(&vb->pdev->dev, "Failed read of cache line " ++ "size from PCI configuration space.\n"); ++ return -EIO; ++ } ++ ++ if ((0x08 == cacheline_size) || (0x10 == cacheline_size) || ++ (0x20 == cacheline_size)) { ++ dl->padding = (cacheline_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 = cpu_to_le32(des1); ++ } ++ d->des1 |= cpu_to_le32(END_OF_RING); ++ dl->count = 0; ++ return 0; ++} ++ ++#define OWNED(_d_) (((_d_)->des0)&OWN_BIT) ++#define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb(); } while (0) ++ ++static int ++vb_initialize_tx_descriptors(struct voicebus *vb) ++{ ++ int i; ++ int des1 = 0xe4800000 | VOICEBUS_SFRAME_SIZE; ++ struct voicebus_descriptor *d; ++ struct voicebus_descriptor_list *dl = &vb->txd; ++ const u32 END_OF_RING = 0x02000000; ++ u8 cacheline_size; ++ ++ WARN_ON(!dl); ++ WARN_ON((NULL == vb->idle_vbb) || (0 == vb->idle_vbb_dma_addr)); ++ ++ /* ++ * 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 (pci_read_config_byte(vb->pdev, PCI_CACHE_LINE_SIZE, ++ &cacheline_size)) { ++ dev_err(&vb->pdev->dev, "Failed read of cache line " ++ "size from PCI configuration space.\n"); ++ return -EIO; ++ } ++ ++ if ((0x08 == cacheline_size) || (0x10 == cacheline_size) || ++ (0x20 == cacheline_size)) { ++ dl->padding = (cacheline_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 = cpu_to_le32(des1); ++ dl->pending[i] = NULL; ++ d->buffer1 = 0; ++ } ++ d->des1 |= cpu_to_le32(END_OF_RING); ++ dl->count = 0; ++ return 0; ++} ++ ++static int ++vb_initialize_rx_descriptors(struct voicebus *vb) ++{ ++ return vb_initialize_descriptors( ++ vb, &vb->rxd, VOICEBUS_SFRAME_SIZE, 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) ++{ ++ unsigned long flags; ++ /* ++ * 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) { ++ dev_warn(&vb->pdev->dev, MESSAGE, ms, DRING_SIZE); ++ return -EINVAL; ++ } else if (VOICEBUS_DEFAULT_LATENCY > ms) { ++ dev_warn(&vb->pdev->dev, MESSAGE, ms, VOICEBUS_DEFAULT_LATENCY); ++ return -EINVAL; ++ } ++ spin_lock_irqsave(&vb->lock, flags); ++ vb->min_tx_buffer_count = ms; ++ spin_unlock_irqrestore(&vb->lock, flags); ++ return 0; ++} ++EXPORT_SYMBOL(voicebus_set_minlatency); ++ ++/*! \brief Returns the number of buffers currently on the transmit queue. */ ++int ++voicebus_current_latency(struct voicebus *vb) ++{ ++ int latency; ++ unsigned long flags; ++ spin_lock_irqsave(&vb->lock, flags); ++ latency = vb->min_tx_buffer_count; ++ spin_unlock_irqrestore(&vb->lock, flags); ++ 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) ++{ ++ u32 ret; ++ ret = readl(vb->iobase + addr); ++ rmb(); ++ return ret; ++} ++ ++/*! ++ * \brief Read one of the hardware control registers with locks held. ++ */ ++static inline u32 ++vb_getctl(struct voicebus *vb, u32 addr) ++{ ++ unsigned long flags; ++ u32 val; ++ spin_lock_irqsave(&vb->lock, flags); ++ val = __vb_getctl(vb, addr); ++ spin_unlock_irqrestore(&vb->lock, flags); ++ return val; ++} ++ ++static int ++__vb_is_stopped(struct voicebus *vb) ++{ ++ u32 reg; ++ reg = __vb_getctl(vb, SR_CSR5); ++ reg = (reg >> 17) & 0x3f; ++ return ((0 == reg) || (3 == reg)) ? 1 : 0; ++} ++/*! ++ * \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) ++{ ++ int ret; ++ unsigned long flags; ++ spin_lock_irqsave(&vb->lock, flags); ++ ret = __vb_is_stopped(vb); ++ spin_unlock_irqrestore(&vb->lock, flags); ++ return ret; ++} ++ ++#if defined(CONFIG_VOICEBUS_INTERRUPT) ++ ++static inline void vb_disable_deferred(struct voicebus *vb) ++{ ++ if (atomic_inc_return(&vb->deferred_disabled_count) == 1) ++ disable_irq(vb->pdev->irq); ++} ++ ++static inline void vb_enable_deferred(struct voicebus *vb) ++{ ++ if (atomic_dec_return(&vb->deferred_disabled_count) == 0) ++ enable_irq(vb->pdev->irq); ++} ++ ++#else ++ ++static inline void vb_disable_deferred(struct voicebus *vb) ++{ ++ tasklet_disable(&vb->tasklet); ++} ++ ++static inline void vb_enable_deferred(struct voicebus *vb) ++{ ++ tasklet_enable(&vb-tasklet); ++} ++ ++#endif ++ ++static void ++vb_cleanup_tx_descriptors(struct voicebus *vb) ++{ ++ unsigned int i; ++ struct voicebus_descriptor_list *dl = &vb->txd; ++ struct voicebus_descriptor *d; ++ struct vbb *vbb; ++ ++ vb_disable_deferred(vb); ++ ++ while (!list_empty(&vb->tx_complete)) { ++ vbb = list_entry(vb->tx_complete.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ dma_pool_free(vb->pool, vbb, vbb->dma_addr); ++ } ++ ++ for (i = 0; i < DRING_SIZE; ++i) { ++ d = vb_descriptor(dl, i); ++ if (d->buffer1 && ++ (d->buffer1 != le32_to_cpu(vb->idle_vbb_dma_addr))) { ++ WARN_ON(!dl->pending[i]); ++ vbb = dl->pending[i]; ++ dma_pool_free(vb->pool, vbb, vbb->dma_addr); ++ } ++ if (NORMAL == vb->mode) { ++ d->des1 |= cpu_to_le32(0x80000000); ++ d->buffer1 = cpu_to_le32(vb->idle_vbb_dma_addr); ++ dl->pending[i] = vb->idle_vbb; ++ SET_OWNED(d); ++ } else { ++ d->buffer1 = 0; ++ dl->pending[i] = NULL; ++ d->des0 &= ~OWN_BIT; ++ } ++ } ++ ++ dl->head = dl->tail = 0; ++ dl->count = 0; ++ vb_enable_deferred(vb); ++} ++ ++static void vb_cleanup_rx_descriptors(struct voicebus *vb) ++{ ++ unsigned int i; ++ struct voicebus_descriptor_list *dl = &vb->rxd; ++ struct voicebus_descriptor *d; ++ struct vbb *vbb; ++ ++ vb_disable_deferred(vb); ++ for (i = 0; i < DRING_SIZE; ++i) { ++ d = vb_descriptor(dl, i); ++ if (d->buffer1) { ++ d->buffer1 = 0; ++ BUG_ON(!dl->pending[i]); ++ vbb = dl->pending[i]; ++ list_add_tail(&vbb->entry, &vb->free_rx); ++ dl->pending[i] = NULL; ++ } ++ d->des0 &= ~OWN_BIT; ++ } ++ dl->head = 0; ++ dl->tail = 0; ++ dl->count = 0; ++ vb_enable_deferred(vb); ++} ++ ++static void vb_cleanup_descriptors(struct voicebus *vb, ++ struct voicebus_descriptor_list *dl) ++{ ++ if (dl == &vb->txd) ++ vb_cleanup_tx_descriptors(vb); ++ else ++ vb_cleanup_rx_descriptors(vb); ++} ++ ++static void ++vb_free_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) ++{ ++ struct vbb *vbb; ++ 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); ++ while (!list_empty(&vb->free_rx)) { ++ vbb = list_entry(vb->free_rx.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ dma_pool_free(vb->pool, vbb, vbb->dma_addr); ++ } ++} ++ ++/*! ++ * \brief Write one of the hardware control registers without acquiring locks. ++ */ ++static inline void ++__vb_setctl(struct voicebus *vb, u32 addr, u32 val) ++{ ++ wmb(); ++ writel(val, vb->iobase + addr); ++ readl(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) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&vb->lock, flags); ++ __vb_setctl(vb, addr, val); ++ spin_unlock_irqrestore(&vb->lock, flags); ++} ++ ++static int ++__vb_sdi_clk(struct voicebus *vb, u32 *sdi) ++{ ++ unsigned int ret; ++ *sdi &= ~CSR9_MDC; ++ __vb_setctl(vb, 0x0048, *sdi); ++ ret = __vb_getctl(vb, 0x0048); ++ *sdi |= CSR9_MDC; ++ __vb_setctl(vb, 0x0048, *sdi); ++ return (ret & CSR9_MDI) ? 1 : 0; ++} ++ ++static void ++__vb_sdi_sendbits(struct voicebus *vb, u32 bits, int count, u32 *sdi) ++{ ++ *sdi &= ~CSR9_MMC; ++ __vb_setctl(vb, 0x0048, *sdi); ++ while (count--) { ++ ++ if (bits & (1 << count)) ++ *sdi |= CSR9_MDO; ++ else ++ *sdi &= ~CSR9_MDO; ++ ++ __vb_sdi_clk(vb, sdi); ++ } ++} ++ ++static void ++vb_setsdi(struct voicebus *vb, int addr, u16 val) ++{ ++ u32 bits; ++ u32 sdi = 0; ++ unsigned long flags; ++ /* Send preamble */ ++ bits = 0xffffffff; ++ spin_lock_irqsave(&vb->lock, flags); ++ __vb_sdi_sendbits(vb, bits, 32, &sdi); ++ bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; ++ __vb_sdi_sendbits(vb, bits, 16, &sdi); ++ __vb_sdi_sendbits(vb, val, 16, &sdi); ++ spin_unlock_irqrestore(&vb->lock, flags); ++} ++ ++/*! \brief Resets the voicebus hardware interface. */ ++static int ++vb_reset_interface(struct voicebus *vb) ++{ ++ unsigned long timeout; ++ u32 reg; ++ u32 pci_access; ++ enum { ++ /* Software Reset */ ++ SWR = (1 << 0), ++ /* Bus Arbitration (1 for priority transmit) */ ++ BAR = (1 << 1), ++ /* Memory Write Invalidate */ ++ MWI = (1 << 24), ++ /* Memory Read Line */ ++ MRL = (1 << 23), ++ /* Descriptor Skip Length */ ++ DSLShift = 2, ++ /* Cache Alignment */ ++ CALShift = 14, ++ /* Transmit Auto Pollling */ ++ TAPShift = 17, ++ }; ++ const u32 DEFAULT_PCI_ACCESS = MWI | MRL | (0x2 << TAPShift) | BAR; ++ u8 cacheline_size; ++ BUG_ON(in_interrupt()); ++ ++ if (pci_read_config_byte(vb->pdev, PCI_CACHE_LINE_SIZE, ++ &cacheline_size)) { ++ dev_err(&vb->pdev->dev, "Failed read of cache line " ++ "size from PCI configuration space.\n"); ++ return -EIO; ++ } ++ ++ switch (cacheline_size) { ++ case 0x08: ++ pci_access = DEFAULT_PCI_ACCESS | (0x1 << CALShift); ++ break; ++ case 0x10: ++ pci_access = DEFAULT_PCI_ACCESS | (0x2 << CALShift); ++ break; ++ case 0x20: ++ pci_access = DEFAULT_PCI_ACCESS | (0x3 << CALShift); ++ break; ++ default: ++ if (*vb->debug) { ++ dev_warn(&vb->pdev->dev, "Host system set a cache " ++ "size of %d which is not supported. " ++ "Disabling memory write line and memory " ++ "read line.\n", cacheline_size); ++ } ++ pci_access = 0xfe584202; ++ break; ++ } ++ ++ /* The transmit and receive descriptors will have the same padding. */ ++ pci_access |= ((vb->txd.padding / sizeof(u32)) << DSLShift) & 0x7c; ++ ++ vb_setctl(vb, 0x0000, pci_access | SWR); ++ ++ timeout = jiffies + HZ/10; /* 100ms interval */ ++ do { ++ reg = vb_getctl(vb, 0x0000); ++ } while ((reg & SWR) && time_before(jiffies, timeout)); ++ ++ if (reg & SWR) { ++ if (-1 == reg) { ++ dev_err(&vb->pdev->dev, ++ "Unable to read I/O registers.\n"); ++ } else { ++ dev_err(&vb->pdev->dev, "Did not come out of reset " ++ "within 100ms\n"); ++ } ++ return -EIO; ++ } ++ ++ vb_setctl(vb, 0x0000, pci_access); ++ ++ return 0; ++} ++ ++/*! ++ * \brief Give a frame to the hardware to use for receiving. ++ * ++ */ ++static inline int ++vb_submit_rxb(struct voicebus *vb, struct vbb *vbb) ++{ ++ struct voicebus_descriptor *d; ++ struct voicebus_descriptor_list *dl = &vb->rxd; ++ unsigned int tail = dl->tail; ++ ++ d = vb_descriptor(dl, tail); ++ ++ if (unlikely(d->buffer1)) { ++ /* Do not overwrite a buffer that is still in progress. */ ++ WARN_ON(1); ++ list_add_tail(&vbb->entry, &vb->free_rx); ++ return -EBUSY; ++ } ++ ++ dl->pending[tail] = vbb; ++ dl->tail = (++tail) & DRING_MASK; ++ d->buffer1 = cpu_to_le32(vbb->dma_addr); ++ SET_OWNED(d); /* That's it until the hardware is done with it. */ ++ ++dl->count; ++ return 0; ++} ++ ++static int __voicebus_transmit(struct voicebus *vb, struct vbb *vbb) ++{ ++ struct voicebus_descriptor *d; ++ struct voicebus_descriptor_list *dl = &vb->txd; ++ ++ d = vb_descriptor(dl, dl->tail); ++ ++ if (unlikely((le32_to_cpu(d->buffer1) != vb->idle_vbb_dma_addr) && ++ d->buffer1)) { ++ if (printk_ratelimit()) ++ dev_warn(&vb->pdev->dev, "Dropping tx buffer buffer\n"); ++ dma_pool_free(vb->pool, vbb, vbb->dma_addr); ++ /* Schedule the underrun handler to run here, since we'll need ++ * to cleanup as best we can. */ ++ schedule_work(&vb->underrun_work); ++ return -EFAULT; ++ } ++ ++ dl->pending[dl->tail] = vbb; ++ d->buffer1 = cpu_to_le32(vbb->dma_addr); ++ dl->tail = (dl->tail + 1) & DRING_MASK; ++ SET_OWNED(d); /* That's it until the hardware is done with it. */ ++ ++dl->count; ++ return 0; ++} ++ ++/** ++ * voicebus_transmit - Queue a buffer on the hardware descriptor ring. ++ * ++ */ ++int voicebus_transmit(struct voicebus *vb, struct vbb *vbb) ++{ ++ int res = __voicebus_transmit(vb, vbb); ++ __vb_setctl(vb, 0x0008, 0x00000000); ++ return res; ++} ++EXPORT_SYMBOL(voicebus_transmit); ++ ++ ++/*! ++ * \brief Instruct the hardware to check for a new tx descriptor. ++ */ ++static inline void ++__vb_tx_demand_poll(struct voicebus *vb) ++{ ++ u32 status = __vb_getctl(vb, 0x0028); ++ if ((status & 0x00700000) == 0x00600000) ++ __vb_setctl(vb, 0x0008, 0x00000000); ++} ++ ++static void setup_descriptors(struct voicebus *vb) ++{ ++ int i; ++ struct vbb *vbb; ++ dma_addr_t dma_addr; ++ LIST_HEAD(buffers); ++ unsigned long flags; ++ ++ might_sleep(); ++ ++ vb_cleanup_tx_descriptors(vb); ++ vb_cleanup_rx_descriptors(vb); ++ ++ /* 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); ++ ++ for (i = 0; i < DRING_SIZE; ++i) { ++ if (list_empty(&vb->free_rx)) { ++ vbb = dma_pool_alloc(vb->pool, GFP_KERNEL, ++ &dma_addr); ++ if (vbb) ++ vbb->dma_addr = dma_addr; ++ } else { ++ vbb = list_entry(vb->free_rx.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ } ++ if (unlikely(NULL == vbb)) ++ BUG_ON(1); ++ list_add_tail(&vbb->entry, &buffers); ++ } ++ ++ vb_disable_deferred(vb); ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ vb_submit_rxb(vb, vbb); ++ } ++ vb_enable_deferred(vb); ++ ++ if (BOOT != vb->mode) { ++ for (i = 0; i < vb->min_tx_buffer_count; ++i) { ++ vbb = dma_pool_alloc(vb->pool, GFP_KERNEL, ++ &dma_addr); ++ if (unlikely(NULL == vbb)) ++ BUG_ON(1); ++ ++ vbb->dma_addr = dma_addr; ++ list_add_tail(&vbb->entry, &buffers); ++ } ++ ++ local_irq_save(flags); ++ handle_transmit(vb, &buffers); ++ local_irq_restore(flags); ++ ++ vb_disable_deferred(vb); ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del_init(&vbb->entry); ++ __voicebus_transmit(vb, vbb); ++ } ++ __vb_setctl(vb, 0x0008, 0x00000000); ++ vb_enable_deferred(vb); ++ } ++ ++} ++ ++static void ++__vb_set_control_defaults(struct voicebus *vb) ++{ ++ /* 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); ++ vb_getctl(vb, 0x0078); ++} ++ ++static void __vb_set_mac_only_mode(struct voicebus *vb) ++{ ++ u32 reg; ++ reg = __vb_getctl(vb, 0x00fc); ++ __vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x4); ++ __vb_getctl(vb, 0x00fc); ++} ++ ++static int ++vb_initialize_interface(struct voicebus *vb) ++{ ++ u32 reg; ++ ++ setup_descriptors(vb); ++ ++ __vb_set_control_defaults(vb); ++ ++ reg = vb_getctl(vb, 0x00fc); ++ vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x7); ++ vb_setsdi(vb, 0x00, 0x0100); ++ vb_setsdi(vb, 0x16, 0x2100); ++ ++ __vb_set_mac_only_mode(vb); ++ 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; ++} ++ ++#ifdef DBG ++static void ++dump_descriptor(struct voicebus *vb, struct voicebus_descriptor *d) ++{ ++ VB_PRINTK(vb, DEBUG, "Displaying descriptor at address %08x\n", (unsigned int)d); ++ VB_PRINTK(vb, DEBUG, " des0: %08x\n", le32_to_cpu(d->des0)); ++ VB_PRINTK(vb, DEBUG, " des1: %08x\n", le32_to_cpu(d->des1)); ++ VB_PRINTK(vb, DEBUG, " buffer1: %08x\n", le32_to_cpu(d->buffer1)); ++ VB_PRINTK(vb, DEBUG, " container: %08x\n", le32_to_cpu(d->container)); ++} ++ ++static void ++show_buffer(struct voicebus *vb, struct vbb *vbb) ++{ ++ int x; ++ unsigned char *c; ++ c = vbb; ++ printk(KERN_DEBUG "Packet %d\n", count); ++ printk(KERN_DEBUG ""); ++ for (x = 1; x <= VOICEBUS_SFRAME_SIZE; ++x) { ++ printk("%02x ", c[x]); ++ if (x % 16 == 0) ++ printk("\n"); ++ } ++ printk(KERN_DEBUG "\n\n"); ++} ++#endif ++ ++/*! ++ * \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 void * ++vb_get_completed_txb(struct voicebus *vb) ++{ ++ struct voicebus_descriptor_list *dl = &vb->txd; ++ struct voicebus_descriptor *d; ++ struct vbb *vbb; ++ unsigned int head = dl->head; ++ ++ d = vb_descriptor(dl, head); ++ ++ if (OWNED(d) || !d->buffer1 || ++ (le32_to_cpu(d->buffer1) == vb->idle_vbb_dma_addr)) ++ return NULL; ++ ++ vbb = dl->pending[head]; ++ if (NORMAL == vb->mode) { ++ d->buffer1 = cpu_to_le32(vb->idle_vbb_dma_addr); ++ dl->pending[head] = vb->idle_vbb; ++ SET_OWNED(d); ++ } else { ++ d->buffer1 = 0; ++ dl->pending[head] = NULL; ++ } ++ dl->head = (++head) & DRING_MASK; ++ --dl->count; ++ vb_net_capture_vbb(vb, vbb, 1, d->des0, d->container); ++ return vbb; ++} ++ ++static void * ++vb_get_completed_rxb(struct voicebus *vb, u32 *des0) ++{ ++ struct voicebus_descriptor *d; ++ struct voicebus_descriptor_list *dl = &vb->rxd; ++ unsigned int head = dl->head; ++ struct vbb *vbb; ++ ++ d = vb_descriptor(dl, head); ++ ++ if ((0 == d->buffer1) || OWNED(d)) ++ return NULL; ++ ++ vbb = dl->pending[head]; ++ dl->head = (++head) & DRING_MASK; ++ d->buffer1 = 0; ++ --dl->count; ++# ifdef VOICEBUS_NET_DEBUG ++ vb_net_capture_vbb(vb, vbb, 0, d->des0, d->container); ++# endif ++ *des0 = le32_to_cpu(d->des0); ++ return vbb; ++} ++ ++/*! ++ * \brief Command the hardware to check if it owns the next receive ++ * descriptor. ++ */ ++static inline void ++__vb_rx_demand_poll(struct voicebus *vb) ++{ ++ if (((__vb_getctl(vb, 0x0028) >> 17) & 0x7) == 0x4) ++ __vb_setctl(vb, 0x0010, 0x00000000); ++} ++ ++#ifndef CONFIG_VOICEBUS_TIMER ++static void ++__vb_enable_interrupts(struct voicebus *vb) ++{ ++ if (BOOT == vb->mode) ++ __vb_setctl(vb, IER_CSR7, DEFAULT_NO_IDLE_INTERRUPTS); ++ else ++ __vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS); ++} ++#endif ++ ++static void ++__vb_disable_interrupts(struct voicebus *vb) ++{ ++ __vb_setctl(vb, IER_CSR7, 0); ++} ++ ++static void ++vb_disable_interrupts(struct voicebus *vb) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&vb->lock, flags); ++ __vb_disable_interrupts(vb); ++ spin_unlock_irqrestore(&vb->lock, flags); ++} ++ ++static void start_packet_processing(struct voicebus *vb) ++{ ++ u32 reg; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vb->lock, flags); ++ clear_bit(VOICEBUS_STOP, &vb->flags); ++ clear_bit(VOICEBUS_STOPPED, &vb->flags); ++#if defined(CONFIG_VOICEBUS_TIMER) ++ mod_timer(&vb->timer, jiffies + HZ/1000); ++#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); ++ __vb_getctl(vb, 0x0030); ++ __vb_rx_demand_poll(vb); ++ __vb_tx_demand_poll(vb); ++ __vb_getctl(vb, 0x0030); ++ spin_unlock_irqrestore(&vb->lock, flags); ++} ++ ++static void vb_tasklet_boot(unsigned long data); ++static void vb_tasklet_hx8(unsigned long data); ++static void vb_tasklet_normal(unsigned long data); ++ ++/*! ++ * \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) ++{ ++ int ret; ++ ++ if (!vb_is_stopped(vb)) ++ return -EBUSY; ++ ++ if (NORMAL == vb->mode) { ++ tasklet_init(&vb->tasklet, vb_tasklet_normal, ++ (unsigned long)vb); ++ } else if (BOOT == vb->mode) { ++ tasklet_init(&vb->tasklet, vb_tasklet_boot, ++ (unsigned long)vb); ++ } else if (HX8 == vb->mode) { ++ tasklet_init(&vb->tasklet, vb_tasklet_hx8, ++ (unsigned long)vb); ++ } else { ++ return -EINVAL; ++ } ++ ++ ret = vb_reset_interface(vb); ++ if (ret) ++ return ret; ++ ret = vb_initialize_interface(vb); ++ if (ret) ++ return ret; ++ ++ start_packet_processing(vb); ++ ++ BUG_ON(vb_is_stopped(vb)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(voicebus_start); ++ ++static void vb_stop_txrx_processors(struct voicebus *vb) ++{ ++ unsigned long flags; ++ u32 reg; ++ int i; ++ ++ spin_lock_irqsave(&vb->lock, flags); ++ reg = __vb_getctl(vb, NAR_CSR6); ++ reg &= ~(0x2002); ++ __vb_setctl(vb, NAR_CSR6, reg); ++ spin_unlock_irqrestore(&vb->lock, flags); ++ ++ barrier(); ++ i = 150; ++ while (--i && (__vb_getctl(vb, SR_CSR5) & (0x007e0000))) ++ udelay(100); ++} ++ ++/*! ++ * \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. ++ */ ++void voicebus_stop(struct voicebus *vb) ++{ ++ static DEFINE_SEMAPHORE(stop); ++ ++ down(&stop); ++ ++ if (test_bit(VOICEBUS_STOP, &vb->flags) || vb_is_stopped(vb)) { ++ up(&stop); ++ return; ++ } ++ ++ set_bit(VOICEBUS_STOP, &vb->flags); ++ vb_stop_txrx_processors(vb); ++ ++ WARN_ON(!vb_is_stopped(vb)); ++ set_bit(VOICEBUS_STOPPED, &vb->flags); ++ ++#if defined(CONFIG_VOICEBUS_TIMER) ++ del_timer_sync(&vb->timer); ++#endif ++ vb_disable_interrupts(vb); ++ up(&stop); ++} ++EXPORT_SYMBOL(voicebus_stop); ++ ++/** ++ * voicebus_quiesce - Halt the voicebus interface. ++ * @vb: The voicebus structure to quiet ++ * ++ * This ensures that the device is not engaged in any DMA transactions or ++ * interrupting. It does not grab any locks since it may be called by a dying ++ * kernel. ++ */ ++void voicebus_quiesce(struct voicebus *vb) ++{ ++ if (!vb) ++ return; ++ ++ /* Reset the device */ ++ __vb_disable_interrupts(vb); ++ __vb_setctl(vb, 0x0000, 0x1); ++ __vb_getctl(vb, 0x0000); ++} ++EXPORT_SYMBOL(voicebus_quiesce); ++ ++/*! ++ * \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) ++{ ++ set_bit(VOICEBUS_SHUTDOWN, &vb->flags); ++ ++#ifdef VOICEBUS_NET_DEBUG ++ vb_net_unregister(vb); ++#endif ++ ++ /* Make sure the underrun_work isn't running or going to run. */ ++ cancel_work_sync(&vb->underrun_work); ++ ++ /* quiesce the hardware */ ++ voicebus_stop(vb); ++ ++ vb_reset_interface(vb); ++ ++ tasklet_kill(&vb->tasklet); ++ ++#if !defined(CONFIG_VOICEBUS_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); ++ if (vb->idle_vbb_dma_addr) { ++ dma_free_coherent(&vb->pdev->dev, VOICEBUS_SFRAME_SIZE, ++ vb->idle_vbb, vb->idle_vbb_dma_addr); ++ } ++ ++ release_mem_region(pci_resource_start(vb->pdev, 1), ++ pci_resource_len(vb->pdev, 1)); ++ ++ pci_iounmap(vb->pdev, vb->iobase); ++ pci_clear_mwi(vb->pdev); ++ pci_disable_device(vb->pdev); ++ dma_pool_destroy(vb->pool); ++} ++EXPORT_SYMBOL(voicebus_release); ++ ++static void ++vb_increase_latency(struct voicebus *vb, unsigned int increase, ++ struct list_head *buffers) ++{ ++ struct vbb *vbb; ++ int i; ++ LIST_HEAD(local); ++ ++ if (0 == increase) ++ return; ++ ++ if (test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags)) ++ return; ++ ++ if (unlikely(increase > VOICEBUS_MAXLATENCY_BUMP)) ++ increase = VOICEBUS_MAXLATENCY_BUMP; ++ ++ if ((increase + vb->min_tx_buffer_count) > vb->max_latency) ++ increase = vb->max_latency - vb->min_tx_buffer_count; ++ ++ /* 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. */ ++ ++ /* 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. */ ++ for (i = 0; i < increase; ++i) { ++ dma_addr_t dma_addr; ++ vbb = dma_pool_alloc(vb->pool, GFP_ATOMIC, &dma_addr); ++ WARN_ON(NULL == vbb); ++ if (likely(NULL != vbb)) { ++ vbb->dma_addr = dma_addr; ++ list_add_tail(&vbb->entry, &local); ++ } ++ } ++ ++ handle_transmit(vb, &local); ++ list_splice_tail(&local, buffers); ++ ++ /* Set the new latency (but we want to ensure that there aren't any ++ * printks to the console, so we don't call the function) */ ++ vb->min_tx_buffer_count += increase; ++} ++ ++static void vb_schedule_deferred(struct voicebus *vb) ++{ ++#if !defined(CONFIG_VOICEBUS_INTERRUPT) ++ tasklet_hi_schedule(&vb->tasklet); ++#else ++ vb->tasklet.func(vb->tasklet.data); ++#endif ++} ++ ++/** ++ * vb_tasklet_boot() - When vb->mode == BOOT ++ * ++ * This deferred processing routine is for hx8 boards during initialization. It ++ * simply services any completed tx / rx packets without any concerns about what ++ * the current latency is. ++ */ ++static void vb_tasklet_boot(unsigned long data) ++{ ++ struct voicebus *vb = (struct voicebus *)data; ++ LIST_HEAD(buffers); ++ struct vbb *vbb; ++ const int DEFAULT_COUNT = 5; ++ int count = DEFAULT_COUNT; ++ u32 des0 = 0; ++ ++ /* First, temporarily store any non-idle buffers that the hardware has ++ * indicated it's finished transmitting. Non idle buffers are those ++ * buffers that contain actual data and was filled out by the client ++ * driver (as of this writing, the wcte12xp or wctdm24xxp drivers) when ++ * passed up through the handle_transmit callback. ++ * ++ * On the other hand, idle buffers are "dummy" buffers that solely exist ++ * to in order to prevent the transmit descriptor ring from ever ++ * completely draining. */ ++ while ((vbb = vb_get_completed_txb(vb))) ++ list_add_tail(&vbb->entry, &vb->tx_complete); ++ ++ while (--count && !list_empty(&vb->tx_complete)) ++ list_move_tail(vb->tx_complete.next, &buffers); ++ ++ /* Prep all the new buffers for transmit before actually sending any ++ * of them. */ ++ handle_transmit(vb, &buffers); ++ ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ __voicebus_transmit(vb, vbb); ++ } ++ __vb_setctl(vb, 0x0008, 0x00000000); ++ ++ /* If there may still be buffers in the descriptor rings, reschedule ++ * ourself to run again. We essentially yield here to allow any other ++ * cards a chance to run. */ ++#if !defined(CONFIG_VOICEBUS_INTERRUPT) ++ if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags))) ++ vb_schedule_deferred(vb); ++#endif ++ ++ /* And finally, pass up any receive buffers. */ ++ count = DEFAULT_COUNT; ++ while (--count && (vbb = vb_get_completed_rxb(vb, &des0))) { ++ if (likely((des0 & (0x7fff << 16)) == ++ (VOICEBUS_SFRAME_SIZE << 16))) ++ list_add_tail(&vbb->entry, &buffers); ++ else ++ vb_submit_rxb(vb, vbb); ++ } ++ ++ handle_receive(vb, &buffers); ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ vb_submit_rxb(vb, vbb); ++ } ++ return; ++} ++ ++/** ++ * vb_tasklet_hx8() - When vb->mode == HX8 ++ * ++ * The normal deferred processing routine for the Hx8 boards. This deferred ++ * processing routine doesn't configure any idle buffers and increases the ++ * latency when there is a hard underrun. There are not any softunderruns here, ++ * unlike in vb_tasklet_normal. ++ */ ++static void vb_tasklet_hx8(unsigned long data) ++{ ++ struct voicebus *vb = (struct voicebus *)data; ++ int hardunderrun; ++ LIST_HEAD(buffers); ++ struct vbb *vbb; ++ const int DEFAULT_COUNT = 5; ++ int count = DEFAULT_COUNT; ++ u32 des0 = 0; ++ ++ hardunderrun = test_and_clear_bit(VOICEBUS_HARD_UNDERRUN, &vb->flags); ++ /* First, temporarily store any non-idle buffers that the hardware has ++ * indicated it's finished transmitting. Non idle buffers are those ++ * buffers that contain actual data and was filled out by the client ++ * driver (as of this writing, the wcte12xp or wctdm24xxp drivers) when ++ * passed up through the handle_transmit callback. ++ * ++ * On the other hand, idle buffers are "dummy" buffers that solely exist ++ * to in order to prevent the transmit descriptor ring from ever ++ * completely draining. */ ++ while ((vbb = vb_get_completed_txb(vb))) ++ list_add_tail(&vbb->entry, &vb->tx_complete); ++ ++ while (--count && !list_empty(&vb->tx_complete)) ++ list_move_tail(vb->tx_complete.next, &buffers); ++ ++ /* Prep all the new buffers for transmit before actually sending any ++ * of them. */ ++ handle_transmit(vb, &buffers); ++ ++ if (unlikely(hardunderrun)) ++ vb_increase_latency(vb, 1, &buffers); ++ ++ /* Now we can send all our buffers together in a group. */ ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ __voicebus_transmit(vb, vbb); ++ } ++ __vb_setctl(vb, 0x0008, 0x00000000); ++ ++ /* Print any messages about soft latency bumps after we fix the transmit ++ * descriptor ring. Otherwise it's possible to take so much time ++ * printing the dmesg output that we lose the lead that we got on the ++ * hardware, resulting in a hard underrun condition. */ ++ if (unlikely(hardunderrun)) { ++#if !defined(CONFIG_VOICEBUS_SYSFS) ++ if (!test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags) && ++ printk_ratelimit()) { ++ if (vb->max_latency != vb->min_tx_buffer_count) { ++ dev_info(&vb->pdev->dev, "Missed interrupt. " ++ "Increasing latency to %d ms in " ++ "order to compensate.\n", ++ vb->min_tx_buffer_count); ++ } else { ++ dev_info(&vb->pdev->dev, "ERROR: Unable to " ++ "service card within %d ms and " ++ "unable to further increase " ++ "latency.\n", vb->max_latency); ++ } ++ } ++#endif ++ } ++ ++#if !defined(CONFIG_VOICEBUS_INTERRUPT) ++ /* If there may still be buffers in the descriptor rings, reschedule ++ * ourself to run again. We essentially yield here to allow any other ++ * cards a chance to run. */ ++ if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags))) ++ vb_schedule_deferred(vb); ++#endif ++ ++ /* And finally, pass up any receive buffers. */ ++ count = DEFAULT_COUNT; ++ while (--count && (vbb = vb_get_completed_rxb(vb, &des0))) { ++ if (((des0 >> 16) & 0x7fff) == VOICEBUS_SFRAME_SIZE) ++ list_add_tail(&vbb->entry, &buffers); ++ else ++ vb_submit_rxb(vb, vbb); ++ } ++ ++ handle_receive(vb, &buffers); ++ ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ vb_submit_rxb(vb, vbb); ++ } ++ ++ return; ++} ++ ++/** ++ * vb_tasklet_relaxed() - When vb->mode == NORMAL ++ * ++ * This is the standard deferred processing routine for CPLD based cards ++ * (essentially the non-hx8 cards). ++ */ ++static void vb_tasklet_normal(unsigned long data) ++{ ++ struct voicebus *vb = (struct voicebus *)data; ++ int softunderrun; ++ LIST_HEAD(buffers); ++ struct vbb *vbb; ++ struct voicebus_descriptor_list *const dl = &vb->txd; ++ struct voicebus_descriptor *d; ++ int behind = 0; ++ const int DEFAULT_COUNT = 5; ++ int count = DEFAULT_COUNT; ++ u32 des0 = 0; ++ ++ BUG_ON(NORMAL != vb->mode); ++ /* First, temporarily store any non-idle buffers that the hardware has ++ * indicated it's finished transmitting. Non idle buffers are those ++ * buffers that contain actual data and was filled out by the client ++ * driver (as of this writing, the wcte12xp or wctdm24xxp drivers) when ++ * passed up through the handle_transmit callback. ++ * ++ * On the other hand, idle buffers are "dummy" buffers that solely exist ++ * to in order to prevent the transmit descriptor ring from ever ++ * completely draining. */ ++ while ((vbb = vb_get_completed_txb(vb))) ++ list_add_tail(&vbb->entry, &vb->tx_complete); ++ ++ if (unlikely(dl->count < 2)) { ++ softunderrun = 1; ++ d = vb_descriptor(dl, dl->head); ++ if (1 == dl->count) ++ return; ++ ++ behind = 2; ++ while (!OWNED(d)) { ++ if (le32_to_cpu(d->buffer1) != vb->idle_vbb_dma_addr) ++ goto tx_error_exit; ++ SET_OWNED(d); ++ dl->head = (dl->head + 1) & DRING_MASK; ++ d = vb_descriptor(dl, dl->head); ++ ++behind; ++ } ++ ++ } else { ++ softunderrun = 0; ++ } ++ ++ while (--count && !list_empty(&vb->tx_complete)) ++ list_move_tail(vb->tx_complete.next, &buffers); ++ ++ /* Prep all the new buffers for transmit before actually sending any ++ * of them. */ ++ handle_transmit(vb, &buffers); ++ ++ if (unlikely(softunderrun)) { ++ int i; ++ unsigned long flags; ++ ++ /* Disable interrupts on the local processor. We don't want ++ * the following process interrupted. We're 'racing' against ++ * the hardware here.... */ ++ local_irq_save(flags); ++ vb_increase_latency(vb, behind, &buffers); ++ d = vb_descriptor(dl, dl->head); ++ while (!OWNED(d)) { ++ if (le32_to_cpu(d->buffer1) != vb->idle_vbb_dma_addr) { ++ local_irq_restore(flags); ++ goto tx_error_exit; ++ } ++ SET_OWNED(d); ++ dl->head = (dl->head + 1) & DRING_MASK; ++ d = vb_descriptor(dl, dl->head); ++ ++behind; ++ } ++ /* Now we'll get a little further ahead of the hardware. */ ++ for (i = 0; i < 5; ++i) { ++ d = vb_descriptor(dl, dl->head); ++ d->buffer1 = cpu_to_le32(vb->idle_vbb_dma_addr); ++ dl->pending[dl->head] = vb->idle_vbb; ++ d->des0 |= OWN_BIT; ++ dl->head = (dl->head + 1) & DRING_MASK; ++ } ++ dl->tail = dl->head; ++ local_irq_restore(flags); ++ } ++ ++ d = vb_descriptor(dl, dl->tail); ++ if (le32_to_cpu(d->buffer1) != vb->idle_vbb_dma_addr) ++ goto tx_error_exit; ++ ++ /* Now we can send all our buffers together in a group. */ ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ __voicebus_transmit(vb, vbb); ++ } ++ ++ writel(0, vb->iobase + 0x8); ++ ++ /* Print any messages about soft latency bumps after we fix the transmit ++ * descriptor ring. Otherwise it's possible to take so much time ++ * printing the dmesg output that we lose the lead that we got on the ++ * hardware, resulting in a hard underrun condition. */ ++ if (unlikely(softunderrun)) { ++#if !defined(CONFIG_VOICEBUS_SYSFS) ++ if (!test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags) && ++ printk_ratelimit()) { ++ if (vb->max_latency != vb->min_tx_buffer_count) { ++ dev_info(&vb->pdev->dev, "Missed interrupt. " ++ "Increasing latency to %d ms in " ++ "order to compensate.\n", ++ vb->min_tx_buffer_count); ++ } else { ++ dev_info(&vb->pdev->dev, "ERROR: Unable to " ++ "service card within %d ms and " ++ "unable to further increase " ++ "latency.\n", vb->max_latency); ++ } ++ } ++#endif ++ } ++ ++#if !defined(CONFIG_VOICEBUS_INTERRUPT) ++ /* If there may still be buffers in the descriptor rings, reschedule ++ * ourself to run again. We essentially yield here to allow any other ++ * cards a chance to run. */ ++ if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags))) ++ vb_schedule_deferred(vb); ++#endif ++ ++ /* And finally, pass up any receive buffers. */ ++ count = DEFAULT_COUNT; ++ while (--count && (vbb = vb_get_completed_rxb(vb, &des0))) { ++ if (((des0 >> 16) & 0x7fff) == VOICEBUS_SFRAME_SIZE) ++ list_add_tail(&vbb->entry, &buffers); ++ else ++ vb_submit_rxb(vb, vbb); ++ } ++ ++ handle_receive(vb, &buffers); ++ ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ vb_submit_rxb(vb, vbb); ++ } ++ ++ return; ++tx_error_exit: ++ vb_disable_interrupts(vb); ++ schedule_work(&vb->underrun_work); ++ while (!list_empty(&buffers)) { ++ vbb = list_entry(buffers.next, struct vbb, entry); ++ list_del(&vbb->entry); ++ dma_pool_free(vb->pool, vbb, vbb->dma_addr); ++ } ++ return; ++} ++ ++/** ++ * handle_hardunderrun() - reset the AN983 after experiencing a hardunderrun. ++ * @work: The work_struct used to queue this function. ++ * ++ */ ++static void handle_hardunderrun(struct work_struct *work) ++{ ++ struct voicebus *vb = container_of(work, struct voicebus, ++ underrun_work); ++ if (test_bit(VOICEBUS_STOP, &vb->flags) || ++ test_bit(VOICEBUS_STOPPED, &vb->flags)) ++ return; ++ ++ voicebus_stop(vb); ++ ++ if (!test_bit(VOICEBUS_SHUTDOWN, &vb->flags)) { ++ ++ if (printk_ratelimit()) { ++ dev_info(&vb->pdev->dev, "Host failed to service " ++ "card interrupt within %d ms which is a " ++ "hardunderun.\n", DRING_SIZE); ++ } ++ ++ if (vb->ops->handle_error) ++ vb->ops->handle_error(vb); ++ ++ vb_disable_deferred(vb); ++ setup_descriptors(vb); ++ start_packet_processing(vb); ++ vb_enable_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 ++vb_isr(int irq, void *dev_id) ++{ ++ struct voicebus *vb = dev_id; ++ unsigned long flags; ++ 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; ++ ++ local_irq_save(flags); ++ ++ if (unlikely((int_status & ++ (TX_UNAVAILABLE_INTERRUPT|RX_UNAVAILABLE_INTERRUPT)) && ++ !test_bit(VOICEBUS_STOP, &vb->flags) && ++ (BOOT != vb->mode))) { ++ if (NORMAL == vb->mode) { ++ __vb_disable_interrupts(vb); ++ __vb_setctl(vb, SR_CSR5, int_status); ++ schedule_work(&vb->underrun_work); ++ } else if (HX8 == vb->mode) { ++ set_bit(VOICEBUS_HARD_UNDERRUN, &vb->flags); ++ vb_schedule_deferred(vb); ++ __vb_setctl(vb, SR_CSR5, int_status); ++ } ++ } else if (likely(int_status & ++ (TX_COMPLETE_INTERRUPT|RX_COMPLETE_INTERRUPT))) { ++ /* ******************************************************** */ ++ /* NORMAL INTERRUPT CASE */ ++ /* ******************************************************** */ ++ vb_schedule_deferred(vb); ++ __vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT|RX_COMPLETE_INTERRUPT); ++ } else { ++ if (int_status & FATAL_BUS_ERROR_INTERRUPT) ++ dev_err(&vb->pdev->dev, "Fatal Bus Error detected!\n"); ++ ++ if (int_status & TX_STOPPED_INTERRUPT) { ++ BUG_ON(!test_bit(VOICEBUS_STOP, &vb->flags)); ++ if (__vb_is_stopped(vb)) { ++ __vb_disable_interrupts(vb); ++ } ++ } ++ if (int_status & RX_STOPPED_INTERRUPT) { ++ BUG_ON(!test_bit(VOICEBUS_STOP, &vb->flags)); ++ if (__vb_is_stopped(vb)) { ++ __vb_disable_interrupts(vb); ++ } ++ } ++ ++ /* Clear the interrupt(s) */ ++ __vb_setctl(vb, SR_CSR5, int_status); ++ } ++ local_irq_restore(flags); ++ ++ return IRQ_HANDLED; ++} ++ ++#if defined(CONFIG_VOICEBUS_TIMER) ++/*! \brief Called if the deferred processing is to happen in the context of ++ * the timer. ++ */ ++static void ++vb_timer(TIMER_DATA_TYPE timer) ++{ ++ unsigned long start = jiffies; ++ struct voicebus *vb = from_timer(vb, timer, timer); ++ vb_isr(0, vb); ++ if (!test_bit(VOICEBUS_STOPPED, &vb->flags)) { ++ mod_timer(&vb->timer, start + HZ/1000); ++ } ++} ++#endif ++ ++/*! ++ * \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 voicebus *vb, const char *board_name, ++ enum voicebus_mode mode) ++{ ++ int retval = 0; ++ int reserved_iomem = 0; ++ ++ BUG_ON(NULL == vb); ++ BUG_ON(NULL == board_name); ++ BUG_ON(NULL == vb->ops); ++ BUG_ON(NULL == vb->pdev); ++ BUG_ON(NULL == vb->debug); ++ ++ /* ---------------------------------------------------------------- ++ Initialize the pure software constructs. ++ ---------------------------------------------------------------- */ ++ vb->max_latency = VOICEBUS_DEFAULT_MAXLATENCY; ++ ++ spin_lock_init(&vb->lock); ++ set_bit(VOICEBUS_STOP, &vb->flags); ++ ++ if ((NORMAL != mode) && (BOOT != mode) && (HX8 != mode)) ++ return -EINVAL; ++ ++ vb->mode = mode; ++ ++ vb->min_tx_buffer_count = VOICEBUS_DEFAULT_LATENCY; ++ ++ INIT_LIST_HEAD(&vb->tx_complete); ++ INIT_LIST_HEAD(&vb->free_rx); ++ ++#if defined(CONFIG_VOICEBUS_TIMER) ++ timer_setup(&vb->timer, vb_timer, 0); ++#endif ++ ++ INIT_WORK(&vb->underrun_work, handle_hardunderrun); ++ ++ /* ---------------------------------------------------------------- ++ Configure the hardware / kernel module interfaces. ++ ---------------------------------------------------------------- */ ++ if (pci_set_dma_mask(vb->pdev, DMA_BIT_MASK(32))) { ++ dev_err(&vb->pdev->dev, "No suitable DMA available.\n"); ++ goto cleanup; ++ } ++ ++ if (pci_enable_device(vb->pdev)) { ++ dev_err(&vb->pdev->dev, "Failed call to pci_enable_device.\n"); ++ retval = -EIO; ++ goto cleanup; ++ } ++ ++ if (0 == (pci_resource_flags(vb->pdev, 0)&IORESOURCE_IO)) { ++ dev_err(&vb->pdev->dev, "BAR0 is not IO Memory.\n"); ++ retval = -EIO; ++ goto cleanup; ++ } ++ vb->iobase = pci_iomap(vb->pdev, 1, 0); ++ if (request_mem_region(pci_resource_start(vb->pdev, 1), ++ pci_resource_len(vb->pdev, 1), ++ board_name)) { ++ reserved_iomem = 1; ++ } else { ++ dev_err(&vb->pdev->dev, "IO Registers are in use by another " ++ "module.\n"); ++ if (!(*vb->debug)) { ++ retval = -EIO; ++ goto cleanup; ++ } ++ } ++ ++ vb->pool = dma_pool_create(board_name, &vb->pdev->dev, ++ sizeof(struct vbb), 64, 0); ++ if (!vb->pool) { ++ retval = -ENOMEM; ++ goto cleanup; ++ } ++ ++ vb->idle_vbb = dma_alloc_coherent(&vb->pdev->dev, VOICEBUS_SFRAME_SIZE, ++ &vb->idle_vbb_dma_addr, GFP_KERNEL); ++ ++ /* ---------------------------------------------------------------- ++ Configure the hardware interface. ++ ---------------------------------------------------------------- */ ++ if (pci_set_dma_mask(vb->pdev, DMA_BIT_MASK(32))) { ++ dev_warn(&vb->pdev->dev, "No suitable DMA available.\n"); ++ goto cleanup; ++ } ++ ++ retval = pci_set_mwi(vb->pdev); ++ if (retval) { ++ dev_warn(&vb->pdev->dev, "Failed to set Memory-Write " \ ++ "Invalidate Command Bit..\n"); ++ } ++ ++ pci_set_master(vb->pdev); ++ ++ if (vb_reset_interface(vb)) { ++ retval = -EIO; ++ dev_warn(&vb->pdev->dev, "Failed reset.\n"); ++ goto cleanup; ++ } ++ ++ retval = vb_initialize_tx_descriptors(vb); ++ if (retval) ++ goto cleanup; ++ ++ retval = vb_initialize_rx_descriptors(vb); ++ if (retval) ++ goto cleanup; ++ ++#if !defined(CONFIG_VOICEBUS_TIMER) ++ retval = request_irq(vb->pdev->irq, vb_isr, IRQF_SHARED, ++ board_name, vb); ++ if (retval) { ++ dev_warn(&vb->pdev->dev, "Failed to request interrupt line.\n"); ++ goto cleanup; ++ } ++#endif ++ ++#ifdef VOICEBUS_NET_DEBUG ++ vb_net_register(vb, board_name); ++#endif ++ return retval; ++cleanup: ++ ++ tasklet_kill(&vb->tasklet); ++ ++ if (vb->pool) ++ dma_pool_destroy(vb->pool); ++ /* 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); ++ ++ dma_free_coherent(&vb->pdev->dev, VOICEBUS_SFRAME_SIZE, ++ vb->idle_vbb, vb->idle_vbb_dma_addr); ++ ++ if (vb->iobase) ++ pci_iounmap(vb->pdev, vb->iobase); ++ ++ if (vb->pdev) ++ pci_disable_device(vb->pdev); ++ ++ if (reserved_iomem) { ++ release_mem_region(pci_resource_start(vb->pdev, 1), ++ pci_resource_len(vb->pdev, 1)); ++ } ++ ++ if (0 == retval) ++ retval = -EIO; ++ return retval; ++} ++EXPORT_SYMBOL(__voicebus_init); ++ ++static spinlock_t loader_list_lock; ++static 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; ++ unsigned long stop; ++ 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) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ++ ret = request_module("dahdi_vpmadt032_loader"); ++#else ++ /* If we use the blocking 'request_module' here and we are ++ * loading the client boards with async_schedule we will hang ++ * here. The module loader will wait for our asynchronous tasks ++ * to finish, but we can't because we're waiting for the load ++ * the finish. */ ++ ret = request_module_nowait("dahdi_vpmadt032_loader"); ++#endif ++ if (ret) ++ return ret; ++ stop = jiffies + HZ; ++ while (time_after(stop, jiffies)) { ++ spin_lock(&loader_list_lock); ++ loader_present = !(list_empty(&binary_loader_list)); ++ spin_unlock(&loader_list_lock); ++ if (loader_present) ++ break; ++ msleep(10); ++ } ++ } ++ ++ 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); ++ dev_info(&vb->pdev->dev, "Failed to find a " ++ "registered loader after loading module.\n"); ++ ret = -ENODEV; ++ } ++ } else { ++ spin_unlock(&loader_list_lock); ++ dev_info(&vb->pdev->dev, "Failed to find a registered " ++ "loader after loading module.\n"); ++ ret = -ENODEV; ++ } ++ 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); ++ ++static int __init voicebus_module_init(void) ++{ ++ /* 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_device(NULL, NULL); ++ spin_lock_init(&loader_list_lock); ++ return 0; ++} ++ ++static 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 -Nru linux-source-4.19/drivers/dahdi/voicebus/voicebus.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus.h +--- linux-source-4.19/drivers/dahdi/voicebus/voicebus.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,253 @@ ++/* ++ * VoiceBus(tm) Interface Library. ++ * ++ * Written by Shaun Ruffell ++ * and based on previous work by Mark Spencer , ++ * Matthew Fredrickson , and ++ * Michael Spiceland ++ * ++ * Copyright (C) 2007-2010 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__ ++ ++#include ++ ++ ++#define VOICEBUS_DEFAULT_LATENCY 3U ++#define VOICEBUS_DEFAULT_MAXLATENCY 25U ++#define VOICEBUS_MAXLATENCY_BUMP 6U ++ ++#define VOICEBUS_SFRAME_SIZE 1004U ++ ++/*! The number of descriptors in both the tx and rx descriptor ring. */ ++#define DRING_SIZE (1 << 7) /* Must be a power of 2 */ ++#define DRING_MASK (DRING_SIZE-1) ++ ++/* Define CONFIG_VOICEBUS_SYSFS to create some attributes under the pci device. ++ * This is disabled by default because it hasn't been tested on the full range ++ * of supported kernels. */ ++#undef CONFIG_VOICEBUS_SYSFS ++ ++/* Do not generate interrupts on this interface, but instead just poll it */ ++#undef CONFIG_VOICEBUS_TIMER ++ ++/* Define this in order to create a debugging network interface. */ ++#undef VOICEBUS_NET_DEBUG ++ ++/* Define this to only run the processing in an interrupt handler ++ * (and not tasklet). */ ++#define CONFIG_VOICEBUS_INTERRUPT ++ ++/* ++ * Enable the following definition in order to disable Active-State Power ++ * Management on the PCIe bridge for PCIe cards. This has been known to work ++ * around issues where the BIOS enables it on the cards even though the ++ * platform does not support it. ++ * ++ */ ++#undef CONFIG_VOICEBUS_DISABLE_ASPM ++ ++/* Define this to use a FIFO for the software echocan reference. ++ * (experimental) */ ++#undef CONFIG_VOICEBUS_ECREFERENCE ++ ++#ifdef CONFIG_VOICEBUS_ECREFERENCE ++ ++struct dahdi_fifo; ++unsigned int __dahdi_fifo_put(struct dahdi_fifo *fifo, u8 *data, size_t size); ++unsigned int __dahdi_fifo_get(struct dahdi_fifo *fifo, u8 *data, size_t size); ++void dahdi_fifo_free(struct dahdi_fifo *fifo); ++struct dahdi_fifo *dahdi_fifo_alloc(size_t maxsize, gfp_t alloc_flags); ++ ++#endif ++ ++#ifdef VOICEBUS_NET_DEBUG ++#include ++#include ++#include ++#endif ++ ++struct voicebus; ++ ++struct vbb { ++ u8 data[VOICEBUS_SFRAME_SIZE]; ++ struct list_head entry; ++ dma_addr_t dma_addr; ++}; ++ ++struct voicebus_operations { ++ void (*handle_receive)(struct voicebus *vb, struct list_head *buffers); ++ void (*handle_transmit)(struct voicebus *vb, struct list_head *buffers); ++ void (*handle_error)(struct voicebus *vb); ++}; ++ ++/** ++ * struct voicebus_descriptor_list - A single descriptor list. ++ */ ++struct voicebus_descriptor_list { ++ struct voicebus_descriptor *desc; ++ unsigned int head; ++ unsigned int tail; ++ void *pending[DRING_SIZE]; ++ dma_addr_t desc_dma; ++ unsigned long count; ++ unsigned int padding; ++}; ++ ++/* Bit definitions for struct voicebus.flags */ ++#define VOICEBUS_SHUTDOWN 0 ++#define VOICEBUS_STOP 1 ++#define VOICEBUS_STOPPED 2 ++#define VOICEBUS_LATENCY_LOCKED 3 ++#define VOICEBUS_HARD_UNDERRUN 4 ++ ++/** ++ * voicebus_mode ++ * ++ * NORMAL: For non-hx8 boards. Uses idle_buffers. ++ * BOOT: For hx8 boards. For sending single packets at a time. ++ * HX8: Normal operating mode for Hx8 Boards. Does not use ++ * idle_buffers. ++ */ ++enum voicebus_mode { ++ NORMAL = 0, ++ BOOT = 1, ++ HX8 = 2, ++}; ++ ++/** ++ * struct voicebus - Represents physical interface to voicebus card. ++ * ++ * @tx_complete: only used in the tasklet to temporarily hold complete tx ++ * buffers. ++ */ ++struct voicebus { ++ struct pci_dev *pdev; ++ spinlock_t lock; ++ struct voicebus_descriptor_list rxd; ++ struct voicebus_descriptor_list txd; ++ u8 *idle_vbb; ++ dma_addr_t idle_vbb_dma_addr; ++ const int *debug; ++ void __iomem *iobase; ++ struct tasklet_struct tasklet; ++ enum voicebus_mode mode; ++ ++#if defined(CONFIG_VOICEBUS_INTERRUPT) ++ atomic_t deferred_disabled_count; ++#endif ++ ++#if defined(CONFIG_VOICEBUS_TIMER) ++ struct timer_list timer; ++#endif ++ ++ struct work_struct underrun_work; ++ const struct voicebus_operations *ops; ++ unsigned long flags; ++ unsigned int min_tx_buffer_count; ++ unsigned int max_latency; ++ struct list_head tx_complete; ++ struct list_head free_rx; ++ struct dma_pool *pool; ++ ++#ifdef VOICEBUS_NET_DEBUG ++ struct sk_buff_head captured_packets; ++ struct net_device *netdev; ++ struct net_device_stats net_stats; ++ struct napi_struct napi; ++ atomic_t tx_seqnum; ++ atomic_t rx_seqnum; ++#endif ++}; ++ ++int __voicebus_init(struct voicebus *vb, const char *board_name, ++ enum voicebus_mode mode); ++void voicebus_release(struct voicebus *vb); ++int voicebus_start(struct voicebus *vb); ++void voicebus_stop(struct voicebus *vb); ++void voicebus_quiesce(struct voicebus *vb); ++int voicebus_transmit(struct voicebus *vb, struct vbb *vbb); ++int voicebus_set_minlatency(struct voicebus *vb, unsigned int milliseconds); ++int voicebus_current_latency(struct voicebus *vb); ++ ++static inline int voicebus_init(struct voicebus *vb, const char *board_name) ++{ ++ return __voicebus_init(vb, board_name, NORMAL); ++} ++ ++static inline int ++voicebus_boot_init(struct voicebus *vb, const char *board_name) ++{ ++ return __voicebus_init(vb, board_name, BOOT); ++} ++ ++/** ++ * voicebus_lock_latency() - Do not increase the latency during underruns. ++ * ++ */ ++static inline void voicebus_lock_latency(struct voicebus *vb) ++{ ++ set_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags); ++} ++ ++/** ++ * voicebus_unlock_latency() - Bump up the latency during underruns. ++ * ++ */ ++static inline void voicebus_unlock_latency(struct voicebus *vb) ++{ ++ clear_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags); ++} ++ ++/** ++ * voicebus_is_latency_locked() - Return 1 if latency is currently locked. ++ * ++ */ ++static inline int voicebus_is_latency_locked(const struct voicebus *vb) ++{ ++ return test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags); ++} ++ ++static inline void voicebus_set_normal_mode(struct voicebus *vb) ++{ ++ vb->mode = NORMAL; ++} ++ ++static inline void voicebus_set_hx8_mode(struct voicebus *vb) ++{ ++ vb->mode = HX8; ++} ++ ++/** ++ * voicebus_set_max_latency() - Set the maximum number of milliseconds the latency will be able to grow to. ++ */ ++static inline void ++voicebus_set_maxlatency(struct voicebus *vb, unsigned int max_latency) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&vb->lock, flags); ++ vb->max_latency = clamp(max_latency, ++ vb->min_tx_buffer_count, ++ VOICEBUS_DEFAULT_MAXLATENCY); ++ spin_unlock_irqrestore(&vb->lock, flags); ++} ++#endif /* __VOICEBUS_H__ */ +diff -Nru linux-source-4.19/drivers/dahdi/voicebus/voicebus_net.c linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus_net.c +--- linux-source-4.19/drivers/dahdi/voicebus/voicebus_net.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus_net.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,338 @@ ++/* ++ * Voicebus network debug interface ++ * ++ * Written by Shaun Ruffell ++ * ++ * Copyright (C) 2010-2011 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 "voicebus.h" ++#include "voicebus_net.h" ++ ++#ifdef VOICEBUS_NET_DEBUG ++ ++struct voicebus_netdev_priv { ++ struct voicebus *vb; ++}; ++ ++static inline struct voicebus * ++voicebus_from_netdev(struct net_device *netdev) ++{ ++ struct voicebus_netdev_priv *priv; ++ priv = netdev_priv(netdev); ++ return priv->vb; ++} ++ ++static void * ++skb_to_vbb(struct voicebus *vb, struct sk_buff *skb) ++{ ++ int res; ++ struct vbb *vbb; ++ const int COMMON_HEADER = 30; ++ dma_addr_t dma_addr; ++ ++ if (skb->len != (VOICEBUS_SFRAME_SIZE + COMMON_HEADER)) { ++ dev_warn(&vb->pdev->dev, "Packet of length %d is not the " ++ "required %d.\n", skb->len, ++ VOICEBUS_SFRAME_SIZE + COMMON_HEADER); ++ return NULL; ++ } ++ ++ vbb = dma_pool_alloc(vb->pool, GFP_KERNEL, &dma_addr); ++ if (!vbb) ++ return NULL; ++ ++ vbb->dma_addr = dma_addr; ++ res = skb_copy_bits(skb, COMMON_HEADER, vbb, VOICEBUS_SFRAME_SIZE); ++ if (res) { ++ dev_warn(&vb->pdev->dev, "Failed call to skb_copy_bits.\n"); ++ dma_pool_free(vb->pool, vbb, vbb->dma_addr); ++ return NULL; ++ } ++ return vbb; ++} ++ ++static int ++vb_net_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) ++{ ++ struct voicebus *vb = voicebus_from_netdev(netdev); ++ void *vbb; ++ ++ vbb = skb_to_vbb(vb, skb); ++ if (vbb) ++ voicebus_transmit(vb, vbb); ++ ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++} ++ ++static int vb_net_receive(struct voicebus *vb, int max) ++{ ++ int count = 0; ++ struct sk_buff *skb; ++ WARN_ON(0 == max); ++ while ((skb = skb_dequeue(&vb->captured_packets))) { ++ netif_receive_skb(skb); ++ if (++count >= max) ++ break; ++ } ++ return count; ++} ++ ++static int vb_net_poll(struct napi_struct *napi, int budget) ++{ ++ struct voicebus *vb = container_of(napi, struct voicebus, napi); ++ int count; ++ ++ count = vb_net_receive(vb, budget); ++ ++ if (!skb_queue_len(&vb->captured_packets)) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++ netif_rx_complete(vb->netdev, &vb->napi); ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ++ netif_rx_complete(&vb->napi); ++#else ++ napi_complete(&vb->napi); ++#endif ++ } ++ return count; ++} ++ ++static void vb_net_set_multi(struct net_device *netdev) ++{ ++ struct voicebus *vb = voicebus_from_netdev(netdev); ++ dev_dbg(&vb->pdev->dev, "%s promiscuity:%d\n", ++ __func__, netdev->promiscuity); ++} ++ ++static int vb_net_up(struct net_device *netdev) ++{ ++ struct voicebus *vb = voicebus_from_netdev(netdev); ++ dev_dbg(&vb->pdev->dev, "%s\n", __func__); ++ napi_enable(&vb->napi); ++ return 0; ++} ++ ++static int vb_net_down(struct net_device *netdev) ++{ ++ struct voicebus *vb = voicebus_from_netdev(netdev); ++ dev_dbg(&vb->pdev->dev, "%s\n", __func__); ++ napi_disable(&vb->napi); ++ return 0; ++} ++ ++static struct net_device_stats * ++vb_net_get_stats(struct net_device *netdev) ++{ ++ struct voicebus *vb = voicebus_from_netdev(netdev); ++ return &vb->net_stats; ++} ++ ++#ifdef HAVE_NET_DEVICE_OPS ++static const struct net_device_ops vb_netdev_ops = { ++ .ndo_set_multicast_list = &vb_net_set_multi, ++ .ndo_open = &vb_net_up, ++ .ndo_stop = &vb_net_down, ++ .ndo_start_xmit = &vb_net_hard_start_xmit, ++ .ndo_get_stats = &vb_net_get_stats, ++}; ++#endif ++ ++/** ++ * vb_net_register - Register a new network interface. ++ * @vb: voicebus card to register the interface for. ++ * ++ * The network interface is primarily used for debugging in order to watch the ++ * traffic between the transcoder and the host. ++ * ++ */ ++int vb_net_register(struct voicebus *vb, const char *board_name) ++{ ++ int res; ++ struct net_device *netdev; ++ struct voicebus_netdev_priv *priv; ++ const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ netdev = alloc_netdev(sizeof(*priv), board_name, ++ NET_NAME_UNKNOWN, ether_setup); ++#else ++ netdev = alloc_netdev(sizeof(*priv), board_name, ether_setup); ++#endif ++ ++ if (!netdev) ++ return -ENOMEM; ++ priv = netdev_priv(netdev); ++ priv->vb = vb; ++ memcpy(netdev->dev_addr, our_mac, sizeof(our_mac)); ++# ifdef HAVE_NET_DEVICE_OPS ++ netdev->netdev_ops = &vb_netdev_ops; ++# else ++ netdev->set_multicast_list = vb_net_set_multi; ++ netdev->open = vb_net_up; ++ netdev->stop = vb_net_down; ++ netdev->hard_start_xmit = vb_net_hard_start_xmit; ++ netdev->get_stats = vb_net_get_stats; ++# endif ++ ++ netdev->promiscuity = 0; ++ netdev->flags |= IFF_NOARP; ++ netif_napi_add(netdev, &vb->napi, vb_net_poll, 64); ++ ++ skb_queue_head_init(&vb->captured_packets); ++ res = register_netdev(netdev); ++ if (res) { ++ dev_warn(&vb->pdev->dev, ++ "Failed to register network device %s.\n", board_name); ++ goto error_sw; ++ } ++ ++ vb->netdev = netdev; ++ ++ dev_dbg(&vb->pdev->dev, ++ "Created network device %s for debug.\n", board_name); ++ return 0; ++ ++error_sw: ++ if (netdev) ++ free_netdev(netdev); ++ return res; ++} ++ ++void vb_net_unregister(struct voicebus *wc) ++{ ++ struct sk_buff *skb; ++ if (!wc->netdev) ++ return; ++ ++ unregister_netdev(wc->netdev); ++ ++ while ((skb = skb_dequeue(&wc->captured_packets))) ++ kfree_skb(skb); ++ ++ free_netdev(wc->netdev); ++ wc->netdev = NULL; ++} ++ ++/* Header format for the voicebus network interface. */ ++struct voicebus_net_hdr { ++ struct ethhdr ethhdr; ++ __be16 seq_num; ++ __be32 des0; ++ __be16 tag; ++ __be16 filler[4]; ++} __attribute__((packed)); ++ ++static struct sk_buff * ++vbb_to_skb(struct net_device *netdev, const void *vbb, const int tx, ++ const u32 des0, const u16 tag) ++{ ++ struct voicebus *vb = voicebus_from_netdev(netdev); ++ struct sk_buff *skb; ++ struct voicebus_net_hdr *hdr; ++ /* 0x88B5 is the local experimental ethertype */ ++ const u16 VOICEBUS_ETHTYPE = 0x88b5; ++ const u8 BOARD_MAC[6] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; ++ const u8 HOST_MAC[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ++ ++ skb = netdev_alloc_skb(vb->netdev, ++ VOICEBUS_SFRAME_SIZE + sizeof(*hdr) + NET_IP_ALIGN); ++ if (!skb) ++ return NULL; ++ ++ skb_reserve(skb, NET_IP_ALIGN); ++ skb->dev = netdev; ++ hdr = (struct voicebus_net_hdr *)skb_put(skb, VOICEBUS_SFRAME_SIZE + ++ sizeof(*hdr)); ++ /* Fill in the source and destination mac addresses appropriately ++ * depending on whether this is a packet we are transmitting or a packet ++ * that we have received. */ ++ if (tx) { ++ memcpy(hdr->ethhdr.h_dest, BOARD_MAC, sizeof(BOARD_MAC)); ++ memcpy(hdr->ethhdr.h_source, HOST_MAC, sizeof(HOST_MAC)); ++ hdr->seq_num = cpu_to_be16(atomic_inc_return( ++ &vb->tx_seqnum)); ++ } else { ++ memcpy(hdr->ethhdr.h_dest, HOST_MAC, sizeof(HOST_MAC)); ++ memcpy(hdr->ethhdr.h_source, BOARD_MAC, sizeof(BOARD_MAC)); ++ hdr->seq_num = cpu_to_be16(atomic_inc_return( ++ &vb->rx_seqnum)); ++ } ++ memset(hdr->filler, 0, sizeof(hdr->filler)); ++ hdr->des0 = cpu_to_be32(des0); ++ hdr->tag = cpu_to_be16(tag); ++ hdr->ethhdr.h_proto = htons(VOICEBUS_ETHTYPE); ++ /* copy the rest of the packet. */ ++ memcpy(skb->data + sizeof(*hdr), vbb, VOICEBUS_SFRAME_SIZE); ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ return skb; ++} ++ ++/** ++ * vb_net_capture_cmd - Send a vbb to the network stack. ++ * @vb: Interface card received the command. ++ * @vbb: Voicebus buffer to pass up.. ++ * @tx: 1 if this is a vbb that the driver is sending to the card. ++ * ++ */ ++void vb_net_capture_vbb(struct voicebus *vb, const void *vbb, const int tx, ++ const u32 des0, const u16 tag) ++{ ++ struct sk_buff *skb; ++ struct net_device *netdev = vb->netdev; ++ const int MAX_CAPTURED_PACKETS = 5000; ++ ++ if (!netdev) ++ return; ++ ++ /* If the interface isn't up, we don't need to capture the packet. */ ++ if (!(netdev->flags & IFF_UP)) ++ return; ++ ++ if (skb_queue_len(&vb->captured_packets) > MAX_CAPTURED_PACKETS) { ++ WARN_ON_ONCE(1); ++ return; ++ } ++ ++ skb = vbb_to_skb(netdev, vbb, tx, des0, tag); ++ if (!skb) ++ return; ++ ++ skb_queue_tail(&vb->captured_packets, skb); ++# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++ netif_rx_schedule(netdev, &vb->napi); ++# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ++ netif_rx_schedule(&vb->napi); ++# else ++ napi_schedule(&vb->napi); ++# endif ++ return; ++} ++ ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/voicebus/voicebus_net.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus_net.h +--- linux-source-4.19/drivers/dahdi/voicebus/voicebus_net.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/voicebus_net.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,10 @@ ++#ifdef VOICEBUS_NET_DEBUG ++int vb_net_register(struct voicebus *, const char *); ++void vb_net_unregister(struct voicebus *); ++void vb_net_capture_vbb(struct voicebus *, const void *, ++ const int, const u32, const u16); ++#else ++#define vb_net_register(a, b) do { ; } while (0) ++#define vb_net_unregister(a) do { ; } while (0) ++#define vb_net_capture_vbb(a, b, c, d, e) do { ; } while (0) ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/voicebus/vpmadtreg.c linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmadtreg.c +--- linux-source-4.19/drivers/dahdi/voicebus/vpmadtreg.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmadtreg.c 2020-10-28 00:17:08.671192284 +0100 +@@ -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 -Nru linux-source-4.19/drivers/dahdi/voicebus/vpmadtreg.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmadtreg.h +--- linux-source-4.19/drivers/dahdi/voicebus/vpmadtreg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmadtreg.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,33 @@ ++/* ++ * 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-2010 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 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 -Nru linux-source-4.19/drivers/dahdi/voicebus/vpmoct.c linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmoct.c +--- linux-source-4.19/drivers/dahdi/voicebus/vpmoct.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmoct.c 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,835 @@ ++/* ++ * VPMOCT Driver. ++ * ++ * Written by Russ Meyerriecks ++ * ++ * Copyright (C) 2010-2011 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 ++#include ++ ++#include "voicebus/vpmoct.h" ++#include "linux/firmware.h" ++ ++struct vpmoct_header { ++ u8 header[6]; ++ __le32 chksum; ++ u8 pad[20]; ++ u8 major; ++ u8 minor; ++} __packed; ++ ++static int _vpmoct_read(struct vpmoct *vpm, u8 address, ++ void *data, size_t size, ++ u8 *new_command, u8 *new_address) ++{ ++ struct vpmoct_cmd *cmd; ++ unsigned long flags; ++ ++ if (unlikely(size >= ARRAY_SIZE(cmd->data))) { ++ memset(data, -1, size); ++ return -1; ++ } ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) { ++ dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n"); ++ return 0; ++ } ++ ++ init_completion(&cmd->complete); ++ ++ cmd->command = 0x60 + size; ++ cmd->address = address; ++ cmd->chunksize = size; ++ ++ spin_lock_irqsave(&vpm->list_lock, flags); ++ list_add_tail(&cmd->node, &vpm->pending_list); ++ spin_unlock_irqrestore(&vpm->list_lock, flags); ++ ++ /* Wait for receiveprep to process our result */ ++ if (!wait_for_completion_timeout(&cmd->complete, HZ/5)) { ++ spin_lock_irqsave(&vpm->list_lock, flags); ++ list_del(&cmd->node); ++ spin_unlock_irqrestore(&vpm->list_lock, flags); ++ kfree(cmd); ++ dev_err(vpm->dev, "vpmoct_read_byte cmd timed out\n"); ++ return 0; ++ } ++ ++ memcpy(data, &cmd->data[0], size); ++ ++ if (new_command) ++ *new_command = cmd->command; ++ if (new_address) ++ *new_address = cmd->address; ++ ++ kfree(cmd); ++ return 0; ++} ++ ++static u8 vpmoct_read_byte(struct vpmoct *vpm, u8 address) ++{ ++ u8 val; ++ _vpmoct_read(vpm, address, &val, sizeof(val), NULL, NULL); ++ return val; ++} ++ ++static u32 vpmoct_read_dword(struct vpmoct *vpm, u8 address) ++{ ++ __le32 val; ++ _vpmoct_read(vpm, address, &val, sizeof(val), NULL, NULL); ++ return le32_to_cpu(val); ++} ++ ++static void vpmoct_write_byte(struct vpmoct *vpm, u8 address, u8 data) ++{ ++ struct vpmoct_cmd *cmd; ++ unsigned long flags; ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) { ++ dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n"); ++ return; ++ } ++ ++ cmd->command = 0x21; ++ cmd->address = address; ++ cmd->data[0] = data; ++ cmd->chunksize = 1; ++ ++ spin_lock_irqsave(&vpm->list_lock, flags); ++ list_add_tail(&cmd->node, &vpm->pending_list); ++ spin_unlock_irqrestore(&vpm->list_lock, flags); ++} ++ ++static void vpmoct_write_dword(struct vpmoct *vpm, u8 address, u32 data) ++{ ++ struct vpmoct_cmd *cmd; ++ unsigned long flags; ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) { ++ dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n"); ++ return; ++ } ++ ++ cmd->command = 0x20 + sizeof(data); ++ cmd->address = address; ++ *(__le32 *)(&cmd->data[0]) = cpu_to_le32(data); ++ cmd->chunksize = sizeof(data); ++ ++ spin_lock_irqsave(&vpm->list_lock, flags); ++ list_add_tail(&cmd->node, &vpm->pending_list); ++ spin_unlock_irqrestore(&vpm->list_lock, flags); ++} ++ ++static void vpmoct_write_chunk(struct vpmoct *vpm, u8 address, ++ const u8 *data, u8 chunksize) ++{ ++ struct vpmoct_cmd *cmd; ++ unsigned long flags; ++ ++ if (unlikely(chunksize > ARRAY_SIZE(cmd->data))) ++ return; ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); ++ if (unlikely(!cmd)) { ++ dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n"); ++ return; ++ } ++ ++ cmd->command = 0x20 + chunksize; ++ cmd->address = address; ++ cmd->chunksize = chunksize; ++ ++ memcpy(cmd->data, data, chunksize); ++ ++ spin_lock_irqsave(&vpm->list_lock, flags); ++ list_add_tail(&cmd->node, &vpm->pending_list); ++ spin_unlock_irqrestore(&vpm->list_lock, flags); ++} ++ ++static u8 vpmoct_resync(struct vpmoct *vpm) ++{ ++ unsigned long time; ++ u8 status = 0xff; ++ u8 address; ++ u8 command; ++ ++ /* Poll the status register until it returns valid values ++ * This is because we have to wait on the bootloader to do ++ * its thing. ++ * Timeout after 3 seconds ++ */ ++ time = jiffies + 3*HZ; ++ while (time_after(time, jiffies) && (0xff == status)) { ++ status = _vpmoct_read(vpm, VPMOCT_BOOT_STATUS, &status, ++ sizeof(status), &command, &address); ++ ++ /* Throw out invalid statuses */ ++ if ((0x55 != command) || (0xaa != address)) ++ status = 0xff; ++ } ++ ++ if ((status != 0xff) && status) ++ dev_info(vpm->dev, "Resync with status %x\n", status); ++ ++ return status; ++} ++ ++static inline short vpmoct_erase_flash(struct vpmoct *vpm) ++{ ++ short res; ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_FLASH_ERASE); ++ res = vpmoct_resync(vpm); ++ if (res) ++ dev_info(vpm->dev, "Unable to erase flash\n"); ++ return res; ++} ++ ++static inline short ++vpmoct_send_firmware_header(struct vpmoct *vpm, const struct firmware *fw) ++{ ++ unsigned short i; ++ short res; ++ ++ /* Send the encrypted firmware header */ ++ for (i = 0; i < VPMOCT_FIRM_HEADER_LEN; i++) { ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_RAM+i, ++ fw->data[i + sizeof(struct vpmoct_header)]); ++ } ++ /* Decrypt header */ ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_DECRYPT); ++ res = vpmoct_resync(vpm); ++ if (res) ++ dev_info(vpm->dev, "Unable to send firmware header\n"); ++ return res; ++} ++ ++static inline short ++vpmoct_send_firmware_body(struct vpmoct *vpm, const struct firmware *fw) ++{ ++ unsigned int i, ram_index, flash_index, flash_address; ++ const u8 *buf; ++ u8 chunksize; ++ ++ /* Load the body of the firmware */ ++ ram_index = 0; ++ flash_index = 0; ++ flash_address = 0; ++ for (i = VPMOCT_FIRM_HEADER_LEN*2; i < fw->size;) { ++ if (ram_index >= VPMOCT_BOOT_RAM_LEN) { ++ /* Tell bootloader to load ram buffer into buffer */ ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, ++ 0x10 + flash_index); ++ /* Assuming the memory load doesn't take longer than 1 ++ * eframe just insert a blank eframe before continuing ++ * the firmware load */ ++ vpmoct_read_byte(vpm, VPMOCT_BOOT_STATUS); ++ ram_index = 0; ++ flash_index++; ++ } ++ if (flash_index >= VPMOCT_FLASH_BUF_SECTIONS) { ++ /* Tell the bootloader the memory address for load */ ++ vpmoct_write_dword(vpm, VPMOCT_BOOT_ADDRESS1, ++ flash_address); ++ /* Tell the bootloader to load from flash buffer */ ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, ++ VPMOCT_BOOT_FLASH_COPY); ++ if (vpmoct_resync(vpm)) ++ goto error; ++ flash_index = 0; ++ flash_address = i-VPMOCT_FIRM_HEADER_LEN*2; ++ } ++ /* Try to buffer for batch writes if possible */ ++ chunksize = VPMOCT_BOOT_RAM_LEN - ram_index; ++ if (chunksize > VPMOCT_MAX_CHUNK) ++ chunksize = VPMOCT_MAX_CHUNK; ++ ++ buf = &fw->data[i]; ++ vpmoct_write_chunk(vpm, VPMOCT_BOOT_RAM+ram_index, ++ buf, chunksize); ++ ram_index += chunksize; ++ i += chunksize; ++ } ++ ++ /* Flush remaining ram buffer to flash buffer */ ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, ++ VPMOCT_BOOT_FLASHLOAD + flash_index); ++ if (vpmoct_resync(vpm)) ++ goto error; ++ /* Tell boot loader the memory address to flash load */ ++ vpmoct_write_dword(vpm, VPMOCT_BOOT_ADDRESS1, flash_address); ++ /* Tell the bootloader to load flash from flash buffer */ ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_FLASH_COPY); ++ if (vpmoct_resync(vpm)) ++ goto error; ++ ++ return 0; ++ ++error: ++ dev_info(vpm->dev, "Unable to load firmware body\n"); ++ return -1; ++} ++ ++/** ++ * vpmoct_get_mode - Return the current operating mode of the VPMOCT032. ++ * @vpm: The vpm to query. ++ * ++ * Will be either BOOTLOADER, APPLICATION, or UNKNOWN. ++ * ++ */ ++static enum vpmoct_mode vpmoct_get_mode(struct vpmoct *vpm) ++{ ++ int i; ++ enum vpmoct_mode ret = UNKNOWN; ++ char identifier[11] = {0}; ++ ++ for (i = 0; i < ARRAY_SIZE(identifier) - 1; i++) ++ identifier[i] = vpmoct_read_byte(vpm, VPMOCT_IDENT+i); ++ ++ if (!memcmp(identifier, "bootloader", sizeof(identifier) - 1)) ++ ret = BOOTLOADER; ++ else if (!memcmp(identifier, "VPMOCT032\0", sizeof(identifier) - 1)) ++ ret = APPLICATION; ++ ++ dev_dbg(vpm->dev, "vpmoct identifier: %s\n", identifier); ++ return ret; ++} ++ ++ ++static inline short ++vpmoct_check_firmware_crc(struct vpmoct *vpm, size_t size, u8 major, u8 minor) ++{ ++ short ret = 0; ++ u8 status; ++ ++ /* Load firmware size */ ++ vpmoct_write_dword(vpm, VPMOCT_BOOT_RAM, size); ++ ++ /* Load firmware version */ ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_RAM+8, major); ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_RAM+9, minor); ++ ++ /* Validate the firmware load */ ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_IMAGE_VALIDATE); ++ ++ status = vpmoct_resync(vpm); ++ if (status) { ++ dev_info(vpm->dev, ++ "vpmoct firmware CRC check failed: %x\n", status); ++ /* TODO: Try the load again */ ++ ret = -1; ++ } else { ++ ++ /* Switch to application code */ ++ vpmoct_write_dword(vpm, VPMOCT_BOOT_ADDRESS2, 0xDEADBEEF); ++ vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_REBOOT); ++ ++ msleep(250); ++ status = vpmoct_resync(vpm); ++ ++ if (APPLICATION != vpmoct_get_mode(vpm)) { ++ dev_info(vpm->dev, ++ "vpmoct firmware failed to switch to " ++ "application. (%x)\n", status); ++ ret = -1; ++ } else { ++ vpm->mode = APPLICATION; ++ dev_info(vpm->dev, ++ "vpmoct firmware uploaded successfully\n"); ++ } ++ } ++ ++ return ret; ++} ++ ++static inline short vpmoct_switch_to_boot(struct vpmoct *vpm) ++{ ++ vpmoct_write_dword(vpm, 0x74, 0x00009876); ++ vpmoct_write_byte(vpm, 0x71, 0x02); ++ if (vpmoct_resync(vpm)) { ++ dev_info(vpm->dev, "Failed to switch to bootloader\n"); ++ return -1; ++ } ++ vpm->mode = BOOTLOADER; ++ return 0; ++} ++ ++struct vpmoct_load_work { ++ struct vpmoct *vpm; ++ struct work_struct work; ++ struct workqueue_struct *wq; ++ load_complete_func_t load_complete; ++ bool operational; ++}; ++ ++/** ++ * vpmoct_load_complete_fn - ++ * ++ * This function should run in the context of one of the system workqueues so ++ * that it can destroy any workqueues that may have been created to setup a ++ * long running firmware load. ++ * ++ */ ++static void vpmoct_load_complete_fn(struct work_struct *data) ++{ ++ struct vpmoct_load_work *work = ++ container_of(data, struct vpmoct_load_work, work); ++ /* Do not touch work->vpm after calling load complete. It may have ++ * been freed in the function by the board driver. */ ++ work->load_complete(work->vpm->dev, work->operational); ++ destroy_workqueue(work->wq); ++ kfree(work); ++} ++ ++/** ++ * vpmoct_load_complete - Call the load_complete function in a system workqueue. ++ * @work: ++ * @operational: Whether the VPM is functioning or not. ++ * ++ */ ++static void ++vpmoct_load_complete(struct vpmoct_load_work *work, bool operational) ++{ ++ work->operational = operational; ++ ++ INIT_WORK(&work->work, vpmoct_load_complete_fn); ++ schedule_work(&work->work); ++} ++ ++static bool is_valid_vpmoct_firmware(const struct firmware *fw) ++{ ++ const struct vpmoct_header *header = ++ (const struct vpmoct_header *)fw->data; ++ u32 crc = crc32(~0, &fw->data[10], fw->size - 10) ^ ~0; ++ return (!memcmp("DIGIUM", header->header, sizeof(header->header)) && ++ (le32_to_cpu(header->chksum) == crc)); ++} ++ ++static void vpmoct_set_defaults(struct vpmoct *vpm) ++{ ++ vpmoct_write_dword(vpm, 0x40, 0); ++ vpmoct_write_dword(vpm, 0x30, 0); ++} ++ ++static const char *const FIRMWARE_NAME = "dahdi-fw-vpmoct032.bin"; ++#if defined(HOTPLUG_FIRMWARE) ++static int ++vpmoct_request_firmware(const struct firmware **fw, struct device *dev) ++{ ++ return request_firmware(fw, FIRMWARE_NAME, dev); ++} ++ ++static void vpmoct_release_firmware(const struct firmware *fw) ++{ ++ release_firmware(fw); ++} ++#else ++static int ++vpmoct_request_firmware(const struct firmware **fw_p, struct device *dev) ++{ ++ struct firmware *fw; ++ extern void _binary_dahdi_fw_vpmoct032_bin_size; ++ extern u8 _binary_dahdi_fw_vpmoct032_bin_start[]; ++ ++ *fw_p = fw = kzalloc(sizeof(*fw), GFP_KERNEL); ++ if (!fw) ++ return -ENOMEM; ++ ++ fw->data = _binary_dahdi_fw_vpmoct032_bin_start; ++ /* Yes... this is weird. objcopy gives us a symbol containing ++ the size of the firmware, not a pointer a variable containing the ++ size. The only way we can get the value of the symbol is to take ++ its address, so we define it as a pointer and then cast that value ++ to the proper type. */ ++ fw->size = (size_t) &_binary_dahdi_fw_vpmoct032_bin_size; ++ ++ return 0; ++} ++ ++static void vpmoct_release_firmware(const struct firmware *fw) ++{ ++ kfree(fw); ++} ++#endif ++ ++/** ++ * vpmoct_load_flash - Check the current flash version and possibly load. ++ * @vpm: The VPMOCT032 module to check / load. ++ * ++ */ ++static void vpmoct_load_flash(struct work_struct *data) ++{ ++ struct vpmoct_load_work *work = ++ container_of(data, struct vpmoct_load_work, work); ++ int res; ++ struct vpmoct *const vpm = work->vpm; ++ const struct firmware *fw; ++ const struct vpmoct_header *header; ++ char serial[VPMOCT_SERIAL_SIZE+1]; ++ int i; ++ ++ res = vpmoct_request_firmware(&fw, vpm->dev); ++ if (res) { ++ dev_warn(vpm->dev, ++ "vpmoct: Failed to load firmware from userspace! %d\n", ++ res); ++ header = NULL; ++ fw = NULL; ++ } else { ++ header = (const struct vpmoct_header *)fw->data; ++ } ++ ++ if (vpm->mode == APPLICATION) { ++ ++ /* Check the running application firmware ++ * for the proper version */ ++ vpm->major = vpmoct_read_byte(vpm, VPMOCT_MAJOR); ++ vpm->minor = vpmoct_read_byte(vpm, VPMOCT_MINOR); ++ for (i = 0; i < VPMOCT_SERIAL_SIZE; i++) ++ serial[i] = vpmoct_read_byte(vpm, VPMOCT_SERIAL+i); ++ serial[VPMOCT_SERIAL_SIZE] = '\0'; ++ ++ dev_info(vpm->dev, ++ "vpmoct: Detected firmware v%d.%d Serial: %s\n", ++ vpm->major, vpm->minor, ++ (serial[0] != -1) ? serial : "(None)"); ++ ++ if (!fw) { ++ /* Again, we'll use the existing loaded firmware. */ ++ vpmoct_set_defaults(vpm); ++ vpmoct_load_complete(work, true); ++ return; ++ } ++ ++ if (!is_valid_vpmoct_firmware(fw)) { ++ dev_warn(vpm->dev, ++ "%s is invalid. Please reinstall.\n", ++ FIRMWARE_NAME); ++ ++ /* Just use the old version of the fimware. */ ++ vpmoct_release_firmware(fw); ++ vpmoct_set_defaults(vpm); ++ vpmoct_load_complete(work, true); ++ return; ++ } ++ ++ if (vpm->minor == header->minor && ++ vpm->major == header->major) { ++ /* Proper version is running */ ++ vpmoct_release_firmware(fw); ++ vpmoct_set_defaults(vpm); ++ vpmoct_load_complete(work, true); ++ return; ++ } else { ++ ++ /* Incorrect version of application code is ++ * loaded. Reset to bootloader mode */ ++ if (vpmoct_switch_to_boot(vpm)) ++ goto error; ++ } ++ } ++ ++ if (!fw) { ++ vpmoct_load_complete(work, false); ++ return; ++ } else if (!is_valid_vpmoct_firmware(fw)) { ++ dev_warn(vpm->dev, ++ "%s is invalid. Please reinstall.\n", FIRMWARE_NAME); ++ goto error; ++ } ++ ++ dev_info(vpm->dev, "vpmoct: Uploading firmware, v%d.%d. This can "\ ++ "take up to 1 minute\n", ++ header->major, header->minor); ++ if (vpmoct_erase_flash(vpm)) ++ goto error; ++ if (vpmoct_send_firmware_header(vpm, fw)) ++ goto error; ++ if (vpmoct_send_firmware_body(vpm, fw)) ++ goto error; ++ if (vpmoct_check_firmware_crc(vpm, fw->size-VPMOCT_FIRM_HEADER_LEN*2, ++ header->major, header->minor)) ++ goto error; ++ vpmoct_release_firmware(fw); ++ vpmoct_set_defaults(vpm); ++ vpmoct_load_complete(work, true); ++ return; ++ ++error: ++ dev_info(vpm->dev, "Unable to load firmware\n"); ++ vpmoct_release_firmware(fw); ++ /* TODO: Should we disable module if the firmware doesn't load? */ ++ vpmoct_load_complete(work, false); ++ return; ++} ++ ++struct vpmoct *vpmoct_alloc(void) ++{ ++ struct vpmoct *vpm; ++ ++ vpm = kzalloc(sizeof(*vpm), GFP_KERNEL); ++ if (!vpm) ++ return NULL; ++ ++ spin_lock_init(&vpm->list_lock); ++ INIT_LIST_HEAD(&vpm->pending_list); ++ INIT_LIST_HEAD(&vpm->active_list); ++ mutex_init(&vpm->mutex); ++ return vpm; ++} ++EXPORT_SYMBOL(vpmoct_alloc); ++ ++void vpmoct_free(struct vpmoct *vpm) ++{ ++ unsigned long flags; ++ struct vpmoct_cmd *cmd; ++ LIST_HEAD(list); ++ ++ if (!vpm) ++ return; ++ ++ spin_lock_irqsave(&vpm->list_lock, flags); ++ list_splice(&vpm->active_list, &list); ++ list_splice(&vpm->pending_list, &list); ++ spin_unlock_irqrestore(&vpm->list_lock, flags); ++ ++ while (!list_empty(&list)) { ++ cmd = list_entry(list.next, struct vpmoct_cmd, node); ++ list_del(&cmd->node); ++ kfree(cmd); ++ } ++ ++ kfree(vpm); ++} ++EXPORT_SYMBOL(vpmoct_free); ++ ++/** ++ * vpmoct_init - Check for / initialize VPMOCT032 module. ++ * @vpm: struct vpmoct allocated with vpmoct_alloc ++ * @load_complete_fn: Function to call when the load is complete. ++ * ++ * Check to see if there is a VPMOCT module installed. If there appears to be ++ * one return 0 and perform any necessary setup in the background. The ++ * load_complete function will be called in a system global workqueue when the ++ * initialization is complete. ++ * ++ * Must be called in process context. ++ */ ++int vpmoct_init(struct vpmoct *vpm, load_complete_func_t load_complete) ++{ ++ struct vpmoct_load_work *work; ++ ++ if (!vpm || !vpm->dev || !load_complete) ++ return -EINVAL; ++ ++ if (vpmoct_resync(vpm)) { ++ load_complete(vpm->dev, false); ++ return -ENODEV; ++ } ++ ++ vpm->mode = vpmoct_get_mode(vpm); ++ ++ if (UNKNOWN == vpm->mode) { ++ load_complete(vpm->dev, false); ++ return -ENODEV; ++ } ++ ++ work = kzalloc(sizeof(*work), GFP_KERNEL); ++ if (!work) { ++ load_complete(vpm->dev, false); ++ return -ENOMEM; ++ } ++ ++ work->wq = create_singlethread_workqueue("vpmoct"); ++ if (!work->wq) { ++ kfree(work); ++ load_complete(vpm->dev, false); ++ return -ENOMEM; ++ } ++ ++ INIT_WORK(&work->work, vpmoct_load_flash); ++ ++ work->vpm = vpm; ++ work->load_complete = load_complete; ++ queue_work(work->wq, &work->work); ++ return 0; ++} ++EXPORT_SYMBOL(vpmoct_init); ++ ++static void ++vpmoct_set_companding(struct vpmoct *vpm, int channo, int companding) ++{ ++ u32 new_companding; ++ bool do_update = false; ++ ++ mutex_lock(&vpm->mutex); ++ new_companding = (DAHDI_LAW_MULAW == companding) ? ++ (vpm->companding & ~(1 << channo)) : ++ (vpm->companding | (1 << channo)); ++ if (vpm->companding != new_companding) { ++ vpm->companding = new_companding; ++ if (!vpm->companding_update_active) { ++ do_update = true; ++ vpm->companding_update_active = 1; ++ } ++ } ++ mutex_unlock(&vpm->mutex); ++ ++ while (do_update) { ++ u32 update; ++ ++ vpmoct_write_dword(vpm, 0x40, new_companding); ++ update = vpmoct_read_dword(vpm, 0x40); ++ ++ WARN_ON(new_companding != update); ++ ++ mutex_lock(&vpm->mutex); ++ if (vpm->companding != new_companding) { ++ new_companding = vpm->companding; ++ } else { ++ vpm->companding_update_active = 0; ++ do_update = false; ++ } ++ mutex_unlock(&vpm->mutex); ++ } ++} ++ ++/** ++ * vpmoct_echo_update - Enable / Disable the VPMOCT032 echocan state ++ * @vpm: The echocan to operate on. ++ * @channo: Which echocan timeslot to enable / disable. ++ * @echo_on: Whether we're turning the echocan on or off. ++ * ++ * When this function returns, the echocan is scheduled to be enabled or ++ * disabled at some point in the near future. ++ * ++ * Must be called in process context. ++ * ++ */ ++static void vpmoct_echo_update(struct vpmoct *vpm, int channo, bool echo_on) ++{ ++ u32 echo; ++ unsigned long timeout; ++ bool do_update = false; ++ ++ mutex_lock(&vpm->mutex); ++ echo = (echo_on) ? (vpm->echo | (1 << channo)) : ++ (vpm->echo & ~(1 << channo)); ++ if (vpm->echo != echo) { ++ vpm->echo = echo; ++ if (!vpm->echo_update_active) { ++ do_update = true; ++ vpm->echo_update_active = 1; ++ } ++ } ++ mutex_unlock(&vpm->mutex); ++ ++ timeout = jiffies + 2*HZ; ++ while (do_update) { ++ u32 new; ++ ++ vpmoct_write_dword(vpm, 0x30, echo); ++ new = vpmoct_read_dword(vpm, 0x10); ++ ++ mutex_lock(&vpm->mutex); ++ if (((vpm->echo != echo) || (new != echo)) && ++ time_before(jiffies, timeout)) { ++ echo = vpm->echo; ++ } else { ++ vpm->echo_update_active = 0; ++ do_update = false; ++ } ++ mutex_unlock(&vpm->mutex); ++ } ++ ++ if (!time_before(jiffies, timeout)) ++ dev_warn(vpm->dev, "vpmoct: Updating echo state timed out.\n"); ++} ++ ++int vpmoct_echocan_create(struct vpmoct *vpm, int channo, int companding) ++{ ++ vpmoct_set_companding(vpm, channo, companding); ++ vpmoct_echo_update(vpm, channo, true); ++ return 0; ++} ++EXPORT_SYMBOL(vpmoct_echocan_create); ++ ++void vpmoct_echocan_free(struct vpmoct *vpm, int channo) ++{ ++ vpmoct_echo_update(vpm, channo, false); ++} ++EXPORT_SYMBOL(vpmoct_echocan_free); ++ ++/* Enable a vpm debugging mode where the pre-echo-canceled audio ++ * stream is physically output on timeslot 24. ++ */ ++int vpmoct_preecho_enable(struct vpmoct *vpm, const int channo) ++{ ++ int ret; ++ mutex_lock(&vpm->mutex); ++ if (!vpm->preecho_enabled) { ++ vpm->preecho_enabled = 1; ++ vpm->preecho_timeslot = channo; ++ ++ vpmoct_write_dword(vpm, 0x74, channo); ++ ++ /* Begin pre-echo stream on timeslot 24 */ ++ vpmoct_write_byte(vpm, 0x71, 0x0a); ++ ret = 0; ++ } else { ++ ret = -EBUSY; ++ } ++ mutex_unlock(&vpm->mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL(vpmoct_preecho_enable); ++ ++int vpmoct_preecho_disable(struct vpmoct *vpm, const int channo) ++{ ++ int ret; ++ ++ mutex_lock(&vpm->mutex); ++ if (!vpm->preecho_enabled) { ++ ret = 0; ++ } else if (channo == vpm->preecho_timeslot) { ++ vpm->preecho_enabled = 0; ++ ++ /* Disable pre-echo stream by loading in a non-existing ++ * channel number */ ++ vpmoct_write_byte(vpm, 0x74, 0xff); ++ ++ /* Stop pre-echo stream on timeslot 24 */ ++ vpmoct_write_byte(vpm, 0x71, 0x0a); ++ ret = 0; ++ } else { ++ ret = -EINVAL; ++ } ++ mutex_unlock(&vpm->mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL(vpmoct_preecho_disable); +diff -Nru linux-source-4.19/drivers/dahdi/voicebus/vpmoct.h linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmoct.h +--- linux-source-4.19/drivers/dahdi/voicebus/vpmoct.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/voicebus/vpmoct.h 2020-10-28 00:17:08.671192284 +0100 +@@ -0,0 +1,110 @@ ++/* ++ * VPMOCT Driver. ++ * ++ * Written by Russ Meyerriecks ++ * ++ * Copyright (C) 2010-2011 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 _VPMOCT_H ++#define _VPMOCT_H ++ ++#include ++#include ++#include ++#include "dahdi/kernel.h" ++ ++#include ++ ++#define VPMOCT_FIRM_HEADER_LEN 32 ++#define VPMOCT_BOOT_RAM_LEN 128 ++#define VPMOCT_FLASH_BUF_SECTIONS 4 ++#define VPMOCT_MAX_CHUNK 7 ++ ++/* Bootloader commands */ ++#define VPMOCT_BOOT_FLASH_ERASE 0x01 ++#define VPMOCT_BOOT_FLASH_COPY 0x02 ++#define VPMOCT_BOOT_IMAGE_VALIDATE 0x06 ++#define VPMOCT_BOOT_REBOOT 0x07 ++#define VPMOCT_BOOT_DECRYPT 0x08 ++#define VPMOCT_BOOT_FLASHLOAD 0x10 ++ ++/* Dual use registers */ ++#define VPMOCT_IDENT 0x00 ++#define VPMOCT_MAJOR 0x0a ++#define VPMOCT_MINOR 0x0b ++#define VPMOCT_SERIAL 0x90 ++#define VPMOCT_SERIAL_SIZE 32 ++ ++/* Bootloader registers */ ++#define VPMOCT_BOOT_ERROR 0x0c ++#define VPMOCT_BOOT_STATUS 0x10 ++#define VPMOCT_BOOT_CMD 0x11 ++#define VPMOCT_BOOT_LEN 0x14 ++#define VPMOCT_BOOT_ADDRESS1 0x18 ++#define VPMOCT_BOOT_ADDRESS2 0x1c ++#define VPMOCT_BOOT_RAM 0x20 ++ ++enum vpmoct_mode { UNKNOWN = 0, APPLICATION, BOOTLOADER }; ++ ++struct vpmoct { ++ struct list_head pending_list; ++ struct list_head active_list; ++ spinlock_t list_lock; ++ struct mutex mutex; ++ enum vpmoct_mode mode; ++ struct device *dev; ++ u32 companding; ++ u32 echo; ++ unsigned int preecho_enabled:1; ++ unsigned int echo_update_active:1; ++ unsigned int companding_update_active:1; ++ u8 preecho_timeslot; ++ u8 preecho_buf[8]; ++ u8 major; ++ u8 minor; ++}; ++ ++struct vpmoct_cmd { ++ struct list_head node; ++ u8 address; ++ u8 data[VPMOCT_MAX_CHUNK]; ++ u8 command; ++ u8 chunksize; ++ u8 txident; ++ struct completion complete; ++}; ++ ++static inline bool is_vpmoct_cmd_read(const struct vpmoct_cmd *cmd) ++{ ++ return (0x60 == (cmd->command & 0xf0)); ++} ++ ++struct vpmoct *vpmoct_alloc(void); ++void vpmoct_free(struct vpmoct *vpm); ++typedef void (*load_complete_func_t)(struct device *dev, bool operational); ++int vpmoct_init(struct vpmoct *vpm, load_complete_func_t load_complete); ++int vpmoct_echocan_create(struct vpmoct *vpm, ++ int channo, ++ int companding); ++void vpmoct_echocan_free(struct vpmoct *vpm, ++ int channo); ++int vpmoct_preecho_enable(struct vpmoct *vpm, int channo); ++int vpmoct_preecho_disable(struct vpmoct *vpm, int channo); ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c linux-source-4.19-dahdi/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c +--- linux-source-4.19/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,150 @@ ++/* ++ * DAHDI Telephony Interface to VPMADT032 Firmware Loader ++ * ++ * Copyright (C) 2008-2012 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 ++ ++#include ++ ++static int debug; ++ ++#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; ++ ++ va_start(args, format); ++ res = vprintk(format, args); ++ va_end(args); ++ ++ 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 *pvt; ++ struct completion done; ++ struct voicebus_operations ops; ++}; ++ ++static void handle_receive(struct voicebus *vb, struct list_head *buffers) ++{ ++ struct vbb *vbb; ++ struct private_context *ctx = container_of(vb->ops, ++ struct private_context, ops); ++ list_for_each_entry(vbb, buffers, entry) { ++ __vpmadt032_receive(ctx->pvt, vbb->data); ++ if (__vpmadt032_done(ctx->pvt)) ++ complete(&ctx->done); ++ } ++} ++ ++static void handle_transmit(struct voicebus *vb, struct list_head *buffers) ++{ ++ struct vbb *vbb; ++ struct private_context *ctx = container_of(vb->ops, ++ struct private_context, ops); ++ list_for_each_entry(vbb, buffers, entry) ++ __vpmadt032_transmit(ctx->pvt, vbb->data); ++} ++ ++static void init_private_context(struct private_context *ctx) ++{ ++ init_completion(&ctx->done); ++ ctx->ops.handle_receive = handle_receive; ++ ctx->ops.handle_transmit = handle_transmit; ++} ++ ++static int vpmadt032_load_firmware(struct voicebus *vb) ++{ ++ int ret = 0; ++ struct private_context *ctx; ++ const struct voicebus_operations *old; ++ int id; ++ might_sleep(); ++ ctx = kzalloc(sizeof(struct private_context), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ init_private_context(ctx); ++ ctx->vb = vb; ++ ++ if (0x8007 == vb->pdev->device || 0x8008 == vb->pdev->device) ++ id = vb->pdev->vendor << 16 | 0x2400; ++ else ++ id = vb->pdev->vendor << 16 | vb->pdev->device; ++ ++ ret = __vpmadt032_start_load(0, id, &ctx->pvt); ++ if (ret) ++ goto error_exit; ++ old = vb->ops; ++ vb->ops = &ctx->ops; ++ if (!wait_for_completion_timeout(&ctx->done, HZ*20)) ++ ret = -EIO; ++ vb->ops = old; ++ __vpmadt032_cleanup(ctx->pvt); ++error_exit: ++ kfree(ctx); ++ return ret; ++} ++ ++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 -Nru linux-source-4.19/drivers/dahdi/wcaxx-base.c linux-source-4.19-dahdi/drivers/dahdi/wcaxx-base.c +--- linux-source-4.19/drivers/dahdi/wcaxx-base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcaxx-base.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,4548 @@ ++/* ++ * A4A,A4B,A8A,A8B TDM FXS/FXO Interface Driver for DAHDI Telephony interface ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) ++/* Define this if you would like to load the modules in parallel. While this ++ * can speed up loads when multiple cards handled by this driver are installed, ++ * it also makes it impossible to abort module loads with ctrl-c */ ++#undef USE_ASYNC_INIT ++#include ++#else ++#undef USE_ASYNC_INIT ++#endif ++ ++#include ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#include ++#endif /* 4.11.0 */ ++ ++#include "proslic.h" ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "wcxb.h" ++#include "wcxb_spi.h" ++#include "wcxb_flash.h" ++ ++/*! ++ * \brief Default ringer debounce (in ms) ++ */ ++#define DEFAULT_RING_DEBOUNCE 1024 ++#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */ ++ ++#define OHT_TIMER 6000 /* How long after RING to retain OHT */ ++ ++#define FLAG_EXPRESS (1 << 0) ++ ++#define NUM_MODULES 8 ++ ++#define CMD_WR(addr, val) (((addr<<8)&0xff00) | (val&0xff)) ++ ++enum battery_state { ++ BATTERY_UNKNOWN = 0, ++ BATTERY_DEBOUNCING_PRESENT, ++ BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM, ++ BATTERY_DEBOUNCING_PRESENT_ALARM, ++ BATTERY_PRESENT, ++ BATTERY_DEBOUNCING_LOST, ++ BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM, ++ BATTERY_DEBOUNCING_LOST_ALARM, ++ BATTERY_LOST, ++}; ++ ++enum ring_detector_state { ++ RINGOFF = 0, ++ DEBOUNCING_RINGING_POSITIVE, ++ DEBOUNCING_RINGING_NEGATIVE, ++ RINGING, ++ DEBOUNCING_RINGOFF, ++}; ++ ++enum polarity_state { ++ UNKNOWN_POLARITY = 0, ++ POLARITY_DEBOUNCE_POSITIVE, ++ POLARITY_POSITIVE, ++ POLARITY_DEBOUNCE_NEGATIVE, ++ POLARITY_NEGATIVE, ++}; ++ ++struct wcaxx_chan { ++ struct dahdi_chan chan; ++ struct dahdi_echocan_state ec; ++ int timeslot; ++ unsigned int hwpreec_enabled:1; ++}; ++ ++struct fxo { ++ enum ring_detector_state ring_state:4; ++ enum battery_state battery_state:4; ++ enum polarity_state polarity_state:4; ++ u8 ring_polarity_change_count:4; ++ u8 hook_ring_shadow; ++ s8 line_voltage_status; ++ int offhook; ++ int neonmwi_state; ++ int neonmwi_last_voltage; ++ unsigned int neonmwi_debounce; ++ unsigned int neonmwi_offcounter; ++ unsigned long display_fxovoltage; ++ unsigned long ringdebounce_timer; ++ unsigned long battdebounce_timer; ++ unsigned long poldebounce_timer; ++}; ++ ++struct fxs { ++ int idletxhookstate; /* IDLE changing hook state */ ++ /* lasttxhook reflects the last value written to the proslic's reg 64 ++ * (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last write is ++ * pending i.e. it is in process of being written to the register NOTE: ++ * in order for this value to actually be written to the proslic, the ++ * appropriate matching value must be written into the sethook variable ++ * so that it gets queued and handled by the voicebus ISR. ++ */ ++ u8 lasttxhook; ++ u8 linefeed_control_shadow; ++ u8 hook_state_shadow; ++ u8 oht_active:1; ++ u8 off_hook:1; ++ int palarms; ++ struct dahdi_vmwi_info vmwisetting; ++ int vmwi_active_messages; ++ int vmwi_linereverse; ++ int reversepolarity; /* polarity reversal */ ++ struct { ++ u8 vals[12]; ++ } calregs; ++ unsigned long check_alarm; ++ unsigned long check_proslic; ++ unsigned long oppending_timeout; ++ unsigned long ohttimer; ++}; ++ ++#define fxs_lf(fxs, value) _fxs_lf((fxs), SLIC_LF_##value) ++static inline bool _fxs_lf(const struct fxs *fxs, const unsigned value) ++{ ++ return (fxs->lasttxhook & SLIC_LF_SETMASK) == value; ++} ++ ++enum module_type { ++ NONE = 0, ++ FXS, ++ FXO, ++}; ++ ++#define MODULE_POLL_TIME_MS 10 ++ ++struct wcaxx_mod_poll { ++ struct wcxb_spi_message m; ++ struct wcxb_spi_transfer t; ++ struct wcaxx_module *mod; ++ struct wcaxx *wc; ++ u8 buffer[6]; ++ u8 master_buffer[6]; ++}; ++ ++struct wcaxx_module { ++ union modtypes { ++ struct fxo fxo; ++ struct fxs fxs; ++ } mod; ++ u8 card; ++ u8 subaddr; ++ enum module_type type; ++ int sethook; /* pending hook state command */ ++ int dacssrc; ++ struct wcxb_spi_device *spi; ++ struct wcaxx_mod_poll *mod_poll; ++}; ++ ++struct _device_desc { ++ const char *name; ++ unsigned int ports; ++}; ++ ++static const struct _device_desc device_a8a = { "Wildcard A8A", 8}; ++static const struct _device_desc device_a8b = { "Wildcard A8B", 8}; ++static const struct _device_desc device_a4a = { "Wildcard A4A", 4}; ++static const struct _device_desc device_a4b = { "Wildcard A4B", 4}; ++ ++struct wcaxx { ++ const struct _device_desc *desc; ++ const char *board_name; ++ ++ unsigned long framecount; ++ unsigned long module_poll_time; ++ int mods_per_board; ++ ++ spinlock_t reglock; ++ struct wcaxx_module mods[NUM_MODULES]; ++ struct wcxb xb; ++ struct dahdi_span span; ++ struct wcaxx_chan *chans[NUM_MODULES]; ++ struct dahdi_echocan_state *ec[NUM_MODULES]; ++ int companding; ++ struct dahdi_device *ddev; ++ struct wcxb_spi_master *master; ++#define INITIALIZED 0 ++ unsigned long bit_flags; ++ /* 4 SPI devices that are matched to the chip selects. The 4 port ++ * modules will share a single SPI device since they use the same chip ++ * select. */ ++ struct wcxb_spi_device *spi_devices[4]; ++ struct vpm450m *vpm; ++ struct list_head card_node; ++ u16 num; ++}; ++ ++static inline bool is_pcie(const struct wcaxx *wc) ++{ ++ return (wc->desc == &device_a8b) || (wc->desc == &device_a4b); ++} ++ ++static inline bool is_four_port(const struct wcaxx *wc) ++{ ++ return (4 == wc->desc->ports); ++} ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "oct6100api/oct6100_api.h" ++ ++#define ECHOCAN_NUM_CHANS 8 ++ ++#define FLAG_DTMF (1 << 0) ++#define FLAG_MUTE (1 << 1) ++#define FLAG_ECHO (1 << 2) ++ ++#define OCT_CHIP_ID 0 ++#define OCT_MAX_TDM_STREAMS 4 ++#define OCT_TONEEVENT_BUFFER_SIZE 128 ++#define SOUT_STREAM 1 ++#define RIN_STREAM 0 ++#define SIN_STREAM 2 ++ ++static int vpmsupport = 1; ++static int wcaxx_vpm_init(struct wcaxx *wc); ++static void echocan_free(struct dahdi_chan *chan, ++ struct dahdi_echocan_state *ec); ++static const struct dahdi_echocan_features vpm_ec_features = { ++ .NLP_automatic = 1, ++ .CED_tx_detect = 1, ++ .CED_rx_detect = 1, ++}; ++ ++static const struct dahdi_echocan_ops vpm_ec_ops = { ++ .echocan_free = echocan_free, ++}; ++ ++struct vpm450m { ++ tPOCT6100_INSTANCE_API pApiInstance; ++ struct oct612x_context context; ++ UINT32 aulEchoChanHndl[32]; ++ int chanflags[32]; ++ int ecmode[32]; ++ int numchans; ++}; ++ ++static int wcaxx_oct612x_write(struct oct612x_context *context, ++ u32 address, u16 value) ++{ ++ struct wcaxx *wc = dev_get_drvdata(context->dev); ++ wcxb_set_echocan_reg(&wc->xb, address, value); ++ return 0; ++} ++ ++static int wcaxx_oct612x_read(struct oct612x_context *context, u32 address, ++ u16 *value) ++{ ++ struct wcaxx *wc = dev_get_drvdata(context->dev); ++ *value = wcxb_get_echocan_reg(&wc->xb, address); ++ return 0; ++} ++ ++static int wcaxx_oct612x_write_smear(struct oct612x_context *context, ++ u32 address, u16 value, size_t count) ++{ ++ unsigned int i; ++ struct wcaxx *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ wcxb_set_echocan_reg(&wc->xb, address + (i << 1), value); ++ return 0; ++} ++ ++static int wcaxx_oct612x_write_burst(struct oct612x_context *context, ++ u32 address, const u16 *buffer, ++ size_t count) ++{ ++ unsigned int i; ++ struct wcaxx *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ wcxb_set_echocan_reg(&wc->xb, address + (i << 1), buffer[i]); ++ return 0; ++} ++ ++static int wcaxx_oct612x_read_burst(struct oct612x_context *context, ++ u32 address, u16 *buffer, size_t count) ++{ ++ unsigned int i; ++ struct wcaxx *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ buffer[i] = wcxb_get_echocan_reg(&wc->xb, address + (i << 1)); ++ return 0; ++} ++ ++static const struct oct612x_ops wcaxx_oct612x_ops = { ++ .write = wcaxx_oct612x_write, ++ .read = wcaxx_oct612x_read, ++ .write_smear = wcaxx_oct612x_write_smear, ++ .write_burst = wcaxx_oct612x_write_burst, ++ .read_burst = wcaxx_oct612x_read_burst, ++}; ++ ++ ++static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ ++ if (vpm450m->ecmode[channel] == mode) ++ return; ++ modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); ++ if (!modify) { ++ pr_notice("Unable to allocate memory for setec!\n"); ++ return; ++ } ++ Oct6100ChannelModifyDef(modify); ++ modify->ulEchoOperationMode = mode; ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n", ++ vpm450m->aulEchoChanHndl[channel], channel, ulResult); ++ } else { ++#ifdef OCTASIC_DEBUG ++ pr_debug("Echo can on channel %d set to %d\n", channel, mode); ++#endif ++ vpm450m->ecmode[channel] = mode; ++ } ++ kfree(modify); ++} ++ ++static void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen) ++{ ++ if (eclen) { ++ vpm450m->chanflags[channel] |= FLAG_ECHO; ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_NORMAL); ++ } else { ++ vpm450m->chanflags[channel] &= ~FLAG_ECHO; ++ if (vpm450m->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) { ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_HT_RESET); ++ } else { ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_POWER_DOWN); ++ } ++ } ++} ++ ++static UINT32 tdmmode_chan_to_slot_map(int mode, int channel) ++{ ++ /* Four phases on the tdm bus, skip three of them per channel */ ++ /* Due to a bug in the octasic, we had to move the data onto phase 2 */ ++ return 1+(channel*4); ++} ++ ++static int echocan_initialize_channel(struct vpm450m *vpm, ++ int channel, int mode) ++{ ++ tOCT6100_CHANNEL_OPEN ChannelOpen; ++ UINT32 law_to_use = cOCT6100_PCM_U_LAW; ++ UINT32 tdmslot_setting; ++ UINT32 ulResult; ++ ++ if (0 > channel || ECHOCAN_NUM_CHANS <= channel) ++ return -1; ++ ++ tdmslot_setting = tdmmode_chan_to_slot_map(mode, channel); ++ ++ /* Fill Open channel structure with defaults */ ++ Oct6100ChannelOpenDef(&ChannelOpen); ++ ++ /* Assign the handle memory.*/ ++ ChannelOpen.pulChannelHndl = &vpm->aulEchoChanHndl[channel]; ++ ChannelOpen.ulUserChanId = channel; ++ /* Enable Tone disabling for Fax and Modems */ ++ ChannelOpen.fEnableToneDisabler = TRUE; ++ ++ /* Passthrough TDM data by default, no echocan */ ++ ChannelOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; ++ ++ /* Configure the TDM settings.*/ ++ /* Input from the framer */ ++ ChannelOpen.TdmConfig.ulSinStream = SIN_STREAM; ++ ChannelOpen.TdmConfig.ulSinTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulSinPcmLaw = law_to_use; ++ ++ /* Input from the Host (pre-framer) */ ++ ChannelOpen.TdmConfig.ulRinStream = RIN_STREAM; ++ ChannelOpen.TdmConfig.ulRinTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulRinPcmLaw = law_to_use; ++ ++ /* Output to the Host */ ++ ChannelOpen.TdmConfig.ulSoutStream = SOUT_STREAM; ++ ChannelOpen.TdmConfig.ulSoutTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulSoutPcmLaw = law_to_use; ++ ++ /* From asterisk after echo-cancellation - goes nowhere */ ++ ChannelOpen.TdmConfig.ulRoutStream = cOCT6100_UNASSIGNED; ++ ChannelOpen.TdmConfig.ulRoutTimeslot = cOCT6100_UNASSIGNED; ++ ChannelOpen.TdmConfig.ulRoutPcmLaw = law_to_use; ++ ++ /* Set the desired VQE features.*/ ++ ChannelOpen.VqeConfig.fEnableNlp = TRUE; ++ ChannelOpen.VqeConfig.fRinDcOffsetRemoval = TRUE; ++ ChannelOpen.VqeConfig.fSinDcOffsetRemoval = TRUE; ++ ChannelOpen.VqeConfig.ulComfortNoiseMode = ++ cOCT6100_COMFORT_NOISE_NORMAL; ++ ++ /* Open the channel.*/ ++ ulResult = Oct6100ChannelOpen(vpm->pApiInstance, &ChannelOpen); ++ ++ return ulResult; ++} ++ ++static struct vpm450m *init_vpm450m(struct wcaxx *wc, int isalaw, ++ const struct firmware *firmware) ++{ ++ tOCT6100_CHIP_OPEN *ChipOpen; ++ tOCT6100_GET_INSTANCE_SIZE InstanceSize; ++ tOCT6100_CHANNEL_OPEN *ChannelOpen; ++ UINT32 ulResult; ++ struct vpm450m *vpm450m; ++ int x, i; ++ ++ vpm450m = kzalloc(sizeof(struct vpm450m), GFP_KERNEL); ++ if (!vpm450m) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate vpm450m struct\n"); ++ return NULL; ++ } ++ ++ vpm450m->context.dev = &wc->xb.pdev->dev; ++ vpm450m->context.ops = &wcaxx_oct612x_ops; ++ ++ ChipOpen = kzalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL); ++ if (!ChipOpen) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate ChipOpen\n"); ++ kfree(vpm450m); ++ return NULL; ++ } ++ ++ ChannelOpen = kzalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL); ++ if (!ChannelOpen) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate ChannelOpen\n"); ++ kfree(vpm450m); ++ kfree(ChipOpen); ++ return NULL; ++ } ++ ++ for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++) ++ vpm450m->ecmode[x] = -1; ++ ++ vpm450m->numchans = ECHOCAN_NUM_CHANS; ++ dev_info(&wc->xb.pdev->dev, "Echo cancellation for %d channels\n", ++ wc->desc->ports); ++ ++ Oct6100ChipOpenDef(ChipOpen); ++ ChipOpen->pProcessContext = &vpm450m->context; ++ ++ /* Change default parameters as needed */ ++ /* upclk oscillator is at 33.33 Mhz */ ++ ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; ++ ++ /* mclk will be generated by internal PLL at 133 Mhz */ ++ ChipOpen->fEnableMemClkOut = TRUE; ++ ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; ++ ++ /* User defined Chip ID.*/ ++ ChipOpen->ulUserChipId = OCT_CHIP_ID; ++ ++ /* Set the maximums that the chip needs to support */ ++ ChipOpen->ulMaxChannels = vpm450m->numchans; ++ ChipOpen->ulMaxTdmStreams = OCT_MAX_TDM_STREAMS; ++ ++ /* External Memory Settings */ ++ /* Use DDR memory.*/ ++ ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; ++ ChipOpen->ulNumMemoryChips = 1; ++ ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; ++ ++ ChipOpen->pbyImageFile = (PUINT8) firmware->data; ++ ChipOpen->ulImageSize = firmware->size; ++ ++ /* Set TDM data stream frequency */ ++ for (i = 0; i < ChipOpen->ulMaxTdmStreams; i++) ++ ChipOpen->aulTdmStreamFreqs[i] = cOCT6100_TDM_STREAM_FREQ_8MHZ; ++ ++ /* Configure TDM sampling */ ++ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; ++ /* Disable to save RAM footprint space */ ++ ChipOpen->fEnableChannelRecording = FALSE; ++ ++ /* In this example we will maintain the API using polling so interrupts ++ * must be disabled */ ++ ChipOpen->InterruptConfig.ulErrorH100Config = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulErrorMemoryConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulFatalGeneralConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulFatalMemoryConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ++ ChipOpen->ulSoftToneEventsBufSize = OCT_TONEEVENT_BUFFER_SIZE; ++ ++ /* Inserting default values into tOCT6100_GET_INSTANCE_SIZE structure ++ * parameters. */ ++ Oct6100GetInstanceSizeDef(&InstanceSize); ++ ++ /* Get the size of the OCT6100 instance structure. */ ++ ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize); ++ if (ulResult != cOCT6100_ERR_OK) { ++ dev_info(&wc->xb.pdev->dev, "Unable to get instance size: %x\n", ++ ulResult); ++ return NULL; ++ } ++ ++ vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); ++ if (!vpm450m->pApiInstance) { ++ dev_info(&wc->xb.pdev->dev, ++ "Out of memory (can't allocate %d bytes)!\n", ++ InstanceSize.ulApiInstanceSize); ++ return NULL; ++ } ++ ++ /* Perform the actual configuration of the chip. */ ++ wcxb_enable_echocan_dram(&wc->xb); ++ ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen); ++ if (ulResult != cOCT6100_ERR_OK) { ++ dev_info(&wc->xb.pdev->dev, "Unable to Oct6100ChipOpen: %x\n", ++ ulResult); ++ return NULL; ++ } ++ ++ /* OCT6100 is now booted and channels can be opened */ ++ /* Open all channels */ ++ for (i = 0; i < ECHOCAN_NUM_CHANS; i++) { ++ ulResult = echocan_initialize_channel(vpm450m, i, isalaw); ++ if (0 != ulResult) { ++ dev_info(&wc->xb.pdev->dev, ++ "Unable to echocan_initialize_channel: %x\n", ++ ulResult); ++ return NULL; ++ } ++ } ++ ++ if (vpmsupport) ++ wcxb_enable_echocan(&wc->xb); ++ else ++ wcxb_disable_echocan(&wc->xb); ++ ++ kfree(ChipOpen); ++ kfree(ChannelOpen); ++ return vpm450m; ++} ++ ++static void release_vpm450m(struct vpm450m *vpm450m) ++{ ++ UINT32 ulResult; ++ tOCT6100_CHIP_CLOSE ChipClose; ++ ++ Oct6100ChipCloseDef(&ChipClose); ++ ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose); ++ if (ulResult != cOCT6100_ERR_OK) ++ pr_notice("Failed to close chip, code %08x!\n", ulResult); ++ vfree(vpm450m->pApiInstance); ++ kfree(vpm450m); ++} ++ ++static const char *wcaxx_echocan_name(const struct dahdi_chan *chan) ++{ ++ struct wcaxx *wc = chan->pvt; ++ if (wc->vpm) ++ return "VPMOCT032"; ++ else ++ return NULL; ++} ++ ++static int wcaxx_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ struct wcaxx *wc = chan->pvt; ++ int channel; ++ const struct dahdi_echocan_ops *ops; ++ const struct dahdi_echocan_features *features; ++ ++ if (!vpmsupport || !wc->vpm) ++ return -ENODEV; ++ ++ ops = &vpm_ec_ops; ++ features = &vpm_ec_features; ++ ++ if (ecp->param_count > 0) { ++ dev_warn(&wc->xb.pdev->dev, ++ "%s echo canceller does not support parameters; failing request\n", ++ chan->ec_factory->get_name(chan)); ++ return -EINVAL; ++ } ++ ++ *ec = wc->ec[chan->chanpos - 1]; ++ (*ec)->ops = ops; ++ (*ec)->features = *features; ++ ++ channel = chan->chanpos-1; ++ ++ if (wc->vpm) ++ vpm450m_setec(wc->vpm, channel, ecp->tap_length); ++ return 0; ++} ++ ++static void echocan_free(struct dahdi_chan *chan, ++ struct dahdi_echocan_state *ec) ++{ ++ struct wcaxx *wc = chan->pvt; ++ int channel; ++ ++ memset(ec, 0, sizeof(*ec)); ++ ++ channel = chan->chanpos - 1; ++ ++ if (wc->vpm) ++ vpm450m_setec(wc->vpm, channel, 0); ++} ++ ++static int wcaxx_vpm_init(struct wcaxx *wc) ++{ ++ int companding = 0; ++ struct firmware embedded_firmware; ++ const struct firmware *firmware = &embedded_firmware; ++#if !defined(HOTPLUG_FIRMWARE) ++ extern void _binary_dahdi_fw_oct6114_032_bin_size; ++ extern u8 _binary_dahdi_fw_oct6114_032_bin_start[]; ++#else ++ static const char oct032_firmware[] = "dahdi-fw-oct6114-032.bin"; ++#endif ++ int res; ++ ++ if (!vpmsupport) { ++ dev_info(&wc->xb.pdev->dev, "VPM: Support Disabled\n"); ++ return -1; ++ } ++ ++ wcxb_reset_echocan(&wc->xb); ++ if (!wcxb_is_echocan_present(&wc->xb)) { ++ dev_info(&wc->xb.pdev->dev, "VPM not present.\n"); ++ return -1; ++ } ++ ++#if defined(HOTPLUG_FIRMWARE) ++ res = request_firmware(&firmware, oct032_firmware, &wc->xb.pdev->dev); ++ if ((0 != res) || !firmware) { ++ dev_notice(&wc->xb.pdev->dev, ++ "VPM450: firmware %s not available from userspace\n", ++ oct032_firmware); ++ return -1; ++ } ++#else ++ embedded_firmware.data = _binary_dahdi_fw_oct6114_032_bin_start; ++ /* Yes... this is weird. objcopy gives us a symbol containing ++ the size of the firmware, not a pointer a variable containing ++ the size. The only way we can get the value of the symbol ++ is to take its address, so we define it as a pointer and ++ then cast that value to the proper type. ++ */ ++ embedded_firmware.size = (size_t)&_binary_dahdi_fw_oct6114_032_bin_size; ++#endif ++ ++ wc->vpm = init_vpm450m(wc, companding, firmware); ++ if (!wc->vpm) { ++ dev_notice(&wc->xb.pdev->dev, "VPM450: Failed to initialize\n"); ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ return -EIO; ++ } ++ ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ ++ dev_info(&wc->xb.pdev->dev, ++ "VPM450: Present and operational servicing %d span\n", 1); ++ ++ return 0; ++} ++ ++static inline bool is_initialized(struct wcaxx *wc) ++{ ++ return (test_bit(INITIALIZED, &wc->bit_flags) > 0); ++} ++ ++static inline struct wcxb_spi_device * ++_get_spi_device_for_8_port(struct wcaxx *wc, unsigned int port, bool altcs) ++{ ++ switch (port) { ++ case 0: ++ return wc->spi_devices[0]; ++ case 1: ++ return (altcs) ? wc->spi_devices[0] : wc->spi_devices[1]; ++ case 2: ++ WARN_ON(!altcs); ++ return wc->spi_devices[0]; ++ case 3: ++ WARN_ON(!altcs); ++ return wc->spi_devices[0]; ++ case 4: ++ return wc->spi_devices[2]; ++ case 5: ++ return (altcs) ? wc->spi_devices[2] : wc->spi_devices[3]; ++ case 6: ++ WARN_ON(!altcs); ++ return wc->spi_devices[2]; ++ case 7: ++ WARN_ON(!altcs); ++ return wc->spi_devices[2]; ++ default: ++ WARN_ON(1); ++ return wc->spi_devices[0]; ++ } ++} ++ ++static inline struct wcxb_spi_device * ++_get_spi_device_for_4_port(struct wcaxx *wc, unsigned int port) ++{ ++ if (port > 3) { ++ WARN_ON(1); ++ return wc->spi_devices[0]; ++ } else { ++ return wc->spi_devices[port]; ++ } ++} ++ ++static inline struct wcxb_spi_device * ++get_spi_device_for_port(struct wcaxx *wc, unsigned int port, bool altcs) ++{ ++ if (is_four_port(wc)) ++ return _get_spi_device_for_4_port(wc, port); ++ else ++ return _get_spi_device_for_8_port(wc, port, altcs); ++} ++ ++static u8 wcaxx_getreg(struct wcaxx *wc, ++ struct wcaxx_module *const mod, int addr); ++static void wcaxx_setreg(struct wcaxx *wc, struct wcaxx_module *const mod, ++ int addr, int val); ++ ++static DEFINE_MUTEX(card_list_lock); ++static LIST_HEAD(card_list); ++ ++#include "adt_lec.h" ++ ++/* ++ Experimental max loop current limit for the proslic ++ Loop current limit is from 20 mA to 41 mA in steps of 3 ++ (according to datasheet) ++ So set the value below to: ++ 0x00 : 20mA (default) ++ 0x01 : 23mA ++ 0x02 : 26mA ++ 0x03 : 29mA ++ 0x04 : 32mA ++ 0x05 : 35mA ++ 0x06 : 37mA ++ 0x07 : 41mA ++*/ ++static int loopcurrent = 20; ++ ++/* Following define is a logical exclusive OR to determine if the polarity of ++ * an fxs line is to be reversed. The items taken into account are: ++ * overall polarity reversal for the module, ++ * polarity reversal for the port, ++ * and the state of the line reversal MWI indicator ++ */ ++#define POLARITY_XOR(fxs) \ ++ ((reversepolarity != 0) ^ ((fxs)->reversepolarity != 0) ^ \ ++ ((fxs)->vmwi_linereverse != 0)) ++ ++static int reversepolarity; ++ ++static alpha indirect_regs[] = { ++ {0, 255, "DTMF_ROW_0_PEAK", 0x55C2}, ++ {1, 255, "DTMF_ROW_1_PEAK", 0x51E6}, ++ {2, 255, "DTMF_ROW2_PEAK", 0x4B85}, ++ {3, 255, "DTMF_ROW3_PEAK", 0x4937}, ++ {4, 255, "DTMF_COL1_PEAK", 0x3333}, ++ {5, 255, "DTMF_FWD_TWIST", 0x0202}, ++ {6, 255, "DTMF_RVS_TWIST", 0x0202}, ++ {7, 255, "DTMF_ROW_RATIO_TRES", 0x0198}, ++ {8, 255, "DTMF_COL_RATIO_TRES", 0x0198}, ++ {9, 255, "DTMF_ROW_2ND_ARM", 0x0611}, ++ {10, 255, "DTMF_COL_2ND_ARM", 0x0202}, ++ {11, 255, "DTMF_PWR_MIN_TRES", 0x00E5}, ++ {12, 255, "DTMF_OT_LIM_TRES", 0x0A1C}, ++ {13, 0, "OSC1_COEF", 0x7B30}, ++ {14, 1, "OSC1X", 0x0063}, ++ {15, 2, "OSC1Y", 0x0000}, ++ {16, 3, "OSC2_COEF", 0x7870}, ++ {17, 4, "OSC2X", 0x007D}, ++ {18, 5, "OSC2Y", 0x0000}, ++ {19, 6, "RING_V_OFF", 0x0000}, ++ {20, 7, "RING_OSC", 0x7EF0}, ++ {21, 8, "RING_X", 0x0160}, ++ {22, 9, "RING_Y", 0x0000}, ++ {23, 255, "PULSE_ENVEL", 0x2000}, ++ {24, 255, "PULSE_X", 0x2000}, ++ {25, 255, "PULSE_Y", 0x0000}, ++ {26, 13, "RECV_DIGITAL_GAIN", 0x2000}, /* playback volume set lower */ ++ {27, 14, "XMIT_DIGITAL_GAIN", 0x4000}, ++ {28, 15, "LOOP_CLOSE_TRES", 0x1000}, ++ {29, 16, "RING_TRIP_TRES", 0x3600}, ++ {30, 17, "COMMON_MIN_TRES", 0x1000}, ++ {31, 18, "COMMON_MAX_TRES", 0x0200}, ++ {32, 19, "PWR_ALARM_Q1Q2", 0x07C0}, ++ {33, 20, "PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */}, ++ {34, 21, "PWR_ALARM_Q5Q6", 0x1B80}, ++ {35, 22, "LOOP_CLOSURE_FILTER", 0x8000}, ++ {36, 23, "RING_TRIP_FILTER", 0x0320}, ++ {37, 24, "TERM_LP_POLE_Q1Q2", 0x008C}, ++ {38, 25, "TERM_LP_POLE_Q3Q4", 0x0100}, ++ {39, 26, "TERM_LP_POLE_Q5Q6", 0x0010}, ++ {40, 27, "CM_BIAS_RINGING", 0x0C00}, ++ {41, 64, "DCDC_MIN_V", 0x0C00}, ++ {42, 255, "DCDC_XTRA", 0x1000}, ++ {43, 66, "LOOP_CLOSE_TRES_LOW", 0x1000}, ++}; ++ ++/* Undefine to enable Power alarm / Transistor debug -- note: do not ++ enable for normal operation! */ ++/* #define PAQ_DEBUG */ ++ ++#define DEBUG_CARD (1 << 0) ++#define DEBUG_ECHOCAN (1 << 1) ++ ++#include "fxo_modes.h" ++ ++static inline struct dahdi_chan * ++get_dahdi_chan(const struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ return wc->span.chans[mod->card]; ++} ++ ++static inline void mod_hooksig(struct wcaxx *wc, ++ struct wcaxx_module *mod, ++ enum dahdi_rxsig rxsig) ++{ ++ dahdi_hooksig(get_dahdi_chan(wc, mod), rxsig); ++} ++ ++static void wcaxx_release(struct wcaxx *wc); ++ ++static int fxovoltage; ++static unsigned int battdebounce; ++static unsigned int battalarm; ++static unsigned int battthresh; ++static int debug; ++static int int_mode; ++#ifdef DEBUG ++static int robust; ++static int digitalloopback; ++#endif ++static int lowpower; ++static int boostringer; ++static int fastringer; ++static int _opermode; ++static char *opermode = "FCC"; ++static int fxshonormode; ++static int alawoverride; ++static char *companding = "auto"; ++static int fastpickup = -1; /* -1 auto, 0 no, 1 yes */ ++static int fxotxgain; ++static int fxorxgain; ++static int fxstxgain; ++static int fxsrxgain; ++static int nativebridge; ++static int ringdebounce = DEFAULT_RING_DEBOUNCE; ++static int latency = WCXB_DEFAULT_LATENCY; ++static unsigned int max_latency = WCXB_DEFAULT_MAXLATENCY; ++static int forceload; ++ ++#define MS_PER_HOOKCHECK (1) ++#define NEONMWI_ON_DEBOUNCE (100/MS_PER_HOOKCHECK) ++static int neonmwi_monitor; ++static int neonmwi_level = 75; /* neon mwi trip voltage */ ++static int neonmwi_envelope = 10; ++/* Time in milliseconds the monitor is checked before saying no message is ++ * waiting */ ++static int neonmwi_offlimit = 16000; ++static int neonmwi_offlimit_cycles; ++ ++static int wcaxx_init_proslic(struct wcaxx *wc, ++ struct wcaxx_module *const mod, int fast, ++ int manual, int sane); ++ ++ ++struct wcaxx_setreg_memory { ++ struct wcxb_spi_message m; ++ struct wcxb_spi_transfer t; ++ u8 buffer[3]; ++}; ++ ++/** ++ * wcxb_spi_complete_setreg - Cleanup after a SPI write. ++ * ++ * We don't care about the results of setreg. Just go ahead and free up the ++ * messages. ++ * ++ */ ++static void wcaxx_complete_setreg(void *arg) ++{ ++ struct wcaxx_setreg_memory *setreg = arg; ++ kfree(setreg); ++} ++ ++static void wcaxx_setreg(struct wcaxx *wc, struct wcaxx_module *mod, ++ int addr, int val) ++{ ++ struct wcaxx_setreg_memory *setreg = kzalloc(sizeof(*setreg), ++ GFP_ATOMIC); ++ struct wcxb_spi_message *const m = &setreg->m; ++ struct wcxb_spi_transfer *const t = &setreg->t; ++ if (!setreg) { ++ WARN_ON_ONCE(!setreg); ++ return; ++ } ++ wcxb_spi_message_init(m); ++ t->tx_buf = setreg->buffer; ++ wcxb_spi_message_add_tail(t, m); ++ if (FXO == mod->type) { ++ static const int ADDRS[4] = {0x00, 0x08, 0x04, 0x0c}; ++ setreg->buffer[0] = 0x20 | ADDRS[mod->subaddr]; ++ } else { ++ setreg->buffer[0] = 1 << mod->subaddr; ++ } ++ setreg->buffer[1] = (addr) & 0x7f; ++ setreg->buffer[2] = val; ++ t->len = 3; ++ m->complete = &wcaxx_complete_setreg; ++ m->arg = setreg; ++ wcxb_spi_async(mod->spi, m); ++} ++ ++/** ++ * wcaxx_fsxinit - Initilize all SPI devices to 3 byte mode. ++ * ++ * All the modules on the card need to be initialized to 3 byte mode in order to ++ * talk to the daisy-chained SLIC / DAA on the quad modules. ++ * ++ */ ++static void wcaxx_fxsinit(struct wcxb_spi_device *const spi) ++{ ++ int res; ++ u8 data_byte[2] = {0, 0x80}; ++ struct wcxb_spi_transfer t; ++ struct wcxb_spi_message m; ++ memset(&t, 0, sizeof(t)); ++ wcxb_spi_message_init(&m); ++ t.tx_buf = data_byte; ++ t.len = sizeof(data_byte); ++ wcxb_spi_message_add_tail(&t, &m); ++ res = wcxb_spi_sync(spi, &m); ++ WARN_ON_ONCE(0 != res); ++ return; ++} ++ ++static u8 ++wcaxx_getreg(struct wcaxx *wc, struct wcaxx_module *const mod, int addr) ++{ ++ int res; ++ u8 buffer[3]; ++ struct wcxb_spi_message m; ++ struct wcxb_spi_transfer t; ++ memset(&t, 0, sizeof(t)); ++ wcxb_spi_message_init(&m); ++ ++ t.tx_buf = t.rx_buf = buffer; ++ t.len = sizeof(buffer); ++ wcxb_spi_message_add_tail(&t, &m); ++ ++ if (FXO == mod->type) { ++ static const int ADDRS[4] = {0x00, 0x08, 0x04, 0x0c}; ++ buffer[0] = 0x60 | ADDRS[mod->subaddr]; ++ buffer[1] = addr & 0x7f; ++ buffer[2] = 0; ++ } else { ++ buffer[0] = 1 << mod->subaddr; ++ buffer[1] = (addr | 0x80) & 0xff; ++ buffer[2] = 0; ++ } ++ res = wcxb_spi_sync(mod->spi, &m); ++ WARN_ON_ONCE(0 != res); ++ return buffer[2]; ++} ++ ++static int wcaxx_getregs(struct wcaxx *wc, struct wcaxx_module *const mod, ++ int *const addresses, const size_t count) ++{ ++ int x; ++ for (x = 0; x < count; ++x) ++ addresses[x] = wcaxx_getreg(wc, mod, addresses[x]); ++ return 0; ++} ++ ++static int wait_access(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ unsigned char data = 0; ++ int count = 0; ++ ++ #define MAX 10 /* attempts */ ++ ++ /* Wait for indirect access */ ++ while (count++ < MAX) { ++ data = wcaxx_getreg(wc, mod, I_STATUS); ++ if (!data) ++ return 0; ++ } ++ ++ if (count > (MAX-1)) { ++ dev_notice(&wc->xb.pdev->dev, ++ " ##### Loop error (%02x) #####\n", data); ++ } ++ ++ return 0; ++} ++ ++static unsigned char translate_3215(unsigned char address) ++{ ++ int x; ++ for (x = 0; x < ARRAY_SIZE(indirect_regs); x++) { ++ if (indirect_regs[x].address == address) { ++ address = indirect_regs[x].altaddr; ++ break; ++ } ++ } ++ return address; ++} ++ ++static int wcaxx_proslic_setreg_indirect(struct wcaxx *wc, ++ struct wcaxx_module *const mod, ++ unsigned char address, ++ unsigned short data) ++{ ++ int res = -1; ++ ++ address = translate_3215(address); ++ if (address == 255) ++ return 0; ++ ++ if (!wait_access(wc, mod)) { ++ wcaxx_setreg(wc, mod, IDA_LO, (u8)(data & 0xFF)); ++ wcaxx_setreg(wc, mod, IDA_HI, (u8)((data & 0xFF00)>>8)); ++ wcaxx_setreg(wc, mod, IAA, address); ++ res = 0; ++ }; ++ return res; ++} ++ ++static int wcaxx_proslic_getreg_indirect(struct wcaxx *wc, ++ struct wcaxx_module *const mod, ++ unsigned char address) ++{ ++ int res = -1; ++ char *p = NULL; ++ ++ address = translate_3215(address); ++ if (address == 255) ++ return 0; ++ ++ if (!wait_access(wc, mod)) { ++ wcaxx_setreg(wc, mod, IAA, address); ++ if (!wait_access(wc, mod)) { ++ int addresses[2] = {IDA_LO, IDA_HI}; ++ wcaxx_getregs(wc, mod, addresses, ++ ARRAY_SIZE(addresses)); ++ res = addresses[0] | (addresses[1] << 8); ++ } else ++ p = "Failed to wait inside\n"; ++ } else ++ p = "failed to wait\n"; ++ if (p) ++ dev_notice(&wc->xb.pdev->dev, "%s", p); ++ return res; ++} ++ ++static int ++wcaxx_proslic_init_indirect_regs(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ unsigned char i; ++ ++ for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) { ++ if (wcaxx_proslic_setreg_indirect(wc, mod, ++ indirect_regs[i].address, ++ indirect_regs[i].initial)) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int wcaxx_proslic_verify_indirect_regs(struct wcaxx *wc, ++ struct wcaxx_module *mod) ++{ ++ int passed = 1; ++ unsigned short i, initial; ++ int j; ++ ++ for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) { ++ j = wcaxx_proslic_getreg_indirect(wc, mod, ++ (u8)indirect_regs[i].address); ++ if (j < 0) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Failed to read indirect register %d\n", i); ++ return -1; ++ } ++ initial = indirect_regs[i].initial; ++ ++ if ((j != initial) && (indirect_regs[i].altaddr != 255)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "!!!!!!! %s iREG %X = %X should be %X\n", ++ indirect_regs[i].name, ++ indirect_regs[i].address, j, initial); ++ passed = 0; ++ } ++ } ++ ++ if (passed) { ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Init Indirect Registers completed successfully.\n"); ++ } ++ } else { ++ dev_notice(&wc->xb.pdev->dev, ++ " !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++/** ++ * wcaxx_proslic_check_oppending - ++ * ++ * Ensures that a write to the line feed register on the SLIC has been ++ * processed. If it hasn't after the timeout value, then it will resend the ++ * command and wait for another timeout period. ++ * ++ */ ++static void wcaxx_proslic_check_oppending(struct wcaxx *wc, ++ struct wcaxx_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ unsigned long flags; ++ ++ if (!(fxs->lasttxhook & SLIC_LF_OPPENDING)) ++ return; ++ ++ /* Monitor the Pending LF state change, for the next 100ms */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ if (!(fxs->lasttxhook & SLIC_LF_OPPENDING)) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return; ++ } ++ ++ if ((fxs->linefeed_control_shadow & SLIC_LF_SETMASK) == ++ (fxs->lasttxhook & SLIC_LF_SETMASK)) { ++ fxs->lasttxhook &= SLIC_LF_SETMASK; ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "SLIC_LF OK: card=%d shadow=%02x " ++ "lasttxhook=%02x framecount=%ld\n", mod->card, ++ fxs->linefeed_control_shadow, ++ fxs->lasttxhook, wc->framecount); ++ } ++ } else if (time_after(wc->framecount, fxs->oppending_timeout)) { ++ /* Check again in 100 ms */ ++ fxs->oppending_timeout = wc->framecount + 100; ++ ++ wcaxx_setreg(wc, mod, LINE_STATE, fxs->lasttxhook); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "SLIC_LF RETRY: card=%d shadow=%02x " ++ "lasttxhook=%02x framecount=%ld\n", mod->card, ++ fxs->linefeed_control_shadow, ++ fxs->lasttxhook, wc->framecount); ++ } ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++/* 256ms interrupt */ ++static void wcaxx_proslic_recheck_sanity(struct wcaxx *wc, ++ struct wcaxx_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ int res; ++ unsigned long flags; ++ const unsigned int MAX_ALARMS = 10; ++ ++#ifdef PAQ_DEBUG ++ res = mod->isrshadow[1]; ++ res &= ~0x3; ++ if (res) { ++ mod->isrshadow[1] = 0; ++ fxs->palarms++; ++ if (fxs->palarms < MAX_ALARMS) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Power alarm (%02x) on module %d, resetting!\n", ++ res, card + 1); ++ mod->sethook = CMD_WR(19, res); ++ /* Update shadow register to avoid extra power alarms ++ * until next read */ ++ mod->isrshadow[1] = 0; ++ } else { ++ if (fxs->palarms == MAX_ALARMS) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Too many power alarms on card %d, NOT resetting!\n", ++ card + 1); ++ } ++ } ++ } ++#else ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ /* reg 64 has to be zero at last isr read */ ++ res = !fxs->linefeed_control_shadow && ++ !(fxs->lasttxhook & SLIC_LF_OPPENDING) && /* not a transition */ ++ fxs->lasttxhook; /* not an intended zero */ ++ ++ if (res) { ++ fxs->palarms++; ++ if (fxs->palarms < MAX_ALARMS) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Power alarm on module %d, resetting!\n", ++ mod->card + 1); ++ if (fxs->lasttxhook == SLIC_LF_RINGING) { ++ fxs->lasttxhook = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ } ++ fxs->lasttxhook |= SLIC_LF_OPPENDING; ++ mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ fxs->oppending_timeout = wc->framecount + 100; ++ ++ /* Update shadow register to avoid extra power alarms ++ * until next read */ ++ fxs->linefeed_control_shadow = fxs->lasttxhook; ++ } else { ++ if (fxs->palarms == MAX_ALARMS) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Too many power alarms on card %d, " ++ "NOT resetting!\n", mod->card + 1); ++ } ++ } ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++#endif ++} ++ ++static inline bool is_fxo_ringing(const struct fxo *const fxo) ++{ ++ return ((fxo->hook_ring_shadow & 0x60) && ++ ((fxo->battery_state == BATTERY_PRESENT) || ++ (fxo->battery_state == BATTERY_DEBOUNCING_LOST))); ++} ++ ++static inline bool is_fxo_ringing_positive(const struct fxo *const fxo) ++{ ++ return (((fxo->hook_ring_shadow & 0x60) == 0x20) && ++ ((fxo->battery_state == BATTERY_PRESENT) || ++ (fxo->battery_state == BATTERY_DEBOUNCING_LOST))); ++} ++ ++static inline bool is_fxo_ringing_negative(const struct fxo *const fxo) ++{ ++ return (((fxo->hook_ring_shadow & 0x60) == 0x40) && ++ ((fxo->battery_state == BATTERY_PRESENT) || ++ (fxo->battery_state == BATTERY_DEBOUNCING_LOST))); ++} ++ ++static inline void set_ring(struct fxo *fxo, enum ring_detector_state new) ++{ ++ fxo->ring_state = new; ++} ++ ++static void wcaxx_fxo_ring_detect(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ static const unsigned int POLARITY_CHANGES_NEEDED = 2; ++ ++ /* Look for ring status bits (Ring Detect Signal Negative and Ring ++ * Detect Signal Positive) to transition back and forth ++ * POLARITY_CHANGES_NEEDED times to indicate that a ring is occurring. ++ * Provide some number of samples to allow for the transitions to occur ++ * before giving up. NOTE: neon mwi voltages will trigger one of these ++ * bits to go active but not to have transitions between the two bits ++ * (i.e. no negative to positive or positive to negative traversals) */ ++ ++ switch (fxo->ring_state) { ++ case DEBOUNCING_RINGING_POSITIVE: ++ if (is_fxo_ringing_negative(fxo)) { ++ if (++fxo->ring_polarity_change_count > ++ POLARITY_CHANGES_NEEDED) { ++ mod_hooksig(wc, mod, DAHDI_RXSIG_RING); ++ set_ring(fxo, RINGING); ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "RING on %s!\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ } else { ++ set_ring(fxo, DEBOUNCING_RINGING_NEGATIVE); ++ } ++ } else if (time_after(wc->framecount, ++ fxo->ringdebounce_timer)) { ++ set_ring(fxo, RINGOFF); ++ } ++ break; ++ case DEBOUNCING_RINGING_NEGATIVE: ++ if (is_fxo_ringing_positive(fxo)) { ++ if (++fxo->ring_polarity_change_count > ++ POLARITY_CHANGES_NEEDED) { ++ mod_hooksig(wc, mod, DAHDI_RXSIG_RING); ++ set_ring(fxo, RINGING); ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "RING on %s!\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ } else { ++ set_ring(fxo, DEBOUNCING_RINGING_POSITIVE); ++ } ++ } else if (time_after(wc->framecount, ++ fxo->ringdebounce_timer)) { ++ set_ring(fxo, RINGOFF); ++ } ++ break; ++ case RINGING: ++ if (!is_fxo_ringing(fxo)) { ++ set_ring(fxo, DEBOUNCING_RINGOFF); ++ fxo->ringdebounce_timer = ++ wc->framecount + ringdebounce / 8; ++ } ++ break; ++ case DEBOUNCING_RINGOFF: ++ if (!is_fxo_ringing(fxo)) { ++ if (time_after(wc->framecount, ++ fxo->ringdebounce_timer)) { ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "NO RING on %s!\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK); ++ set_ring(fxo, RINGOFF); ++ } ++ } else { ++ set_ring(fxo, RINGING); ++ } ++ break; ++ case RINGOFF: ++ if (is_fxo_ringing(fxo)) { ++ /* Look for positive/negative crossings in ring status ++ * reg */ ++ if (is_fxo_ringing_positive(fxo)) ++ set_ring(fxo, DEBOUNCING_RINGING_POSITIVE); ++ else ++ set_ring(fxo, DEBOUNCING_RINGING_NEGATIVE); ++ fxo->ringdebounce_timer = ++ wc->framecount + ringdebounce / 8; ++ fxo->ring_polarity_change_count = 0; ++ } ++ break; ++ } ++} ++ ++#define MS_PER_CHECK_HOOK 1 ++static void ++wcaxx_check_battery_lost(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ /* possible existing states: ++ battery lost, no debounce timer ++ battery lost, debounce timer (going to battery present) ++ battery present or unknown, no debounce timer ++ battery present or unknown, debounce timer (going to battery lost) ++ */ ++ switch (fxo->battery_state) { ++ case BATTERY_DEBOUNCING_PRESENT_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_PRESENT: ++ fxo->battery_state = BATTERY_LOST; ++ break; ++ case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ break; ++ case BATTERY_UNKNOWN: ++ mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK); ++ case BATTERY_PRESENT: ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM: ++ case BATTERY_DEBOUNCING_LOST: /* Intentional drop through */ ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "NO BATTERY on %d/%d!\n", ++ wc->span.spanno, ++ mod->card + 1); ++ } ++#ifdef JAPAN ++ if (!wc->ohdebounce && wc->offhook) { ++ dahdi_hooksig(wc->aspan->chans[card], ++ DAHDI_RXSIG_ONHOOK); ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "Signalled On Hook\n"); ++ } ++#ifdef ZERO_BATT_RING ++ wc->onhook++; ++#endif ++ } ++#else ++ mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK); ++#endif ++ /* set the alarm timer, taking into account that part ++ * of its time period has already passed while ++ * debouncing occurred */ ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ } ++ break; ++ case BATTERY_DEBOUNCING_LOST_ALARM: ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ fxo->battery_state = BATTERY_LOST; ++ dahdi_alarm_channel(get_dahdi_chan(wc, mod), ++ DAHDI_ALARM_RED); ++ } ++ break; ++ case BATTERY_LOST: ++ break; ++ } ++} ++ ++static void ++wcaxx_check_battery_present(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ switch (fxo->battery_state) { ++ case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM: ++ case BATTERY_DEBOUNCING_PRESENT: /* intentional drop through */ ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "BATTERY on %d/%d (%s)!\n", ++ wc->span.spanno, mod->card + 1, ++ (fxo->line_voltage_status < 0) ? ++ "-" : "+"); ++ } ++#ifdef ZERO_BATT_RING ++ if (wc->onhook) { ++ wc->onhook = 0; ++ dahdi_hooksig(wc->aspan->chans[card], ++ DAHDI_RXSIG_OFFHOOK); ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "Signalled Off Hook\n"); ++ } ++ } ++#else ++ mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK); ++#endif ++ /* set the alarm timer, taking into account that part ++ * of its time period has already passed while ++ * debouncing occurred */ ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ } ++ break; ++ case BATTERY_DEBOUNCING_PRESENT_ALARM: ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ fxo->battery_state = BATTERY_PRESENT; ++ dahdi_alarm_channel(get_dahdi_chan(wc, mod), ++ DAHDI_ALARM_NONE); ++ } ++ break; ++ case BATTERY_PRESENT: ++ break; ++ case BATTERY_DEBOUNCING_LOST_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_LOST: ++ fxo->battery_state = BATTERY_PRESENT; ++ break; ++ case BATTERY_UNKNOWN: ++ mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK); ++ case BATTERY_LOST: /* intentional drop through */ ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ } ++} ++ ++static void ++wcaxx_fxo_stop_debouncing_polarity(struct wcaxx *wc, ++ struct wcaxx_module *const mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ switch (fxo->polarity_state) { ++ case UNKNOWN_POLARITY: ++ break; ++ case POLARITY_DEBOUNCE_POSITIVE: ++ fxo->polarity_state = POLARITY_NEGATIVE; ++ break; ++ case POLARITY_POSITIVE: ++ break; ++ case POLARITY_DEBOUNCE_NEGATIVE: ++ fxo->polarity_state = POLARITY_POSITIVE; ++ break; ++ case POLARITY_NEGATIVE: ++ break; ++ }; ++} ++ ++static void ++wcaxx_fxo_check_polarity(struct wcaxx *wc, struct wcaxx_module *const mod, ++ const bool positive_polarity) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ switch (fxo->polarity_state) { ++ case UNKNOWN_POLARITY: ++ fxo->polarity_state = (positive_polarity) ? POLARITY_POSITIVE : ++ POLARITY_NEGATIVE; ++ break; ++ case POLARITY_DEBOUNCE_POSITIVE: ++ if (!positive_polarity) { ++ fxo->polarity_state = POLARITY_NEGATIVE; ++ } else if (time_after(wc->framecount, fxo->poldebounce_timer)) { ++ fxo->polarity_state = POLARITY_POSITIVE; ++ dahdi_qevent_lock(get_dahdi_chan(wc, mod), ++ DAHDI_EVENT_POLARITY); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "%s: Polarity NEGATIVE -> POSITIVE\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ } ++ break; ++ case POLARITY_POSITIVE: ++ if (!positive_polarity) { ++ fxo->polarity_state = POLARITY_DEBOUNCE_NEGATIVE; ++ fxo->poldebounce_timer = wc->framecount + ++ POLARITY_DEBOUNCE; ++ } ++ break; ++ case POLARITY_DEBOUNCE_NEGATIVE: ++ if (positive_polarity) { ++ fxo->polarity_state = POLARITY_POSITIVE; ++ } else if (time_after(wc->framecount, fxo->poldebounce_timer)) { ++ dahdi_qevent_lock(get_dahdi_chan(wc, mod), ++ DAHDI_EVENT_POLARITY); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "%s: Polarity POSITIVE -> NEGATIVE\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ fxo->polarity_state = POLARITY_NEGATIVE; ++ } ++ break; ++ case POLARITY_NEGATIVE: ++ if (positive_polarity) { ++ fxo->polarity_state = POLARITY_DEBOUNCE_POSITIVE; ++ fxo->poldebounce_timer = wc->framecount + ++ POLARITY_DEBOUNCE; ++ } ++ break; ++ }; ++} ++ ++static bool is_neon_voltage_present(const struct fxo *fxo, u8 abs_voltage) ++{ ++ return (fxo->battery_state == BATTERY_PRESENT && ++ abs_voltage > neonmwi_level && ++ (0 == fxo->neonmwi_last_voltage || ++ ((fxo->line_voltage_status >= fxo->neonmwi_last_voltage - ++ neonmwi_envelope) && ++ (fxo->line_voltage_status <= fxo->neonmwi_last_voltage + ++ neonmwi_envelope) ++ ) ++ ) ++ ); ++} ++ ++static void do_neon_monitor(struct wcaxx *wc, ++ struct wcaxx_module *mod, u8 abs_voltage) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ struct dahdi_chan *const chan = get_dahdi_chan(wc, mod); ++ ++ /* Look for 4 consecutive voltage readings where the voltage is over the ++ * neon limit but does not vary greatly from the last reading */ ++ if (is_neon_voltage_present(fxo, abs_voltage)) { ++ fxo->neonmwi_last_voltage = fxo->line_voltage_status; ++ if (NEONMWI_ON_DEBOUNCE == fxo->neonmwi_debounce) { ++ fxo->neonmwi_offcounter = neonmwi_offlimit_cycles; ++ if (0 == fxo->neonmwi_state) { ++ dahdi_qevent_lock(chan, ++ DAHDI_EVENT_NEONMWI_ACTIVE); ++ fxo->neonmwi_state = 1; ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "NEON MWI active for card %d\n", ++ mod->card+1); ++ } ++ } ++ fxo->neonmwi_debounce++; ++ } else if (NEONMWI_ON_DEBOUNCE > fxo->neonmwi_debounce) { ++ fxo->neonmwi_debounce++; ++ } else { ++ fxo->neonmwi_offcounter = neonmwi_offlimit_cycles; ++ } ++ } else { ++ fxo->neonmwi_debounce = 0; ++ fxo->neonmwi_last_voltage = 0; ++ } ++ ++ /* If no neon mwi pulse for given period of time, indicte no neon mwi ++ * state */ ++ if (fxo->neonmwi_state && 0 < fxo->neonmwi_offcounter) { ++ fxo->neonmwi_offcounter--; ++ if (0 == fxo->neonmwi_offcounter) { ++ dahdi_qevent_lock(get_dahdi_chan(wc, mod), ++ DAHDI_EVENT_NEONMWI_INACTIVE); ++ fxo->neonmwi_state = 0; ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "NEON MWI cleared for card %d\n", ++ mod->card+1); ++ } ++ } ++ } ++} ++ ++static void ++wcaxx_voicedaa_check_hook(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ signed char b; ++ u8 abs_voltage; ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ /* Try to track issues that plague slot one FXO's */ ++ b = fxo->hook_ring_shadow & 0x9b; ++ ++ if (fxo->offhook) { ++ if (b != 0x9) ++ wcaxx_setreg(wc, mod, 5, 0x9); ++ } else { ++ if (b != 0x8) ++ wcaxx_setreg(wc, mod, 5, 0x8); ++ ++ wcaxx_fxo_ring_detect(wc, mod); ++ } ++ ++ abs_voltage = abs(fxo->line_voltage_status); ++ ++ if (fxovoltage && time_after(wc->framecount, fxo->display_fxovoltage)) { ++ /* Every 100 ms */ ++ fxo->display_fxovoltage = wc->framecount + 100; ++ dev_info(&wc->xb.pdev->dev, ++ "Port %d: Voltage: %d\n", ++ mod->card + 1, fxo->line_voltage_status); ++ } ++ ++ if (unlikely(DAHDI_RXSIG_INITIAL == ++ get_dahdi_chan(wc, mod)->rxhooksig)) { ++ /* ++ * dahdi-base will set DAHDI_RXSIG_INITIAL after a ++ * DAHDI_STARTUP or DAHDI_CHANCONFIG ioctl so that new events ++ * will be queued on the channel with the current received ++ * hook state. Channels that use robbed-bit signalling always ++ * report the current received state via the dahdi_rbsbits ++ * call. Since we only call dahdi_hooksig when we've detected ++ * a change to report, let's forget our current state in order ++ * to force us to report it again via dahdi_hooksig. ++ * ++ */ ++ fxo->battery_state = BATTERY_UNKNOWN; ++ } ++ ++ if (abs_voltage < battthresh) { ++ wcaxx_fxo_stop_debouncing_polarity(wc, mod); ++ wcaxx_check_battery_lost(wc, mod); ++ } else { ++ wcaxx_check_battery_present(wc, mod); ++ wcaxx_fxo_check_polarity(wc, mod, ++ (fxo->line_voltage_status > 0)); ++ } ++ ++ /* Look for neon mwi pulse */ ++ if (neonmwi_monitor && !fxo->offhook) ++ do_neon_monitor(wc, mod, abs_voltage); ++#undef MS_PER_CHECK_HOOK ++} ++ ++static void ++wcaxx_fxs_hooksig(struct wcaxx *wc, struct wcaxx_module *const mod, ++ enum dahdi_txsig txsig) ++{ ++ int x = 0; ++ unsigned long flags; ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ switch (txsig) { ++ case DAHDI_TXSIG_ONHOOK: ++ switch (get_dahdi_chan(wc, mod)->sig) { ++ case DAHDI_SIG_FXOGS: ++ x = (POLARITY_XOR(fxs)) ? ++ SLIC_LF_RING_OPEN : ++ SLIC_LF_TIP_OPEN; ++ break; ++ case DAHDI_SIG_EM: ++ case DAHDI_SIG_FXOKS: ++ case DAHDI_SIG_FXOLS: ++ default: ++ x = fxs->idletxhookstate; ++ break; ++ } ++ break; ++ case DAHDI_TXSIG_OFFHOOK: ++ switch (get_dahdi_chan(wc, mod)->sig) { ++ case DAHDI_SIG_EM: ++ x = (POLARITY_XOR(fxs)) ? ++ SLIC_LF_ACTIVE_FWD : ++ SLIC_LF_ACTIVE_REV; ++ break; ++ default: ++ x = fxs->idletxhookstate; ++ break; ++ } ++ break; ++ case DAHDI_TXSIG_START: ++ x = SLIC_LF_RINGING; ++ break; ++ case DAHDI_TXSIG_KEWL: ++ x = SLIC_LF_OPEN; ++ break; ++ default: ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dev_notice(&wc->xb.pdev->dev, ++ "Can't set tx state to %d\n", txsig); ++ return; ++ } ++ ++ if (x != fxs->lasttxhook) { ++ fxs->lasttxhook = x | SLIC_LF_OPPENDING; ++ mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ fxs->oppending_timeout = wc->framecount + 100; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Setting FXS hook state to %d (%02x) framecount=%ld\n", ++ txsig, x, wc->framecount); ++ } ++ } else { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++} ++ ++static void ++wcaxx_fxs_off_hook(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "fxs_off_hook: Card %d Going off hook\n", mod->card); ++ } ++ switch (fxs->lasttxhook) { ++ case SLIC_LF_RINGING: /* Ringing */ ++ case SLIC_LF_OHTRAN_FWD: /* Forward On Hook Transfer */ ++ case SLIC_LF_OHTRAN_REV: /* Reverse On Hook Transfer */ ++ /* just detected OffHook, during Ringing or OnHookTransfer */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ break; ++ } ++ if ((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN) ++ wcaxx_fxs_hooksig(wc, mod, DAHDI_TXSIG_OFFHOOK); ++ dahdi_hooksig(get_dahdi_chan(wc, mod), DAHDI_RXSIG_OFFHOOK); ++ ++#ifdef DEBUG ++ if (robust) ++ wcaxx_init_proslic(wc, mod, 1, 0, 1); ++#endif ++} ++ ++/** ++ * wcaxx_fxs_on_hook - Report on hook to DAHDI. ++ * @wc: Board hosting the module. ++ * @card: Index of the module / port to place on hook. ++ * ++ * If we are intentionally dropping battery to signal a forward ++ * disconnect we do not want to place the line "On-Hook". In this ++ * case, the core of DAHDI will place us on hook when one of the RBS ++ * timers expires. ++ * ++ */ ++static void ++wcaxx_fxs_on_hook(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "fxs_on_hook: Card %d Going on hook\n", mod->card); ++ } ++ ++ if ((mod->mod.fxs.lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN) ++ wcaxx_fxs_hooksig(wc, mod, DAHDI_TXSIG_ONHOOK); ++ dahdi_hooksig(get_dahdi_chan(wc, mod), DAHDI_RXSIG_ONHOOK); ++} ++ ++static void ++wcaxx_isr_misc_fxs(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ unsigned long flags; ++ ++ if (time_after(wc->framecount, fxs->check_alarm)) { ++ /* Accept an alarm once per 10 seconds */ ++ fxs->check_alarm = wc->framecount + (1000*10); ++ if (fxs->palarms) ++ fxs->palarms--; ++ } ++ ++ if (fxs->off_hook && !(fxs->hook_state_shadow & 1)) { ++ wcaxx_fxs_on_hook(wc, mod); ++ fxs->off_hook = 0; ++ } else if (!fxs->off_hook && (fxs->hook_state_shadow & 1)) { ++ wcaxx_fxs_off_hook(wc, mod); ++ fxs->off_hook = 1; ++ } ++ ++ wcaxx_proslic_check_oppending(wc, mod); ++ ++ if (time_after(wc->framecount, fxs->check_proslic)) { ++ fxs->check_proslic = wc->framecount + 250; /* every 250ms */ ++ wcaxx_proslic_recheck_sanity(wc, mod); ++ } ++ ++ if (SLIC_LF_RINGING == fxs->lasttxhook) { ++ /* RINGing, prepare for OHT */ ++ fxs->ohttimer = wc->framecount + OHT_TIMER; ++ /* OHT mode when idle */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? SLIC_LF_OHTRAN_REV : ++ SLIC_LF_OHTRAN_FWD; ++ } else if (fxs->oht_active) { ++ /* check if still OnHook */ ++ if (!fxs->off_hook) { ++ if (time_before(wc->framecount, fxs->ohttimer)) ++ return; ++ ++ /* Switch to active */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD; ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (SLIC_LF_OHTRAN_FWD == fxs->lasttxhook) { ++ /* Apply the change if appropriate */ ++ fxs->lasttxhook = SLIC_LF_OPPENDING | ++ SLIC_LF_ACTIVE_FWD; ++ /* Data enqueued here */ ++ mod->sethook = CMD_WR(LINE_STATE, ++ fxs->lasttxhook); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d OnHookTransfer stop\n", ++ mod->card); ++ } ++ } else if (SLIC_LF_OHTRAN_REV == fxs->lasttxhook) { ++ /* Apply the change if appropriate */ ++ fxs->lasttxhook = SLIC_LF_OPPENDING | ++ SLIC_LF_ACTIVE_REV; ++ /* Data enqueued here */ ++ mod->sethook = CMD_WR(LINE_STATE, ++ fxs->lasttxhook); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d OnHookTransfer stop\n", ++ mod->card); ++ } ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else { ++ fxs->oht_active = 0; ++ /* Switch to active */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD; ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d OnHookTransfer abort\n", ++ mod->card); ++ } ++ } ++ ++ } ++} ++ ++static void wcaxx_handle_receive(struct wcxb *xb, void *_frame) ++{ ++ int i, j; ++ struct wcaxx *wc = container_of(xb, struct wcaxx, xb); ++ u8 *const frame = _frame; ++ ++ wc->framecount++; ++ ++ if (time_after(wc->framecount, wc->module_poll_time)) { ++ for (i = 0; i < wc->mods_per_board; i++) { ++ struct wcaxx_module *const mod = &wc->mods[i]; ++ if (mod->mod_poll) { ++ wcxb_spi_async(mod->spi, &mod->mod_poll->m); ++ mod->mod_poll = NULL; ++ } ++ } ++ wc->module_poll_time = wc->framecount + MODULE_POLL_TIME_MS; ++ } ++ ++ /* TODO: This protection needs to be thought about. */ ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->span.flags)) ++ return; ++ ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) { ++ for (i = 0; i < wc->span.channels; i++) { ++ wc->chans[i]->chan.readchunk[j] = ++ frame[j*WCXB_DMA_CHAN_SIZE+(1+i*4)]; ++ } ++ } ++ for (i = 0; i < wc->span.channels; i++) { ++ struct dahdi_chan *const c = wc->span.chans[i]; ++ __dahdi_ec_chunk(c, c->readchunk, c->readchunk, c->writechunk); ++ } ++ _dahdi_receive(&wc->span); ++ return; ++} ++ ++static void wcaxx_handle_transmit(struct wcxb *xb, void *_frame) ++{ ++ int i, j; ++ struct wcaxx *wc = container_of(xb, struct wcaxx, xb); ++ u8 *const frame = _frame; ++ ++ wcxb_spi_handle_interrupt(wc->master); ++ ++ /* TODO: This protection needs to be thought about. */ ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->span.flags)) ++ return; ++ ++ _dahdi_transmit(&wc->span); ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) { ++ for (i = 0; i < wc->span.channels; i++) { ++ struct dahdi_chan *c = &wc->chans[i]->chan; ++ frame[j*WCXB_DMA_CHAN_SIZE+(1+i*4)] = c->writechunk[j]; ++ } ++ } ++ return; ++} ++ ++static int wcaxx_voicedaa_insane(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ int blah; ++ blah = wcaxx_getreg(wc, mod, 2); ++ if (blah != 0x3) ++ return -2; ++ blah = wcaxx_getreg(wc, mod, 11); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "VoiceDAA System: %02x\n", blah & 0xf); ++ } ++ return 0; ++} ++ ++static int ++wcaxx_proslic_insane(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ int blah, reg1, insane_report; ++ insane_report = 0; ++ ++ blah = wcaxx_getreg(wc, mod, 0); ++ if (blah != 0xff && (debug & DEBUG_CARD)) { ++ dev_info(&wc->xb.pdev->dev, ++ "ProSLIC on module %d, product %d, " ++ "version %d\n", mod->card, (blah & 0x30) >> 4, ++ (blah & 0xf)); ++ } ++ ++#if 0 ++ if ((blah & 0x30) >> 4) { ++ dev_info(&wc->xb.pdev->dev, ++ "ProSLIC on module %d is not a 3210.\n", mod->card); ++ return -1; ++ } ++#endif ++ if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { ++ /* SLIC not loaded */ ++ return -1; ++ } ++ ++ /* let's be really sure this is an FXS before we continue */ ++ reg1 = wcaxx_getreg(wc, mod, 1); ++ if ((0x80 != (blah & 0xf0)) || (0x88 != reg1)) { ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "DEBUG: not FXS b/c reg0=%x or " ++ "reg1 != 0x88 (%x).\n", blah, reg1); ++ } ++ return -1; ++ } ++ ++ blah = wcaxx_getreg(wc, mod, 8); ++ if (blah != 0x2) { ++ dev_notice(&wc->xb.pdev->dev, ++ "ProSLIC on module %d insane (1) %d should be 2\n", ++ mod->card, blah); ++ return -1; ++ } else if (insane_report) { ++ dev_notice(&wc->xb.pdev->dev, ++ "ProSLIC on module %d Reg 8 Reads %d Expected " ++ "is 0x2\n", mod->card, blah); ++ } ++ ++ blah = wcaxx_getreg(wc, mod, 64); ++ if (blah != 0x0) { ++ dev_notice(&wc->xb.pdev->dev, ++ "ProSLIC on module %d insane (2)\n", ++ mod->card); ++ return -1; ++ } else if (insane_report) { ++ dev_notice(&wc->xb.pdev->dev, ++ "ProSLIC on module %d Reg 64 Reads %d Expected " ++ "is 0x0\n", mod->card, blah); ++ } ++ ++ blah = wcaxx_getreg(wc, mod, 11); ++ if (blah != 0x33) { ++ dev_notice(&wc->xb.pdev->dev, ++ "ProSLIC on module %d insane (3)\n", mod->card); ++ return -1; ++ } else if (insane_report) { ++ dev_notice(&wc->xb.pdev->dev, ++ "ProSLIC on module %d Reg 11 Reads %d " ++ "Expected is 0x33\n", mod->card, blah); ++ } ++ ++ /* Just be sure it's setup right. */ ++ wcaxx_setreg(wc, mod, 30, 0); ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "ProSLIC on module %d seems sane.\n", mod->card); ++ } ++ return 0; ++} ++ ++static int ++wcaxx_proslic_powerleak_test(struct wcaxx *wc, ++ struct wcaxx_module *const mod) ++{ ++ unsigned long start; ++ unsigned char vbat; ++ ++ /* Turn off linefeed */ ++ wcaxx_setreg(wc, mod, LINE_STATE, 0); ++ ++ /* Power down */ ++ wcaxx_setreg(wc, mod, 14, 0x10); ++ ++ start = jiffies; ++ ++ /* TODO: Why is this sleep necessary. Without it, the first read ++ * comes back with a 0 value. */ ++ msleep(20); ++ ++ while ((vbat = wcaxx_getreg(wc, mod, 82)) > 0x6) { ++ if (time_after(jiffies, start + HZ/4)) ++ break; ++ } ++ ++ if (vbat < 0x06) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Excessive leakage detected on module %d: %d " ++ "volts (%02x) after %d ms\n", mod->card, ++ 376 * vbat / 1000, vbat, ++ (int)((jiffies - start) * 1000 / HZ)); ++ return -1; ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Post-leakage voltage: %d volts\n", 376 * vbat / 1000); ++ } ++ return 0; ++} ++ ++static int wcaxx_powerup_proslic(struct wcaxx *wc, ++ struct wcaxx_module *mod, int fast) ++{ ++ unsigned char vbat; ++ unsigned long origjiffies; ++ int lim; ++ ++ /* Set period of DC-DC converter to 1/64 khz */ ++ wcaxx_setreg(wc, mod, 92, 0xc0 /* was 0xff */); ++ ++ /* Wait for VBat to powerup */ ++ origjiffies = jiffies; ++ ++ /* Disable powerdown */ ++ wcaxx_setreg(wc, mod, 14, 0); ++ ++ /* If fast, don't bother checking anymore */ ++ if (fast) ++ return 0; ++ ++ while ((vbat = wcaxx_getreg(wc, mod, 82)) < 0xc0) { ++ /* Wait no more than 500ms */ ++ if ((jiffies - origjiffies) > HZ/2) ++ break; ++ } ++ ++ if (vbat < 0xc0) { ++ dev_notice(&wc->xb.pdev->dev, "ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM CARD??\n", ++ mod->card, (int)(((jiffies - origjiffies) * 1000 / HZ)), ++ vbat * 375); ++ return -1; ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "ProSLIC on module %d powered up to -%d volts (%02x) " ++ "in %d ms\n", mod->card, vbat * 376 / 1000, vbat, ++ (int)(((jiffies - origjiffies) * 1000 / HZ))); ++ } ++ ++ /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */ ++ /* If out of range, just set it to the default value */ ++ lim = (loopcurrent - 20) / 3; ++ if (loopcurrent > 41) { ++ lim = 0; ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Loop current out of range! Setting to default 20mA!\n"); ++ } ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Loop current set to %dmA!\n", (lim*3)+20); ++ } ++ wcaxx_setreg(wc, mod, LOOP_I_LIMIT, lim); ++ ++ /* Engage DC-DC converter */ ++ wcaxx_setreg(wc, mod, 93, 0x19 /* was 0x19 */); ++ return 0; ++ ++} ++ ++static int ++wcaxx_proslic_manual_calibrate(struct wcaxx *wc, ++ struct wcaxx_module *const mod) ++{ ++ unsigned long origjiffies; ++ unsigned char i; ++ ++ /* Disable all interupts in DR21-23 */ ++ wcaxx_setreg(wc, mod, 21, 0); ++ wcaxx_setreg(wc, mod, 22, 0); ++ wcaxx_setreg(wc, mod, 23, 0); ++ ++ wcaxx_setreg(wc, mod, 64, 0); ++ ++ /* (0x18) Calibrations without the ADC and DAC offset and without ++ * common mode calibration. */ ++ wcaxx_setreg(wc, mod, 97, 0x18); ++ ++ /* (0x47) Calibrate common mode and differential DAC mode DAC + ILIM */ ++ wcaxx_setreg(wc, mod, 96, 0x47); ++ ++ origjiffies = jiffies; ++ while (wcaxx_getreg(wc, mod, 96) != 0) { ++ if ((jiffies-origjiffies) > 80) ++ return -1; ++ } ++ /* Initialized DR 98 and 99 to get consistant results. 98 and 99 are ++ * the results registers and the search should have same intial ++ * conditions. ++ */ ++ ++ /******* The following is the manual gain mismatch calibration ********/ ++ /******* This is also available as a function *************************/ ++ msleep(20); ++ wcaxx_proslic_setreg_indirect(wc, mod, 88, 0); ++ wcaxx_proslic_setreg_indirect(wc, mod, 89, 0); ++ wcaxx_proslic_setreg_indirect(wc, mod, 90, 0); ++ wcaxx_proslic_setreg_indirect(wc, mod, 91, 0); ++ wcaxx_proslic_setreg_indirect(wc, mod, 92, 0); ++ wcaxx_proslic_setreg_indirect(wc, mod, 93, 0); ++ ++ /* This is necessary if the calibration occurs other than at reset */ ++ wcaxx_setreg(wc, mod, 98, 0x10); ++ wcaxx_setreg(wc, mod, 99, 0x10); ++ ++ for (i = 0x1f; i > 0; i--) { ++ wcaxx_setreg(wc, mod, 98, i); ++ msleep(40); ++ if ((wcaxx_getreg(wc, mod, 88)) == 0) ++ break; ++ } ++ ++ for (i = 0x1f; i > 0; i--) { ++ wcaxx_setreg(wc, mod, 99, i); ++ msleep(40); ++ if ((wcaxx_getreg(wc, mod, 89)) == 0) ++ break; ++ } ++ ++ /******** The preceding is the manual gain mismatch calibration *******/ ++ /******** The following is the longitudinal Balance Cal ***************/ ++ wcaxx_setreg(wc, mod, 64, 1); ++ msleep(100); ++ ++ wcaxx_setreg(wc, mod, 64, 0); ++ ++ /* enable interrupt for the balance Cal */ ++ wcaxx_setreg(wc, mod, 23, 0x4); ++ ++ /* this is a singular calibration bit for longitudinal calibration */ ++ wcaxx_setreg(wc, mod, 97, 0x1); ++ wcaxx_setreg(wc, mod, 96, 0x40); ++ ++ wcaxx_getreg(wc, mod, 96); /* Read Reg 96 just cause */ ++ ++ wcaxx_setreg(wc, mod, 21, 0xFF); ++ wcaxx_setreg(wc, mod, 22, 0xFF); ++ wcaxx_setreg(wc, mod, 23, 0xFF); ++ ++ /**The preceding is the longitudinal Balance Cal***/ ++ return 0; ++ ++} ++ ++static int ++wcaxx_proslic_calibrate(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ unsigned long origjiffies; ++ int x; ++ ++ /* Perform all calibrations */ ++ wcaxx_setreg(wc, mod, 97, 0x1f); ++ ++ /* Begin, no speedup */ ++ wcaxx_setreg(wc, mod, 96, 0x5f); ++ ++ /* Wait for it to finish */ ++ origjiffies = jiffies; ++ while (wcaxx_getreg(wc, mod, 96)) { ++ if (time_after(jiffies, (origjiffies + (2*HZ)))) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Timeout waiting for calibration of " ++ "module %d\n", mod->card); ++ return -1; ++ } ++ } ++ ++ if (debug & DEBUG_CARD) { ++ /* Print calibration parameters */ ++ dev_info(&wc->xb.pdev->dev, ++ "Calibration Vector Regs 98 - 107:\n"); ++ for (x = 98; x < 108; x++) { ++ dev_info(&wc->xb.pdev->dev, ++ "%d: %02x\n", x, wcaxx_getreg(wc, mod, x)); ++ } ++ } ++ return 0; ++} ++ ++/********************************************************************* ++ * Set the hwgain on the analog modules ++ * ++ * card = the card position for this module (0-23) ++ * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35) ++ * tx = (0 for rx; 1 for tx) ++ * ++ *******************************************************************/ ++static int ++wcaxx_set_hwgain(struct wcaxx *wc, struct wcaxx_module *mod, ++ __s32 gain, __u32 tx) ++{ ++ if (mod->type != FXO) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Cannot adjust gain. Unsupported module type!\n"); ++ return -1; ++ } ++ ++ if (tx) { ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "setting FXO tx gain for card=%d to %d\n", ++ mod->card, gain); ++ } ++ if (gain >= -150 && gain <= 0) { ++ wcaxx_setreg(wc, mod, 38, 16 + (gain / -10)); ++ wcaxx_setreg(wc, mod, 40, 16 + (-gain % 10)); ++ } else if (gain <= 120 && gain > 0) { ++ wcaxx_setreg(wc, mod, 38, gain/10); ++ wcaxx_setreg(wc, mod, 40, (gain%10)); ++ } else { ++ dev_notice(&wc->xb.pdev->dev, ++ "FXO tx gain is out of range (%d)\n", gain); ++ return -1; ++ } ++ } else { /* rx */ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "setting FXO rx gain for card=%d to %d\n", ++ mod->card, gain); ++ } ++ if (gain >= -150 && gain <= 0) { ++ wcaxx_setreg(wc, mod, 39, 16 + (gain / -10)); ++ wcaxx_setreg(wc, mod, 41, 16 + (-gain % 10)); ++ } else if (gain <= 120 && gain > 0) { ++ wcaxx_setreg(wc, mod, 39, gain/10); ++ wcaxx_setreg(wc, mod, 41, (gain%10)); ++ } else { ++ dev_notice(&wc->xb.pdev->dev, ++ "FXO rx gain is out of range (%d)\n", gain); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int set_lasttxhook_interruptible(struct wcaxx *wc, struct fxs *fxs, ++ unsigned newval, int *psethook) ++{ ++ int res = 0; ++ unsigned long flags; ++ int timeout = 0; ++ ++ do { ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (SLIC_LF_OPPENDING & fxs->lasttxhook) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ if (timeout++ > 100) ++ return -1; ++ msleep(100); ++ } else { ++ fxs->lasttxhook = (newval & SLIC_LF_SETMASK) | ++ SLIC_LF_OPPENDING; ++ *psethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ } ++ } while (1); ++ ++ return res; ++} ++ ++/* Must be called from within an interruptible context */ ++static int set_vmwi(struct wcaxx *wc, struct wcaxx_module *const mod) ++{ ++ int x; ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ /* Presently only supports line reversal MWI */ ++ if ((fxs->vmwi_active_messages) && ++ (fxs->vmwisetting.vmwi_type & DAHDI_VMWI_LREV)) ++ fxs->vmwi_linereverse = 1; ++ else ++ fxs->vmwi_linereverse = 0; ++ ++ /* Set line polarity for new VMWI state */ ++ if (POLARITY_XOR(fxs)) { ++ fxs->idletxhookstate |= SLIC_LF_REVMASK; ++ /* Do not set while currently ringing or open */ ++ if (((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_RINGING) && ++ ((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN)) { ++ x = fxs->lasttxhook; ++ x |= SLIC_LF_REVMASK; ++ set_lasttxhook_interruptible(wc, fxs, x, &mod->sethook); ++ } ++ } else { ++ fxs->idletxhookstate &= ~SLIC_LF_REVMASK; ++ /* Do not set while currently ringing or open */ ++ if (((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_RINGING) && ++ ((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN)) { ++ x = fxs->lasttxhook; ++ x &= ~SLIC_LF_REVMASK; ++ set_lasttxhook_interruptible(wc, fxs, x, &mod->sethook); ++ } ++ } ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "Setting VMWI on channel %d, messages=%d, lrev=%d\n", ++ mod->card, fxs->vmwi_active_messages, ++ fxs->vmwi_linereverse); ++ } ++ return 0; ++} ++ ++static void ++wcaxx_voicedaa_set_ts(struct wcaxx *wc, struct wcaxx_module *mod, int ts) ++{ ++ /* 34 bits from framesysc to the first channel, 8 bits in each ts * (th ++ * e timeslot we're assigning + 1 to skip for VPMOCT issue on first ++ * timeslot + 3 in that there are 4 bytes assigned for each timeslot on ++ * framer which was copied to this card */ ++ /* 34 + 8 * (ts + 1 + 3) */ ++ wcaxx_setreg(wc, mod, 34, (ts * 8 + 42 + (ts * 3 * 8)) & 0xff); ++ wcaxx_setreg(wc, mod, 35, (ts * 8 + 42 + (ts * 3 * 8)) >> 8); ++ wcaxx_setreg(wc, mod, 36, (ts * 8 + 42 + (ts * 3 * 8)) & 0xff); ++ wcaxx_setreg(wc, mod, 37, (ts * 8 + 42 + (ts * 3 * 8)) >> 8); ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "voicedaa: card %d new timeslot: %d\n", ++ mod->card + 1, ts); ++ } ++} ++ ++static int ++wcaxx_init_voicedaa(struct wcaxx *wc, struct wcaxx_module *mod, ++ int fast, int manual, int sane) ++{ ++ unsigned char reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0; ++ unsigned long flags; ++ unsigned long newjiffies; ++ ++ /* Send a short write to the device in order to reset the SPI state ++ * machine. It may be out of sync since the driver was probing for an ++ * FXS device on that chip select. */ ++ /* wcxb_spi_short_write(mod->spi); */ ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->type = FXO; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (!sane && wcaxx_voicedaa_insane(wc, mod)) ++ return -2; ++ ++ /* Software reset */ ++ wcaxx_setreg(wc, mod, 1, 0x80); ++ msleep(100); ++ ++ /* Set On-hook speed, Ringer impedence, and ringer threshold */ ++ reg16 |= (fxo_modes[_opermode].ohs << 6); ++ reg16 |= (fxo_modes[_opermode].rz << 1); ++ reg16 |= (fxo_modes[_opermode].rt); ++ wcaxx_setreg(wc, mod, 16, reg16); ++ ++ /* Enable ring detector full-wave rectifier mode */ ++ wcaxx_setreg(wc, mod, 18, 2); ++ wcaxx_setreg(wc, mod, 24, 0); ++ ++ /* Set DC Termination: ++ Tip/Ring voltage adjust, minimum operational current, current ++ limitation */ ++ reg26 |= (fxo_modes[_opermode].dcv << 6); ++ reg26 |= (fxo_modes[_opermode].mini << 4); ++ reg26 |= (fxo_modes[_opermode].ilim << 1); ++ wcaxx_setreg(wc, mod, 26, reg26); ++ ++ /* Set AC Impedence */ ++ reg30 = (fxo_modes[_opermode].acim); ++ wcaxx_setreg(wc, mod, 30, reg30); ++ ++ /* Misc. DAA parameters */ ++ ++ /* If fast pickup is set, then the off hook counter will be set to 8 ++ * ms, otherwise 128 ms. */ ++ reg31 = (fastpickup) ? 0xe3 : 0xa3; ++ ++ reg31 |= (fxo_modes[_opermode].ohs2 << 3); ++ wcaxx_setreg(wc, mod, 31, reg31); ++ ++ wcaxx_voicedaa_set_ts(wc, mod, mod->card); ++ ++ /* Enable ISO-Cap */ ++ wcaxx_setreg(wc, mod, 6, 0x00); ++ ++ /* Turn off the calibration delay when fastpickup is enabled. */ ++ if (fastpickup) ++ wcaxx_setreg(wc, mod, 17, wcaxx_getreg(wc, mod, 17) | 0x20); ++ ++ /* Wait 2000ms for ISO-cap to come up */ ++ newjiffies = jiffies + msecs_to_jiffies(2000); ++ ++ while (time_before(jiffies, newjiffies) && ++ !(wcaxx_getreg(wc, mod, 11) & 0xf0)) ++ msleep(100); ++ ++ if (!(wcaxx_getreg(wc, mod, 11) & 0xf0)) { ++ dev_notice(&wc->xb.pdev->dev, "VoiceDAA did not bring up ISO link properly!\n"); ++ return -1; ++ } ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, "ISO-Cap is now up, line side: %02x rev %02x\n", ++ wcaxx_getreg(wc, mod, 11) >> 4, ++ (wcaxx_getreg(wc, mod, 13) >> 2) & 0xf); ++ } ++ ++ /* Enable on-hook line monitor */ ++ wcaxx_setreg(wc, mod, 5, 0x08); ++ ++ /* Take values for fxotxgain and fxorxgain and apply them to module */ ++ wcaxx_set_hwgain(wc, mod, fxotxgain, 1); ++ wcaxx_set_hwgain(wc, mod, fxorxgain, 0); ++ ++#ifdef DEBUG ++ if (digitalloopback) { ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on digital loopback for port %d.\n", ++ mod->card + 1); ++ wcaxx_setreg(wc, mod, 10, 0x01); ++ } ++#endif ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", ++ (wcaxx_getreg(wc, mod, 38)/16) ? ++ -(wcaxx_getreg(wc, mod, 38) - 16) : ++ wcaxx_getreg(wc, mod, 38), ++ (wcaxx_getreg(wc, mod, 40)/16) ? ++ -(wcaxx_getreg(wc, mod, 40) - 16) : ++ wcaxx_getreg(wc, mod, 40), ++ (wcaxx_getreg(wc, mod, 39)/16) ? ++ -(wcaxx_getreg(wc, mod, 39) - 16) : ++ wcaxx_getreg(wc, mod, 39), ++ (wcaxx_getreg(wc, mod, 41)/16) ? ++ -(wcaxx_getreg(wc, mod, 41) - 16) : ++ wcaxx_getreg(wc, mod, 41)); ++ } ++ ++ return 0; ++} ++ ++static void ++wcaxx_proslic_set_ts(struct wcaxx *wc, struct wcaxx_module *mod, int ts) ++{ ++ /* Tx Start low byte 0 */ ++ wcaxx_setreg(wc, mod, 2, (ts * 8 + 42 + (ts * 3 * 8)) & 0xff); ++ /* Tx Start high byte 0 */ ++ wcaxx_setreg(wc, mod, 3, (ts * 8 + 42 + (ts * 3 * 8)) >> 8); ++ /* Rx Start low byte 0 */ ++ wcaxx_setreg(wc, mod, 4, (ts * 8 + 42 + (ts * 3 * 8)) & 0xff); ++ /* Rx Start high byte 0 */ ++ wcaxx_setreg(wc, mod, 5, (ts * 8 + 42 + (ts * 3 * 8)) >> 8); ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "proslic: card %d new timeslot: %d\n", ++ mod->card + 1, ts); ++ } ++} ++ ++static int ++wcaxx_init_proslic(struct wcaxx *wc, struct wcaxx_module *const mod, ++ int fast, int manual, int sane) ++{ ++ ++ struct fxs *const fxs = &mod->mod.fxs; ++ unsigned short tmp[5]; ++ unsigned long flags; ++ unsigned char r19, r9; ++ int x; ++ int fxsmode = 0; ++ int addresses[ARRAY_SIZE(fxs->calregs.vals)]; ++ ++#if 0 /* TODO */ ++ if (wc->mods[mod->card & 0xfc].type == QRV) ++ return -2; ++#endif ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->type = FXS; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* msleep(100); */ ++ ++ /* Sanity check the ProSLIC */ ++ if (!sane && wcaxx_proslic_insane(wc, mod)) ++ return -2; ++ ++ /* Initialize VMWI settings */ ++ memset(&(fxs->vmwisetting), 0, sizeof(fxs->vmwisetting)); ++ fxs->vmwi_linereverse = 0; ++ ++ /* By default, don't send on hook */ ++ if (!reversepolarity != !fxs->reversepolarity) ++ fxs->idletxhookstate = SLIC_LF_ACTIVE_REV; ++ else ++ fxs->idletxhookstate = SLIC_LF_ACTIVE_FWD; ++ ++ if (sane) { ++ /* Make sure we turn off the DC->DC converter to prevent ++ * anything from blowing up */ ++ wcaxx_setreg(wc, mod, 14, 0x10); ++ } ++ ++ if (wcaxx_proslic_init_indirect_regs(wc, mod)) { ++ dev_info(&wc->xb.pdev->dev, ++ "Indirect Registers failed to initialize on " ++ "module %d.\n", mod->card); ++ return -1; ++ } ++ ++ /* Clear scratch pad area */ ++ wcaxx_proslic_setreg_indirect(wc, mod, 97, 0); ++ ++ /* Clear digital loopback */ ++ wcaxx_setreg(wc, mod, 8, 0); ++ ++ /* Revision C optimization */ ++ wcaxx_setreg(wc, mod, 108, 0xeb); ++ ++ /* Disable automatic VBat switching for safety to prevent ++ * Q7 from accidently turning on and burning out. ++ * If pulse dialing has trouble at high REN loads change this to 0x17 */ ++ wcaxx_setreg(wc, mod, 67, 0x07); ++ ++ /* Turn off Q7 */ ++ wcaxx_setreg(wc, mod, 66, 1); ++ ++ /* Flush ProSLIC digital filters by setting to clear, while ++ saving old values */ ++ for (x = 0; x < 5; x++) { ++ tmp[x] = wcaxx_proslic_getreg_indirect(wc, mod, x + 35); ++ wcaxx_proslic_setreg_indirect(wc, mod, x + 35, 0x8000); ++ } ++ ++ /* Power up the DC-DC converter */ ++ if (wcaxx_powerup_proslic(wc, mod, fast)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Unable to do INITIAL ProSLIC powerup on " ++ "module %d\n", mod->card); ++ return -1; ++ } ++ ++ if (!fast) { ++ /* Check for power leaks */ ++ if (wcaxx_proslic_powerleak_test(wc, mod)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "ProSLIC module %d failed leakage test. " ++ "Check for short circuit\n", mod->card); ++ } ++ /* Power up again */ ++ if (wcaxx_powerup_proslic(wc, mod, fast)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Unable to do FINAL ProSLIC powerup on " ++ "module %d\n", mod->card); ++ return -1; ++ } ++#ifndef NO_CALIBRATION ++ /* Perform calibration */ ++ if (manual) { ++ if (wcaxx_proslic_manual_calibrate(wc, mod)) { ++ dev_dbg(&wc->xb.pdev->dev, ++ "Proslic failed on Manual Calibration\n"); ++ if (wcaxx_proslic_manual_calibrate(wc, mod)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); ++ return -1; ++ } ++ dev_info(&wc->xb.pdev->dev, ++ "Proslic Passed Manual Calibration on Second Attempt\n"); ++ } ++ } else { ++ if (wcaxx_proslic_calibrate(wc, mod)) { ++ dev_dbg(&wc->xb.pdev->dev, ++ "ProSlic died on Auto Calibration.\n"); ++ if (wcaxx_proslic_calibrate(wc, mod)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Proslic Failed on Second Attempt to Auto Calibrate\n"); ++ return -1; ++ } ++ dev_info(&wc->xb.pdev->dev, ++ "Proslic Passed Auto Calibration on Second Attempt\n"); ++ } ++ } ++ /* Perform DC-DC calibration */ ++ wcaxx_setreg(wc, mod, 93, 0x99); ++ r19 = wcaxx_getreg(wc, mod, 107); ++ if ((r19 < 0x2) || (r19 > 0xd)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "DC-DC cal has a surprising direct 107 of 0x%02x!\n", ++ r19); ++ wcaxx_setreg(wc, mod, 107, 0x8); ++ } ++ ++ /* Save calibration vectors */ ++ for (x = 0; x < ARRAY_SIZE(addresses); x++) ++ addresses[x] = 96 + x; ++ wcaxx_getregs(wc, mod, addresses, ARRAY_SIZE(addresses)); ++ for (x = 0; x < ARRAY_SIZE(fxs->calregs.vals); x++) ++ fxs->calregs.vals[x] = addresses[x]; ++#endif ++ ++ } else { ++ /* Restore calibration registers */ ++ for (x = 0; x < ARRAY_SIZE(fxs->calregs.vals); x++) ++ wcaxx_setreg(wc, mod, 96 + x, fxs->calregs.vals[x]); ++ } ++ /* Calibration complete, restore original values */ ++ for (x = 0; x < 5; x++) ++ wcaxx_proslic_setreg_indirect(wc, mod, x + 35, tmp[x]); ++ ++ if (wcaxx_proslic_verify_indirect_regs(wc, mod)) { ++ dev_info(&wc->xb.pdev->dev, "Indirect Registers failed verification.\n"); ++ return -1; ++ } ++ ++ /* U-Law 8-bit interface */ ++ wcaxx_proslic_set_ts(wc, mod, mod->card); ++ ++ wcaxx_setreg(wc, mod, 18, 0xff); /* clear all interrupt */ ++ wcaxx_setreg(wc, mod, 19, 0xff); ++ wcaxx_setreg(wc, mod, 20, 0xff); ++ wcaxx_setreg(wc, mod, 22, 0xff); ++ wcaxx_setreg(wc, mod, 73, 0x04); ++ ++ wcaxx_setreg(wc, mod, 69, 0x4); ++ ++ if (fxshonormode) { ++ static const int ACIM2TISS[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, ++ 0x0, 0x0, 0x6, 0x0, 0x0, ++ 0x0, 0x2, 0x0, 0x3 }; ++ fxsmode = ACIM2TISS[fxo_modes[_opermode].acim]; ++ wcaxx_setreg(wc, mod, 10, 0x08 | fxsmode); ++ if (fxo_modes[_opermode].ring_osc) { ++ wcaxx_proslic_setreg_indirect(wc, mod, 20, ++ fxo_modes[_opermode].ring_osc); ++ } ++ if (fxo_modes[_opermode].ring_x) { ++ wcaxx_proslic_setreg_indirect(wc, mod, 21, ++ fxo_modes[_opermode].ring_x); ++ } ++ } ++ if (lowpower) ++ wcaxx_setreg(wc, mod, 72, 0x10); ++ ++ if (fastringer) { ++ /* Speed up Ringer */ ++ wcaxx_proslic_setreg_indirect(wc, mod, 20, 0x7e6d); ++ wcaxx_proslic_setreg_indirect(wc, mod, 21, 0x01b9); ++ /* Beef up Ringing voltage to 89V */ ++ if (boostringer) { ++ wcaxx_setreg(wc, mod, 74, 0x3f); ++ if (wcaxx_proslic_setreg_indirect(wc, mod, 21, 0x247)) ++ return -1; ++ dev_info(&wc->xb.pdev->dev, ++ "Boosting fast ringer on slot %d (89V peak)\n", ++ mod->card + 1); ++ } else if (lowpower) { ++ if (wcaxx_proslic_setreg_indirect(wc, mod, 21, 0x14b)) ++ return -1; ++ dev_info(&wc->xb.pdev->dev, ++ "Reducing fast ring power on slot %d " ++ "(50V peak)\n", mod->card + 1); ++ } else ++ dev_info(&wc->xb.pdev->dev, ++ "Speeding up ringer on slot %d (25Hz)\n", ++ mod->card + 1); ++ } else { ++ /* Beef up Ringing voltage to 89V */ ++ if (boostringer) { ++ wcaxx_setreg(wc, mod, 74, 0x3f); ++ if (wcaxx_proslic_setreg_indirect(wc, mod, 21, 0x1d1)) ++ return -1; ++ dev_info(&wc->xb.pdev->dev, ++ "Boosting ringer on slot %d (89V peak)\n", ++ mod->card + 1); ++ } else if (lowpower) { ++ if (wcaxx_proslic_setreg_indirect(wc, mod, 21, 0x108)) ++ return -1; ++ dev_info(&wc->xb.pdev->dev, ++ "Reducing ring power on slot %d " ++ "(50V peak)\n", mod->card + 1); ++ } ++ } ++ ++ if (fxstxgain || fxsrxgain) { ++ r9 = wcaxx_getreg(wc, mod, 9); ++ switch (fxstxgain) { ++ case 35: ++ r9 += 8; ++ break; ++ case -35: ++ r9 += 4; ++ break; ++ case 0: ++ break; ++ } ++ ++ switch (fxsrxgain) { ++ case 35: ++ r9 += 2; ++ break; ++ case -35: ++ r9 += 1; ++ break; ++ case 0: ++ break; ++ } ++ wcaxx_setreg(wc, mod, 9, r9); ++ } ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "DEBUG: fxstxgain:%s fxsrxgain:%s\n", ++ ((wcaxx_getreg(wc, mod, 9) / 8) == 1) ? ++ "3.5" : ((wcaxx_getreg(wc, mod, 9) / 4) == 1) ? ++ "-3.5" : "0.0", ++ ((wcaxx_getreg(wc, mod, 9) / 2) == 1) ? ++ "3.5" : ((wcaxx_getreg(wc, mod, 9) % 2) ? ++ "-3.5" : "0.0")); ++ } ++ ++ fxs->lasttxhook = fxs->idletxhookstate; ++ wcaxx_setreg(wc, mod, LINE_STATE, fxs->lasttxhook); ++ ++ /* Preset the shadow register so that we won't get a power alarm when ++ * we finish initialization, otherwise the line state register may not ++ * have been read yet. */ ++ fxs->linefeed_control_shadow = fxs->lasttxhook; ++ return 0; ++} ++ ++static void wcaxx_get_fxs_regs(struct wcaxx *wc, struct wcaxx_module *mod, ++ struct wctdm_regs *regs) ++{ ++ int x; ++ ++ for (x = 0; x < NUM_INDIRECT_REGS; x++) ++ regs->indirect[x] = wcaxx_proslic_getreg_indirect(wc, mod, x); ++ ++ for (x = 0; x < NUM_REGS; x++) ++ regs->direct[x] = wcaxx_getreg(wc, mod, x); ++} ++ ++static void wcaxx_get_fxo_regs(struct wcaxx *wc, struct wcaxx_module *mod, ++ struct wctdm_regs *regs) ++{ ++ const unsigned int NUM_FXO_REGS = 60; ++ int x; ++ ++ for (x = 0; x < NUM_FXO_REGS; x++) ++ regs->direct[x] = wcaxx_getreg(wc, mod, x); ++} ++ ++static int ++wcaxx_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) ++{ ++ struct wctdm_stats stats; ++ struct wctdm_regop regop; ++ struct wctdm_echo_coefs echoregs; ++ struct dahdi_hwgain hwgain; ++ struct wcaxx *wc = chan->pvt; ++ int x; ++ struct wcaxx_module *const mod = &wc->mods[chan->chanpos - 1]; ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ switch (cmd) { ++ case DAHDI_ONHOOKTRANSFER: ++ if (mod->type != FXS) ++ return -EINVAL; ++ if (get_user(x, (__user int *) data)) ++ return -EFAULT; ++ ++ /* Active mode when idle */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ ++ if (fxs_lf(fxs, ACTIVE_FWD) || fxs_lf(fxs, ACTIVE_REV)) { ++ int res; ++ ++ res = set_lasttxhook_interruptible(wc, fxs, ++ (POLARITY_XOR(fxs) ? ++ SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD), ++ &mod->sethook); ++ ++ if (debug & DEBUG_CARD) { ++ if (res) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d TIMEOUT: " ++ "OnHookTransfer start\n", ++ chan->chanpos - 1); ++ } else { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d OnHookTransfer " ++ "start\n", chan->chanpos - 1); ++ } ++ } ++ ++ } ++ ++ fxs->ohttimer = wc->framecount + x; ++ fxs->oht_active = 1; ++ ++ break; ++ case DAHDI_VMWI_CONFIG: ++ if (mod->type != FXS) ++ return -EINVAL; ++ if (copy_from_user(&(fxs->vmwisetting), ++ (__user void *)data, ++ sizeof(fxs->vmwisetting))) ++ return -EFAULT; ++ set_vmwi(wc, mod); ++ break; ++ case DAHDI_VMWI: ++ if (mod->type != FXS) ++ return -EINVAL; ++ if (get_user(x, (__user int *) data)) ++ return -EFAULT; ++ if (0 > x) ++ return -EFAULT; ++ fxs->vmwi_active_messages = x; ++ set_vmwi(wc, mod); ++ break; ++ case WCTDM_GET_STATS: ++ if (mod->type == FXS) { ++ stats.tipvolt = wcaxx_getreg(wc, mod, 80) * -376; ++ stats.ringvolt = wcaxx_getreg(wc, mod, 81) * -376; ++ stats.batvolt = wcaxx_getreg(wc, mod, 82) * -376; ++ } else if (mod->type == FXO) { ++ stats.tipvolt = (s8)wcaxx_getreg(wc, mod, 29) * 1000; ++ stats.ringvolt = (s8)wcaxx_getreg(wc, mod, 29) * 1000; ++ stats.batvolt = (s8)wcaxx_getreg(wc, mod, 29) * 1000; ++ } else ++ return -EINVAL; ++ if (copy_to_user((__user void *) data, &stats, sizeof(stats))) ++ return -EFAULT; ++ break; ++ case WCTDM_GET_REGS: ++ { ++ struct wctdm_regs *regs = kzalloc(sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return -ENOMEM; ++ ++ if (mod->type == FXS) ++ wcaxx_get_fxs_regs(wc, mod, regs); ++ else ++ wcaxx_get_fxo_regs(wc, mod, regs); ++ ++ if (copy_to_user((__user void *)data, regs, sizeof(*regs))) { ++ kfree(regs); ++ return -EFAULT; ++ } ++ ++ kfree(regs); ++ break; ++ } ++ case WCTDM_SET_REG: ++ if (copy_from_user(®op, (__user void *) data, sizeof(regop))) ++ return -EFAULT; ++ if (regop.indirect) { ++ if (mod->type != FXS) ++ return -EINVAL; ++ dev_info(&wc->xb.pdev->dev, ++ "Setting indirect %d to 0x%04x on %d\n", ++ regop.reg, regop.val, chan->chanpos); ++ wcaxx_proslic_setreg_indirect(wc, mod, regop.reg, ++ regop.val); ++ } else { ++ regop.val &= 0xff; ++ if (regop.reg == LINE_STATE) { ++ /* Set feedback register to indicate the new ++ * state that is being set */ ++ fxs->lasttxhook = (regop.val & 0x0f) | ++ SLIC_LF_OPPENDING; ++ } ++ dev_info(&wc->xb.pdev->dev, ++ "Setting direct %d to %04x on %d\n", ++ regop.reg, regop.val, chan->chanpos); ++ wcaxx_setreg(wc, mod, regop.reg, regop.val); ++ } ++ break; ++ case WCTDM_SET_ECHOTUNE: ++ dev_info(&wc->xb.pdev->dev, "-- Setting echo registers:\n"); ++ if (copy_from_user(&echoregs, (__user void *) data, ++ sizeof(echoregs))) ++ return -EFAULT; ++ ++ if (mod->type == FXO) { ++ /* Set the ACIM register */ ++ wcaxx_setreg(wc, mod, 30, echoregs.acim); ++ ++ /* Set the digital echo canceller registers */ ++ wcaxx_setreg(wc, mod, 45, echoregs.coef1); ++ wcaxx_setreg(wc, mod, 46, echoregs.coef2); ++ wcaxx_setreg(wc, mod, 47, echoregs.coef3); ++ wcaxx_setreg(wc, mod, 48, echoregs.coef4); ++ wcaxx_setreg(wc, mod, 49, echoregs.coef5); ++ wcaxx_setreg(wc, mod, 50, echoregs.coef6); ++ wcaxx_setreg(wc, mod, 51, echoregs.coef7); ++ wcaxx_setreg(wc, mod, 52, echoregs.coef8); ++ ++ dev_info(&wc->xb.pdev->dev, "-- Set echo registers successfully\n"); ++ ++ break; ++ } else { ++ return -EINVAL; ++ ++ } ++ break; ++ case DAHDI_SET_HWGAIN: ++ if (copy_from_user(&hwgain, (__user void *) data, ++ sizeof(hwgain))) ++ return -EFAULT; ++ ++ wcaxx_set_hwgain(wc, mod, hwgain.newgain, hwgain.tx); ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "Setting hwgain on channel %d to %d for %s direction\n", ++ chan->chanpos-1, hwgain.newgain, ++ ((hwgain.tx) ? "tx" : "rx")); ++ } ++ break; ++ case DAHDI_TONEDETECT: ++ /* Hardware DTMF detection is not supported. */ ++ return -ENOSYS; ++ case DAHDI_SETPOLARITY: ++ if (get_user(x, (__user int *) data)) ++ return -EFAULT; ++ if (mod->type != FXS) ++ return -EINVAL; ++ /* Can't change polarity while ringing or when open */ ++ if (((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_RINGING) || ++ ((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_OPEN)) { ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d Unable to Set Polarity\n", ++ chan->chanpos - 1); ++ } ++ return -EINVAL; ++ } ++ ++ fxs->reversepolarity = (x) ? 1 : 0; ++ ++ if (POLARITY_XOR(fxs)) { ++ fxs->idletxhookstate |= SLIC_LF_REVMASK; ++ x = fxs->lasttxhook & SLIC_LF_SETMASK; ++ x |= SLIC_LF_REVMASK; ++ if (x != fxs->lasttxhook) { ++ x = set_lasttxhook_interruptible(wc, fxs, x, ++ &mod->sethook); ++ if ((debug & DEBUG_CARD) && x) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d TIMEOUT: Set Reverse Polarity\n", ++ chan->chanpos - 1); ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d Set Reverse Polarity\n", ++ chan->chanpos - 1); ++ } ++ } ++ } else { ++ fxs->idletxhookstate &= ~SLIC_LF_REVMASK; ++ x = fxs->lasttxhook & SLIC_LF_SETMASK; ++ x &= ~SLIC_LF_REVMASK; ++ if (x != fxs->lasttxhook) { ++ x = set_lasttxhook_interruptible(wc, fxs, x, ++ &mod->sethook); ++ if ((debug & DEBUG_CARD) & x) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d TIMEOUT: Set Normal Polarity\n", ++ chan->chanpos - 1); ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->xb.pdev->dev, ++ "Channel %d Set Normal Polarity\n", ++ chan->chanpos - 1); ++ } ++ } ++ } ++ break; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static int wcaxx_open(struct dahdi_chan *chan) ++{ ++ struct wcaxx *const wc = chan->pvt; ++ unsigned long flags; ++ struct wcaxx_module *const mod = &wc->mods[chan->chanpos - 1]; ++ ++#if 0 ++ if (wc->dead) ++ return -ENODEV; ++#endif ++ if (mod->type == FXO) { ++ /* Reset the mwi indicators */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->mod.fxo.neonmwi_debounce = 0; ++ mod->mod.fxo.neonmwi_offcounter = 0; ++ mod->mod.fxo.neonmwi_state = 0; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++ ++ return 0; ++} ++ ++static inline struct wcaxx *span_to_wcaxx(struct dahdi_span *span) ++{ ++ struct wcaxx *wc = container_of(span, struct wcaxx, span); ++ return wc; ++} ++ ++static int wcaxx_watchdog(struct dahdi_span *span, int event) ++{ ++ struct wcaxx *wc = span_to_wcaxx(span); ++ dev_info(&wc->xb.pdev->dev, "TDM: Called watchdog\n"); ++ return 0; ++} ++ ++static int wcaxx_close(struct dahdi_chan *chan) ++{ ++ struct wcaxx *wc; ++ int x; ++ ++ wc = chan->pvt; ++ for (x = 0; x < wc->mods_per_board; x++) { ++ struct wcaxx_module *const mod = &wc->mods[x]; ++ if (FXS == mod->type) { ++ mod->mod.fxs.idletxhookstate = ++ POLARITY_XOR(&mod->mod.fxs) ? SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ } ++ } ++ ++ return 0; ++} ++ ++static int wcaxx_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) ++{ ++ struct wcaxx *wc = chan->pvt; ++ struct wcaxx_module *const mod = &wc->mods[chan->chanpos - 1]; ++ ++ if (mod->type == FXO) { ++ switch (txsig) { ++ case DAHDI_TXSIG_START: ++ case DAHDI_TXSIG_OFFHOOK: ++ mod->mod.fxo.offhook = 1; ++ mod->sethook = CMD_WR(5, 0x9); ++ /* wcaxx_setreg(wc, chan->chanpos - 1, 5, 0x9); */ ++ break; ++ case DAHDI_TXSIG_ONHOOK: ++ mod->mod.fxo.offhook = 0; ++ mod->sethook = CMD_WR(5, 0x8); ++ /* wcaxx_setreg(wc, chan->chanpos - 1, 5, 0x8); */ ++ break; ++ default: ++ dev_notice(&wc->xb.pdev->dev, ++ "Can't set tx state to %d\n", txsig); ++ break; ++ } ++ } else if (mod->type == FXS) { ++ wcaxx_fxs_hooksig(wc, mod, txsig); ++ } ++ return 0; ++} ++ ++static void wcaxx_dacs_connect(struct wcaxx *wc, int srccard, int dstcard) ++{ ++ struct wcaxx_module *const srcmod = &wc->mods[srccard]; ++ struct wcaxx_module *const dstmod = &wc->mods[dstcard]; ++ unsigned int type; ++ ++ if (wc->mods[dstcard].dacssrc > -1) { ++ dev_notice(&wc->xb.pdev->dev, "wcaxx_dacs_connect: Can't have double sourcing yet!\n"); ++ return; ++ } ++ type = wc->mods[srccard].type; ++ if ((type == FXS) || (type == FXO)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "wcaxx_dacs_connect: Unsupported modtype for " ++ "card %d\n", srccard); ++ return; ++ } ++ type = wc->mods[dstcard].type; ++ if ((type != FXS) && (type != FXO)) { ++ dev_notice(&wc->xb.pdev->dev, ++ "wcaxx_dacs_connect: Unsupported modtype " ++ "for card %d\n", dstcard); ++ return; ++ } ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "connect %d => %d\n", srccard, dstcard); ++ } ++ ++ dstmod->dacssrc = srccard; ++ ++ /* make srccard transmit to srccard+24 on the TDM bus */ ++ if (srcmod->type == FXS) { ++ /* proslic */ ++ wcaxx_setreg(wc, srcmod, PCM_XMIT_START_COUNT_LSB, ++ ((srccard+24) * 8) & 0xff); ++ wcaxx_setreg(wc, srcmod, PCM_XMIT_START_COUNT_MSB, ++ ((srccard+24) * 8) >> 8); ++ } else if (srcmod->type == FXO) { ++ /* daa TX */ ++ wcaxx_setreg(wc, srcmod, 34, ((srccard+24) * 8) & 0xff); ++ wcaxx_setreg(wc, srcmod, 35, ((srccard+24) * 8) >> 8); ++ } ++ ++ /* have dstcard receive from srccard+24 on the TDM bus */ ++ if (dstmod->type == FXS) { ++ /* proslic */ ++ wcaxx_setreg(wc, dstmod, PCM_RCV_START_COUNT_LSB, ++ ((srccard+24) * 8) & 0xff); ++ wcaxx_setreg(wc, dstmod, PCM_RCV_START_COUNT_MSB, ++ ((srccard+24) * 8) >> 8); ++ } else if (dstmod->type == FXO) { ++ /* daa RX */ ++ wcaxx_setreg(wc, dstmod, 36, ((srccard+24) * 8) & 0xff); ++ wcaxx_setreg(wc, dstmod, 37, ((srccard+24) * 8) >> 8); ++ } ++} ++ ++static void wcaxx_dacs_disconnect(struct wcaxx *wc, int card) ++{ ++ struct wcaxx_module *const mod = &wc->mods[card]; ++ struct wcaxx_module *dacssrc; ++ ++ if (mod->dacssrc <= -1) ++ return; ++ ++ dacssrc = &wc->mods[mod->dacssrc]; ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "wcaxx_dacs_disconnect: restoring TX for %d and RX for %d\n", ++ mod->dacssrc, card); ++ } ++ ++ /* restore TX (source card) */ ++ if (dacssrc->type == FXS) { ++ wcaxx_setreg(wc, dacssrc, PCM_XMIT_START_COUNT_LSB, ++ (mod->dacssrc * 8) & 0xff); ++ wcaxx_setreg(wc, dacssrc, PCM_XMIT_START_COUNT_MSB, ++ (mod->dacssrc * 8) >> 8); ++ } else if (dacssrc->type == FXO) { ++ wcaxx_setreg(wc, mod, 34, (card * 8) & 0xff); ++ wcaxx_setreg(wc, mod, 35, (card * 8) >> 8); ++ } else { ++ dev_warn(&wc->xb.pdev->dev, ++ "WARNING: wcaxx_dacs_disconnect() called " ++ "on unsupported modtype\n"); ++ } ++ ++ /* restore RX (this card) */ ++ if (FXS == mod->type) { ++ wcaxx_setreg(wc, mod, PCM_RCV_START_COUNT_LSB, ++ (card * 8) & 0xff); ++ wcaxx_setreg(wc, mod, PCM_RCV_START_COUNT_MSB, ++ (card * 8) >> 8); ++ } else if (FXO == mod->type) { ++ wcaxx_setreg(wc, mod, 36, (card * 8) & 0xff); ++ wcaxx_setreg(wc, mod, 37, (card * 8) >> 8); ++ } else { ++ dev_warn(&wc->xb.pdev->dev, ++ "WARNING: wcaxx_dacs_disconnect() called " ++ "on unsupported modtype\n"); ++ } ++ ++ mod->dacssrc = -1; ++} ++ ++static int wcaxx_dacs(struct dahdi_chan *dst, struct dahdi_chan *src) ++{ ++ struct wcaxx *wc; ++ ++ if (!nativebridge) ++ return 0; /* should this return -1 since unsuccessful? */ ++ ++ wc = dst->pvt; ++ ++ if (src) { ++ wcaxx_dacs_connect(wc, src->chanpos - 1, dst->chanpos - 1); ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "dacs connecct: %d -> %d!\n\n", ++ src->chanpos, dst->chanpos); ++ } ++ } else { ++ wcaxx_dacs_disconnect(wc, dst->chanpos - 1); ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "dacs disconnect: %d!\n", dst->chanpos); ++ } ++ } ++ return 0; ++} ++ ++/** ++ * wcaxx_chanconfig - Called when the channels are being configured. ++ * ++ * Ensure that the card is completely ready to go before we allow the channels ++ * to be completely configured. This is to allow lengthy initialization ++ * actions to take place in background on driver load and ensure we're synced ++ * up by the time dahdi_cfg is run. ++ * ++ */ ++static int ++wcaxx_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype) ++{ ++ struct wcaxx *wc = chan->pvt; ++ if ((file->f_flags & O_NONBLOCK) && !is_initialized(wc)) ++ return -EAGAIN; ++ return 0; ++} ++ ++/* ++ * wcaxx_assigned - Called when span is assigned. ++ * @span: The span that is now assigned. ++ * ++ * This function is called by the core of DAHDI after the span number and ++ * channel numbers have been assigned. ++ * ++ */ ++static void wcaxx_assigned(struct dahdi_span *span) ++{ ++ struct dahdi_span *s; ++ struct dahdi_device *ddev = span->parent; ++ struct wcaxx *wc = NULL; ++ ++ list_for_each_entry(s, &ddev->spans, device_node) { ++ wc = container_of(s, struct wcaxx, span); ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags)) ++ return; ++ } ++} ++ ++static const struct dahdi_span_ops wcaxx_span_ops = { ++ .owner = THIS_MODULE, ++ .hooksig = wcaxx_hooksig, ++ .open = wcaxx_open, ++ .close = wcaxx_close, ++ .ioctl = wcaxx_ioctl, ++ .watchdog = wcaxx_watchdog, ++ .chanconfig = wcaxx_chanconfig, ++ .dacs = wcaxx_dacs, ++ .assigned = wcaxx_assigned, ++ .echocan_create = wcaxx_echocan_create, ++ .echocan_name = wcaxx_echocan_name, ++}; ++ ++static struct wcaxx_chan * ++wcaxx_init_chan(struct wcaxx *wc, struct dahdi_span *s, int channo) ++{ ++ struct wcaxx_chan *c; ++ ++ c = kzalloc(sizeof(*c), GFP_KERNEL); ++ if (!c) ++ return NULL; ++ ++ snprintf(c->chan.name, sizeof(c->chan.name), "WCTDM/%d/%d", ++ wc->num, channo); ++ c->chan.chanpos = channo+1; ++ c->chan.span = s; ++ c->chan.pvt = wc; ++ c->timeslot = channo; ++ return c; ++} ++ ++static void wcaxx_init_span(struct wcaxx *wc) ++{ ++ int x; ++ struct wcaxx_chan *c; ++ struct dahdi_echocan_state *ec[NUM_MODULES] = {NULL, }; ++ ++ /* DAHDI stuff */ ++ wc->span.offset = 0; ++ ++ sprintf(wc->span.name, "WCTDM/%d", wc->num); ++ ++ snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, ++ "%s", wc->desc->name); ++ ++ if (wc->companding == DAHDI_LAW_DEFAULT) { ++ wc->span.deflaw = DAHDI_LAW_MULAW; ++ } else if (wc->companding == DAHDI_LAW_ALAW) { ++ /* Force everything to alaw */ ++ wc->span.deflaw = DAHDI_LAW_ALAW; ++ } else { ++ /* Auto set to ulaw */ ++ wc->span.deflaw = DAHDI_LAW_MULAW; ++ } ++ ++ wc->span.ops = &wcaxx_span_ops; ++ wc->span.flags = DAHDI_FLAG_RBS; ++ wc->span.spantype = SPANTYPE_ANALOG_MIXED; ++ ++ wc->span.chans = kmalloc(sizeof(wc->span.chans[0]) * wc->desc->ports, ++ GFP_KERNEL); ++ if (!wc->span.chans) ++ return; ++ ++ /* allocate channels for the span */ ++ for (x = 0; x < wc->desc->ports; x++) { ++ c = wcaxx_init_chan(wc, &wc->span, x); ++ if (!c) ++ return; ++ wc->chans[x] = c; ++ wc->span.chans[x] = &c->chan; ++ ++ /* TODO: Should echocan state hide under VPM_ENABLED or does ++ * software ec use it? */ ++ ec[x] = kzalloc(sizeof(*ec[x]), GFP_KERNEL); ++ } ++ ++ wc->span.channels = wc->desc->ports; ++ memcpy(wc->ec, ec, sizeof(wc->ec)); ++ memset(ec, 0, sizeof(ec)); ++} ++ ++/** ++ * should_set_alaw() - Should be called after all the spans are initialized. ++ * ++ * Returns true if the module companding should be set to alaw, otherwise ++ * false. ++ */ ++static bool should_set_alaw(const struct wcaxx *wc) ++{ ++ if (DAHDI_LAW_ALAW == wc->companding) ++ return true; ++ else ++ return false; ++} ++ ++static void wcaxx_fixup_span(struct wcaxx *wc) ++{ ++ struct dahdi_span *s; ++ int x, y; ++ ++ y = 0; ++ s = &wc->span; ++ ++ for (x = 0; x < wc->desc->ports; x++) { ++ struct wcaxx_module *const mod = &wc->mods[x]; ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "fixup_analog: x=%d, y=%d modtype=%d, " ++ "s->chans[%d]=%p\n", x, y, mod->type, ++ y, s->chans[y]); ++ } ++ if (mod->type == FXO) { ++ int val; ++ s->chans[y++]->sigcap = DAHDI_SIG_FXSKS | ++ DAHDI_SIG_FXSLS | DAHDI_SIG_SF | ++ DAHDI_SIG_CLEAR; ++ val = should_set_alaw(wc) ? 0x20 : 0x28; ++#ifdef DEBUG ++ val = (digitalloopback) ? 0x30 : val; ++#endif ++ wcaxx_setreg(wc, mod, 33, val); ++ wcaxx_voicedaa_set_ts(wc, mod, wc->chans[x]->timeslot); ++ } else if (mod->type == FXS) { ++ ++ /* NOTE: Digital loopback does not work on the FXS ++ * modules in the same way since the data is still ++ * companded by the ProSLIC and doesn't appear to have ++ * perfect symetry. */ ++ ++ s->chans[y++]->sigcap = DAHDI_SIG_FXOKS | ++ DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | ++ DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; ++ wcaxx_setreg(wc, mod, 1, ++ (should_set_alaw(wc) ? 0x20 : 0x28)); ++ wcaxx_proslic_set_ts(wc, mod, wc->chans[x]->timeslot); ++ } else { ++ s->chans[y++]->sigcap = 0; ++ } ++ } ++} ++ ++static bool wcaxx_init_fxs_port(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ u8 readi; ++ enum {UNKNOWN = 0, SANE = 1}; ++ int ret = wcaxx_init_proslic(wc, mod, 0, 0, UNKNOWN); ++ if (!ret) { ++ if (debug & DEBUG_CARD) { ++ readi = wcaxx_getreg(wc, mod, LOOP_I_LIMIT); ++ dev_info(&wc->xb.pdev->dev, ++ "Proslic module %d loop current is %dmA\n", ++ mod->card, ((readi*3) + 20)); ++ } ++ return true; ++ } ++ ++ if (ret != -2) { ++ /* Init with Manual Calibration */ ++ if (!wcaxx_init_proslic(wc, mod, 0, 1, SANE)) { ++ if (debug & DEBUG_CARD) { ++ readi = wcaxx_getreg(wc, mod, LOOP_I_LIMIT); ++ dev_info(&wc->xb.pdev->dev, ++ "Proslic module %d loop current is %dmA\n", ++ mod->card, ((readi*3)+20)); ++ } ++ } else { ++ dev_notice(&wc->xb.pdev->dev, ++ "Port %d: FAILED FXS (%s)\n", mod->card + 1, ++ fxshonormode ? fxo_modes[_opermode].name : ++ "FCC"); ++ } ++ return true; ++ } ++ return false; ++} ++ ++static void wcaxx_reset_module(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ ++ u32 reg_val = (1UL << (mod->spi->chip_select + 12)); ++ wcxb_gpio_clear(&wc->xb, reg_val); ++ udelay(500); ++ wcxb_gpio_set(&wc->xb, reg_val); ++ msleep(250); /* TODO: What should this value be? */ ++} ++ ++static bool check_for_single_fxs(struct wcaxx *wc, unsigned int port) ++{ ++ bool result; ++ struct wcaxx_module *mod = &wc->mods[port]; ++ ++ mod->spi = get_spi_device_for_port(wc, mod->card, false); ++ mod->subaddr = 0; ++ wcaxx_reset_module(wc, mod); ++ wcaxx_fxsinit(mod->spi); ++ result = wcaxx_init_fxs_port(wc, mod); ++ if (!result) ++ mod->type = NONE; ++ ++ /* It is currently unclear why this read is necessary for some of the ++ * S100M modules to properly function. */ ++ wcaxx_getreg(wc, mod, 0x00); ++ return result; ++} ++ ++static bool check_for_single_fxo(struct wcaxx *wc, unsigned int port) ++{ ++ bool result; ++ struct wcaxx_module *mod = &wc->mods[port]; ++ mod->spi = get_spi_device_for_port(wc, mod->card, false); ++ mod->subaddr = 0; ++ wcaxx_reset_module(wc, mod); ++ result = (wcaxx_init_voicedaa(wc, mod, 0, 0, 0) == 0); ++ if (!result) ++ mod->type = NONE; ++ return result; ++} ++ ++static bool check_for_quad_fxs(struct wcaxx *wc, unsigned int base_port) ++{ ++ int port; ++ int offset; ++ struct wcaxx_module *mod = &wc->mods[base_port + 1]; ++ ++ /* Cannot have quad port modules on the 4 port base cards. */ ++ if (is_four_port(wc)) ++ return false; ++ ++ /* We can assume that the base port has already been configured as an ++ * FXS port if we're even in this function */ ++ mod->spi = get_spi_device_for_port(wc, mod->card, true); ++ mod->subaddr = offset = 1; ++ if (wcaxx_init_fxs_port(wc, mod)) { ++ /* This must be a 4 port FXS module... */ ++ for (port = base_port + 2; port < base_port+4; ++port) { ++ mod = &wc->mods[port]; ++ mod->spi = get_spi_device_for_port(wc, mod->card, true); ++ mod->subaddr = ++offset; ++ if (!wcaxx_init_fxs_port(wc, mod)) { ++ /* This means that a quad-module failed to ++ * setup ports 3 or 4? */ ++ dev_err(&wc->xb.pdev->dev, ++ "Quad-FXS at base %d failed initialization.\n", ++ base_port); ++ goto error_exit; ++ } ++ } ++ return true; ++ } ++error_exit: ++ for (port = base_port + 1; port < base_port + 4; ++port) { ++ mod = &wc->mods[port]; ++ mod->type = NONE; ++ } ++ return false; ++} ++ ++static bool check_for_quad_fxo(struct wcaxx *wc, unsigned int base_port) ++{ ++ int port; ++ int offset; ++ struct wcaxx_module *mod = &wc->mods[base_port + 1]; ++ ++ /* Cannot have quad port modules on the 4 port base cards. */ ++ if (is_four_port(wc)) ++ return false; ++ ++ /* We can assume that the base port has already been configured as an ++ * FXO port if we're even in this function */ ++ mod->spi = get_spi_device_for_port(wc, mod->card, true); ++ mod->subaddr = offset = 1; ++ if (!wcaxx_init_voicedaa(wc, mod, 0, 0, 0)) { ++ /* This must be a 4 port FXO module. */ ++ for (port = base_port + 2; port < base_port + 4; ++port) { ++ mod = &wc->mods[port]; ++ mod->spi = get_spi_device_for_port(wc, mod->card, true); ++ mod->subaddr = ++offset; ++ if (wcaxx_init_voicedaa(wc, mod, 0, 0, 0)) { ++ dev_err(&wc->xb.pdev->dev, ++ "Quad-FXO at base %d failed initialization.\n", ++ base_port); ++ goto error_exit; ++ } ++ } ++ return true; ++ } ++error_exit: ++ for (port = base_port + 1; port < base_port + 4; ++port) { ++ mod = &wc->mods[port]; ++ mod->type = NONE; ++ } ++ return false; ++} ++ ++static void __wcaxx_identify_four_port_module_group(struct wcaxx *wc) ++{ ++ int i; ++ for (i = 0; i < wc->desc->ports; i++) { ++ if (!check_for_single_fxs(wc, i)) ++ check_for_single_fxo(wc, i); ++ } ++ return; ++} ++ ++static void ++__wcaxx_identify_module_group(struct wcaxx *wc, unsigned long base) ++{ ++ if (check_for_single_fxs(wc, base)) { ++ if (check_for_quad_fxs(wc, base)) { ++ /* S400M installed */ ++ return; ++ } else if (check_for_single_fxs(wc, base + 1)) { ++ /* Two S110M installed */ ++ return; ++ } else if (check_for_single_fxo(wc, base + 1)) { ++ /* 1 S110M 1 X100M */ ++ return; ++ } else { ++ /* 1 S110M 1 Empty */ ++ return; ++ } ++ } else if (check_for_single_fxo(wc, base)) { ++ if (check_for_quad_fxo(wc, base)) { ++ /* X400M installed */ ++ return; ++ } else if (check_for_single_fxo(wc, base + 1)) { ++ /* Two X100M installed */ ++ return; ++ } else if (check_for_single_fxs(wc, base + 1)) { ++ /* 1 X100M 1 S100M installed */ ++ return; ++ } else { ++ /* 1 X100M 1 Empty */ ++ return; ++ } ++ } else if (check_for_single_fxs(wc, base + 1)) { ++ /* 1 Empty 1 S110M installed */ ++ return; ++ } else if (check_for_single_fxo(wc, base + 1)) { ++ /* 1 Empty 1 X100M installed */ ++ return; ++ } ++ /* No module */ ++ return; ++} ++ ++/** ++ * wcaxx_print_moule_configuration - Print the configuration to the kernel log ++ * @wc: The card we're interested in. ++ * ++ * This is to ensure that the module configuration from each card shows up ++ * sequentially in the kernel log, as opposed to interleaved with one another. ++ * ++ */ ++static void wcaxx_print_module_configuration(const struct wcaxx *const wc) ++{ ++ int i; ++ static DEFINE_MUTEX(print); ++ ++ mutex_lock(&print); ++ for (i = 0; i < wc->mods_per_board; ++i) { ++ const struct wcaxx_module *const mod = &wc->mods[i]; ++ ++ switch (mod->type) { ++ case FXO: ++ dev_info(&wc->xb.pdev->dev, ++ "Port %d: Installed -- AUTO FXO (%s mode)\n", ++ i + 1, fxo_modes[_opermode].name); ++ break; ++ case FXS: ++ dev_info(&wc->xb.pdev->dev, ++ "Port %d: Installed -- AUTO FXS/DPO\n", i + 1); ++ break; ++ case NONE: ++ dev_info(&wc->xb.pdev->dev, ++ "Port %d: Not installed\n", i + 1); ++ break; ++ } ++ } ++ mutex_unlock(&print); ++} ++ ++static void wcaxx_identify_modules(struct wcaxx *wc) ++{ ++ int x; ++ unsigned long flags; ++ ++ /* A8A/A8B - Reset the modules. */ ++ wcxb_gpio_clear(&wc->xb, 0xf000); ++ msleep(50); /* TODO: what should these values be? */ ++ wcxb_gpio_set(&wc->xb, 0xf000); ++ msleep(250); /* TODO: What should these values be? */ ++ ++ /* Place all units in the daisy chain mode of operation. This allows ++ * multiple devices to share a chip select (like on the X400 and S400 ++ * modules) */ ++ for (x = 0; x < ARRAY_SIZE(wc->spi_devices); ++x) ++ wcaxx_fxsinit(wc->spi_devices[x]); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->mods_per_board = wc->desc->ports; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ BUG_ON(wc->desc->ports % 4); ++ ++ if (is_four_port(wc)) { ++ __wcaxx_identify_four_port_module_group(wc); ++ } else { ++ for (x = 0; x < wc->desc->ports/4; x++) ++ __wcaxx_identify_module_group(wc, x*4); ++ } ++ ++ wcaxx_print_module_configuration(wc); ++} ++ ++static struct pci_driver wcaxx_driver; ++ ++static void wcaxx_back_out_gracefully(struct wcaxx *wc) ++{ ++ int i; ++ unsigned long flags; ++ ++ clear_bit(INITIALIZED, &wc->bit_flags); ++ smp_mb__after_atomic(); ++ ++ /* Make sure we're not on the card list anymore. */ ++ mutex_lock(&card_list_lock); ++ list_del(&wc->card_node); ++ mutex_unlock(&card_list_lock); ++ ++ wcxb_release(&wc->xb); ++ ++ for (i = 0; i < wc->mods_per_board; i++) { ++ struct wcaxx_module *const mod = &wc->mods[i]; ++ kfree(mod->mod_poll); ++ mod->mod_poll = NULL; ++ } ++ ++ kfree(wc->span.chans); ++ wc->span.chans = NULL; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ for (i = 0; i < wc->span.channels; ++i) { ++ kfree(wc->chans[i]); ++ kfree(wc->ec[i]); ++ wc->chans[i] = NULL; ++ wc->ec[i] = NULL; ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ for (i = 0; i < ARRAY_SIZE(wc->spi_devices); i++) ++ wcxb_spi_device_destroy(wc->spi_devices[i]); ++ wcxb_spi_master_destroy(wc->master); ++ ++ kfree(wc->board_name); ++ if (wc->ddev) { ++ kfree(wc->ddev->devicetype); ++ kfree(wc->ddev->location); ++ kfree(wc->ddev->hardware_id); ++ dahdi_free_device(wc->ddev); ++ } ++ kfree(wc); ++} ++ ++static void wcaxx_handle_error(struct wcxb *xb) ++{ ++ struct wcaxx *wc = container_of(xb, struct wcaxx, xb); ++ wc->ddev->irqmisses++; ++} ++ ++static const struct wcxb_operations wcxb_operations = { ++ .handle_receive = wcaxx_handle_receive, ++ .handle_transmit = wcaxx_handle_transmit, ++ .handle_error = wcaxx_handle_error, ++}; ++ ++struct cmd_results { ++ u8 results[8]; ++}; ++ ++static int wcaxx_check_firmware(struct wcaxx *wc) ++{ ++ char *filename; ++ u32 firmware_version; ++ const bool force_firmware = false; ++ const unsigned int A4A_VERSION = 0x0a0017; ++ const unsigned int A4B_VERSION = 0x0d001e; ++ const unsigned int A8A_VERSION = 0x1d0017; ++ const unsigned int A8B_VERSION = 0x1f001e; ++ ++ if (wc->desc == &device_a8a) { ++ firmware_version = A8A_VERSION; ++ filename = "dahdi-fw-a8a.bin"; ++ } else if (wc->desc == &device_a8b) { ++ firmware_version = A8B_VERSION; ++ filename = "dahdi-fw-a8b.bin"; ++ } else if (wc->desc == &device_a4a) { ++ firmware_version = A4A_VERSION; ++ filename = "dahdi-fw-a4a.bin"; ++ } else if (wc->desc == &device_a4b) { ++ firmware_version = A4B_VERSION; ++ filename = "dahdi-fw-a4b.bin"; ++ } else { ++ /* This is a bug in the driver code */ ++ WARN_ON(1); ++ return 0; ++ } ++ ++ return wcxb_check_firmware(&wc->xb, firmware_version, ++ filename, force_firmware, WCXB_RESET_NOW); ++} ++ ++static void wcaxx_check_sethook(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ if (mod->sethook) { ++ wcaxx_setreg(wc, mod, ((mod->sethook >> 8) & 0xff), ++ mod->sethook & 0xff); ++ mod->sethook = 0; ++ } ++} ++ ++static void wcaxx_poll_fxs_complete(void *arg) ++{ ++ struct wcaxx_mod_poll *poll_fxs = arg; ++ struct wcaxx *wc = poll_fxs->wc; ++ struct wcaxx_module *const mod = poll_fxs->mod; ++ ++ if (!is_initialized(wc)) { ++ kfree(poll_fxs); ++ return; ++ } ++ ++ mod->mod.fxs.hook_state_shadow = poll_fxs->buffer[2]; ++ mod->mod.fxs.linefeed_control_shadow = poll_fxs->buffer[5]; ++ wcaxx_isr_misc_fxs(poll_fxs->wc, poll_fxs->mod); ++ memcpy(poll_fxs->buffer, poll_fxs->master_buffer, ++ sizeof(poll_fxs->buffer)); ++ wcaxx_check_sethook(poll_fxs->wc, poll_fxs->mod); ++ mod->mod_poll = poll_fxs; ++} ++ ++/** ++ * wcaxx_start_poll_fxs - Starts the interrupt polling loop for FXS modules. ++ * ++ * To stop the polling loop, clear the initialized bit and then flush the ++ * pending wcxb_spi messages. ++ * ++ */ ++static int wcaxx_start_poll_fxs(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ struct wcaxx_mod_poll *mod_poll = kzalloc(sizeof(*mod_poll), ++ GFP_KERNEL); ++ struct wcxb_spi_message *m = &mod_poll->m; ++ struct wcxb_spi_transfer *t = &mod_poll->t; ++ ++ WARN_ON(!is_initialized(wc)); ++ if (!mod_poll) ++ return -ENOMEM; ++ ++ memset(t, 0, sizeof(*t)); ++ wcxb_spi_message_init(m); ++ ++ t->tx_buf = t->rx_buf = mod_poll->buffer; ++ t->len = sizeof(mod_poll->buffer); ++ wcxb_spi_message_add_tail(t, m); ++ mod_poll->wc = wc; ++ mod_poll->mod = mod; ++ ++ mod_poll->master_buffer[0] = 1 << mod_poll->mod->subaddr; ++ mod_poll->master_buffer[1] = (LOOP_STAT | 0x80) & 0xff; ++ mod_poll->master_buffer[2] = 0; ++ ++ mod_poll->master_buffer[3] = mod_poll->master_buffer[0]; ++ mod_poll->master_buffer[4] = (LINE_STATE | 0x80) & 0xff; ++ mod_poll->master_buffer[5] = 0; ++ ++ memcpy(mod_poll->buffer, mod_poll->master_buffer, ++ sizeof(mod_poll->buffer)); ++ ++ m->arg = mod_poll; ++ m->complete = &wcaxx_poll_fxs_complete; ++ wcxb_spi_async(mod->spi, m); ++ return 0; ++} ++ ++static void wcaxx_poll_fxo_complete(void *arg) ++{ ++ struct wcaxx_mod_poll *poll_fxo = arg; ++ struct wcaxx *wc = poll_fxo->wc; ++ struct wcaxx_module *const mod = poll_fxo->mod; ++ ++ if (!is_initialized(wc)) { ++ kfree(poll_fxo); ++ return; ++ } ++ ++ mod->mod.fxo.hook_ring_shadow = poll_fxo->buffer[2]; ++ mod->mod.fxo.line_voltage_status = poll_fxo->buffer[5]; ++ wcaxx_voicedaa_check_hook(poll_fxo->wc, poll_fxo->mod); ++ memcpy(poll_fxo->buffer, poll_fxo->master_buffer, ++ sizeof(poll_fxo->buffer)); ++ wcaxx_check_sethook(poll_fxo->wc, poll_fxo->mod); ++ mod->mod_poll = poll_fxo; ++} ++ ++/** ++ * wcaxx_start_poll_fxo - Starts the interrupt polling loop for FXS modules. ++ * ++ * To stop the polling loop, clear the initialized bit and then flush the ++ * pending wcxb_spi messages. ++ * ++ */ ++static int wcaxx_start_poll_fxo(struct wcaxx *wc, struct wcaxx_module *mod) ++{ ++ static const int ADDRS[4] = {0x00, 0x08, 0x04, 0x0c}; ++ struct wcaxx_mod_poll *poll_fxo = kzalloc(sizeof(*poll_fxo), ++ GFP_KERNEL); ++ struct wcxb_spi_message *m = &poll_fxo->m; ++ struct wcxb_spi_transfer *t = &poll_fxo->t; ++ ++ WARN_ON(!is_initialized(wc)); ++ if (!poll_fxo) ++ return -ENOMEM; ++ ++ memset(t, 0, sizeof(*t)); ++ wcxb_spi_message_init(m); ++ ++ t->tx_buf = t->rx_buf = poll_fxo->buffer; ++ t->len = sizeof(poll_fxo->buffer); ++ wcxb_spi_message_add_tail(t, m); ++ poll_fxo->wc = wc; ++ poll_fxo->mod = mod; ++ ++ poll_fxo->master_buffer[0] = 0x60 | ADDRS[poll_fxo->mod->subaddr]; ++ poll_fxo->master_buffer[1] = 5 & 0x7f; /* Hook / Ring State */ ++ poll_fxo->master_buffer[2] = 0; ++ ++ poll_fxo->master_buffer[3] = poll_fxo->master_buffer[0]; ++ poll_fxo->master_buffer[4] = 29 & 0x7f; /* Battery */ ++ poll_fxo->master_buffer[5] = 0; ++ ++ memcpy(poll_fxo->buffer, poll_fxo->master_buffer, ++ sizeof(poll_fxo->buffer)); ++ ++ m->arg = poll_fxo; ++ m->complete = &wcaxx_poll_fxo_complete; ++ wcxb_spi_async(mod->spi, m); ++ return 0; ++} ++ ++/** ++ * wcaxx_read_serial - Returns the serial number of the board. ++ * @wc: The board whos serial number we are reading. ++ * ++ * The buffer returned is dynamically allocated and must be kfree'd by the ++ * caller. If memory could not be allocated, NULL is returned. ++ * ++ * Must be called in process context. ++ * ++ */ ++static char *wcaxx_read_serial(struct wcaxx *wc) ++{ ++ int i; ++ static const int MAX_SERIAL = 20*5; ++ const unsigned int SERIAL_ADDRESS = 0x1f0000; ++ unsigned char *serial = kzalloc(MAX_SERIAL + 1, GFP_KERNEL); ++ struct wcxb const *xb = &wc->xb; ++ struct wcxb_spi_master *flash_spi_master = NULL; ++ struct wcxb_spi_device *flash_spi_device = NULL; ++ const unsigned int FLASH_SPI_BASE = 0x200; ++ ++ if (!serial) ++ return NULL; ++ ++ flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev, ++ xb->membase + FLASH_SPI_BASE, ++ false); ++ if (!flash_spi_master) ++ return NULL; ++ ++ flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0); ++ if (!flash_spi_device) ++ goto error_exit; ++ ++ wcxb_flash_read(flash_spi_device, SERIAL_ADDRESS, ++ serial, MAX_SERIAL); ++ ++ for (i = 0; i < MAX_SERIAL; ++i) { ++ if ((serial[i] < 0x20) || (serial[i] > 0x7e)) { ++ serial[i] = '\0'; ++ break; ++ } ++ } ++ ++ if (!i) { ++ kfree(serial); ++ serial = NULL; ++ } else { ++ /* Limit the size of the buffer to just what is needed to ++ * actually hold the serial number. */ ++ unsigned char *new_serial; ++ new_serial = kasprintf(GFP_KERNEL, "%s", serial); ++ kfree(serial); ++ serial = new_serial; ++ } ++ ++error_exit: ++ wcxb_spi_device_destroy(flash_spi_device); ++ wcxb_spi_master_destroy(flash_spi_master); ++ return serial; ++} ++ ++static void wcaxx_start_module_polling(struct wcaxx *wc) ++{ ++ int x; ++ WARN_ON(!is_initialized(wc)); ++ for (x = 0; x < wc->mods_per_board; x++) { ++ struct wcaxx_module *const mod = &wc->mods[x]; ++ switch (mod->type) { ++ case FXO: ++ wcaxx_start_poll_fxo(wc, mod); ++ break; ++ case FXS: ++ wcaxx_start_poll_fxs(wc, mod); ++ break; ++ case NONE: ++ break; ++ } ++ } ++ wc->module_poll_time = wc->framecount + MODULE_POLL_TIME_MS; ++} ++ ++/** ++ * t43x_assign_num - Assign wc->num a unique value and place on card_list ++ * ++ */ ++static void wcaxx_assign_num(struct wcaxx *wc) ++{ ++ mutex_lock(&card_list_lock); ++ if (list_empty(&card_list)) { ++ wc->num = 0; ++ list_add(&wc->card_node, &card_list); ++ } else { ++ struct wcaxx *cur; ++ struct list_head *insert_pos; ++ int new_num = 0; ++ ++ insert_pos = &card_list; ++ list_for_each_entry(cur, &card_list, card_node) { ++ if (new_num != cur->num) ++ break; ++ new_num++; ++ insert_pos = &cur->card_node; ++ } ++ ++ wc->num = new_num; ++ list_add_tail(&wc->card_node, insert_pos); ++ } ++ mutex_unlock(&card_list_lock); ++} ++ ++#ifdef USE_ASYNC_INIT ++struct async_data { ++ struct pci_dev *pdev; ++ const struct pci_device_id *ent; ++}; ++static int __devinit ++__wcaxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent, ++ async_cookie_t cookie) ++#else ++static int __devinit ++__wcaxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++#endif ++{ ++ struct wcaxx *wc; ++ int i, ret; ++ int curchan; ++ ++ neonmwi_offlimit_cycles = neonmwi_offlimit / MS_PER_HOOKCHECK; ++ ++ wc = kzalloc(sizeof(*wc), GFP_KERNEL); ++ if (!wc) ++ return -ENOMEM; ++ ++ wcaxx_assign_num(wc); ++ ++ wc->desc = (struct _device_desc *)ent->driver_data; ++ ++ spin_lock_init(&wc->reglock); ++ ++ wc->board_name = kasprintf(GFP_KERNEL, "%s%d", ++ wcaxx_driver.name, wc->num); ++ if (!wc->board_name) { ++ wcaxx_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ ++#ifdef CONFIG_VOICEBUS_DISABLE_ASPM ++ if (is_pcie(wc)) { ++ pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S | ++ PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); ++ }; ++#endif ++ ++ pci_set_drvdata(pdev, wc); ++ wc->xb.ops = &wcxb_operations; ++ wc->xb.pdev = pdev; ++ wc->xb.debug = &debug; ++ ++ ret = wcxb_init(&wc->xb, wc->board_name, int_mode); ++ if (ret) { ++ wcaxx_back_out_gracefully(wc); ++ return ret; ++ } ++ ++ wcxb_set_minlatency(&wc->xb, latency); ++ wcxb_set_maxlatency(&wc->xb, max_latency); ++ ++ ret = wcaxx_check_firmware(wc); ++ if (ret) { ++ wcaxx_back_out_gracefully(wc); ++ return ret; ++ } ++ ++ wcxb_lock_latency(&wc->xb); ++ ++ wc->mods_per_board = NUM_MODULES; ++ ++ if (alawoverride) { ++ companding = "alaw"; ++ dev_info(&wc->xb.pdev->dev, ++ "The module parameter alawoverride has been deprecated. Please use the parameter companding=alaw instead"); ++ } ++ ++ if (!strcasecmp(companding, "alaw")) ++ /* Force this card's companding to alaw */ ++ wc->companding = DAHDI_LAW_ALAW; ++ else if (!strcasecmp(companding, "ulaw")) ++ /* Force this card's companding to ulaw */ ++ wc->companding = DAHDI_LAW_MULAW; ++ else ++ /* Auto detect this card's companding */ ++ wc->companding = DAHDI_LAW_DEFAULT; ++ ++ wc->master = wcxb_spi_master_create(&pdev->dev, ++ wc->xb.membase + 0x280, true); ++ for (i = 0; i < ARRAY_SIZE(wc->spi_devices); i++) ++ wc->spi_devices[i] = wcxb_spi_device_create(wc->master, 3-i); ++ ++ for (i = 0; i < ARRAY_SIZE(wc->mods); i++) { ++ struct wcaxx_module *const mod = &wc->mods[i]; ++ mod->dacssrc = -1; ++ mod->card = i; ++ mod->spi = NULL; ++ mod->subaddr = 0; ++ mod->type = NONE; ++ } ++ ++ ret = wcaxx_vpm_init(wc); ++ if (!ret) ++ wcxb_enable_echocan(&wc->xb); ++ ++ /* Now track down what modules are installed */ ++ wcaxx_identify_modules(wc); ++ ++ /* Start the hardware processing. */ ++ if (wcxb_start(&wc->xb)) { ++ WARN_ON(1); ++ return -EIO; ++ } ++ ++ if (fatal_signal_pending(current)) { ++ wcaxx_back_out_gracefully(wc); ++ return -EINTR; ++ } ++ ++ curchan = 0; ++ wcaxx_init_span(wc); ++ wcaxx_fixup_span(wc); ++ curchan += wc->desc->ports; ++ ++#ifdef USE_ASYNC_INIT ++ async_synchronize_cookie(cookie); ++#endif ++ wc->ddev = dahdi_create_device(); ++ if (!wc->ddev) { ++ wcaxx_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ wc->ddev->manufacturer = "Digium"; ++ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d", ++ pdev->bus->number, ++ PCI_SLOT(pdev->devfn) + 1); ++ if (!wc->ddev->location) { ++ wcaxx_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ ++ if (wc->vpm) ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (%s)", ++ wc->desc->name, "VPMOCT032"); ++ else ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", ++ wc->desc->name); ++ ++ if (!wc->ddev->devicetype) { ++ wcaxx_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ ++ wc->ddev->hardware_id = wcaxx_read_serial(wc); ++ ++ list_add_tail(&wc->span.device_node, &wc->ddev->spans); ++ ++ if (dahdi_register_device(wc->ddev, &wc->xb.pdev->dev)) { ++ dev_notice(&wc->xb.pdev->dev, "Unable to register device with DAHDI\n"); ++ wcaxx_back_out_gracefully(wc); ++ return -1; ++ } ++ ++ dev_info(&wc->xb.pdev->dev, "Found a %s (SN: %s)\n", ++ wc->desc->name, wc->ddev->hardware_id); ++ ++ set_bit(INITIALIZED, &wc->bit_flags); ++ wcaxx_start_module_polling(wc); ++ wcxb_unlock_latency(&wc->xb); ++ return 0; ++} ++ ++#ifdef USE_ASYNC_INIT ++static __devinit void ++wcaxx_init_one_async(void *data, async_cookie_t cookie) ++{ ++ struct async_data *dat = data; ++ __wcaxx_init_one(dat->pdev, dat->ent, cookie); ++ kfree(dat); ++} ++ ++static int __devinit ++wcaxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ struct async_data *dat; ++ ++ dat = kmalloc(sizeof(*dat), GFP_KERNEL); ++ /* If we can't allocate the memory for the async_data, odds are we won't ++ * be able to initialize the device either, but let's try synchronously ++ * anyway... */ ++ if (!dat) ++ return __wcaxx_init_one(pdev, ent, 0); ++ ++ dat->pdev = pdev; ++ dat->ent = ent; ++ async_schedule(wcaxx_init_one_async, dat); ++ return 0; ++} ++#else ++static int __devinit ++wcaxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ return __wcaxx_init_one(pdev, ent); ++} ++#endif ++ ++static void wcaxx_release(struct wcaxx *wc) ++{ ++ if (is_initialized(wc)) ++ dahdi_unregister_device(wc->ddev); ++ ++ wcaxx_back_out_gracefully(wc); ++} ++ ++static void __devexit wcaxx_remove_one(struct pci_dev *pdev) ++{ ++ struct wcaxx *wc = pci_get_drvdata(pdev); ++ ++ if (!wc) ++ return; ++ ++ dev_info(&wc->xb.pdev->dev, "Removing a %s.\n", wc->desc->name); ++ ++ flush_scheduled_work(); ++ wcxb_stop(&wc->xb); ++ ++ if (wc->vpm) ++ release_vpm450m(wc->vpm); ++ wc->vpm = NULL; ++ ++ wcaxx_release(wc); ++} ++ ++static DEFINE_PCI_DEVICE_TABLE(wcaxx_pci_tbl) = { ++ { 0xd161, 0x800d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ (unsigned long) &device_a8b ++ }, ++ { 0xd161, 0x800c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ (unsigned long) &device_a8a ++ }, ++ { 0xd161, 0x8010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ (unsigned long) &device_a4b ++ }, ++ { 0xd161, 0x800f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ (unsigned long) &device_a4a ++ }, ++ { 0 } ++}; ++ ++MODULE_DEVICE_TABLE(pci, wcaxx_pci_tbl); ++ ++static void wcaxx_shutdown(struct pci_dev *pdev) ++{ ++ struct wcaxx *wc = pci_get_drvdata(pdev); ++ wcxb_stop(&wc->xb); ++} ++ ++static int wcaxx_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ return -ENOSYS; ++} ++ ++static struct pci_driver wcaxx_driver = { ++ .name = "wcaxx", ++ .probe = wcaxx_init_one, ++ .remove = __devexit_p(wcaxx_remove_one), ++ .shutdown = wcaxx_shutdown, ++ .suspend = wcaxx_suspend, ++ .id_table = wcaxx_pci_tbl, ++}; ++ ++static int __init wcaxx_init(void) ++{ ++ int res; ++ int x; ++ ++ for (x = 0; x < ARRAY_SIZE(fxo_modes); x++) { ++ if (!strcmp(fxo_modes[x].name, opermode)) ++ break; ++ } ++ if (x < ARRAY_SIZE(fxo_modes)) { ++ _opermode = x; ++ } else { ++ pr_notice("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", ++ opermode); ++ for (x = 0; x < ARRAY_SIZE(fxo_modes); x++) ++ pr_notice(" %s\n", fxo_modes[x].name); ++ pr_notice("Note this option is CASE SENSITIVE!\n"); ++ return -ENODEV; ++ } ++ ++ if (!strcmp(opermode, "AUSTRALIA")) { ++ boostringer = 1; ++ fxshonormode = 1; ++ } ++ ++ if (-1 == fastpickup) { ++ if (!strcmp(opermode, "JAPAN")) ++ fastpickup = 1; ++ else ++ fastpickup = 0; ++ } ++ ++ /* for the voicedaa_check_hook defaults, if the user has not ++ * overridden them by specifying them as module parameters, then get ++ * the values from the selected operating mode */ ++ if (!battdebounce) ++ battdebounce = fxo_modes[_opermode].battdebounce; ++ if (!battalarm) ++ battalarm = fxo_modes[_opermode].battalarm; ++ if (!battthresh) ++ battthresh = fxo_modes[_opermode].battthresh; ++ ++ res = pci_register_driver(&wcaxx_driver); ++ if (res) ++ return -ENODEV; ++ ++#ifdef USE_ASYNC_INIT ++ async_synchronize_full(); ++#endif ++ return 0; ++} ++ ++static void __exit wcaxx_cleanup(void) ++{ ++ pci_unregister_driver(&wcaxx_driver); ++} ++ ++ ++module_param(debug, int, 0600); ++module_param(int_mode, int, 0400); ++MODULE_PARM_DESC(int_mode, ++ "0 = Use MSI interrupt if available. 1 = Legacy interrupt only.\n"); ++module_param(fastpickup, int, 0400); ++MODULE_PARM_DESC(fastpickup, ++ "Set to 1 to shorten the calibration delay when taking an FXO port off " ++ "hook. This can be required for Type-II CID. If -1 the calibration " ++ "delay will depend on the current opermode.\n"); ++module_param(fxovoltage, int, 0600); ++module_param(loopcurrent, int, 0600); ++module_param(reversepolarity, int, 0600); ++#ifdef DEBUG ++module_param(robust, int, 0600); ++module_param(digitalloopback, int, 0400); ++MODULE_PARM_DESC(digitalloopback, ++ "Set to 1 to place FXO modules into loopback mode for troubleshooting."); ++#endif ++module_param(opermode, charp, 0600); ++module_param(lowpower, int, 0600); ++module_param(boostringer, int, 0600); ++module_param(fastringer, int, 0600); ++module_param(fxshonormode, int, 0600); ++module_param(battdebounce, uint, 0600); ++module_param(battalarm, uint, 0600); ++module_param(battthresh, uint, 0600); ++module_param(nativebridge, int, 0600); ++module_param(fxotxgain, int, 0600); ++module_param(fxorxgain, int, 0600); ++module_param(fxstxgain, int, 0600); ++module_param(fxsrxgain, int, 0600); ++module_param(ringdebounce, int, 0600); ++module_param(latency, int, 0400); ++module_param(max_latency, int, 0400); ++module_param(neonmwi_monitor, int, 0600); ++module_param(neonmwi_level, int, 0600); ++module_param(neonmwi_envelope, int, 0600); ++module_param(neonmwi_offlimit, int, 0600); ++module_param(vpmsupport, int, 0400); ++ ++module_param(forceload, int, 0600); ++MODULE_PARM_DESC(forceload, ++ "Set to 1 in order to force an FPGA reload after power on."); ++ ++module_param(companding, charp, 0400); ++MODULE_PARM_DESC(companding, ++ "Change the companding to \"auto\" or \"alaw\" or \"ulaw\". Auto " ++ "(default) will set everything to ulaw unless a BRI module is " ++ "installed. It will use alaw in that case."); ++ ++MODULE_DESCRIPTION("A4A,A4B,A8A,A8B Driver for Analog Telephony Cards"); ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(wcaxx_init); ++module_exit(wcaxx_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/wcb4xxp/Kbuild linux-source-4.19-dahdi/drivers/dahdi/wcb4xxp/Kbuild +--- linux-source-4.19/drivers/dahdi/wcb4xxp/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcb4xxp/Kbuild 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,7 @@ ++obj-m += wcb4xxp.o ++ ++EXTRA_CFLAGS += -I$(src)/.. -Wno-undef ++ ++wcb4xxp-objs := base.o ++ ++$(obj)/base.o: $(src)/wcb4xxp.h +diff -Nru linux-source-4.19/drivers/dahdi/wcb4xxp/base.c linux-source-4.19-dahdi/drivers/dahdi/wcb4xxp/base.c +--- linux-source-4.19/drivers/dahdi/wcb4xxp/base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcb4xxp/base.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,3726 @@ ++/* ++ * WCB410P Quad-BRI PCI Driver ++ * Written by Andrew Kohlsmith ++ * ++ * Copyright (C) 2009-2012 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 /* printk() */ ++#include /* error codes */ ++#include ++#include /* size_t */ ++#include /* O_ACCMODE */ ++#include ++#include ++#include /* for PCI structures */ ++#include ++#include ++#include ++#include /* dev_err() */ ++#include ++#include /* copy_*_user */ ++#include /* work_struct */ ++#include /* timer_struct */ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "wcb4xxp.h" ++ ++#ifndef BIT /* added in 2.6.24 */ ++#define BIT(i) (1UL << (i)) ++#endif ++#define BIT_SET(x, i) ((x) |= BIT(i)) ++#define BIT_CLR(x, i) ((x) &= ~BIT(i)) ++#define IS_SET(x, i) (((x) & BIT(i)) != 0) ++#define BITMASK(i) (((u64)1 << (i)) - 1) ++ ++ ++#if (DAHDI_CHUNKSIZE != 8) ++#error Sorry, wcb4xxp does not support chunksize != 8 ++#endif ++ ++//#define SIMPLE_BCHAN_FIFO ++//#define DEBUG_LOWLEVEL_REGS /* debug __pci_in/out, not b4xxp_setreg */ ++ ++#define DEBUG_GENERAL (1 << 0) /* general debug messages */ ++#define DEBUG_DTMF (1 << 1) /* emit DTMF detector messages */ ++#define DEBUG_REGS (1 << 2) /* emit register read/write, but only if the kernel's DEBUG is defined */ ++#define DEBUG_FOPS (1 << 3) /* emit file operation messages */ ++#define DEBUG_ECHOCAN (1 << 4) ++#define DEBUG_ST_STATE (1 << 5) /* S/T state machine */ ++#define DEBUG_HDLC (1 << 6) /* HDLC controller */ ++#define DEBUG_ALARM (1 << 7) /* alarm changes */ ++ ++#define DBG (debug & DEBUG_GENERAL) ++#define DBG_DTMF (debug & DEBUG_DTMF) ++#define DBG_REGS (debug & DEBUG_REGS) ++#define DBG_FOPS (debug & DEBUG_FOPS) ++#define DBG_EC (debug & DEBUG_ECHOCAN) ++#define DBG_ST (debug & DEBUG_ST_STATE) ++#define DBG_HDLC (debug & DEBUG_HDLC) ++#define DBG_ALARM (debug & DEBUG_ALARM) ++ ++#define DBG_SPANFILTER (BIT(bspan->port) & spanfilter) ++ ++static int debug = 0; ++static int spanfilter = 0xFF; /* Bitmap for ports 1-8 */ ++#ifdef LOOPBACK_SUPPORTED ++static int loopback = 0; ++#endif ++static int milliwatt = 0; ++static int pedanticpci = 0; ++static int teignorered = 0; ++static int alarmdebounce = 500; ++static int persistentlayer1 = 1; ++static int vpmsupport = 1; ++static int timer_1_ms = 2000; ++static int timer_3_ms = 30000; ++static char *companding = "alaw"; ++ ++#if !defined(mmiowb) ++#define mmiowb() barrier() ++#endif ++ ++#define MAX_B4_CARDS 64 ++static struct b4xxp *cards[MAX_B4_CARDS]; ++ ++static int led_fader_table[] = { ++ 0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, ++ 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, ++ 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, ++}; ++ ++#undef CREATE_WCB4XXP_PROCFS_ENTRY ++#ifdef CREATE_WCB4XXP_PROCFS_ENTRY ++#define PROCFS_NAME "wcb4xxp" ++static struct proc_dir_entry *myproc; ++#endif ++ ++/* Expansion; right now there's just one card and all of its idiosyncrasies. */ ++ ++#define FLAG_yyy (1 << 0) ++#define FLAG_zzz (1 << 1) ++ ++struct devtype { ++ char *desc; ++ unsigned int flags; ++ int ports; /* Number of ports the card has */ ++ enum cards_ids card_type; /* Card type - Digium B410P, ... */ ++}; ++ ++static struct devtype wcb41xp = {"Wildcard B410P", .ports = 4, ++ .card_type = B410P}; ++static struct devtype wcb43xp = {"Wildcard B430P", .ports = 4, ++ .card_type = B430P}; ++static struct devtype wcb23xp = {"Wildcard B230P", .ports = 2, ++ .card_type = B230P}; ++ ++#define IS_B430P(card) ((card)->card_type == B430P) ++#define IS_B230P(card) ((card)->card_type == B230P) ++#define IS_GEN2(card) (IS_B430P(card) || IS_B230P(card)) ++#define IS_B410P(card) ((card)->card_type == B410P) ++#define CARD_HAS_EC(card) (IS_B410P(card) || IS_B430P(card) || IS_B230P(card)) ++ ++static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++static void b4xxp_update_leds(struct b4xxp *b4); ++ ++static const struct dahdi_echocan_features my_ec_features = { ++ .NLP_automatic = 1, ++ .CED_tx_detect = 1, ++ .CED_rx_detect = 1, ++}; ++ ++static const struct dahdi_echocan_ops my_ec_ops = { ++ .echocan_free = echocan_free, ++}; ++ ++/* ++ * lowlevel PCI access functions ++ * These are simply wrappers for the normal PCI access functions that the kernel provides, ++ * except that they allow us to work around specific PCI quirks with module options. ++ * Currently the only option supported is pedanticpci, which injects a (min.) 3us delay ++ * after any PCI access to forcibly disable fast back-to-back transactions. ++ * In the case of a PCI write, pedanticpci will also read from the status register, which ++ * has the effect of flushing any pending PCI writes. ++ */ ++ ++static inline unsigned char __pci_in8(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned char ret = ioread8(b4->addr + reg); ++ ++#ifdef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ drv_dbg(&b4->pdev->dev, ++ "read 0x%02x from 0x%p\n", ret, b4->addr + reg); ++ } ++#endif ++ if (unlikely(pedanticpci)) { ++ udelay(3); ++ } ++ ++ return ret; ++} ++ ++static inline unsigned short __pci_in16(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned short ret = ioread16(b4->addr + reg); ++ ++#ifdef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ drv_dbg(&b4->pdev->dev, ++ "read 0x%04x from 0x%p\n", ret, b4->addr + reg); ++ } ++#endif ++ if (unlikely(pedanticpci)) { ++ udelay(3); ++ } ++ ++ return ret; ++} ++ ++static inline unsigned int __pci_in32(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned int ret = ioread32(b4->addr + reg); ++ ++#ifdef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ drv_dbg(&b4->pdev->dev, ++ "read 0x%04x from 0x%p\n", ret, b4->addr + reg); ++ } ++#endif ++ if (unlikely(pedanticpci)) { ++ udelay(3); ++ } ++ ++ return ret; ++} ++ ++static inline void __pci_out32(struct b4xxp *b4, const unsigned int reg, const unsigned int val) ++{ ++#ifdef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ drv_dbg(&b4->pdev->dev, ++ "writing 0x%02x to 0x%p\n", val, b4->addr + reg); ++ } ++#endif ++ iowrite32(val, b4->addr + reg); ++ ++ if (unlikely(pedanticpci)) { ++ udelay(3); ++ (void)ioread8(b4->addr + R_STATUS); ++ } ++} ++ ++static inline void __pci_out8(struct b4xxp *b4, const unsigned int reg, const unsigned char val) ++{ ++#ifdef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ drv_dbg(&b4->pdev->dev, ++ "writing 0x%02x to 0x%p\n", val, b4->addr + reg); ++ } ++#endif ++ iowrite8(val, b4->addr + reg); ++ ++ if (unlikely(pedanticpci)) { ++ udelay(3); ++ (void)ioread8(b4->addr + R_STATUS); ++ } ++} ++ ++ ++/* ++ * Standard I/O access functions ++ * uses spinlocks to protect against multiple I/O accesses ++ * DOES NOT automatically memory barrier ++ */ ++static inline unsigned char b4xxp_getreg8(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned int ret; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&b4->reglock, irq_flags); ++#undef RETRY_REGISTER_READS ++#ifdef RETRY_REGISTER_READS ++ switch (reg) { ++ case A_Z1: ++ case A_Z1H: ++ case A_F2: ++ case R_IRQ_OVIEW: ++ case R_BERT_STA: ++ case A_ST_RD_STA: ++ case R_IRQ_FIFO_BL0: ++ case A_Z2: ++ case A_Z2H: ++ case A_F1: ++ case R_RAM_USE: ++ case R_F0_CNTL: ++ case A_ST_SQ_RD: ++ case R_IRQ_FIFO_BL7: ++ /* On pg 53 of the data sheet for the hfc, it states that we must ++ * retry certain registers until we get two consecutive reads that are ++ * the same. */ ++retry: ++ ret = __pci_in8(b4, reg); ++ if (ret != __pci_in8(b4, reg)) ++ goto retry; ++ break; ++ default: ++#endif ++ ret = __pci_in8(b4, reg); ++#ifdef RETRY_REGISTER_READS ++ break; ++ } ++#endif ++ spin_unlock_irqrestore(&b4->reglock, irq_flags); ++ ++#ifndef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ dev_dbg(&b4->pdev->dev, ++ "read 0x%02x from 0x%p\n", ret, b4->addr + reg); ++ } ++#endif ++ return ret; ++} ++ ++static inline unsigned int b4xxp_getreg32(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned int ret; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&b4->reglock, irq_flags); ++ ret = __pci_in32(b4, reg); ++ spin_unlock_irqrestore(&b4->reglock, irq_flags); ++ ++#ifndef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ dev_dbg(&b4->pdev->dev, ++ "read 0x%04x from 0x%p\n", ret, b4->addr + reg); ++ } ++#endif ++ return ret; ++} ++ ++static inline unsigned short b4xxp_getreg16(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned int ret; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&b4->reglock, irq_flags); ++ ret = __pci_in16(b4, reg); ++ spin_unlock_irqrestore(&b4->reglock, irq_flags); ++ ++#ifndef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ dev_dbg(&b4->pdev->dev, ++ "read 0x%04x from 0x%p\n", ret, b4->addr + reg); ++ } ++#endif ++ return ret; ++} ++ ++static inline void b4xxp_setreg32(struct b4xxp *b4, const unsigned int reg, const unsigned int val) ++{ ++ unsigned long irq_flags; ++ ++#ifndef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ dev_dbg(&b4->pdev->dev, ++ "writing 0x%02x to 0x%p\n", val, b4->addr + reg); ++ } ++#endif ++ spin_lock_irqsave(&b4->reglock, irq_flags); ++ __pci_out32(b4, reg, val); ++ spin_unlock_irqrestore(&b4->reglock, irq_flags); ++} ++ ++static inline void b4xxp_setreg8(struct b4xxp *b4, const unsigned int reg, const unsigned char val) ++{ ++ unsigned long irq_flags; ++ ++#ifndef DEBUG_LOWLEVEL_REGS ++ if (unlikely(DBG_REGS)) { ++ dev_dbg(&b4->pdev->dev, ++ "writing 0x%02x to 0x%p\n", val, b4->addr + reg); ++ } ++#endif ++ spin_lock_irqsave(&b4->reglock, irq_flags); ++ __pci_out8(b4, reg, val); ++ spin_unlock_irqrestore(&b4->reglock, irq_flags); ++} ++ ++/* ++ * A lot of the registers in the HFC are indexed. ++ * this function sets the index, and then writes to the indexed register in an ordered fashion. ++ * memory barriers are useless unless spinlocked, so that's what these wrapper functions do. ++ */ ++static void b4xxp_setreg_ra(struct b4xxp *b4, unsigned char r, unsigned char rd, unsigned char a, unsigned char ad) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&b4->seqlock, irq_flags); ++ ++ b4xxp_setreg8(b4, r, rd); ++ wmb(); ++ b4xxp_setreg8(b4, a, ad); ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&b4->seqlock, irq_flags); ++} ++ ++static unsigned char b4xxp_getreg_ra(struct b4xxp *b4, unsigned char r, unsigned char rd, unsigned char a) ++{ ++ unsigned long irq_flags; ++ unsigned char val; ++ ++ spin_lock_irqsave(&b4->seqlock, irq_flags); ++ ++ b4xxp_setreg8(b4, r, rd); ++ wmb(); ++ val = b4xxp_getreg8(b4, a); ++ ++ mmiowb(); ++ spin_unlock_irqrestore(&b4->seqlock, irq_flags); ++ return val; ++} ++ ++/* This gpio register set wrapper protects bit 0 on b430 devices from being ++ * cleared, as it's used for reset */ ++static void hfc_gpio_set(struct b4xxp *b4, unsigned char bits) ++{ ++ if (IS_GEN2(b4)) { ++ b4xxp_setreg8(b4, R_GPIO_OUT1, bits | 0x01); ++ flush_pci(); ++ } else { ++ b4xxp_setreg8(b4, R_GPIO_OUT1, bits); ++ } ++} ++ ++/* ++ * HFC-4S GPIO routines ++ * ++ * the B410P uses the HFC-4S GPIO as follows: ++ * GPIO 8..10: output, CPLD register select ++ * GPIO12..15: output, 1 = enable power for port 1-4 ++ * GPI16: input, 0 = echo can #1 interrupt ++ * GPI17: input, 0 = echo can #2 interrupt ++ * GPI23: input, 1 = NT power module installed ++ * GPI24..27: input, NT power module problem on port 1-4 ++ * GPI28..31: input, 1 = port 1-4 in NT mode ++ */ ++ ++/* initialize HFC-4S GPIO. Set up pin drivers before setting GPIO mode */ ++static void hfc_gpio_init(struct b4xxp *b4) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&b4->seqlock, irq_flags); ++ ++ flush_pci(); ++ mb(); ++ ++ /* GPIO0..7 input */ ++ b4xxp_setreg8(b4, R_GPIO_EN0, 0x00); ++ ++ if (IS_GEN2(b4)) ++ b4xxp_setreg8(b4, R_GPIO_EN1, 0xf1); ++ else ++ b4xxp_setreg8(b4, R_GPIO_EN1, 0xf7); ++ ++ hfc_gpio_set(b4, 0x00); ++ ++ mb(); ++ ++ switch (b4->card_type) { ++ case OCTOBRI: /* fall through */ ++ case B800P_OV: /* fall through */ ++ case BN8S0: ++ /* GPIO0..15 S/T - HFC-8S uses GPIO8-15 for S/T ports 5-8 */ ++ b4xxp_setreg8(b4, R_GPIO_SEL, 0x00); ++ break; ++ default: ++ /* GPIO0..7 S/T, 8..15 GPIO */ ++ b4xxp_setreg8(b4, R_GPIO_SEL, 0xf0); ++ break; ++ } ++ ++ mb(); ++ ++ spin_unlock_irqrestore(&b4->seqlock, irq_flags); ++} ++ ++/* ++ * HFC SRAM interface code. ++ * This came from mattf, I don't even pretend to understand it, ++ * It seems to be using undocumented features in the HFC. ++ * I just added the __pci_in8() to ensure the PCI writes made it ++ * to hardware by the time these functions return. ++ */ ++static inline void enablepcibridge(struct b4xxp *b4) ++{ ++ b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x03); ++ flush_pci(); ++} ++ ++static inline void disablepcibridge(struct b4xxp *b4) ++{ ++ b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x02); ++ flush_pci(); ++} ++ ++/* NOTE: read/writepcibridge do not use __pci_in/out because they are using b4->ioaddr not b4->addr */ ++static inline unsigned char readpcibridge(struct b4xxp *b4, unsigned char address) ++{ ++ unsigned short cipv; ++ unsigned char data; ++ ++ ++/* slow down a PCI read access by 1 PCI clock cycle */ ++ b4xxp_setreg8(b4, R_CTRL, 0x4); ++ wmb(); ++ ++ if (address == 0) ++ cipv=0x4000; ++ else ++ cipv=0x5800; ++ ++/* select local bridge port address by writing to CIP port */ ++ iowrite16(cipv, b4->ioaddr + 4); ++ wmb(); ++ data = ioread8(b4->ioaddr); ++ ++/* restore R_CTRL for normal PCI read cycle speed */ ++ b4xxp_setreg8(b4, R_CTRL, 0x0); ++ wmb(); ++ flush_pci(); ++ ++ return data; ++} ++ ++static inline void writepcibridge(struct b4xxp *b4, unsigned char address, unsigned char data) ++{ ++ unsigned short cipv; ++ unsigned int datav; ++ ++ ++ if (address == 0) ++ cipv=0x4000; ++ else ++ cipv=0x5800; ++ ++/* select local bridge port address by writing to CIP port */ ++ iowrite16(cipv, b4->ioaddr + 4); ++ wmb(); ++ ++/* define a 32 bit dword with 4 identical bytes for write sequence */ ++ datav = data | ( (__u32) data <<8) | ( (__u32) data <<16) | ( (__u32) data <<24); ++ ++/* ++ * write this 32 bit dword to the bridge data port ++ * this will initiate a write sequence of up to 4 writes to the same address on the local bus ++ * interface ++ * the number of write accesses is undefined but >=1 and depends on the next PCI transaction ++ * during write sequence on the local bus ++ */ ++ iowrite32(datav, b4->ioaddr); ++ wmb(); ++ flush_pci(); ++} ++ ++/* CPLD access code, more or less copied verbatim from code provided by mattf. */ ++static inline void cpld_select_reg(struct b4xxp *b4, unsigned char reg) ++{ ++ hfc_gpio_set(b4, reg); ++ flush_pci(); ++} ++ ++static inline void cpld_setreg(struct b4xxp *b4, unsigned char reg, unsigned char val) ++{ ++ cpld_select_reg(b4, reg); ++ ++ enablepcibridge(b4); ++ writepcibridge(b4, 1, val); ++ disablepcibridge(b4); ++} ++ ++static inline unsigned char cpld_getreg(struct b4xxp *b4, unsigned char reg) ++{ ++ unsigned char data; ++ ++ cpld_select_reg(b4, reg); ++ ++ enablepcibridge(b4); ++ data = readpcibridge(b4, 1); ++ disablepcibridge(b4); ++ ++ return data; ++} ++ ++ ++/* ++ * echo canceller code, verbatim from mattf. ++ * I don't pretend to understand it. ++ */ ++static inline void ec_select_addr(struct b4xxp *b4, unsigned short addr) ++{ ++ cpld_setreg(b4, 0, 0xff & addr); ++ cpld_setreg(b4, 1, 0x01 & (addr >> 8)); ++} ++ ++static inline unsigned short ec_read_data(struct b4xxp *b4) ++{ ++ unsigned short addr; ++ unsigned short highbit; ++ ++ addr = cpld_getreg(b4, 0); ++ highbit = cpld_getreg(b4, 1); ++ ++ addr = addr | (highbit << 8); ++ ++ return addr & 0x1ff; ++} ++ ++static unsigned char hfc_sram_read(struct b4xxp *b4) ++{ ++ unsigned char data; ++ ++ enablepcibridge(b4); ++ data = readpcibridge(b4, 1); ++ disablepcibridge(b4); ++ cpld_select_reg(b4, 0); ++ ++ return data; ++} ++ ++static void hfc_sram_write(struct b4xxp *b4, char data) ++{ ++ enablepcibridge(b4); ++ writepcibridge(b4, 1, data); ++ cpld_select_reg(b4, 0); ++ disablepcibridge(b4); ++} ++ ++static void set_dsp_address(struct b4xxp *b4, unsigned short addr, bool dir) ++{ ++ hfc_gpio_set(b4, 0x30); ++ hfc_sram_write(b4, 0xff & addr); ++ hfc_gpio_set(b4, 0x40); ++ /* dir = 1 write */ ++ if (dir) ++ hfc_sram_write(b4, 0x03 & (addr >> 8)); ++ else ++ hfc_sram_write(b4, 0x80 | (0x03 & (addr >> 8))); ++} ++ ++/* Read from zarlink echocan without locks */ ++static unsigned char __zl_read(struct b4xxp *b4, unsigned short addr) ++{ ++ unsigned char data; ++ ++ set_dsp_address(b4, addr, 0); ++ hfc_gpio_set(b4, ((addr & 0x0400) >> 3) | 0x50); ++ data = hfc_sram_read(b4); ++ hfc_gpio_set(b4, 0x00); ++ ++ return data; ++} ++ ++/* Write to zarlink echocan unlocked */ ++static void __zl_write(struct b4xxp *b4, unsigned short addr, ++ unsigned char data) ++{ ++ unsigned char val; ++ ++ hfc_gpio_set(b4, 0x00); ++ set_dsp_address(b4, addr, 1); ++ hfc_sram_write(b4, data); ++ val = ((addr & 0x0400) >> 3); ++ val = (val | 0x50); ++ hfc_gpio_set(b4, val); ++ hfc_gpio_set(b4, 0x00); ++} ++ ++/* Write to zarlink echocan locked */ ++static void zl_write(struct b4xxp *b4, unsigned short addr, unsigned char data) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ __zl_write(b4, addr, data); ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++} ++ ++static inline unsigned char ec_read(struct b4xxp *b4, int which, unsigned short addr) ++{ ++ unsigned char data; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ ec_select_addr(b4, addr); ++ ++ if (!which) ++ cpld_select_reg(b4, 2); ++ else ++ cpld_select_reg(b4, 3); ++ ++ enablepcibridge(b4); ++ data = readpcibridge(b4, 1); ++ disablepcibridge(b4); ++ ++ cpld_select_reg(b4, 0); ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++ ++ return data; ++} ++ ++static inline void ec_write(struct b4xxp *b4, int which, unsigned short addr, unsigned char data) ++{ ++ unsigned char in; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ ++ ec_select_addr(b4, addr); ++ ++ enablepcibridge(b4); ++ ++ if (!which) ++ cpld_select_reg(b4, 2); ++ else ++ cpld_select_reg(b4, 3); ++ ++ writepcibridge(b4, 1, data); ++ cpld_select_reg(b4, 0); ++ disablepcibridge(b4); ++ ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++ ++ in = ec_read(b4, which, addr); ++ ++ if ((in != data) && printk_ratelimit()) { ++ dev_warn(&b4->pdev->dev, ++ "ec_write: Wrote 0x%02x to register 0x%02x " ++ "of VPM %d but got back 0x%02x\n", ++ data, addr, which, in); ++ } ++} ++ ++#define NUM_EC 2 ++#define MAX_TDM_CHAN 32 ++ ++static void zl_init(struct b4xxp *b4) ++{ ++ int i, offset; ++ int group_addr[4] = {0x00, 0x40, 0x80, 0xc0}; ++ ++ if (!b4->shutdown) ++ dev_info(&b4->pdev->dev, "Initializing Zarlink echocan\n"); ++ ++ /* There are 4 "groups" of echocans with two channels in each */ ++ /* Main group control reg 0-3 */ ++ ++ /* Hardware Reset Sequence */ ++ b4xxp_setreg8(b4, R_GPIO_OUT1, 0x00); ++ udelay(100); ++ b4xxp_setreg8(b4, R_GPIO_OUT1, 0x01); ++ udelay(500); ++ ++ /* Software reset sequence */ ++ zl_write(b4, 0x400, 0x41); ++ zl_write(b4, 0x401, 0x01); ++ zl_write(b4, 0x402, 0x01); ++ zl_write(b4, 0x403, 0x01); ++ udelay(250); ++ zl_write(b4, 0x400, 0x40); ++ zl_write(b4, 0x401, 0x00); ++ zl_write(b4, 0x402, 0x00); ++ zl_write(b4, 0x403, 0x00); ++ udelay(500); ++ ++ /* Power up & Configure echo can gruops */ ++ if (!strcasecmp(companding, "alaw")) { ++ zl_write(b4, 0x400, 0x47); ++ zl_write(b4, 0x401, 0x07); ++ zl_write(b4, 0x402, 0x07); ++ zl_write(b4, 0x403, 0x07); ++ } else { ++ zl_write(b4, 0x400, 0x45); ++ zl_write(b4, 0x401, 0x05); ++ zl_write(b4, 0x402, 0x05); ++ zl_write(b4, 0x403, 0x05); ++ } ++ udelay(250); ++ ++ for (i = 0; i <= 3; i++) { ++ int group = group_addr[i]; ++ /* Control reg 1, bank A & B, channel bypass mode */ ++ zl_write(b4, group + 0x00, 0x08); ++ /* Control reg 1 on bank B must be written twicer as */ ++ /* per the datasheet */ ++ zl_write(b4, group + 0x20, 0x0a); ++ zl_write(b4, group + 0x20, 0x0a); ++ ++ /* Two channels of the echocan must be set separately, ++ one at offset 0x00 and one at offset 0x20 */ ++ for (offset = group; offset <= (group + 0x20); offset += 0x20) { ++ /* Control reg 2 */ ++ zl_write(b4, offset + 0x01, 0x00); ++ /* Flat Delay */ ++ zl_write(b4, offset + 0x04, 0x00); ++ /* Decay Step Size Reg */ ++ zl_write(b4, offset + 0x06, 0x04); ++ /* Decay Step Number */ ++ zl_write(b4, offset + 0x07, 0x00); ++ /* Control reg 3 */ ++ zl_write(b4, offset + 0x08, 0xfb); ++ /* Control reg 4 */ ++ zl_write(b4, offset + 0x09, 0x54); ++ /* Noise Scaling */ ++ zl_write(b4, offset + 0x0a, 0x16); ++ /* Noise Control */ ++ zl_write(b4, offset + 0x0b, 0x45); ++ /* DTDT Reg 1*/ ++ zl_write(b4, offset + 0x14, 0x00); ++ /* DTDT Reg 2*/ ++ zl_write(b4, offset + 0x15, 0x48); ++ /* NLPTHR reg 1*/ ++ zl_write(b4, offset + 0x18, 0xe0); ++ /* NLPTHR reg 2*/ ++ zl_write(b4, offset + 0x19, 0x0c); ++ /* Step Size, MU reg 1*/ ++ zl_write(b4, offset + 0x1a, 0x00); ++ /* Step Size, MU reg 2*/ ++ zl_write(b4, offset + 0x1b, 0x40); ++ /* Gains reg 1*/ ++ zl_write(b4, offset + 0x1c, 0x44); ++ /* Gains reg 2*/ ++ zl_write(b4, offset + 0x1d, 0x44); ++ } ++ } ++} ++ ++static void ec_init(struct b4xxp *b4) ++{ ++ unsigned char b; ++ unsigned int i, j, mask; ++ ++ if (!CARD_HAS_EC(b4)) ++ return; ++ ++ /* Short circuit to the new zarlink echocan logic */ ++ if (IS_GEN2(b4)) { ++ zl_init(b4); ++ return; ++ } ++ ++/* Setup GPIO */ ++ for (i=0; i < NUM_EC; i++) { ++ b = ec_read(b4, i, 0x1a0); ++ ++ dev_info(&b4->pdev->dev, ++ "VPM %d/%d init: chip ver %02x\n", i, NUM_EC - 1, b); ++ ++ for (j=0; j < b4->numspans; j++) { ++ ec_write(b4, i, 0x1a8 + j, 0x00); /* GPIO out */ ++ ec_write(b4, i, 0x1ac + j, 0x00); /* GPIO dir */ ++ ec_write(b4, i, 0x1b0 + j, 0x00); /* GPIO sel */ ++ } ++ ++/* Setup TDM path - sets fsync and tdm_clk as inputs */ ++ b = ec_read(b4, i, 0x1a3); /* misc_con */ ++ ec_write(b4, i, 0x1a3, b & ~0x02); ++ ++/* Setup Echo length (512 taps) */ ++ ec_write(b4, i, 0x022, 1); ++ ec_write(b4, i, 0x023, 0xff); ++ ++/* Setup timeslots */ ++ ec_write(b4, i, 0x02f, 0x00); ++ mask = 0x02020202 << (i * 4); ++ ++/* Setup the tdm channel masks for all chips*/ ++ for (j=0; j < 4; j++) ++ ec_write(b4, i, 0x33 - j, (mask >> (j << 3)) & 0xff); ++ ++/* Setup convergence rate */ ++ b = ec_read(b4, i, 0x20); ++ b &= 0xe0; ++ b |= 0x12; ++ if (!strcasecmp(companding, "alaw")) { ++ if (DBG) ++ dev_info(&b4->pdev->dev, "Setting alaw mode\n"); ++ b |= 0x01; ++ } else { ++ if (DBG) ++ dev_info(&b4->pdev->dev, "Setting ulaw mode"); ++ } ++ ++ ec_write(b4, i, 0x20, b); ++ if (DBG) ++ dev_info(&b4->pdev->dev, "reg 0x20 is 0x%02x\n", b); ++ ++ if (DBG) { ++ dev_info(&b4->pdev->dev, ++ "NLP threshold is set to %d (0x%02x)\n", b, b); ++ } ++ ++/* Initialize echo cans */ ++ for (j=0; j < MAX_TDM_CHAN; j++) { ++ if (mask & (0x00000001 << j)) ++ ec_write(b4, i, j, 0x00); ++ } ++ ++ mdelay(10); ++ ++/* Put in bypass mode */ ++ for (j=0; j < MAX_TDM_CHAN; j++) { ++ if (mask & (0x00000001 << j)) { ++ ec_write(b4, i, j, 0x01); ++ } ++ } ++ ++/* Enable bypass */ ++ for (j=0; j < MAX_TDM_CHAN; j++) { ++ if (mask & (0x00000001 << j)) ++ ec_write(b4, i, 0x78 + j, 0x01); ++ } ++ } ++} ++ ++/* performs a register write and then waits for the HFC "busy" bit to clear */ ++static void hfc_setreg_waitbusy(struct b4xxp *b4, const unsigned int reg, const unsigned int val) ++{ ++ /* V_BUSY is not supposed to take longer than 1us */ ++ /* Since this func can be called with interrupts locked ++ * we should just a regular loop, as jiffies may not update ++ */ ++ int TIMEOUT = 0.002 * 3000000; ++ int x = 0; ++ ++ b4xxp_setreg8(b4, reg, val); ++ ++ while (b4xxp_getreg8(b4, R_STATUS) & V_BUSY) { ++ if (x++ > TIMEOUT) { ++ if (printk_ratelimit()) { ++ dev_info(&b4->pdev->dev, ++ "hfc_setreg_waitbusy(write 0x%02x to 0x%02x) timed out waiting for busy flag to clear!\n", ++ val, reg); ++ } ++ return; ++ } ++ } ++} ++ ++/* ++ * reads an 8-bit register over over and over until the same value is read twice, then returns that value. ++ */ ++static inline unsigned char hfc_readcounter8(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned char r1, r2; ++ unsigned long maxwait = 1048576; ++ ++ do { ++ r1 = b4xxp_getreg8(b4, reg); ++ r2 = b4xxp_getreg8(b4, reg); ++ } while ((r1 != r2) && maxwait--); ++ ++ if (!maxwait && printk_ratelimit()) { ++ dev_warn(&b4->pdev->dev, ++ "hfc_readcounter8(reg 0x%02x) timed out waiting " ++ "for data to settle!\n", reg); ++ } ++ ++ return r1; ++} ++ ++/* ++ * reads a 16-bit register over over and over until the same value is read twice, then returns that value. ++ */ ++static inline unsigned short hfc_readcounter16(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned short r1, r2; ++ unsigned long maxwait = 1048576; ++ ++ do { ++ r1 = b4xxp_getreg16(b4, reg); ++ r2 = b4xxp_getreg16(b4, reg); ++ } while ((r1 != r2) && maxwait--); ++ ++ if (!maxwait && printk_ratelimit()) { ++ dev_warn(&b4->pdev->dev, ++ "hfc_readcounter16(reg 0x%02x) timed out waiting " ++ "for data to settle!\n", reg); ++ } ++ ++ return r1; ++} ++ ++static inline unsigned int hfc_readcounter32(struct b4xxp *b4, const unsigned int reg) ++{ ++ unsigned int r1, r2; ++ unsigned long maxwait = 1048576; ++ ++ do { ++ r1 = b4xxp_getreg32(b4, reg); ++ r2 = b4xxp_getreg32(b4, reg); ++ } while ((r1 != r2) && maxwait--); ++ ++ if (!maxwait && printk_ratelimit()) { ++ dev_warn(&b4->pdev->dev, ++ "hfc_readcounter32(reg 0x%02x) timed out waiting " ++ "for data to settle!\n", reg); ++ } ++ ++ return r1; ++} ++ ++/* performs a soft-reset of the HFC-4S. This is as clean-slate as you can get to a hardware reset. */ ++static void hfc_reset(struct b4xxp *b4) ++{ ++ int b, c; ++ ++/* all 32 FIFOs the same size (384 bytes), channel select data flow mode, sized for internal RAM */ ++ b4xxp_setreg8(b4, R_FIFO_MD, V_FIFO_MD_00 | V_DF_MD_CSM | V_FIFO_SZ_00); ++ flush_pci(); ++ ++/* reset everything, wait 500us, then bring everything BUT the PCM system out of reset */ ++ b4xxp_setreg8(b4, R_CIRM, HFC_FULL_RESET); ++ flush_pci(); ++ ++ udelay(500); ++ ++ b4xxp_setreg8(b4, R_CIRM, V_PCM_RES); ++ flush_pci(); ++ ++ udelay(500); ++ ++/* ++ * Now bring PCM out of reset and do a very basic setup of the PCM system to allow it to finish resetting correctly. ++ * set F0IO as an output, and set up a 32-timeslot PCM bus ++ * See Section 8.3 in the HFC-4S datasheet for more details. ++ */ ++ b4xxp_setreg8(b4, R_CIRM, 0x00); ++ b4xxp_setreg8(b4, R_PCM_MD0, V_PCM_MD | V_PCM_IDX_MD1); ++ flush_pci(); ++ ++ if (IS_GEN2(b4)) ++ b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_4096); ++ else ++ b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_2048); ++ ++ flush_pci(); ++ ++/* now wait for R_F0_CNTL to reach at least 2 before continuing */ ++ c=10; ++ while ((b = b4xxp_getreg8(b4, R_F0_CNTL)) < 2 && c) { udelay(100); c--; } ++ ++ if (!c && b < 2) { ++ dev_warn(&b4->pdev->dev, "hfc_reset() did not get the green light from the PCM system!\n"); ++ } ++} ++ ++static inline void hfc_enable_fifo_irqs(struct b4xxp *b4) ++{ ++ b4xxp_setreg8(b4, R_IRQ_CTRL, V_FIFO_IRQ | V_GLOB_IRQ_EN); ++ flush_pci(); ++} ++ ++static inline void hfc_disable_fifo_irqs(struct b4xxp *b4) ++{ ++ b4xxp_setreg8(b4, R_IRQ_CTRL, V_GLOB_IRQ_EN); ++ flush_pci(); ++} ++ ++static void hfc_enable_interrupts(struct b4xxp *b4) ++{ ++ b4->running = 1; ++ ++/* clear any pending interrupts */ ++ b4xxp_getreg8(b4, R_STATUS); ++ b4xxp_getreg8(b4, R_IRQ_MISC); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL0); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL1); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL2); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL3); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL4); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL5); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL6); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL7); ++ ++ b4xxp_setreg8(b4, R_IRQMSK_MISC, V_TI_IRQ); ++ hfc_enable_fifo_irqs(b4); ++} ++ ++static void hfc_disable_interrupts(struct b4xxp *b4) ++{ ++ b4xxp_setreg8(b4, R_IRQMSK_MISC, 0); ++ b4xxp_setreg8(b4, R_IRQ_CTRL, 0); ++ flush_pci(); ++ b4->running = 0; ++} ++ ++/* ++ * Connects an S/T port's B channel to a host-facing FIFO through the PCM busses. ++ * This bchan flow plan should match up with the EC requirements. ++ * TODO: Interrupts are only enabled on the host FIFO RX side, since everything is (should be) synchronous. ++ * *** performs no error checking of parameters *** ++ */ ++static void hfc_assign_bchan_fifo_ec(struct b4xxp *b4, int port, int bchan) ++{ ++ int fifo, hfc_chan, ts; ++ unsigned long irq_flags; ++ static int first=1; ++ ++ if (first) { ++ first = 0; ++ dev_info(&b4->pdev->dev, "Hardware echo cancellation enabled.\n"); ++ } ++ ++ fifo = port * 2; ++ hfc_chan = port * 4; ++ ts = port * 8; ++ ++ if (bchan) { ++ fifo += 1; ++ hfc_chan += 1; ++ ts += 4; ++ } ++ ++/* record the host's FIFO # in the span fifo array */ ++ b4->spans[port].fifos[bchan] = fifo; ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ ++ if (DBG) { ++ dev_info(&b4->pdev->dev, ++ "port %d, B channel %d\n\tS/T -> PCM ts %d uses HFC " ++ "chan %d via FIFO %d\n", ++ port, bchan, ts + 1, hfc_chan, 16 + fifo); ++ } ++ ++/* S/T RX -> PCM TX FIFO, transparent mode, no IRQ. */ ++ hfc_setreg_waitbusy(b4, R_FIFO, ((16 + fifo) << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_110); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT)); ++ b4xxp_setreg8(b4, R_SLOT, ((ts + 1) << V_SL_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_TX_STIO1 | (hfc_chan << V_CH_SNUM_SHIFT)); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) ++ pr_info("\tPCM ts %d -> host uses HFC chan %d via FIFO %d\n", ts + 1, 16 + hfc_chan, fifo); ++ ++/* PCM RX -> Host TX FIFO, transparent mode, enable IRQ. */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_001); ++ b4xxp_setreg8(b4, A_CHANNEL, ((16 + hfc_chan) << V_CH_FNUM_SHIFT) | V_CH_FDIR); ++ b4xxp_setreg8(b4, R_SLOT, ((ts + 1) << V_SL_NUM_SHIFT) | 1); ++ b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_RX_STIO2 | ((16 + hfc_chan) << V_CH_SNUM_SHIFT) | 1); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++// b4xxp_setreg8(b4, A_IRQ_MSK, V_IRQ); ++ ++ if (DBG) ++ pr_info("\thost -> PCM ts %d uses HFC chan %d via FIFO %d\n", ts, 16 + hfc_chan, fifo); ++ ++/* Host FIFO -> PCM TX */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_001); ++ b4xxp_setreg8(b4, A_CHANNEL, ((16 + hfc_chan) << V_CH_FNUM_SHIFT)); ++ b4xxp_setreg8(b4, R_SLOT, (ts << V_SL_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_RX_STIO2 | ((16 + hfc_chan) << V_CH_SNUM_SHIFT)); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) ++ pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ts, hfc_chan, 16 + fifo); ++ ++/* PCM -> S/T */ ++ hfc_setreg_waitbusy(b4, R_FIFO, ((16 + fifo) << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_110); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT) | V_CH_FDIR); ++ b4xxp_setreg8(b4, R_SLOT, (ts << V_SL_NUM_SHIFT) | V_SL_DIR); ++ b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_TX_STIO2 | (hfc_chan << V_CH_SNUM_SHIFT) | V_CH_SDIR); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) ++ pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ts, hfc_chan, 16 + fifo); ++ ++ flush_pci(); /* ensure all those writes actually hit hardware */ ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++} ++ ++static void hfc_assign_fifo_zl(struct b4xxp *b4, int port, int bchan) ++{ ++ int fifo, hfc_chan, ts; ++ unsigned long irq_flags; ++ static int first = 1; ++ ++ if (first) { ++ first = 0; ++ dev_info(&b4->pdev->dev, "Zarlink echo cancellation enabled.\n"); ++ } ++ ++ fifo = port * 2; ++ hfc_chan = port * 4; ++ ts = port * 8; ++ ++ if (bchan) { ++ fifo += 1; ++ hfc_chan += 1; ++ ts += 4; ++ } ++ ++ /* record the host's FIFO # in the span fifo array */ ++ if (IS_B230P(b4)) ++ b4->spans[2-port].fifos[bchan] = fifo; ++ else ++ b4->spans[3-port].fifos[bchan] = fifo; ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ ++ if (DBG) { ++ dev_info(&b4->pdev->dev, ++ "port %d, B channel %d\n\tS/T -> PCM ts %d uses HFC chan %d via FIFO %d\n", ++ port, bchan, ts + 1, hfc_chan, 16 + fifo); ++ } ++ ++ /* S/T RX -> PCM TX FIFO, transparent mode, no IRQ. */ ++ hfc_setreg_waitbusy(b4, R_FIFO, ((16 + fifo) << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_110); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT)); ++ b4xxp_setreg8(b4, R_SLOT, (((fifo * 2)+1) << V_SL_NUM_SHIFT)); ++ b4xxp_setreg8(b4, ++ A_SL_CFG, V_ROUT_TX_STIO1 | (hfc_chan << V_CH_SNUM_SHIFT)); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) { ++ pr_info("\tPCM ts %d -> host uses HFC chan %d via FIFO %d\n", ++ ts + 1, 16 + hfc_chan, fifo); ++ } ++ ++ /* PCM RX -> Host TX FIFO, transparent mode, enable IRQ. */ ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_001); ++ b4xxp_setreg8(b4, A_CHANNEL, ++ ((16 + hfc_chan) << V_CH_FNUM_SHIFT) | V_CH_FDIR); ++ b4xxp_setreg8(b4, R_SLOT, ++ (((fifo * 2) + 4) << V_SL_NUM_SHIFT) | V_SL_DIR); ++ b4xxp_setreg8(b4, A_SL_CFG, ++ V_ROUT_RX_STIO2 | ((16 + hfc_chan) << V_CH_SNUM_SHIFT) | ++ V_CH_SDIR); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) { ++ pr_info("\thost -> PCM ts %d uses HFC chan %d via FIFO %d\n", ++ ts, 16 + hfc_chan, fifo); ++ } ++ ++ /* Host FIFO -> PCM TX */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_001); ++ b4xxp_setreg8(b4, A_CHANNEL, ((16 + hfc_chan) << V_CH_FNUM_SHIFT)); ++ b4xxp_setreg8(b4, R_SLOT, ((fifo * 2) << V_SL_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_SL_CFG, ++ V_ROUT_TX_STIO1 | ((16 + hfc_chan) << V_CH_SNUM_SHIFT)); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) { ++ pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ++ ts, hfc_chan, 16 + fifo); ++ } ++ ++ /* PCM -> S/T */ ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ ((16 + fifo) << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_110); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT) | V_CH_FDIR); ++ b4xxp_setreg8(b4, R_SLOT, (((fifo*2)+3) << V_SL_NUM_SHIFT) | V_SL_DIR); ++ b4xxp_setreg8(b4, A_SL_CFG, ++ V_ROUT_RX_STIO2 | (hfc_chan << V_CH_SNUM_SHIFT) | V_CH_SDIR); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) { ++ pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ++ ts, hfc_chan, 16 + fifo); ++ } ++ ++ flush_pci(); ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++} ++ ++static void hfc_assign_bchan_fifo_noec(struct b4xxp *b4, int port, int bchan) ++{ ++ int fifo, hfc_chan, ts; ++ unsigned long irq_flags; ++ static int first=1; ++ ++ if (first) { ++ first = 0; ++ dev_info(&b4->pdev->dev, "NOTE: hardware echo cancellation has been disabled\n"); ++ } ++ ++ fifo = port * 2; ++ hfc_chan = port * 4; ++ ts = port * 8; ++ ++ if (bchan) { ++ fifo += 1; ++ hfc_chan += 1; ++ ts += 4; ++ } ++ ++/* record the host's FIFO # in the span fifo array */ ++ b4->spans[port].fifos[bchan] = fifo; ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ ++ if (DBG) { ++ dev_info(&b4->pdev->dev, ++ "port %d, B channel %d\n\thost -> S/T " ++ "uses HFC chan %d via FIFO %d\n", ++ port, bchan, hfc_chan, fifo); ++ } ++ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_000); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT)); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) ++ pr_info("\tS/T -> host uses HFC chan %d via FIFO %d\n", hfc_chan, fifo); ++ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_000); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT) | V_CH_FDIR); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) ++ pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ts, hfc_chan, 16 + fifo); ++ ++ flush_pci(); /* ensure all those writes actually hit hardware */ ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++} ++ ++/* ++ * Connects an S/T port's D channel to a host-facing FIFO. ++ * Both TX and RX interrupts are enabled! ++ * *** performs no error checking of parameters *** ++ */ ++static void hfc_assign_dchan_fifo(struct b4xxp *b4, int port) ++{ ++ int fifo, hfc_chan; ++ unsigned long irq_flags; ++ ++ switch (b4->card_type) { ++ case B800P_OV: /* fall through */ ++ case OCTOBRI: /* fall through */ ++ case BN8S0: ++ /* In HFC-8S cards we can't use ports 8-11 for dchan FIFOs */ ++ fifo = port + 16; ++ break; ++ default: ++ fifo = port + 8; ++ break; ++ } ++ ++ hfc_chan = (port * 4) + 2; ++ ++/* record the host's FIFO # in the span fifo array */ ++ if (IS_B430P(b4)) ++ b4->spans[3-port].fifos[2] = fifo; ++ else if (IS_B230P(b4)) ++ b4->spans[2-port].fifos[2] = fifo; ++ else ++ b4->spans[port].fifos[2] = fifo; ++ ++ if (DBG) { ++ dev_info(&b4->pdev->dev, ++ "port %d, D channel\n\thost -> S/T uses HFC chan %d " ++ "via FIFO %d\n", port, hfc_chan, fifo); ++ } ++ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ ++/* Host FIFO -> S/T TX, HDLC mode, no IRQ. */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_TRP_IRQ | V_DATA_FLOW_000); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT)); ++ b4xxp_setreg8(b4, A_SUBCH_CFG, 0x02); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) ++ pr_info("\tS/T -> host uses HFC chan %d via FIFO %d\n", hfc_chan, fifo); ++ ++/* S/T RX -> Host FIFO, HDLC mode, IRQ will be enabled when port opened. */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_TRP_IRQ | V_DATA_FLOW_000); ++ b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT) | V_CH_FDIR); ++ b4xxp_setreg8(b4, A_SUBCH_CFG, 0x02); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ if (DBG) ++ pr_info("\n"); ++ ++ flush_pci(); /* ensure all those writes actually hit hardware */ ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++} ++ ++/* takes a read/write fifo pair and optionally resets it, optionally enabling the rx/tx interrupt */ ++static void hfc_reset_fifo_pair(struct b4xxp *b4, int fifo, int reset, int force_no_irq) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_IRQ_MSK, (!force_no_irq && b4->fifo_en_txint & (1 << fifo)) ? V_IRQ : 0); ++ ++ if (reset) ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_IRQ_MSK, (!force_no_irq && b4->fifo_en_rxint & (1 << fifo)) ? V_IRQ : 0); ++ ++ if (reset) ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); ++ ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++} ++ ++ ++static void b4xxp_set_sync_src(struct b4xxp *b4, int port) ++{ ++ int b; ++ struct b4xxp_span *bspan; ++ ++ /* -1 = no timing selection */ ++ if (port == -1) { ++ b = 0; ++ } else { ++ bspan = &b4->spans[port]; ++ b = (bspan->phy_port & V_SYNC_SEL_MASK) | V_MAN_SYNC; ++ } ++ ++ b4xxp_setreg8(b4, R_ST_SYNC, b); ++ b4->syncspan = port; ++} ++ ++/* ++ * Finds the highest-priority sync span that is not in alarm and returns it. ++ * Note: the span #s in b4->spans[].sync are 1-based, and this returns ++ * a 0-based span, or -1 if no spans are found. ++ */ ++static int b4xxp_find_sync(struct b4xxp *b4) ++{ ++ int i, psrc, src; ++ ++ src = -1; /* default to automatic */ ++ ++ for (i=0; i < b4->numspans; i++) { ++ if (DBG) ++ dev_info(&b4->pdev->dev, "Checking sync pos %d, have span %d\n", i, b4->spans[i].sync); ++ psrc = b4->spans[i].sync; ++ if (psrc > 0 && !b4->spans[psrc - 1].span.alarms) { ++ if (DBG) ++ dev_info(&b4->pdev->dev, "chosen\n"); ++ src = psrc; ++ break; ++ } ++ } ++ ++ if (src >= 0) ++ return src - 1; ++ else ++ return src; ++} ++ ++static ssize_t b4_timing_master_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct b4xxp *b4 = dev_get_drvdata(dev); ++ return sprintf(buf, "%d\n", b4->syncspan); ++} ++ ++static DEVICE_ATTR(timing_master, 0400, b4_timing_master_show, NULL); ++ ++static void create_sysfs_files(struct b4xxp *b4) ++{ ++ int ret; ++ ret = device_create_file(&b4->pdev->dev, ++ &dev_attr_timing_master); ++ if (ret) { ++ dev_info(&b4->pdev->dev, ++ "Failed to create device attributes.\n"); ++ } ++} ++ ++static void remove_sysfs_files(struct b4xxp *b4) ++{ ++ device_remove_file(&b4->pdev->dev, ++ &dev_attr_timing_master); ++} ++ ++/* ++ * allocates memory and pretty-prints a given S/T state engine state to it. ++ * calling routine is responsible for freeing the pointer returned! ++ * Performs no hardware access whatsoever, but does use GFP_KERNEL so do not call from IRQ context. ++ * if full == 1, prints a "full" dump; otherwise just prints current state. ++ */ ++static char *hfc_decode_st_state(struct b4xxp *b4, struct b4xxp_span *span, unsigned char state, int full) ++{ ++ int nt, sta; ++ char s[128], *str; ++ const char *ststr[2][16] = { /* TE, NT */ ++ { "RESET", "?", "SENSING", "DEACT.", "AWAIT.SIG", "IDENT.INPUT", "SYNCD", "ACTIVATED", ++ "LOSTFRAMING", "?", "?", "?", "?", "?", "?", "?" }, ++ { "RESET", "DEACT.", "PEND.ACT", "ACTIVE", "PEND.DEACT", "?", "?", "?", ++ "?", "?", "?", "?", "?", "?", "?", "?" } ++ }; ++ ++ str = kmalloc(256, GFP_ATOMIC); ++ if (!str) { ++ dev_warn(&b4->pdev->dev, "could not allocate mem for ST state decode string!\n"); ++ return NULL; ++ } ++ ++ nt = !span->te_mode; ++ sta = (state & V_ST_STA_MASK); ++ ++ sprintf(str, "P%d: %s state %c%d (%s)", span->port + 1, (nt ? "NT" : "TE"), (nt ? 'G' : 'F'), sta, ststr[nt][sta]); ++ ++ if (full) { ++ sprintf(s, " SYNC: %s, RX INFO0: %s", ((state & V_FR_SYNC) ? "yes" : "no"), ((state & V_INFO0) ? "yes" : "no")); ++ strcat(str, s); ++ ++ if (nt) { ++ sprintf(s, ", T2 %s, auto G2->G3: %s", ((state & V_T2_EXP) ? "expired" : "OK"), ++ ((state & V_G2_G3) ? "yes" : "no")); ++ strcat(str, s); ++ } ++ } ++ ++ return str; ++} ++ ++/* ++ * sets an S/T port state machine to a given state. ++ * if 'auto' is nonzero, will put the state machine back in auto mode after setting the state. ++ */ ++static void hfc_handle_state(struct b4xxp_span *s); ++static void hfc_force_st_state(struct b4xxp *b4, struct b4xxp_span *s, int state, int resume_auto) ++{ ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, ++ A_ST_RD_STA, state | V_ST_LD_STA); ++ ++ udelay(6); ++ ++ if (resume_auto) { ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_RD_STA, state); ++ } ++ ++ if (DBG_ST) { ++ char *x; ++ ++ x = hfc_decode_st_state(b4, s, state, 1); ++ dev_info(&b4->pdev->dev, ++ "forced port %d to state %d (auto: %d), new decode: %s\n", ++ s->port + 1, state, resume_auto, x); ++ kfree(x); ++ } ++ ++/* make sure that we activate any timers/etc needed by this state change */ ++ hfc_handle_state(s); ++} ++ ++static void hfc_stop_st(struct b4xxp_span *s); ++static void hfc_start_st(struct b4xxp_span *s); ++ ++/* figures out what to do when an S/T port's timer expires. */ ++static void hfc_timer_expire(struct b4xxp_span *s, int t_no) ++{ ++ struct b4xxp *b4 = s->parent; ++ ++ if (DBG_ST) { ++ dev_info(&b4->pdev->dev, ++ "%lu: hfc_timer_expire, Port %d T%d expired " ++ "(value=%lu ena=%d)\n", ++ b4->ticks, s->port + 1, t_no + 1, s->hfc_timers[t_no], ++ s->hfc_timer_on[t_no]); ++ } ++/* ++ * There are four timers associated with every HFC S/T port: ++ * T1 is used by the NT state machine, and is the maximum time the NT side ++ * should wait for G3 (active) state. ++ * T2 is not actually used in the driver, it is handled by the HFC-4S ++ * internally. ++ * T3 is used by the TE state machine; it is the maximum time the TE side should ++ * wait for the INFO4 (activated) signal. ++ * T4 is a special timer used for debug purposes for monitoring of L1 state ++ * during activation attempt. ++ */ ++ ++/* First, disable the expired timer; hfc_force_st_state() may activate it again. */ ++ s->hfc_timer_on[t_no] = 0; ++ ++ switch(t_no) { ++ case HFC_T1: /* switch to G4 (pending deact.), resume auto mode */ ++ hfc_force_st_state(b4, s, 4, 1); ++ break; ++ case HFC_T2: /* switch to G1 (deactivated), resume auto mode */ ++ hfc_force_st_state(b4, s, 1, 1); ++ break; ++ case HFC_T3: /* switch to F3 (deactivated), resume auto mode */ ++ hfc_stop_st(s); ++ if (persistentlayer1) ++ hfc_start_st(s); ++ break; ++ case HFC_T4: ++ hfc_handle_state(s); ++ s->hfc_timers[HFC_T4] = b4->ticks + 1000; ++ s->hfc_timer_on[HFC_T4] = 1; ++ break; ++ default: ++ if (printk_ratelimit()) { ++ dev_warn(&b4->pdev->dev, ++ "hfc_timer_expire found an unknown expired " ++ "timer (%d)??\n", t_no); ++ } ++ } ++} ++ ++/* ++ * Run through the active timers on a card and deal with any expiries. ++ * Also see if the alarm debounce time has expired and if it has, tell DAHDI. ++ */ ++static void hfc_update_st_timers(struct b4xxp *b4) ++{ ++ int i, j; ++ struct b4xxp_span *s; ++ ++ for (i=0; i < b4->numspans; i++) { ++ s = &b4->spans[i]; ++ ++ for (j = HFC_T1; j < ARRAY_SIZE(s->hfc_timers); j++) { ++ /* we don't really do timer2, it is expired by the ++ * state change handler */ ++ if (j == HFC_T2) ++ continue; ++ ++ if (s->hfc_timer_on[j] && time_after_eq(b4->ticks, s->hfc_timers[j])) { ++ hfc_timer_expire(s, j); ++ } ++ } ++ ++ if (s->newalarm != s->span.alarms && time_after_eq(b4->ticks, s->alarmtimer)) { ++ s->span.alarms = s->newalarm; ++ if ((!s->newalarm && teignorered) || (!teignorered)) { ++ dahdi_alarm_notify(&s->span); ++ } ++ b4xxp_set_sync_src(b4, b4xxp_find_sync(b4)); ++ if (DBG_ALARM) { ++ dev_info(&b4->pdev->dev, ++ "span %d: alarm %d " ++ "debounced\n", ++ i + 1, s->newalarm); ++ } ++ } ++ } ++} ++ ++/* this is the driver-level state machine for an S/T port */ ++static void hfc_handle_state(struct b4xxp_span *s) ++{ ++ struct b4xxp *b4; ++ unsigned char state, sta; ++ int nt, oldalarm; ++ unsigned long oldtimer; ++ ++ b4 = s->parent; ++ nt = !s->te_mode; ++ ++ state = b4xxp_getreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_RD_STA); ++ ++ sta = (state & V_ST_STA_MASK); ++ ++ if (DBG_ST) { ++ char *x; ++ ++ x = hfc_decode_st_state(b4, s, state, 1); ++ dev_info(&b4->pdev->dev, ++ "port %d phy_port %d A_ST_RD_STA old=0x%02x now=0x%02x, decoded: %s\n", ++ s->port + 1, s->phy_port, s->oldstate, state, x); ++ kfree(x); ++ } ++ ++ oldalarm = s->newalarm; ++ oldtimer = s->alarmtimer; ++ ++ if (nt) { ++ switch(sta) { ++ default: /* Invalid NT state */ ++ case 0x0: /* NT state G0: Reset */ ++ case 0x1: /* NT state G1: Deactivated */ ++ case 0x4: /* NT state G4: Pending Deactivation */ ++ s->newalarm = DAHDI_ALARM_RED; ++ break; ++ case 0x2: /* NT state G2: Pending Activation */ ++ s->newalarm = DAHDI_ALARM_YELLOW; ++ break; ++ case 0x3: /* NT state G3: Active */ ++ s->hfc_timer_on[HFC_T1] = 0; ++ s->newalarm = 0; ++ break; ++ } ++ } else { ++ switch(sta) { ++ default: /* Invalid TE state */ ++ case 0x0: /* TE state F0: Reset */ ++ case 0x2: /* TE state F2: Sensing */ ++ case 0x3: /* TE state F3: Deactivated */ ++ case 0x4: /* TE state F4: Awaiting Signal */ ++ case 0x8: /* TE state F8: Lost Framing */ ++ s->newalarm = DAHDI_ALARM_RED; ++ break; ++ case 0x5: /* TE state F5: Identifying Input */ ++ case 0x6: /* TE state F6: Synchronized */ ++ s->newalarm = DAHDI_ALARM_YELLOW; ++ break; ++ case 0x7: /* TE state F7: Activated */ ++ s->hfc_timer_on[HFC_T3] = 0; ++ s->hfc_timer_on[HFC_T4] = 0; ++ s->newalarm = 0; ++ break; ++ } ++ } ++ ++ s->alarmtimer = b4->ticks + alarmdebounce; ++ s->oldstate = state; ++ ++ if (DBG_ALARM) { ++ dev_info(&b4->pdev->dev, "span %d: old alarm %d expires %ld, new alarm %d expires %ld\n", ++ s->port + 1, oldalarm, oldtimer, s->newalarm, s->alarmtimer); ++ } ++ ++/* we only care about T2 expiry in G4. */ ++ if (nt && (sta == 4) && (state & V_T2_EXP)) { ++ if (s->hfc_timer_on[HFC_T2]) ++ hfc_timer_expire(s, HFC_T2); /* handle T2 expiry */ ++ } ++ ++/* If we're in F3 and receiving INFO0, start T3 and jump to F4 */ ++ if (!nt && (sta == 3) && (state & V_INFO0)) { ++ if (persistentlayer1) { ++ s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms; ++ s->hfc_timer_on[HFC_T3] = 1; ++ if (DBG_ST) { ++ dev_info(&b4->pdev->dev, ++ "port %d: receiving INFO0 in state 3, " ++ "setting T3 and jumping to F4\n", ++ s->port + 1); ++ } ++ hfc_start_st(s); ++ } ++ } ++} ++ ++static void hfc_stop_all_timers(struct b4xxp_span *s) ++{ ++ s->hfc_timer_on[HFC_T4] = 0; ++ s->hfc_timer_on[HFC_T3] = 0; ++ s->hfc_timer_on[HFC_T2] = 0; ++ s->hfc_timer_on[HFC_T1] = 0; ++} ++ ++static void hfc_stop_st(struct b4xxp_span *s) ++{ ++ struct b4xxp *b4 = s->parent; ++ ++ hfc_stop_all_timers(s); ++ ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_WR_STA, ++ V_ST_ACT_DEACTIVATE); ++} ++ ++/* ++ * resets an S/T interface to a given NT/TE mode ++ */ ++static void hfc_reset_st(struct b4xxp_span *s) ++{ ++ int b; ++ struct b4xxp *b4; ++ ++ b4 = s->parent; ++ ++ hfc_stop_st(s); ++ ++/* force state G0/F0 (reset), then force state 1/2 (deactivated/sensing) */ ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_WR_STA, V_ST_LD_STA); ++ flush_pci(); /* make sure write hit hardware */ ++ ++ s->span.alarms = DAHDI_ALARM_RED; ++ s->newalarm = DAHDI_ALARM_RED; ++ dahdi_alarm_notify(&s->span); ++ ++ udelay(10); ++ ++/* set up the clock control register. Must be done before we activate the interface. */ ++ if (s->te_mode) ++ b = 0x0e; ++ else ++ b = 0x0c | (6 << V_ST_SMPL_SHIFT); ++ ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_CLK_DLY, b); ++ ++/* set TE/NT mode, enable B and D channels. */ ++ ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_CTRL0, ++ V_B1_EN | V_B2_EN | (s->te_mode ? 0 : V_ST_MD)); ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_CTRL1, ++ V_G2_G3_EN | V_E_IGNO); ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_CTRL2, ++ V_B1_RX_EN | V_B2_RX_EN); ++ ++/* enable the state machine. */ ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_WR_STA, 0x00); ++ flush_pci(); ++ ++ udelay(100); ++} ++ ++static void hfc_start_st(struct b4xxp_span *s) ++{ ++ struct b4xxp *b4 = s->parent; ++ ++ b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_WR_STA, ++ V_ST_ACT_ACTIVATE); ++ ++/* start T1 if in NT mode, T3 if in TE mode */ ++ if (s->te_mode) { ++ s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms; ++ s->hfc_timer_on[HFC_T3] = 1; ++ s->hfc_timer_on[HFC_T1] = 0; ++ ++ s->hfc_timers[HFC_T4] = b4->ticks + 1000; ++ s->hfc_timer_on[HFC_T4] = 1; ++ ++ if (DBG_ST) { ++ dev_info(&b4->pdev->dev, ++ "setting port %d t3 timer to %lu\n", ++ s->port + 1, s->hfc_timers[HFC_T3]); ++ } ++ } else { ++ s->hfc_timers[HFC_T1] = b4->ticks + timer_1_ms; ++ s->hfc_timer_on[HFC_T1] = 1; ++ s->hfc_timer_on[HFC_T3] = 0; ++ if (DBG_ST) { ++ dev_info(&b4->pdev->dev, ++ "setting port %d t1 timer to %lu\n", ++ s->port + 1, s->hfc_timers[HFC_T1]); ++ } ++ } ++} ++ ++/* ++ * read in the HFC GPIO to determine each port's mode (TE or NT). ++ * Then, reset and start the port. ++ * the flow controller should be set up before this is called. ++ */ ++static void hfc_init_all_st(struct b4xxp *b4) ++{ ++ int gpio = 0; ++ int i, nt; ++ struct b4xxp_span *s; ++ ++ /* All other cards supported by this driver read jumpers for modes */ ++ if (!IS_GEN2(b4)) ++ gpio = b4xxp_getreg8(b4, R_GPI_IN3); ++ ++ for (i=0; i < b4->numspans; i++) { ++ s = &b4->spans[i]; ++ s->parent = b4; ++ ++ if (IS_B430P(b4)) { ++ /* The physical ports are reversed on the b430 */ ++ /* Port 0-3 in b4->spans[] are physically ports 3-0 */ ++ s->phy_port = b4->numspans-1-i; ++ s->port = i; ++ } else if (IS_B230P(b4)) { ++ /* The physical ports are reversed on the b230 */ ++ /* Port 0-1 in b4->spans[] are physically ports 2-1 */ ++ s->phy_port = b4->numspans - i; ++ s->port = i; ++ } else { ++ s->phy_port = i; ++ s->port = i; ++ } ++ ++ /* The way the Digium B410P card reads the NT/TE mode ++ * jumper is the oposite of how other HFC-4S cards do: ++ * - In B410P: GPIO=0: NT ++ * - In Junghanns: GPIO=0: TE ++ */ ++ if (IS_B410P(b4)) { ++ nt = ((gpio & (1 << (i + 4))) == 0); ++ } else if (IS_GEN2(b4)) { ++ /* Read default digital lineconfig reg on GEN2 */ ++ int reg; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ hfc_gpio_set(b4, 0x20); ++ reg = hfc_sram_read(b4); ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++ ++ if (reg & (1 << (4 + s->phy_port))) ++ nt = 1; ++ else ++ nt = 0; ++ } else { ++ nt = ((gpio & (1 << (i + 4))) != 0); ++ } ++ ++ s->te_mode = !nt; ++ ++ dev_info(&b4->pdev->dev, ++ "Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE")); ++ ++ } ++} ++ ++/* ++ * Look at one B-channel FIFO and determine if we should exchange data with it. ++ * It is assumed that the S/T port is active. ++ * returns 1 if data was exchanged, 0 otherwise. ++ */ ++static int hfc_poll_one_bchan_fifo(struct b4xxp_span *span, int c) ++{ ++ int fifo, zlen, z1, z2, ret; ++ unsigned long irq_flags; ++ struct b4xxp *b4; ++ struct dahdi_chan *chan; ++ ++ ret = 0; ++ b4 = span->parent; ++ fifo = span->fifos[c]; ++ chan = span->chans[c]; ++ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ ++/* select RX FIFO */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR | V_REV); ++ ++ get_Z(z1, z2, zlen); ++ ++/* TODO: error checking, full FIFO mostly */ ++ ++ if (zlen >= DAHDI_CHUNKSIZE) { ++ *(unsigned int *)&chan->readchunk[0] = b4xxp_getreg32(b4, A_FIFO_DATA2); ++ *(unsigned int *)&chan->readchunk[4] = b4xxp_getreg32(b4, A_FIFO_DATA2); ++/* ++ * now TX FIFO ++ * ++ * Note that we won't write to the TX FIFO if there wasn't room in the RX FIFO. ++ * The TX and RX sides should be kept pretty much lock-step. ++ * ++ * Write the last byte _NOINC so that if we don't get more data in time, we aren't leaking unknown data ++ * (See HFC datasheet) ++ */ ++ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_REV); ++ ++ b4xxp_setreg32(b4, A_FIFO_DATA2, *(unsigned int *) &chan->writechunk[0]); ++ b4xxp_setreg32(b4, A_FIFO_DATA2, *(unsigned int *) &chan->writechunk[4]); ++ ret = 1; ++ } ++ ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++ return ret; ++} ++ ++/* ++ * Run through all of the host-facing B-channel RX FIFOs, looking for at least 8 bytes available. ++ * If a B channel RX fifo has enough data, perform the data transfer in both directions. ++ * D channel is done in an interrupt handler. ++ * The S/T port state must be active or we ignore the fifo. ++ * Returns nonzero if there was at least DAHDI_CHUNKSIZE bytes in the FIFO ++ */ ++static int hfc_poll_fifos(struct b4xxp *b4) ++{ ++ int ret=0, span; ++ unsigned long irq_flags; ++ ++ for (span=0; span < b4->numspans; span++) { ++ ++/* Make sure DAHDI's got this span up */ ++ if (!(b4->spans[span].span.flags & DAHDI_FLAG_RUNNING)) ++ continue; ++ ++/* TODO: Make sure S/T port is in active state */ ++ ret = hfc_poll_one_bchan_fifo(&b4->spans[span], 0); ++ ret |= hfc_poll_one_bchan_fifo(&b4->spans[span], 1); ++ } ++ ++/* change the active FIFO one last time to make sure the last-changed FIFO updates its pointers (as per the datasheet) */ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ hfc_setreg_waitbusy(b4, R_FIFO, (31 << V_FIFO_NUM_SHIFT)); ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++ ++ return ret; ++} ++ ++/* NOTE: assumes fifo lock is held */ ++static inline void debug_fz(struct b4xxp *b4, int fifo, const char *prefix, char *buf) ++{ ++ int f1, f2, flen, z1, z2, zlen; ++ ++ get_F(f1, f2, flen); ++ get_Z(z1, z2, zlen); ++ ++ sprintf(buf, "%s: (fifo %d): f1/f2/flen=%d/%d/%d, z1/z2/zlen=%d/%d/%d\n", prefix, fifo, f1, f2, flen, z1, z2, zlen); ++} ++ ++/* enable FIFO RX int and reset the FIFO */ ++static int hdlc_start(struct b4xxp *b4, int fifo) ++{ ++ b4->fifo_en_txint |= (1 << fifo); ++ b4->fifo_en_rxint |= (1 << fifo); ++ ++ hfc_reset_fifo_pair(b4, fifo, 1, 0); ++ return 0; ++} ++ ++/* disable FIFO ints and reset the FIFO */ ++static void hdlc_stop(struct b4xxp *b4, int fifo) ++{ ++ b4->fifo_en_txint &= ~(1 << fifo); ++ b4->fifo_en_rxint &= ~(1 << fifo); ++ ++ hfc_reset_fifo_pair(b4, fifo, 1, 0); ++} ++ ++/* ++ * Inner loop for D-channel receive function. ++ * Retrieves a full HDLC frame from the hardware. ++ * If the hardware indicates that the frame is complete, ++ * we check the HDLC engine's STAT byte and update DAHDI as needed. ++ * ++ * Returns the number of HDLC frames left in the FIFO. ++ */ ++static int hdlc_rx_frame(struct b4xxp_span *bspan) ++{ ++ int fifo, i, j, zleft; ++ int z1, z2, zlen, f1, f2, flen; ++ unsigned char buf[WCB4XXP_HDLC_BUF_LEN]; ++ char debugbuf[256]; ++ unsigned long irq_flags; ++ struct b4xxp *b4 = bspan->parent; ++ unsigned char stat; ++ ++ fifo = bspan->fifos[2]; ++ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ get_F(f1, f2, flen); ++ get_Z(z1, z2, zlen); ++ debug_fz(b4, fifo, "hdlc_rx_frame", debugbuf); ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++ ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ pr_info("%s", debugbuf); ++ } ++ ++/* first check to make sure we really do have HDLC frames available to retrieve */ ++ if (flen == 0) { ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ dev_info(&b4->pdev->dev, "hdlc_rx_frame(span %d): no frames available?\n", ++ bspan->port + 1); ++ } ++ ++ return flen; ++ } ++ ++ zleft = zlen + 1; /* include STAT byte that the HFC injects after FCS */ ++ ++ do { ++ int truncated; ++ if (zleft > WCB4XXP_HDLC_BUF_LEN) { ++ truncated = 1; ++ j = WCB4XXP_HDLC_BUF_LEN; ++ } else { ++ truncated = 0; ++ j = zleft; ++ } ++ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ for (i=0; i < j; i++) ++ buf[i] = b4xxp_getreg8(b4, A_FIFO_DATA0); ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++ ++/* don't send STAT byte to DAHDI */ ++ if ((bspan->sigchan) && (j > 1)) ++ dahdi_hdlc_putbuf(bspan->sigchan, buf, truncated ? j : j - 1); ++ ++ zleft -= j; ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ dev_info(&b4->pdev->dev, "hdlc_rx_frame(span %d): z1/z2/zlen=%d/%d/%d, zleft=%d\n", ++ bspan->port + 1, z1, z2, zlen, zleft); ++ for (i=0; i < j; i++) printk("%02x%c", buf[i], (i < ( j - 1)) ? ' ':'\n'); ++ } ++ } while (zleft > 0); ++ stat = buf[j - 1]; ++ ++/* Frame received, increment F2 and get an updated count of frames left */ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F); ++ get_F(f1, f2, flen); ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++ ++ /* If this channel is not configured with a signalling span we don't ++ * need to notify the rest of dahdi about this frame. */ ++ if (!bspan->sigchan) ++ return flen; ++ ++ ++bspan->frames_in; ++ if (zlen < 3) { ++ if (DBG_HDLC && DBG_SPANFILTER) ++ dev_notice(&b4->pdev->dev, "odd, zlen less then 3?\n"); ++ dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_ABORT); ++ } else { ++ ++/* if STAT != 0, indicates bad frame */ ++ if (stat != 0x00) { ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ dev_info(&b4->pdev->dev, ++ "(span %d) STAT=0x%02x indicates " ++ "frame problem: ", ++ bspan->port + 1, stat); ++ } ++ if (stat == 0xff) { ++ if (DBG_HDLC && DBG_SPANFILTER) ++ printk("HDLC Abort\n"); ++ dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_ABORT); ++ } else { ++ if (DBG_HDLC && DBG_SPANFILTER) ++ printk("Bad FCS\n"); ++ dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_BADFCS); ++ } ++/* STAT == 0, means frame was OK */ ++ } else { ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ dev_info(&b4->pdev->dev, ++ "(span %d) Frame %d is good!\n", ++ bspan->port + 1, bspan->frames_in); ++ } ++ dahdi_hdlc_finish(bspan->sigchan); ++ } ++ } ++ ++ return flen; ++} ++ ++ ++/* ++ * Takes one blob of data from DAHDI and shoots it out to the hardware. ++ * The blob may or may not be a complete HDLC frame. ++ * If it isn't, the D-channel FIFO interrupt handler will take care of pulling the rest. ++ * Returns nonzero if there is still data to send in the current HDLC frame. ++ */ ++static int hdlc_tx_frame(struct b4xxp_span *bspan) ++{ ++ struct b4xxp *b4 = bspan->parent; ++ int res, i, fifo; ++ int z1, z2, zlen; ++ unsigned char buf[WCB4XXP_HDLC_BUF_LEN]; ++ unsigned int size = sizeof(buf) / sizeof(buf[0]); ++ char debugbuf[256]; ++ unsigned long irq_flags; ++ ++ /* if we're ignoring TE red alarms and we are in alarm, restart the ++ * S/T state machine */ ++ if (bspan->te_mode && bspan->newalarm != 0) ++ hfc_start_st(bspan); ++ ++ fifo = bspan->fifos[2]; ++ res = dahdi_hdlc_getbuf(bspan->sigchan, buf, &size); ++ ++ spin_lock_irqsave(&b4->fifolock, irq_flags); ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ ++ get_Z(z1, z2, zlen); ++ debug_fz(b4, fifo, "hdlc_tx_frame", debugbuf); ++ ++/* TODO: check zlen, etc. */ ++ ++ if (size > 0) { ++ bspan->sigactive = 1; ++ ++ for (i=0; i < size; i++) ++ b4xxp_setreg8(b4, A_FIFO_DATA0, buf[i]); ++ ++/* ++ * If we got a full frame from DAHDI, increment F and decrement our HDLC pending counter. ++ * Otherwise, select the FIFO again (to start transmission) and make sure the ++ * TX IRQ is enabled so we will get called again to finish off the data ++ */ ++ if (res != 0) { ++ ++bspan->frames_out; ++ bspan->sigactive = 0; ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F); ++ atomic_dec(&bspan->hdlc_pending); ++ } else { ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_IRQ_MSK, V_IRQ); ++ } ++ } ++ ++/* if there are no more frames pending, disable the interrupt. */ ++ if (res == -1) { ++ b4xxp_setreg8(b4, A_IRQ_MSK, 0); ++ } ++ ++ spin_unlock_irqrestore(&b4->fifolock, irq_flags); ++ ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ dev_info(&b4->pdev->dev, "%s", debugbuf); ++ dev_info(&b4->pdev->dev, "hdlc_tx_frame(span %d): DAHDI gave %d bytes for FIFO %d (res=%d)\n", ++ bspan->port + 1, size, fifo, res); ++ for (i=0; i < size; i++) ++ printk("%02x%c", buf[i], (i < (size - 1)) ? ' ' : '\n'); ++ ++ if (size && res != 0) { ++ pr_info("Transmitted frame %d on span %d\n", ++ bspan->frames_out - 1, bspan->port + 1); ++ } ++ } ++ ++ return(res == 0); ++} ++ ++/* ++ * b4xxp lowlevel functions ++ * These are functions which impact more than just the HFC controller. ++ * (those are named hfc_xxx()) ++ */ ++ ++/* ++ * Performs a total reset of the card, reinitializes GPIO. ++ * The card is initialized enough to have LEDs running, and that's about it. ++ * Anything to do with audio and enabling any kind of processing is done in stage2. ++ */ ++static void b4xxp_init_stage1(struct b4xxp *b4) ++{ ++ int i; ++ ++ hfc_reset(b4); /* total reset of controller */ ++ hfc_gpio_init(b4); /* initialize controller GPIO for CPLD access */ ++ ec_init(b4); /* initialize VPM and VPM GPIO */ ++ ++ b4xxp_setreg8(b4, R_IRQ_CTRL, 0x00); /* make sure interrupts are disabled */ ++ flush_pci(); /* make sure PCI write hits hardware */ ++ ++/* disable all FIFO interrupts */ ++ for (i=0; i < HFC_NR_FIFOS; i++) { ++ hfc_setreg_waitbusy(b4, R_FIFO, (i << V_FIFO_NUM_SHIFT)); ++ b4xxp_setreg8(b4, A_IRQ_MSK, 0x00); /* disable the interrupt */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (i << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b4xxp_setreg8(b4, A_IRQ_MSK, 0x00); /* disable the interrupt */ ++ flush_pci(); ++ } ++ ++/* clear any pending FIFO interrupts */ ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL0); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL1); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL2); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL3); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL4); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL5); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL6); ++ b4xxp_getreg8(b4, R_IRQ_FIFO_BL7); ++ ++ b4xxp_setreg8(b4, R_SCI_MSK, 0x00); /* mask off all S/T interrupts */ ++ b4xxp_setreg8(b4, R_IRQMSK_MISC, 0x00); /* nothing else can generate an interrupt */ ++ ++ /* ++ * set up the clock controller B410P & Cologne Eval Board have a ++ * 24.576MHz crystal, so the PCM clock is 2x the incoming clock. ++ * Other cards have a 49.152Mhz crystal, so the PCM clock equals ++ * incoming clock. ++ */ ++ ++ if (IS_B410P(b4) || IS_GEN2(b4) || (b4->card_type == QUADBRI_EVAL)) ++ b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x02); ++ else ++ b4xxp_setreg8(b4, R_BRG_PCM_CFG, V_PCM_CLK); ++ ++ /* Reset LED state */ ++ b4->ledreg = 0; ++ b4xxp_update_leds(b4); ++ ++ flush_pci(); ++ ++ udelay(100); /* wait a bit for clock to settle */ ++} ++ ++/* ++ * Stage 2 hardware init. ++ * Sets up the flow controller, PCM and FIFOs. ++ * Initializes the echo cancellers. ++ * S/T interfaces are not initialized here, that is done later, in hfc_init_all_st(). ++ * Interrupts are enabled and once the s/t interfaces are configured, chip should be pretty much operational. ++ */ ++static void b4xxp_init_stage2(struct b4xxp *b4) ++{ ++ int span; ++ ++/* ++ * set up PCM bus. ++ * HFC is PCM master. ++ * C4IO, SYNC_I and SYNC_O unused. ++ * 32 channels, frame signal positive polarity, active for 2 C4 clocks. ++ * only the first two timeslots in each quad are active ++ * STIO0 is transmit-only, STIO1 is receive-only. ++ */ ++ b4xxp_setreg8(b4, R_PCM_MD0, V_PCM_MD | V_PCM_IDX_MD1); ++ flush_pci(); ++ ++ if (IS_GEN2(b4)) { ++ b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_4096); ++ b4xxp_setreg8(b4, R_PWM_MD, 0x50); ++ b4xxp_setreg8(b4, R_PWM0, 0x38); ++ } else { ++ b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_2048); ++ b4xxp_setreg8(b4, R_PWM_MD, 0xa0); ++ b4xxp_setreg8(b4, R_PWM0, 0x1b); ++ } ++ ++/* ++ * set up the flow controller. ++ * B channel map: (4 ports cards with Hardware Echo Cancel present & active) ++ * FIFO 0 connects Port 1 B0 using HFC channel 16 and PCM timeslots 0/1. ++ * FIFO 1 connects Port 1 B1 using HFC channel 17 and PCM timeslots 4/5. ++ * FIFO 2 connects Port 2 B0 using HFC channel 20 and PCM timeslots 8/9. ++ * FIFO 3 connects Port 2 B1 using HFC channel 21 and PCM timeslots 12/13. ++ * FIFO 4 connects Port 3 B0 using HFC channel 24 and PCM timeslots 16/17. ++ * FIFO 5 connects Port 3 B1 using HFC channel 25 and PCM timeslots 20/21. ++ * FIFO 6 connects Port 4 B0 using HFC channel 28 and PCM timeslots 24/25. ++ * FIFO 7 connects Port 4 B1 using HFC channel 29 and PCM timeslots 28/29. ++ * ++ * All B channel FIFOs have their HDLC controller in transparent mode, ++ * and only the FIFO for B0 on each port has its interrupt operational. ++ * ++ * D channels are handled by FIFOs 8-11. ++ * FIFO 8 connects Port 1 D using HFC channel 3 ++ * FIFO 9 connects Port 2 D using HFC channel 7 ++ * FIFO 10 connects Port 3 D using HFC channel 11 ++ * FIFO 11 connects Port 4 D using HFC channel 15 ++ * ++ * D channel FIFOs are operated in HDLC mode and interrupt on end of frame. ++ * ++ * B channel map: (8 ports cards without Hardware Echo Cancel) ++ * FIFO 0 connects Port 1 B0 using HFC channel 0 ++ * FIFO 1 connects Port 1 B1 using HFC channel 1 ++ * FIFO 2 connects Port 2 B0 using HFC channel 4 ++ * FIFO 3 connects Port 2 B1 using HFC channel 5 ++ * ......................... ++ * FIFO 14 connects Port 8 B0 using HFC channel 28 ++ * FIFO 15 connects Port 8 B1 using HFC channel 29 ++ * ++ * All B channel FIFOs have their HDLC controller in transparent mode, ++ * and only the FIFO for B0 on each port has its interrupt operational. ++ * ++ * D channels are handled by FIFOs 16-23. ++ * FIFO 16 connects Port 1 D using HFC channel 3 ++ * FIFO 17 connects Port 2 D using HFC channel 7 ++ * FIFO 18 connects Port 3 D using HFC channel 11 ++ * FIFO 19 connects Port 4 D using HFC channel 15 ++ * ................ ++ * FIFO 23 connects Port 8 D using HFC channel 31 ++ * D channel FIFOs are operated in HDLC mode and interrupt on end of frame. ++ */ ++ for (span=0; span < b4->numspans; span++) { ++ if (IS_B430P(b4)) { ++ hfc_assign_fifo_zl(b4, span, 0); ++ hfc_assign_fifo_zl(b4, span, 1); ++ hfc_assign_dchan_fifo(b4, span); ++ } else if (IS_B230P(b4)) { ++ hfc_assign_fifo_zl(b4, span + 1, 0); ++ hfc_assign_fifo_zl(b4, span + 1, 1); ++ hfc_assign_dchan_fifo(b4, span + 1); ++ } else { ++ if ((vpmsupport) && (CARD_HAS_EC(b4))) { ++ hfc_assign_bchan_fifo_ec(b4, span, 0); ++ hfc_assign_bchan_fifo_ec(b4, span, 1); ++ } else { ++ hfc_assign_bchan_fifo_noec(b4, span, 0); ++ hfc_assign_bchan_fifo_noec(b4, span, 1); ++ } ++ hfc_assign_dchan_fifo(b4, span); ++ } ++ } ++ ++/* set up the timer interrupt for 1ms intervals */ ++ b4xxp_setreg8(b4, R_TI_WD, (2 << V_EV_TS_SHIFT)); ++ ++/* ++ * At this point, everything's set up and ready to go. ++ * Don't actually enable the global interrupt pin. ++ * DAHDI still needs to start up the spans, and we don't know exactly when. ++ */ ++} ++ ++static void b4xxp_setleds(struct b4xxp *b4, unsigned char val) ++{ ++ ec_write(b4, 0, 0x1a8 + 3, val); ++} ++ ++static void b4xxp_update_leds_hfc_8s(struct b4xxp *b4) ++{ ++ unsigned long lled = 0; /* A bit set is a led OFF */ ++ unsigned long leddw; ++ int j; ++ struct b4xxp_span *bspan; ++ ++ b4->blinktimer++; ++ for (j = 7; j >= 0; j--) { ++ bspan = &b4->spans[7 - j]; ++ if (!(bspan->span.flags & DAHDI_FLAG_RUNNING) || ++ bspan->span.alarms) { ++ BIT_SET(lled, j); ++ continue; /* Led OFF */ ++ } ++ ++ if (bspan->span.mainttimer || bspan->span.maintstat) { ++ /* Led Blinking in maint state */ ++ if (b4->blinktimer >= 0x7f) ++ BIT_SET(lled, j); ++ } ++ /* Else: Led on */ ++ } ++ ++ /* Write Leds...*/ ++ leddw = lled << 24 | lled << 16 | lled << 8 | lled; ++ b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x21); ++ iowrite16(0x4000, b4->ioaddr + 4); ++ iowrite32(leddw, b4->ioaddr); ++ b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x20); ++ ++ if (b4->blinktimer == 0xff) ++ b4->blinktimer = -1; ++} ++ ++/* So far only tested for OpenVox cards. Please test it for other hardware */ ++static void b4xxp_update_leds_hfc(struct b4xxp *b4) ++{ ++ int i; ++ int leds = 0, green_leds = 0; /* Default: off */ ++ struct b4xxp_span *bspan; ++ ++ b4->blinktimer++; ++ for (i=0; i < b4->numspans; i++) { ++ bspan = &b4->spans[i]; ++ ++ if (!(bspan->span.flags & DAHDI_FLAG_RUNNING)) ++ continue; /* Leds are off */ ++ ++ if (bspan->span.alarms) { ++ /* Red blinking -> Alarm */ ++ if (b4->blinktimer >= 0x7f) ++ BIT_SET(leds, i); ++ } else if (bspan->span.mainttimer || bspan->span.maintstat) { ++ /* Green blinking -> Maint status */ ++ if (b4->blinktimer >= 0x7f) ++ BIT_SET(green_leds, i); ++ } else { ++ /* Steady grean -> No Alarm */ ++ BIT_SET(green_leds, i); ++ } ++ } ++ ++ /* Actually set them. for red: just set the bit in R_GPIO_EN1. ++ For green: in both R_GPIO_EN1 and R_GPIO_OUT1. */ ++ leds |= green_leds; ++ b4xxp_setreg8(b4, R_GPIO_EN1, leds); ++ hfc_gpio_set(b4, green_leds); ++ ++ if (b4->blinktimer == 0xff) ++ b4->blinktimer = -1; ++} ++ ++static void b4xxp_set_span_led(struct b4xxp *b4, int span, unsigned char val) ++{ ++ if (IS_GEN2(b4)) { ++ unsigned long flags; ++ ++ if (IS_B230P(b4)) { ++ b4->ledreg &= ~(0x03 << (span + 1)*2); ++ b4->ledreg |= (val << (span + 1)*2); ++ } else { ++ b4->ledreg &= ~(0x03 << span*2); ++ b4->ledreg |= (val << span*2); ++ } ++ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ /* Set multiplexer for led R/W */ ++ hfc_gpio_set(b4, 0x10); ++ hfc_sram_write(b4, b4->ledreg); ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++ } else { ++ int shift, spanmask; ++ ++ shift = span << 1; ++ spanmask = ~(0x03 << shift); ++ ++ b4->ledreg &= spanmask; ++ b4->ledreg |= (val << shift); ++ b4xxp_setleds(b4, b4->ledreg); ++ } ++} ++ ++static void b4xxp_update_leds(struct b4xxp *b4) ++{ ++ int i; ++ struct b4xxp_span *bspan; ++ ++ if (b4->numspans == 8) { ++ /* Use the alternative function for non-Digium HFC-8S cards */ ++ b4xxp_update_leds_hfc_8s(b4); ++ return; ++ } ++ ++ if (!IS_B410P(b4) && !IS_GEN2(b4)) { ++ /* Use the alternative function for non-Digium HFC-4S cards */ ++ b4xxp_update_leds_hfc(b4); ++ return; ++ } ++ ++ b4->blinktimer++; ++ for (i=0; i < b4->numspans; i++) { ++ bspan = &b4->spans[i]; ++ ++ if (bspan->span.flags & DAHDI_FLAG_RUNNING) { ++ if (bspan->span.alarms) { ++ if (b4->blinktimer == (led_fader_table[b4->alarmpos] >> 1)) ++ b4xxp_set_span_led(b4, i, LED_RED); ++ if (b4->blinktimer == 0xf) ++ b4xxp_set_span_led(b4, i, LED_OFF); ++ } else if (bspan->span.mainttimer || bspan->span.maintstat) { ++ if (b4->blinktimer == (led_fader_table[b4->alarmpos] >> 1)) ++ b4xxp_set_span_led(b4, i, LED_GREEN); ++ if (b4->blinktimer == 0xf) ++ b4xxp_set_span_led(b4, i, LED_OFF); ++ } else { ++ /* No Alarm */ ++ b4xxp_set_span_led(b4, i, LED_GREEN); ++ } ++ } else ++ b4xxp_set_span_led(b4, i, LED_OFF); ++ } ++ ++ if (b4->blinktimer == 0xf) { ++ b4->blinktimer = -1; ++ b4->alarmpos++; ++ if (b4->alarmpos >= (sizeof(led_fader_table) / sizeof(led_fader_table[0]))) ++ b4->alarmpos = 0; ++ } ++} ++ ++static const char *b4xxp_echocan_name(const struct dahdi_chan *chan) ++{ ++ struct b4xxp_span *bspan = container_of(chan->span, struct b4xxp_span, ++ span); ++ if (!vpmsupport) ++ return NULL; ++ ++ if (IS_B410P(bspan->parent)) ++ return "LASVEGAS2"; ++ ++ if (IS_GEN2(bspan->parent)) ++ return "ZARLINK"; ++ ++ return NULL; ++} ++ ++static int b4xxp_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ struct b4xxp_span *bspan = container_of(chan->span, struct b4xxp_span, span); ++ int channel; ++ ++ if (!vpmsupport || !CARD_HAS_EC(bspan->parent)) ++ return -ENODEV; ++ ++ if (chan->chanpos == 3) { ++ printk(KERN_WARNING "Cannot enable echo canceller on D channel of span %d; failing request\n", chan->span->offset); ++ return -EINVAL; ++ } ++ ++ if (ecp->param_count > 0) { ++ printk(KERN_WARNING "wcb4xxp echo canceller does not support parameters; failing request\n"); ++ return -EINVAL; ++ } ++ ++ *ec = &bspan->ec[chan->chanpos]; ++ (*ec)->ops = &my_ec_ops; ++ (*ec)->features = my_ec_features; ++ ++ if (DBG_EC) ++ printk("Enabling echo cancellation on chan %d span %d\n", chan->chanpos, chan->span->offset); ++ ++ if (IS_GEN2(bspan->parent)) { ++ int group; ++ int chan_offset = (chan->chanpos % 2) ? 0x00 : 0x20; ++ int reg; ++ unsigned long flags; ++ ++ /* Zarlink has 4 groups of 2 channel echo cancelers */ ++ /* Each channel has it's own individual control reg */ ++ group = bspan->phy_port * 0x40; ++ ++ spin_lock_irqsave(&bspan->parent->seqlock, flags); ++ reg = __zl_read(bspan->parent, group + chan_offset); ++ reg &= ~(1 << 3); ++ __zl_write(bspan->parent, group + chan_offset, reg); ++ spin_unlock_irqrestore(&bspan->parent->seqlock, flags); ++ } else { ++ channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1; ++ ec_write(bspan->parent, chan->chanpos - 1, channel, 0x7e); ++ } ++ ++ return 0; ++} ++ ++static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct b4xxp_span *bspan = container_of(chan->span, struct b4xxp_span, span); ++ int channel; ++ ++ memset(ec, 0, sizeof(*ec)); ++ ++ if (DBG_EC) ++ printk("Disabling echo cancellation on chan %d span %d\n", chan->chanpos, chan->span->offset); ++ ++ if (IS_GEN2(bspan->parent)) { ++ int group; ++ int chan_offset = (chan->chanpos % 2) ? 0x00 : 0x20; ++ int reg; ++ unsigned long flags; ++ ++ /* Zarlink has 4 groups of 2 channel echo cancelers */ ++ /* Each channel has it's own individual control reg */ ++ group = bspan->phy_port * 0x40; ++ ++ spin_lock_irqsave(&bspan->parent->seqlock, flags); ++ reg = __zl_read(bspan->parent, group + chan_offset); ++ reg |= (1 << 3); ++ __zl_write(bspan->parent, group + chan_offset, reg); ++ spin_unlock_irqrestore(&bspan->parent->seqlock, flags); ++ } else { ++ channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1; ++ ec_write(bspan->parent, chan->chanpos - 1, channel, 0x01); ++ } ++} ++ ++/* ++ * Filesystem and DAHDI interfaces ++ */ ++static int b4xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) ++{ ++ switch(cmd) { ++ default: ++ return -ENOTTY; ++ } ++ ++ return 0; ++} ++ ++static int b4xxp_startup(struct file *file, struct dahdi_span *span) ++{ ++ struct b4xxp_span *bspan = container_of(span, struct b4xxp_span, span); ++ struct b4xxp *b4 = bspan->parent; ++ ++ if (!b4->running) ++ hfc_enable_interrupts(bspan->parent); ++ ++ return 0; ++} ++ ++static int b4xxp_shutdown(struct dahdi_span *span) ++{ ++ struct b4xxp_span *bspan = container_of(span, struct b4xxp_span, span); ++ ++ hfc_disable_interrupts(bspan->parent); ++ return 0; ++} ++ ++/* resets all the FIFOs for a given span. Disables IRQs for the span FIFOs */ ++static void b4xxp_reset_span(struct b4xxp_span *bspan) ++{ ++ int i; ++ struct b4xxp *b4 = bspan->parent; ++ ++ for (i=0; i < 3; i++) { ++ hfc_reset_fifo_pair(b4, bspan->fifos[i], (i == 2) ? 1 : 0, 1); ++ } ++ ++ b4xxp_set_sync_src(b4, b4xxp_find_sync(b4)); ++} ++ ++/* spanconfig for us means to set up the HFC FIFO and channel mapping */ ++static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ int i; ++ struct b4xxp_span *bspan = container_of(span, struct b4xxp_span, span); ++ struct b4xxp *b4 = bspan->parent; ++ ++ if (DBG) ++ dev_info(&b4->pdev->dev, "Configuring span %d offset %d to be sync %d\n", span->spanno, span->offset, lc->sync); ++ ++ if (lc->sync < 0 || lc->sync > b4->numspans) { ++ dev_info(&b4->pdev->dev, ++ "Span %d has invalid sync priority (%d), removing " ++ "from sync source list\n", span->spanno, lc->sync); ++ lc->sync = 0; ++ } ++ ++ /* remove this span number from the current sync sources, if there */ ++ for (i = 0; i < b4->numspans; i++) { ++ if (b4->spans[i].sync == (span->offset + 1)) { ++ b4->spans[i].sync = 0; ++ } ++ } ++ ++ if (lc->sync) ++ b4->spans[lc->sync - 1].sync = (span->offset + 1); ++ ++ /* B430 sets TE/NT and Termination resistance modes via dahdi_cfg */ ++ if (IS_GEN2(b4)) { ++ int te_mode, term, reg; ++ unsigned long flags; ++ ++ te_mode = (lc->lineconfig & DAHDI_CONFIG_NTTE) ? 0 : 1; ++ term = (lc->lineconfig & DAHDI_CONFIG_TERM) ? 1 : 0; ++ dev_info(&b4->pdev->dev, ++ "Configuring span %d in %s mode with termination resistance %s\n", ++ bspan->port + 1, (te_mode) ? "TE" : "NT", ++ (term) ? "ENABLED" : "DISABLED"); ++ ++ if (!te_mode && lc->sync) { ++ dev_info(&b4->pdev->dev, ++ "NT Spans cannot be timing sources. Changing priority to 0\n"); ++ lc->sync = 0; ++ } ++ ++ /* Setup NT/TE */ ++ /* Bits 7 downto 5 correspond to spans 4-1 */ ++ /* 1 sets NT mode, 0 sets TE mode */ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ hfc_gpio_set(b4, 0x20); ++ reg = hfc_sram_read(b4); ++ hfc_gpio_set(b4, 0x00); ++ ++ if (te_mode) ++ reg &= ~(1 << (7 - bspan->phy_port)); ++ else ++ reg |= (1 << (7 - bspan->phy_port)); ++ ++ /* Setup Termination resistance */ ++ /* Bits 4 downto 0 correspond to spans 4-1 */ ++ /* 1 sets resistance mode, 0 sets no resistance */ ++ if (term) ++ reg |= (1 << (3 - bspan->phy_port)); ++ else ++ reg &= ~(1 << (3 - bspan->phy_port)); ++ ++ hfc_gpio_set(b4, 0x20); ++ hfc_sram_write(b4, reg); ++ hfc_gpio_set(b4, 0x00); ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++ ++ bspan->te_mode = te_mode; ++ bspan->span.spantype = (bspan->te_mode) ++ ? SPANTYPE_DIGITAL_BRI_TE ++ : SPANTYPE_DIGITAL_BRI_NT; ++ } ++ ++ hfc_reset_st(bspan); ++ if (persistentlayer1) ++ hfc_start_st(bspan); ++ ++ b4xxp_reset_span(bspan); ++ ++/* call startup() manually here, because DAHDI won't call the startup function unless it receives an IOCTL to do so, and dahdi_cfg doesn't. */ ++ b4xxp_startup(file, &bspan->span); ++ ++ span->flags |= DAHDI_FLAG_RUNNING; ++ ++ return 0; ++} ++ ++/* chanconfig for us means to configure the HDLC controller, if appropriate */ ++static int ++b4xxp_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype) ++{ ++ int alreadyrunning; ++ struct b4xxp *b4 = chan->pvt; ++ struct b4xxp_span *bspan = &b4->spans[chan->span->offset]; ++ int fifo = bspan->fifos[2]; ++ ++ alreadyrunning = bspan->span.flags & DAHDI_FLAG_RUNNING; ++ ++ if (DBG_FOPS) { ++ dev_info(&b4->pdev->dev, "%s channel %d (%s) sigtype %08x\n", ++ alreadyrunning ? "Reconfigured" : "Configured", chan->channo, chan->name, sigtype); ++ } ++ ++ /* (re)configure signalling channel */ ++ if ((sigtype == DAHDI_SIG_HARDHDLC) || (bspan->sigchan == chan)) { ++ if (DBG_FOPS) ++ dev_info(&b4->pdev->dev, "%sonfiguring hardware HDLC on %s\n", ++ ((sigtype == DAHDI_SIG_HARDHDLC) ? "C" : "Unc"), chan->name); ++ ++ if (alreadyrunning && bspan->sigchan) { ++ hdlc_stop(b4, fifo); ++ atomic_set(&bspan->hdlc_pending, 0); ++ bspan->sigactive = 0; ++ smp_mb(); ++ bspan->sigchan = NULL; ++ } ++ ++ if (sigtype == DAHDI_SIG_HARDHDLC) { ++ if (hdlc_start(b4, fifo)) { ++ dev_warn(&b4->pdev->dev, "Error initializing signalling controller\n"); ++ return -1; ++ } ++ } ++ ++ bspan->sigchan = (sigtype == DAHDI_SIG_HARDHDLC) ? chan : NULL; ++ bspan->sigactive = 0; ++ atomic_set(&bspan->hdlc_pending, 0); ++ } else { ++/* FIXME: shouldn't I be returning an error? */ ++ } ++ ++ return 0; ++} ++ ++static int _b4xxp_open(struct dahdi_chan *chan) ++{ ++ struct b4xxp *b4 = chan->pvt; ++ struct b4xxp_span *bspan = &b4->spans[chan->span->offset]; ++ ++ if (DBG_FOPS && DBG_SPANFILTER) { ++ dev_info(&b4->pdev->dev, "open() on chan %s (%i/%i)\n", ++ chan->name, chan->channo, chan->chanpos); ++ } ++ ++ hfc_reset_fifo_pair(b4, bspan->fifos[chan->chanpos - 1], 0, 0); ++ return 0; ++} ++ ++static int b4xxp_open(struct dahdi_chan *chan) ++{ ++ unsigned long flags; ++ int res; ++ spin_lock_irqsave(&chan->lock, flags); ++ res = _b4xxp_open(chan); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return res; ++} ++ ++static int b4xxp_close(struct dahdi_chan *chan) ++{ ++ struct b4xxp *b4 = chan->pvt; ++ struct b4xxp_span *bspan = &b4->spans[chan->span->offset]; ++ ++ if (DBG_FOPS && DBG_SPANFILTER) { ++ dev_info(&b4->pdev->dev, "close() on chan %s (%i/%i)\n", ++ chan->name, chan->channo, chan->chanpos); ++ } ++ ++ hfc_reset_fifo_pair(b4, bspan->fifos[chan->chanpos - 1], 1, 1); ++ return 0; ++} ++ ++/* DAHDI calls this when it has data it wants to send to the HDLC controller */ ++static void b4xxp_hdlc_hard_xmit(struct dahdi_chan *chan) ++{ ++ struct b4xxp *b4 = chan->pvt; ++ int span = chan->span->offset; ++ struct b4xxp_span *bspan = &b4->spans[span]; ++ ++ if ((DBG_FOPS || DBG_HDLC) && DBG_SPANFILTER) ++ dev_info(&b4->pdev->dev, "hdlc_hard_xmit on chan %s (%i/%i), span=%i\n", ++ chan->name, chan->channo, chan->chanpos, span + 1); ++ ++/* ++ * increment the hdlc_pending counter and trigger the bottom-half so it ++ * will be picked up and sent. ++ */ ++ if (bspan->sigchan == chan) { ++ atomic_inc(&bspan->hdlc_pending); ++ } ++} ++ ++/* internal functions, not specific to the hardware or DAHDI */ ++ ++static const struct dahdi_span_ops b4xxp_span_ops = { ++ .owner = THIS_MODULE, ++ .spanconfig = b4xxp_spanconfig, ++ .chanconfig = b4xxp_chanconfig, ++ .startup = b4xxp_startup, ++ .shutdown = b4xxp_shutdown, ++ .open = b4xxp_open, ++ .close = b4xxp_close, ++ .ioctl = b4xxp_ioctl, ++ .hdlc_hard_xmit = b4xxp_hdlc_hard_xmit, ++ .echocan_create = b4xxp_echocan_create, ++ .echocan_name = b4xxp_echocan_name, ++}; ++ ++/* initialize the span/chan structures. Doesn't touch hardware, although the callbacks might. */ ++static void init_spans(struct b4xxp *b4) ++{ ++ int i, j; ++ struct b4xxp_span *bspan; ++ struct dahdi_chan *chan; ++ ++/* for each span on the card */ ++ for (i=0; i < b4->numspans; i++) { ++ bspan = &b4->spans[i]; ++ bspan->parent = b4; ++ ++ bspan->span.spantype = (bspan->te_mode) ++ ? SPANTYPE_DIGITAL_BRI_TE ++ : SPANTYPE_DIGITAL_BRI_NT; ++ bspan->span.offset = i; ++ bspan->span.channels = WCB4XXP_CHANNELS_PER_SPAN; ++ bspan->span.flags = 0; ++ ++ if (!strcasecmp(companding, "ulaw")) ++ bspan->span.deflaw = DAHDI_LAW_MULAW; ++ else ++ bspan->span.deflaw = DAHDI_LAW_ALAW; ++ /* For simplicty, we'll accept all line modes since BRI ++ * ignores this setting anyway.*/ ++ bspan->span.linecompat = DAHDI_CONFIG_AMI | ++ DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | ++ DAHDI_CONFIG_ESF | DAHDI_CONFIG_HDB3 | ++ DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4 | ++ DAHDI_CONFIG_NTTE | DAHDI_CONFIG_TERM; ++ ++ sprintf(bspan->span.name, "B4/%d/%d", b4->cardno, i+1); ++ sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1); ++ ++ bspan->span.ops = &b4xxp_span_ops; ++/* HDLC stuff */ ++ bspan->sigchan = NULL; ++ bspan->sigactive = 0; ++ ++ bspan->span.chans = bspan->chans; ++ ++/* now initialize each channel in the span */ ++ for (j=0; j < WCB4XXP_CHANNELS_PER_SPAN; j++) { ++ bspan->chans[j] = &bspan->_chans[j]; ++ chan = bspan->chans[j]; ++ chan->pvt = b4; ++ ++ sprintf(chan->name, "B4/%d/%d/%d", b4->cardno, i + 1, j + 1); ++ /* The last channel in the span is the D-channel */ ++ if (j == WCB4XXP_CHANNELS_PER_SPAN - 1) { ++ chan->sigcap = DAHDI_SIG_HARDHDLC; ++ } else { ++ chan->sigcap = DAHDI_SIG_CLEAR | DAHDI_SIG_DACS; ++ } ++ chan->chanpos = j + 1; ++ chan->writechunk = (void *)(bspan->writechunk + j * DAHDI_CHUNKSIZE); ++ chan->readchunk = (void *)(bspan->readchunk + j * DAHDI_CHUNKSIZE); ++ } ++ } ++} ++ ++ ++static void b4xxp_bottom_half(unsigned long data); ++ ++/* top-half interrupt handler */ ++static irqreturn_t b4xxp_interrupt(int irq, void *dev_id) ++{ ++ struct b4xxp *b4 = dev_id; ++ unsigned char status; ++ unsigned long flags; ++ int i; ++ ++ /* Make sure it's really for us */ ++ status = __pci_in8(b4, R_STATUS); ++ if (!(status & HFC_INTS)) ++ return IRQ_NONE; ++ ++/* ++ * since the interrupt is for us, read in the FIFO and misc IRQ status registers. ++ * Don't replace the struct copies; OR in the new bits instead. ++ * That way if we get behind, we don't lose anything. ++ * We don't actually do any processing here, we simply flag the bottom-half to do the heavy lifting. ++ */ ++ local_irq_save(flags); ++ ++ if (status & V_FR_IRQSTA) { ++ b4->fifo_irqstatus[0] |= __pci_in8(b4, R_IRQ_FIFO_BL0); ++ b4->fifo_irqstatus[1] |= __pci_in8(b4, R_IRQ_FIFO_BL1); ++ b4->fifo_irqstatus[2] |= __pci_in8(b4, R_IRQ_FIFO_BL2); ++ b4->fifo_irqstatus[3] |= __pci_in8(b4, R_IRQ_FIFO_BL3); ++ b4->fifo_irqstatus[4] |= __pci_in8(b4, R_IRQ_FIFO_BL4); ++ b4->fifo_irqstatus[5] |= __pci_in8(b4, R_IRQ_FIFO_BL5); ++ b4->fifo_irqstatus[6] |= __pci_in8(b4, R_IRQ_FIFO_BL6); ++ b4->fifo_irqstatus[7] |= __pci_in8(b4, R_IRQ_FIFO_BL7); ++ } ++ ++ if (status & V_MISC_IRQSTA) { ++ b4->misc_irqstatus |= __pci_in8(b4, R_IRQ_MISC); ++ } ++ ++/* ++ * Well, that was the plan. It appears that I can't do this in the bottom half ++ * or I start to see data corruption (too long a time between IRQ and tasklet??) ++ * So, I do the B-channel stuff right here in interrupt context. yuck. ++ */ ++ if (b4->misc_irqstatus & V_TI_IRQ) { ++ hfc_poll_fifos(b4); ++ for (i=0; i < b4->numspans; i++) { ++ if (b4->spans[i].span.flags & DAHDI_FLAG_RUNNING) { ++ dahdi_ec_span(&b4->spans[i].span); ++ dahdi_receive(&b4->spans[i].span); ++ dahdi_transmit(&b4->spans[i].span); ++ } ++ } ++ } ++ ++/* kick off bottom-half handler */ ++ /* tasklet_hi_schedule(&b4->b4xxp_tlet); */ ++ b4xxp_bottom_half((unsigned long)b4); ++ ++ local_irq_restore(flags); ++ ++ return IRQ_RETVAL(1); ++} ++ ++ ++/* ++ * The bottom half of course does all the heavy lifting for the interrupt. ++ * ++ * The original plan was to have the B channel RX FIFO interrupts enabled, and ++ * to do the actual work here. Since that doesn't seem to work so well, we ++ * poll the B channel FIFOs right in the interrupt handler and take care of the B ++ * channel stuff there. The bottom half works for the timer interrupt and D ++ * channel stuff. ++ * ++ * The HFC-4S timer interrupt is used to for several things: ++ * - Update the S/T state machines, expire their timers, etc. ++ * - Provide DAHDI's timing source, if so configured ++ * - Update LEDs ++ */ ++static void b4xxp_bottom_half(unsigned long data) ++{ ++ struct b4xxp *b4 = (struct b4xxp *)data; ++ int i, j, k, fifo, fifo_low, fifo_high; ++ unsigned char b, b2; ++ ++ if (b4->shutdown) ++ return; ++ ++ if (IS_GEN2(b4)) { ++ unsigned long timeout = jiffies + (HZ/10); ++ int i; ++ struct b4xxp_span *bspan; ++ ++ for (i = 0; i < b4->numspans; i++) { ++ /* Map the ports from the virtual ports to the fifos */ ++ bspan = &b4->spans[i]; ++ b = (b4->fifo_irqstatus[2] >> (2 * bspan->phy_port)); ++ ++ if (b & V_IRQ_FIFOx_TX) { ++ while (hdlc_tx_frame(&b4->spans[i])) { ++ if (time_after(jiffies, timeout)) { ++ dev_err(&b4->pdev->dev, ++ "bottom_half timed out\n"); ++ break; ++ } ++ } ++ } ++ ++ if (b & V_IRQ_FIFOx_RX) { ++ while (hdlc_rx_frame(&b4->spans[i])) { ++ if (time_after(jiffies, timeout)) { ++ dev_err(&b4->pdev->dev, ++ "bottom_half timed out\n"); ++ break; ++ } ++ } ++ } ++ } ++ ++ b4->fifo_irqstatus[2] = 0; ++ } else { ++ ++ /* HFC-4S d-chan fifos 8-11 *** HFC-8S d-chan fifos 16-23 */ ++ if (b4->numspans == 8) { ++ fifo_low = 16; ++ fifo_high = 23; ++ } else { ++ fifo_low = 8; ++ fifo_high = 11; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ b = b2 = b4->fifo_irqstatus[i]; ++ ++ for (j = 0; j < b4->numspans; j++) { ++ fifo = i*4 + j; ++ ++ if (b & V_IRQ_FIFOx_TX) { ++ if (fifo >= fifo_low && fifo <= fifo_high) { ++ /* d-chan fifos */ ++ /* ++ * WOW I don't like this. ++ * It's bad enough that I have to send a fake frame to get an HDLC TX FIFO interrupt, ++ * but now, I have to loop until the whole frame is read, or I get RX interrupts ++ * (even though the chip says HDLC mode gives an IRQ when a *full frame* is received). ++ * Yuck. It works well, but yuck. ++ */ ++ do { ++ k = hdlc_tx_frame(&b4->spans[fifo - fifo_low]); ++ } while (k); ++ } else { ++ if (printk_ratelimit()) ++ dev_warn(&b4->pdev->dev, "Got FIFO TX int from non-d-chan FIFO %d??\n", fifo); ++ } ++ } ++ ++ if (b & V_IRQ_FIFOx_RX) { ++ if (fifo >= fifo_low && fifo <= fifo_high) { /* dchan fifos */ ++ /* ++ * I have to loop here until hdlc_rx_frame says there are no more frames waiting. ++ * for whatever reason, the HFC will not generate another interrupt if there are ++ * still HDLC frames waiting to be received. ++ * i.e. I get an int when F1 changes, not when F1 != F2. ++ */ ++ do { ++ k = hdlc_rx_frame(&b4->spans[fifo - fifo_low]); ++ } while (k); ++ } else { ++ if (printk_ratelimit()) ++ dev_warn(&b4->pdev->dev, "Got FIFO RX int from non-d-chan FIFO %d??\n", fifo); ++ } ++ } ++ ++ b >>= 2; ++ } ++ ++ /* zero the bits we just processed */ ++ b4->fifo_irqstatus[i] &= ~b2; ++ } ++ } ++ ++/* ++ * timer interrupt ++ * every tick (1ms), check the FIFOs and run through the S/T port timers. ++ * every 100ms or so, look for S/T state machine changes. ++ */ ++ if (b4->misc_irqstatus & V_TI_IRQ) { ++ ++/* ++ * We should check the FIFOs here, but I'm seeing this tasklet getting scheduled FAR too late to be useful. ++ * For now, we're handling that in the IRQ handler itself. (ICK!!) ++ */ ++ b4->ticks++; ++ ++ hfc_update_st_timers(b4); ++ ++ b4xxp_update_leds(b4); ++ ++ /* Poll interface state at 100ms interval */ ++ if (!(b4->ticks % 100)) { ++ b = b4xxp_getreg8(b4, R_SCI); ++ if (b) { ++ for (i=0; i < b4->numspans; i++) { ++ if (IS_B230P(b4)) { ++ if (b & (1 << (i+1))) ++ hfc_handle_state(&b4->spans[1-i]); ++ } else { ++ if (b & (1 << i)) { ++ /* physical spans are reversed for b430 */ ++ if (IS_B430P(b4)) ++ hfc_handle_state(&b4->spans[b4->numspans-1-i]); ++ else ++ hfc_handle_state(&b4->spans[i]); ++ } ++ } ++ } ++ } ++ } ++ ++/* We're supposed to kick DAHDI here, too, but again, seeing too much latency between the interrupt and the bottom-half. */ ++ ++/* clear the timer interrupt flag. */ ++ b4->misc_irqstatus &= ~V_TI_IRQ; ++ } ++ ++/* ++ * Check for outgoing HDLC frame requests ++ * The HFC does not generate TX interrupts when there is room to send, so ++ * I use an atomic counter that is incremented every time DAHDI wants to send ++ * a frame, and decremented every time I send a frame. It'd be better if I could ++ * just use the interrupt handler, but the HFC seems to trigger a FIFO TX IRQ ++ * only when it has finished sending a frame, not when one can be sent. ++ */ ++ for (i=0; i < b4->numspans; i++) { ++ struct b4xxp_span *bspan = &b4->spans[i]; ++ ++ if (atomic_read(&bspan->hdlc_pending)) { ++ do { ++ k = hdlc_tx_frame(bspan); ++ } while (k); ++ } ++ } ++} ++ ++ ++/********************************************************************************* proc stuff *****/ ++ ++#ifdef CREATE_WCB4XXP_PROCFS_ENTRY ++static int b4xxp_proc_read_one(char *buf, struct b4xxp *b4) ++{ ++ struct dahdi_chan *chan; ++ int len, i, j; ++ char str[80], sBuf[4096]; ++ ++ *sBuf=0; ++ sprintf(sBuf, "Card %d, PCI identifier %s, IRQ %d\n", ++ b4->cardno + 1, b4->pdev->dev.bus_id, b4->irq); ++ ++ strcat(sBuf,"Tx:\n"); ++ for (j=0; j<(b4->numspans * 2) ; j++) { /* B Channels */ ++ for (i=0; i<(b4->numspans * 3) ; i++) { /* All Channels */ ++ chan = b4->spans[i/3].chans[i%3]; ++ sprintf(str, "%02x ", chan->writechunk[j]); ++ strcat(sBuf, str); ++ } ++ ++ strcat(sBuf, "\n"); ++ } ++ ++ strcat(sBuf, "\nRx:\n"); ++ for (j=0; j < (b4->numspans * 2); j++) { /* B Channels */ ++ for (i=0; i < (b4->numspans * 3); i++) { /* All Channels */ ++ chan = b4->spans[i / 3].chans[i % 3]; ++ sprintf(str, "%02x%c", chan->readchunk[j], (i == 11) ? '\n' : ' '); ++ strcat(sBuf, str); ++ } ++ } ++ ++ strcat(sBuf, "\nPort states:\n"); ++ for (i=0; i < b4->numspans; i++) { ++ int state; ++ char *x; ++ struct b4xxp_span *s = &b4->spans[i]; ++ ++ state = b4xxp_getreg_ra(b4, R_ST_SEL, s->port, A_ST_RD_STA); ++ x = hfc_decode_st_state(b4, s, state, 0); ++ sprintf(str, "%s\n", x); ++ strcat(sBuf, str); ++ kfree(x); ++ } ++ ++ len = sprintf(buf, "%s\n%s\nTicks: %ld\n", sBuf, str, b4->ticks); ++ return len; ++} ++ ++static int b4xxp_proc_read(char *buf, char **start, off_t offset, int count, int *eof, void *data) ++{ ++ struct b4xxp **b4_cards = data; ++ char sBuf[256]; ++ int i, len; ++ ++ len = sprintf(buf, "WCB4XXP Card Information\n"); ++ for (i=0; b4_cards[i] != NULL; i++) { ++ if (i) ++ len += sprintf(buf + len, "\n-----\n"); ++ len += b4xxp_proc_read_one(buf + len, b4_cards[i]); ++ } ++ ++ *sBuf = 0; ++ strcat(sBuf, "\n-----\n\nAudio: "); ++#ifdef LOOPBACK_SUPPORTED ++ if (loopback >= 3) ++ strcat(sBuf, "DAHDI and S/T"); ++ else if (loopback == 2) ++ strcat(sBuf, "DAHDI"); ++ else if (loopback == 1) ++ strcat(sBuf, "S/T"); ++ else ++ strcat(sBuf, "not"); ++ strcat(sBuf, " looped back"); ++#else ++ strcat(sBuf, "not looped back"); ++#endif ++ ++ if (milliwatt) ++ strcat(sBuf, ", outgoing S/T replaced with mu-law milliwatt tone"); ++ ++ len += sprintf(buf + len, "%s\n", sBuf); ++ ++ if (alarmdebounce) ++ sprintf(sBuf, "Alarms: debounced (%dms)", alarmdebounce); ++ else ++ strcpy(sBuf, "Alarms: not debounced"); ++ ++ len += sprintf(buf + len, "%s\nT1 timer period %dms\nT3 timer period %dms\n", sBuf, timer_1_ms, timer_3_ms); ++ ++ *eof = 1; ++ return len; ++} ++#endif /* CREATE_WCB4XXP_PROCFS_ENTRY */ ++ ++static int b4xxp_startdefaultspan(struct b4xxp *b4) ++{ ++ struct dahdi_lineconfig lc = {0,}; ++ return b4xxp_spanconfig(NULL, &b4->spans[0].span, &lc); ++} ++ ++static void set_ufm(struct b4xxp *b4, int signal) ++{ ++ int reg; ++ ++ hfc_gpio_set(b4, 0x70); ++ reg = hfc_sram_read(b4); ++ hfc_gpio_set(b4, 0x00); ++ ++ hfc_gpio_set(b4, 0x70); ++ hfc_sram_write(b4, reg | signal); ++ hfc_gpio_set(b4, 0x00); ++} ++ ++static void clr_ufm(struct b4xxp *b4, int signal) ++{ ++ int reg; ++ ++ hfc_gpio_set(b4, 0x70); ++ reg = hfc_sram_read(b4); ++ hfc_gpio_set(b4, 0x00); ++ ++ hfc_gpio_set(b4, 0x70); ++ hfc_sram_write(b4, reg & ~signal); ++ hfc_gpio_set(b4, 0x00); ++} ++ ++static unsigned char read_ufm_status(struct b4xxp *b4) ++{ ++ unsigned char ret; ++ ++ hfc_gpio_set(b4, 0x00); ++ ret = hfc_sram_read(b4); ++ hfc_gpio_set(b4, 0x00); ++ ++ return ret; ++} ++ ++/* Try to read the serial number from 2nd gen devices */ ++static int read_serial(struct b4xxp *b4, char *serial) ++{ ++ unsigned long flags; ++ int i, j; ++ int ret = 0; ++ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ ++ set_ufm(b4, UFM_ARSHIFT); ++ set_ufm(b4, UFM_ARCLK); ++ clr_ufm(b4, UFM_ARDIN); ++ set_ufm(b4, UFM_DRSHIFT); ++ set_ufm(b4, UFM_DRCLK); ++ clr_ufm(b4, UFM_ERASE); ++ clr_ufm(b4, UFM_PROGRAM); ++ ++ for (i = 0; i < 255; i++) { ++ char data = 0; ++ ++ /* Bang out address */ ++ for (j = 0; j < 9; j++) { ++ int mask = 0x100 >> j; ++ ++ if ((i & mask) == 0) ++ clr_ufm(b4, UFM_ARDIN); ++ else ++ set_ufm(b4, UFM_ARDIN); ++ ++ clr_ufm(b4, UFM_ARCLK); ++ set_ufm(b4, UFM_ARCLK); ++ } ++ ++ /* Latch the address */ ++ clr_ufm(b4, UFM_DRCLK); ++ clr_ufm(b4, UFM_DRSHIFT); ++ set_ufm(b4, UFM_DRCLK); ++ set_ufm(b4, UFM_DRSHIFT); ++ ++ /* Bang in data */ ++ for (j = 0; j < 8; j++) { ++ int drdout = (read_ufm_status(b4) & 0x80) >> 7; ++ ++ clr_ufm(b4, UFM_DRCLK); ++ set_ufm(b4, UFM_DRCLK); ++ ++ if (drdout == 1) ++ data = data + (0x80 >> j); ++ } ++ ++ /* Bang out the data padding */ ++ for (j = 0; j < 8; j++) { ++ clr_ufm(b4, UFM_DRCLK); ++ set_ufm(b4, UFM_DRCLK); ++ } ++ ++ if ((data >= 0x20) && (data < 0x7f)) { ++ serial[i] = data; ++ } else if (!i) { ++ ret = 1; ++ break; ++ } else { ++ break; ++ } ++ } ++ ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++ ++ return ret; ++} ++ ++static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ int x, ret; ++ struct b4xxp *b4; ++ struct devtype *dt; ++ ++ dt = (struct devtype *)(ent->driver_data); ++ dev_info(&pdev->dev, "probe called for b4xx...\n"); ++ ++ if ((ret = pci_enable_device(pdev))) ++ goto err_out_disable_pdev; ++ ++ if ((ret = pci_request_regions(pdev, dt->desc))) { ++ dev_err(&pdev->dev, "Unable to request regions!\n"); ++ goto err_out_disable_pdev; ++ } ++ ++ if (!pdev->irq) { /* we better have an IRQ */ ++ dev_err(&pdev->dev, "Device has no associated IRQ?\n"); ++ ret = -EIO; ++ goto err_out_release_regions; ++ } ++ ++ if (!(b4 = kzalloc(sizeof(struct b4xxp), GFP_KERNEL))) { ++ dev_err(&pdev->dev, "Couldn't allocate memory for b4xxp structure!\n"); ++ ret = -ENOMEM; ++ goto err_out_release_regions; ++ } ++ ++/* card found, enabled and main struct allocated. Fill it out. */ ++ b4->variety = dt->desc; ++ b4->card_type = dt->card_type; ++ b4->pdev = pdev; ++ pci_set_drvdata(pdev, b4); ++ ++ b4->ioaddr = pci_iomap(pdev, 0, 0); ++ b4->addr = pci_iomap(pdev, 1, 0); ++ b4->irq = pdev->irq; ++ ++ spin_lock_init(&b4->reglock); ++ spin_lock_init(&b4->seqlock); ++ spin_lock_init(&b4->fifolock); ++ ++ x = b4xxp_getreg8(b4, R_CHIP_ID); ++ if ((x != 0xc0) && (x != 0x80)) { /* wrong chip? */ ++ dev_err(&pdev->dev, "Unknown/unsupported controller detected (R_CHIP_ID = 0x%02x)\n", x); ++ goto err_out_free_mem; ++ } ++ ++/* future proofing */ ++ b4->chiprev = b4xxp_getreg8(b4, R_CHIP_RV); ++ ++/* check for various board-specific flags and modify init as necessary */ ++/* ++ if (dt->flags & FLAG_XXX) ++ use_flag_somehow(); ++*/ ++ ++ b4->numspans = dt->ports; ++ b4->syncspan = -1; /* sync span is unknown */ ++ if (b4->numspans > MAX_SPANS_PER_CARD) { ++ dev_err(&b4->pdev->dev, ++ "Driver does not know how to handle a %d span card!\n", ++ b4->numspans); ++ goto err_out_free_mem; ++ } ++ ++ dev_info(&b4->pdev->dev, "Identified %s (controller rev %d) at %p, IRQ %i\n", ++ b4->variety, b4->chiprev, b4->ioaddr, b4->irq); ++ ++/* look for the next free card structure */ ++ for (x=0; x < MAX_B4_CARDS; x++) { ++ if (!cards[x]) ++ break; ++ } ++ ++ if (x >= MAX_B4_CARDS) { ++ dev_err(&pdev->dev, "Attempt to register more than %i cards, aborting!\n", MAX_B4_CARDS); ++ goto err_out_free_mem; ++ } ++ ++/* update the cards array, make sure the b4xxp struct knows where in the array it is */ ++ b4->cardno = x; ++ cards[x] = b4; ++ ++ b4xxp_init_stage1(b4); ++ ++ if (IS_GEN2(b4)) { ++ int version; ++ unsigned long flags; ++ char serial[255]; ++ ++ /* Read and print firmware version */ ++ spin_lock_irqsave(&b4->seqlock, flags); ++ hfc_gpio_set(b4, 0x60); ++ version = hfc_sram_read(b4); ++ spin_unlock_irqrestore(&b4->seqlock, flags); ++ ++ dev_info(&b4->pdev->dev, "CPLD ver: %x\n", version); ++ ++ /* Read and print serial number */ ++ if (read_serial(b4, &serial[0])) ++ dev_info(&b4->pdev->dev, ++ "Unable to read serial number\n"); ++ else ++ dev_info(&b4->pdev->dev, "serial: %s\n", serial); ++ } ++ ++ create_sysfs_files(b4); ++ ++ if (request_irq(pdev->irq, b4xxp_interrupt, IRQF_SHARED, "b4xxp", b4)) { ++ dev_err(&b4->pdev->dev, "Unable to request IRQ %d\n", ++ pdev->irq); ++ ret = -EIO; ++ goto err_out_del_from_card_array; ++ } ++ ++/* initialize the tasklet structure */ ++/* TODO: perhaps only one tasklet for any number of cards in the system... don't need one per card I don't think. */ ++ tasklet_init(&b4->b4xxp_tlet, b4xxp_bottom_half, (unsigned long)b4); ++ ++/* interrupt allocated and tasklet initialized, it's now safe to finish initializing the hardware */ ++ b4xxp_init_stage2(b4); ++ hfc_init_all_st(b4); ++ ++/* initialize the DAHDI structures, and let DAHDI know it has some new hardware to play with */ ++ b4->ddev = dahdi_create_device(); ++ init_spans(b4); ++ ++ for (x=0; x < b4->numspans; x++) { ++ struct dahdi_span *const s = &b4->spans[x].span; ++ list_add_tail(&s->device_node, &b4->ddev->spans); ++ } ++ ++ b4->ddev->manufacturer = "Digium"; ++ b4->ddev->devicetype = b4->variety; ++ b4->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d", ++ b4->pdev->bus->number, ++ PCI_SLOT(b4->pdev->devfn) + 1); ++ if (!b4->ddev->location) { ++ ret = -ENOMEM; ++ goto err_out_del_from_card_array; ++ } ++ ++ if (dahdi_register_device(b4->ddev, &b4->pdev->dev)) { ++ dev_err(&b4->pdev->dev, "Unable to register device.\n"); ++ goto err_out_unreg_spans; ++ } ++ ++ dev_info(&b4->pdev->dev, "Did not do the highestorder stuff\n"); ++ ++ ret = b4xxp_startdefaultspan(b4); ++ if (ret) ++ goto err_out_unreg_spans; ++ ++ ret = 0; ++ return ret; ++ ++/* 'x' will have the failing span #. (0-3). We need to unregister everything before it. */ ++err_out_unreg_spans: ++ dahdi_unregister_device(b4->ddev); ++ ++ b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */ ++ free_irq(pdev->irq, b4); ++ ++err_out_del_from_card_array: ++ for (x=0; x < MAX_B4_CARDS; x++) { ++ if (cards[x] == b4) { ++ b4->cardno = -1; ++ cards[x] = NULL; ++ break; ++ } ++ } ++ ++ if (x >= MAX_B4_CARDS) ++ dev_err(&pdev->dev, "b4 struct @ %p should be in cards array but isn't?!\n", b4); ++ ++err_out_free_mem: ++ pci_set_drvdata(pdev, NULL); ++ pci_iounmap(pdev, b4->ioaddr); ++ pci_iounmap(pdev, b4->addr); ++ kfree(b4->ddev->location); ++ dahdi_free_device(b4->ddev); ++ kfree(b4); ++ ++err_out_release_regions: ++ pci_release_regions(pdev); ++ ++err_out_disable_pdev: ++ pci_disable_device(pdev); ++ ++ return ret; ++} ++ ++static void __devexit b4xxp_remove(struct pci_dev *pdev) ++{ ++ struct b4xxp *b4 = pci_get_drvdata(pdev); ++ ++ if (b4) { ++ b4->shutdown = 1; ++ ++ dahdi_unregister_device(b4->ddev); ++ ++ b4xxp_init_stage1(b4); ++ remove_sysfs_files(b4); ++ free_irq(pdev->irq, b4); ++ pci_set_drvdata(pdev, NULL); ++ pci_iounmap(pdev, b4->ioaddr); ++ pci_iounmap(pdev, b4->addr); ++ pci_release_regions(pdev); ++ pci_disable_device(pdev); ++ ++ b4->ioaddr = b4->addr = NULL; ++ ++ tasklet_kill(&b4->b4xxp_tlet); ++ ++ kfree(b4->ddev->location); ++ dahdi_free_device(b4->ddev); ++ kfree(b4); ++ } ++ ++ dev_info(&pdev->dev, "Driver unloaded.\n"); ++ return; ++} ++ ++static DEFINE_PCI_DEVICE_TABLE(b4xx_ids) = ++{ ++ {0xd161, 0xb410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb41xp}, ++ {0xd161, 0x8014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb43xp}, ++ {0xd161, 0x8015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb43xp}, ++ {0xd161, 0x8016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb23xp}, ++ {0xd161, 0x8017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb23xp}, ++ {0, } ++ ++}; ++ ++static int b4xx_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ return -ENOSYS; ++} ++ ++static struct pci_driver b4xx_driver = { ++ .name = "wcb4xxp", ++ .probe = b4xx_probe, ++ .remove = __devexit_p(b4xxp_remove), ++ .id_table = b4xx_ids, ++ .suspend = b4xx_suspend, ++}; ++ ++static int __init b4xx_init(void) ++{ ++ ++#ifdef CREATE_WCB4XXP_PROCFS_ENTRY ++ if (!(myproc = create_proc_read_entry(PROCFS_NAME, 0444, NULL, ++ b4xxp_proc_read, cards))) { ++ printk(KERN_ERR "%s: ERROR: Could not initialize /proc/%s\n",THIS_MODULE->name, PROCFS_NAME); ++ } ++#endif ++ if (pci_register_driver(&b4xx_driver)) ++ return -ENODEV; ++ ++ return 0; ++} ++ ++static void __exit b4xx_exit(void) ++{ ++#ifdef CREATE_WCB4XXP_PROCFS_ENTRY ++ remove_proc_entry(PROCFS_NAME, NULL); ++#endif ++ pci_unregister_driver(&b4xx_driver); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++module_param(spanfilter, int, S_IRUGO | S_IWUSR); ++#ifdef LOOPBACK_SUPPORTED ++module_param(loopback, int, S_IRUGO | S_IWUSR); ++#endif ++module_param(milliwatt, int, S_IRUGO | S_IWUSR); ++module_param(pedanticpci, int, S_IRUGO); ++module_param(teignorered, int, S_IRUGO | S_IWUSR); ++module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(vpmsupport, int, S_IRUGO); ++module_param(timer_1_ms, int, S_IRUGO | S_IWUSR); ++module_param(timer_3_ms, int, S_IRUGO | S_IWUSR); ++module_param(companding, charp, S_IRUGO); ++module_param(persistentlayer1, int, S_IRUGO | S_IWUSR); ++ ++MODULE_PARM_DESC(debug, "bitmap: 1=general 2=dtmf 4=regops 8=fops 16=ec 32=st state 64=hdlc 128=alarm"); ++MODULE_PARM_DESC(spanfilter, "debug filter for spans. bitmap: 1=port 1, 2=port 2, 4=port 3, 8=port 4"); ++#ifdef LOOPBACK_SUPPORTED ++MODULE_PARM_DESC(loopback, "TODO: bitmap: 1=loop back S/T port 2=loop back DAHDI"); ++#endif ++MODULE_PARM_DESC(milliwatt, "1=replace outgoing S/T data with mu-law milliwatt"); ++MODULE_PARM_DESC(pedanticpci, "1=disable PCI back-to-back transfers and flush all PCI writes immediately"); ++MODULE_PARM_DESC(teignorered, "1=ignore (do not inform DAHDI) if a red alarm exists in TE mode"); ++MODULE_PARM_DESC(alarmdebounce, "msec to wait before set/clear alarm condition"); ++MODULE_PARM_DESC(vpmsupport, "1=enable hardware EC, 0=disable hardware EC"); ++MODULE_PARM_DESC(timer_1_ms, "NT: msec to wait for link activation, TE: unused."); ++MODULE_PARM_DESC(timer_3_ms, "TE: msec to wait for link activation, NT: unused."); ++MODULE_PARM_DESC(companding, "Change the companding to \"alaw\" or \"ulaw\""\ ++ "(alaw by default)"); ++ ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_DESCRIPTION("B410P & Similars multi-port BRI module driver."); ++MODULE_LICENSE("GPL"); ++ ++MODULE_DEVICE_TABLE(pci, b4xx_ids); ++ ++module_init(b4xx_init); ++module_exit(b4xx_exit); +diff -Nru linux-source-4.19/drivers/dahdi/wcb4xxp/wcb4xxp.h linux-source-4.19-dahdi/drivers/dahdi/wcb4xxp/wcb4xxp.h +--- linux-source-4.19/drivers/dahdi/wcb4xxp/wcb4xxp.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcb4xxp/wcb4xxp.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,541 @@ ++/* ++ * Wilcard B410P Quad-BRI Interface Driver for Zapata Telephony interface ++ * Written by Andrew Kohlsmith ++ */ ++ ++#ifndef _B4XX_H_ ++#define _B4XX_H_ ++ ++#include ++ ++#define HFC_NR_FIFOS 32 ++#define HFC_ZMIN 0x80 /* from datasheet */ ++#define HFC_ZMAX 0x1ff ++#define HFC_FMIN 0x00 ++#define HFC_FMAX 0x0f ++ ++/* ++ * yuck. Any reg which is not mandated read/write or read-only is write-only. ++ * Also, there are dozens of registers with the same address. ++ * Additionally, there are array registers (A_) which have an index register ++ * These A_ registers require an index register to be written to indicate WHICH in the array you want. ++ */ ++ ++#define R_CIRM 0x00 /* WO */ ++#define R_CTRL 0x01 /* WO */ ++#define R_BRG_PCM_CFG 0x02 /* WO */ ++#define A_Z12 0x04 /* RO */ ++#define A_Z1L 0x04 /* RO */ ++#define A_Z1 0x04 /* RO */ ++#define A_Z1H 0x05 /* RO */ ++#define A_Z2L 0x06 /* RO */ ++#define A_Z2 0x06 /* RO */ ++#define A_Z2H 0x07 /* RO */ ++#define R_RAM_ADDR0 0x08 /* WO */ ++#define R_RAM_ADDR1 0x09 /* WO */ ++#define R_RAM_ADDR2 0x0a /* WO */ ++#define R_FIRST_FIFO 0x0b /* WO */ ++#define R_RAM_MISC 0x0c /* WO */ ++#define A_F1 0x0c /* RO */ ++#define A_F12 0x0c /* RO */ ++#define R_FIFO_MD 0x0d /* WO */ ++#define A_F2 0x0d /* RO */ ++#define A_INC_RES_FIFO 0x0e /* WO */ ++#define R_FSM_IDX 0x0f /* WO */ ++#define R_FIFO 0x0f /* WO */ ++ ++#define R_SLOT 0x10 /* WO */ ++#define R_IRQ_OVIEW 0x10 /* RO */ ++#define R_IRQMSK_MISC 0x11 /* WO */ ++#define R_IRQ_MISC 0x11 /* RO */ ++#define R_SCI_MSK 0x12 /* WO */ ++#define R_SCI 0x12 /* RO */ ++#define R_IRQ_CTRL 0x13 /* WO */ ++#define R_PCM_MD0 0x14 /* WO */ ++#define R_CONF_OFLOW 0x14 /* RO */ ++#define R_PCM_MD1 0x15 /* WO */ ++#define R_PCM_MD2 0x15 /* WO */ ++#define R_SH0H 0x15 /* WO */ ++#define R_SH1H 0x15 /* WO */ ++#define R_SH0L 0x15 /* WO */ ++#define R_SH1L 0x15 /* WO */ ++#define R_SL_SEL0 0x15 /* WO */ ++#define R_SL_SEL1 0x15 /* WO */ ++#define R_SL_SEL2 0x15 /* WO */ ++#define R_SL_SEL3 0x15 /* WO */ ++#define R_SL_SEL4 0x15 /* WO */ ++#define R_SL_SEL5 0x15 /* WO */ ++#define R_SL_SEL6 0x15 /* WO */ ++#define R_SL_SEL7 0x15 /* WO */ ++#define R_RAM_USE 0x15 /* RO */ ++#define R_ST_SEL 0x16 /* WO */ ++#define R_CHIP_ID 0x16 /* RO */ ++#define R_ST_SYNC 0x17 /* WO */ ++#define R_BERT_STA 0x17 /* RO */ ++#define R_CONF_EN 0x18 /* WO */ ++#define R_F0_CNTL 0x18 /* RO */ ++#define R_F0_CNTH 0x19 /* RO */ ++#define R_TI_WD 0x1a /* WO */ ++#define R_BERT_ECL 0x1a /* RO */ ++#define R_BERT_WD_MD 0x1b /* WO */ ++#define R_BERT_ECH 0x1b /* RO */ ++#define R_DTMF 0x1c /* WO */ ++#define R_STATUS 0x1c /* RO */ ++#define R_DTMF_N 0x1d /* WO */ ++#define R_CHIP_RV 0x1f /* RO */ ++ ++#define A_ST_WR_STA 0x30 /* WO */ ++#define A_ST_RD_STA 0x30 /* RO */ ++#define A_ST_CTRL0 0x31 /* WO */ ++#define A_ST_CTRL1 0x32 /* WO */ ++#define A_ST_CTRL2 0x33 /* WO */ ++#define A_ST_SQ_WR 0x34 /* WO */ ++#define A_ST_SQ_RD 0x34 /* RO */ ++#define A_ST_CLK_DLY 0x37 /* WO */ ++ ++#define R_PWM0 0x38 /* WO */ ++#define R_PWM1 0x39 /* WO */ ++ ++#define A_ST_B1_TX 0x3c /* WO */ ++#define A_ST_B1_RX 0x3c /* RO */ ++#define A_ST_B2_TX 0x3d /* WO */ ++#define A_ST_B2_RX 0x3d /* RO */ ++#define A_ST_D_TX 0x3e /* WO */ ++#define A_ST_D_RX 0x3e /* RO */ ++#define A_ST_E_RX 0x3f /* RO */ ++ ++#define R_GPIO_OUT0 0x40 /* WO */ ++#define R_GPIO_IN0 0x40 /* RO */ ++#define R_GPIO_OUT1 0x41 /* WO */ ++#define R_GPIO_IN1 0x41 /* RO */ ++#define R_GPIO_EN0 0x42 /* WO */ ++#define R_GPIO_EN1 0x43 /* WO */ ++#define R_GPIO_SEL 0x44 /* WO */ ++#define R_GPI_IN0 0x44 /* RO */ ++#define R_GPI_IN1 0x45 /* RO */ ++#define R_PWM_MD 0x46 /* WO */ ++#define R_GPI_IN2 0x46 /* RO */ ++#define R_GPI_IN3 0x47 /* RO */ ++ ++#define A_FIFO_DATA2 0x80 /* RW */ ++#define A_FIFO_DATA0 0x80 /* RW */ ++#define A_FIFO_DATA1 0x80 /* RW */ ++ ++#define A_FIFO_DATA2_NOINC 0x84 /* WO */ ++#define A_FIFO_DATA0_NOINC 0x84 /* WO */ ++#define A_FIFO_DATA1_NOINC 0x84 /* WO */ ++ ++#define R_INT_DATA 0x88 /* RO */ ++ ++#define R_RAM_DATA 0xc0 /* RW */ ++ ++#define R_IRQ_FIFO_BL0 0xc8 /* RO */ ++#define R_IRQ_FIFO_BL1 0xc9 /* RO */ ++#define R_IRQ_FIFO_BL2 0xca /* RO */ ++#define R_IRQ_FIFO_BL3 0xcb /* RO */ ++#define R_IRQ_FIFO_BL4 0xcc /* RO */ ++#define R_IRQ_FIFO_BL5 0xcd /* RO */ ++#define R_IRQ_FIFO_BL6 0xce /* RO */ ++#define R_IRQ_FIFO_BL7 0xcf /* RO */ ++ ++#define A_SL_CFG 0xd0 /* WO */ ++#define A_CONF 0xd1 /* WO */ ++#define A_CH_MSK 0xf4 /* WO */ ++#define A_CON_HDLC 0xfa /* WO */ ++#define A_SUBCH_CFG 0xfb /* WO */ ++#define A_CHANNEL 0xfc /* WO */ ++#define A_FIFO_SEQ 0xfd /* WO */ ++#define A_IRQ_MSK 0xff /* WO */ ++ ++/* R_CIRM bits */ ++#define V_SRES (1 << 3) /* soft reset (group 0) */ ++#define V_HFC_RES (1 << 4) /* HFC reset (group 1) */ ++#define V_PCM_RES (1 << 5) /* PCM reset (group 2) */ ++#define V_ST_RES (1 << 6) /* S/T reset (group 3) */ ++#define V_RLD_EPR (1 << 7) /* EEPROM reload */ ++#define HFC_FULL_RESET (V_SRES | V_HFC_RES | V_PCM_RES | V_ST_RES | V_RLD_EPR) ++ ++/* A_IRQ_MSK bits */ ++#define V_IRQ (1 << 0) /* FIFO interrupt enable */ ++#define V_BERT_EN (1 << 1) /* enable BERT */ ++#define V_MIX_IRQ (1 << 2) /* mixed interrupt enable (frame + transparent mode) */ ++ ++/* R_STATUS bits */ ++#define V_BUSY (1 << 0) /* 1=HFC busy, limited register access */ ++#define V_PROC (1 << 1) /* 1=HFC in processing phase */ ++#define V_LOST_STA (1 << 3) /* 1=frames have been lost */ ++#define V_SYNC_IN (1 << 4) /* level on SYNC_I pin */ ++#define V_EXT_IRQSTA (1 << 5) /* 1=external interrupt */ ++#define V_MISC_IRQSTA (1 << 6) /* 1=misc interrupt has occurred */ ++#define V_FR_IRQSTA (1 << 7) /* 1=fifo interrupt has occured */ ++#define HFC_INTS (V_EXT_IRQSTA | V_MISC_IRQSTA | V_FR_IRQSTA) ++ ++/* R_SCI/R_SCI_MSK bits */ ++#define V_SCI_ST0 (1 << 0) /* state change for port 1 */ ++#define V_SCI_ST1 (1 << 1) /* state change for port 2 */ ++#define V_SCI_ST2 (1 << 2) /* state change for port 3 */ ++#define V_SCI_ST3 (1 << 3) /* state change for port 4 */ ++ ++/* R_IRQ_FIFO_BLx bits */ ++#define V_IRQ_FIFOx_TX (1 << 0) /* FIFO TX interrupt occurred */ ++#define V_IRQ_FIFOx_RX (1 << 1) /* FIFO RX interrupt occurred */ ++#define IRQ_FIFOx_TXRX (V_IRQ_FIFOx_TX | V_IRQ_FIFOx_RX) ++ ++/* R_IRQ_MISC / R_IRQMSK_MISC bits */ ++#define V_TI_IRQ (1 << 1) /* timer elapsed */ ++#define V_IRQ_PROC (1 << 2) /* processing/non-processing transition */ ++#define V_DTMF_IRQ (1 << 3) /* DTMF detection completed */ ++#define V_EXT_IRQ (1 << 5) /* external interrupt occured */ ++ ++/* R_IRQ_CTRL bits */ ++#define V_FIFO_IRQ (1 << 0) /* enable any unmasked FIFO IRQs */ ++#define V_GLOB_IRQ_EN (1 << 3) /* enable any unmasked IRQs */ ++#define V_IRQ_POL (1 << 4) /* 1=IRQ active high */ ++ ++/* R_BERT_WD_MD bits */ ++#define V_BERT_ERR (1 << 3) /* 1=generate an error bit in BERT stream */ ++#define V_AUTO_WD_RES (1 << 5) /* 1=automatically kick the watchdog */ ++#define V_WD_RES (1 << 7) /* 1=kick the watchdog (bit auto clears) */ ++ ++/* R_TI_WS bits */ ++#define V_EV_TS_SHIFT (0) ++#define V_EV_TS_MASK (0x0f) ++#define V_WD_TS_SHIFT (4) ++#define V_WD_TS_MASK (0xf0) ++ ++/* R_BRG_PCM_CFG bits */ ++#define V_PCM_CLK (1 << 5) /* 1=PCM clk = OSC, 0 = PCM clk is 2x OSC */ ++ ++/* R_PCM_MD0 bits */ ++#define V_PCM_MD (1 << 0) /* 1=PCM master */ ++#define V_C4_POL (1 << 1) /* 1=F0IO sampled on rising edge of C4IO */ ++#define V_F0_NEG (1 << 2) /* 1=negative polarity of F0IO */ ++#define V_F0_LEN (1 << 3) /* 1=F0IO active for 2 C4IO clocks */ ++#define V_PCM_IDX_SEL0 (0x0 << 4) /* reg15 = R_SL_SEL0 */ ++#define V_PCM_IDX_SEL1 (0x1 << 4) /* reg15 = R_SL_SEL1 */ ++#define V_PCM_IDX_SEL2 (0x2 << 4) /* reg15 = R_SL_SEL2 */ ++#define V_PCM_IDX_SEL3 (0x3 << 4) /* reg15 = R_SL_SEL3 */ ++#define V_PCM_IDX_SEL4 (0x4 << 4) /* reg15 = R_SL_SEL4 */ ++#define V_PCM_IDX_SEL5 (0x5 << 4) /* reg15 = R_SL_SEL5 */ ++#define V_PCM_IDX_SEL6 (0x6 << 4) /* reg15 = R_SL_SEL6 */ ++#define V_PCM_IDX_SEL7 (0x7 << 4) /* reg15 = R_SL_SEL7 */ ++#define V_PCM_IDX_MD1 (0x9 << 4) /* reg15 = R_PCM_MD1 */ ++#define V_PCM_IDX_MD2 (0xa << 4) /* reg15 = R_PCM_MD2 */ ++#define V_PCM_IDX_SH0L (0xc << 4) /* reg15 = R_SH0L */ ++#define V_PCM_IDX_SH0H (0xd << 4) /* reg15 = R_SH0H */ ++#define V_PCM_IDX_SH1L (0xe << 4) /* reg15 = R_SH1L */ ++#define V_PCM_IDX_SH1H (0xf << 4) /* reg15 = R_SH1H */ ++#define V_PCM_IDX_MASK (0xf0) ++ ++/* R_PCM_MD1 bits */ ++#define V_CODEC_MD (1 << 0) /* no damn idea */ ++#define V_PLL_ADJ_00 (0x0 << 2) /* adj 4 times by 0.5 system clk cycles */ ++#define V_PLL_ADJ_01 (0x1 << 2) /* adj 3 times by 0.5 system clk cycles */ ++#define V_PLL_ADJ_10 (0x2 << 2) /* adj 2 times by 0.5 system clk cycles */ ++#define V_PLL_ADJ_11 (0x3 << 2) /* adj 1 time by 0.5 system clk cycles */ ++#define V_PCM_DR_2048 (0x0 << 4) /* 2.048Mbps, 32 timeslots */ ++#define V_PCM_DR_4096 (0x1 << 4) /* 4.096Mbps, 64 timeslots */ ++#define V_PCM_DR_8192 (0x2 << 4) /* 8.192Mbps, 128 timeslots */ ++#define V_PCM_LOOP (1 << 6) /* 1=internal loopback */ ++#define V_PLL_ADJ_MASK (0x3 << 2) ++#define V_PCM_DR_MASK (0x3 << 4) ++ ++/* A_SL_CFG bits */ ++#define V_CH_SDIR (1 << 0) /* 1=HFC channel receives data from PCM TS */ ++#define V_ROUT_TX_DIS (0x0 << 6) /* disabled, output disabled */ ++#define V_ROUT_TX_LOOP (0x1 << 6) /* internally looped, output disabled */ ++#define V_ROUT_TX_STIO1 (0x2 << 6) /* output data to STIO1 */ ++#define V_ROUT_TX_STIO2 (0x3 << 6) /* output data to STIO2 */ ++#define V_ROUT_RX_DIS (0x0 << 6) /* disabled, input data ignored */ ++#define V_ROUT_RX_LOOP (0x1 << 6) /* internally looped, input data ignored */ ++#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data from STIO2 */ ++#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data from STIO1 */ ++ ++#define V_CH_SNUM_SHIFT (1) ++#define V_CH_SNUM_MASK (31 << 1) ++ ++/* A_CON_HDLC bits */ ++#define V_IFF (1 << 0) /* Inter-Frame Fill: 0=0x7e, 1=0xff */ ++#define V_HDLC_TRP (1 << 1) /* 0=HDLC mode, 1=transparent */ ++#define V_TRP_IRQ_0 (0x0 << 2) /* FIFO enabled, no interrupt */ ++#define V_TRP_IRQ_64 (0x1 << 2) /* FIFO enabled, int @ 64 bytes */ ++#define V_TRP_IRQ_128 (0x2 << 2) /* FIFO enabled, int @ 128 bytes */ ++#define V_TRP_IRQ_256 (0x3 << 2) /* FIFO enabled, int @ 256 bytes */ ++#define V_TRP_IRQ_512 (0x4 << 2) /* FIFO enabled, int @ 512 bytes */ ++#define V_TRP_IRQ_1024 (0x5 << 2) /* FIFO enabled, int @ 1024 bytes */ ++#define V_TRP_IRQ_2048 (0x6 << 2) /* FIFO enabled, int @ 2048 bytes */ ++#define V_TRP_IRQ_4096 (0x7 << 2) /* FIFO enabled, int @ 4096 bytes */ ++#define V_TRP_IRQ (0x1 << 2) /* FIFO enabled, interrupt at end of frame (HDLC mode) */ ++#define V_DATA_FLOW_000 (0x0 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_001 (0x1 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_010 (0x2 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_011 (0x3 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_100 (0x4 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_101 (0x5 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_110 (0x6 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_111 (0x7 << 5) /* see A_CON_HDLC reg description in datasheet */ ++ ++/* R_FIFO bits */ ++#define V_FIFO_DIR (1 << 0) /* 1=RX FIFO data */ ++#define V_REV (1 << 7) /* 1=MSB first */ ++#define V_FIFO_NUM_SHIFT (1) ++#define V_FIFO_NUM_MASK (0x3e) ++ ++/* A_CHANNEL bits */ ++#define V_CH_FDIR (1 << 0) /* 1=HFC chan for RX data */ ++#define V_CH_FNUM_SHIFT (1) ++#define V_CH_FNUM_MASK (0x3e) ++ ++/* R_SLOT bits */ ++#define V_SL_DIR (1 << 0) /* 1=timeslot will RX PCM data from bus */ ++#define V_SL_NUM_SHIFT (1) ++#define V_SL_NUM_MASK (0xfe) ++ ++/* A_INC_RES_FIFO bits */ ++#define V_INC_F (1 << 0) /* 1=increment FIFO F-counter (bit auto-clears) */ ++#define V_RES_FIFO (1 << 1) /* 1=reset FIFO (bit auto-clears) */ ++#define V_RES_LOST (1 << 2) /* 1=reset LOST error (bit auto-clears) */ ++ ++/* R_FIFO_MD bits */ ++#define V_FIFO_MD_00 (0x0 << 0) ++#define V_FIFO_MD_01 (0x1 << 0) ++#define V_FIFO_MD_10 (0x2 << 0) ++#define V_FIFO_MD_11 (0x3 << 0) ++#define V_DF_MD_SM (0x0 << 2) /* simple data flow mode */ ++#define V_DF_MD_CSM (0x1 << 2) /* channel select mode */ ++#define V_DF_MD_FSM (0x3 << 2) /* FIFO sequence mode */ ++#define V_FIFO_SZ_00 (0x0 << 4) ++#define V_FIFO_SZ_01 (0x1 << 4) ++#define V_FIFO_SZ_10 (0x2 << 4) ++#define V_FIFO_SZ_11 (0x3 << 4) ++ ++/* A_SUBCH_CFG bits */ ++#define V_BIT_CNT_8BIT (0) /* process 8 bits */ ++#define V_BIT_CNT_1BIT (1) /* process 1 bit */ ++#define V_BIT_CNT_2BIT (2) /* process 2 bits */ ++#define V_BIT_CNT_3BIT (3) /* process 3 bits */ ++#define V_BIT_CNT_4BIT (4) /* process 4 bits */ ++#define V_BIT_CNT_5BIT (5) /* process 5 bits */ ++#define V_BIT_CNT_6BIT (6) /* process 6 bits */ ++#define V_BIT_CNT_7BIT (7) /* process 7 bits */ ++#define V_LOOP_FIFO (1 << 6) /* loop FIFO data */ ++#define V_INV_DATA (1 << 7) /* invert FIFO data */ ++#define V_START_BIT_SHIFT (3) ++#define V_START_BIT_MASK (0x38) ++ ++/* R_ST_SYNC bits */ ++#define V_MAN_SYNC (1 << 3) /* 1=manual sync mode */ ++#define V_SYNC_SEL_MASK (0x03) ++ ++/* A_ST_WR_STA bits */ ++#define V_ST_SET_STA_MASK (0x0f) ++#define V_ST_LD_STA (1 << 4) /* 1=force ST_SET_STA mode, must be manually cleared 6us later */ ++#define V_ST_ACT_NOP (0x0 << 5) /* NOP */ ++#define V_ST_ACT_DEACTIVATE (0x2 << 5) /* start deactivation. auto-clears */ ++#define V_ST_ACT_ACTIVATE (0x3 << 5) /* start activation. auto-clears. */ ++#define V_SET_G2_G3 (1 << 7) /* 1=auto G2->G3 in NT mode. auto-clears after transition. */ ++ ++/* A_ST_RD_STA */ ++#define V_ST_STA_MASK (0x0f) ++#define V_FR_SYNC (1 << 4) /* 1=synchronized */ ++#define V_T2_EXP (1 << 5) /* 1=T2 expired (NT only) */ ++#define V_INFO0 (1 << 6) /* 1=INFO0 */ ++#define V_G2_G3 (1 << 7) /* 1=allows G2->G3 (NT only, auto-clears) */ ++ ++/* A_ST_CLK_DLY bits */ ++#define V_ST_SMPL_SHIFT (4) ++ ++/* A_ST_CTRL0 bits */ ++#define V_B1_EN (1 << 0) /* 1=B1-channel transmit */ ++#define V_B2_EN (1 << 1) /* 1=B2-channel transmit */ ++#define V_ST_MD (1 << 2) /* 0=TE, 1=NT */ ++#define V_D_PRIO (1 << 3) /* D-Chan priority 0=high, 1=low */ ++#define V_SQ_EN (1 << 4) /* S/Q bits transmit (1=enabled) */ ++#define V_96KHZ (1 << 5) /* 1=transmit test signal */ ++#define V_TX_LI (1 << 6) /* 0=capacitive line mode, 1=non-capacitive */ ++#define V_ST_STOP (1 << 7) /* 1=power down */ ++ ++/* A_ST_CTRL1 bits */ ++#define V_G2_G3_EN (1 << 0) /* 1=G2->G3 allowed without V_SET_G2_G3 */ ++#define V_D_HI (1 << 2) /* 1=D-chan reset */ ++#define V_E_IGNO (1 << 3) /* TE:1=ignore Echan, NT:should always be 1. */ ++#define V_E_LO (1 << 4) /* NT only: 1=force Echan low */ ++#define V_B12_SWAP (1 << 7) /* 1=swap B1/B2 */ ++ ++/* A_ST_CTRL2 bits */ ++#define V_B1_RX_EN (1 << 0) /* 1=enable B1 RX */ ++#define V_B2_RX_EN (1 << 1) /* 1=enable B2 RX */ ++#define V_ST_TRI (1 << 6) /* 1=tristate S/T output buffer */ ++ ++/* User Flash Manager */ ++#define UFM_PROGRAM (1<<0) ++#define UFM_ERASE (1<<1) ++#define UFM_DRSHIFT (1<<2) ++#define UFM_DRDIN (1<<3) ++#define UFM_DRCLK (1<<4) ++#define UFM_ARSHIFT (1<<5) ++#define UFM_ARDIN (1<<6) ++#define UFM_ARCLK (1<<7) ++ ++#define NUM_REGS 0xff ++#define NUM_PCI 12 ++ ++/* From this point down, things only the kernel needs to know about */ ++#ifdef __KERNEL__ ++ ++#define HFC_T1 0 ++#define HFC_T2 1 ++#define HFC_T3 2 ++#define HFC_T4 3 ++ ++#define MAX_SPANS_PER_CARD 8 ++ ++#define WCB4XXP_CHANNELS_PER_SPAN 3 /* 2 B-channels and 1 D-Channel for each BRI span */ ++#define WCB4XXP_HDLC_BUF_LEN 32 /* arbitrary, just the max # of byts we will send to DAHDI per call */ ++ ++struct b4xxp_span { ++ struct b4xxp *parent; ++ int port; /* virtual port */ ++ int phy_port; /* physical port */ ++ ++ unsigned char writechunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE]; ++ unsigned char readchunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE]; ++ ++ int sync; /* sync priority */ ++ ++ int oldstate; /* old state machine state */ ++ int newalarm; /* alarm to send to zaptel once alarm timer expires */ ++ unsigned long alarmtimer; ++ ++ int te_mode; /* 1=TE, 0=NT */ ++ unsigned long hfc_timers[4]; /* T1, T2, T3, Fake T4 */ ++ int hfc_timer_on[4]; /* 1=timer active */ ++ int fifos[WCB4XXP_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */ ++ ++ /* HDLC controller fields */ ++ struct dahdi_chan *sigchan; /* pointer to the signalling channel for this span */ ++ int sigactive; /* nonzero means we're in the middle of sending an HDLC frame */ ++ atomic_t hdlc_pending; /* hdlc_hard_xmit() increments, hdlc_tx_frame() decrements */ ++ int frames_out; ++ int frames_in; ++ ++ struct dahdi_span span; /* zaptel span info for this span */ ++ struct dahdi_chan *chans[WCB4XXP_CHANNELS_PER_SPAN]; /* Individual channels */ ++ struct dahdi_echocan_state ec[WCB4XXP_CHANNELS_PER_SPAN]; /* echocan state for each channel */ ++ struct dahdi_chan _chans[WCB4XXP_CHANNELS_PER_SPAN]; /* Backing memory */ ++}; ++ ++enum cards_ids { /* Cards ==> Brand & Model */ ++ B410P = 0, /* Digium B410P */ ++ B200P_OV, /* OpenVox B200P */ ++ B400P_OV, /* OpenVox B400P */ ++ B800P_OV, /* OpenVox B800P */ ++ DUOBRI, /* HFC-2S Junghanns.NET duoBRI PCI */ ++ QUADBRI, /* HFC-4S Junghanns.NET quadBRI PCI */ ++ OCTOBRI, /* HFC-8S Junghanns.NET octoBRI PCI */ ++ BN2S0, /* BeroNet BN2S0 */ ++ BN4S0, /* Beronet BN4S0 */ ++ BN8S0, /* BeroNet BN8S0 */ ++ BSWYX_SX2, /* Swyx 4xS0 SX2 QuadBri */ ++ QUADBRI_EVAL, /* HFC-4S CCD Eval. Board */ ++ B430P, /* Digium B430P */ ++ B230P /* Digium B230P */ ++ }; ++ ++/* This structure exists one per card */ ++struct b4xxp { ++ char *variety; ++ int chiprev; /* revision of HFC-4S */ ++ ++ struct pci_dev *pdev; /* Pointer to PCI device */ ++ void __iomem *addr; /* I/O address (memory mapped) */ ++ void __iomem *ioaddr; /* I/O address (index based) */ ++ int irq; /* IRQ used by device */ ++ ++ spinlock_t reglock; /* lock for all register accesses */ ++ spinlock_t seqlock; /* lock for "sequence" accesses that must be ordered */ ++ spinlock_t fifolock; /* lock for all FIFO accesses (reglock must be available) */ ++ ++ volatile unsigned long ticks; ++ ++ unsigned long fifo_en_rxint; /* each bit is the RX int enable for that FIFO */ ++ unsigned long fifo_en_txint; /* each bit is the TX int enable for that FIFO */ ++ ++ unsigned char fifo_irqstatus[8]; /* top-half ORs in new interrupts, bottom-half ANDs them out */ ++ unsigned char misc_irqstatus; /* same for this */ ++ unsigned char st_irqstatus; /* same for this too */ ++ ++ unsigned int numspans; ++ ++ int blinktimer; /* for the fancy LED alarms */ ++ int alarmpos; /* ditto */ ++ ++ int cardno; /* Which card we are */ ++ int globalconfig; /* Whether global setup has been done */ ++ int syncspan; /* span that HFC uses for sync on this card */ ++ int running; /* interrupts are enabled */ ++ ++ struct b4xxp_span spans[MAX_SPANS_PER_CARD]; /* Individual spans */ ++ int order; /* Order */ ++ int flags; /* Device flags */ ++ enum cards_ids card_type; /* For LED handling mostly */ ++ int master; /* Are we master */ ++ int ledreg; /* copy of the LED Register */ ++ unsigned int gpio; ++ unsigned int gpioctl; ++ int spansstarted; /* number of spans started */ ++ ++ /* Flags for our bottom half */ ++ unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */ ++ struct tasklet_struct b4xxp_tlet; ++ struct dahdi_device *ddev; ++}; ++ ++/* CPLD access bits */ ++#define B4_RDADDR 0 ++#define B4_WRADDR 1 ++#define B4_COUNT 2 ++#define B4_DMACTRL 3 ++#define B4_INTR 4 ++#define B4_VERSION 6 ++#define B4_LEDS 7 ++#define B4_GPIOCTL 8 ++#define B4_GPIO 9 ++#define B4_LADDR 10 ++#define B4_LDATA 11 ++ ++#define B4_LCS (1 << 11) ++#define B4_LCS2 (1 << 12) ++#define B4_LALE (1 << 13) ++#define B4_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */ ++#define B4_ACTIVATE (1 << 12) ++#define B4_LREAD (1 << 15) ++#define B4_LWRITE (1 << 16) ++ ++#define LED_OFF (0) ++#define LED_RED (1) ++#define LED_GREEN (2) ++ ++#define get_F(f1, f2, flen) { \ ++ f1 = hfc_readcounter8(b4, A_F1); \ ++ f2 = hfc_readcounter8(b4, A_F2); \ ++ flen = f1 - f2; \ ++ \ ++ if(flen < 0) \ ++ flen += (HFC_FMAX - HFC_FMIN) + 1; \ ++ } ++ ++#define get_Z(z1, z2, zlen) { \ ++ z1 = hfc_readcounter16(b4, A_Z1); \ ++ z2 = hfc_readcounter16(b4, A_Z2); \ ++ zlen = z1 - z2; \ ++ \ ++ if(zlen < 0) \ ++ zlen += (HFC_ZMAX - HFC_ZMIN) + 1; \ ++ } ++ ++#define flush_pci() (void)ioread8(b4->addr + R_STATUS) ++ ++#endif /* __KERNEL__ */ ++#endif /* _B4XX_H_ */ ++ +diff -Nru linux-source-4.19/drivers/dahdi/wct4xxp/Kbuild linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/Kbuild +--- linux-source-4.19/drivers/dahdi/wct4xxp/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/Kbuild 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,31 @@ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp.o ++ ++FIRM_DIR := ../firmware ++ ++EXTRA_CFLAGS += -I$(src)/.. -I$(src)/../oct612x/ $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef ++ ++# The OCT612X source files are from a vendor drop and we do not want to edit ++# them to make this warning go away. Therefore, turn off the ++# unused-but-set-variable warning for this driver. ++ ++EXTRA_CFLAGS += $(call cc-option, -Wno-unused-but-set-variable) ++ ++ifeq ($(HOTPLUG_FIRMWARE),yes) ++ EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE ++endif ++ ++wct4xxp-objs := base.o vpm450m.o ++ ++ifneq ($(HOTPLUG_FIRMWARE),yes) ++wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o ++$(warning WARNING: You are compiling firmware into wct4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.) ++endif ++ ++$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o ++ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-064.o ++ ++$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-128.o: $(obj)/base.o ++ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-128.o ++ ++$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-256.o: $(obj)/base.o ++ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-256.o +diff -Nru linux-source-4.19/drivers/dahdi/wct4xxp/base.c linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/base.c +--- linux-source-4.19/drivers/dahdi/wct4xxp/base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/base.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,5463 @@ ++/* ++ * TE410P Quad-T1/E1 PCI Driver version 0.1, 12/16/02 ++ * ++ * Written by Mark Spencer ++ * Based on previous works, designs, and archetectures conceived and ++ * written by Jim Dixon . ++ * Further modified, optimized, and maintained by ++ * Matthew Fredrickson and ++ * Russ Meyerriecks ++ * ++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony. ++ * Copyright (C) 2001-2012, 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "wct4xxp.h" ++#include "vpm450m.h" ++ ++/* Support first generation cards? */ ++#define SUPPORT_GEN1 ++ ++/* Define to get more attention-grabbing but slightly more I/O using ++ alarm status */ ++#undef FANCY_ALARM ++ ++/* Define to support Digium Voice Processing Module expansion card */ ++#define VPM_SUPPORT ++ ++#define DEBUG_MAIN (1 << 0) ++#define DEBUG_DTMF (1 << 1) ++#define DEBUG_REGS (1 << 2) ++#define DEBUG_TSI (1 << 3) ++#define DEBUG_ECHOCAN (1 << 4) ++#define DEBUG_RBS (1 << 5) ++#define DEBUG_FRAMER (1 << 6) ++ ++/* Maximum latency to be used with Gen 5 */ ++#define GEN5_MAX_LATENCY 127 ++ ++/* ++ * Define CONFIG_FORCE_EXTENDED_RESET to allow the qfalc framer extra time ++ * to reset itself upon hardware initialization. This exits for rare ++ * cases for customers who are seeing the qfalc returning unexpected ++ * information at initialization ++ */ ++/* #define CONFIG_FORCE_EXTENDED_RESET */ ++/* #define CONFIG_NOEXTENDED_RESET */ ++ ++/* ++ * Uncomment the following definition in order to disable Active-State Power ++ * Management on the PCIe bridge for PCIe cards. This has been known to work ++ * around issues where the BIOS enables it on the cards even though the ++ * platform does not support it. ++ * ++ */ ++/* #define CONFIG_WCT4XXP_DISABLE_ASPM */ ++ ++#if defined(CONFIG_FORCE_EXTENDED_RESET) && defined(CONFIG_NOEXTENDED_RESET) ++#error "You cannot define both CONFIG_FORCE_EXTENDED_RESET and " \ ++ "CONFIG_NOEXTENDED_RESET." ++#endif ++ ++int debug = 0; ++static int timingcable = 0; ++static int t1e1override = -1; /* deprecated */ ++static char *default_linemode = "auto"; ++static int j1mode = 0; ++static int sigmode = FRMR_MODE_NO_ADDR_CMP; ++static int alarmdebounce = 2500; /* LOF/LFA def to 2.5s AT&T TR54016*/ ++static int losalarmdebounce = 2500;/* LOS def to 2.5s AT&T TR54016*/ ++static int aisalarmdebounce = 2500;/* AIS(blue) def to 2.5s AT&T TR54016*/ ++static int yelalarmdebounce = 500;/* RAI(yellow) def to 0.5s AT&T devguide */ ++static int max_latency = GEN5_MAX_LATENCY; /* Used to set a maximum latency (if you don't wish it to hard cap it at a certain value) in milliseconds */ ++#ifdef VPM_SUPPORT ++static int vpmsupport = 1; ++/* If set to auto, vpmdtmfsupport is enabled for VPM400M and disabled for VPM450M */ ++static int vpmdtmfsupport = -1; /* -1=auto, 0=disabled, 1=enabled*/ ++#endif /* VPM_SUPPORT */ ++ ++/* Enabling bursting can more efficiently utilize PCI bus bandwidth, but ++ can also cause PCI bus starvation, especially in combination with other ++ aggressive cards. Please note that burst mode has no effect on CPU ++ utilization / max number of calls / etc. */ ++static int noburst; ++/* For 56kbps links, set this module parameter to 0x7f */ ++static int hardhdlcmode = 0xff; ++ ++static int latency = 1; ++ ++static int ms_per_irq = 1; ++static int ignore_rotary; ++ ++#ifdef FANCY_ALARM ++static int altab[] = { ++0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, ++}; ++#endif ++ ++#define MAX_SPANS 16 ++ ++#define FLAG_STARTED (1 << 0) ++#define FLAG_NMF (1 << 1) ++#define FLAG_SENDINGYELLOW (1 << 2) ++ ++#define FLAG_2NDGEN (1 << 3) ++#define FLAG_2PORT (1 << 4) ++#define FLAG_VPM2GEN (1 << 5) ++#define FLAG_OCTOPT (1 << 6) ++#define FLAG_3RDGEN (1 << 7) ++#define FLAG_BURST (1 << 8) ++#define FLAG_EXPRESS (1 << 9) ++#define FLAG_5THGEN (1 << 10) ++#define FLAG_8PORT (1 << 11) ++ ++#define CANARY 0xc0de ++ ++/* names of available HWEC modules */ ++#ifdef VPM_SUPPORT ++#define T4_VPM_PRESENT (1 << 28) ++static const char *vpmoct064_name = "VPMOCT064"; ++static const char *vpmoct128_name = "VPMOCT128"; ++static const char *vpmoct256_name = "VPMOCT256"; ++#endif ++ ++struct devtype { ++ char *desc; ++ unsigned int flags; ++}; ++ ++static struct devtype wct820p5 = { "Wildcard TE820 (5th Gen)", FLAG_8PORT | FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS }; ++static struct devtype wct420p5 = { "Wildcard TE420 (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS }; ++static struct devtype wct410p5 = { "Wildcard TE410P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; ++static struct devtype wct405p5 = { "Wildcard TE405P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; ++static struct devtype wct220p5 = { "Wildcard TE220 (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT | FLAG_EXPRESS }; ++static struct devtype wct210p5 = { "Wildcard TE210P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; ++static struct devtype wct205p5 = { "Wildcard TE205P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; ++ ++static struct devtype wct4xxp = { "Wildcard TE410P/TE405P (1st Gen)", 0 }; ++static struct devtype wct420p4 = { "Wildcard TE420 (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS }; ++static struct devtype wct410p4 = { "Wildcard TE410P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; ++static struct devtype wct410p3 = { "Wildcard TE410P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; ++static struct devtype wct405p4 = { "Wildcard TE405P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; ++static struct devtype wct405p3 = { "Wildcard TE405P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; ++static struct devtype wct410p2 = { "Wildcard TE410P (2nd Gen)", FLAG_2NDGEN }; ++static struct devtype wct405p2 = { "Wildcard TE405P (2nd Gen)", FLAG_2NDGEN }; ++static struct devtype wct220p4 = { "Wildcard TE220 (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT | FLAG_EXPRESS }; ++static struct devtype wct205p4 = { "Wildcard TE205P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; ++static struct devtype wct205p3 = { "Wildcard TE205P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; ++static struct devtype wct210p4 = { "Wildcard TE210P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; ++static struct devtype wct210p3 = { "Wildcard TE210P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; ++static struct devtype wct205 = { "Wildcard TE205P ", FLAG_2NDGEN | FLAG_2PORT }; ++static struct devtype wct210 = { "Wildcard TE210P ", FLAG_2NDGEN | FLAG_2PORT }; ++ ++ ++struct t4; ++ ++enum linemode {T1, E1, J1}; ++ ++struct spi_state { ++ int wrreg; ++ int rdreg; ++}; ++ ++struct t4_span { ++ struct t4 *owner; ++ u32 *writechunk; /* Double-word aligned write memory */ ++ u32 *readchunk; /* Double-word aligned read memory */ ++ enum linemode linemode; ++ int sync; ++ int alarmtimer; ++ int notclear; ++ unsigned long alarm_time; ++ unsigned long losalarm_time; ++ unsigned long aisalarm_time; ++ unsigned long yelalarm_time; ++ unsigned long alarmcheck_time; ++ int spanflags; ++ int syncpos; ++ ++#ifdef SUPPORT_GEN1 ++ int e1check; /* E1 check */ ++#endif ++ struct dahdi_span span; ++ unsigned char txsigs[16]; /* Transmit sigs */ ++ int loopupcnt; ++ int loopdowncnt; ++#ifdef SUPPORT_GEN1 ++ unsigned char ec_chunk1[31][DAHDI_CHUNKSIZE]; /* first EC chunk buffer */ ++ unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE]; /* second EC chunk buffer */ ++#endif ++ /* HDLC controller fields */ ++ struct dahdi_chan *sigchan; ++ unsigned char sigmode; ++ int sigactive; ++ int frames_out; ++ int frames_in; ++ ++#ifdef VPM_SUPPORT ++ unsigned long dtmfactive; ++ unsigned long dtmfmask; ++ unsigned long dtmfmutemask; ++#endif ++ struct dahdi_chan *chans[32]; /* Individual channels */ ++ struct dahdi_echocan_state *ec[32]; /* Echocan state for each channel */ ++}; ++ ++struct t4 { ++ /* This structure exists one per card */ ++ struct pci_dev *dev; /* Pointer to PCI device */ ++ unsigned int intcount; ++ int num; /* Which card we are */ ++ int syncsrc; /* active sync source */ ++ struct dahdi_device *ddev; ++ struct t4_span *tspans[8]; /* Individual spans */ ++ int numspans; /* Number of spans on the card */ ++ int blinktimer; ++#ifdef FANCY_ALARM ++ int alarmpos; ++#endif ++ int irq; /* IRQ used by device */ ++ int order; /* Order */ ++ const struct devtype *devtype; ++ unsigned int reset_required:1; /* If reset needed in serial_setup */ ++ unsigned int falc31:1; /* are we falc v3.1 (atomic not necessary) */ ++ unsigned int t1e1:8; /* T1 / E1 select pins */ ++ int ledreg; /* LED Register */ ++ int ledreg2; /* LED Register2 */ ++ unsigned int gpio; ++ unsigned int gpioctl; ++ int e1recover; /* E1 recovery timer */ ++ spinlock_t reglock; /* lock register access */ ++ int spansstarted; /* number of spans started */ ++ u32 *writechunk; /* Double-word aligned write memory */ ++ u32 *readchunk; /* Double-word aligned read memory */ ++ int last0; /* for detecting double-missed IRQ */ ++ ++ /* DMA related fields */ ++ unsigned int dmactrl; ++ dma_addr_t readdma; ++ dma_addr_t writedma; ++ void __iomem *membase; /* Base address of card */ ++ ++#define T4_CHECK_VPM 0 ++#define T4_LOADING_FW 1 ++#define T4_STOP_DMA 2 ++#define T4_CHECK_TIMING 3 ++#define T4_CHANGE_LATENCY 4 ++#define T4_IGNORE_LATENCY 5 ++ unsigned long checkflag; ++ struct work_struct bh_work; ++ /* Latency related additions */ ++ unsigned char rxident; ++ unsigned char lastindex; ++ int numbufs; ++ int needed_latency; ++ ++#ifdef VPM_SUPPORT ++ struct vpm450m *vpm; ++#endif ++ struct spi_state st; ++}; ++ ++static inline bool is_pcie(const struct t4 *wc) ++{ ++ return (wc->devtype->flags & FLAG_EXPRESS) > 0; ++} ++ ++static inline bool has_e1_span(const struct t4 *wc) ++{ ++ return (wc->t1e1 > 0); ++} ++ ++static inline bool is_octal(const struct t4 *wc) ++{ ++ return (wc->devtype->flags & FLAG_8PORT) > 0; ++} ++ ++static inline int T4_BASE_SIZE(struct t4 *wc) ++{ ++ if (is_octal(wc)) ++ return DAHDI_MAX_CHUNKSIZE * 32 * 8; ++ else ++ return DAHDI_MAX_CHUNKSIZE * 32 * 4; ++} ++ ++/** ++ * ports_on_framer - The number of ports on the framers. ++ * @wc: Board to check. ++ * ++ * The framer ports could be different the the number of ports on the card ++ * since the dual spans have four ports internally but two ports extenally. ++ * ++ */ ++static inline unsigned int ports_on_framer(const struct t4 *wc) ++{ ++ return (is_octal(wc)) ? 8 : 4; ++} ++ ++#ifdef VPM_SUPPORT ++static void t4_vpm_init(struct t4 *wc); ++ ++static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++ ++static const struct dahdi_echocan_features vpm_ec_features = { ++ .NLP_automatic = 1, ++ .CED_tx_detect = 1, ++ .CED_rx_detect = 1, ++}; ++ ++static const struct dahdi_echocan_ops vpm_ec_ops = { ++ .echocan_free = echocan_free, ++}; ++#endif ++ ++static void __set_clear(struct t4 *wc, int span); ++static int _t4_startup(struct file *file, struct dahdi_span *span); ++static int t4_startup(struct file *file, struct dahdi_span *span); ++static int t4_shutdown(struct dahdi_span *span); ++static int t4_rbsbits(struct dahdi_chan *chan, int bits); ++static int t4_maint(struct dahdi_span *span, int cmd); ++static int t4_clear_maint(struct dahdi_span *span); ++static int t4_reset_counters(struct dahdi_span *span); ++#ifdef SUPPORT_GEN1 ++static int t4_reset_dma(struct t4 *wc); ++#endif ++static void t4_hdlc_hard_xmit(struct dahdi_chan *chan); ++static int t4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data); ++static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan); ++static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan); ++static void __t4_set_rclk_src(struct t4 *wc, int span); ++static void __t4_set_sclk_src(struct t4 *wc, int mode, int master, int slave); ++static void t4_check_alarms(struct t4 *wc, int span); ++static void t4_check_sigbits(struct t4 *wc, int span); ++ ++#define WC_RDADDR 0 ++#define WC_WRADDR 1 ++#define WC_COUNT 2 ++#define WC_DMACTRL 3 ++#define WC_INTR 4 ++/* #define WC_GPIO 5 */ ++#define WC_VERSION 6 ++#define WC_LEDS 7 ++#define WC_GPIOCTL 8 ++#define WC_GPIO 9 ++#define WC_LADDR 10 ++#define WC_LDATA 11 ++#define WC_LEDS2 12 ++ ++#define WC_SET_AUTH (1 << 20) ++#define WC_GET_AUTH (1 << 12) ++ ++#define WC_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */ ++#define WC_LCS (1 << 11) ++#define WC_LCS2 (1 << 12) ++#define WC_LALE (1 << 13) ++#define WC_LFRMR_CS2 (1 << 14) /* Framer's ChipSelect signal 2 */ ++#define WC_LREAD (1 << 15) ++#define WC_LWRITE (1 << 16) ++ ++#define WC_ACTIVATE (1 << 12) ++ ++#define WC_OFF (0) ++#define WC_RED (1) ++#define WC_GREEN (2) ++#define WC_YELLOW (3) ++ ++#define WC_RECOVER 0 ++#define WC_SELF 1 ++ ++#define LIM0_T 0x36 /* Line interface mode 0 register */ ++#define LIM0_LL (1 << 1) /* Local Loop */ ++#define LIM1_T 0x37 /* Line interface mode 1 register */ ++#define LIM1_RL (1 << 1) /* Remote Loop */ ++ ++#define FMR0 0x1C /* Framer Mode Register 0 */ ++#define FMR0_SIM (1 << 0) /* Alarm Simulation */ ++#define FMR1_T 0x1D /* Framer Mode Register 1 */ ++#define FMR1_ECM (1 << 2) /* Error Counter 1sec Interrupt Enable */ ++#define FMR5 0x21 /* Framer Mode Register 5 */ ++#define FMR5_XLU (1 << 4) /* Transmit loopup code */ ++#define FMR5_XLD (1 << 5) /* Transmit loopdown code */ ++#define FMR5_EIBR (1 << 6) /* Internal Bit Robbing Access */ ++#define DEC_T 0x60 /* Diable Error Counter */ ++#define IERR_T 0x1B /* Single Bit Defect Insertion Register */ ++#define IBV (1 << 0) /* Bipolar violation */ ++#define IPE (1 << 1) /* PRBS defect */ ++#define ICASE (1 << 2) /* CAS defect */ ++#define ICRCE (1 << 3) /* CRC defect */ ++#define IMFE (1 << 4) /* Multiframe defect */ ++#define IFASE (1 << 5) /* FAS defect */ ++#define ISR3_SEC (1 << 6) /* Internal one-second interrupt bit mask */ ++#define ISR3_ES (1 << 7) /* Errored Second interrupt bit mask */ ++#define ESM 0x47 /* Errored Second mask register */ ++ ++#define FMR2_T 0x1E /* Framer Mode Register 2 */ ++#define FMR2_PLB (1 << 2) /* Framer Mode Register 2 */ ++ ++#define FECL_T 0x50 /* Framing Error Counter Lower Byte */ ++#define FECH_T 0x51 /* Framing Error Counter Higher Byte */ ++#define CVCL_T 0x52 /* Code Violation Counter Lower Byte */ ++#define CVCH_T 0x53 /* Code Violation Counter Higher Byte */ ++#define CEC1L_T 0x54 /* CRC Error Counter 1 Lower Byte */ ++#define CEC1H_T 0x55 /* CRC Error Counter 1 Higher Byte */ ++#define EBCL_T 0x56 /* E-Bit Error Counter Lower Byte */ ++#define EBCH_T 0x57 /* E-Bit Error Counter Higher Byte */ ++#define BECL_T 0x58 /* Bit Error Counter Lower Byte */ ++#define BECH_T 0x59 /* Bit Error Counter Higher Byte */ ++#define COEC_T 0x5A /* COFA Event Counter */ ++#define PRBSSTA_T 0xDA /* PRBS Status Register */ ++ ++#define LCR1_T 0x3B /* Loop Code Register 1 */ ++#define EPRM (1 << 7) /* Enable PRBS rx */ ++#define XPRBS (1 << 6) /* Enable PRBS tx */ ++#define FLLB (1 << 1) /* Framed line loop/Invert */ ++#define LLBP (1 << 0) /* Line Loopback Pattern */ ++#define TPC0_T 0xA8 /* Test Pattern Control Register */ ++#define FRA (1 << 6) /* Framed/Unframed Selection */ ++#define PRBS23 (3 << 4) /* Pattern selection (23 poly) */ ++#define PRM (1 << 2) /* Non framed mode */ ++#define FRS1_T 0x4D /* Framer Receive Status Reg 1 */ ++#define LLBDD (1 << 4) ++#define LLBAD (1 << 3) ++ ++#define MAX_T4_CARDS 64 ++ ++static struct t4 *cards[MAX_T4_CARDS]; ++ ++struct t8_firm_header { ++ u8 header[6]; ++ __le32 chksum; ++ u8 pad[18]; ++ __le32 version; ++} __packed; ++ ++#define MAX_TDM_CHAN 32 ++#define MAX_DTMF_DET 16 ++ ++#define HDLC_IMR0_MASK (FRMR_IMR0_RME | FRMR_IMR0_RPF) ++#define HDLC_IMR1_MASK (FRMR_IMR1_XDU | FRMR_IMR1_XPR) ++ ++static inline unsigned int __t4_pci_in(struct t4 *wc, const unsigned int addr) ++{ ++ unsigned int res = readl(wc->membase + (addr * sizeof(u32))); ++ return res; ++} ++ ++static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) ++{ ++#ifdef DEBUG ++ unsigned int tmp; ++#endif ++ writel(value, wc->membase + (addr * sizeof(u32))); ++#ifdef DEBUG ++ tmp = __t4_pci_in(wc, WC_VERSION); ++ if ((tmp & 0xffff0000) != 0xc01a0000) ++ dev_notice(&wc->dev->dev, ++ "Version Synchronization Error!\n"); ++#else ++ __t4_pci_in(wc, WC_VERSION); ++#endif ++} ++ ++static inline void __t4_gpio_set(struct t4 *wc, unsigned bits, unsigned int val) ++{ ++ unsigned int newgpio; ++ newgpio = wc->gpio & (~bits); ++ newgpio |= val; ++ if (newgpio != wc->gpio) { ++ wc->gpio = newgpio; ++ __t4_pci_out(wc, WC_GPIO, wc->gpio); ++ } ++} ++ ++static inline void __t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) ++{ ++ unsigned int newgpioctl; ++ newgpioctl = wc->gpioctl & (~bits); ++ newgpioctl |= val; ++ if (newgpioctl != wc->gpioctl) { ++ wc->gpioctl = newgpioctl; ++ __t4_pci_out(wc, WC_GPIOCTL, wc->gpioctl); ++ } ++} ++ ++static inline void t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t4_gpio_setdir(wc, bits, val); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static inline void t4_gpio_set(struct t4 *wc, unsigned int bits, unsigned int val) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t4_gpio_set(wc, bits, val); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static inline void t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t4_pci_out(wc, addr, value); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static inline void __t4_set_led(struct t4 *wc, int span, int color) ++{ ++ if (span <= 3) { ++ int oldreg = wc->ledreg; ++ ++ wc->ledreg &= ~(0x3 << (span << 1)); ++ wc->ledreg |= (color << (span << 1)); ++ if (oldreg != wc->ledreg) ++ __t4_pci_out(wc, WC_LEDS, wc->ledreg); ++ } else { ++ int oldreg = wc->ledreg2; ++ ++ span &= 3; ++ wc->ledreg2 &= ~(0x3 << (span << 1)); ++ wc->ledreg2 |= (color << (span << 1)); ++ if (oldreg != wc->ledreg2) ++ __t4_pci_out(wc, WC_LEDS2, wc->ledreg2); ++ } ++} ++ ++static inline void t4_activate(struct t4 *wc) ++{ ++ wc->ledreg |= WC_ACTIVATE; ++ t4_pci_out(wc, WC_LEDS, wc->ledreg); ++} ++ ++static inline unsigned int t4_pci_in(struct t4 *wc, const unsigned int addr) ++{ ++ unsigned int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ret = __t4_pci_in(wc, addr); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return ret; ++} ++ ++static unsigned int __t4_framer_in(const struct t4 *wc, int unit, ++ const unsigned int addr) ++{ ++ unsigned int ret; ++ register u32 val; ++ void __iomem *const wc_laddr = wc->membase + (WC_LADDR*sizeof(u32)); ++ void __iomem *const wc_version = wc->membase + (WC_VERSION*sizeof(u32)); ++ void __iomem *const wc_ldata = wc->membase + (WC_LDATA*sizeof(u32)); ++ int haddr = (((unit & 4) ? 0 : WC_LFRMR_CS2)); ++ unit &= 0x3; ++ ++ val = ((unit & 0x3) << 8) | (addr & 0xff) | haddr; ++ writel(val, wc_laddr); ++ readl(wc_version); ++ writel(val | WC_LFRMR_CS | WC_LREAD, wc_laddr); ++ readl(wc_version); ++ ret = readb(wc_ldata); ++ writel(val, wc_laddr); ++ readl(wc_version); ++ return ret; ++} ++ ++static unsigned int ++t4_framer_in(struct t4 *wc, int unit, const unsigned int addr) ++{ ++ unsigned long flags; ++ unsigned int ret; ++ spin_lock_irqsave(&wc->reglock, flags); ++ ret = __t4_framer_in(wc, unit, addr); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return ret; ++} ++ ++static void __t4_framer_out(const struct t4 *wc, int unit, const u8 addr, ++ const unsigned int value) ++{ ++ register u32 val; ++ void __iomem *const wc_laddr = wc->membase + (WC_LADDR*sizeof(u32)); ++ void __iomem *const wc_version = wc->membase + (WC_VERSION*sizeof(u32)); ++ void __iomem *const wc_ldata = wc->membase + (WC_LDATA*sizeof(u32)); ++ int haddr = (((unit & 4) ? 0 : WC_LFRMR_CS2)); ++ ++ val = ((unit & 0x3) << 8) | (addr & 0xff) | haddr; ++ writel(val, wc_laddr); ++ readl(wc_version); ++ writel(value, wc_ldata); ++ readl(wc_version); ++ writel(val | WC_LFRMR_CS | WC_LWRITE, wc_laddr); ++ readl(wc_version); ++ writel(val, wc_laddr); ++ readl(wc_version); ++} ++ ++static void t4_framer_out(struct t4 *wc, int unit, ++ const unsigned int addr, ++ const unsigned int value) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t4_framer_out(wc, unit, addr, value); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++#ifdef VPM_SUPPORT ++ ++static inline void __t4_raw_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) ++{ ++ int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; ++ if (!octopt) ++ __t4_gpio_set(wc, 0xff, (addr >> 8)); ++ __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); ++ if (!octopt) ++ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); ++ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); ++ if (!octopt) ++ __t4_gpio_set(wc, 0xff, (value >> 8)); ++ __t4_pci_out(wc, WC_LDATA, (value & 0xffff)); ++ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE | WC_LCS)); ++ __t4_pci_out(wc, WC_LADDR, (0)); ++} ++ ++static inline unsigned int __t4_raw_oct_in(struct t4 *wc, const unsigned int addr) ++{ ++ unsigned int ret; ++ int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; ++ if (!octopt) ++ __t4_gpio_set(wc, 0xff, (addr >> 8)); ++ __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); ++ if (!octopt) ++ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); ++ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); ++ __t4_pci_out(wc, WC_LADDR, (WC_LALE)); ++ if (!octopt) { ++ __t4_gpio_setdir(wc, 0xff, 0x00); ++ __t4_gpio_set(wc, 0xff, 0x00); ++ } ++ __t4_pci_out(wc, WC_LADDR, (WC_LREAD | WC_LALE | WC_LCS)); ++ if (octopt) { ++ ret = __t4_pci_in(wc, WC_LDATA) & 0xffff; ++ } else { ++ ret = __t4_pci_in(wc, WC_LDATA) & 0xff; ++ ret |= (__t4_pci_in(wc, WC_GPIO) & 0xff) << 8; ++ } ++ __t4_pci_out(wc, WC_LADDR, (0)); ++ if (!octopt) ++ __t4_gpio_setdir(wc, 0xff, 0xff); ++ return ret & 0xffff; ++} ++ ++static inline unsigned int __t4_oct_in(struct t4 *wc, unsigned int addr) ++{ ++#ifdef PEDANTIC_OCTASIC_CHECKING ++ int count = 1000; ++#endif ++ __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); ++ __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); ++ __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1)); ++#ifdef PEDANTIC_OCTASIC_CHECKING ++ while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); ++ if (count != 1000) ++ dev_notice(&wc->dev->dev, "Yah, read can be slow...\n"); ++ if (!count) ++ dev_notice(&wc->dev->dev, "Read timed out!\n"); ++#endif ++ return __t4_raw_oct_in(wc, 0x0004); ++} ++ ++static inline unsigned int t4_oct_in(struct t4 *wc, const unsigned int addr) ++{ ++ unsigned long flags; ++ unsigned int ret; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ret = __t4_oct_in(wc, addr); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return ret; ++} ++ ++static inline void __t4_oct_out(struct t4 *wc, unsigned int addr, unsigned int value) ++{ ++#ifdef PEDANTIC_OCTASIC_CHECKING ++ int count = 1000; ++#endif ++ __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); ++ __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); ++ __t4_raw_oct_out(wc, 0x0004, value); ++ __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1); ++#ifdef PEDANTIC_OCTASIC_CHECKING ++ while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); ++ if (count != 1000) ++ dev_notice(&wc->dev->dev, "Yah, write can be slow\n"); ++ if (!count) ++ dev_notice(&wc->dev->dev, "Write timed out!\n"); ++#endif ++} ++ ++static inline void t4_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t4_oct_out(wc, addr, value); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static void t4_check_vpm(struct t4 *wc) ++{ ++ int channel, tone, start, span; ++ ++ if (vpm450m_checkirq(wc->vpm)) { ++ while(vpm450m_getdtmf(wc->vpm, &channel, &tone, &start)) { ++ span = channel & 0x3; ++ channel >>= 2; ++ if (!has_e1_span(wc)) ++ channel -= 5; ++ else ++ channel -= 1; ++ if (unlikely(debug)) ++ dev_info(&wc->dev->dev, "Got tone %s of '%c' " ++ "on channel %d of span %d\n", ++ (start ? "START" : "STOP"), ++ tone, channel, span + 1); ++ if (test_bit(channel, &wc->tspans[span]->dtmfmask) && (tone != 'u')) { ++ if (start) { ++ /* The octasic is supposed to mute us, but... Yah, you ++ guessed it. */ ++ if (test_bit(channel, &wc->tspans[span]->dtmfmutemask)) { ++ unsigned long flags; ++ struct dahdi_chan *chan = wc->tspans[span]->span.chans[channel]; ++ int y; ++ spin_lock_irqsave(&chan->lock, flags); ++ for (y=0;ynumbufs;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); ++ } ++ set_bit(channel, &wc->tspans[span]->dtmfactive); ++ dahdi_qevent_lock(wc->tspans[span]->span.chans[channel], (DAHDI_EVENT_DTMFDOWN | tone)); ++ } else { ++ clear_bit(channel, &wc->tspans[span]->dtmfactive); ++ dahdi_qevent_lock(wc->tspans[span]->span.chans[channel], (DAHDI_EVENT_DTMFUP | tone)); ++ } ++ } ++ } ++ } ++} ++ ++#endif /* VPM_SUPPORT */ ++ ++static void hdlc_stop(struct t4 *wc, unsigned int span) ++{ ++ struct t4_span *t = wc->tspans[span]; ++ unsigned char imr0, imr1, mode; ++ unsigned long flags; ++ int i = 0; ++ ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Stopping HDLC controller on span " ++ "%d\n", span+1); ++ ++ /* Clear receive and transmit timeslots */ ++ for (i = 0; i < 4; i++) { ++ t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00); ++ t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00); ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ imr0 = __t4_framer_in(wc, span, FRMR_IMR0); ++ imr1 = __t4_framer_in(wc, span, FRMR_IMR1); ++ ++ /* Disable HDLC interrupts */ ++ imr0 |= HDLC_IMR0_MASK; ++ __t4_framer_out(wc, span, FRMR_IMR0, imr0); ++ ++ imr1 |= HDLC_IMR1_MASK; ++ __t4_framer_out(wc, span, FRMR_IMR1, imr1); ++ ++ mode = __t4_framer_in(wc, span, FRMR_MODE); ++ mode &= ~FRMR_MODE_HRAC; ++ __t4_framer_out(wc, span, FRMR_MODE, mode); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ t->sigactive = 0; ++} ++ ++static inline void __t4_framer_cmd(struct t4 *wc, unsigned int span, int cmd) ++{ ++ __t4_framer_out(wc, span, FRMR_CMDR, cmd); ++} ++ ++static inline void t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd) ++{ ++ int sis; ++ int loops = 0; ++ ++ /* XXX could be time consuming XXX */ ++ for (;;) { ++ sis = t4_framer_in(wc, span, FRMR_SIS); ++ if (!(sis & 0x04)) ++ break; ++ if (!loops++ && (debug & DEBUG_FRAMER)) { ++ dev_notice(&wc->dev->dev, "!!!SIS Waiting before cmd " ++ "%02x\n", cmd); ++ } ++ } ++ if (loops && (debug & DEBUG_FRAMER)) ++ dev_notice(&wc->dev->dev, "!!!SIS waited %d loops\n", loops); ++ ++ t4_framer_out(wc, span, FRMR_CMDR, cmd); ++} ++ ++static int hdlc_start(struct t4 *wc, unsigned int span, struct dahdi_chan *chan, unsigned char mode) ++{ ++ struct t4_span *t = wc->tspans[span]; ++ unsigned char imr0, imr1; ++ int offset = chan->chanpos; ++ unsigned long flags; ++ ++ if (debug & DEBUG_FRAMER) ++ dev_info(&wc->dev->dev, "Starting HDLC controller for channel " ++ "%d span %d\n", offset, span+1); ++ ++ if (mode != FRMR_MODE_NO_ADDR_CMP) ++ return -1; ++ ++ mode |= FRMR_MODE_HRAC; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ /* Make sure we're in the right mode */ ++ __t4_framer_out(wc, span, FRMR_MODE, mode); ++ __t4_framer_out(wc, span, FRMR_TSEO, 0x00); ++ __t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode); ++ ++ /* Set the interframe gaps, etc */ ++ __t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS); ++ ++ __t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC); ++ ++ /* Set up the time slot that we want to tx/rx on */ ++ __t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8))); ++ __t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8))); ++ ++ imr0 = __t4_framer_in(wc, span, FRMR_IMR0); ++ imr1 = __t4_framer_in(wc, span, FRMR_IMR1); ++ ++ /* Enable our interrupts again */ ++ imr0 &= ~HDLC_IMR0_MASK; ++ __t4_framer_out(wc, span, FRMR_IMR0, imr0); ++ ++ imr1 &= ~HDLC_IMR1_MASK; ++ __t4_framer_out(wc, span, FRMR_IMR1, imr1); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* Reset the signaling controller */ ++ t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ t->sigchan = chan; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ t->sigactive = 0; ++ ++ return 0; ++} ++ ++static void __set_clear(struct t4 *wc, int span) ++{ ++ int i,j; ++ int oldnotclear; ++ unsigned short val=0; ++ struct t4_span *ts = wc->tspans[span]; ++ ++ oldnotclear = ts->notclear; ++ if (E1 != ts->linemode) { ++ for (i=0;i<24;i++) { ++ j = (i/8); ++ if (ts->span.chans[i]->flags & DAHDI_FLAG_CLEAR) { ++ val |= 1 << (7 - (i % 8)); ++ ts->notclear &= ~(1 << i); ++ } else ++ ts->notclear |= (1 << i); ++ if ((i % 8)==7) { ++ if (debug) ++ dev_notice(&wc->dev->dev, "Putting %d " ++ "in register %02x on span %d" ++ "\n", val, 0x2f + j, span + 1); ++ __t4_framer_out(wc, span, 0x2f + j, val); ++ val = 0; ++ } ++ } ++ } else { ++ for (i=0;i<31;i++) { ++ if (ts->span.chans[i]->flags & DAHDI_FLAG_CLEAR) ++ ts->notclear &= ~(1 << i); ++ else ++ ts->notclear |= (1 << i); ++ } ++ } ++ if (ts->notclear != oldnotclear) { ++ unsigned char reg; ++ reg = __t4_framer_in(wc, span, FRMR_IMR0); ++ if (ts->notclear) ++ reg &= ~0x08; ++ else ++ reg |= 0x08; ++ __t4_framer_out(wc, span, FRMR_IMR0, reg); ++ } ++} ++ ++static int t4_dacs(struct dahdi_chan *dst, struct dahdi_chan *src) ++{ ++ struct t4 *wc; ++ struct t4_span *ts; ++ wc = dst->pvt; ++ ts = wc->tspans[dst->span->offset]; ++ if (src && (src->pvt != dst->pvt)) { ++ if (ts->spanflags & FLAG_2NDGEN) ++ t4_tsi_unassign(wc, dst->span->offset, dst->chanpos); ++ wc = src->pvt; ++ if (ts->spanflags & FLAG_2NDGEN) ++ t4_tsi_unassign(wc, src->span->offset, src->chanpos); ++ if (debug) ++ dev_notice(&wc->dev->dev, "Unassigning %d/%d by " ++ "default and...\n", src->span->offset, ++ src->chanpos); ++ if (debug) ++ dev_notice(&wc->dev->dev, "Unassigning %d/%d by " ++ "default\n", dst->span->offset, dst->chanpos); ++ return -1; ++ } ++ if (src) { ++ t4_tsi_assign(wc, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos); ++ if (debug) ++ dev_notice(&wc->dev->dev, "Assigning channel %d/%d -> " ++ "%d/%d!\n", src->span->offset, src->chanpos, ++ dst->span->offset, dst->chanpos); ++ } else { ++ t4_tsi_unassign(wc, dst->span->offset, dst->chanpos); ++ if (debug) ++ dev_notice(&wc->dev->dev, "Unassigning channel %d/%d!" ++ "\n", dst->span->offset, dst->chanpos); ++ } ++ return 0; ++} ++ ++#ifdef VPM_SUPPORT ++ ++void oct_set_reg(void *data, unsigned int reg, unsigned int val) ++{ ++ struct t4 *wc = data; ++ t4_oct_out(wc, reg, val); ++} ++ ++unsigned int oct_get_reg(void *data, unsigned int reg) ++{ ++ struct t4 *wc = data; ++ unsigned int ret; ++ ret = t4_oct_in(wc, reg); ++ return ret; ++} ++ ++static const char *__t4_echocan_name(struct t4 *wc) ++{ ++ if (wc->vpm) { ++ if (wc->numspans == 2) ++ return vpmoct064_name; ++ else if (wc->numspans == 4) ++ return vpmoct128_name; ++ else if (wc->numspans == 8) ++ return vpmoct256_name; ++ } ++ return NULL; ++} ++ ++static const char *t4_echocan_name(const struct dahdi_chan *chan) ++{ ++ struct t4 *wc = chan->pvt; ++ return __t4_echocan_name(wc); ++} ++ ++static int t4_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ struct t4 *wc = chan->pvt; ++ struct t4_span *tspan = container_of(chan->span, struct t4_span, span); ++ int channel; ++ const bool alaw = (chan->span->deflaw == 2); ++ ++ if (!vpmsupport || !wc->vpm) ++ return -ENODEV; ++ ++ if (ecp->param_count > 0) { ++ dev_warn(&wc->dev->dev, "%s echo canceller does not support " ++ "parameters; failing request\n", ++ chan->ec_factory->get_name(chan)); ++ return -EINVAL; ++ } ++ ++ *ec = tspan->ec[chan->chanpos - 1]; ++ (*ec)->ops = &vpm_ec_ops; ++ (*ec)->features = vpm_ec_features; ++ ++ channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4; ++ ++ if (is_octal(wc)) ++ channel = channel << 3; ++ else ++ channel = channel << 2; ++ channel |= chan->span->offset; ++ if (debug & DEBUG_ECHOCAN) { ++ dev_notice(&wc->dev->dev, ++ "echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n", ++ wc->num, chan->chanpos, chan->span->offset, ++ channel, ecp->tap_length); ++ } ++ vpm450m_set_alaw_companding(wc->vpm, channel, alaw); ++ vpm450m_setec(wc->vpm, channel, ecp->tap_length); ++ return 0; ++} ++ ++static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct t4 *wc = chan->pvt; ++ int channel; ++ ++ if (!wc->vpm) ++ return; ++ ++ memset(ec, 0, sizeof(*ec)); ++ channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4; ++ ++ if (is_octal(wc)) ++ channel = channel << 3; ++ else ++ channel = channel << 2; ++ channel |= chan->span->offset; ++ if (debug & DEBUG_ECHOCAN) { ++ dev_notice(&wc->dev->dev, ++ "echocan: Card is %d, Channel is %d, Span is %d, offset is %d length 0\n", ++ wc->num, chan->chanpos, chan->span->offset, channel); ++ } ++ vpm450m_setec(wc->vpm, channel, 0); ++} ++#endif ++ ++static int t4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) ++{ ++ struct t4_regs regs; ++ struct t4_reg reg; ++ int x; ++ struct t4 *wc = chan->pvt; ++#ifdef VPM_SUPPORT ++ int j; ++ int channel; ++ struct t4_span *ts = wc->tspans[chan->span->offset]; ++#endif ++ ++ switch(cmd) { ++ case WCT4_SET_REG: ++ if (copy_from_user(®, (struct t4_reg __user *)data, ++ sizeof(reg))) ++ return -EFAULT; ++ t4_pci_out(wc, reg.reg, reg.val); ++ break; ++ case WCT4_GET_REG: ++ if (copy_from_user(®, (struct t4_reg __user *)data, ++ sizeof(reg))) ++ return -EFAULT; ++ reg.val = t4_pci_in(wc, reg.reg); ++ if (copy_to_user((struct t4_reg __user *)data, ++ ®, sizeof(reg))) ++ return -EFAULT; ++ break; ++ case WCT4_GET_REGS: ++ for (x=0;xspan->offset, x); ++ if (copy_to_user((void __user *) data, ++ ®s, sizeof(regs))) ++ return -EFAULT; ++ break; ++#ifdef VPM_SUPPORT ++ case DAHDI_TONEDETECT: ++ if (get_user(j, (__user int *) data)) ++ return -EFAULT; ++ if (!wc->vpm) ++ return -ENOSYS; ++ if (j && (vpmdtmfsupport == 0)) ++ return -ENOSYS; ++ if (j & DAHDI_TONEDETECT_ON) ++ set_bit(chan->chanpos - 1, &ts->dtmfmask); ++ else ++ clear_bit(chan->chanpos - 1, &ts->dtmfmask); ++ if (j & DAHDI_TONEDETECT_MUTE) ++ set_bit(chan->chanpos - 1, &ts->dtmfmutemask); ++ else ++ clear_bit(chan->chanpos - 1, &ts->dtmfmutemask); ++ ++ channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4; ++ if (is_octal(wc)) ++ channel = channel << 3; ++ else ++ channel = channel << 2; ++ channel |= chan->span->offset; ++ vpm450m_setdtmf(wc->vpm, channel, j & DAHDI_TONEDETECT_ON, ++ j & DAHDI_TONEDETECT_MUTE); ++ return 0; ++#endif ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts) ++{ ++ int res, i; ++ unsigned int size = 32; ++ unsigned char buf[32]; ++ ++ res = dahdi_hdlc_getbuf(ts->sigchan, buf, &size); ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Got buffer sized %d and res %d " ++ "for %d\n", size, res, span); ++ if (size > 0) { ++ ts->sigactive = 1; ++ ++ if (debug & DEBUG_FRAMER) { ++ dev_notice(&wc->dev->dev, "TX("); ++ for (i = 0; i < size; i++) ++ dev_notice(&wc->dev->dev, "%s%02x", ++ (i ? " " : ""), buf[i]); ++ dev_notice(&wc->dev->dev, ")\n"); ++ } ++ ++ for (i = 0; i < size; i++) ++ t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]); ++ ++ if (res) /* End of message */ { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, ++ "transmiting XHF|XME\n"); ++ t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME); ++ ++ts->frames_out; ++ if ((debug & DEBUG_FRAMER) && !(ts->frames_out & 0x0f)) ++ dev_notice(&wc->dev->dev, "Transmitted %d " ++ "frames on span %d\n", ts->frames_out, ++ span); ++ } else { /* Still more to transmit */ ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "transmiting XHF\n"); ++ t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF); ++ } ++ } ++ else if (res < 0) ++ ts->sigactive = 0; ++} ++ ++static void t4_hdlc_hard_xmit(struct dahdi_chan *chan) ++{ ++ struct t4 *wc = chan->pvt; ++ int span = chan->span->offset; ++ struct t4_span *ts = wc->tspans[span]; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (!ts->sigchan) { ++ dev_notice(&wc->dev->dev, "t4_hdlc_hard_xmit: Invalid (NULL) " ++ "signalling channel\n"); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return; ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "t4_hdlc_hard_xmit on channel %s " ++ "(sigchan %s), sigactive=%d\n", chan->name, ++ ts->sigchan->name, ts->sigactive); ++ ++ if ((ts->sigchan == chan) && !ts->sigactive) ++ t4_hdlc_xmit_fifo(wc, span, ts); ++} ++ ++/** ++ * t4_set_framer_bits - Atomically set bits in a framer register. ++ */ ++static void t4_set_framer_bits(struct t4 *wc, unsigned int spanno, ++ unsigned int const addr, u16 bits) ++{ ++ unsigned long flags; ++ unsigned int reg; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t4_framer_in(wc, spanno, addr); ++ __t4_framer_out(wc, spanno, addr, (reg | bits)); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static int t4_maint(struct dahdi_span *span, int cmd) ++{ ++ struct t4_span *ts = container_of(span, struct t4_span, span); ++ struct t4 *wc = ts->owner; ++ unsigned int reg; ++ unsigned long flags; ++ ++ if (E1 == ts->linemode) { ++ switch(cmd) { ++ case DAHDI_MAINT_NONE: ++ dev_info(&wc->dev->dev, "Clearing all maint modes\n"); ++ t4_clear_maint(span); ++ break; ++ case DAHDI_MAINT_LOCALLOOP: ++ dev_info(&wc->dev->dev, ++ "Turning on local loopback\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, LIM0_T, LIM0_LL); ++ break; ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ dev_info(&wc->dev->dev, ++ "Turning on network line loopback\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, LIM1_T, LIM1_RL); ++ break; ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ dev_info(&wc->dev->dev, ++ "Turning on network payload loopback\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, FMR2_T, FMR2_PLB); ++ break; ++ case DAHDI_MAINT_LOOPUP: ++ case DAHDI_MAINT_LOOPDOWN: ++ dev_info(&wc->dev->dev, ++ "Loopup & loopdown not supported in E1 mode\n"); ++ return -ENOSYS; ++ case DAHDI_MAINT_FAS_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IFASE); ++ break; ++ case DAHDI_MAINT_MULTI_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IMFE); ++ break; ++ case DAHDI_MAINT_CRC_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, ICRCE); ++ break; ++ case DAHDI_MAINT_CAS_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, ICASE); ++ break; ++ case DAHDI_MAINT_PRBS_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IPE); ++ break; ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IBV); ++ break; ++ case DAHDI_RESET_COUNTERS: ++ t4_reset_counters(span); ++ break; ++ case DAHDI_MAINT_ALARM_SIM: ++ dev_info(&wc->dev->dev, "Invoking alarm state"); ++ t4_set_framer_bits(wc, span->offset, FMR0, FMR0_SIM); ++ break; ++ default: ++ dev_info(&wc->dev->dev, ++ "Unknown E1 maint command: %d\n", cmd); ++ return -ENOSYS; ++ } ++ } else { ++ switch(cmd) { ++ case DAHDI_MAINT_NONE: ++ dev_info(&wc->dev->dev, "Clearing all maint modes\n"); ++ t4_clear_maint(span); ++ break; ++ case DAHDI_MAINT_LOCALLOOP: ++ dev_info(&wc->dev->dev, ++ "Turning on local loopback\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, LIM0_T, LIM0_LL); ++ break; ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ dev_info(&wc->dev->dev, ++ "Turning on network line loopback\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, LIM1_T, LIM1_RL); ++ break; ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ dev_info(&wc->dev->dev, ++ "Turning on network payload loopback\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, FMR2_T, FMR2_PLB); ++ break; ++ case DAHDI_MAINT_LOOPUP: ++ dev_info(&wc->dev->dev, "Transmitting loopup code\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, FMR5, FMR5_XLU); ++ ts->span.maintstat = DAHDI_MAINT_REMOTELOOP; ++ break; ++ case DAHDI_MAINT_LOOPDOWN: ++ dev_info(&wc->dev->dev, "Transmitting loopdown code\n"); ++ t4_clear_maint(span); ++ t4_set_framer_bits(wc, span->offset, FMR5, FMR5_XLD); ++ break; ++ case DAHDI_MAINT_FAS_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IFASE); ++ break; ++ case DAHDI_MAINT_MULTI_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IMFE); ++ break; ++ case DAHDI_MAINT_CRC_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, ICRCE); ++ break; ++ case DAHDI_MAINT_CAS_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, ICASE); ++ break; ++ case DAHDI_MAINT_PRBS_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IPE); ++ break; ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ t4_framer_out(wc, span->offset, IERR_T, IBV); ++ break; ++ case DAHDI_MAINT_PRBS: ++ dev_info(&wc->dev->dev, "PRBS not supported\n"); ++ return -ENOSYS; ++ case DAHDI_RESET_COUNTERS: ++ t4_reset_counters(span); ++ break; ++ case DAHDI_MAINT_ALARM_SIM: ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t4_framer_in(wc, span->offset, FMR0); ++ ++ /* ++ * The alarm simulation state machine requires us to ++ * bring this bit up and down for at least 1 clock cycle ++ */ ++ __t4_framer_out(wc, span->offset, ++ FMR0, (reg | FMR0_SIM)); ++ udelay(1); ++ __t4_framer_out(wc, span->offset, ++ FMR0, (reg & ~FMR0_SIM)); ++ udelay(1); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ reg = t4_framer_in(wc, span->offset, 0x4e); ++ if (debug & DEBUG_MAIN) { ++ dev_info(&wc->dev->dev, ++ "FRS2(alarm state): %d\n", ++ ((reg & 0xe0) >> 5)); ++ } ++ break; ++ default: ++ dev_info(&wc->dev->dev, "Unknown T1 maint command:%d\n", ++ cmd); ++ break; ++ } ++ } ++ return 0; ++} ++ ++static int t4_clear_maint(struct dahdi_span *span) ++{ ++ struct t4_span *ts = container_of(span, struct t4_span, span); ++ struct t4 *wc = ts->owner; ++ unsigned int reg; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ /* Clear local loop */ ++ reg = __t4_framer_in(wc, span->offset, LIM0_T); ++ __t4_framer_out(wc, span->offset, LIM0_T, (reg & ~LIM0_LL)); ++ ++ /* Clear Remote Loop */ ++ reg = __t4_framer_in(wc, span->offset, LIM1_T); ++ __t4_framer_out(wc, span->offset, LIM1_T, (reg & ~LIM1_RL)); ++ ++ /* Clear Remote Payload Loop */ ++ reg = __t4_framer_in(wc, span->offset, FMR2_T); ++ __t4_framer_out(wc, span->offset, FMR2_T, (reg & ~FMR2_PLB)); ++ ++ /* Clear PRBS */ ++ reg = __t4_framer_in(wc, span->offset, LCR1_T); ++ __t4_framer_out(wc, span->offset, LCR1_T, (reg & ~(XPRBS | EPRM))); ++ ++ /* Clear loopup/loopdown signals on the line */ ++ reg = __t4_framer_in(wc, span->offset, FMR5); ++ __t4_framer_out(wc, span->offset, FMR5, (reg & ~(FMR5_XLU | FMR5_XLD))); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ span->mainttimer = 0; ++ ++ return 0; ++} ++ ++static int t4_reset_counters(struct dahdi_span *span) ++{ ++ struct t4_span *ts = container_of(span, struct t4_span, span); ++ memset(&ts->span.count, 0, sizeof(ts->span.count)); ++ return 0; ++} ++ ++static int t4_rbsbits(struct dahdi_chan *chan, int bits) ++{ ++ u_char m,c; ++ int k,n,b; ++ struct t4 *wc = chan->pvt; ++ struct t4_span *ts = wc->tspans[chan->span->offset]; ++ unsigned long flags; ++ ++ if (debug & DEBUG_RBS) ++ dev_notice(&wc->dev->dev, "Setting bits to %d on channel %s\n", ++ bits, chan->name); ++ spin_lock_irqsave(&wc->reglock, flags); ++ k = chan->span->offset; ++ if (E1 == ts->linemode) { ++ if (chan->chanpos == 16) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return 0; ++ } ++ n = chan->chanpos - 1; ++ if (chan->chanpos > 15) n--; ++ b = (n % 15); ++ c = ts->txsigs[b]; ++ m = (n / 15) << 2; /* nibble selector */ ++ c &= (0xf << m); /* keep the other nibble */ ++ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ ++ ts->txsigs[b] = c; ++ /* output them to the chip */ ++ __t4_framer_out(wc,k,0x71 + b,c); ++ } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) { ++ n = chan->chanpos - 1; ++ b = (n/4); ++ c = ts->txsigs[b]; ++ m = ((3 - (n % 4)) << 1); /* nibble selector */ ++ c &= ~(0x3 << m); /* keep the other nibble */ ++ c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ ++ ts->txsigs[b] = c; ++ /* output them to the chip */ ++ __t4_framer_out(wc,k,0x70 + b,c); ++ __t4_framer_out(wc,k,0x70 + b + 6,c); ++ } else if (ts->span.lineconfig & DAHDI_CONFIG_ESF) { ++ n = chan->chanpos - 1; ++ b = (n/2); ++ c = ts->txsigs[b]; ++ m = ((n % 2) << 2); /* nibble selector */ ++ c &= (0xf << m); /* keep the other nibble */ ++ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ ++ ts->txsigs[b] = c; ++ /* output them to the chip */ ++ __t4_framer_out(wc,k,0x70 + b,c); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ if (debug & DEBUG_RBS) ++ dev_notice(&wc->dev->dev, "Finished setting RBS bits\n"); ++ return 0; ++} ++ ++static int t4_shutdown(struct dahdi_span *span) ++{ ++ int tspan; ++ int wasrunning; ++ unsigned long flags; ++ struct t4_span *ts = container_of(span, struct t4_span, span); ++ struct t4 *wc = ts->owner; ++ ++ tspan = span->offset + 1; ++ if (tspan < 0) { ++ dev_notice(&wc->dev->dev, "T%dXXP: Span '%d' isn't us?\n", ++ wc->numspans, span->spanno); ++ return -1; ++ } ++ ++ if (debug & DEBUG_MAIN) ++ dev_notice(&wc->dev->dev, "Shutting down span %d (%s)\n", ++ span->spanno, span->name); ++ ++ /* Stop HDLC controller if runned */ ++ if (ts->sigchan) ++ hdlc_stop(wc, span->offset); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wasrunning = span->flags & DAHDI_FLAG_RUNNING; ++ ++ span->flags &= ~DAHDI_FLAG_RUNNING; ++ __t4_set_led(wc, span->offset, WC_OFF); ++ if (((wc->numspans == 8) && ++ (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[4]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[5]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[6]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[7]->span.flags & DAHDI_FLAG_RUNNING))) ++ || ++ ((wc->numspans == 4) && ++ (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING))) ++ || ++ ((wc->numspans == 2) && ++ (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) && ++ (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)))) { ++ /* No longer in use, disable interrupts */ ++ dev_info(&wc->dev->dev, "TE%dXXP: Disabling interrupts since " ++ "there are no active spans\n", wc->numspans); ++ set_bit(T4_STOP_DMA, &wc->checkflag); ++ } else ++ set_bit(T4_CHECK_TIMING, &wc->checkflag); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* Wait for interrupt routine to shut itself down */ ++ msleep(10); ++ if (wasrunning) ++ wc->spansstarted--; ++ ++ if (debug & DEBUG_MAIN) ++ dev_notice(&wc->dev->dev, "Span %d (%s) shutdown\n", ++ span->spanno, span->name); ++ return 0; ++} ++ ++static void t4_chan_set_sigcap(struct dahdi_span *span, int x) ++{ ++ struct t4_span *wc = container_of(span, struct t4_span, span); ++ struct dahdi_chan *chan = wc->chans[x]; ++ chan->sigcap = DAHDI_SIG_CLEAR; ++ /* E&M variant supported depends on span type */ ++ if (E1 == wc->linemode) { ++ /* E1 sigcap setup */ ++ if (span->lineconfig & DAHDI_CONFIG_CCS) { ++ /* CCS setup */ ++ chan->sigcap |= DAHDI_SIG_MTP2 | DAHDI_SIG_SF | ++ DAHDI_SIG_HARDHDLC; ++ return; ++ } ++ /* clear out sig and sigcap for channel 16 on E1 CAS ++ * lines, otherwise, set it correctly */ ++ if (x == 15) { ++ /* CAS signaling channel setup */ ++ wc->chans[15]->sigcap = 0; ++ wc->chans[15]->sig = 0; ++ return; ++ } ++ /* normal CAS setup */ ++ chan->sigcap |= DAHDI_SIG_EM_E1 | DAHDI_SIG_FXSLS | ++ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_SF | ++ DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | ++ DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS; ++ } else { ++ /* T1 sigcap setup */ ++ chan->sigcap |= DAHDI_SIG_EM | DAHDI_SIG_FXSLS | ++ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_MTP2 | ++ DAHDI_SIG_SF | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | ++ DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS | ++ DAHDI_SIG_HARDHDLC; ++ } ++} ++ ++static int ++_t4_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ int i; ++ struct t4_span *ts = container_of(span, struct t4_span, span); ++ struct t4 *wc = ts->owner; ++ ++ if (debug) ++ dev_info(&wc->dev->dev, "About to enter spanconfig!\n"); ++ if (debug & DEBUG_MAIN) ++ dev_notice(&wc->dev->dev, "TE%dXXP: Configuring span %d\n", ++ wc->numspans, span->spanno); ++ ++ if (lc->sync < 0) ++ lc->sync = 0; ++ if (lc->sync > wc->numspans) { ++ dev_warn(&wc->dev->dev, "WARNING: Cannot set priority on span %d to %d. Please set to a number between 1 and %d\n", ++ span->spanno, lc->sync, wc->numspans); ++ lc->sync = 0; ++ } ++ ++ /* remove this span number from the current sync sources, if there */ ++ for(i = 0; i < wc->numspans; i++) { ++ if (wc->tspans[i]->sync == span->spanno) ++ wc->tspans[i]->sync = 0; ++ } ++ wc->tspans[span->offset]->syncpos = lc->sync; ++ /* if a sync src, put it in proper place */ ++ if (lc->sync) ++ wc->tspans[lc->sync - 1]->sync = span->spanno; ++ ++ set_bit(T4_CHECK_TIMING, &wc->checkflag); ++ ++ /* Make sure this is clear in case of multiple startup and shutdown ++ * iterations */ ++ clear_bit(T4_STOP_DMA, &wc->checkflag); ++ ++ /* make sure that sigcaps gets updated if necessary */ ++ for (i = 0; i < span->channels; i++) ++ t4_chan_set_sigcap(span, i); ++ ++ /* If we're already running, then go ahead and apply the changes */ ++ if (span->flags & DAHDI_FLAG_RUNNING) ++ return _t4_startup(file, span); ++ ++ if (debug) ++ dev_info(&wc->dev->dev, "Done with spanconfig!\n"); ++ return 0; ++} ++ ++static int ++t4_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ int ret; ++ struct dahdi_device *const ddev = span->parent; ++ struct dahdi_span *s; ++ ++ ret = _t4_spanconfig(file, span, lc); ++ ++ /* Make sure all the spans have a basic configuration in case they are ++ * not all specified in the configuration files. */ ++ lc->sync = 0; ++ list_for_each_entry(s, &ddev->spans, device_node) { ++ WARN_ON(!s->channels); ++ if (!s->channels) ++ continue; ++ if (!s->chans[0]->sigcap) ++ _t4_spanconfig(file, s, lc); ++ } ++ return ret; ++} ++ ++static int ++t4_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype) ++{ ++ int alreadyrunning; ++ unsigned long flags; ++ struct t4 *wc = chan->pvt; ++ struct t4_span *ts = wc->tspans[chan->span->offset]; ++ ++ alreadyrunning = ts->span.flags & DAHDI_FLAG_RUNNING; ++ if (debug & DEBUG_MAIN) { ++ if (alreadyrunning) ++ dev_notice(&wc->dev->dev, "TE%dXXP: Reconfigured " ++ "channel %d (%s) sigtype %d\n", wc->numspans, ++ chan->channo, chan->name, sigtype); ++ else ++ dev_notice(&wc->dev->dev, "TE%dXXP: Configured channel" ++ " %d (%s) sigtype %d\n", wc->numspans, ++ chan->channo, chan->name, sigtype); ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ if (alreadyrunning) ++ __set_clear(wc, chan->span->offset); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* (re)configure signalling channel */ ++ if ((sigtype == DAHDI_SIG_HARDHDLC) || (ts->sigchan == chan)) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "%sonfiguring hardware HDLC " ++ "on %s\n", ++ ((sigtype == DAHDI_SIG_HARDHDLC) ? "C" : "Unc"), ++ chan->name); ++ if (alreadyrunning) { ++ if (ts->sigchan) ++ hdlc_stop(wc, ts->sigchan->span->offset); ++ if (sigtype == DAHDI_SIG_HARDHDLC) { ++ if (hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) { ++ dev_notice(&wc->dev->dev, "Error " ++ "initializing signalling " ++ "controller\n"); ++ return -1; ++ } ++ } else { ++ spin_lock_irqsave(&wc->reglock, flags); ++ ts->sigchan = NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++ ++ } ++ else { ++ spin_lock_irqsave(&wc->reglock, flags); ++ ts->sigchan = (sigtype == DAHDI_SIG_HARDHDLC) ? chan : NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ts->sigactive = 0; ++ } ++ } ++ return 0; ++} ++ ++static int set_span_devicetype(struct t4 *wc) ++{ ++#ifdef VPM_SUPPORT ++ const char *vpmstring = __t4_echocan_name(wc); ++ ++ if (vpmstring) { ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (%s)", ++ wc->devtype->desc, vpmstring); ++ } else { ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc); ++ } ++#else ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc); ++#endif ++ ++ if (!wc->ddev->devicetype) ++ return -ENOMEM; ++ return 0; ++} ++ ++/* The number of cards we have seen with each ++ possible 'order' switch setting. ++*/ ++static unsigned int order_index[16]; ++ ++static void setup_chunks(struct t4 *wc, int which) ++{ ++ struct t4_span *ts; ++ int offset = 1; ++ int x, y; ++ int gen2; ++ int basesize = T4_BASE_SIZE(wc) >> 2; ++ ++ if (!has_e1_span(wc)) ++ offset += 4; ++ ++ gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN); ++ ++ for (x = 0; x < wc->numspans; x++) { ++ ts = wc->tspans[x]; ++ ts->writechunk = (void *)(wc->writechunk + (x * 32 * 2) + (which * (basesize))); ++ ts->readchunk = (void *)(wc->readchunk + (x * 32 * 2) + (which * (basesize))); ++ for (y=0;ytspans[x]->span.channels;y++) { ++ struct dahdi_chan *mychans = ts->chans[y]; ++ if (gen2) { ++ mychans->writechunk = (void *)(wc->writechunk + ((x * 32 + y + offset) * 2) + (which * (basesize))); ++ mychans->readchunk = (void *)(wc->readchunk + ((x * 32 + y + offset) * 2) + (which * (basesize))); ++ } ++ } ++ } ++} ++ ++static int __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, ++ bool first_time); ++static int __t4_hardware_init_2(struct t4 *wc, bool first_time); ++ ++static int t4_hardware_stop(struct t4 *wc); ++ ++static void t4_framer_reset(struct t4 *wc) ++{ ++ const bool first_time = false; ++#ifdef VPM_SUPPORT ++ bool have_vpm = wc->vpm != NULL; ++ if (have_vpm) { ++ release_vpm450m(wc->vpm); ++ wc->vpm = NULL; ++ } ++#endif ++ t4_hardware_stop(wc); ++ __t4_set_sclk_src(wc, WC_SELF, 0, 0); ++ __t4_hardware_init_1(wc, wc->devtype->flags, first_time); ++ __t4_hardware_init_2(wc, first_time); ++#ifdef VPM_SUPPORT ++ if (have_vpm) { ++ t4_vpm_init(wc); ++ wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0; ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ } ++#endif ++ setup_chunks(wc, 0); ++ wc->lastindex = 0; ++} ++ ++/** ++ * t4_serial_setup - Setup serial parameters and system interface. ++ * @wc: The card to configure. ++ * ++ */ ++static void t4_serial_setup(struct t4 *wc) ++{ ++ unsigned long flags; ++ unsigned int unit; ++ bool reset_required = false; ++ ++ if (debug) { ++ dev_info(&wc->dev->dev, ++ "TE%dXXP: Setting up global serial parameters\n", ++ wc->numspans); ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reset_required = wc->reset_required > 0; ++ wc->reset_required = 0; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (reset_required) ++ t4_framer_reset(wc); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from ++ * channel 0 */ ++ __t4_framer_out(wc, 0, 0x85, 0xe0); ++ if (is_octal(wc)) ++ __t4_framer_out(wc, 0, FRMR_GPC2, 0x00); ++ ++ /* IPC: Interrupt push/pull active low */ ++ __t4_framer_out(wc, 0, 0x08, 0x01); ++ ++ if (is_octal(wc)) { ++ /* Global clocks (16.384 Mhz CLK) */ ++ __t4_framer_out(wc, 0, 0x92, 0x00); /* GCM1 */ ++ __t4_framer_out(wc, 0, 0x93, 0x18); ++ __t4_framer_out(wc, 0, 0x94, 0xfb); ++ __t4_framer_out(wc, 0, 0x95, 0x0b); ++ __t4_framer_out(wc, 0, 0x96, 0x01); ++ __t4_framer_out(wc, 0, 0x97, 0x0b); ++ __t4_framer_out(wc, 0, 0x98, 0xdb); ++ __t4_framer_out(wc, 0, 0x99, 0xdf); ++ } else { ++ /* Global clocks (8.192 Mhz CLK) */ ++ __t4_framer_out(wc, 0, 0x92, 0x00); ++ __t4_framer_out(wc, 0, 0x93, 0x18); ++ __t4_framer_out(wc, 0, 0x94, 0xfb); ++ __t4_framer_out(wc, 0, 0x95, 0x0b); ++ __t4_framer_out(wc, 0, 0x96, 0x00); ++ __t4_framer_out(wc, 0, 0x97, 0x0b); ++ __t4_framer_out(wc, 0, 0x98, 0xdb); ++ __t4_framer_out(wc, 0, 0x99, 0xdf); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ for (unit = 0; unit < ports_on_framer(wc); ++unit) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ /* Configure interrupts */ ++ /* GCR: Interrupt on Activation/Deactivation of each */ ++ __t4_framer_out(wc, unit, FRMR_GCR, 0x00); ++ ++ /* Configure system interface */ ++ if (is_octal(wc)) { ++ /* SIC1: 16.384 Mhz clock/bus, double buffer receive / ++ * transmit, byte interleaved */ ++ __t4_framer_out(wc, unit, FRMR_SIC1, 0xc2 | 0x08); ++ } else { ++ /* SIC1: 8.192 Mhz clock/bus, double buffer receive / ++ * transmit, byte interleaved */ ++ __t4_framer_out(wc, unit, FRMR_SIC1, 0xc2); ++ } ++ /* SIC2: No FFS, no center receive eliastic buffer, phase */ ++ __t4_framer_out(wc, unit, FRMR_SIC2, 0x20 | (unit << 1)); ++ /* SIC3: Edges for capture */ ++ if (is_octal(wc)) { ++ __t4_framer_out(wc, unit, FRMR_SIC3, 0x04 | (1 << 4)); ++ } else { ++ __t4_framer_out(wc, unit, FRMR_SIC3, 0x04); ++ } ++ /* CMR2: We provide sync and clock for tx and rx. */ ++ __t4_framer_out(wc, unit, FRMR_CMR2, 0x00); ++ ++ if (is_octal(wc)) { ++ /* Set RCLK to 16 MHz */ ++ __t4_framer_out(wc, unit, FRMR_CMR4, 0x5); ++ ++ if (!has_e1_span(wc)) { /* T1/J1 mode */ ++ __t4_framer_out(wc, unit, FRMR_XC0, 0x07); ++ __t4_framer_out(wc, unit, FRMR_XC1, 0x04); ++ if (wc->tspans[unit]->linemode == J1) ++ __t4_framer_out(wc, unit, FRMR_RC0, 0x87); ++ else ++ __t4_framer_out(wc, unit, FRMR_RC0, 0x07); ++ __t4_framer_out(wc, unit, FRMR_RC1, 0x04); ++ } else { /* E1 mode */ ++ __t4_framer_out(wc, unit, FRMR_XC0, 0x00); ++ __t4_framer_out(wc, unit, FRMR_XC1, 0x04); ++ __t4_framer_out(wc, unit, FRMR_RC0, 0x00); ++ __t4_framer_out(wc, unit, FRMR_RC1, 0x04); ++ } ++ ++ } else { ++ if (!has_e1_span(wc)) { /* T1/J1 mode */ ++ __t4_framer_out(wc, unit, FRMR_XC0, 0x03); ++ __t4_framer_out(wc, unit, FRMR_XC1, 0x84); ++ if (J1 == wc->tspans[unit]->linemode) ++ __t4_framer_out(wc, unit, FRMR_RC0, 0x83); ++ else ++ __t4_framer_out(wc, unit, FRMR_RC0, 0x03); ++ __t4_framer_out(wc, unit, FRMR_RC1, 0x84); ++ } else { /* E1 mode */ ++ __t4_framer_out(wc, unit, FRMR_XC0, 0x00); ++ __t4_framer_out(wc, unit, FRMR_XC1, 0x04); ++ __t4_framer_out(wc, unit, FRMR_RC0, 0x04); ++ __t4_framer_out(wc, unit, FRMR_RC1, 0x04); ++ } ++ } ++ ++ /* Configure ports */ ++ ++ /* PC1: SPYR/SPYX input on RPA/XPA */ ++ __t4_framer_out(wc, unit, 0x80, 0x00); ++ ++ /* PC2: RMFB/XSIG output/input on RPB/XPB */ ++ /* PC3: Some unused stuff */ ++ /* PC4: Some more unused stuff */ ++ if (is_octal(wc)) { ++ __t4_framer_out(wc, unit, 0x81, 0xBB); ++ __t4_framer_out(wc, unit, 0x82, 0xf5); ++ __t4_framer_out(wc, unit, 0x83, 0x35); ++ } else if (wc->falc31) { ++ __t4_framer_out(wc, unit, 0x81, 0xBB); ++ __t4_framer_out(wc, unit, 0x82, 0xBB); ++ __t4_framer_out(wc, unit, 0x83, 0xBB); ++ } else { ++ __t4_framer_out(wc, unit, 0x81, 0x22); ++ __t4_framer_out(wc, unit, 0x82, 0x65); ++ __t4_framer_out(wc, unit, 0x83, 0x35); ++ } ++ ++ /* PC5: XMFS active low, SCLKR is input, RCLK is output */ ++ __t4_framer_out(wc, unit, 0x84, 0x01); ++ ++ if (debug & DEBUG_MAIN) { ++ dev_notice(&wc->dev->dev, ++ "Successfully initialized serial bus " ++ "for unit %d\n", unit); ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++} ++ ++/** ++ * t4_span_assigned - Called when the span is assigned by DAHDI. ++ * @span: Span that has been assigned. ++ * ++ * When this function is called, the span has a valid spanno and all the ++ * channels on the span have valid channel numbers assigned. ++ * ++ * This function is necessary because a device may be registered, and ++ * then user space may then later decide to assign span numbers and the ++ * channel numbers. ++ * ++ */ ++static void t4_span_assigned(struct dahdi_span *span) ++{ ++ struct t4_span *tspan = container_of(span, struct t4_span, span); ++ struct t4 *wc = tspan->owner; ++ struct dahdi_span *pos; ++ unsigned int unassigned_spans = 0; ++ unsigned long flags; ++ ++ /* We use this to make sure all the spans are assigned before ++ * running the serial setup. */ ++ list_for_each_entry(pos, &wc->ddev->spans, device_node) { ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &pos->flags)) ++ ++unassigned_spans; ++ } ++ ++ if (0 == unassigned_spans) { ++ t4_serial_setup(wc); ++ ++ set_bit(T4_CHECK_TIMING, &wc->checkflag); ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t4_set_sclk_src(wc, WC_SELF, 0, 0); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++} ++ ++static void free_wc(struct t4 *wc) ++{ ++ unsigned int x, y; ++ ++ flush_scheduled_work(); ++ ++ for (x = 0; x < ARRAY_SIZE(wc->tspans); x++) { ++ if (!wc->tspans[x]) ++ continue; ++ for (y = 0; y < ARRAY_SIZE(wc->tspans[x]->chans); y++) { ++ kfree(wc->tspans[x]->chans[y]); ++ kfree(wc->tspans[x]->ec[y]); ++ } ++ kfree(wc->tspans[x]); ++ } ++ ++ kfree(wc->ddev->devicetype); ++ kfree(wc->ddev->location); ++ kfree(wc->ddev->hardware_id); ++ dahdi_free_device(wc->ddev); ++ kfree(wc); ++} ++ ++/** ++ * t4_alloc_channels - Allocate the channels on a span. ++ * @wc: The board we're allocating for. ++ * @ts: The span we're allocating for. ++ * @linemode: Which mode (T1/E1/J1) to use for this span. ++ * ++ * This function must only be called before the span is assigned it's ++ * possible for user processes to have an open reference to the ++ * channels. ++ * ++ */ ++static int t4_alloc_channels(struct t4 *wc, struct t4_span *ts, ++ enum linemode linemode) ++{ ++ int i; ++ ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &ts->span.flags)) { ++ dev_dbg(&wc->dev->dev, ++ "Cannot allocate channels on a span that is already " ++ "assigned.\n"); ++ return -EINVAL; ++ } ++ ++ /* Cleanup any previously allocated channels. */ ++ for (i = 0; i < ARRAY_SIZE(ts->chans); ++i) { ++ kfree(ts->chans[i]); ++ kfree(ts->ec[i]); ++ ts->chans[i] = NULL; ++ ts->ec[i] = NULL; ++ } ++ ++ ts->linemode = linemode; ++ for (i = 0; i < ((E1 == ts->linemode) ? 31 : 24); i++) { ++ struct dahdi_chan *chan; ++ struct dahdi_echocan_state *ec; ++ ++ chan = kzalloc(sizeof(*chan), GFP_KERNEL); ++ if (!chan) { ++ free_wc(wc); ++ return -ENOMEM; ++ } ++ ts->chans[i] = chan; ++ ++ ec = kzalloc(sizeof(*ec), GFP_KERNEL); ++ if (!ec) { ++ free_wc(wc); ++ return -ENOMEM; ++ } ++ ts->ec[i] = ec; ++ } ++ ++ return 0; ++} ++ ++static void t4_init_one_span(struct t4 *wc, struct t4_span *ts) ++{ ++ unsigned long flags; ++ unsigned int reg; ++ int i; ++ ++ snprintf(ts->span.name, sizeof(ts->span.name) - 1, ++ "TE%d/%d/%d", wc->numspans, wc->num, ts->span.offset + 1); ++ snprintf(ts->span.desc, sizeof(ts->span.desc) - 1, ++ "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, ++ ts->span.offset + 1); ++ ++ switch (ts->linemode) { ++ case T1: ++ ts->span.spantype = SPANTYPE_DIGITAL_T1; ++ break; ++ case E1: ++ ts->span.spantype = SPANTYPE_DIGITAL_E1; ++ break; ++ case J1: ++ ts->span.spantype = SPANTYPE_DIGITAL_J1; ++ break; ++ } ++ ++ /* HDLC Specific init */ ++ ts->sigchan = NULL; ++ ts->sigmode = sigmode; ++ ts->sigactive = 0; ++ ++ if (E1 != ts->linemode) { ++ ts->span.channels = 24; ++ ts->span.deflaw = DAHDI_LAW_MULAW; ++ ts->span.linecompat = DAHDI_CONFIG_AMI | ++ DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | ++ DAHDI_CONFIG_ESF; ++ } else { ++ ts->span.channels = 31; ++ ts->span.deflaw = DAHDI_LAW_ALAW; ++ ts->span.linecompat = DAHDI_CONFIG_AMI | ++ DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | ++ DAHDI_CONFIG_CRC4; ++ } ++ ts->span.chans = ts->chans; ++ ts->span.flags = DAHDI_FLAG_RBS; ++ ++ for (i = 0; i < ts->span.channels; i++) { ++ struct dahdi_chan *const chan = ts->chans[i]; ++ chan->pvt = wc; ++ snprintf(chan->name, sizeof(chan->name) - 1, ++ "%s/%d", ts->span.name, i + 1); ++ t4_chan_set_sigcap(&ts->span, i); ++ chan->chanpos = i + 1; ++ } ++ ++ /* Enable 1sec timer interrupt */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t4_framer_in(wc, ts->span.offset, FMR1_T); ++ __t4_framer_out(wc, ts->span.offset, FMR1_T, (reg | FMR1_ECM)); ++ ++ /* Enable Errored Second interrupt */ ++ __t4_framer_out(wc, ts->span.offset, ESM, 0); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ t4_reset_counters(&ts->span); ++} ++ ++/** ++ * t4_set_linemode - Allows user space to change the linemode before spans are assigned. ++ * @span: span on which to change the linemode. ++ * @linemode: A value from enumerated spantypes ++ * ++ * This callback is used to override the E1/T1 mode jumper settings and set ++ * the linemode on for each span. Called when the "spantype" attribute ++ * is written in sysfs under the dahdi_device. ++ * ++ */ ++static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode) ++{ ++ struct t4_span *ts = container_of(span, struct t4_span, span); ++ struct t4 *wc = ts->owner; ++ int res = 0; ++ enum linemode mode; ++ const char *old_name; ++ static DEFINE_MUTEX(linemode_lock); ++ unsigned long flags; ++ ++ dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name, ++ dahdi_spantype2str(linemode)); ++ ++ if (span->spantype == linemode) ++ return 0; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->reset_required = 1; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* Do not allow the t1e1 member to be changed by multiple threads. */ ++ mutex_lock(&linemode_lock); ++ old_name = dahdi_spantype2str(span->spantype); ++ switch (linemode) { ++ case SPANTYPE_DIGITAL_T1: ++ dev_info(&wc->dev->dev, ++ "Changing from %s to T1 line mode.\n", old_name); ++ mode = T1; ++ wc->t1e1 &= ~(1 << span->offset); ++ break; ++ case SPANTYPE_DIGITAL_E1: ++ dev_info(&wc->dev->dev, ++ "Changing from %s to E1 line mode.\n", old_name); ++ mode = E1; ++ wc->t1e1 |= (1 << span->offset); ++ break; ++ case SPANTYPE_DIGITAL_J1: ++ dev_info(&wc->dev->dev, ++ "Changing from %s to J1 line mode.\n", old_name); ++ mode = J1; ++ wc->t1e1 &= ~(1 << span->offset); ++ break; ++ default: ++ dev_err(&wc->dev->dev, ++ "Got invalid linemode %d from dahdi\n", linemode); ++ res = -EINVAL; ++ } ++ ++ if (!res) { ++ t4_alloc_channels(wc, ts, mode); ++ t4_init_one_span(wc, ts); ++ dahdi_init_span(span); ++ } ++ ++ mutex_unlock(&linemode_lock); ++ return res; ++} ++ ++static const struct dahdi_span_ops t4_gen1_span_ops = { ++ .owner = THIS_MODULE, ++ .spanconfig = t4_spanconfig, ++ .chanconfig = t4_chanconfig, ++ .startup = t4_startup, ++ .shutdown = t4_shutdown, ++ .rbsbits = t4_rbsbits, ++ .maint = t4_maint, ++ .ioctl = t4_ioctl, ++ .hdlc_hard_xmit = t4_hdlc_hard_xmit, ++ .assigned = t4_span_assigned, ++ .set_spantype = t4_set_linemode, ++}; ++ ++static const struct dahdi_span_ops t4_gen2_span_ops = { ++ .owner = THIS_MODULE, ++ .spanconfig = t4_spanconfig, ++ .chanconfig = t4_chanconfig, ++ .startup = t4_startup, ++ .shutdown = t4_shutdown, ++ .rbsbits = t4_rbsbits, ++ .maint = t4_maint, ++ .ioctl = t4_ioctl, ++ .hdlc_hard_xmit = t4_hdlc_hard_xmit, ++ .dacs = t4_dacs, ++ .assigned = t4_span_assigned, ++ .set_spantype = t4_set_linemode, ++#ifdef VPM_SUPPORT ++ .echocan_create = t4_echocan_create, ++ .echocan_name = t4_echocan_name, ++#endif ++}; ++ ++/** ++ * init_spans - Do first initialization on all the spans ++ * @wc: Card to initialize the spans on. ++ * ++ * This function is called *before* the dahdi_device is first registered ++ * with the system. What happens in t4_init_one_span can happen between ++ * when the device is registered and when the spans are assigned via ++ * sysfs (or automatically). ++ * ++ */ ++static void init_spans(struct t4 *wc) ++{ ++ int x, y; ++ int gen2; ++ struct t4_span *ts; ++ unsigned int reg; ++ unsigned long flags; ++ ++ gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN); ++ for (x = 0; x < wc->numspans; x++) { ++ ts = wc->tspans[x]; ++ ++ sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1); ++ snprintf(ts->span.desc, sizeof(ts->span.desc) - 1, ++ "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1); ++ switch (ts->linemode) { ++ case T1: ++ ts->span.spantype = SPANTYPE_DIGITAL_T1; ++ break; ++ case E1: ++ ts->span.spantype = SPANTYPE_DIGITAL_E1; ++ break; ++ case J1: ++ ts->span.spantype = SPANTYPE_DIGITAL_J1; ++ break; ++ } ++ ++ /* HDLC Specific init */ ++ ts->sigchan = NULL; ++ ts->sigmode = sigmode; ++ ts->sigactive = 0; ++ ++ if (E1 != ts->linemode) { ++ ts->span.channels = 24; ++ ts->span.deflaw = DAHDI_LAW_MULAW; ++ ts->span.linecompat = DAHDI_CONFIG_AMI | ++ DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | ++ DAHDI_CONFIG_ESF; ++ } else { ++ ts->span.channels = 31; ++ ts->span.deflaw = DAHDI_LAW_ALAW; ++ ts->span.linecompat = DAHDI_CONFIG_AMI | ++ DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | ++ DAHDI_CONFIG_CRC4; ++ } ++ ts->span.chans = ts->chans; ++ ts->span.flags = DAHDI_FLAG_RBS; ++ ++ ts->owner = wc; ++ ts->span.offset = x; ++ ts->writechunk = (void *)(wc->writechunk + x * 32 * 2); ++ ts->readchunk = (void *)(wc->readchunk + x * 32 * 2); ++ ++ if (gen2) { ++ ts->span.ops = &t4_gen2_span_ops; ++ } else { ++ ts->span.ops = &t4_gen1_span_ops; ++ } ++ ++ for (y=0;ytspans[x]->span.channels;y++) { ++ struct dahdi_chan *mychans = ts->chans[y]; ++ sprintf(mychans->name, "TE%d/%d/%d/%d", wc->numspans, wc->num, x + 1, y + 1); ++ t4_chan_set_sigcap(&ts->span, x); ++ mychans->pvt = wc; ++ mychans->chanpos = y + 1; ++ } ++ ++ /* Start checking for alarms in 250 ms */ ++ ts->alarmcheck_time = jiffies + msecs_to_jiffies(250); ++ ++ /* Enable 1sec timer interrupt */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t4_framer_in(wc, x, FMR1_T); ++ __t4_framer_out(wc, x, FMR1_T, (reg | FMR1_ECM)); ++ ++ /* Enable Errored Second interrupt */ ++ __t4_framer_out(wc, x, ESM, 0); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ t4_reset_counters(&ts->span); ++ ++ } ++ ++ set_span_devicetype(wc); ++ setup_chunks(wc, 0); ++ wc->lastindex = 0; ++} ++ ++static int syncsrc = 0; ++static int syncnum = 0 /* -1 */; ++static int syncspan = 0; ++static DEFINE_SPINLOCK(synclock); ++ ++static void __t4_set_rclk_src(struct t4 *wc, int span) ++{ ++ if (is_octal(wc)) { ++ int cmr5 = 0x00 | (span << 5); ++ int cmr1 = 0x38; /* Clock Mode: RCLK sourced by DCO-R1 ++ by default, Disable Clock-Switching */ ++ ++ __t4_framer_out(wc, 0, 0x44, cmr1); ++ __t4_framer_out(wc, 0, FRMR_CMR5, cmr5); ++ } else { ++ int cmr1 = 0x38; /* Clock Mode: RCLK sourced by DCO-R1 ++ by default, Disable Clock-Switching */ ++ cmr1 |= (span << 6); ++ __t4_framer_out(wc, 0, 0x44, cmr1); ++ } ++ ++ dev_info(&wc->dev->dev, "RCLK source set to span %d\n", span+1); ++} ++ ++static void __t4_set_sclk_src(struct t4 *wc, int mode, int master, int slave) ++{ ++ if (slave) { ++ wc->dmactrl |= (1 << 25); ++ dev_info(&wc->dev->dev, "SCLK is slaved to timing cable\n"); ++ } else { ++ wc->dmactrl &= ~(1 << 25); ++ } ++ ++ if (master) { ++ wc->dmactrl |= (1 << 24); ++ dev_info(&wc->dev->dev, "SCLK is master to timing cable\n"); ++ } else { ++ wc->dmactrl &= ~(1 << 24); ++ } ++ ++ if (mode == WC_RECOVER) ++ wc->dmactrl |= (1 << 29); /* Recover timing from RCLK */ ++ ++ if (mode == WC_SELF) ++ wc->dmactrl &= ~(1 << 29);/* Provide timing from MCLK */ ++ ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++} ++ ++static ssize_t t4_timing_master_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct t4 *wc = dev_get_drvdata(dev); ++ if (wc->dmactrl & (1 << 29)) ++ return sprintf(buf, "%d\n", wc->syncsrc); ++ else ++ return sprintf(buf, "%d\n", -1); ++} ++ ++static DEVICE_ATTR(timing_master, 0400, t4_timing_master_show, NULL); ++ ++static void create_sysfs_files(struct t4 *wc) ++{ ++ int ret; ++ ret = device_create_file(&wc->dev->dev, ++ &dev_attr_timing_master); ++ if (ret) { ++ dev_info(&wc->dev->dev, ++ "Failed to create device attributes.\n"); ++ } ++} ++ ++static void remove_sysfs_files(struct t4 *wc) ++{ ++ device_remove_file(&wc->dev->dev, ++ &dev_attr_timing_master); ++} ++ ++static inline void __t4_update_timing(struct t4 *wc) ++{ ++ int i; ++ /* update sync src info */ ++ if (wc->syncsrc != syncsrc) { ++ dev_info(&wc->dev->dev, "Swapping card %d from %d to %d\n", ++ wc->num, wc->syncsrc, syncsrc); ++ wc->syncsrc = syncsrc; ++ /* Update sync sources */ ++ for (i = 0; i < wc->numspans; i++) { ++ wc->tspans[i]->span.syncsrc = wc->syncsrc; ++ } ++ if (syncnum == wc->num) { ++ __t4_set_rclk_src(wc, syncspan-1); ++ __t4_set_sclk_src(wc, WC_RECOVER, 1, 0); ++ if (debug) ++ dev_notice(&wc->dev->dev, "Card %d, using sync " ++ "span %d, master\n", wc->num, syncspan); ++ } else { ++ __t4_set_sclk_src(wc, WC_RECOVER, 0, 1); ++ if (debug) ++ dev_notice(&wc->dev->dev, "Card %d, using " ++ "Timing Bus, NOT master\n", wc->num); ++ } ++ } ++} ++ ++static int __t4_findsync(struct t4 *wc) ++{ ++ int i; ++ int x; ++ unsigned long flags; ++ int p; ++ int nonzero; ++ int newsyncsrc = 0; /* DAHDI span number */ ++ int newsyncnum = 0; /* wct4xxp card number */ ++ int newsyncspan = 0; /* span on given wct4xxp card */ ++ spin_lock_irqsave(&synclock, flags); ++ if (!wc->num) { ++ /* If we're the first card, go through all the motions, up to 8 levels ++ of sync source */ ++ p = 1; ++ while (p < 8) { ++ nonzero = 0; ++ for (x=0;cards[x];x++) { ++ for (i = 0; i < cards[x]->numspans; i++) { ++ if (cards[x]->tspans[i]->syncpos) { ++ nonzero = 1; ++ if ((cards[x]->tspans[i]->syncpos == p) && ++ !(cards[x]->tspans[i]->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_LOOPBACK)) && ++ (cards[x]->tspans[i]->span.flags & DAHDI_FLAG_RUNNING)) { ++ /* This makes a good sync source */ ++ newsyncsrc = cards[x]->tspans[i]->span.spanno; ++ newsyncnum = x; ++ newsyncspan = i + 1; ++ /* Jump out */ ++ goto found; ++ } ++ } ++ } ++ } ++ if (nonzero) ++ p++; ++ else ++ break; ++ } ++found: ++ if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) { ++ if (debug) ++ dev_notice(&wc->dev->dev, "New syncnum: %d " ++ "(was %d), syncsrc: %d (was %d), " ++ "syncspan: %d (was %d)\n", newsyncnum, ++ syncnum, newsyncsrc, syncsrc, ++ newsyncspan, syncspan); ++ syncnum = newsyncnum; ++ syncsrc = newsyncsrc; ++ syncspan = newsyncspan; ++ for (x=0;cards[x];x++) { ++ __t4_update_timing(cards[x]); ++ } ++ } ++ } ++ __t4_update_timing(wc); ++ spin_unlock_irqrestore(&synclock, flags); ++ return 0; ++} ++ ++static void __t4_set_timing_source_auto(struct t4 *wc) ++{ ++ int x, i; ++ int firstprio, secondprio; ++ firstprio = secondprio = 4; ++ ++ if (debug) ++ dev_info(&wc->dev->dev, "timing source auto\n"); ++ clear_bit(T4_CHECK_TIMING, &wc->checkflag); ++ if (timingcable) { ++ __t4_findsync(wc); ++ } else { ++ if (debug) ++ dev_info(&wc->dev->dev, "Evaluating spans for timing " ++ "source\n"); ++ for (x=0;xnumspans;x++) { ++ if ((wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) && ++ !(wc->tspans[x]->span.alarms & (DAHDI_ALARM_RED | ++ DAHDI_ALARM_BLUE))) { ++ if (debug) ++ dev_info(&wc->dev->dev, "span %d is " ++ "green : syncpos %d\n", x+1, ++ wc->tspans[x]->syncpos); ++ if (wc->tspans[x]->syncpos) { ++ /* Valid rsync source in recovered ++ timing mode */ ++ if (firstprio == 4) ++ firstprio = x; ++ else if (wc->tspans[x]->syncpos < ++ wc->tspans[firstprio]->syncpos) ++ firstprio = x; ++ } else { ++ /* Valid rsync source in system timing ++ mode */ ++ if (secondprio == 4) ++ secondprio = x; ++ } ++ } ++ } ++ if (firstprio != 4) { ++ wc->syncsrc = firstprio; ++ __t4_set_rclk_src(wc, firstprio); ++ __t4_set_sclk_src(wc, WC_RECOVER, 0, 0); ++ dev_info(&wc->dev->dev, "Recovered timing mode, "\ ++ "RCLK set to span %d\n", ++ firstprio+1); ++ } else if (secondprio != 4) { ++ wc->syncsrc = -1; ++ __t4_set_rclk_src(wc, secondprio); ++ __t4_set_sclk_src(wc, WC_SELF, 0, 0); ++ dev_info(&wc->dev->dev, "System timing mode, "\ ++ "RCLK set to span %d\n", ++ secondprio+1); ++ } else { ++ wc->syncsrc = -1; ++ dev_info(&wc->dev->dev, "All spans in alarm : No valid"\ ++ "span to source RCLK from\n"); ++ /* Default rclk to lock with span 1 */ ++ __t4_set_rclk_src(wc, 0); ++ __t4_set_sclk_src(wc, WC_SELF, 0, 0); ++ } ++ ++ /* Propagate sync selection to dahdi_span struct ++ * this is read by dahdi_tool to display the span's ++ * master/slave sync information */ ++ for (i = 0; i < wc->numspans; i++) { ++ wc->tspans[i]->span.syncsrc = wc->syncsrc + 1; ++ } ++ } ++} ++ ++static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlevel) ++{ ++ unsigned int fmr4, fmr2, fmr1, fmr0, lim2; ++ char *framing, *line; ++ int mytxlevel; ++ if ((txlevel > 7) || (txlevel < 4)) ++ mytxlevel = 0; ++ else ++ mytxlevel = txlevel - 4; ++ ++ if (is_octal(wc)) ++ fmr1 = 0x9c | 0x02; /* FMR1: Mode 1, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, no XAIS */ ++ else ++ fmr1 = 0x9c; /* FMR1: Mode 1, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, no XAIS */ ++ ++ fmr2 = 0x20; /* FMR2: no payload loopback, don't auto yellow */ ++ fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ ++ lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ ++ lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ ++ __t4_framer_out(wc, unit, 0x1d, fmr1); ++ __t4_framer_out(wc, unit, 0x1e, fmr2); ++ ++ /* Configure line interface */ ++ if (lineconfig & DAHDI_CONFIG_AMI) { ++ line = "AMI"; ++ /* workaround for errata #2 in ES v3 09-10-16 */ ++ fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0; ++ } else { ++ line = "B8ZS"; ++ fmr0 = 0xf0; ++ } ++ if (lineconfig & DAHDI_CONFIG_D4) { ++ framing = "D4"; ++ } else { ++ framing = "ESF"; ++ fmr4 |= 0x2; ++ fmr2 |= 0xc0; ++ } ++ __t4_framer_out(wc, unit, 0x1c, fmr0); ++ __t4_framer_out(wc, unit, 0x20, fmr4); ++ __t4_framer_out(wc, unit, FMR5, FMR5_EIBR); /* FMR5: Enable RBS mode */ ++ ++ __t4_framer_out(wc, unit, 0x37, 0xf0 ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ ++ __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ ++ ++ __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ ++ __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ ++ ++ if (wc->falc31) { ++ if (debug) ++ dev_info(&wc->dev->dev, "card %d span %d: setting Rtx " ++ "to 0ohm for T1\n", wc->num, unit); ++ __t4_framer_out(wc, unit, 0x86, 0x00); /* PC6: set Rtx to 0ohm for T1 */ ++ ++ // Hitting the bugfix register to fix errata #3 ++ __t4_framer_out(wc, unit, 0xbd, 0x05); ++ } ++ ++ __t4_framer_out(wc, unit, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ ++ __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ ++ __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ ++ ++ /* Generate pulse mask for T1 */ ++ switch(mytxlevel) { ++ case 3: ++ __t4_framer_out(wc, unit, 0x26, 0x07); /* XPM0 */ ++ __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */ ++ __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ ++ break; ++ case 2: ++ __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */ ++ __t4_framer_out(wc, unit, 0x27, 0x11); /* XPM1 */ ++ __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */ ++ break; ++ case 1: ++ __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */ ++ __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */ ++ __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ ++ break; ++ case 0: ++ default: ++ __t4_framer_out(wc, unit, 0x26, 0xd7); /* XPM0 */ ++ __t4_framer_out(wc, unit, 0x27, 0x22); /* XPM1 */ ++ __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */ ++ break; ++ } ++ ++ /* Don't mask framer interrupts if hardware HDLC is in use */ ++ __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CAS changes, etc */ ++ __t4_framer_out(wc, unit, FRMR_IMR1, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about nothing */ ++ __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: All the alarm stuff! */ ++ __t4_framer_out(wc, unit, 0x17, 0x34); /* IMR3: AIS and friends */ ++ __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: Slips on transmit */ ++ ++ dev_info(&wc->dev->dev, "Span %d configured for %s/%s\n", unit + 1, ++ framing, line); ++} ++ ++static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig) ++{ ++ unsigned int fmr2, fmr1, fmr0; ++ unsigned int cas = 0; ++ unsigned int imr3extra=0; ++ char *crc4 = ""; ++ char *framing, *line; ++ if (is_octal(wc)) { ++ /* 16 MHz */ ++ fmr1 = 0x44 | 0x02; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ ++ } else { ++ /* 8 MHz */ ++ fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ ++ } ++ fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ ++ if (lineconfig & DAHDI_CONFIG_CRC4) { ++ fmr1 |= 0x08; /* CRC4 transmit */ ++ fmr2 |= 0xc0; /* CRC4 receive */ ++ crc4 = "/CRC4"; ++ } ++ __t4_framer_out(wc, unit, 0x1d, fmr1); ++ __t4_framer_out(wc, unit, 0x1e, fmr2); ++ ++ /* Configure line interface */ ++ if (lineconfig & DAHDI_CONFIG_AMI) { ++ line = "AMI"; ++ /* workaround for errata #2 in ES v3 09-10-16 */ ++ fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0; ++ } else { ++ line = "HDB3"; ++ fmr0 = 0xf0; ++ } ++ if (lineconfig & DAHDI_CONFIG_CCS) { ++ framing = "CCS"; ++ imr3extra = 0x28; ++ } else { ++ framing = "CAS"; ++ cas = 0x40; ++ } ++ __t4_framer_out(wc, unit, 0x1c, fmr0); ++ ++ __t4_framer_out(wc, unit, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ ++ __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ ++ ++ __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ ++ __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ ++ ++ if (wc->falc31) { ++ if (debug) ++ dev_info(&wc->dev->dev, ++ "setting Rtx to 7.5ohm for E1\n"); ++ __t4_framer_out(wc, unit, 0x86, 0x40); /* PC6: turn on 7.5ohm Rtx for E1 */ ++ } ++ ++ /* Condition receive line interface for E1 after reset */ ++ __t4_framer_out(wc, unit, 0xbb, 0x17); ++ __t4_framer_out(wc, unit, 0xbc, 0x55); ++ __t4_framer_out(wc, unit, 0xbb, 0x97); ++ __t4_framer_out(wc, unit, 0xbb, 0x11); ++ __t4_framer_out(wc, unit, 0xbc, 0xaa); ++ __t4_framer_out(wc, unit, 0xbb, 0x91); ++ __t4_framer_out(wc, unit, 0xbb, 0x12); ++ __t4_framer_out(wc, unit, 0xbc, 0x55); ++ __t4_framer_out(wc, unit, 0xbb, 0x92); ++ __t4_framer_out(wc, unit, 0xbb, 0x0c); ++ __t4_framer_out(wc, unit, 0xbb, 0x00); ++ __t4_framer_out(wc, unit, 0xbb, 0x8c); ++ ++ __t4_framer_out(wc, unit, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ ++ __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ ++ __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ ++ ++ __t4_framer_out(wc, unit, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ ++ __t4_framer_out(wc, unit, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ ++ ++ ++ /* Generate pulse mask for E1 */ ++ __t4_framer_out(wc, unit, 0x26, 0x54); /* XPM0 */ ++ __t4_framer_out(wc, unit, 0x27, 0x02); /* XPM1 */ ++ __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ ++ ++ /* Don't mask framer interrupts if hardware HDLC is in use */ ++ __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CRC errors, CAS changes, etc */ ++ __t4_framer_out(wc, unit, FRMR_IMR1, 0x3f & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about loopup / loopdown */ ++ __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */ ++ __t4_framer_out(wc, unit, 0x17, 0x04 | imr3extra); /* IMR3: AIS */ ++ __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */ ++ ++ __t4_framer_out(wc, unit, 0x2f, 0x00); ++ __t4_framer_out(wc, unit, 0x30, 0x00); ++ __t4_framer_out(wc, unit, 0x31, 0x00); ++ ++ dev_info(&wc->dev->dev, "TE%dXXP: Span %d configured for %s/%s%s\n", ++ wc->numspans, unit + 1, framing, line, crc4); ++} ++ ++/** ++ * t4_check_for_interrupts - Return 0 if the card is generating interrupts. ++ * @wc: The card to check. ++ * ++ * If the card is not generating interrupts, this function will also place all ++ * the spans on the card into red alarm. ++ * ++ */ ++static int t4_check_for_interrupts(struct t4 *wc) ++{ ++ unsigned int starting_intcount = wc->intcount; ++ unsigned long stop_time = jiffies + HZ*2; ++ unsigned long flags; ++ int x; ++ ++ msleep(20); ++ spin_lock_irqsave(&wc->reglock, flags); ++ while (starting_intcount == wc->intcount) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ if (time_after(jiffies, stop_time)) { ++ for (x = 0; x < wc->numspans; x++) ++ wc->tspans[x]->span.alarms = DAHDI_ALARM_RED; ++ dev_err(&wc->dev->dev, "Interrupts not detected.\n"); ++ return -EIO; ++ } ++ msleep(100); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return 0; ++} ++ ++static int _t4_startup(struct file *file, struct dahdi_span *span) ++{ ++#ifdef SUPPORT_GEN1 ++ int i; ++#endif ++ int tspan; ++ unsigned long flags; ++ int alreadyrunning; ++ struct t4_span *ts = container_of(span, struct t4_span, span); ++ struct t4 *wc = ts->owner; ++ ++ set_bit(T4_IGNORE_LATENCY, &wc->checkflag); ++ if (debug) ++ dev_info(&wc->dev->dev, "About to enter startup!\n"); ++ ++ tspan = span->offset + 1; ++ if (tspan < 0) { ++ dev_info(&wc->dev->dev, "TE%dXXP: Span '%d' isn't us?\n", ++ wc->numspans, span->spanno); ++ return -1; ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ alreadyrunning = span->flags & DAHDI_FLAG_RUNNING; ++ ++#ifdef SUPPORT_GEN1 ++ /* initialize the start value for the entire chunk of last ec buffer */ ++ for(i = 0; i < span->channels; i++) ++ { ++ memset(ts->ec_chunk1[i], ++ DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE); ++ memset(ts->ec_chunk2[i], ++ DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE); ++ } ++#endif ++ /* Force re-evaluation of timing source */ ++ wc->syncsrc = -1; ++ set_bit(T4_CHECK_TIMING, &wc->checkflag); ++ ++ if (E1 == ts->linemode) ++ __t4_configure_e1(wc, span->offset, span->lineconfig); ++ else ++ __t4_configure_t1(wc, span->offset, span->lineconfig, span->txlevel); ++ ++ /* Note clear channel status */ ++ wc->tspans[span->offset]->notclear = 0; ++ __set_clear(wc, span->offset); ++ ++ if (!alreadyrunning) { ++ span->flags |= DAHDI_FLAG_RUNNING; ++ wc->spansstarted++; ++ ++ if (wc->devtype->flags & FLAG_5THGEN) ++ __t4_pci_out(wc, 5, (ms_per_irq << 16) | wc->numbufs); ++ else ++ __t4_pci_out(wc, 5, (1 << 16) | 1); ++ /* enable interrupts */ ++ /* Start DMA, enabling DMA interrupts on read only */ ++ wc->dmactrl |= (ts->spanflags & FLAG_2NDGEN) ? 0xc0000000 : 0xc0000003; ++#ifdef VPM_SUPPORT ++ wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0; ++#endif ++ /* Seed interrupt register */ ++ __t4_pci_out(wc, WC_INTR, 0x0c); ++ if (noburst || !(ts->spanflags & FLAG_BURST)) ++ wc->dmactrl |= (1 << 26); ++ else ++ wc->dmactrl &= ~(1 << 26); ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ ++ /* Startup HDLC controller too */ ++ } ++ ++ if (ts->sigchan) { ++ struct dahdi_chan *sigchan = ts->sigchan; ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ if (hdlc_start(wc, span->offset, sigchan, ts->sigmode)) { ++ dev_notice(&wc->dev->dev, "Error initializing " ++ "signalling controller\n"); ++ return -1; ++ } ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ local_irq_save(flags); ++ t4_check_alarms(wc, span->offset); ++ t4_check_sigbits(wc, span->offset); ++ local_irq_restore(flags); ++ ++ if (wc->tspans[0]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Primary Sync Source\n", ++ span->spanno); ++ if (wc->tspans[1]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Secondary Sync Source\n", ++ span->spanno); ++ if (wc->numspans >= 4) { ++ if (wc->tspans[2]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Tertiary Sync Source" ++ "\n", span->spanno); ++ if (wc->tspans[3]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Quaternary Sync " ++ "Source\n", span->spanno); ++ } ++ if (wc->numspans == 8) { ++ if (wc->tspans[4]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Quinary Sync " ++ "Source\n", span->spanno); ++ if (wc->tspans[5]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Senary Sync " ++ "Source\n", span->spanno); ++ if (wc->tspans[6]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Septenary Sync " ++ "Source\n", span->spanno); ++ if (wc->tspans[7]->sync == span->spanno) ++ dev_info(&wc->dev->dev, "SPAN %d: Octonary Sync " ++ "Source\n", span->spanno); ++ } ++ ++ if (!alreadyrunning) { ++ if (t4_check_for_interrupts(wc)) ++ return -EIO; ++ } ++ ++ if (debug) ++ dev_info(&wc->dev->dev, "Completed startup!\n"); ++ clear_bit(T4_IGNORE_LATENCY, &wc->checkflag); ++ return 0; ++} ++ ++static int t4_startup(struct file *file, struct dahdi_span *span) ++{ ++ int ret; ++ struct dahdi_device *const ddev = span->parent; ++ struct dahdi_span *s; ++ ++ ret = _t4_startup(file, span); ++ list_for_each_entry(s, &ddev->spans, device_node) { ++ if (!test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags)) { ++ _t4_startup(file, s); ++ } ++ } ++ return ret; ++} ++ ++#ifdef SUPPORT_GEN1 ++static inline void e1_check(struct t4 *wc, int span, int val) ++{ ++ struct t4_span *ts = wc->tspans[span]; ++ if ((ts->span.channels > 24) && ++ (ts->span.flags & DAHDI_FLAG_RUNNING) && ++ !(ts->span.alarms) && ++ (!wc->e1recover)) { ++ if (val != 0x1b) { ++ ts->e1check++; ++ } else ++ ts->e1check = 0; ++ if (ts->e1check > 100) { ++ /* Wait 1000 ms */ ++ wc->e1recover = 1000 * 8; ++ wc->tspans[0]->e1check = wc->tspans[1]->e1check = 0; ++ if (wc->numspans == 4) ++ wc->tspans[2]->e1check = wc->tspans[3]->e1check = 0; ++ if (debug & DEBUG_MAIN) ++ dev_notice(&wc->dev->dev, "Detected loss of " ++ "E1 alignment on span %d!\n", span); ++ t4_reset_dma(wc); ++ } ++ } ++} ++ ++static void t4_receiveprep(struct t4 *wc, int irq) ++{ ++ unsigned int *readchunk; ++ int dbl = 0; ++ int x,y,z; ++ unsigned int tmp; ++ int offset=0; ++ if (!has_e1_span(wc)) ++ offset = 4; ++ if (irq & 1) { ++ /* First part */ ++ readchunk = wc->readchunk; ++ if (!wc->last0) ++ dbl = 1; ++ wc->last0 = 0; ++ } else { ++ readchunk = wc->readchunk + DAHDI_CHUNKSIZE * 32; ++ if (wc->last0) ++ dbl = 1; ++ wc->last0 = 1; ++ } ++ if (unlikely(dbl && (debug & DEBUG_MAIN))) ++ dev_notice(&wc->dev->dev, "Double/missed interrupt detected\n"); ++ ++ for (x=0;xnumspans == 4) { ++ wc->tspans[3]->span.chans[z]->readchunk[x] = tmp & 0xff; ++ wc->tspans[2]->span.chans[z]->readchunk[x] = (tmp & 0xff00) >> 8; ++ } ++ wc->tspans[1]->span.chans[z]->readchunk[x] = (tmp & 0xff0000) >> 16; ++ wc->tspans[0]->span.chans[z]->readchunk[x] = tmp >> 24; ++ } ++ if (has_e1_span(wc)) { ++ if (wc->e1recover > 0) ++ wc->e1recover--; ++ tmp = readchunk[0]; ++ if (wc->numspans == 4) { ++ e1_check(wc, 3, (tmp & 0x7f)); ++ e1_check(wc, 2, (tmp & 0x7f00) >> 8); ++ } ++ e1_check(wc, 1, (tmp & 0x7f0000) >> 16); ++ e1_check(wc, 0, (tmp & 0x7f000000) >> 24); ++ for (z=24;z<31;z++) { ++ /* Only E1 channels now */ ++ tmp = readchunk[z+1]; ++ if (wc->numspans == 4) { ++ if (wc->tspans[3]->span.channels > 24) ++ wc->tspans[3]->span.chans[z]->readchunk[x] = tmp & 0xff; ++ if (wc->tspans[2]->span.channels > 24) ++ wc->tspans[2]->span.chans[z]->readchunk[x] = (tmp & 0xff00) >> 8; ++ } ++ if (wc->tspans[1]->span.channels > 24) ++ wc->tspans[1]->span.chans[z]->readchunk[x] = (tmp & 0xff0000) >> 16; ++ if (wc->tspans[0]->span.channels > 24) ++ wc->tspans[0]->span.chans[z]->readchunk[x] = tmp >> 24; ++ } ++ } ++ /* Advance pointer by 4 TDM frame lengths */ ++ readchunk += 32; ++ } ++ for (x=0;xnumspans;x++) { ++ if (wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) { ++ for (y=0;ytspans[x]->span.channels;y++) { ++ /* Echo cancel double buffered data */ ++ dahdi_ec_chunk(wc->tspans[x]->span.chans[y], ++ wc->tspans[x]->span.chans[y]->readchunk, ++ wc->tspans[x]->ec_chunk2[y]); ++ memcpy(wc->tspans[x]->ec_chunk2[y],wc->tspans[x]->ec_chunk1[y], ++ DAHDI_CHUNKSIZE); ++ memcpy(wc->tspans[x]->ec_chunk1[y], ++ wc->tspans[x]->span.chans[y]->writechunk, ++ DAHDI_CHUNKSIZE); ++ } ++ _dahdi_receive(&wc->tspans[x]->span); ++ } ++ } ++} ++#endif ++ ++#if (DAHDI_CHUNKSIZE != 8) ++#error Sorry, nextgen does not support chunksize != 8 ++#endif ++ ++static void __receive_span(struct t4_span *ts) ++{ ++#ifdef VPM_SUPPORT ++ int y; ++ unsigned long merged; ++ merged = ts->dtmfactive & ts->dtmfmutemask; ++ if (merged) { ++ for (y=0;yspan.channels;y++) { ++ /* Mute any DTMFs which are supposed to be muted */ ++ if (test_bit(y, &merged)) { ++ memset(ts->span.chans[y]->readchunk, DAHDI_XLAW(0, ts->span.chans[y]), DAHDI_CHUNKSIZE); ++ } ++ } ++ } ++#endif ++ _dahdi_ec_span(&ts->span); ++ _dahdi_receive(&ts->span); ++} ++ ++static inline void __transmit_span(struct t4_span *ts) ++{ ++ _dahdi_transmit(&ts->span); ++} ++ ++static void t4_prep_gen2(struct t4 *wc) ++{ ++ int x; ++ for (x=0;xnumspans;x++) { ++ if (wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) { ++ __receive_span(wc->tspans[x]); ++ __transmit_span(wc->tspans[x]); ++ } ++ } ++} ++ ++#ifdef SUPPORT_GEN1 ++static void t4_transmitprep(struct t4 *wc, int irq) ++{ ++ u32 *writechunk; ++ int x, y, z; ++ unsigned int tmp; ++ int offset = 0; ++ if (!has_e1_span(wc)) ++ offset = 4; ++ if (irq & 1) { ++ /* First part */ ++ writechunk = wc->writechunk + 1; ++ } else { ++ writechunk = wc->writechunk + DAHDI_CHUNKSIZE * 32 + 1; ++ } ++ for (y=0;ynumspans;y++) { ++ if (wc->tspans[y]->span.flags & DAHDI_FLAG_RUNNING) ++ _dahdi_transmit(&wc->tspans[y]->span); ++ } ++ ++ for (x=0;xtspans[3]->span.chans[z]->writechunk[x]) | ++ (wc->tspans[2]->span.chans[z]->writechunk[x] << 8) | ++ (wc->tspans[1]->span.chans[z]->writechunk[x] << 16) | ++ (wc->tspans[0]->span.chans[z]->writechunk[x] << 24); ++ writechunk[z+offset] = tmp; ++ } ++ if (has_e1_span(wc)) { ++ for (z=24;z<31;z++) { ++ /* Only E1 channels now */ ++ tmp = 0; ++ if (wc->numspans == 4) { ++ if (wc->tspans[3]->span.channels > 24) ++ tmp |= wc->tspans[3]->span.chans[z]->writechunk[x]; ++ if (wc->tspans[2]->span.channels > 24) ++ tmp |= (wc->tspans[2]->span.chans[z]->writechunk[x] << 8); ++ } ++ if (wc->tspans[1]->span.channels > 24) ++ tmp |= (wc->tspans[1]->span.chans[z]->writechunk[x] << 16); ++ if (wc->tspans[0]->span.channels > 24) ++ tmp |= (wc->tspans[0]->span.chans[z]->writechunk[x] << 24); ++ writechunk[z] = tmp; ++ } ++ } ++ /* Advance pointer by 4 TDM frame lengths */ ++ writechunk += 32; ++ } ++ ++} ++#endif ++ ++static void t4_dahdi_rbsbits(struct dahdi_chan *const chan, int rxs) ++{ ++ if ((debug & DEBUG_RBS) && printk_ratelimit()) { ++ const struct t4_span *tspan = container_of(chan->span, ++ struct t4_span, ++ span); ++ const struct t4 *const wc = tspan->owner; ++ dev_notice(&wc->dev->dev, "Detected sigbits change on " \ ++ "channel %s to %04x\n", chan->name, rxs); ++ } ++ dahdi_rbsbits(chan, rxs); ++} ++ ++static void t4_check_sigbits(struct t4 *wc, int span) ++{ ++ int a,i,rxs; ++ struct t4_span *ts = wc->tspans[span]; ++ ++ if (debug & DEBUG_RBS) ++ dev_notice(&wc->dev->dev, "Checking sigbits on span %d\n", ++ span + 1); ++ ++ if (E1 == ts->linemode) { ++ for (i = 0; i < 15; i++) { ++ a = t4_framer_in(wc, span, 0x71 + i); ++ /* Get high channel in low bits */ ++ rxs = (a & 0xf); ++ if (!(ts->span.chans[i+16]->sig & DAHDI_SIG_CLEAR)) { ++ if (ts->span.chans[i+16]->rxsig != rxs) ++ t4_dahdi_rbsbits(ts->span.chans[i+16], rxs); ++ } ++ rxs = (a >> 4) & 0xf; ++ if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { ++ if (ts->span.chans[i]->rxsig != rxs) ++ t4_dahdi_rbsbits(ts->span.chans[i], rxs); ++ } ++ } ++ } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) { ++ for (i = 0; i < 24; i+=4) { ++ a = t4_framer_in(wc, span, 0x70 + (i>>2)); ++ /* Get high channel in low bits */ ++ rxs = (a & 0x3) << 2; ++ if (!(ts->span.chans[i+3]->sig & DAHDI_SIG_CLEAR)) { ++ if (ts->span.chans[i+3]->rxsig != rxs) ++ t4_dahdi_rbsbits(ts->span.chans[i+3], rxs); ++ } ++ rxs = (a & 0xc); ++ if (!(ts->span.chans[i+2]->sig & DAHDI_SIG_CLEAR)) { ++ if (ts->span.chans[i+2]->rxsig != rxs) ++ t4_dahdi_rbsbits(ts->span.chans[i+2], rxs); ++ } ++ rxs = (a >> 2) & 0xc; ++ if (!(ts->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) { ++ if (ts->span.chans[i+1]->rxsig != rxs) ++ t4_dahdi_rbsbits(ts->span.chans[i+1], rxs); ++ } ++ rxs = (a >> 4) & 0xc; ++ if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { ++ if (ts->span.chans[i]->rxsig != rxs) ++ t4_dahdi_rbsbits(ts->span.chans[i], rxs); ++ } ++ } ++ } else { ++ for (i = 0; i < 24; i+=2) { ++ a = t4_framer_in(wc, span, 0x70 + (i>>1)); ++ /* Get high channel in low bits */ ++ rxs = (a & 0xf); ++ if (!(ts->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) { ++ /* XXX Not really reset on every trans! XXX */ ++ if (ts->span.chans[i+1]->rxsig != rxs) { ++ t4_dahdi_rbsbits(ts->span.chans[i+1], rxs); ++ } ++ } ++ rxs = (a >> 4) & 0xf; ++ if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { ++ /* XXX Not really reset on every trans! XXX */ ++ if (ts->span.chans[i]->rxsig != rxs) { ++ t4_dahdi_rbsbits(ts->span.chans[i], rxs); ++ } ++ } ++ } ++ } ++} ++ ++/* Must be called from within hardirq context. */ ++static void t4_check_alarms(struct t4 *wc, int span) ++{ ++ unsigned char c, d, e; ++ int alarms; ++ int x,j; ++ struct t4_span *ts = wc->tspans[span]; ++ ++ if (time_before(jiffies, ts->alarmcheck_time)) ++ return; ++ ++ if (!(ts->span.flags & DAHDI_FLAG_RUNNING)) ++ return; ++ ++ spin_lock(&wc->reglock); ++ ++ c = __t4_framer_in(wc, span, 0x4c); ++ d = __t4_framer_in(wc, span, 0x4d); ++ ++ /* Assume no alarms */ ++ alarms = 0; ++ ++ /* And consider only carrier alarms */ ++ ts->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN); ++ ++ if (E1 == ts->linemode) { ++ if (c & 0x04) { ++ /* No multiframe found, force RAI high after 400ms only if ++ we haven't found a multiframe since last loss ++ of frame */ ++ if (!(ts->spanflags & FLAG_NMF)) { ++ __t4_framer_out(wc, span, 0x20, 0x9f | 0x20); /* LIM0: Force RAI High */ ++ ts->spanflags |= FLAG_NMF; ++ dev_notice(&wc->dev->dev, ++ "Lost crc4-multiframe alignment\n"); ++ } ++ __t4_framer_out(wc, span, 0x1e, 0xc3); /* Reset to CRC4 mode */ ++ __t4_framer_out(wc, span, 0x1c, 0xf2); /* Force Resync */ ++ __t4_framer_out(wc, span, 0x1c, 0xf0); /* Force Resync */ ++ } else if (!(c & 0x02)) { ++ if ((ts->spanflags & FLAG_NMF)) { ++ __t4_framer_out(wc, span, 0x20, 0x9f); /* LIM0: Clear forced RAI */ ++ ts->spanflags &= ~FLAG_NMF; ++ dev_notice(&wc->dev->dev, ++ "Obtained crc4-multiframe alignment\n"); ++ } ++ } ++ } else { ++ /* Detect loopup code if we're not sending one */ ++ if ((!ts->span.mainttimer) && (d & 0x08)) { ++ /* Loop-up code detected */ ++ if ((ts->loopupcnt++ > 80) && (ts->span.maintstat != DAHDI_MAINT_REMOTELOOP)) { ++ dev_notice(&wc->dev->dev, ++ "span %d: Loopup detected,"\ ++ " enabling remote loop\n", ++ span+1); ++ __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */ ++ __t4_framer_out(wc, span, 0x37, 0xf6 ); /* LIM1: Enable remote loop */ ++ ts->span.maintstat = DAHDI_MAINT_REMOTELOOP; ++ } ++ } else ++ ts->loopupcnt = 0; ++ /* Same for loopdown code */ ++ if ((!ts->span.mainttimer) && (d & 0x10)) { ++ /* Loop-down code detected */ ++ if ((ts->loopdowncnt++ > 80) && (ts->span.maintstat == DAHDI_MAINT_REMOTELOOP)) { ++ dev_notice(&wc->dev->dev, ++ "span %d: Loopdown detected,"\ ++ " disabling remote loop\n", ++ span+1); ++ __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */ ++ __t4_framer_out(wc, span, 0x37, 0xf0 ); /* LIM1: Disable remote loop */ ++ ts->span.maintstat = DAHDI_MAINT_NONE; ++ } ++ } else ++ ts->loopdowncnt = 0; ++ } ++ ++ if (ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { ++ for (x=0,j=0;x < ts->span.channels;x++) ++ if ((ts->span.chans[x]->flags & DAHDI_FLAG_OPEN) || ++ dahdi_have_netdev(ts->span.chans[x])) ++ j++; ++ if (!j) ++ alarms |= DAHDI_ALARM_NOTOPEN; ++ } ++ ++ /* Loss of Frame Alignment */ ++ if (c & 0x20) { ++ if (!ts->alarm_time) { ++ if (unlikely(debug)) { ++ /* starting to debounce LOF/LFA */ ++ dev_info(&wc->dev->dev, "wct%dxxp: LOF/LFA " ++ "detected on span %d but debouncing " ++ "for %d ms\n", wc->numspans, span + 1, ++ alarmdebounce); ++ } ++ ts->alarm_time = jiffies + ++ msecs_to_jiffies(alarmdebounce); ++ } else if (time_after(jiffies, ts->alarm_time)) { ++ /* Disable Slip Interrupts */ ++ e = __t4_framer_in(wc, span, 0x17); ++ __t4_framer_out(wc, span, 0x17, (e|0x03)); ++ ++ alarms |= DAHDI_ALARM_RED; ++ } ++ } else { ++ ts->alarm_time = 0; ++ } ++ ++ /* Loss of Signal */ ++ if (c & 0x80) { ++ if (!ts->losalarm_time) { ++ if (unlikely(debug)) { ++ /* starting to debounce LOS */ ++ dev_info(&wc->dev->dev, "wct%dxxp: LOS " ++ "detected on span %d but debouncing " ++ "for %d ms\n", wc->numspans, ++ span + 1, losalarmdebounce); ++ } ++ ts->losalarm_time = jiffies + ++ msecs_to_jiffies(losalarmdebounce); ++ } else if (time_after(jiffies, ts->losalarm_time)) { ++ /* Disable Slip Interrupts */ ++ e = __t4_framer_in(wc, span, 0x17); ++ __t4_framer_out(wc, span, 0x17, (e|0x03)); ++ ++ alarms |= DAHDI_ALARM_RED; ++ } ++ } else { ++ ts->losalarm_time = 0; ++ } ++ ++ /* Alarm Indication Signal */ ++ if (c & 0x40) { ++ if (!ts->aisalarm_time) { ++ if (unlikely(debug)) { ++ /* starting to debounce AIS */ ++ dev_info(&wc->dev->dev, "wct%dxxp: AIS " ++ "detected on span %d but debouncing " ++ "for %d ms\n", wc->numspans, ++ span + 1, aisalarmdebounce); ++ } ++ ts->aisalarm_time = jiffies + ++ msecs_to_jiffies(aisalarmdebounce); ++ } else if (time_after(jiffies, ts->aisalarm_time)) { ++ alarms |= DAHDI_ALARM_BLUE; ++ } ++ } else { ++ ts->aisalarm_time = 0; ++ } ++ ++ /* Add detailed alarm status information to a red alarm state */ ++ if (alarms & DAHDI_ALARM_RED) { ++ if (c & FRS0_LOS) ++ alarms |= DAHDI_ALARM_LOS; ++ if (c & FRS0_LFA) ++ alarms |= DAHDI_ALARM_LFA; ++ if (c & FRS0_LMFA) ++ alarms |= DAHDI_ALARM_LMFA; ++ } ++ ++ if (unlikely(debug)) { ++ /* Check to ensure the xmit line isn't shorted */ ++ if (unlikely(d & FRS1_XLS)) { ++ dev_info(&wc->dev->dev, ++ "Detected a possible hardware malfunction"\ ++ " this card may need servicing\n"); ++ } ++ } ++ ++ if (((!ts->span.alarms) && alarms) || ++ (ts->span.alarms && (!alarms))) ++ set_bit(T4_CHECK_TIMING, &wc->checkflag); ++ ++ /* Keep track of recovering */ ++ if ((!alarms) && ts->span.alarms) ++ ts->alarmtimer = DAHDI_ALARMSETTLE_TIME; ++ if (ts->alarmtimer) ++ alarms |= DAHDI_ALARM_RECOVER; ++ ++ /* If receiving alarms, go into Yellow alarm state */ ++ if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) { ++ /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ ++ unsigned char fmr4; ++ fmr4 = __t4_framer_in(wc, span, 0x20); ++ __t4_framer_out(wc, span, 0x20, fmr4 | 0x20); ++ dev_info(&wc->dev->dev, "Setting yellow alarm span %d\n", ++ span+1); ++ ts->spanflags |= FLAG_SENDINGYELLOW; ++ } else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) { ++ unsigned char fmr4; ++ /* We manually do yellow alarm to handle RECOVER */ ++ fmr4 = __t4_framer_in(wc, span, 0x20); ++ __t4_framer_out(wc, span, 0x20, fmr4 & ~0x20); ++ dev_info(&wc->dev->dev, "Clearing yellow alarm span %d\n", ++ span+1); ++ ++ /* Re-enable timing slip interrupts */ ++ e = __t4_framer_in(wc, span, 0x17); ++ ++ __t4_framer_out(wc, span, 0x17, (e & ~(0x03))); ++ ++ ts->spanflags &= ~FLAG_SENDINGYELLOW; ++ } ++ ++ /* Re-check the timing source when we enter/leave alarm, not withstanding ++ yellow alarm */ ++ if (c & 0x10) { /* receiving yellow (RAI) */ ++ if (!ts->yelalarm_time) { ++ if (unlikely(debug)) { ++ /* starting to debounce AIS */ ++ dev_info(&wc->dev->dev, "wct%dxxp: yellow " ++ "(RAI) detected on span %d but " ++ "debouncing for %d ms\n", ++ wc->numspans, span + 1, ++ yelalarmdebounce); ++ } ++ ts->yelalarm_time = jiffies + ++ msecs_to_jiffies(yelalarmdebounce); ++ } else if (time_after(jiffies, ts->yelalarm_time)) { ++ alarms |= DAHDI_ALARM_YELLOW; ++ } ++ } else { ++ ts->yelalarm_time = 0; ++ } ++ ++ if (alarms) ++ ts->alarmcheck_time = jiffies + msecs_to_jiffies(100); ++ else ++ ts->alarmcheck_time = jiffies + msecs_to_jiffies(50); ++ ++ if (ts->span.mainttimer || ts->span.maintstat) ++ alarms |= DAHDI_ALARM_LOOPBACK; ++ ts->span.alarms = alarms; ++ ++ spin_unlock(&wc->reglock); ++ dahdi_alarm_notify(&ts->span); ++} ++ ++static void t4_do_counters(struct t4 *wc) ++{ ++ int span; ++ for (span = 0; span < wc->numspans; span++) { ++ struct t4_span *ts = wc->tspans[span]; ++ ++ spin_lock(&wc->reglock); ++ if (ts->alarmtimer && (0 == (--ts->alarmtimer))) ++ ts->span.alarms &= ~(DAHDI_ALARM_RECOVER); ++ spin_unlock(&wc->reglock); ++ ++ t4_check_alarms(wc, span); ++ } ++} ++ ++static inline void __handle_leds(struct t4 *wc) ++{ ++ int x; ++ ++ wc->blinktimer++; ++ for (x=0;xnumspans;x++) { ++ struct t4_span *ts = wc->tspans[x]; ++ if (ts->span.flags & DAHDI_FLAG_RUNNING) { ++ if ((ts->span.alarms & (DAHDI_ALARM_RED | ++ DAHDI_ALARM_BLUE)) || ++ ts->losalarm_time) { ++#ifdef FANCY_ALARM ++ if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { ++ __t4_set_led(wc, x, WC_RED); ++ } ++ if (wc->blinktimer == 0xf) { ++ __t4_set_led(wc, x, WC_OFF); ++ } ++#else ++ if (wc->blinktimer == 160) { ++ __t4_set_led(wc, x, WC_RED); ++ } else if (wc->blinktimer == 480) { ++ __t4_set_led(wc, x, WC_OFF); ++ } ++#endif ++ } else if (ts->span.alarms & DAHDI_ALARM_YELLOW) { ++ /* Yellow Alarm */ ++ __t4_set_led(wc, x, WC_YELLOW); ++ } else if (ts->span.mainttimer || ts->span.maintstat) { ++#ifdef FANCY_ALARM ++ if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { ++ __t4_set_led(wc, x, WC_GREEN); ++ } ++ if (wc->blinktimer == 0xf) { ++ __t4_set_led(wc, x, WC_OFF); ++ } ++#else ++ if (wc->blinktimer == 160) { ++ __t4_set_led(wc, x, WC_GREEN); ++ } else if (wc->blinktimer == 480) { ++ __t4_set_led(wc, x, WC_OFF); ++ } ++#endif ++ } else { ++ /* No Alarm */ ++ __t4_set_led(wc, x, WC_GREEN); ++ } ++ } else ++ __t4_set_led(wc, x, WC_OFF); ++ ++ } ++#ifdef FANCY_ALARM ++ if (wc->blinktimer == 0xf) { ++ wc->blinktimer = -1; ++ wc->alarmpos++; ++ if (wc->alarmpos >= ARRAY_SIZE(altab)) ++ wc->alarmpos = 0; ++ } ++#else ++ if (wc->blinktimer == 480) ++ wc->blinktimer = 0; ++#endif ++} ++ ++static inline void t4_framer_interrupt(struct t4 *wc, int span) ++{ ++ /* Check interrupts for a given span */ ++ unsigned char gis, isr0, isr1, isr2, isr3, isr4; ++ int readsize = -1; ++ struct t4_span *ts = wc->tspans[span]; ++ struct dahdi_chan *sigchan; ++ unsigned long flags; ++ bool recheck_sigbits = false; ++ ++ ++ /* 1st gen cards isn't used interrupts */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ gis = __t4_framer_in(wc, span, FRMR_GIS); ++ isr0 = (gis & FRMR_GIS_ISR0) ? __t4_framer_in(wc, span, FRMR_ISR0) : 0; ++ isr1 = (gis & FRMR_GIS_ISR1) ? __t4_framer_in(wc, span, FRMR_ISR1) : 0; ++ isr2 = (gis & FRMR_GIS_ISR2) ? __t4_framer_in(wc, span, FRMR_ISR2) : 0; ++ isr3 = (gis & FRMR_GIS_ISR3) ? __t4_framer_in(wc, span, FRMR_ISR3) : 0; ++ isr4 = (gis & FRMR_GIS_ISR4) ? __t4_framer_in(wc, span, FRMR_ISR4) : 0; ++ ++ if ((debug & DEBUG_FRAMER) && !(isr3 & ISR3_SEC)) { ++ dev_info(&wc->dev->dev, "gis: %02x, isr0: %02x, isr1: %02x, "\ ++ "isr2: %02x, isr3: %08x, isr4: %02x, intcount=%u\n", ++ gis, isr0, isr1, isr2, isr3, isr4, wc->intcount); ++ } ++ ++ /* Collect performance counters once per second */ ++ if (isr3 & ISR3_SEC) { ++ ts->span.count.fe += __t4_framer_in(wc, span, FECL_T); ++ ts->span.count.crc4 += __t4_framer_in(wc, span, CEC1L_T); ++ ts->span.count.cv += __t4_framer_in(wc, span, CVCL_T); ++ ts->span.count.ebit += __t4_framer_in(wc, span, EBCL_T); ++ ts->span.count.be += __t4_framer_in(wc, span, BECL_T); ++ ts->span.count.prbs = __t4_framer_in(wc, span, FRS1_T); ++ if (DAHDI_RXSIG_INITIAL == ts->span.chans[0]->rxhooksig) ++ recheck_sigbits = true; ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* Collect errored second counter once per second */ ++ if (isr3 & ISR3_ES) { ++ ts->span.count.errsec += 1; ++ } ++ ++ if (isr0 & 0x08 || recheck_sigbits) ++ t4_check_sigbits(wc, span); ++ ++ if (E1 == ts->linemode) { ++ /* E1 checks */ ++ if ((isr3 & 0x38) || isr2 || isr1) ++ t4_check_alarms(wc, span); ++ } else { ++ /* T1 checks */ ++ if (isr2 || (isr3 & 0x08)) ++ t4_check_alarms(wc, span); ++ } ++ if (!ts->span.alarms) { ++ if ((isr3 & 0x3) || (isr4 & 0xc0)) ++ ts->span.count.timingslips++; ++ ++ if (debug & DEBUG_MAIN) { ++ if (isr3 & 0x02) ++ dev_notice(&wc->dev->dev, "TE%d10P: RECEIVE " ++ "slip NEGATIVE on span %d\n", ++ wc->numspans, span + 1); ++ if (isr3 & 0x01) ++ dev_notice(&wc->dev->dev, "TE%d10P: RECEIVE " ++ "slip POSITIVE on span %d\n", ++ wc->numspans, span + 1); ++ if (isr4 & 0x80) ++ dev_notice(&wc->dev->dev, "TE%dXXP: TRANSMIT " ++ "slip POSITIVE on span %d\n", ++ wc->numspans, span + 1); ++ if (isr4 & 0x40) ++ dev_notice(&wc->dev->dev, "TE%d10P: TRANSMIT " ++ "slip NEGATIVE on span %d\n", ++ wc->numspans, span + 1); ++ } ++ } else ++ ts->span.count.timingslips = 0; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ /* HDLC controller checks - receive side */ ++ if (!ts->sigchan) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return; ++ } ++ ++ sigchan = ts->sigchan; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (isr0 & FRMR_ISR0_RME) { ++ readsize = (t4_framer_in(wc, span, FRMR_RBCH) << 8) | t4_framer_in(wc, span, FRMR_RBCL); ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Received data length is %d " ++ "(%d)\n", readsize, ++ readsize & FRMR_RBCL_MAX_SIZE); ++ /* RPF isn't set on last part of frame */ ++ if ((readsize > 0) && ((readsize &= FRMR_RBCL_MAX_SIZE) == 0)) ++ readsize = FRMR_RBCL_MAX_SIZE + 1; ++ } else if (isr0 & FRMR_ISR0_RPF) ++ readsize = FRMR_RBCL_MAX_SIZE + 1; ++ ++ if (readsize > 0) { ++ int i; ++ unsigned char readbuf[FRMR_RBCL_MAX_SIZE + 1]; ++ ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Framer %d: Got RPF/RME! " ++ "readsize is %d\n", sigchan->span->offset, ++ readsize); ++ ++ for (i = 0; i < readsize; i++) ++ readbuf[i] = t4_framer_in(wc, span, FRMR_RXFIFO); ++ ++ /* Tell the framer to clear the RFIFO */ ++ t4_framer_cmd_wait(wc, span, FRMR_CMDR_RMC); ++ ++ if (debug & DEBUG_FRAMER) { ++ dev_notice(&wc->dev->dev, "RX("); ++ for (i = 0; i < readsize; i++) ++ dev_notice(&wc->dev->dev, "%s%02x", ++ (i ? " " : ""), readbuf[i]); ++ dev_notice(&wc->dev->dev, ")\n"); ++ } ++ ++ if (isr0 & FRMR_ISR0_RME) { ++ /* Do checks for HDLC problems */ ++ unsigned char rsis = readbuf[readsize-1]; ++ unsigned char rsis_reg = t4_framer_in(wc, span, FRMR_RSIS); ++ ++ ++ts->frames_in; ++ if ((debug & DEBUG_FRAMER) && !(ts->frames_in & 0x0f)) ++ dev_notice(&wc->dev->dev, "Received %d frames " ++ "on span %d\n", ts->frames_in, span); ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Received HDLC frame" ++ " %d. RSIS = 0x%x (%x)\n", ++ ts->frames_in, rsis, rsis_reg); ++ if (!(rsis & FRMR_RSIS_CRC16)) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "CRC check " ++ "failed %d\n", span); ++ dahdi_hdlc_abort(sigchan, DAHDI_EVENT_BADFCS); ++ } else if (rsis & FRMR_RSIS_RAB) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "ABORT of " ++ "current frame due to " ++ "overflow %d\n", span); ++ dahdi_hdlc_abort(sigchan, DAHDI_EVENT_ABORT); ++ } else if (rsis & FRMR_RSIS_RDO) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "HDLC " ++ "overflow occured %d\n", ++ span); ++ dahdi_hdlc_abort(sigchan, DAHDI_EVENT_OVERRUN); ++ } else if (!(rsis & FRMR_RSIS_VFR)) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Valid Frame" ++ " check failed on span %d\n", ++ span); ++ dahdi_hdlc_abort(sigchan, DAHDI_EVENT_ABORT); ++ } else { ++ dahdi_hdlc_putbuf(sigchan, readbuf, readsize - 1); ++ dahdi_hdlc_finish(sigchan); ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Received " ++ "valid HDLC frame on span %d" ++ "\n", span); ++ } ++ } else if (isr0 & FRMR_ISR0_RPF) ++ dahdi_hdlc_putbuf(sigchan, readbuf, readsize); ++ } ++ ++ /* Transmit side */ ++ if (isr1 & FRMR_ISR1_XDU) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "XDU: Resetting signal " ++ "controller!\n"); ++ t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); ++ } else if (isr1 & FRMR_ISR1_XPR) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Sigchan %d is %p\n", ++ sigchan->chanpos, sigchan); ++ ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "Framer %d: Got XPR!\n", ++ sigchan->span->offset); ++ t4_hdlc_xmit_fifo(wc, span, ts); ++ } ++ ++ if (isr1 & FRMR_ISR1_ALLS) { ++ if (debug & DEBUG_FRAMER) ++ dev_notice(&wc->dev->dev, "ALLS received\n"); ++ } ++} ++ ++#ifdef SUPPORT_GEN1 ++static irqreturn_t _t4_interrupt(int irq, void *dev_id) ++{ ++ struct t4 *wc = dev_id; ++ unsigned long flags; ++ int x; ++ ++ unsigned int status; ++ unsigned int status2; ++ ++ /* Make sure it's really for us */ ++ status = __t4_pci_in(wc, WC_INTR); ++ ++ /* Process framer interrupts */ ++ status2 = t4_framer_in(wc, 0, FRMR_CIS); ++ if (status2 & 0x0f) { ++ for (x = 0; x < wc->numspans; ++x) { ++ if (status2 & (1 << x)) ++ t4_framer_interrupt(wc, x); ++ } ++ } ++ ++ /* Ignore if it's not for us */ ++ if (!status) ++ return IRQ_NONE; ++ ++ __t4_pci_out(wc, WC_INTR, 0); ++ ++ if (!wc->spansstarted) { ++ dev_notice(&wc->dev->dev, "Not prepped yet!\n"); ++ return IRQ_NONE; ++ } ++ ++ wc->intcount++; ++ ++ if (status & 0x3) { ++ t4_receiveprep(wc, status); ++ t4_transmitprep(wc, status); ++ } ++ ++ t4_do_counters(wc); ++ ++ x = wc->intcount & 15 /* 63 */; ++ switch(x) { ++ case 0: ++ case 1: ++ case 2: ++ case 3: ++ t4_check_sigbits(wc, x); ++ break; ++ case 4: ++ case 5: ++ case 6: ++ case 7: ++ t4_check_alarms(wc, x - 4); ++ break; ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ __handle_leds(wc); ++ ++ if (test_bit(T4_CHECK_TIMING, &wc->checkflag)) ++ __t4_set_timing_source_auto(wc); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return IRQ_RETVAL(1); ++} ++ ++static irqreturn_t t4_interrupt(int irq, void *dev_id) ++{ ++ irqreturn_t ret; ++ unsigned long flags; ++ local_irq_save(flags); ++ ret = _t4_interrupt(irq, dev_id); ++ local_irq_restore(flags); ++ return ret; ++} ++#endif ++ ++static int t4_allocate_buffers(struct t4 *wc, int numbufs, ++ void **oldalloc, dma_addr_t *oldwritedma) ++{ ++ void *alloc; ++ dma_addr_t writedma; ++ ++ /* 32 channels, Double-buffer, Read/Write, 4 spans */ ++ alloc = pci_alloc_consistent(wc->dev, numbufs * T4_BASE_SIZE(wc) * 2, ++ &writedma); ++ ++ if (!alloc) { ++ dev_notice(&wc->dev->dev, "wct%dxxp: Unable to allocate " ++ "DMA-able memory\n", wc->numspans); ++ return -ENOMEM; ++ } ++ ++ if (oldwritedma) ++ *oldwritedma = wc->writedma; ++ if (oldalloc) ++ *oldalloc = wc->writechunk; ++ ++ wc->writechunk = alloc; ++ wc->writedma = writedma; ++ ++ /* Read is after the whole write piece (in words) */ ++ wc->readchunk = wc->writechunk + (T4_BASE_SIZE(wc) * numbufs) / 4; ++ ++ /* Same thing but in bytes... */ ++ wc->readdma = wc->writedma + (T4_BASE_SIZE(wc) * numbufs); ++ ++ wc->numbufs = numbufs; ++ ++ /* Initialize Write/Buffers to all blank data */ ++ memset(wc->writechunk, 0x00, T4_BASE_SIZE(wc) * numbufs); ++ memset(wc->readchunk, 0xff, T4_BASE_SIZE(wc) * numbufs); ++ ++ if (debug) { ++ dev_notice(&wc->dev->dev, "DMA memory base of size %d at " \ ++ "%p. Read: %p and Write %p\n", ++ numbufs * T4_BASE_SIZE(wc) * 2, wc->writechunk, ++ wc->readchunk, wc->writechunk); ++ } ++ ++ return 0; ++} ++ ++static void t4_increase_latency(struct t4 *wc, int newlatency) ++{ ++ unsigned long flags; ++ void *oldalloc; ++ dma_addr_t oldaddr; ++ int oldbufs; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ __t4_pci_out(wc, WC_DMACTRL, 0x00000000); ++ /* Acknowledge any pending interrupts */ ++ __t4_pci_out(wc, WC_INTR, 0x00000000); ++ ++ __t4_pci_in(wc, WC_VERSION); ++ ++ oldbufs = wc->numbufs; ++ ++ if (t4_allocate_buffers(wc, newlatency, &oldalloc, &oldaddr)) { ++ dev_info(&wc->dev->dev, "Error allocating latency buffers for " ++ "latency of %d\n", newlatency); ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return; ++ } ++ ++ __t4_pci_out(wc, WC_RDADDR, wc->readdma); ++ __t4_pci_out(wc, WC_WRADDR, wc->writedma); ++ ++ __t4_pci_in(wc, WC_VERSION); ++ ++ __t4_pci_out(wc, 5, (ms_per_irq << 16) | newlatency); ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ ++ __t4_pci_in(wc, WC_VERSION); ++ ++ wc->rxident = 0; ++ wc->lastindex = 0; ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ pci_free_consistent(wc->dev, T4_BASE_SIZE(wc) * oldbufs * 2, ++ oldalloc, oldaddr); ++ ++ dev_info(&wc->dev->dev, "Increased latency to %d\n", newlatency); ++ ++} ++ ++static void t4_work_func(struct work_struct *work) ++{ ++ struct t4 *wc = container_of(work, struct t4, bh_work); ++ ++ if (test_bit(T4_CHANGE_LATENCY, &wc->checkflag)) { ++ if (wc->needed_latency != wc->numbufs) { ++ t4_increase_latency(wc, wc->needed_latency); ++ clear_bit(T4_CHANGE_LATENCY, &wc->checkflag); ++ } ++ } ++#ifdef VPM_SUPPORT ++ if (wc->vpm) { ++ if (test_and_clear_bit(T4_CHECK_VPM, &wc->checkflag)) { ++ /* How stupid is it that the octasic can't generate an ++ * interrupt when there's a tone, in spite of what ++ * their documentation says? */ ++ t4_check_vpm(wc); ++ } ++ } ++#endif ++} ++ ++static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id) ++{ ++ struct t4 *wc = dev_id; ++ unsigned int status; ++ unsigned char rxident, expected; ++ ++ /* Check this first in case we get a spurious interrupt */ ++ if (unlikely(test_bit(T4_STOP_DMA, &wc->checkflag))) { ++ /* Stop DMA cleanly if requested */ ++ wc->dmactrl = 0x0; ++ t4_pci_out(wc, WC_DMACTRL, 0x00000000); ++ /* Acknowledge any pending interrupts */ ++ t4_pci_out(wc, WC_INTR, 0x00000000); ++ spin_lock(&wc->reglock); ++ __t4_set_sclk_src(wc, WC_SELF, 0, 0); ++ spin_unlock(&wc->reglock); ++ return IRQ_RETVAL(1); ++ } ++ ++ /* Make sure it's really for us */ ++ status = __t4_pci_in(wc, WC_INTR); ++ ++ /* Ignore if it's not for us */ ++ if (!(status & 0x7)) { ++ return IRQ_NONE; ++ } ++ ++ if (unlikely(!wc->spansstarted)) { ++ dev_info(&wc->dev->dev, "Not prepped yet!\n"); ++ return IRQ_NONE; ++ } ++ ++ wc->intcount++; ++ if ((wc->devtype->flags & FLAG_5THGEN) && (status & 0x2)) { ++ rxident = (status >> 16) & 0x7f; ++ expected = (wc->rxident + ms_per_irq) % 128; ++ ++ if ((rxident != expected) && !test_bit(T4_IGNORE_LATENCY, &wc->checkflag)) { ++ int needed_latency; ++ int smallest_max; ++ ++ if (debug & DEBUG_MAIN) ++ dev_warn(&wc->dev->dev, "Missed interrupt. " ++ "Expected ident of %d and got ident " ++ "of %d\n", expected, rxident); ++ ++ if (test_bit(T4_IGNORE_LATENCY, &wc->checkflag)) { ++ dev_info(&wc->dev->dev, ++ "Should have ignored latency\n"); ++ } ++ if (rxident > wc->rxident) { ++ needed_latency = rxident - wc->rxident; ++ } else { ++ needed_latency = (128 - wc->rxident) + rxident; ++ } ++ ++ needed_latency += 1; ++ ++ smallest_max = (max_latency >= GEN5_MAX_LATENCY) ? GEN5_MAX_LATENCY : max_latency; ++ ++ if (needed_latency > smallest_max) { ++ dev_info(&wc->dev->dev, "Truncating latency " ++ "request to %d instead of %d\n", ++ smallest_max, needed_latency); ++ needed_latency = smallest_max; ++ } ++ ++ if (needed_latency > wc->numbufs) { ++ dev_info(&wc->dev->dev, "Need to increase " ++ "latency. Estimated latency should " ++ "be %d\n", needed_latency); ++ wc->ddev->irqmisses++; ++ wc->needed_latency = needed_latency; ++ __t4_pci_out(wc, WC_DMACTRL, 0x00000000); ++ set_bit(T4_CHANGE_LATENCY, &wc->checkflag); ++ goto out; ++ } ++ } ++ ++ wc->rxident = rxident; ++ } ++ ++#ifdef DEBUG ++ if (unlikely((wc->intcount < 20))) ++ dev_dbg(&wc->dev->dev, "2G: Got interrupt, status = %08x, " ++ "CIS = %04x\n", status, t4_framer_in(wc, 0, FRMR_CIS)); ++#endif ++ ++ if (likely(status & 0x2)) { ++ unsigned int reg5 = __t4_pci_in(wc, 5); ++ ++#ifdef DEBUG ++ if (wc->intcount < 20) ++ dev_info(&wc->dev->dev, "Reg 5 is %08x\n", reg5); ++#endif ++ ++ if (wc->devtype->flags & FLAG_5THGEN) { ++ unsigned int current_index = (reg5 >> 8) & 0x7f; ++ ++ while (((wc->lastindex + 1) % wc->numbufs) != current_index) { ++ wc->lastindex = (wc->lastindex + 1) % wc->numbufs; ++ setup_chunks(wc, wc->lastindex); ++ t4_prep_gen2(wc); ++ } ++ } else { ++ t4_prep_gen2(wc); ++ } ++ ++ t4_do_counters(wc); ++ spin_lock(&wc->reglock); ++ __handle_leds(wc); ++ spin_unlock(&wc->reglock); ++ ++ } ++ ++ if (unlikely(status & 0x1)) { ++ unsigned char cis; ++ ++ cis = t4_framer_in(wc, 0, FRMR_CIS); ++ if (cis & FRMR_CIS_GIS1) ++ t4_framer_interrupt(wc, 0); ++ if (cis & FRMR_CIS_GIS2) ++ t4_framer_interrupt(wc, 1); ++ if (cis & FRMR_CIS_GIS3) ++ t4_framer_interrupt(wc, 2); ++ if (cis & FRMR_CIS_GIS4) ++ t4_framer_interrupt(wc, 3); ++ ++ if (is_octal(wc)) { ++ if (cis & FRMR_CIS_GIS5) ++ t4_framer_interrupt(wc, 4); ++ if (cis & FRMR_CIS_GIS6) ++ t4_framer_interrupt(wc, 5); ++ if (cis & FRMR_CIS_GIS7) ++ t4_framer_interrupt(wc, 6); ++ if (cis & FRMR_CIS_GIS8) ++ t4_framer_interrupt(wc, 7); ++ } ++ } ++ ++#ifdef VPM_SUPPORT ++ if (wc->vpm && vpmdtmfsupport) { ++ /* How stupid is it that the octasic can't generate an ++ * interrupt when there's a tone, in spite of what their ++ * documentation says? */ ++ if (!(wc->intcount & 0xf)) ++ set_bit(T4_CHECK_VPM, &wc->checkflag); ++ } ++#endif ++ ++ spin_lock(&wc->reglock); ++ ++ if (unlikely(test_bit(T4_CHECK_TIMING, &wc->checkflag))) { ++ __t4_set_timing_source_auto(wc); ++ } ++ ++ spin_unlock(&wc->reglock); ++ ++out: ++ if (unlikely(test_bit(T4_CHANGE_LATENCY, &wc->checkflag) || test_bit(T4_CHECK_VPM, &wc->checkflag))) ++ schedule_work(&wc->bh_work); ++ ++ __t4_pci_out(wc, WC_INTR, 0); ++ return IRQ_RETVAL(1); ++} ++ ++static irqreturn_t t4_interrupt_gen2(int irq, void *dev_id) ++{ ++ irqreturn_t ret; ++ unsigned long flags; ++ local_irq_save(flags); ++ ret = _t4_interrupt_gen2(irq, dev_id); ++ local_irq_restore(flags); ++ return ret; ++} ++ ++#ifdef SUPPORT_GEN1 ++static int t4_reset_dma(struct t4 *wc) ++{ ++ /* Turn off DMA and such */ ++ wc->dmactrl = 0x0; ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ t4_pci_out(wc, WC_COUNT, 0); ++ t4_pci_out(wc, WC_RDADDR, 0); ++ t4_pci_out(wc, WC_WRADDR, 0); ++ t4_pci_out(wc, WC_INTR, 0); ++ /* Turn it all back on */ ++ t4_pci_out(wc, WC_RDADDR, wc->readdma); ++ t4_pci_out(wc, WC_WRADDR, wc->writedma); ++ t4_pci_out(wc, WC_COUNT, ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); ++ t4_pci_out(wc, WC_INTR, 0); ++#ifdef VPM_SUPPORT ++ wc->dmactrl = 0xc0000000 | (1 << 29) | ++ ((wc->vpm) ? T4_VPM_PRESENT : 0); ++#else ++ wc->dmactrl = 0xc0000000 | (1 << 29); ++#endif ++ if (noburst) ++ wc->dmactrl |= (1 << 26); ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ return 0; ++} ++#endif ++ ++#ifdef VPM_SUPPORT ++static void t4_vpm_init(struct t4 *wc) ++{ ++ int laws[8] = { 0, }; ++ int x; ++ unsigned int vpm_capacity; ++ struct firmware embedded_firmware; ++ const struct firmware *firmware = &embedded_firmware; ++#if !defined(HOTPLUG_FIRMWARE) ++ extern void _binary_dahdi_fw_oct6114_064_bin_size; ++ extern void _binary_dahdi_fw_oct6114_128_bin_size; ++ extern void _binary_dahdi_fw_oct6114_256_bin_size; ++ extern u8 _binary_dahdi_fw_oct6114_064_bin_start[]; ++ extern u8 _binary_dahdi_fw_oct6114_128_bin_start[]; ++ extern u8 _binary_dahdi_fw_oct6114_256_bin_start[]; ++#else ++ static const char oct064_firmware[] = "dahdi-fw-oct6114-064.bin"; ++ static const char oct128_firmware[] = "dahdi-fw-oct6114-128.bin"; ++ static const char oct256_firmware[] = "dahdi-fw-oct6114-256.bin"; ++#endif ++ ++ if (!vpmsupport) { ++ dev_info(&wc->dev->dev, "VPM450: Support Disabled\n"); ++ return; ++ } ++ ++ /* Turn on GPIO/DATA mux if supported */ ++ t4_gpio_setdir(wc, (1 << 24), (1 << 24)); ++ __t4_raw_oct_out(wc, 0x000a, 0x5678); ++ __t4_raw_oct_out(wc, 0x0004, 0x1234); ++ __t4_raw_oct_in(wc, 0x0004); ++ __t4_raw_oct_in(wc, 0x000a); ++ if (debug) ++ dev_notice(&wc->dev->dev, "OCT Result: %04x/%04x\n", ++ __t4_raw_oct_in(wc, 0x0004), ++ __t4_raw_oct_in(wc, 0x000a)); ++ if (__t4_raw_oct_in(wc, 0x0004) != 0x1234) { ++ dev_notice(&wc->dev->dev, "VPM450: Not Present\n"); ++ return; ++ } ++ ++ /* Setup alaw vs ulaw rules */ ++ for (x = 0;x < wc->numspans; x++) { ++ if (wc->tspans[x]->span.channels > 24) ++ laws[x] = 1; ++ } ++ ++ vpm_capacity = get_vpm450m_capacity(&wc->dev->dev); ++ if (vpm_capacity != wc->numspans * 32) { ++ dev_info(&wc->dev->dev, "Disabling VPMOCT%03d. TE%dXXP"\ ++ " requires a VPMOCT%03d", vpm_capacity, ++ wc->numspans, wc->numspans*32); ++ return; ++ } ++ ++ switch (vpm_capacity) { ++ case 64: ++#if defined(HOTPLUG_FIRMWARE) ++ if ((request_firmware(&firmware, oct064_firmware, &wc->dev->dev) != 0) || ++ !firmware) { ++ dev_notice(&wc->dev->dev, "VPM450: firmware %s not " ++ "available from userspace\n", oct064_firmware); ++ return; ++ } ++#else ++ embedded_firmware.data = _binary_dahdi_fw_oct6114_064_bin_start; ++ /* Yes... this is weird. objcopy gives us a symbol containing ++ the size of the firmware, not a pointer a variable containing ++ the size. The only way we can get the value of the symbol ++ is to take its address, so we define it as a pointer and ++ then cast that value to the proper type. ++ */ ++ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_064_bin_size; ++#endif ++ break; ++ case 128: ++#if defined(HOTPLUG_FIRMWARE) ++ if ((request_firmware(&firmware, oct128_firmware, &wc->dev->dev) != 0) || ++ !firmware) { ++ dev_notice(&wc->dev->dev, "VPM450: firmware %s not " ++ "available from userspace\n", oct128_firmware); ++ return; ++ } ++#else ++ embedded_firmware.data = _binary_dahdi_fw_oct6114_128_bin_start; ++ /* Yes... this is weird. objcopy gives us a symbol containing ++ the size of the firmware, not a pointer a variable containing ++ the size. The only way we can get the value of the symbol ++ is to take its address, so we define it as a pointer and ++ then cast that value to the proper type. ++ */ ++ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_128_bin_size; ++#endif ++ break; ++ case 256: ++#if defined(HOTPLUG_FIRMWARE) ++ if ((request_firmware(&firmware, oct256_firmware, &wc->dev->dev) != 0) || ++ !firmware) { ++ dev_notice(&wc->dev->dev, "VPM450: firmware %s not " ++ "available from userspace\n", oct256_firmware); ++ return; ++ } ++#else ++ embedded_firmware.data = _binary_dahdi_fw_oct6114_256_bin_start; ++ /* Yes... this is weird. objcopy gives us a symbol containing ++ the size of the firmware, not a pointer a variable containing ++ the size. The only way we can get the value of the symbol ++ is to take its address, so we define it as a pointer and ++ then cast that value to the proper type. ++ */ ++ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_256_bin_size; ++#endif ++ break; ++ default: ++ dev_notice(&wc->dev->dev, "Unsupported channel capacity found " ++ "on VPM module (%d).\n", vpm_capacity); ++ return; ++ } ++ ++ wc->vpm = init_vpm450m(&wc->dev->dev, laws, wc->numspans, firmware); ++ if (!wc->vpm) { ++ dev_notice(&wc->dev->dev, "VPM450: Failed to initialize\n"); ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ return; ++ } ++ ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ ++ if (vpmdtmfsupport == -1) { ++ dev_info(&wc->dev->dev, "VPM450: hardware DTMF disabled.\n"); ++ vpmdtmfsupport = 0; ++ } ++ ++ dev_info(&wc->dev->dev, "VPM450: Present and operational servicing %d " ++ "span(s)\n", wc->numspans); ++ ++} ++#endif /* VPM_SUPPORT */ ++ ++static void t4_tsi_reset(struct t4 *wc) ++{ ++ int x; ++ if (is_octal(wc)) { ++ for (x = 0; x < 256; x++) { ++ wc->dmactrl &= ~0x0001ffff; ++ wc->dmactrl |= (0x00004000 | ((x & 0x7f) << 7) | ((x >> 7) << 15)); ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ } ++ wc->dmactrl &= ~0x0001ffff; ++ } else { ++ for (x = 0; x < 128; x++) { ++ wc->dmactrl &= ~0x00007fff; ++ wc->dmactrl |= (0x00004000 | (x << 7)); ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ } ++ wc->dmactrl &= ~0x00007fff; ++ } ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++} ++ ++/* Note that channels here start from 1 */ ++static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan) ++{ ++ unsigned long flags; ++ int fromts, tots; ++ ++ fromts = (fromspan << 5) |(fromchan); ++ tots = (tospan << 5) | (tochan); ++ ++ if (!has_e1_span(wc)) { ++ fromts += 4; ++ tots += 4; ++ } ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (is_octal(wc)) { ++ int fromts_b = fromts & 0x7f; ++ int fromts_t = fromts >> 7; ++ int tots_b = tots & 0x7f; ++ int tots_t = tots >> 7; ++ ++ wc->dmactrl &= ~0x0001ffff; ++ wc->dmactrl |= ((fromts_t << 16) | (tots_t << 15) | 0x00004000 | (tots_b << 7) | (fromts_b)); ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ wc->dmactrl &= ~0x0001ffff; ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ } else { ++ wc->dmactrl &= ~0x00007fff; ++ wc->dmactrl |= (0x00004000 | (tots << 7) | (fromts)); ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ wc->dmactrl &= ~0x00007fff; ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan) ++{ ++ unsigned long flags; ++ int tots; ++ ++ tots = (tospan << 5) | (tochan); ++ ++ if (!has_e1_span(wc)) ++ tots += 4; ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (is_octal(wc)) { ++ int tots_b = tots & 0x7f; ++ int tots_t = tots >> 7; ++ ++ wc->dmactrl &= ~0x0001ffff; ++ wc->dmactrl |= ((tots_t << 15) | 0x00004000 | (tots_b << 7)); ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ if (debug & DEBUG_TSI) ++ dev_notice(&wc->dev->dev, "Sending '%08x\n", wc->dmactrl); ++ wc->dmactrl &= ~0x0001ffff; ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ } else { ++ wc->dmactrl &= ~0x00007fff; ++ wc->dmactrl |= (0x00004000 | (tots << 7)); ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ if (debug & DEBUG_TSI) ++ dev_notice(&wc->dev->dev, "Sending '%08x\n", wc->dmactrl); ++ wc->dmactrl &= ~0x00007fff; ++ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++#ifndef CONFIG_NOEXTENDED_RESET ++static void t4_extended_reset(struct t4 *wc) ++{ ++ unsigned int oldreg = t4_pci_in(wc, 0x4); ++ ++ udelay(1000); ++ ++ t4_pci_out(wc, 0x4, 0x42000000); ++ t4_pci_out(wc, 0xa, 0x42000000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00180000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00180000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00180000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00180000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00180000); ++ t4_pci_out(wc, 0xa, 0x00080000); ++ t4_pci_out(wc, 0xa, 0x00180000); ++ t4_pci_out(wc, 0x4, oldreg); ++ ++ udelay(1000); ++} ++#endif ++ ++#define SPI_CS (0) ++#define SPI_CLK (1) ++#define SPI_IO0 (2) ++#define SPI_IO1 (3) ++#define SPI_IO3 (4) ++#define SPI_IO2 (5) ++#define SPI_IN (0) ++#define SPI_OUT (1) ++#define ESPI_REG 13 ++ ++static void t8_clear_bit(struct t4 *wc, int whichb) ++{ ++ wc->st.wrreg &= ~(1 << whichb); ++} ++ ++static void t8_set_bit(struct t4 *wc, int whichb, int val) ++{ ++ t8_clear_bit(wc, whichb); ++ wc->st.wrreg |= (val << whichb); ++} ++ ++static int t8_get_bit(struct t4 *wc, int whichb) ++{ ++ return (wc->st.rdreg >> whichb) & 1; ++} ++ ++static void set_iodir(struct t4 *wc, int whichb, int dir) ++{ ++ whichb += 16; ++ t8_clear_bit(wc, whichb); ++ t8_set_bit(wc, whichb, dir); ++} ++ ++static void write_hwreg(struct t4 *wc) ++{ ++ t4_pci_out(wc, ESPI_REG, wc->st.wrreg); ++} ++ ++static void read_hwreg(struct t4 *wc) ++{ ++ wc->st.rdreg = t4_pci_in(wc, ESPI_REG); ++} ++ ++static void set_cs(struct t4 *wc, int state) ++{ ++ t8_set_bit(wc, SPI_CS, state); ++ write_hwreg(wc); ++} ++ ++static void set_clk(struct t4 *wc, int clk) ++{ ++ t8_set_bit(wc, SPI_CLK, clk); ++ write_hwreg(wc); ++} ++ ++static void clk_bit_out(struct t4 *wc, int val) ++{ ++ t8_set_bit(wc, SPI_IO0, val & 1); ++ set_clk(wc, 0); ++ set_clk(wc, 1); ++} ++ ++static void shift_out(struct t4 *wc, int val) ++{ ++ int i; ++ for (i = 7; i >= 0; i--) ++ clk_bit_out(wc, (val >> i) & 1); ++} ++ ++static int clk_bit_in(struct t4 *wc) ++{ ++ int ret; ++ set_clk(wc, 0); ++ read_hwreg(wc); ++ ret = t8_get_bit(wc, SPI_IO1); ++ set_clk(wc, 1); ++ return ret; ++} ++ ++static int shift_in(struct t4 *wc) ++{ ++ int ret = 0; ++ int i; ++ int bit; ++ ++ for (i = 7; i >= 0; i--) { ++ bit = clk_bit_in(wc); ++ ret |= ((bit & 1) << i); ++ } ++ return ret; ++} ++ ++static void write_enable(struct t4 *wc) ++{ ++ int cmd = 0x06; ++ set_cs(wc, 0); ++ shift_out(wc, cmd); ++ set_cs(wc, 1); ++} ++ ++static int read_sr1(struct t4 *wc) ++{ ++ int cmd = 0x05; ++ int ret; ++ set_cs(wc, 0); ++ shift_out(wc, cmd); ++ ret = shift_in(wc); ++ set_cs(wc, 1); ++ return ret; ++} ++ ++static void clear_busy(struct t4 *wc) ++{ ++ static const int SR1_BUSY = (1 << 0); ++ unsigned long stop; ++ ++ stop = jiffies + 2*HZ; ++ while (read_sr1(wc) & SR1_BUSY) { ++ if (time_after(jiffies, stop)) { ++ if (printk_ratelimit()) { ++ dev_err(&wc->dev->dev, ++ "Lockup in %s\n", __func__); ++ } ++ break; ++ } ++ cond_resched(); ++ } ++} ++ ++static void sector_erase(struct t4 *wc, uint32_t addr) ++{ ++ int cmd = 0x20; ++ write_enable(wc); ++ set_cs(wc, 0); ++ shift_out(wc, cmd); ++ shift_out(wc, (addr >> 16) & 0xff); ++ shift_out(wc, (addr >> 8) & 0xff); ++ shift_out(wc, (addr >> 0) & 0xff); ++ set_cs(wc, 1); ++ clear_busy(wc); ++} ++ ++static void erase_half(struct t4 *wc) ++{ ++ uint32_t addr = 0x00080000; ++ uint32_t i; ++ ++ dev_info(&wc->dev->dev, "Erasing octal firmware\n"); ++ ++ for (i = addr; i < (addr + 0x80000); i += 4096) ++ sector_erase(wc, i); ++} ++ ++ ++#define T8_FLASH_PAGE_SIZE 256UL ++ ++static void t8_update_firmware_page(struct t4 *wc, u32 address, ++ const u8 *page_data, size_t size) ++{ ++ int i; ++ ++ write_enable(wc); ++ set_cs(wc, 0); ++ shift_out(wc, 0x02); ++ shift_out(wc, (address >> 16) & 0xff); ++ shift_out(wc, (address >> 8) & 0xff); ++ shift_out(wc, (address >> 0) & 0xff); ++ ++ for (i = 0; i < size; ++i) ++ shift_out(wc, page_data[i]); ++ ++ set_cs(wc, 1); ++ clear_busy(wc); ++} ++ ++static int t8_update_firmware(struct t4 *wc, const struct firmware *fw, ++ const char *t8_firmware) ++{ ++ int res; ++ size_t offset = 0; ++ const u32 BASE_ADDRESS = 0x00080000; ++ const u8 *data, *end; ++ size_t size = 0; ++ ++ /* Erase flash */ ++ erase_half(wc); ++ ++ dev_info(&wc->dev->dev, ++ "Uploading %s. This can take up to 30 seconds.\n", t8_firmware); ++ ++ data = &fw->data[sizeof(struct t8_firm_header)]; ++ end = &fw->data[fw->size]; ++ ++ while (data < end) { ++ /* Calculate the tail end of data that's shorter than a page */ ++ size = min(T8_FLASH_PAGE_SIZE, (unsigned long)(end - data)); ++ ++ t8_update_firmware_page(wc, BASE_ADDRESS + offset, ++ data, size); ++ data += T8_FLASH_PAGE_SIZE; ++ offset += T8_FLASH_PAGE_SIZE; ++ ++ cond_resched(); ++ } ++ ++ /* Reset te820 fpga after loading firmware */ ++ dev_info(&wc->dev->dev, "Firmware load complete. Reseting device.\n"); ++ res = pci_save_state(wc->dev); ++ if (res) ++ goto error_exit; ++ /* Set the fpga reset bits and clobber the remainder of the ++ * register, device will be reset anyway */ ++ t4_pci_out(wc, WC_LEDS, 0xe0000000); ++ msleep(1000); ++ ++ pci_restore_state(wc->dev); ++ ++ /* Signal the driver to restart initialization. ++ * This will back out all initialization so far and ++ * restart the driver load process */ ++ return -EAGAIN; ++ ++error_exit: ++ return res; ++} ++ ++static char read_flash_byte(struct t4 *wc, unsigned int addr) ++{ ++ int cmd = 0x03; ++ char data; ++ ++ set_cs(wc, 0); ++ ++ shift_out(wc, cmd); ++ ++ shift_out(wc, (addr >> 16) & 0xff); ++ shift_out(wc, (addr >> 8) & 0xff); ++ shift_out(wc, (addr >> 0) & 0xff); ++ ++ data = shift_in(wc) & 0xff; ++ ++ set_cs(wc, 1); ++ ++ return data; ++} ++ ++/** ++ * t8_read_serial - Returns the serial number of the board. ++ * @wc: The board whos serial number we are reading. ++ * ++ * The buffer returned is dynamically allocated and must be kfree'd by the ++ * caller. If memory could not be allocated, NULL is returned. ++ * ++ * Must be called in process context. ++ * ++ */ ++static char *t8_read_serial(struct t4 *wc) ++{ ++ int i; ++ static const int MAX_SERIAL = 14; ++ static const u32 base_addr = 0x00080000-256; ++ unsigned char c; ++ unsigned char *serial = kzalloc(MAX_SERIAL + 1, GFP_KERNEL); ++ ++ if (!serial) ++ return NULL; ++ ++ for (i = 0; i < MAX_SERIAL; ++i) { ++ c = read_flash_byte(wc, base_addr+i); ++ if ((c >= 'a' && c <= 'z') || ++ (c >= 'A' && c <= 'Z') || ++ (c >= '0' && c <= '9')) ++ serial[i] = c; ++ else ++ break; ++ ++ } ++ ++ if (!i) { ++ kfree(serial); ++ serial = NULL; ++ } ++ ++ return serial; ++} ++ ++static void setup_spi(struct t4 *wc) ++{ ++ wc->st.rdreg = wc->st.wrreg = 0; ++ ++ set_iodir(wc, SPI_IO0, SPI_OUT); ++ set_iodir(wc, SPI_IO1, SPI_IN); ++ set_iodir(wc, SPI_CS, SPI_OUT); ++ set_iodir(wc, SPI_CLK, SPI_OUT); ++ ++ t8_set_bit(wc, SPI_CS, 1); ++ t8_set_bit(wc, SPI_CLK, 1); ++ ++ write_hwreg(wc); ++} ++ ++static int t8_check_firmware(struct t4 *wc, unsigned int version) ++{ ++ const struct firmware *fw; ++ static const char t8_firmware[] = "dahdi-fw-te820.bin"; ++ const struct t8_firm_header *header; ++ int res = 0; ++ u32 crc; ++ ++ res = request_firmware(&fw, t8_firmware, &wc->dev->dev); ++ if (res) { ++ dev_info(&wc->dev->dev, "firmware %s not " ++ "available from userspace\n", t8_firmware); ++ goto cleanup; ++ } ++ ++ header = (const struct t8_firm_header *)fw->data; ++ ++ /* Check the crc before anything else */ ++ crc = crc32(~0, &fw->data[10], fw->size - 10) ^ ~0; ++ if (memcmp("DIGIUM", header->header, sizeof(header->header)) || ++ (le32_to_cpu(header->chksum) != crc)) { ++ dev_info(&wc->dev->dev, ++ "%s is invalid. Please reinstall.\n", t8_firmware); ++ goto cleanup; ++ } ++ ++ /* Spi struct must be setup before any access to flash memory */ ++ setup_spi(wc); ++ ++ /* Check the two firmware versions */ ++ if (le32_to_cpu(header->version) == version) ++ goto cleanup; ++ ++ dev_info(&wc->dev->dev, "%s Version: %08x available for flash\n", ++ t8_firmware, header->version); ++ ++ res = t8_update_firmware(wc, fw, t8_firmware); ++ if (res && res != -EAGAIN) { ++ dev_info(&wc->dev->dev, "Failed to load firmware %s\n", ++ t8_firmware); ++ } ++ ++cleanup: ++ release_firmware(fw); ++ return res; ++} ++ ++static int ++__t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time) ++{ ++ unsigned int version; ++ int res; ++ ++ version = t4_pci_in(wc, WC_VERSION); ++ if (is_octal(wc) && first_time) { ++ dev_info(&wc->dev->dev, "Firmware Version: %01x.%02x\n", ++ (version & 0xf00) >> 8, ++ version & 0xff); ++ } else if (first_time) { ++ dev_info(&wc->dev->dev, "Firmware Version: %08x\n", version); ++ } ++ if (debug) { ++ dev_info(&wc->dev->dev, "Burst Mode: %s\n", ++ (!(cardflags & FLAG_BURST) && noburst) ? "Off" : "On"); ++ } ++ ++ /* Check the field updatable firmware for the wcte820 */ ++ if (is_octal(wc)) { ++ res = t8_check_firmware(wc, version); ++ if (res) ++ return res; ++ ++ wc->ddev->hardware_id = t8_read_serial(wc); ++ } ++ ++#if defined(CONFIG_FORCE_EXTENDED_RESET) ++ t4_extended_reset(wc); ++#elif !defined(CONFIG_NOEXTENDED_RESET) ++ if (wc->devtype->flags & FLAG_EXPRESS) ++ t4_extended_reset(wc); ++#endif ++ ++ /* Make sure DMA engine is not running and interrupts are acknowledged */ ++ wc->dmactrl = 0x0; ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ /* Reset Framer and friends */ ++ t4_pci_out(wc, WC_LEDS, 0x00000000); ++ ++ /* Set DMA addresses */ ++ t4_pci_out(wc, WC_RDADDR, wc->readdma); ++ t4_pci_out(wc, WC_WRADDR, wc->writedma); ++ ++ /* Setup counters, interrupt flags (ignored in Gen2) */ ++ if (cardflags & FLAG_2NDGEN) { ++ t4_tsi_reset(wc); ++ } else { ++ t4_pci_out(wc, WC_COUNT, ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); ++ } ++ ++ /* Reset pending interrupts */ ++ t4_pci_out(wc, WC_INTR, 0x00000000); ++ ++ /* Read T1/E1 status */ ++ if (first_time) { ++ if (!strcasecmp("auto", default_linemode)) { ++ if (-1 == t1e1override) { ++ wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & ++ 0x0f00) >> 8); ++ wc->t1e1 &= 0xf; ++ if (is_octal(wc)) { ++ wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) & ++ 0x0f00) >> 4; ++ } ++ } else { ++ dev_warn(&wc->dev->dev, ++ "'t1e1override' is deprecated. Please use 'default_linemode'.\n"); ++ wc->t1e1 = t1e1override & 0xf; ++ } ++ } else if (!strcasecmp("t1", default_linemode)) { ++ wc->t1e1 = 0; ++ } else if (!strcasecmp("e1", default_linemode)) { ++ wc->t1e1 = 0xff; ++ } else if (!strcasecmp("j1", default_linemode)) { ++ wc->t1e1 = 0; ++ j1mode = 1; ++ } else { ++ dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n", ++ default_linemode); ++ wc->t1e1 = 0; ++ } ++ } ++ ++ wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28; ++ order_index[wc->order]++; ++ ++ /* TE820 Auth Check */ ++ if (is_octal(wc)) { ++ unsigned long stop = jiffies + HZ; ++ uint32_t donebit; ++ ++ t4_pci_out(wc, WC_LEDS2, WC_SET_AUTH); ++ donebit = t4_pci_in(wc, WC_LEDS2); ++ while (!(donebit & WC_GET_AUTH)) { ++ if (time_after(jiffies, stop)) { ++ /* Encryption check failed, stop operation */ ++ dev_info(&wc->dev->dev, ++ "Failed encryption check. " ++ "Unloading driver.\n"); ++ return -EIO; ++ } ++ msleep(20); ++ donebit = t4_pci_in(wc, WC_LEDS2); ++ } ++ } ++ ++ return 0; ++} ++ ++static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) ++{ ++ return __t4_hardware_init_1(wc, cardflags, true); ++} ++ ++static int __t4_hardware_init_2(struct t4 *wc, bool first_time) ++{ ++ int x; ++ unsigned int regval; ++ unsigned long flags; ++ ++ if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) { ++ wc->tspans[0]->spanflags |= FLAG_OCTOPT; ++ } ++ /* Setup LEDS, take out of reset */ ++ t4_pci_out(wc, WC_LEDS, 0x000000ff); ++ udelay(100); ++ t4_activate(wc); ++ udelay(100); ++ ++ /* In order to find out the QFALC framer version, we have to ++ * temporarily turn off compat mode and take a peak at VSTR. We turn ++ * compat back on when we are done. ++ * ++ */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ regval = __t4_framer_in(wc, 0, 0xd6); ++ if (is_octal(wc)) ++ regval |= (1 << 4); /* SSI16 - For 16 MHz multiplex mode with comp = 1 */ ++ else ++ regval |= (1 << 5); /* set COMP_DIS*/ ++ ++ __t4_framer_out(wc, 0, 0xd6, regval); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (!is_octal(wc)) { ++ regval = t4_framer_in(wc, 0, 0x4a); ++ if (first_time && regval == 0x05) { ++ dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or " ++ "earlier\n"); ++ } else if (regval == 0x20) { ++ if (first_time) ++ dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n"); ++ wc->falc31 = 1; ++ } else if (first_time) { ++ dev_info(&wc->dev->dev, "FALC Framer Version: Unknown " ++ "(VSTR = 0x%02x)\n", regval); ++ } ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ regval = __t4_framer_in(wc, 0, 0xd6); ++ regval &= ~(1 << 5); /* clear COMP_DIS*/ ++ __t4_framer_out(wc, 0, 0xd6, regval); ++ __t4_framer_out(wc, 0, 0x4a, 0xaa); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (debug) { ++ dev_info(&wc->dev->dev, "Board ID: %02x\n", wc->order); ++ for (x = 0; x < 11; x++) { ++ dev_info(&wc->dev->dev, "Reg %d: 0x%08x\n", x, ++ t4_pci_in(wc, x)); ++ } ++ } ++ ++ wc->gpio = 0x00000000; ++ t4_pci_out(wc, WC_GPIO, wc->gpio); ++ t4_gpio_setdir(wc, (1 << 17), (1 << 17)); ++ t4_gpio_setdir(wc, (0xff), (0xff)); ++ ++ return 0; ++} ++ ++static int t4_hardware_init_2(struct t4 *wc) ++{ ++ return __t4_hardware_init_2(wc, true); ++} ++ ++static int __devinit t4_launch(struct t4 *wc) ++{ ++ int x; ++ int res; ++ ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags)) ++ return 0; ++ ++ if (debug) { ++ dev_info(&wc->dev->dev, ++ "TE%dXXP: Launching card: %d\n", wc->numspans, ++ wc->order); ++ } ++ ++ wc->ddev->manufacturer = "Digium"; ++ if (!ignore_rotary && (1 == order_index[wc->order])) { ++ wc->ddev->location = kasprintf(GFP_KERNEL, ++ "Board ID Switch %d", wc->order); ++ } else { ++ bool express = ((wc->tspans[0]->spanflags & FLAG_EXPRESS) > 0); ++ wc->ddev->location = kasprintf(GFP_KERNEL, ++ "PCI%s Bus %02d Slot %02d", ++ (express) ? " Express" : "", ++ wc->dev->bus->number, ++ PCI_SLOT(wc->dev->devfn) + 1); ++ } ++ ++ if (!wc->ddev->location) ++ return -ENOMEM; ++ ++ for (x = 0; x < wc->numspans; ++x) { ++ list_add_tail(&wc->tspans[x]->span.device_node, ++ &wc->ddev->spans); ++ } ++ ++ INIT_WORK(&wc->bh_work, t4_work_func); ++ ++ res = dahdi_register_device(wc->ddev, &wc->dev->dev); ++ if (res) { ++ dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n"); ++ return res; ++ } ++ ++ return 0; ++} ++ ++/** ++ * wct4xxp_sort_cards - Sort the cards in card array by rotary switch settings. ++ * ++ */ ++static void wct4xxp_sort_cards(void) ++{ ++ int x; ++ ++ /* get the current number of probed cards and run a slice of a tail ++ * insertion sort */ ++ for (x = 0; x < MAX_T4_CARDS; x++) { ++ if (!cards[x+1]) ++ break; ++ } ++ for ( ; x > 0; x--) { ++ if (cards[x]->order < cards[x-1]->order) { ++ struct t4 *tmp = cards[x]; ++ cards[x] = cards[x-1]; ++ cards[x-1] = tmp; ++ } else { ++ /* if we're not moving it, we won't move any more ++ * since all cards are sorted on addition */ ++ break; ++ } ++ } ++} ++ ++static int __devinit ++t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ int res; ++ struct t4 *wc; ++ unsigned int x; ++ int init_latency; ++ ++ if (pci_enable_device(pdev)) { ++ return -EIO; ++ } ++ ++ wc = kzalloc(sizeof(*wc), GFP_KERNEL); ++ if (!wc) ++ return -ENOMEM; ++ ++ wc->ddev = dahdi_create_device(); ++ if (!wc->ddev) { ++ kfree(wc); ++ return -ENOMEM; ++ } ++ ++ spin_lock_init(&wc->reglock); ++ wc->devtype = (const struct devtype *)(ent->driver_data); ++ ++#ifdef CONFIG_WCT4XXP_DISABLE_ASPM ++ if (is_pcie(wc)) { ++ pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S | ++ PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); ++ }; ++#endif ++ ++ if (is_octal(wc)) ++ wc->numspans = 8; ++ else if (wc->devtype->flags & FLAG_2PORT) ++ wc->numspans = 2; ++ else ++ wc->numspans = 4; ++ ++ wc->membase = pci_iomap(pdev, 0, 0); ++ /* This rids of the Double missed interrupt message after loading */ ++ wc->last0 = 1; ++ if (pci_request_regions(pdev, wc->devtype->desc)) ++ dev_info(&pdev->dev, "wct%dxxp: Unable to request regions\n", ++ wc->numspans); ++ ++ if (debug) ++ dev_info(&pdev->dev, "Found TE%dXXP\n", wc->numspans); ++ ++ wc->dev = pdev; ++ ++ /* Enable bus mastering */ ++ pci_set_master(pdev); ++ ++ /* Keep track of which device we are */ ++ pci_set_drvdata(pdev, wc); ++ ++ if (wc->devtype->flags & FLAG_5THGEN) { ++ if ((ms_per_irq > 1) && (latency <= ((ms_per_irq) << 1))) { ++ init_latency = ms_per_irq << 1; ++ } else { ++ if (latency > 2) ++ init_latency = latency; ++ else ++ init_latency = 2; ++ } ++ dev_info(&wc->dev->dev, "5th gen card with initial latency of " ++ "%d and %d ms per IRQ\n", init_latency, ms_per_irq); ++ } else { ++ if (wc->devtype->flags & FLAG_2NDGEN) ++ init_latency = 1; ++ else ++ init_latency = 2; ++ } ++ ++ if (max_latency < init_latency) { ++ printk(KERN_INFO "maxlatency must be set to something greater than %d ms, increasing it to %d\n", init_latency, init_latency); ++ max_latency = init_latency; ++ } ++ ++ if (t4_allocate_buffers(wc, init_latency, NULL, NULL)) { ++ return -ENOMEM; ++ } ++ ++ /* Initialize hardware */ ++ res = t4_hardware_init_1(wc, wc->devtype->flags); ++ if (res) { ++ /* If this function returns -EAGAIN, we expect ++ * to attempt another driver load. Clean everything ++ * up first */ ++ pci_iounmap(wc->dev, wc->membase); ++ pci_release_regions(wc->dev); ++ pci_free_consistent(wc->dev, T4_BASE_SIZE(wc) * wc->numbufs * 2, ++ wc->writechunk, wc->writedma); ++ pci_set_drvdata(wc->dev, NULL); ++ free_wc(wc); ++ return res; ++ } ++ ++ for(x = 0; x < MAX_T4_CARDS; x++) { ++ if (!cards[x]) ++ break; ++ } ++ ++ if (x >= MAX_T4_CARDS) { ++ dev_notice(&wc->dev->dev, "No cards[] slot available!!\n"); ++ kfree(wc); ++ return -ENOMEM; ++ } ++ ++ wc->num = x; ++ cards[x] = wc; ++ ++ /* Allocate pieces we need here */ ++ for (x = 0; x < ports_on_framer(wc); x++) { ++ struct t4_span *ts; ++ enum linemode linemode; ++ ++ ts = kzalloc(sizeof(*ts), GFP_KERNEL); ++ if (!ts) { ++ free_wc(wc); ++ return -ENOMEM; ++ } ++ wc->tspans[x] = ts; ++ ++ ts->spanflags |= wc->devtype->flags; ++ linemode = (wc->t1e1 & (1 << x)) ? E1 : ((j1mode) ? J1 : T1); ++ t4_alloc_channels(wc, wc->tspans[x], linemode); ++ } ++ ++ /* Continue hardware intiialization */ ++ t4_hardware_init_2(wc); ++ ++#ifdef SUPPORT_GEN1 ++ if (request_irq(pdev->irq, (wc->devtype->flags & FLAG_2NDGEN) ? ++ t4_interrupt_gen2 : t4_interrupt, ++ IRQF_SHARED, ++ (wc->numspans == 8) ? "wct8xxp" : ++ (wc->numspans == 2) ? "wct2xxp" : ++ "wct4xxp", ++ wc)) { ++#else ++ if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) { ++ dev_notice(&wc->dev->dev, "This driver does not " ++ "support 1st gen modules\n"); ++ free_wc(wc); ++ return -ENODEV; ++ } ++ ++ if (request_irq(pdev->irq, t4_interrupt_gen2, ++ IRQF_SHARED, "t4xxp", wc)) { ++#endif ++ dev_notice(&wc->dev->dev, "Unable to request IRQ %d\n", ++ pdev->irq); ++ free_wc(wc); ++ return -EIO; ++ } ++ ++ init_spans(wc); ++ ++ if (!ignore_rotary) ++ wct4xxp_sort_cards(); ++ ++ if (wc->ddev->hardware_id) { ++ dev_info(&wc->dev->dev, ++ "Found a Wildcard: %s (SN: %s)\n", wc->devtype->desc, ++ wc->ddev->hardware_id); ++ } else { ++ dev_info(&wc->dev->dev, ++ "Found a Wildcard: %s\n", wc->devtype->desc); ++ } ++ ++#ifdef VPM_SUPPORT ++ if (!wc->vpm) { ++ t4_vpm_init(wc); ++ wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0; ++ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); ++ if (wc->vpm) ++ set_span_devicetype(wc); ++ } ++#endif ++ ++ create_sysfs_files(wc); ++ ++ res = 0; ++ if (ignore_rotary) ++ res = t4_launch(wc); ++ ++ return res; ++} ++ ++static int t4_hardware_stop(struct t4 *wc) ++{ ++ ++ /* Turn off DMA, leave interrupts enabled */ ++ set_bit(T4_STOP_DMA, &wc->checkflag); ++ ++ /* Wait for interrupts to stop */ ++ msleep(25); ++ ++ /* Turn off counter, address, etc */ ++ if (wc->tspans[0]->spanflags & FLAG_2NDGEN) { ++ t4_tsi_reset(wc); ++ } else { ++ t4_pci_out(wc, WC_COUNT, 0x000000); ++ } ++ t4_pci_out(wc, WC_RDADDR, 0x0000000); ++ t4_pci_out(wc, WC_WRADDR, 0x0000000); ++ wc->gpio = 0x00000000; ++ t4_pci_out(wc, WC_GPIO, wc->gpio); ++ t4_pci_out(wc, WC_LEDS, 0x00000000); ++ ++ if (debug) { ++ dev_notice(&wc->dev->dev, "Stopped TE%dXXP, Turned off DMA\n", ++ wc->numspans); ++ } ++ return 0; ++} ++ ++static int __devinit ++t4_init_one_retry(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ int res; ++ res = t4_init_one(pdev, ent); ++ ++ /* If the driver was reset by a firmware load, ++ * try to load once again */ ++ if (-EAGAIN == res) { ++ res = t4_init_one(pdev, ent); ++ if (-EAGAIN == res) { ++ dev_err(&pdev->dev, "Failed to update firmware.\n"); ++ res = -EIO; ++ } ++ } ++ ++ return res; ++} ++ ++static void _t4_remove_one(struct t4 *wc) ++{ ++ int basesize; ++ ++ if (!wc) ++ return; ++ ++ dahdi_unregister_device(wc->ddev); ++ ++ remove_sysfs_files(wc); ++ ++ /* Stop hardware */ ++ t4_hardware_stop(wc); ++ ++#ifdef VPM_SUPPORT ++ /* Release vpm */ ++ if (wc->vpm) ++ release_vpm450m(wc->vpm); ++ wc->vpm = NULL; ++#endif ++ /* Unregister spans */ ++ ++ basesize = DAHDI_MAX_CHUNKSIZE * 32 * 4; ++ if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) ++ basesize = basesize * 2; ++ ++ free_irq(wc->dev->irq, wc); ++ ++ if (wc->membase) ++ pci_iounmap(wc->dev, wc->membase); ++ ++ pci_release_regions(wc->dev); ++ ++ /* Immediately free resources */ ++ pci_free_consistent(wc->dev, T4_BASE_SIZE(wc) * wc->numbufs * 2, ++ wc->writechunk, wc->writedma); ++ ++ order_index[wc->order]--; ++ ++ cards[wc->num] = NULL; ++ pci_set_drvdata(wc->dev, NULL); ++ free_wc(wc); ++} ++ ++static void __devexit t4_remove_one(struct pci_dev *pdev) ++{ ++ struct t4 *wc = pci_get_drvdata(pdev); ++ if (!wc) ++ return; ++ ++ _t4_remove_one(wc); ++} ++ ++ ++static DEFINE_PCI_DEVICE_TABLE(t4_pci_tbl) = ++{ ++ { 0x10ee, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct4xxp }, ++ ++ { 0xd161, 0x1820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct820p5 }, ++ { 0xd161, 0x1420, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct420p5 }, ++ { 0xd161, 0x1410, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p5 }, ++ { 0xd161, 0x1405, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p5 }, ++ { 0xd161, 0x0420, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct420p4 }, ++ { 0xd161, 0x0410, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p4 }, ++ { 0xd161, 0x0405, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p4 }, ++ { 0xd161, 0x0410, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p3 }, ++ { 0xd161, 0x0405, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p3 }, ++ { 0xd161, 0x0410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p2 }, ++ { 0xd161, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p2 }, ++ ++ { 0xd161, 0x1220, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct220p5 }, ++ { 0xd161, 0x1205, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p5 }, ++ { 0xd161, 0x1210, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p5 }, ++ { 0xd161, 0x0220, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct220p4 }, ++ { 0xd161, 0x0205, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p4 }, ++ { 0xd161, 0x0210, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p4 }, ++ { 0xd161, 0x0205, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p3 }, ++ { 0xd161, 0x0210, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p3 }, ++ { 0xd161, 0x0205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct205 }, ++ { 0xd161, 0x0210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct210 }, ++ { 0, } ++}; ++ ++static void _t4_shutdown(struct pci_dev *pdev) ++{ ++ struct t4 *wc = pci_get_drvdata(pdev); ++ t4_hardware_stop(wc); ++} ++ ++static int t4_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ return -ENOSYS; ++} ++ ++static struct pci_driver t4_driver = { ++ .name = "wct4xxp", ++ .probe = t4_init_one_retry, ++ .remove = __devexit_p(t4_remove_one), ++ .shutdown = _t4_shutdown, ++ .suspend = t4_suspend, ++ .id_table = t4_pci_tbl, ++}; ++ ++static int __init t4_init(void) ++{ ++ int i; ++ int res; ++ ++ if (-1 != t1e1override) { ++ pr_info("'t1e1override' module parameter is deprecated. " ++ "Please use 'default_linemode' instead.\n"); ++ } ++ ++ res = pci_register_driver(&t4_driver); ++ if (res) ++ return -ENODEV; ++ ++ /* If we're ignoring the rotary switch settings, then we've already ++ * registered in the context of .probe */ ++ if (!ignore_rotary) { ++ ++ /* Initialize cards since we have all of them. Warn for ++ * missing zero and duplicate numbers. */ ++ ++ if (cards[0] && cards[0]->order != 0) { ++ printk(KERN_NOTICE "wct4xxp: Ident of first card is not zero (%d)\n", ++ cards[0]->order); ++ } ++ ++ for (i = 0; cards[i]; i++) { ++ /* warn the user of duplicate ident values it is ++ * probably unintended */ ++ if (debug && res < 15 && cards[i+1] && ++ cards[res]->order == cards[i+1]->order) { ++ printk(KERN_NOTICE "wct4xxp: Duplicate ident " ++ "value found (%d)\n", cards[i]->order); ++ } ++ res = t4_launch(cards[i]); ++ if (res) { ++ int j; ++ for (j = 0; j < i; ++j) ++ _t4_remove_one(cards[j]); ++ break; ++ } ++ } ++ } ++ return res; ++} ++ ++static void __exit t4_cleanup(void) ++{ ++ pci_unregister_driver(&t4_driver); ++} ++ ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_DESCRIPTION("Wildcard Dual/Quad/Octal-port Digital Card Driver"); ++MODULE_ALIAS("wct2xxp"); ++MODULE_LICENSE("GPL v2"); ++ ++module_param(debug, int, 0600); ++module_param(noburst, int, 0600); ++module_param(timingcable, int, 0600); ++module_param(t1e1override, int, 0400); ++module_param(default_linemode, charp, S_IRUGO); ++MODULE_PARM_DESC(default_linemode, "\"auto\"(default), \"e1\", \"t1\", " ++ "or \"j1\". \"auto\" will use the value from any hardware " ++ "jumpers."); ++module_param(alarmdebounce, int, 0600); ++module_param(losalarmdebounce, int, 0600); ++module_param(aisalarmdebounce, int, 0600); ++module_param(yelalarmdebounce, int, 0600); ++module_param(max_latency, int, 0600); ++module_param(j1mode, int, 0600); ++module_param(sigmode, int, 0600); ++module_param(latency, int, 0600); ++module_param(ms_per_irq, int, 0600); ++module_param(ignore_rotary, int, 0400); ++MODULE_PARM_DESC(ignore_rotary, "Set to > 0 to ignore the rotary switch when " \ ++ "registering with DAHDI."); ++ ++#ifdef VPM_SUPPORT ++module_param(vpmsupport, int, 0600); ++module_param(vpmdtmfsupport, int, 0600); ++#endif ++ ++MODULE_DEVICE_TABLE(pci, t4_pci_tbl); ++ ++module_init(t4_init); ++module_exit(t4_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/wct4xxp/vpm450m.c linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/vpm450m.c +--- linux-source-4.19/drivers/dahdi/wct4xxp/vpm450m.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/vpm450m.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,623 @@ ++/* ++ * Copyright (C) 2005-2012 Digium, Inc. ++ * ++ * Mark Spencer ++ * ++ * 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. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "vpm450m.h" ++#include ++ ++static int wct4xxp_oct612x_write(struct oct612x_context *context, ++ u32 address, u16 value) ++{ ++ struct t4 *wc = dev_get_drvdata(context->dev); ++ oct_set_reg(wc, address, value); ++ return 0; ++} ++ ++static int wct4xxp_oct612x_read(struct oct612x_context *context, u32 address, ++ u16 *value) ++{ ++ struct t4 *wc = dev_get_drvdata(context->dev); ++ *value = (u16)oct_get_reg(wc, address); ++ return 0; ++} ++ ++static int wct4xxp_oct612x_write_smear(struct oct612x_context *context, ++ u32 address, u16 value, size_t count) ++{ ++ struct t4 *wc = dev_get_drvdata(context->dev); ++ int i; ++ for (i = 0; i < count; ++i) ++ oct_set_reg(wc, address + (i << 1), value); ++ return 0; ++} ++ ++static int wct4xxp_oct612x_write_burst(struct oct612x_context *context, ++ u32 address, const u16 *buffer, ++ size_t count) ++{ ++ struct t4 *wc = dev_get_drvdata(context->dev); ++ int i; ++ for (i = 0; i < count; ++i) ++ oct_set_reg(wc, address + (i << 1), buffer[i]); ++ return 0; ++} ++ ++static int wct4xxp_oct612x_read_burst(struct oct612x_context *context, ++ u32 address, u16 *buffer, size_t count) ++{ ++ struct t4 *wc = dev_get_drvdata(context->dev); ++ int i; ++ for (i = 0; i < count; ++i) ++ buffer[i] = oct_get_reg(wc, address + (i << 1)); ++ return 0; ++} ++ ++static const struct oct612x_ops wct4xxp_oct612x_ops = { ++ .write = wct4xxp_oct612x_write, ++ .read = wct4xxp_oct612x_read, ++ .write_smear = wct4xxp_oct612x_write_smear, ++ .write_burst = wct4xxp_oct612x_write_burst, ++ .read_burst = wct4xxp_oct612x_read_burst, ++}; ++ ++#define SOUT_G168_1100GB_ON 0x40000004 ++#define SOUT_DTMF_1 0x40000011 ++#define SOUT_DTMF_2 0x40000012 ++#define SOUT_DTMF_3 0x40000013 ++#define SOUT_DTMF_A 0x4000001A ++#define SOUT_DTMF_4 0x40000014 ++#define SOUT_DTMF_5 0x40000015 ++#define SOUT_DTMF_6 0x40000016 ++#define SOUT_DTMF_B 0x4000001B ++#define SOUT_DTMF_7 0x40000017 ++#define SOUT_DTMF_8 0x40000018 ++#define SOUT_DTMF_9 0x40000019 ++#define SOUT_DTMF_C 0x4000001C ++#define SOUT_DTMF_STAR 0x4000001E ++#define SOUT_DTMF_0 0x40000010 ++#define SOUT_DTMF_POUND 0x4000001F ++#define SOUT_DTMF_D 0x4000001D ++ ++#define ROUT_G168_2100GB_ON 0x10000000 ++#define ROUT_G168_2100GB_WSPR 0x10000002 ++#define ROUT_SOUT_G168_2100HB_END 0x50000003 ++#define ROUT_G168_1100GB_ON 0x10000004 ++ ++#define ROUT_DTMF_1 0x10000011 ++#define ROUT_DTMF_2 0x10000012 ++#define ROUT_DTMF_3 0x10000013 ++#define ROUT_DTMF_A 0x1000001A ++#define ROUT_DTMF_4 0x10000014 ++#define ROUT_DTMF_5 0x10000015 ++#define ROUT_DTMF_6 0x10000016 ++#define ROUT_DTMF_B 0x1000001B ++#define ROUT_DTMF_7 0x10000017 ++#define ROUT_DTMF_8 0x10000018 ++#define ROUT_DTMF_9 0x10000019 ++#define ROUT_DTMF_C 0x1000001C ++#define ROUT_DTMF_STAR 0x1000001E ++#define ROUT_DTMF_0 0x10000010 ++#define ROUT_DTMF_POUND 0x1000001F ++#define ROUT_DTMF_D 0x1000001D ++ ++#if 0 ++#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE ++#else ++#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN ++#endif ++ ++struct vpm450m { ++ tPOCT6100_INSTANCE_API pApiInstance; ++ struct oct612x_context context; ++ UINT32 aulEchoChanHndl[256]; ++ int chanflags[256]; ++ int ecmode[256]; ++ int numchans; ++}; ++ ++#define FLAG_DTMF (1 << 0) ++#define FLAG_MUTE (1 << 1) ++#define FLAG_ECHO (1 << 2) ++#define FLAG_ALAW (1 << 3) ++ ++static unsigned int tones[] = { ++ SOUT_DTMF_1, ++ SOUT_DTMF_2, ++ SOUT_DTMF_3, ++ SOUT_DTMF_A, ++ SOUT_DTMF_4, ++ SOUT_DTMF_5, ++ SOUT_DTMF_6, ++ SOUT_DTMF_B, ++ SOUT_DTMF_7, ++ SOUT_DTMF_8, ++ SOUT_DTMF_9, ++ SOUT_DTMF_C, ++ SOUT_DTMF_STAR, ++ SOUT_DTMF_0, ++ SOUT_DTMF_POUND, ++ SOUT_DTMF_D, ++ SOUT_G168_1100GB_ON, ++ ++ ROUT_DTMF_1, ++ ROUT_DTMF_2, ++ ROUT_DTMF_3, ++ ROUT_DTMF_A, ++ ROUT_DTMF_4, ++ ROUT_DTMF_5, ++ ROUT_DTMF_6, ++ ROUT_DTMF_B, ++ ROUT_DTMF_7, ++ ROUT_DTMF_8, ++ ROUT_DTMF_9, ++ ROUT_DTMF_C, ++ ROUT_DTMF_STAR, ++ ROUT_DTMF_0, ++ ROUT_DTMF_POUND, ++ ROUT_DTMF_D, ++ ROUT_G168_1100GB_ON, ++}; ++ ++void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel, ++ bool alaw) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ UINT32 law_to_use = (alaw) ? cOCT6100_PCM_A_LAW : ++ cOCT6100_PCM_U_LAW; ++ ++ if (channel >= ARRAY_SIZE(vpm450m->chanflags)) { ++ pr_err("Channel out of bounds in %s\n", __func__); ++ return; ++ } ++ /* If we're already in this companding mode, no need to do anything. */ ++ if (alaw == ((vpm450m->chanflags[channel] & FLAG_ALAW) > 0)) ++ return; ++ ++ modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); ++ if (!modify) { ++ pr_notice("Unable to allocate memory for setec!\n"); ++ return; ++ } ++ ++ Oct6100ChannelModifyDef(modify); ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ modify->fTdmConfigModified = TRUE; ++ modify->TdmConfig.ulSinPcmLaw = law_to_use; ++ modify->TdmConfig.ulRinPcmLaw = law_to_use; ++ modify->TdmConfig.ulSoutPcmLaw = law_to_use; ++ modify->TdmConfig.ulRoutPcmLaw = law_to_use; ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n", ++ vpm450m->aulEchoChanHndl[channel], channel, ulResult); ++ } else { ++ if (debug) { ++ pr_info("Changed companding on channel %d to %s.\n", ++ channel, (alaw) ? "alaw" : "ulaw"); ++ } ++ if (alaw) ++ vpm450m->chanflags[channel] |= FLAG_ALAW; ++ else ++ vpm450m->chanflags[channel] &= ~(FLAG_ALAW); ++ } ++ kfree(modify); ++} ++ ++static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ ++ if (vpm450m->ecmode[channel] == mode) ++ return; ++ modify = kzalloc(sizeof(*modify), GFP_ATOMIC); ++ if (!modify) { ++ printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setec!\n"); ++ return; ++ } ++ Oct6100ChannelModifyDef(modify); ++ modify->ulEchoOperationMode = mode; ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ printk(KERN_NOTICE "Failed to apply echo can changes on channel %d %08x!\n", channel, ulResult); ++ } else { ++#ifdef OCTASIC_DEBUG ++ printk(KERN_DEBUG "Echo can on channel %d set to %d\n", channel, mode); ++#endif ++ vpm450m->ecmode[channel] = mode; ++ } ++ kfree(modify); ++} ++ ++void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ ++ if (channel >= ARRAY_SIZE(vpm450m->chanflags)) { ++ pr_err("Channel out of bounds in %s\n", __func__); ++ return; ++ } ++ ++ modify = kzalloc(sizeof(*modify), GFP_KERNEL); ++ if (!modify) { ++ printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setdtmf!\n"); ++ return; ++ } ++ Oct6100ChannelModifyDef(modify); ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ if (mute) { ++ vpm450m->chanflags[channel] |= FLAG_MUTE; ++ modify->VqeConfig.fDtmfToneRemoval = TRUE; ++ } else { ++ vpm450m->chanflags[channel] &= ~FLAG_MUTE; ++ modify->VqeConfig.fDtmfToneRemoval = FALSE; ++ } ++ if (detect) ++ vpm450m->chanflags[channel] |= FLAG_DTMF; ++ else ++ vpm450m->chanflags[channel] &= ~FLAG_DTMF; ++ if (vpm450m->chanflags[channel] & (FLAG_DTMF|FLAG_MUTE)) { ++ if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) { ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); ++ } ++ } else { ++ if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); ++ } ++ ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ printk(KERN_NOTICE "Failed to apply dtmf mute changes on channel %d!\n", channel); ++ } ++/* printk(KERN_DEBUG "VPM450m: Setting DTMF on channel %d: %s / %s\n", channel, (detect ? "DETECT" : "NO DETECT"), (mute ? "MUTE" : "NO MUTE")); */ ++ kfree(modify); ++} ++ ++void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen) ++{ ++ if (channel >= ARRAY_SIZE(vpm450m->chanflags)) { ++ pr_err("Channel out of bounds in %s\n", __func__); ++ return; ++ } ++ ++ if (eclen) { ++ vpm450m->chanflags[channel] |= FLAG_ECHO; ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_NORMAL); ++ } else { ++ vpm450m->chanflags[channel] &= ~FLAG_ECHO; ++ if (vpm450m->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) { ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); ++ } else ++ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); ++ } ++/* printk(KERN_DEBUG "VPM450m: Setting EC on channel %d to %d\n", channel, eclen); */ ++} ++ ++int vpm450m_checkirq(struct vpm450m *vpm450m) ++{ ++ tOCT6100_INTERRUPT_FLAGS InterruptFlags; ++ ++ Oct6100InterruptServiceRoutineDef(&InterruptFlags); ++ Oct6100InterruptServiceRoutine(vpm450m->pApiInstance, &InterruptFlags); ++ ++ return InterruptFlags.fToneEventsPending ? 1 : 0; ++} ++ ++int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start) ++{ ++ tOCT6100_TONE_EVENT tonefound; ++ tOCT6100_EVENT_GET_TONE tonesearch; ++ ++ Oct6100EventGetToneDef(&tonesearch); ++ tonesearch.pToneEvent = &tonefound; ++ tonesearch.ulMaxToneEvent = 1; ++ Oct6100EventGetTone(vpm450m->pApiInstance, &tonesearch); ++ if (tonesearch.ulNumValidToneEvent) { ++ if (channel) ++ *channel = tonefound.ulUserChanId; ++ if (tone) { ++ switch(tonefound.ulToneDetected) { ++ case SOUT_DTMF_1: ++ *tone = '1'; ++ break; ++ case SOUT_DTMF_2: ++ *tone = '2'; ++ break; ++ case SOUT_DTMF_3: ++ *tone = '3'; ++ break; ++ case SOUT_DTMF_A: ++ *tone = 'A'; ++ break; ++ case SOUT_DTMF_4: ++ *tone = '4'; ++ break; ++ case SOUT_DTMF_5: ++ *tone = '5'; ++ break; ++ case SOUT_DTMF_6: ++ *tone = '6'; ++ break; ++ case SOUT_DTMF_B: ++ *tone = 'B'; ++ break; ++ case SOUT_DTMF_7: ++ *tone = '7'; ++ break; ++ case SOUT_DTMF_8: ++ *tone = '8'; ++ break; ++ case SOUT_DTMF_9: ++ *tone = '9'; ++ break; ++ case SOUT_DTMF_C: ++ *tone = 'C'; ++ break; ++ case SOUT_DTMF_STAR: ++ *tone = '*'; ++ break; ++ case SOUT_DTMF_0: ++ *tone = '0'; ++ break; ++ case SOUT_DTMF_POUND: ++ *tone = '#'; ++ break; ++ case SOUT_DTMF_D: ++ *tone = 'D'; ++ break; ++ case SOUT_G168_1100GB_ON: ++ *tone = 'f'; ++ break; ++ default: ++#ifdef OCTASIC_DEBUG ++ printk(KERN_DEBUG "Unknown tone value %08x\n", tonefound.ulToneDetected); ++#endif ++ *tone = 'u'; ++ break; ++ } ++ } ++ if (start) ++ *start = (tonefound.ulEventType == cOCT6100_TONE_PRESENT); ++ return 1; ++ } ++ return 0; ++} ++ ++unsigned int get_vpm450m_capacity(struct device *device) ++{ ++ struct oct612x_context context; ++ UINT32 ulResult; ++ ++ tOCT6100_API_GET_CAPACITY_PINS CapacityPins; ++ ++ context.dev = device; ++ context.ops = &wct4xxp_oct612x_ops; ++ ++ Oct6100ApiGetCapacityPinsDef(&CapacityPins); ++ CapacityPins.pProcessContext = &context; ++ CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR; ++ CapacityPins.fEnableMemClkOut = TRUE; ++ CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; ++ ++ ulResult = Oct6100ApiGetCapacityPins(&CapacityPins); ++ if (ulResult != cOCT6100_ERR_OK) { ++ printk(KERN_DEBUG "Failed to get chip capacity, code %08x!\n", ulResult); ++ return 0; ++ } ++ ++ return CapacityPins.ulCapacityValue; ++} ++ ++struct vpm450m *init_vpm450m(struct device *device, int *isalaw, ++ int numspans, const struct firmware *firmware) ++{ ++ tOCT6100_CHIP_OPEN *ChipOpen; ++ tOCT6100_GET_INSTANCE_SIZE InstanceSize; ++ tOCT6100_CHANNEL_OPEN *ChannelOpen; ++ UINT32 ulResult; ++ const unsigned int mask = (8 == numspans) ? 0x7 : 0x3; ++ unsigned int sout_stream, rout_stream; ++ struct vpm450m *vpm450m; ++ int x,y,law; ++ ++ vpm450m = kzalloc(sizeof(*vpm450m), GFP_KERNEL); ++ if (!vpm450m) ++ return NULL; ++ ++ vpm450m->context.dev = device; ++ vpm450m->context.ops = &wct4xxp_oct612x_ops; ++ ++ ChipOpen = kzalloc(sizeof(*ChipOpen), GFP_KERNEL); ++ if (!ChipOpen) { ++ kfree(vpm450m); ++ kfree(vpm450m); ++ return NULL; ++ } ++ ++ ChannelOpen = kzalloc(sizeof(*ChannelOpen), GFP_KERNEL); ++ if (!ChannelOpen) { ++ kfree(vpm450m); ++ kfree(ChipOpen); ++ return NULL; ++ } ++ ++ for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++) ++ vpm450m->ecmode[x] = -1; ++ ++ vpm450m->numchans = numspans * 32; ++ printk(KERN_INFO "VPM450: echo cancellation for %d channels\n", vpm450m->numchans); ++ ++ Oct6100ChipOpenDef(ChipOpen); ++ ++ /* Setup Chip Open Parameters */ ++ ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; ++ Oct6100GetInstanceSizeDef(&InstanceSize); ++ ++ ChipOpen->pProcessContext = &vpm450m->context; ++ ++ ChipOpen->pbyImageFile = firmware->data; ++ ChipOpen->ulImageSize = firmware->size; ++ ChipOpen->fEnableMemClkOut = TRUE; ++ ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; ++ ChipOpen->ulMaxChannels = vpm450m->numchans; ++ ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; ++ ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; ++ ChipOpen->ulNumMemoryChips = 1; ++ ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ; ++ ChipOpen->ulMaxFlexibleConfParticipants = 0; ++ ChipOpen->ulMaxConfBridges = 0; ++ ChipOpen->ulMaxRemoteDebugSessions = 0; ++ ChipOpen->fEnableChannelRecording = FALSE; ++ ChipOpen->ulSoftToneEventsBufSize = 64; ++ ++ if (vpm450m->numchans <= 128) { ++ ChipOpen->ulMaxTdmStreams = 4; ++ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; ++ } else { ++ ChipOpen->ulMaxTdmStreams = 32; ++ ChipOpen->fEnableFastH100Mode = TRUE; ++ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_RISING_EDGE; ++ } ++ ++#if 0 ++ ChipOpen->fEnableAcousticEcho = TRUE; ++#endif ++ ++ ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize); ++ if (ulResult != cOCT6100_ERR_OK) { ++ printk(KERN_NOTICE "Failed to get instance size, code %08x!\n", ulResult); ++ kfree(vpm450m); ++ kfree(ChipOpen); ++ kfree(ChannelOpen); ++ return NULL; ++ } ++ ++ vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); ++ if (!vpm450m->pApiInstance) { ++ printk(KERN_NOTICE "Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize); ++ kfree(vpm450m); ++ kfree(ChipOpen); ++ kfree(ChannelOpen); ++ return NULL; ++ } ++ ++ ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen); ++ if (ulResult != cOCT6100_ERR_OK) { ++ printk(KERN_NOTICE "Failed to open chip, code %08x!\n", ulResult); ++ vfree(vpm450m->pApiInstance); ++ kfree(vpm450m); ++ kfree(ChipOpen); ++ kfree(ChannelOpen); ++ return NULL; ++ } ++ ++ sout_stream = (8 == numspans) ? 29 : 2; ++ rout_stream = (8 == numspans) ? 24 : 3; ++ ++ for (x = 0; x < ((8 == numspans) ? 256 : 128); x++) { ++ /* execute this loop always on 4 span cards but ++ * on 2 span cards only execute for the channels related to our spans */ ++ if (( numspans > 2) || ((x & 0x03) <2)) { ++ /* span timeslots are interleaved 12341234... ++ * therefore, the lower 2 bits tell us which span this ++ * timeslot/channel ++ */ ++ if (isalaw[x & mask]) { ++ law = cOCT6100_PCM_A_LAW; ++ vpm450m->chanflags[x] |= FLAG_ALAW; ++ } else { ++ law = cOCT6100_PCM_U_LAW; ++ vpm450m->chanflags[x] &= ~(FLAG_ALAW); ++ } ++ Oct6100ChannelOpenDef(ChannelOpen); ++ ChannelOpen->pulChannelHndl = &vpm450m->aulEchoChanHndl[x]; ++ ChannelOpen->ulUserChanId = x; ++ ChannelOpen->TdmConfig.ulRinPcmLaw = law; ++ ChannelOpen->TdmConfig.ulRinStream = 0; ++ ChannelOpen->TdmConfig.ulRinTimeslot = x; ++ ChannelOpen->TdmConfig.ulSinPcmLaw = law; ++ ChannelOpen->TdmConfig.ulSinStream = 1; ++ ChannelOpen->TdmConfig.ulSinTimeslot = x; ++ ChannelOpen->TdmConfig.ulSoutPcmLaw = law; ++ ChannelOpen->TdmConfig.ulSoutStream = sout_stream; ++ ChannelOpen->TdmConfig.ulSoutTimeslot = x; ++#if 1 ++ ChannelOpen->TdmConfig.ulRoutPcmLaw = law; ++ ChannelOpen->TdmConfig.ulRoutStream = rout_stream; ++ ChannelOpen->TdmConfig.ulRoutTimeslot = x; ++#endif ++ ChannelOpen->VqeConfig.fEnableNlp = TRUE; ++ ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE; ++ ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE; ++ ++ ChannelOpen->fEnableToneDisabler = TRUE; ++ ChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL; ++ ++ ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, ChannelOpen); ++ if (ulResult != GENERIC_OK) { ++ printk(KERN_NOTICE "Failed to open channel %d %x!\n", x, ulResult); ++ continue; ++ } ++ for (y = 0; y < ARRAY_SIZE(tones); y++) { ++ tOCT6100_TONE_DETECTION_ENABLE enable; ++ Oct6100ToneDetectionEnableDef(&enable); ++ enable.ulChannelHndl = vpm450m->aulEchoChanHndl[x]; ++ enable.ulToneNumber = tones[y]; ++ if (Oct6100ToneDetectionEnable(vpm450m->pApiInstance, &enable) != GENERIC_OK) ++ printk(KERN_NOTICE "Failed to enable tone detection on channel %d for tone %d!\n", x, y); ++ } ++ } ++ } ++ ++ kfree(ChipOpen); ++ kfree(ChannelOpen); ++ return vpm450m; ++} ++ ++void release_vpm450m(struct vpm450m *vpm450m) ++{ ++ UINT32 ulResult; ++ tOCT6100_CHIP_CLOSE ChipClose; ++ ++ Oct6100ChipCloseDef(&ChipClose); ++ ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose); ++ if (ulResult != cOCT6100_ERR_OK) { ++ printk(KERN_NOTICE "Failed to close chip, code %08x!\n", ulResult); ++ } ++ vfree(vpm450m->pApiInstance); ++ kfree(vpm450m); ++} +diff -Nru linux-source-4.19/drivers/dahdi/wct4xxp/vpm450m.h linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/vpm450m.h +--- linux-source-4.19/drivers/dahdi/wct4xxp/vpm450m.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/vpm450m.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2005-2006 Digium, Inc. ++ * ++ * Mark Spencer ++ * ++ * 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 _VPM450M_H ++#define _VPM450M_H ++ ++#include ++ ++struct t4; ++struct vpm450m; ++ ++/* From driver */ ++unsigned int oct_get_reg(void *data, unsigned int reg); ++void oct_set_reg(void *data, unsigned int reg, unsigned int val); ++ ++/* From vpm450m */ ++struct vpm450m *init_vpm450m(struct device *device, int *isalaw, ++ int numspans, const struct firmware *firmware); ++unsigned int get_vpm450m_capacity(struct device *device); ++void vpm450m_setec(struct vpm450m *instance, int channel, int eclen); ++void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int dtmfmute); ++int vpm450m_checkirq(struct vpm450m *vpm450m); ++int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start); ++void release_vpm450m(struct vpm450m *instance); ++void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, ++ int channel, bool alaw); ++ ++extern int debug; ++ ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/wct4xxp/wct4xxp-diag.c linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/wct4xxp-diag.c +--- linux-source-4.19/drivers/dahdi/wct4xxp/wct4xxp-diag.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wct4xxp/wct4xxp-diag.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,427 @@ ++/* ++ * 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 "wct4xxp.h" ++ ++struct t4_reg_def { ++ int reg; ++ char *name; ++ int global; ++}; ++static struct t4_reg_def xreginfo[] = { ++ { 0x00, "RDADDR" }, ++ { 0x01, "WRADDR" }, ++ { 0x02, "COUNT" }, ++ { 0x03, "DMACTRL" }, ++ { 0x04, "WCINTR" }, ++ { 0x06, "VERSION" }, ++ { 0x07, "LEDS" }, ++ { 0x08, "GPIOCTL" }, ++ { 0x09, "GPIO" }, ++ { 0x0A, "LADDR" }, ++ { 0x0b, "LDATA" }, ++}; ++ ++static struct t4_reg_def reginfo[] = { ++ { 0x00, "XFIFO" }, ++ { 0x01, "XFIFO" }, ++ { 0x02, "CMDR" }, ++ { 0x03, "MODE" }, ++ { 0x04, "RAH1" }, ++ { 0x05, "RAH2" }, ++ { 0x06, "RAL1" }, ++ { 0x07, "RAL2" }, ++ { 0x08, "IPC", 1 }, ++ { 0x09, "CCR1" }, ++ { 0x0a, "CCR2" }, ++ { 0x0c, "RTR1" }, ++ { 0x0d, "RTR2" }, ++ { 0x0e, "RTR3" }, ++ { 0x0f, "RTR4" }, ++ { 0x10, "TTR1" }, ++ { 0x11, "TTR2" }, ++ { 0x12, "TTR3" }, ++ { 0x13, "TTR4" }, ++ { 0x14, "IMR0" }, ++ { 0x15, "IMR1" }, ++ { 0x16, "IMR2" }, ++ { 0x17, "IMR3" }, ++ { 0x18, "IMR4" }, ++ { 0x1b, "IERR" }, ++ { 0x1c, "FMR0" }, ++ { 0x1d, "FMR1" }, ++ { 0x1e, "FMR2" }, ++ { 0x1f, "LOOP" }, ++ { 0x20, "XSW" }, ++ { 0x21, "XSP" }, ++ { 0x22, "XC0" }, ++ { 0x23, "XC1" }, ++ { 0x24, "RC0" }, ++ { 0x25, "RC1" }, ++ { 0x26, "XPM0" }, ++ { 0x27, "XPM1" }, ++ { 0x28, "XPM2" }, ++ { 0x29, "TSWM" }, ++ { 0x2b, "IDLE" }, ++ { 0x2c, "XSA4" }, ++ { 0x2d, "XSA5" }, ++ { 0x2e, "XSA6" }, ++ { 0x2f, "XSA7" }, ++ { 0x30, "XSA8" }, ++ { 0x31, "FMR3" }, ++ { 0x32, "ICB1" }, ++ { 0x33, "ICB2" }, ++ { 0x34, "ICB3" }, ++ { 0x35, "ICB4" }, ++ { 0x36, "LIM0" }, ++ { 0x37, "LIM1" }, ++ { 0x38, "PCD" }, ++ { 0x39, "PCR" }, ++ { 0x3a, "LIM2" }, ++ { 0x3b, "LCR1" }, ++ { 0x3c, "LCR2" }, ++ { 0x3d, "LCR3" }, ++ { 0x3e, "SIC1" }, ++ { 0x3f, "SIC2" }, ++ { 0x40, "SIC3" }, ++ { 0x44, "CMR1" }, ++ { 0x45, "CMR2" }, ++ { 0x46, "GCR" }, ++ { 0x47, "ESM" }, ++ { 0x60, "DEC" }, ++ { 0x70, "XS1" }, ++ { 0x71, "XS2" }, ++ { 0x72, "XS3" }, ++ { 0x73, "XS4" }, ++ { 0x74, "XS5" }, ++ { 0x75, "XS6" }, ++ { 0x76, "XS7" }, ++ { 0x77, "XS8" }, ++ { 0x78, "XS9" }, ++ { 0x79, "XS10" }, ++ { 0x7a, "XS11" }, ++ { 0x7b, "XS12" }, ++ { 0x7c, "XS13" }, ++ { 0x7d, "XS14" }, ++ { 0x7e, "XS15" }, ++ { 0x7f, "XS16" }, ++ { 0x80, "PC1" }, ++ { 0x81, "PC2" }, ++ { 0x82, "PC3" }, ++ { 0x83, "PC4" }, ++ { 0x84, "PC5" }, ++ { 0x85, "GPC1", 1 }, ++ { 0x87, "CMDR2" }, ++ { 0x8d, "CCR5" }, ++ { 0x92, "GCM1", 1 }, ++ { 0x93, "GCM2", 1 }, ++ { 0x94, "GCM3", 1 }, ++ { 0x95, "GCM4", 1 }, ++ { 0x96, "GCM5", 1 }, ++ { 0x97, "GCM6", 1 }, ++ { 0x98, "GCM7", 1 }, ++ { 0x99, "GCM8", 1 }, ++ { 0xa0, "TSEO" }, ++ { 0xa1, "TSBS1" }, ++ { 0xa8, "TPC0" }, ++}; ++ ++static struct t4_reg_def t1_reginfo[] = { ++ { 0x00, "XFIFO" }, ++ { 0x01, "XFIFO" }, ++ { 0x02, "CMDR" }, ++ { 0x03, "MODE" }, ++ { 0x04, "RAH1" }, ++ { 0x05, "RAH2" }, ++ { 0x06, "RAL1" }, ++ { 0x07, "RAL2" }, ++ { 0x08, "IPC", 1 }, ++ { 0x09, "CCR1" }, ++ { 0x0a, "CCR2" }, ++ { 0x0c, "RTR1" }, ++ { 0x0d, "RTR2" }, ++ { 0x0e, "RTR3" }, ++ { 0x0f, "RTR4" }, ++ { 0x10, "TTR1" }, ++ { 0x11, "TTR2" }, ++ { 0x12, "TTR3" }, ++ { 0x13, "TTR4" }, ++ { 0x14, "IMR0" }, ++ { 0x15, "IMR1" }, ++ { 0x16, "IMR2" }, ++ { 0x17, "IMR3" }, ++ { 0x18, "IMR4" }, ++ { 0x1b, "IERR" }, ++ { 0x1c, "FMR0" }, ++ { 0x1d, "FMR1" }, ++ { 0x1e, "FMR2" }, ++ { 0x1f, "LOOP" }, ++ { 0x20, "FMR4" }, ++ { 0x21, "FMR5" }, ++ { 0x22, "XC0" }, ++ { 0x23, "XC1" }, ++ { 0x24, "RC0" }, ++ { 0x25, "RC1" }, ++ { 0x26, "XPM0" }, ++ { 0x27, "XPM1" }, ++ { 0x28, "XPM2" }, ++ { 0x2b, "IDLE" }, ++ { 0x2c, "XDL1" }, ++ { 0x2d, "XDL2" }, ++ { 0x2e, "XDL3" }, ++ { 0x2f, "CCB1" }, ++ { 0x30, "CCB2" }, ++ { 0x31, "CCB3" }, ++ { 0x32, "ICB1" }, ++ { 0x33, "ICB2" }, ++ { 0x34, "ICB3" }, ++ { 0x36, "LIM0" }, ++ { 0x37, "LIM1" }, ++ { 0x38, "PCD" }, ++ { 0x39, "PCR" }, ++ { 0x3a, "LIM2" }, ++ { 0x3b, "LCR1" }, ++ { 0x3c, "LCR2" }, ++ { 0x3d, "LCR3" }, ++ { 0x3e, "SIC1" }, ++ { 0x3f, "SIC2" }, ++ { 0x40, "SIC3" }, ++ { 0x44, "CMR1" }, ++ { 0x45, "CMR2" }, ++ { 0x46, "GCR" }, ++ { 0x47, "ESM" }, ++ { 0x60, "DEC" }, ++ { 0x70, "XS1" }, ++ { 0x71, "XS2" }, ++ { 0x72, "XS3" }, ++ { 0x73, "XS4" }, ++ { 0x74, "XS5" }, ++ { 0x75, "XS6" }, ++ { 0x76, "XS7" }, ++ { 0x77, "XS8" }, ++ { 0x78, "XS9" }, ++ { 0x79, "XS10" }, ++ { 0x7a, "XS11" }, ++ { 0x7b, "XS12" }, ++ { 0x80, "PC1" }, ++ { 0x81, "PC2" }, ++ { 0x82, "PC3" }, ++ { 0x83, "PC4" }, ++ { 0x84, "PC5" }, ++ { 0x85, "GPC1", 1 }, ++ { 0x87, "CMDR2" }, ++ { 0x8d, "CCR5" }, ++ { 0x92, "GCM1", 1 }, ++ { 0x93, "GCM2", 1 }, ++ { 0x94, "GCM3", 1 }, ++ { 0x95, "GCM4", 1 }, ++ { 0x96, "GCM5", 1 }, ++ { 0x97, "GCM6", 1 }, ++ { 0x98, "GCM7", 1 }, ++ { 0x99, "GCM8", 1 }, ++ { 0xa0, "TSEO" }, ++ { 0xa1, "TSBS1" }, ++ { 0xa8, "TPC0" }, ++}; ++ ++static struct t4_reg_def t1_sreginfo[] = { ++ { 0x00, "RFIFO" }, ++ { 0x01, "RFIFO" }, ++ { 0x49, "RBD" }, ++ { 0x4a, "VSTR", 1 }, ++ { 0x4b, "RES" }, ++ { 0x4c, "FRS0" }, ++ { 0x4d, "FRS1" }, ++ { 0x4e, "FRS2" }, ++ { 0x4f, "Old FRS1" }, ++ { 0x50, "FECL" }, ++ { 0x51, "FECH" }, ++ { 0x52, "CVCL" }, ++ { 0x53, "CVCH" }, ++ { 0x54, "CECL" }, ++ { 0x55, "CECH" }, ++ { 0x56, "EBCL" }, ++ { 0x57, "EBCH" }, ++ { 0x58, "BECL" }, ++ { 0x59, "BECH" }, ++ { 0x5a, "COEC" }, ++ { 0x5c, "RDL1" }, ++ { 0x5d, "RDL2" }, ++ { 0x5e, "RDL3" }, ++ { 0x62, "RSP1" }, ++ { 0x63, "RSP2" }, ++ { 0x64, "SIS" }, ++ { 0x65, "RSIS" }, ++ { 0x66, "RBCL" }, ++ { 0x67, "RBCH" }, ++ { 0x68, "ISR0" }, ++ { 0x69, "ISR1" }, ++ { 0x6a, "ISR2" }, ++ { 0x6b, "ISR3" }, ++ { 0x6c, "ISR4" }, ++ { 0x6e, "GIS" }, ++ { 0x6f, "CIS", 1 }, ++ { 0x70, "RS1" }, ++ { 0x71, "RS2" }, ++ { 0x72, "RS3" }, ++ { 0x73, "RS4" }, ++ { 0x74, "RS5" }, ++ { 0x75, "RS6" }, ++ { 0x76, "RS7" }, ++ { 0x77, "RS8" }, ++ { 0x78, "RS9" }, ++ { 0x79, "RS10" }, ++ { 0x7a, "RS11" }, ++ { 0x7b, "RS12" }, ++}; ++ ++static struct t4_reg_def sreginfo[] = { ++ { 0x00, "RFIFO" }, ++ { 0x01, "RFIFO" }, ++ { 0x49, "RBD" }, ++ { 0x4a, "VSTR", 1 }, ++ { 0x4b, "RES" }, ++ { 0x4c, "FRS0" }, ++ { 0x4d, "FRS1" }, ++ { 0x4e, "RSW" }, ++ { 0x4f, "RSP" }, ++ { 0x50, "FECL" }, ++ { 0x51, "FECH" }, ++ { 0x52, "CVCL" }, ++ { 0x53, "CVCH" }, ++ { 0x54, "CEC1L" }, ++ { 0x55, "CEC1H" }, ++ { 0x56, "EBCL" }, ++ { 0x57, "EBCH" }, ++ { 0x58, "CEC2L" }, ++ { 0x59, "CEC2H" }, ++ { 0x5a, "CEC3L" }, ++ { 0x5b, "CEC3H" }, ++ { 0x5c, "RSA4" }, ++ { 0x5d, "RSA5" }, ++ { 0x5e, "RSA6" }, ++ { 0x5f, "RSA7" }, ++ { 0x60, "RSA8" }, ++ { 0x61, "RSA6S" }, ++ { 0x62, "RSP1" }, ++ { 0x63, "RSP2" }, ++ { 0x64, "SIS" }, ++ { 0x65, "RSIS" }, ++ { 0x66, "RBCL" }, ++ { 0x67, "RBCH" }, ++ { 0x68, "ISR0" }, ++ { 0x69, "ISR1" }, ++ { 0x6a, "ISR2" }, ++ { 0x6b, "ISR3" }, ++ { 0x6c, "ISR4" }, ++ { 0x6e, "GIS" }, ++ { 0x6f, "CIS", 1 }, ++ { 0x70, "RS1" }, ++ { 0x71, "RS2" }, ++ { 0x72, "RS3" }, ++ { 0x73, "RS4" }, ++ { 0x74, "RS5" }, ++ { 0x75, "RS6" }, ++ { 0x76, "RS7" }, ++ { 0x77, "RS8" }, ++ { 0x78, "RS9" }, ++ { 0x79, "RS10" }, ++ { 0x7a, "RS11" }, ++ { 0x7b, "RS12" }, ++ { 0x7c, "RS13" }, ++ { 0x7d, "RS14" }, ++ { 0x7e, "RS15" }, ++ { 0x7f, "RS16" }, ++}; ++ ++static char *tobin(int x) ++{ ++ static char s[9] = ""; ++ int y,z=0; ++ for (y=7;y>=0;y--) { ++ if (x & (1 << y)) ++ s[z++] = '1'; ++ else ++ s[z++] = '0'; ++ } ++ s[z] = '\0'; ++ return s; ++} ++ ++static char *tobin32(unsigned int x) ++{ ++ static char s[33] = ""; ++ int y,z=0; ++ for (y=31;y>=0;y--) { ++ if (x & (1 << y)) ++ s[z++] = '1'; ++ else ++ s[z++] = '0'; ++ } ++ s[z] = '\0'; ++ return s; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int fd; ++ int x; ++ char fn[256]; ++ struct t4_regs regs; ++ if ((argc < 2) || ((*(argv[1]) != '/') && !atoi(argv[1]))) { ++ fprintf(stderr, "Usage: wct4xxp-diag \n"); ++ exit(1); ++ } ++ if (*(argv[1]) == '/') ++ dahdi_copy_string(fn, argv[1], sizeof(fn)); ++ else ++ snprintf(fn, sizeof(fn), "/dev/dahdi/%d", atoi(argv[1])); ++ fd = open(fn, O_RDWR); ++ if (fd <0) { ++ fprintf(stderr, "Unable to open '%s': %s\n", fn, strerror(errno)); ++ exit(1); ++ } ++ if (ioctl(fd, WCT4_GET_REGS, ®s)) { ++ fprintf(stderr, "Unable to get registers: %s\n", strerror(errno)); ++ exit(1); ++ } ++ printf("PCI Registers:\n"); ++ for (x=0;x ++ * ++ * Copyright (C) 2001-2010, 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 ++ ++#define FRMR_TTR_BASE 0x10 ++#define FRMR_RTR_BASE 0x0c ++#define FRMR_TSEO 0xa0 ++#define FRMR_TSBS1 0xa1 ++#define FRMR_CCR1 0x09 ++#define FRMR_CCR1_ITF 0x08 ++#define FRMR_CCR1_EITS 0x10 ++#define FRMR_CCR2 0x0a ++#define FRMR_CCR2_RCRC 0x04 ++#define FRMR_CCR2_RADD 0x10 ++#define FRMR_MODE 0x03 ++#define FRMR_MODE_NO_ADDR_CMP 0x80 ++#define FRMR_MODE_SS7 0x20 ++#define FRMR_MODE_HRAC 0x08 ++#define FRMR_IMR0 0x14 ++#define FRMR_IMR0_RME 0x80 ++#define FRMR_IMR0_RPF 0x01 ++#define FRMR_IMR1 0x15 ++#define FRMR_IMR1_ALLS 0x20 ++#define FRMR_IMR1_XDU 0x10 ++#define FRMR_IMR1_XPR 0x01 ++#define FRMR_XC0 0x22 ++#define FRMR_XC1 0x23 ++#define FRMR_RC0 0x24 ++#define FRMR_RC1 0x25 ++#define FRMR_SIC1 0x3e ++#define FRMR_SIC2 0x3f ++#define FRMR_SIC3 0x40 ++#define FRMR_CMR1 0x44 ++#define FRMR_CMR2 0x45 ++/* OctalFALC Only */ ++#define FRMR_CMR4 0x41 ++#define FRMR_CMR5 0x42 ++#define FRMR_CMR6 0x43 ++#define FRMR_GPC2 0x8a ++/* End Octal */ ++#define FRMR_GCR 0x46 ++#define FRMR_ISR0 0x68 ++#define FRMR_ISR0_RME 0x80 ++#define FRMR_ISR0_RPF 0x01 ++#define FRMR_ISR1 0x69 ++#define FRMR_ISR1_ALLS 0x20 ++#define FRMR_ISR1_XDU 0x10 ++#define FRMR_ISR1_XPR 0x01 ++#define FRMR_ISR2 0x6a ++#define FRMR_ISR3 0x6b ++#define FRMR_ISR4 0x6c ++#define FRMR_GIS 0x6e ++#define FRMR_GIS_ISR0 0x01 ++#define FRMR_GIS_ISR1 0x02 ++#define FRMR_GIS_ISR2 0x04 ++#define FRMR_GIS_ISR3 0x08 ++#define FRMR_GIS_ISR4 0x10 ++#define FRMR_CIS 0x6f ++#define FRMR_CIS_GIS1 0x01 ++#define FRMR_CIS_GIS2 0x02 ++#define FRMR_CIS_GIS3 0x04 ++#define FRMR_CIS_GIS4 0x08 ++ ++/* CIS - Octal falc bits */ ++#define FRMR_CIS_GIS5 0x10 ++#define FRMR_CIS_GIS6 0x20 ++#define FRMR_CIS_GIS7 0x40 ++#define FRMR_CIS_GIS8 0x80 ++ ++#define FRMR_CMDR 0x02 ++#define FRMR_CMDR_SRES 0x01 ++#define FRMR_CMDR_XRES 0x10 ++#define FRMR_CMDR_RMC 0x80 ++#define FRMR_CMDR_XTF 0x04 ++#define FRMR_CMDR_XHF 0x08 ++#define FRMR_CMDR_XME 0x02 ++#define FRMR_RSIS 0x65 ++#define FRMR_RSIS_VFR 0x80 ++#define FRMR_RSIS_RDO 0x40 ++#define FRMR_RSIS_CRC16 0x20 ++#define FRMR_RSIS_RAB 0x10 ++#define FRMR_RBCL 0x66 ++#define FRMR_RBCL_MAX_SIZE 0x1f ++#define FRMR_RBCH 0x67 ++#define FRMR_RXFIFO 0x00 ++#define FRMR_SIS 0x64 ++#define FRMR_SIS_XFW 0x40 ++#define FRMR_TXFIFO 0x00 ++ ++#define FRS0 0x4c ++#define FRS0_LOS (1<<7) ++#define FRS0_LFA (1<<5) ++#define FRS0_LMFA (1<<1) ++ ++#define FRS1 0x4d ++#define FRS1_XLS (1<<1) ++#define FRS1_XLO (1<<0) ++ ++#define NUM_REGS 0xa9 ++#define NUM_PCI 12 ++ ++struct t4_regs { ++ unsigned int pci[NUM_PCI]; ++ unsigned char regs[NUM_REGS]; ++}; ++ ++struct t4_reg { ++ unsigned int reg; ++ unsigned int val; ++}; ++ ++#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs) ++#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg) ++#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg) ++ +diff -Nru linux-source-4.19/drivers/dahdi/wctc4xxp/Kbuild linux-source-4.19-dahdi/drivers/dahdi/wctc4xxp/Kbuild +--- linux-source-4.19/drivers/dahdi/wctc4xxp/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wctc4xxp/Kbuild 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,18 @@ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp.o ++ ++FIRM_DIR := ../firmware ++ ++EXTRA_CFLAGS += -I$(src)/.. -Wno-undef ++ ++ifeq ($(HOTPLUG_FIRMWARE),yes) ++ EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE ++endif ++ ++wctc4xxp-objs := base.o ++ ++ifneq ($(HOTPLUG_FIRMWARE),yes) ++wctc4xxp-objs += $(FIRM_DIR)/dahdi-fw-tc400m.o ++endif ++ ++$(obj)/$(FIRM_DIR)/dahdi-fw-tc400m.o: $(obj)/base.o ++ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-tc400m.o +diff -Nru linux-source-4.19/drivers/dahdi/wctc4xxp/base.c linux-source-4.19-dahdi/drivers/dahdi/wctc4xxp/base.c +--- linux-source-4.19/drivers/dahdi/wctc4xxp/base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wctc4xxp/base.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,4261 @@ ++/* Wildcard TC400B Driver ++ * ++ * Copyright (C) 2006-2012, 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 ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#include ++#endif /* 4.11.0 */ ++ ++ ++#include ++ ++/* COMPILE TIME OPTIONS =================================================== */ ++ ++#define INTERRUPT 0 ++#define WORKQUEUE 1 ++#define TASKLET 2 ++ ++/* Define if you want a debug attribute to test alert processing. */ ++#undef EXPORT_FOR_ALERT_ATTRIBUTE ++ ++#ifndef DEFERRED_PROCESSING ++# define DEFERRED_PROCESSING WORKQUEUE ++#endif ++ ++#if DEFERRED_PROCESSING == INTERRUPT ++# define ALLOC_FLAGS GFP_ATOMIC ++#elif DEFERRED_PROCESSING == TASKLET ++# define ALLOC_FLAGS GFP_ATOMIC ++#else ++# define ALLOC_FLAGS GFP_KERNEL ++#endif ++ ++#define WARN_ALWAYS() WARN_ON(1) ++ ++#define DTE_DEBUG(_dbgmask, _fmt, _args...) \ ++ if ((debug & _dbgmask) == (_dbgmask)) { \ ++ dev_info(&(wc)->pdev->dev, _fmt, ## _args); \ ++ } \ ++ ++ ++/* define CONFIG_WCTC4XXP_POLLING to operate in a pure polling mode. This is ++ * was placed in as a debugging tool for a particluar system that wasn't ++ * routing the interrupt properly. Therefore it is off by default and the ++ * driver must be recompiled to enable it. */ ++#undef CONFIG_WCTC4XXP_POLLING ++ ++/* The total number of active channels over which the driver will start polling ++ * the card every 10 ms. */ ++#define POLLING_CALL_THRESHOLD 40 ++ ++#define INVALID 999 /* Used to mark invalid channels, commands, etc.. */ ++#define MAX_CHANNEL_PACKETS 5 ++ ++#define G729_LENGTH 20 ++#define G723_LENGTH 30 ++ ++#define G729_SAMPLES 160 /* G.729 */ ++#define G723_SAMPLES 240 /* G.723.1 */ ++ ++#define G729_BYTES 20 /* G.729 */ ++#define G723_6K_BYTES 24 /* G.723.1 at 6.3kb/s */ ++#define G723_5K_BYTES 20 /* G.723.1 at 5.3kb/s */ ++#define G723_SID_BYTES 4 /* G.723.1 SID frame */ ++ ++#define MAX_CAPTURED_PACKETS 5000 ++ ++/* The following bit fields are used to set the various debug levels. */ ++#define DTE_DEBUG_GENERAL (1 << 0) /* 1 */ ++#define DTE_DEBUG_CHANNEL_SETUP (1 << 1) /* 2 */ ++#define DTE_DEBUG_RTP_TX (1 << 2) /* 4 */ ++#define DTE_DEBUG_RTP_RX (1 << 3) /* 8 */ ++#define DTE_DEBUG_RX_TIMEOUT (1 << 4) /* 16 */ ++#define DTE_DEBUG_NETWORK_IF (1 << 5) /* 32 */ ++#define DTE_DEBUG_NETWORK_EARLY (1 << 6) /* 64 */ ++#define DTE_DEBUG_ETH_STATS (1 << 7) /* 128 */ ++ ++static int debug; ++static char *mode; ++ ++static spinlock_t wctc4xxp_list_lock; ++static struct list_head wctc4xxp_list; ++ ++#define ETH_P_CSM_ENCAPS 0x889B ++ ++struct rtphdr { ++#if defined(__LITTLE_ENDIAN_BITFIELD) ++ __u8 csrc_count:4; ++ __u8 extension:1; ++ __u8 padding:1; ++ __u8 ver:2; ++ __u8 type:7; ++ __u8 marker:1; ++#elif defined(__BIG_ENDIAN_BITFIELD) ++ __u8 ver:2; ++ __u8 padding:1; ++ __u8 extension:1; ++ __u8 csrc_count:4; ++ __u8 marker:1; ++ __u8 type:7; ++#else ++#error "Please fix " ++#endif ++ __be16 seqno; ++ __be32 timestamp; ++ __be32 ssrc; ++} __attribute__((packed)); ++ ++struct rtp_packet { ++ struct ethhdr ethhdr; ++ struct iphdr iphdr; ++ struct udphdr udphdr; ++ struct rtphdr rtphdr; ++ __u8 payload[0]; ++} __attribute__((packed)); ++ ++struct csm_encaps_cmd { ++ /* COMMON PART OF PAYLOAD HEADER */ ++ __u8 length; ++ __u8 index; ++ __u8 type; ++ __u8 class; ++ __le16 function; ++ __le16 reserved; ++ __le16 params[0]; ++} __attribute__((packed)); ++ ++/* Ethernet packet type for communication control information to the DTE. */ ++struct csm_encaps_hdr { ++ struct ethhdr ethhdr; ++ /* CSM_ENCAPS HEADER */ ++ __be16 op_code; ++ __u8 seq_num; ++ __u8 control; ++ __be16 channel; ++ /* There is always at least one command. */ ++ struct csm_encaps_cmd cmd; ++} __attribute__((packed)); ++ ++#define CONTROL_PACKET_OPCODE 0x0001 ++/* Control bits */ ++#define LITTLE_ENDIAN 0x01 ++#define SUPPRESS_ACK 0x40 ++#define MESSAGE_PACKET 0x80 ++ ++#define SUPERVISOR_CHANNEL 0xffff ++ ++/* Supervisor function codes */ ++#define SUPVSR_CREATE_CHANNEL 0x0010 ++ ++#define MONITOR_LIVE_INDICATION_TYPE 0x75 ++#define VOIP_VCEINFO_TYPE 0x0e ++#define CONFIG_CHANGE_TYPE 0x00 ++#define CONFIG_CHANNEL_CLASS 0x02 ++#define CONFIG_DEVICE_CLASS 0x06 ++ ++/* Individual channel config commands */ ++#define MAX_FRAME_SIZE 1518 ++#define SFRAME_SIZE MAX_FRAME_SIZE ++ ++#define DEFAULT_RX_DRING_SIZE (1 << 6) /* Must be a power of two */ ++ ++/* Keep the TX ring shorter in order to reduce the amount of time needed to ++ * bring up channels when sending high priority csm_encaps packets. */ ++#define DEFAULT_TX_DRING_SIZE (1 << 4) /* Must be a power of two */ ++#define MIN_PACKET_LEN 64 ++ ++/* Transcoder buffer (tcb) */ ++struct tcb { ++ void *data; ++ struct list_head node; ++ unsigned long timeout; ++ unsigned long retries; ++#define TX_COMPLETE (1 << 1) ++#define DO_NOT_CAPTURE (1 << 2) ++#define WAIT_FOR_ACK (1 << 3) ++#define WAIT_FOR_RESPONSE (1 << 4) ++#define DTE_CMD_TIMEOUT (1 << 5) ++ u16 flags; ++ u16 next_index; ++ struct completion *complete; ++ struct tcb *response; ++ struct channel_pvt *cpvt; ++ /* The number of bytes available in data. */ ++ int data_len; ++}; ++ ++static inline const struct csm_encaps_hdr * ++response_header(struct tcb *cmd) ++{ ++ BUG_ON(!cmd->response); ++ return (const struct csm_encaps_hdr *)(cmd)->response->data; ++} ++ ++static inline void ++initialize_cmd(struct tcb *cmd, unsigned long cmd_flags) ++{ ++ INIT_LIST_HEAD(&cmd->node); ++ cmd->flags = cmd_flags; ++} ++ ++/*! Used to allocate commands to submit to the dte. */ ++static struct kmem_cache *cmd_cache; ++ ++static inline struct tcb * ++__alloc_cmd(size_t size, gfp_t alloc_flags, unsigned long cmd_flags) ++{ ++ struct tcb *cmd; ++ ++ if (unlikely(size > SFRAME_SIZE)) ++ return NULL; ++ if (size < MIN_PACKET_LEN) ++ size = MIN_PACKET_LEN; ++ cmd = kmem_cache_alloc(cmd_cache, alloc_flags); ++ if (likely(cmd)) { ++ memset(cmd, 0, sizeof(*cmd)); ++ cmd->data = kzalloc(size, alloc_flags); ++ if (unlikely(!cmd->data)) { ++ kmem_cache_free(cmd_cache, cmd); ++ return NULL; ++ } ++ cmd->data_len = size; ++ initialize_cmd(cmd, cmd_flags); ++ } ++ return cmd; ++} ++ ++static struct tcb * ++alloc_cmd(size_t size) ++{ ++ return __alloc_cmd(size, GFP_KERNEL, 0); ++} ++ ++static void ++__free_cmd(struct tcb *cmd) ++{ ++ if (cmd) ++ kfree(cmd->data); ++ kmem_cache_free(cmd_cache, cmd); ++ return; ++} ++ ++static void ++free_cmd(struct tcb *cmd) ++{ ++ if (cmd->response) ++ __free_cmd(cmd->response); ++ __free_cmd(cmd); ++} ++ ++struct channel_stats { ++ atomic_t packets_sent; ++ atomic_t packets_received; ++}; ++ ++struct channel_pvt { ++ spinlock_t lock; /* Lock for this structure */ ++ struct wcdte *wc; ++ u16 seqno; ++ u8 cmd_seqno; ++ u8 ssrc; ++ u8 last_rx_seq_num; ++ u16 timeslot_in_num; /* DTE timeslot to receive from */ ++ u16 timeslot_out_num; /* DTE timeslot to send data to */ ++ u16 chan_in_num; /* DTE channel to receive from */ ++ u16 chan_out_num; /* DTE channel to send data to */ ++ u32 last_timestamp; ++ struct { ++ u8 encoder:1; /* If we're an encoder */ ++ }; ++ struct channel_stats stats; ++ struct list_head rx_queue; /* Transcoded packets for this channel. */ ++ ++ /* Used to prevent user space from flooding the firmware. */ ++ long samples_in_flight; ++ unsigned long send_time; ++}; ++ ++struct wcdte { ++ char board_name[40]; ++ const char *variety; ++ int pos; ++ struct list_head node; ++ spinlock_t reglock; ++ wait_queue_head_t waitq; ++ struct mutex chanlock; ++#define DTE_READY 1 ++#define DTE_SHUTDOWN 2 ++#define DTE_POLLING 3 ++#define DTE_RELOAD 4 ++ unsigned long flags; ++ ++ /* This is a device-global list of commands that are waiting to be ++ * transmited (and did not fit on the transmit descriptor ring) */ ++ spinlock_t cmd_list_lock; ++ struct list_head cmd_list; ++ struct list_head waiting_for_response_list; ++ ++ spinlock_t rx_list_lock; ++ struct list_head rx_list; ++ spinlock_t rx_lock; ++ ++ unsigned int seq_num; ++ int last_rx_seq_num; ++ unsigned char numchannels; ++ unsigned char complexname[40]; ++ ++ /* This section contains the members necessary to communicate with the ++ * physical interface to the transcoding engine. */ ++ struct pci_dev *pdev; ++ unsigned int intmask; ++ void __iomem *iobase; ++ struct wctc4xxp_descriptor_ring *txd; ++ struct wctc4xxp_descriptor_ring *rxd; ++ ++ struct dahdi_transcoder *uencode; ++ struct dahdi_transcoder *udecode; ++ struct channel_pvt *encoders; ++ struct channel_pvt *decoders; ++ ++#if DEFERRED_PROCESSING == WORKQUEUE ++ struct work_struct deferred_work; ++#endif ++ ++ /* ++ * This section contains the members necessary for exporting the ++ * network interface to the host system. This is only used for ++ * debugging purposes. ++ * ++ */ ++ struct sk_buff_head captured_packets; ++ struct net_device *netdev; ++ struct net_device_stats net_stats; ++ struct napi_struct napi; ++ struct timer_list watchdog; ++ u16 open_channels; ++ unsigned long reported_packet_errors; ++}; ++ ++struct wcdte_netdev_priv { ++ struct wcdte *wc; ++}; ++ ++static inline struct wcdte * ++wcdte_from_netdev(struct net_device *netdev) ++{ ++ struct wcdte_netdev_priv *priv; ++ priv = netdev_priv(netdev); ++ return priv->wc; ++} ++ ++ ++static inline void wctc4xxp_set_ready(struct wcdte *wc) ++{ ++ set_bit(DTE_READY, &wc->flags); ++} ++ ++static inline int wctc4xxp_is_ready(struct wcdte *wc) ++{ ++ return test_bit(DTE_READY, &wc->flags); ++} ++ ++#define DTE_FORMAT_ULAW 0x00 ++#define DTE_FORMAT_G723_1 0x04 ++#define DTE_FORMAT_ALAW 0x08 ++#define DTE_FORMAT_G729A 0x12 ++#define DTE_FORMAT_UNDEF 0xFF ++ ++static inline u8 wctc4xxp_dahdifmt_to_dtefmt(unsigned int fmt) ++{ ++ u8 pt; ++ ++ switch (fmt) { ++ case DAHDI_FORMAT_G723_1: ++ pt = DTE_FORMAT_G723_1; ++ break; ++ case DAHDI_FORMAT_ULAW: ++ pt = DTE_FORMAT_ULAW; ++ break; ++ case DAHDI_FORMAT_ALAW: ++ pt = DTE_FORMAT_ALAW; ++ break; ++ case DAHDI_FORMAT_G729A: ++ pt = DTE_FORMAT_G729A; ++ break; ++ default: ++ pt = DTE_FORMAT_UNDEF; ++ break; ++ } ++ ++ return pt; ++} ++ ++static struct sk_buff * ++tcb_to_skb(struct net_device *netdev, const struct tcb *cmd) ++{ ++ struct sk_buff *skb; ++ skb = alloc_skb(cmd->data_len, in_atomic() ? GFP_ATOMIC : GFP_KERNEL); ++ if (skb) { ++ skb->dev = netdev; ++ skb_put(skb, cmd->data_len); ++ memcpy(skb->data, cmd->data, cmd->data_len); ++ skb->protocol = eth_type_trans(skb, netdev); ++ } ++ return skb; ++} ++ ++/** ++ * wctc4xxp_skb_to_cmd - Convert a socket buffer (skb) to a tcb ++ * @wc: The transcoder that we're going to send this command to. ++ * @skb: socket buffer to convert. ++ * ++ */ ++static struct tcb * ++wctc4xxp_skb_to_cmd(struct wcdte *wc, const struct sk_buff *skb) ++{ ++ const gfp_t alloc_flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; ++ struct tcb *cmd; ++ cmd = __alloc_cmd(skb->len, alloc_flags, 0); ++ if (cmd) { ++ int res; ++ cmd->data_len = skb->len; ++ res = skb_copy_bits(skb, 0, cmd->data, cmd->data_len); ++ if (res) { ++ dev_warn(&wc->pdev->dev, ++ "Failed call to skb_copy_bits.\n"); ++ free_cmd(cmd); ++ cmd = NULL; ++ } ++ } ++ return cmd; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) ++static void ++wctc4xxp_net_set_multi(struct net_device *netdev) ++{ ++ struct wcdte *wc = wcdte_from_netdev(netdev); ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "%s promiscuity:%d\n", ++ __func__, netdev->promiscuity); ++} ++#else ++static void ++wctc4xxp_set_rx_mode(struct net_device *netdev) ++{ ++ struct wcdte *wc = wcdte_from_netdev(netdev); ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "%s promiscuity:%d\n", ++ __func__, netdev->promiscuity); ++} ++#endif ++ ++static int ++wctc4xxp_net_up(struct net_device *netdev) ++{ ++ struct wcdte *wc = wcdte_from_netdev(netdev); ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __func__); ++ napi_enable(&wc->napi); ++ return 0; ++} ++ ++static int ++wctc4xxp_net_down(struct net_device *netdev) ++{ ++ struct wcdte *wc = wcdte_from_netdev(netdev); ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __func__); ++ napi_disable(&wc->napi); ++ return 0; ++} ++ ++static void wctc4xxp_transmit_cmd(struct wcdte *, struct tcb *); ++ ++static int ++wctc4xxp_net_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) ++{ ++ struct wcdte *wc = wcdte_from_netdev(netdev); ++ struct tcb *cmd; ++ ++ /* We set DO_NOT_CAPTURE because this packet was already captured by ++ * in code higher up in the networking stack. We don't want to ++ * capture it twice. ++ */ ++ cmd = wctc4xxp_skb_to_cmd(wc, skb); ++ if (cmd) { ++ cmd->flags |= DO_NOT_CAPTURE; ++ wctc4xxp_transmit_cmd(wc, cmd); ++ } ++ ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++} ++ ++static int ++wctc4xxp_net_receive(struct wcdte *wc, int max) ++{ ++ int count = 0; ++ struct sk_buff *skb; ++ WARN_ON(0 == max); ++ while ((skb = skb_dequeue(&wc->captured_packets))) { ++ netif_receive_skb(skb); ++ if (++count >= max) ++ break; ++ } ++ return count; ++} ++ ++static int ++wctc4xxp_poll(struct napi_struct *napi, int budget) ++{ ++ struct wcdte *wc = container_of(napi, struct wcdte, napi); ++ int count; ++ ++ count = wctc4xxp_net_receive(wc, budget); ++ ++ if (!skb_queue_len(&wc->captured_packets)) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++ netif_rx_complete(wc->netdev, &wc->napi); ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ++ netif_rx_complete(&wc->napi); ++#else ++ napi_complete(&wc->napi); ++#endif ++ } ++ return count; ++} ++ ++static struct net_device_stats * ++wctc4xxp_net_get_stats(struct net_device *netdev) ++{ ++ struct wcdte *wc = wcdte_from_netdev(netdev); ++ return &wc->net_stats; ++} ++ ++/* Wait until this device is put into promiscuous mode, or we timeout. */ ++static void ++wctc4xxp_net_waitfor_promiscuous(struct wcdte *wc) ++{ ++ unsigned int seconds = 15; ++ unsigned long start = jiffies; ++ struct net_device *netdev = wc->netdev; ++ ++ dev_info(&wc->pdev->dev, ++ "Waiting %d seconds for adapter to be placed in " \ ++ "promiscuous mode for early trace.\n", seconds); ++ ++ while (!netdev->promiscuity) { ++ if (signal_pending(current)) { ++ dev_info(&wc->pdev->dev, ++ "Aborting wait due to signal.\n"); ++ break; ++ } ++ msleep(100); ++ if (time_after(jiffies, start + (seconds * HZ))) { ++ dev_info(&wc->pdev->dev, ++ "Aborting wait due to timeout.\n"); ++ break; ++ } ++ } ++} ++ ++#ifdef HAVE_NET_DEVICE_OPS ++static const struct net_device_ops wctc4xxp_netdev_ops = { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) ++ .ndo_set_multicast_list = &wctc4xxp_net_set_multi, ++#else ++ .ndo_set_rx_mode = &wctc4xxp_set_rx_mode, ++#endif ++ .ndo_open = &wctc4xxp_net_up, ++ .ndo_stop = &wctc4xxp_net_down, ++ .ndo_start_xmit = &wctc4xxp_net_hard_start_xmit, ++ .ndo_get_stats = &wctc4xxp_net_get_stats, ++}; ++#endif ++ ++/** ++ * wctc4xxp_net_register - Register a new network interface. ++ * @wc: transcoder card to register the interface for. ++ * ++ * The network interface is primarily used for debugging in order to watch the ++ * traffic between the transcoder and the host. ++ * ++ */ ++static int ++wctc4xxp_net_register(struct wcdte *wc) ++{ ++ int res; ++ struct net_device *netdev; ++ struct wcdte_netdev_priv *priv; ++ const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) ++ netdev = alloc_netdev(sizeof(*priv), wc->board_name, ++ NET_NAME_UNKNOWN, ether_setup); ++#else ++ netdev = alloc_netdev(sizeof(*priv), wc->board_name, ether_setup); ++#endif ++ ++ if (!netdev) ++ return -ENOMEM; ++ priv = netdev_priv(netdev); ++ priv->wc = wc; ++ memcpy(netdev->dev_addr, our_mac, sizeof(our_mac)); ++ ++# ifdef HAVE_NET_DEVICE_OPS ++ netdev->netdev_ops = &wctc4xxp_netdev_ops; ++# else ++ netdev->set_multicast_list = &wctc4xxp_net_set_multi; ++ netdev->open = &wctc4xxp_net_up; ++ netdev->stop = &wctc4xxp_net_down; ++ netdev->hard_start_xmit = &wctc4xxp_net_hard_start_xmit; ++ netdev->get_stats = &wctc4xxp_net_get_stats; ++# endif ++ ++ netdev->promiscuity = 0; ++ netdev->flags |= IFF_NOARP; ++ ++ netif_napi_add(netdev, &wc->napi, &wctc4xxp_poll, 64); ++ ++ res = register_netdev(netdev); ++ if (res) { ++ dev_warn(&wc->pdev->dev, ++ "Failed to register network device %s.\n", ++ wc->board_name); ++ goto error_sw; ++ } ++ ++ wc->netdev = netdev; ++ skb_queue_head_init(&wc->captured_packets); ++ ++ if (debug & DTE_DEBUG_NETWORK_EARLY) ++ wctc4xxp_net_waitfor_promiscuous(wc); ++ ++ dev_info(&wc->pdev->dev, ++ "Created network device %s for debug.\n", wc->board_name); ++ return 0; ++ ++error_sw: ++ if (netdev) ++ free_netdev(netdev); ++ return res; ++} ++ ++static void ++wctc4xxp_net_unregister(struct wcdte *wc) ++{ ++ struct sk_buff *skb; ++ ++ if (!wc->netdev) ++ return; ++ unregister_netdev(wc->netdev); ++ while ((skb = skb_dequeue(&wc->captured_packets))) ++ kfree_skb(skb); ++ free_netdev(wc->netdev); ++ wc->netdev = NULL; ++} ++ ++ ++/** ++ * wctc4xxp_net_capture_cmd - Send a tcb to the network stack. ++ * @wc: transcoder that received the command. ++ * @cmd: command to send to network stack. ++ * ++ */ ++static void ++wctc4xxp_net_capture_cmd(struct wcdte *wc, const struct tcb *cmd) ++{ ++ struct sk_buff *skb; ++ struct net_device *netdev = wc->netdev; ++ ++ if (!netdev) ++ return; ++ ++ /* No need to capture if there isn't anyone listening. */ ++ if (!(netdev->flags & IFF_UP)) ++ return; ++ ++ if (skb_queue_len(&wc->captured_packets) > MAX_CAPTURED_PACKETS) { ++ WARN_ON_ONCE(1); ++ return; ++ } ++ ++ skb = tcb_to_skb(netdev, cmd); ++ if (!skb) ++ return; ++ ++ skb_queue_tail(&wc->captured_packets, skb); ++# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++ netif_rx_schedule(netdev, &wc->napi); ++# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ++ netif_rx_schedule(&wc->napi); ++# else ++ napi_schedule(&wc->napi); ++# endif ++ return; ++} ++ ++ ++/*! In-memory structure shared by the host and the adapter. */ ++struct wctc4xxp_descriptor { ++ __le32 des0; ++ __le32 des1; ++ __le32 buffer1; ++ __le32 container; /* Unused */ ++} __attribute__((packed)); ++ ++struct wctc4xxp_descriptor_ring { ++ /* Pointer to an array of descriptors to give to hardware. */ ++ struct wctc4xxp_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 commands. */ ++ struct tcb **pending; ++ /* 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. */ ++ unsigned int count; ++ /*! The number of bytes to pad each descriptor for cache alignment. */ ++ unsigned int padding; ++ /*! Protects this structure from concurrent access. */ ++ spinlock_t lock; ++ /*! PCI device for the card associated with this ring. */ ++ struct pci_dev *pdev; ++ /*! The size of the dring. */ ++ unsigned long size; ++ /*! Total number of packets completed. */ ++ unsigned long packet_count; ++ /*! Total number of packets with errors. */ ++ unsigned long packet_errors; ++}; ++ ++/** ++ * wctc4xxp_descriptor - Returns the desriptor at index. ++ * @dr: The descriptor ring we're using. ++ * @index: index of the descriptor we want. ++ * ++ * We need this function because we do not know what the padding on the ++ * descriptors will be. Otherwise, we would just use an array. ++ */ ++static inline struct wctc4xxp_descriptor * ++wctc4xxp_descriptor(struct wctc4xxp_descriptor_ring *dr, int index) ++{ ++ return (struct wctc4xxp_descriptor *)((u8 *)dr->desc + ++ ((sizeof(*dr->desc) + dr->padding) * index)); ++} ++ ++static int ++wctc4xxp_initialize_descriptor_ring(struct pci_dev *pdev, ++ struct wctc4xxp_descriptor_ring *dr, u32 des1, unsigned int direction, ++ unsigned long size) ++{ ++ int i; ++ const u32 END_OF_RING = 0x02000000; ++ u8 cache_line_size = 0; ++ int add_padding; ++ struct wctc4xxp_descriptor *d = NULL; ++ ++ BUG_ON(!pdev); ++ BUG_ON(!dr); ++ ++ if (pci_read_config_byte(pdev, 0x0c, &cache_line_size)) ++ return -EIO; ++ ++ memset(dr, 0, sizeof(*dr)); ++ dr->size = size; ++ ++ /* ++ * 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. ++ * ++ */ ++ add_padding = (0x08 == cache_line_size) || ++ (0x10 == cache_line_size) || ++ (0x20 == cache_line_size); ++ if (add_padding) ++ dr->padding = (cache_line_size*sizeof(u32)) - sizeof(*d); ++ ++ dr->pending = kmalloc(sizeof(struct tcb *) * dr->size, GFP_KERNEL); ++ if (!dr->pending) ++ return -ENOMEM; ++ ++ dr->desc = pci_alloc_consistent(pdev, ++ (sizeof(*d)+dr->padding)*dr->size, &dr->desc_dma); ++ if (!dr->desc) { ++ kfree(dr->pending); ++ return -ENOMEM; ++ } ++ ++ memset(dr->desc, 0, (sizeof(*d) + dr->padding) * dr->size); ++ for (i = 0; i < dr->size; ++i) { ++ d = wctc4xxp_descriptor(dr, i); ++ memset(d, 0, sizeof(*d)); ++ d->des1 = cpu_to_le32(des1); ++ } ++ ++ d->des1 |= cpu_to_le32(END_OF_RING); ++ dr->direction = direction; ++ spin_lock_init(&dr->lock); ++ dr->pdev = pdev; ++ return 0; ++} ++ ++#define OWN_BIT cpu_to_le32(0x80000000) ++#define OWNED(_d_) (((_d_)->des0)&OWN_BIT) ++#define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb(); } while (0) ++ ++static const unsigned int BUFFER1_SIZE_MASK = 0x7ff; ++ ++static int ++wctc4xxp_submit(struct wctc4xxp_descriptor_ring *dr, struct tcb *c) ++{ ++ volatile struct wctc4xxp_descriptor *d; ++ unsigned int len; ++ unsigned long flags; ++ ++ WARN_ON(!c); ++ len = (c->data_len < MIN_PACKET_LEN) ? MIN_PACKET_LEN : c->data_len; ++ if (c->data_len > MAX_FRAME_SIZE) { ++ WARN_ON_ONCE(!"Invalid command length passed\n"); ++ c->data_len = MAX_FRAME_SIZE; ++ } ++ ++ spin_lock_irqsave(&dr->lock, flags); ++ d = wctc4xxp_descriptor(dr, dr->tail); ++ WARN_ON(!d); ++ if (d->buffer1) { ++ spin_unlock_irqrestore(&dr->lock, flags); ++ /* Do not overwrite a buffer that is still in progress. */ ++ return -EBUSY; ++ } ++ d->des1 &= cpu_to_le32(~(BUFFER1_SIZE_MASK)); ++ d->des1 |= cpu_to_le32(len & BUFFER1_SIZE_MASK); ++ d->buffer1 = cpu_to_le32(pci_map_single(dr->pdev, c->data, ++ SFRAME_SIZE, dr->direction)); ++ ++ SET_OWNED(d); /* That's it until the hardware is done with it. */ ++ dr->pending[dr->tail] = c; ++ dr->tail = (dr->tail + 1) & (dr->size-1); ++ ++dr->count; ++ spin_unlock_irqrestore(&dr->lock, flags); ++ return 0; ++} ++ ++static inline struct tcb* ++wctc4xxp_retrieve(struct wctc4xxp_descriptor_ring *dr) ++{ ++ volatile struct wctc4xxp_descriptor *d; ++ struct tcb *c; ++ unsigned int head = dr->head; ++ unsigned long flags; ++ u32 des0; ++ spin_lock_irqsave(&dr->lock, flags); ++ d = wctc4xxp_descriptor(dr, head); ++ if (d->buffer1 && !OWNED(d)) { ++ pci_unmap_single(dr->pdev, le32_to_cpu(d->buffer1), ++ SFRAME_SIZE, dr->direction); ++ c = dr->pending[head]; ++ WARN_ON(!c); ++ dr->head = (++head) & (dr->size-1); ++ d->buffer1 = 0; ++ --dr->count; ++ WARN_ON(!c); ++ des0 = le32_to_cpu(d->des0); ++ c->data_len = (des0 >> 16) & BUFFER1_SIZE_MASK; ++ if (des0 & (1<<15)) { ++ ++dr->packet_errors; ++ /* The upper layers won't be able to do anything with ++ * this packet. Free it up and log the error. */ ++ free_cmd(c); ++ c = NULL; ++ } else { ++ ++dr->packet_count; ++ WARN_ON(c->data_len > SFRAME_SIZE); ++ } ++ } else { ++ c = NULL; ++ } ++ spin_unlock_irqrestore(&dr->lock, flags); ++ return c; ++} ++ ++static inline int wctc4xxp_getcount(struct wctc4xxp_descriptor_ring *dr) ++{ ++ int count; ++ unsigned long flags; ++ spin_lock_irqsave(&dr->lock, flags); ++ count = dr->count; ++ spin_unlock_irqrestore(&dr->lock, flags); ++ return count; ++} ++ ++static inline int wctc4xxp_get_packet_count(struct wctc4xxp_descriptor_ring *dr) ++{ ++ unsigned long count; ++ unsigned long flags; ++ spin_lock_irqsave(&dr->lock, flags); ++ count = dr->packet_count; ++ spin_unlock_irqrestore(&dr->lock, flags); ++ return count; ++} ++ ++static inline int ++wctc4xxp_get_packet_errors(struct wctc4xxp_descriptor_ring *dr) ++{ ++ unsigned long count; ++ unsigned long flags; ++ spin_lock_irqsave(&dr->lock, flags); ++ count = dr->packet_errors; ++ spin_unlock_irqrestore(&dr->lock, flags); ++ return count; ++} ++ ++static inline void ++wctc4xxp_set_packet_count(struct wctc4xxp_descriptor_ring *dr, ++ unsigned long count) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&dr->lock, flags); ++ dr->packet_count = count; ++ spin_unlock_irqrestore(&dr->lock, flags); ++} ++ ++static inline void ++__wctc4xxp_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) ++{ ++ writel(val, wc->iobase + addr); ++ readl(wc->iobase + addr); ++} ++ ++static inline unsigned int ++__wctc4xxp_getctl(struct wcdte *wc, unsigned int addr) ++{ ++ return readl(wc->iobase + addr); ++} ++ ++static inline void ++wctc4xxp_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&wc->reglock, flags); ++ __wctc4xxp_setctl(wc, addr, val); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static inline void ++wctc4xxp_receive_demand_poll(struct wcdte *wc) ++{ ++ __wctc4xxp_setctl(wc, 0x0010, 0x00000000); ++} ++ ++static inline void ++wctc4xxp_transmit_demand_poll(struct wcdte *wc) ++{ ++ return; ++# if 0 ++ __wctc4xxp_setctl(wc, 0x0008, 0x00000000); ++ ++ /* \todo Investigate why this register needs to be written twice in ++ * order to get it to poll reliably. So far, most of the problems ++ * I've seen with timeouts had more to do with an untransmitted ++ * packet sitting in the outbound descriptor list as opposed to any ++ * problem with the dte firmware. ++ */ ++ __wctc4xxp_setctl(wc, 0x0008, 0x00000000); ++#endif ++} ++ ++#define LENGTH_WITH_N_PARAMETERS(__n) (((__n) * sizeof(u16)) + \ ++ sizeof(struct csm_encaps_cmd)) ++ ++static const u8 dst_mac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; ++static const u8 src_mac[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; ++ ++static int wctc4xxp_transmit_cmd_and_wait(struct wcdte *wc, struct tcb *cmd); ++ ++static void ++setup_common_header(struct wcdte *wc, struct csm_encaps_hdr *hdr) ++{ ++ memcpy(hdr->ethhdr.h_dest, dst_mac, sizeof(dst_mac)); ++ memcpy(hdr->ethhdr.h_source, src_mac, sizeof(src_mac)); ++ hdr->ethhdr.h_proto = cpu_to_be16(ETH_P_CSM_ENCAPS); ++} ++ ++static void ++setup_supervisor_header(struct wcdte *wc, struct csm_encaps_hdr *hdr) ++{ ++ setup_common_header(wc, hdr); ++ ++ hdr->op_code = cpu_to_be16(CONTROL_PACKET_OPCODE); ++ hdr->control = LITTLE_ENDIAN; ++ hdr->seq_num = (wc->seq_num++)&0xf; ++ hdr->channel = cpu_to_be16(SUPERVISOR_CHANNEL); ++} ++ ++static void ++create_supervisor_cmd(struct wcdte *wc, struct tcb *cmd, u8 type, u8 class, ++ u16 function, const u16 *parameters, const int num_parameters) ++{ ++ struct csm_encaps_hdr *hdr = cmd->data; ++ int i; ++ ++ if (cmd->response) { ++ free_cmd(cmd->response); ++ cmd->response = NULL; ++ } ++ ++ setup_supervisor_header(wc, hdr); ++ ++ hdr->cmd.length = LENGTH_WITH_N_PARAMETERS(num_parameters); ++ hdr->cmd.index = 0; ++ hdr->cmd.type = type; ++ hdr->cmd.class = class; ++ hdr->cmd.function = cpu_to_le16(function); ++ hdr->cmd.reserved = 0; ++ ++ for (i = 0; i < num_parameters; ++i) ++ hdr->cmd.params[i] = cpu_to_le16(parameters[i]); ++ ++ cmd->flags = WAIT_FOR_RESPONSE; ++ cmd->data_len = sizeof(struct csm_encaps_hdr) - ++ sizeof(struct csm_encaps_cmd) + ++ hdr->cmd.length; ++ cmd->cpvt = NULL; ++} ++ ++static void ++setup_channel_header(struct channel_pvt *pvt, struct tcb *cmd) ++{ ++ struct csm_encaps_hdr *hdr = cmd->data; ++ ++ if (cmd->response) { ++ free_cmd(cmd->response); ++ cmd->response = NULL; ++ } ++ ++ setup_common_header(pvt->wc, hdr); ++ hdr->op_code = cpu_to_be16(CONTROL_PACKET_OPCODE); ++ hdr->seq_num = (pvt->cmd_seqno++)&0xf; ++ hdr->channel = cpu_to_be16(pvt->chan_in_num); ++ ++ cmd->flags = WAIT_FOR_RESPONSE; ++ cmd->data_len = sizeof(struct csm_encaps_hdr) - ++ sizeof(struct csm_encaps_cmd); ++ cmd->cpvt = pvt; ++ cmd->next_index = 0; ++} ++ ++ ++static void ++append_channel_cmd(struct tcb *cmd, u8 type, u8 class, u16 function, ++ const u16 *parameters, int num_parameters) ++{ ++ int i; ++ struct csm_encaps_cmd *csm_cmd = cmd->data + cmd->data_len; ++ ++ csm_cmd->length = LENGTH_WITH_N_PARAMETERS(num_parameters); ++ csm_cmd->index = cmd->next_index++; ++ csm_cmd->type = type; ++ csm_cmd->class = class; ++ csm_cmd->function = cpu_to_le16(function); ++ csm_cmd->reserved = 0; ++ ++ for (i = 0; i < num_parameters; ++i) ++ csm_cmd->params[i] = cpu_to_le16(parameters[i]); ++ ++ cmd->data_len += csm_cmd->length; ++ /* Pad it out to a DW boundary */ ++ if (cmd->data_len % 4) ++ cmd->data_len += 4 - (cmd->data_len % 4); ++ WARN_ON(cmd->data_len >= SFRAME_SIZE); ++} ++ ++static void ++create_channel_cmd(struct channel_pvt *pvt, struct tcb *cmd, u8 type, u8 class, ++ u16 function, const u16 *parameters, int num_parameters) ++{ ++ setup_channel_header(pvt, cmd); ++ append_channel_cmd(cmd, type, class, function, parameters, ++ num_parameters); ++} ++ ++static int ++send_create_channel_cmd(struct wcdte *wc, struct tcb *cmd, u16 timeslot, ++ u16 *channel_number) ++{ ++ int res; ++ const u16 parameters[] = {0x0002, timeslot}; ++ ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, SUPVSR_CREATE_CHANNEL, ++ parameters, ARRAY_SIZE(parameters)); ++ ++ res = wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++ if (res) ++ return res; ++ ++ if (0x0000 != response_header(cmd)->cmd.params[0]) { ++ if (printk_ratelimit()) { ++ dev_warn(&wc->pdev->dev, ++ "Failed to create channel in timeslot " \ ++ "%d. Response from DTE was (%04x).\n", ++ timeslot, response_header(cmd)->cmd.params[0]); ++ } ++ free_cmd(cmd->response); ++ cmd->response = NULL; ++ return -EIO; ++ } ++ ++ *channel_number = le16_to_cpu(response_header(cmd)->cmd.params[1]); ++ free_cmd(cmd->response); ++ cmd->response = NULL; ++ return 0; ++} ++ ++static int ++send_set_arm_clk_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x012c, 0x0000}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0411, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_set_spu_clk_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x012c, 0x0000}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0412, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_tdm_select_bus_mode_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0004}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0417, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_set_eth_header_cmd(struct wcdte *wc, struct tcb *cmd, ++ const u8 *host_mac, const u8 *assigned_mac) ++{ ++ u16 parameters[8]; ++ u16 *part; ++ ++ parameters[0] = 0x0001; ++ part = (u16 *)host_mac; ++ parameters[1] = part[0]; ++ parameters[2] = part[1]; ++ parameters[3] = part[2]; ++ part = (u16 *)assigned_mac; ++ parameters[4] = part[0]; ++ parameters[5] = part[1]; ++ parameters[6] = part[2]; ++ parameters[7] = 0x0008; ++ ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0100, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_supvsr_setup_tdm_parms(struct wcdte *wc, struct tcb *cmd, ++ u8 bus_number) ++{ ++ const u16 parameters[] = {0x8380, 0x0c00, 0, (bus_number << 2)&0xc}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0407, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_ip_service_config_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0200}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0302, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_arp_service_config_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0001}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0105, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_icmp_service_config_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0xff01}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0304, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_device_set_country_code_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0000}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x041b, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_spu_features_control_cmd(struct wcdte *wc, struct tcb *cmd, u16 options) ++{ ++ const u16 parameters[] = {options}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0013, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++/* Allows sending more than one CSM_ENCAPS packet in a single ethernet frame. */ ++static int send_csme_multi_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x1}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x010a, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_tdm_opt_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0000}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0435, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++send_destroy_channel_cmd(struct wcdte *wc, struct tcb *cmd, u16 channel) ++{ ++ int res; ++ u16 result; ++ const u16 parameters[] = {channel}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0011, parameters, ++ ARRAY_SIZE(parameters)); ++ res = wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++ if (res) ++ return res; ++ /* Let's check the response for any error codes.... */ ++ result = le16_to_cpu(response_header(cmd)->cmd.params[0]); ++ if (0x0000 != result) { ++ dev_err(&wc->pdev->dev, ++ "Failed to destroy channel %04d (%04x)\n", ++ channel, result); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static void ++append_set_ip_hdr_channel_cmd(struct tcb *cmd) ++{ ++ const u16 parameters[] = {0, 0x0045, 0, 0, 0x0040, 0x1180, 0, ++ 0xa8c0, 0x0309, 0xa8c0, 0x0309, ++ swab16(cmd->cpvt->timeslot_out_num + 0x5000), ++ swab16(cmd->cpvt->timeslot_in_num + 0x5000), ++ 0, 0}; ++ append_channel_cmd(cmd, CONFIG_CHANGE_TYPE, CONFIG_CHANNEL_CLASS, ++ 0x9000, parameters, ARRAY_SIZE(parameters)); ++} ++ ++static void ++append_voip_vceopt_cmd(struct tcb *cmd, u16 length) ++{ ++ const u16 parameters[] = {((length << 8)|0x21), 0x1c00, ++ 0x0004, 0, 0}; ++ append_channel_cmd(cmd, CONFIG_CHANGE_TYPE, CONFIG_CHANNEL_CLASS, ++ 0x8001, parameters, ARRAY_SIZE(parameters)); ++} ++ ++static void ++append_voip_tonectl_cmd(struct tcb *cmd) ++{ ++ const u16 parameters[] = {0}; ++ append_channel_cmd(cmd, CONFIG_CHANGE_TYPE, CONFIG_CHANNEL_CLASS, ++ 0x805b, parameters, ARRAY_SIZE(parameters)); ++} ++ ++static void ++append_voip_dtmfopt_cmd(struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0008}; ++ append_channel_cmd(cmd, CONFIG_CHANGE_TYPE, CONFIG_CHANNEL_CLASS, ++ 0x8002, parameters, ARRAY_SIZE(parameters)); ++} ++ ++static void ++append_voip_indctrl_cmd(struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0007}; ++ append_channel_cmd(cmd, CONFIG_CHANGE_TYPE, CONFIG_CHANNEL_CLASS, ++ 0x8084, parameters, ARRAY_SIZE(parameters)); ++} ++ ++static void ++send_voip_vopena_cmd(struct channel_pvt *pvt, struct tcb *cmd, u8 format) ++{ ++ const u16 parameters[] = {1, ((format<<8)|0x80), 0, 0, 0, ++ 0x3412, 0x7856}; ++ create_channel_cmd(pvt, cmd, CONFIG_CHANGE_TYPE, CONFIG_CHANNEL_CLASS, ++ 0x8000, parameters, ARRAY_SIZE(parameters)); ++ wctc4xxp_transmit_cmd(pvt->wc, cmd); ++} ++ ++static int ++send_voip_vopena_close_cmd(struct channel_pvt *pvt, struct tcb *cmd) ++{ ++ int res; ++ const u16 parameters[] = {0}; ++ create_channel_cmd(pvt, cmd, CONFIG_CHANGE_TYPE, CONFIG_CHANNEL_CLASS, ++ 0x8000, parameters, ARRAY_SIZE(parameters)); ++ res = wctc4xxp_transmit_cmd_and_wait(pvt->wc, cmd); ++ if (res) ++ return res; ++ /* Let's check the response for any error codes.... */ ++ if (0x0000 != response_header(cmd)->cmd.params[0]) { ++ WARN_ON(1); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int ++send_ip_options_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ const u16 parameters[] = {0x0002}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0306, parameters, ++ ARRAY_SIZE(parameters)); ++ return wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++} ++ ++static int ++_send_trans_connect_cmd(struct wcdte *wc, struct tcb *cmd, u16 enable, u16 ++ encoder_channel, u16 decoder_channel, u16 encoder_format, ++ u16 decoder_format) ++{ ++ int res; ++ const u16 parameters[] = {enable, encoder_channel, encoder_format, ++ decoder_channel, decoder_format}; ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x9322, parameters, ++ ARRAY_SIZE(parameters)); ++ res = wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++ if (res) ++ return res; ++ ++ /* Let's check the response for any error codes.... */ ++ if (0x0000 != response_header(cmd)->cmd.params[0]) { ++ WARN_ON(1); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int ++send_trans_connect_cmd(struct wcdte *wc, struct tcb *cmd, const u16 ++ encoder_channel, const u16 decoder_channel, const u16 encoder_format, ++ const u16 decoder_format) ++{ ++ return _send_trans_connect_cmd(wc, cmd, 1, encoder_channel, ++ decoder_channel, encoder_format, decoder_format); ++} ++ ++static int ++send_trans_disconnect_cmd(struct wcdte *wc, struct tcb *cmd, const u16 ++ encoder_channel, const u16 decoder_channel, const u16 encoder_format, ++ const u16 decoder_format) ++{ ++ return _send_trans_connect_cmd(wc, cmd, 0, encoder_channel, ++ decoder_channel, encoder_format, decoder_format); ++} ++ ++static int ++send_voip_vceinfo_cmd(struct channel_pvt *pvt, struct tcb *cmd) ++{ ++ int res; ++ const u16 parameters[] = {0}; ++ static const int CONFIG_CHANNEL_STATS_CLASS = 1; ++ create_channel_cmd(pvt, cmd, ++ VOIP_VCEINFO_TYPE, CONFIG_CHANNEL_STATS_CLASS, ++ 0x0000, parameters, 0); ++ res = wctc4xxp_transmit_cmd_and_wait(pvt->wc, cmd); ++ return res; ++} ++ ++static int ++send_eth_statistics_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ int res; ++ const u16 parameters[] = {0}; ++ ++ create_supervisor_cmd(wc, cmd, 0x00, 0x05, 0x0000, ++ parameters, ARRAY_SIZE(parameters)); ++ res = wctc4xxp_transmit_cmd_and_wait(wc, cmd); ++ if (res) ++ return -EIO; ++ if (0x0000 != response_header(cmd)->cmd.params[0]) { ++ dev_info(&wc->pdev->dev, ++ "Failed to get ethernet stats: 0x%04x\n", ++ response_header(cmd)->cmd.params[0]); ++ res = -EIO; ++ } ++ return res; ++} ++ ++static void wctc4xxp_match_packet_counts(struct wcdte *wc) ++{ ++ struct tcb *cmd = alloc_cmd(SFRAME_SIZE); ++ int res; ++ u32 *parms; ++ ++ res = send_eth_statistics_cmd(wc, cmd); ++ if (0 == res) { ++ parms = (u32 *)(&response_header(cmd)->cmd.params[0]); ++ wctc4xxp_set_packet_count(wc->rxd, parms[1]); ++ wctc4xxp_set_packet_count(wc->txd, parms[2]); ++ } ++ free_cmd(cmd); ++} ++ ++static inline u32 wctc4xxp_bytes_to_samples(u32 fmt, size_t count) ++{ ++ switch (fmt) { ++ case DAHDI_FORMAT_G723_1: ++ return count * (G723_SAMPLES/G723_5K_BYTES); ++ case DAHDI_FORMAT_ULAW: ++ case DAHDI_FORMAT_ALAW: ++ return count; ++ case DAHDI_FORMAT_G729A: ++ return count * (G729_SAMPLES/G729_BYTES); ++ default: ++ WARN_ON(1); ++ return 0; ++ } ++} ++ ++static struct tcb * ++wctc4xxp_create_rtp_cmd(struct wcdte *wc, struct dahdi_transcoder_channel *dtc, ++ size_t inbytes) ++{ ++ struct channel_pvt *cpvt = dtc->pvt; ++ struct rtp_packet *packet; ++ struct tcb *cmd; ++ ++ cmd = alloc_cmd(sizeof(*packet) + inbytes); ++ if (!cmd) ++ return NULL; ++ ++ cmd->cpvt = cpvt; ++ packet = cmd->data; ++ ++ BUG_ON(cmd->data_len < sizeof(*packet)); ++ ++ /* setup the ethernet header */ ++ memcpy(packet->ethhdr.h_dest, dst_mac, sizeof(dst_mac)); ++ memcpy(packet->ethhdr.h_source, src_mac, sizeof(src_mac)); ++ packet->ethhdr.h_proto = cpu_to_be16(ETH_P_IP); ++ ++ /* setup the IP header */ ++ packet->iphdr.ihl = 5; ++ packet->iphdr.version = 4; ++ packet->iphdr.tos = 0; ++ packet->iphdr.tot_len = cpu_to_be16(inbytes+40); ++ packet->iphdr.id = 0; ++ packet->iphdr.frag_off = cpu_to_be16(0x4000); ++ packet->iphdr.ttl = 64; ++ packet->iphdr.protocol = 0x11; /* UDP */ ++ packet->iphdr.check = 0; ++ packet->iphdr.saddr = cpu_to_be32(0xc0a80903); ++ packet->iphdr.daddr = cpu_to_be32(0xc0a80903); ++ ++ packet->iphdr.check = ip_fast_csum((void *)&packet->iphdr, ++ packet->iphdr.ihl); ++ ++ /* setup the UDP header */ ++ packet->udphdr.source = cpu_to_be16(cpvt->timeslot_out_num + 0x5000); ++ packet->udphdr.dest = cpu_to_be16(cpvt->timeslot_in_num + 0x5000); ++ packet->udphdr.len = cpu_to_be16(inbytes + sizeof(struct rtphdr) + ++ sizeof(struct udphdr)); ++ packet->udphdr.check = 0; ++ ++ /* Setup the RTP header */ ++ packet->rtphdr.ver = 2; ++ packet->rtphdr.padding = 0; ++ packet->rtphdr.extension = 0; ++ packet->rtphdr.csrc_count = 0; ++ packet->rtphdr.marker = 0; ++ packet->rtphdr.type = wctc4xxp_dahdifmt_to_dtefmt(dtc->srcfmt); ++ packet->rtphdr.seqno = cpu_to_be16(cpvt->seqno); ++ packet->rtphdr.timestamp = cpu_to_be32(cpvt->last_timestamp); ++ packet->rtphdr.ssrc = cpu_to_be32(cpvt->ssrc); ++ ++ cpvt->last_timestamp += wctc4xxp_bytes_to_samples(dtc->srcfmt, ++ inbytes); ++ ++ WARN_ON(cmd->data_len > SFRAME_SIZE); ++ return cmd; ++} ++static void ++wctc4xxp_cleanup_descriptor_ring(struct wctc4xxp_descriptor_ring *dr) ++{ ++ int i; ++ struct wctc4xxp_descriptor *d; ++ ++ if (!dr || !dr->desc) ++ return; ++ ++ for (i = 0; i < dr->size; ++i) { ++ d = wctc4xxp_descriptor(dr, i); ++ if (d->buffer1) { ++ pci_unmap_single(dr->pdev, d->buffer1, ++ SFRAME_SIZE, dr->direction); ++ d->buffer1 = 0; ++ /* Commands will also be sitting on the waiting for ++ * response list, so we want to make sure to delete ++ * them from that list as well. */ ++ list_del_init(&(dr->pending[i])->node); ++ free_cmd(dr->pending[i]); ++ dr->pending[i] = NULL; ++ } ++ } ++ dr->head = 0; ++ dr->tail = 0; ++ dr->count = 0; ++ pci_free_consistent(dr->pdev, (sizeof(*d)+dr->padding) * dr->size, ++ dr->desc, dr->desc_dma); ++ kfree(dr->pending); ++} ++ ++static void wctc4xxp_timeout_all_commands(struct wcdte *wc) ++{ ++ struct tcb *cmd; ++ struct tcb *temp; ++ unsigned long flags; ++ LIST_HEAD(local_list); ++ ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ list_splice_init(&wc->waiting_for_response_list, &local_list); ++ list_splice_init(&wc->cmd_list, &local_list); ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++ ++ list_for_each_entry_safe(cmd, temp, &local_list, node) { ++ list_del_init(&cmd->node); ++ if (cmd->complete) { ++ cmd->flags |= DTE_CMD_TIMEOUT; ++ complete(cmd->complete); ++ } else { ++ free_cmd(cmd); ++ } ++ } ++} ++ ++static void wctc4xxp_cleanup_command_list(struct wcdte *wc) ++{ ++ struct tcb *cmd; ++ unsigned long flags; ++ LIST_HEAD(local_list); ++ ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ list_splice_init(&wc->cmd_list, &local_list); ++ list_splice_init(&wc->waiting_for_response_list, &local_list); ++ list_splice_init(&wc->rx_list, &local_list); ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++ ++ while (!list_empty(&local_list)) { ++ cmd = list_entry(local_list.next, struct tcb, node); ++ list_del_init(&cmd->node); ++ free_cmd(cmd); ++ } ++} ++ ++static inline bool is_rtp_packet(const struct tcb *cmd) ++{ ++ const struct ethhdr *ethhdr = cmd->data; ++ return (cpu_to_be16(ETH_P_IP) == ethhdr->h_proto); ++} ++ ++static void ++wctc4xxp_transmit_cmd(struct wcdte *wc, struct tcb *cmd) ++{ ++ int res; ++ unsigned long flags; ++ ++ /* If we're shutdown all commands will timeout. Just complete the ++ * command here with the timeout flag */ ++ if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) { ++ if (cmd->complete) { ++ cmd->flags |= DTE_CMD_TIMEOUT; ++ list_del_init(&cmd->node); ++ complete(cmd->complete); ++ } else { ++ list_del(&cmd->node); ++ free_cmd(cmd); ++ } ++ return; ++ } ++ ++ if (cmd->data_len < MIN_PACKET_LEN) { ++ memset((u8 *)(cmd->data) + cmd->data_len, 0, ++ MIN_PACKET_LEN-cmd->data_len); ++ cmd->data_len = MIN_PACKET_LEN; ++ } ++ WARN_ON(cmd->response); ++ WARN_ON(cmd->flags & TX_COMPLETE); ++ cmd->timeout = jiffies + HZ/4; ++ ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ if (cmd->flags & (WAIT_FOR_ACK | WAIT_FOR_RESPONSE)) { ++ if (cmd->flags & WAIT_FOR_RESPONSE) { ++ /* We don't need both an ACK and a response. Let's ++ * tell the DTE not to generate an ACK, and we'll just ++ * retry if we do not get the response within the ++ * timeout period. */ ++ struct csm_encaps_hdr *hdr = cmd->data; ++ hdr->control |= SUPPRESS_ACK; ++ } ++ WARN_ON(!list_empty(&cmd->node)); ++ list_add_tail(&cmd->node, &wc->waiting_for_response_list); ++ mod_timer(&wc->watchdog, jiffies + HZ/2); ++ } ++ if (!list_empty(&wc->cmd_list)) { ++ if (is_rtp_packet(cmd)) ++ list_add_tail(&cmd->node, &wc->cmd_list); ++ else ++ list_move(&cmd->node, &wc->cmd_list); ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++ return; ++ } ++ res = wctc4xxp_submit(wc->txd, cmd); ++ if (-EBUSY == res) { ++ /* Looks like we're out of room in the descriptor ++ * ring. We'll add this command to the pending list ++ * and the interrupt service routine will pull from ++ * this list as it clears up room in the descriptor ++ * ring. */ ++ list_move_tail(&cmd->node, &wc->cmd_list); ++ } else if (0 == res) { ++ if (!(cmd->flags & DO_NOT_CAPTURE)) ++ wctc4xxp_net_capture_cmd(wc, cmd); ++ wctc4xxp_transmit_demand_poll(wc); ++ } else { ++ /* Unknown return value... */ ++ WARN_ON(1); ++ } ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++} ++ ++static int ++wctc4xxp_transmit_cmd_and_wait(struct wcdte *wc, struct tcb *cmd) ++{ ++ DECLARE_COMPLETION_ONSTACK(done); ++ cmd->complete = &done; ++ wctc4xxp_transmit_cmd(wc, cmd); ++ wait_for_completion(&done); ++ cmd->complete = NULL; ++ if (cmd->flags & DTE_CMD_TIMEOUT) { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "Timeout waiting for command.\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int wctc4xxp_create_channel_pair(struct wcdte *wc, ++ struct channel_pvt *cpvt, u8 simple, u8 complicated); ++static int wctc4xxp_destroy_channel_pair(struct wcdte *wc, ++ struct channel_pvt *cpvt); ++ ++static void ++wctc4xxp_init_state(struct channel_pvt *cpvt, int encoder, ++ unsigned int channel, struct wcdte *wc) ++{ ++ memset(cpvt, 0, sizeof(*cpvt)); ++ cpvt->encoder = encoder; ++ cpvt->wc = wc; ++ cpvt->chan_in_num = INVALID; ++ cpvt->chan_out_num = INVALID; ++ cpvt->ssrc = 0x78; ++ cpvt->timeslot_in_num = channel*2; ++ cpvt->timeslot_out_num = channel*2; ++ cpvt->last_rx_seq_num = 0xff; ++ if (encoder) ++ ++cpvt->timeslot_out_num; ++ else ++ ++cpvt->timeslot_in_num; ++ spin_lock_init(&cpvt->lock); ++ INIT_LIST_HEAD(&cpvt->rx_queue); ++} ++ ++static unsigned int ++wctc4xxp_getctl(struct wcdte *wc, unsigned int addr) ++{ ++ unsigned int val; ++ unsigned long flags; ++ spin_lock_irqsave(&wc->reglock, flags); ++ val = __wctc4xxp_getctl(wc, addr); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return val; ++} ++ ++static void ++wctc4xxp_cleanup_channel_private(struct wcdte *wc, ++ struct dahdi_transcoder_channel *dtc) ++{ ++ struct tcb *cmd, *temp; ++ struct channel_pvt *cpvt = dtc->pvt; ++ unsigned long flags; ++ LIST_HEAD(local_list); ++ ++ /* Once we cleanup this channel, we do not want any queued packets ++ * waiting to be transmitted. Anything on the hardware descriptor ring ++ * will be flushed by the csm_encaps command to shutdown the channel. */ ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ list_for_each_entry_safe(cmd, temp, &wc->cmd_list, node) { ++ if (cmd->cpvt == cpvt) ++ list_move(&cmd->node, &local_list); ++ } ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++ ++ spin_lock_irqsave(&cpvt->lock, flags); ++ list_splice_init(&cpvt->rx_queue, &local_list); ++ dahdi_tc_clear_data_waiting(dtc); ++ cpvt->samples_in_flight = 0; ++ spin_unlock_irqrestore(&cpvt->lock, flags); ++ ++ memset(&cpvt->stats, 0, sizeof(cpvt->stats)); ++ list_for_each_entry_safe(cmd, temp, &local_list, node) { ++ list_del(&cmd->node); ++ free_cmd(cmd); ++ } ++} ++ ++static void ++wctc4xxp_mark_channel_complement_built(struct wcdte *wc, ++ struct dahdi_transcoder_channel *dtc) ++{ ++ int index; ++ struct channel_pvt *cpvt = dtc->pvt; ++ struct dahdi_transcoder_channel *compl_dtc; ++ struct channel_pvt *compl_cpvt; ++ ++ BUG_ON(!cpvt); ++ index = cpvt->timeslot_in_num/2; ++ BUG_ON(index >= wc->numchannels); ++ if (cpvt->encoder) ++ compl_dtc = &(wc->udecode->channels[index]); ++ else ++ compl_dtc = &(wc->uencode->channels[index]); ++ ++ /* It shouldn't already have been built... */ ++ WARN_ON(dahdi_tc_is_built(compl_dtc)); ++ compl_dtc->built_fmts = dtc->dstfmt | dtc->srcfmt; ++ compl_cpvt = compl_dtc->pvt; ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "dtc: %p is the complement to %p\n", compl_dtc, dtc); ++ compl_cpvt->chan_in_num = cpvt->chan_out_num; ++ compl_cpvt->chan_out_num = cpvt->chan_in_num; ++ dahdi_tc_set_built(compl_dtc); ++ wctc4xxp_cleanup_channel_private(wc, dtc); ++} ++ ++static int ++do_channel_allocate(struct dahdi_transcoder_channel *dtc) ++{ ++ struct channel_pvt *cpvt = dtc->pvt; ++ struct wcdte *wc = cpvt->wc; ++ u8 wctc4xxp_srcfmt; /* Digium Transcoder Engine Source Format */ ++ u8 wctc4xxp_dstfmt; /* Digium Transcoder Engine Dest Format */ ++ int res; ++ ++ /* Check again to see if the channel was built after grabbing the ++ * channel lock, in case the previous holder of the lock ++ * built this channel as a complement to itself. */ ++ if (dahdi_tc_is_built(dtc)) { ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "Allocating channel %p which is already built.\n", dtc); ++ return 0; ++ } ++ ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "Entering %s for channel %p.\n", __func__, dtc); ++ /* Anything on the rx queue now is old news... */ ++ wctc4xxp_cleanup_channel_private(wc, dtc); ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "Allocating a new channel: %p.\n", dtc); ++ wctc4xxp_srcfmt = wctc4xxp_dahdifmt_to_dtefmt(dtc->srcfmt); ++ wctc4xxp_dstfmt = wctc4xxp_dahdifmt_to_dtefmt(dtc->dstfmt); ++ res = wctc4xxp_create_channel_pair(wc, cpvt, wctc4xxp_srcfmt, ++ wctc4xxp_dstfmt); ++ if (res) { ++ dev_err(&wc->pdev->dev, "Failed to create channel pair.\n"); ++ /* A failure to create a channel pair is normally a critical ++ * error in the firmware state. Reload the firmware when this ++ * handle is closed. */ ++ set_bit(DTE_RELOAD, &wc->flags); ++ set_bit(DTE_SHUTDOWN, &wc->flags); ++ return res; ++ } ++ /* Mark this channel as built */ ++ dahdi_tc_set_built(dtc); ++ dtc->built_fmts = dtc->dstfmt | dtc->srcfmt; ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "Channel %p has dstfmt=%x and srcfmt=%x\n", dtc, dtc->dstfmt, ++ dtc->srcfmt); ++ /* Mark the channel complement (other half of encoder/decoder pair) as ++ * built */ ++ wctc4xxp_mark_channel_complement_built(wc, dtc); ++ dahdi_transcoder_alert(dtc); ++ return 0; ++} ++ ++static void ++wctc4xxp_setintmask(struct wcdte *wc, unsigned int intmask) ++{ ++ wc->intmask = intmask; ++ wctc4xxp_setctl(wc, 0x0038, intmask); ++} ++ ++static const u32 DEFAULT_INTERRUPTS = 0x0001a0c0; ++ ++static void ++wctc4xxp_enable_interrupts(struct wcdte *wc) ++{ ++ wctc4xxp_setintmask(wc, DEFAULT_INTERRUPTS); ++} ++ ++static void ++wctc4xxp_disable_interrupts(struct wcdte *wc) ++{ ++ /* Disable interrupts */ ++ wctc4xxp_setintmask(wc, 0x00000000); ++ wctc4xxp_setctl(wc, 0x0084, 0x00000000); ++} ++ ++static void ++wctc4xxp_enable_polling(struct wcdte *wc) ++{ ++ set_bit(DTE_POLLING, &wc->flags); ++ wctc4xxp_setctl(wc, 0x0058, 0x10003); ++ /* Enable the general purpose timer interrupt. */ ++ wctc4xxp_setintmask(wc, (DEFAULT_INTERRUPTS | (1 << 11)) & ~0x41); ++} ++ ++static int wctc4xxp_reset_driver_state(struct wcdte *wc); ++ ++static bool wctc4xxp_need_firmware_reload(struct wcdte *wc) ++{ ++ return !!test_bit(DTE_RELOAD, &wc->flags) && ++ (1 == wc->open_channels); ++} ++ ++static int wctc4xxp_reload_firmware(struct wcdte *wc) ++{ ++ int res; ++ clear_bit(DTE_SHUTDOWN, &wc->flags); ++ res = wctc4xxp_reset_driver_state(wc); ++ if (res) ++ set_bit(DTE_SHUTDOWN, &wc->flags); ++ else ++ clear_bit(DTE_RELOAD, &wc->flags); ++ return res; ++} ++ ++static int ++wctc4xxp_operation_allocate(struct dahdi_transcoder_channel *dtc) ++{ ++ int res = 0; ++ struct wcdte *wc = ((struct channel_pvt *)(dtc->pvt))->wc; ++ ++ res = mutex_lock_killable(&wc->chanlock); ++ if (res) ++ return res; ++ ++ ++wc->open_channels; ++ ++ if (test_bit(DTE_SHUTDOWN, &wc->flags)) { ++ res = -EIO; ++ if (wctc4xxp_need_firmware_reload(wc)) ++ res = wctc4xxp_reload_firmware(wc); ++ } else if (wctc4xxp_need_firmware_reload(wc)) { ++ res = wctc4xxp_reload_firmware(wc); ++ } ++ ++ if (res) ++ goto error_exit; ++ ++ if (wc->open_channels > POLLING_CALL_THRESHOLD) { ++ if (!test_bit(DTE_POLLING, &wc->flags)) ++ wctc4xxp_enable_polling(wc); ++ } ++ ++ if (dahdi_tc_is_built(dtc)) { ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "Allocating channel %p which is already built.\n", dtc); ++ res = 0; ++ } else { ++ res = do_channel_allocate(dtc); ++ } ++ ++error_exit: ++ mutex_unlock(&wc->chanlock); ++ return res; ++} ++ ++static void ++wctc4xxp_disable_polling(struct wcdte *wc) ++{ ++ clear_bit(DTE_POLLING, &wc->flags); ++ wctc4xxp_setctl(wc, 0x0058, 0x0); ++ wctc4xxp_enable_interrupts(wc); ++} ++ ++static void wctc4xxp_check_for_rx_errors(struct wcdte *wc) ++{ ++ /* get_packet_errors() returns the accumulated total errors */ ++ unsigned long errors = wctc4xxp_get_packet_errors(wc->rxd); ++ ++ /* Print warning when the number of errors changes */ ++ if (wc->reported_packet_errors != errors) { ++ if (printk_ratelimit()) { ++ dev_err(&wc->pdev->dev, ++ "%lu errored receive packets.\n", ++ errors - wc->reported_packet_errors); ++ wc->reported_packet_errors = errors; ++ } ++ } ++} ++ ++static int ++wctc4xxp_operation_release(struct dahdi_transcoder_channel *dtc) ++{ ++ int res = 0; ++ int index; ++ /* This is the 'complimentary channel' to dtc. I.e., if dtc is an ++ * encoder, compl_dtc is the decoder and vice-versa */ ++ struct dahdi_transcoder_channel *compl_dtc; ++ struct channel_pvt *compl_cpvt; ++ struct channel_pvt *cpvt = dtc->pvt; ++ struct wcdte *wc = cpvt->wc; ++ int packets_received, packets_sent; ++ ++ BUG_ON(!cpvt); ++ BUG_ON(!wc); ++ ++ res = mutex_lock_killable(&wc->chanlock); ++ if (res) ++ return res; ++ ++ if (test_bit(DTE_SHUTDOWN, &wc->flags)) { ++ /* On shutdown, if we reload the firmware we will reset the ++ * state of all the channels. Therefore we do not want to ++ * process any of the channel release logic even if the firmware ++ * was reloaded successfully. */ ++ if (wctc4xxp_need_firmware_reload(wc)) ++ wctc4xxp_reload_firmware(wc); ++ res = -EIO; ++ } else if (wctc4xxp_need_firmware_reload(wc)) { ++ wctc4xxp_reload_firmware(wc); ++ res = -EIO; ++ } ++ ++ if (wc->open_channels) { ++ --wc->open_channels; ++ ++#if !defined(CONFIG_WCTC4XXP_POLLING) ++ if (wc->open_channels < POLLING_CALL_THRESHOLD) { ++ if (test_bit(DTE_POLLING, &wc->flags)) ++ wctc4xxp_disable_polling(wc); ++ } ++#endif ++ } ++ ++ if (res) ++ goto error_exit; ++ ++ packets_received = atomic_read(&cpvt->stats.packets_received); ++ packets_sent = atomic_read(&cpvt->stats.packets_sent); ++ ++ DTE_DEBUG(DTE_DEBUG_ETH_STATS, ++ "%s channel %d sent %d packets and received %d packets.\n", ++ (cpvt->encoder) ? "encoder" : "decoder", cpvt->chan_out_num, ++ packets_sent, packets_received); ++ ++ ++ /* Remove any packets that are waiting on the outbound queue. */ ++ dahdi_tc_clear_busy(dtc); ++ wctc4xxp_cleanup_channel_private(wc, dtc); ++ index = cpvt->timeslot_in_num/2; ++ BUG_ON(index >= wc->numchannels); ++ if (cpvt->encoder) ++ compl_dtc = &(wc->udecode->channels[index]); ++ else ++ compl_dtc = &(wc->uencode->channels[index]); ++ BUG_ON(!compl_dtc); ++ if (!dahdi_tc_is_built(compl_dtc)) { ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "Releasing a channel that was never built.\n"); ++ res = 0; ++ goto error_exit; ++ } ++ /* If the channel complement (other half of the encoder/decoder pair) is ++ * being used. */ ++ if (dahdi_tc_is_busy(compl_dtc)) { ++ res = 0; ++ goto error_exit; ++ } ++ res = wctc4xxp_destroy_channel_pair(wc, cpvt); ++ if (res) ++ goto error_exit; ++ ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, "Releasing channel: %p\n", dtc); ++ /* Mark this channel as not built */ ++ dahdi_tc_clear_built(dtc); ++ dtc->built_fmts = 0; ++ cpvt->chan_in_num = INVALID; ++ cpvt->chan_out_num = INVALID; ++ /* Mark the channel complement as not built */ ++ dahdi_tc_clear_built(compl_dtc); ++ compl_dtc->built_fmts = 0; ++ compl_cpvt = compl_dtc->pvt; ++ compl_cpvt->chan_in_num = INVALID; ++ compl_cpvt->chan_out_num = INVALID; ++ ++ wctc4xxp_check_for_rx_errors(wc); ++ ++error_exit: ++ mutex_unlock(&wc->chanlock); ++ return res; ++} ++ ++static inline struct tcb* ++get_ready_cmd(struct dahdi_transcoder_channel *dtc) ++{ ++ struct channel_pvt *cpvt = dtc->pvt; ++ struct tcb *cmd; ++ unsigned long flags; ++ spin_lock_irqsave(&cpvt->lock, flags); ++ if (!list_empty(&cpvt->rx_queue)) { ++ WARN_ON(!dahdi_tc_is_data_waiting(dtc)); ++ cmd = list_entry(cpvt->rx_queue.next, struct tcb, node); ++ list_del_init(&cmd->node); ++ } else { ++ cmd = NULL; ++ } ++ if (list_empty(&cpvt->rx_queue)) ++ dahdi_tc_clear_data_waiting(dtc); ++ spin_unlock_irqrestore(&cpvt->lock, flags); ++ return cmd; ++} ++ ++static int ++wctc4xxp_handle_receive_ring(struct wcdte *wc) ++{ ++ struct tcb *cmd; ++ unsigned long flags; ++ unsigned int count = 0; ++ ++ /* If we can't grab this lock, another thread must already be checking ++ * the receive ring...so we should just finish up, and we'll try again ++ * later. */ ++#if defined(spin_trylock_irqsave) ++ if (!spin_trylock_irqsave(&wc->rx_lock, flags)) ++ return 0; ++#else ++ if (spin_is_locked(&wc->rx_lock)) ++ return 0; ++ spin_lock_irqsave(&wc->rx_lock, flags); ++#endif ++ ++ while ((cmd = wctc4xxp_retrieve(wc->rxd))) { ++ ++count; ++ spin_lock(&wc->rx_list_lock); ++ list_add_tail(&cmd->node, &wc->rx_list); ++ spin_unlock(&wc->rx_list_lock); ++ cmd = __alloc_cmd(SFRAME_SIZE, GFP_ATOMIC, 0); ++ if (!cmd) { ++ dev_err(&wc->pdev->dev, ++ "Out of memory in %s.\n", __func__); ++ } else { ++ if (wctc4xxp_submit(wc->rxd, cmd)) { ++ dev_err(&wc->pdev->dev, "Failed submit in %s\n", ++ __func__); ++ free_cmd(cmd); ++ } ++ } ++ } ++ spin_unlock_irqrestore(&wc->rx_lock, flags); ++ return count; ++} ++ ++/* Called with a buffer in which to copy a transcoded frame. */ ++static ssize_t ++wctc4xxp_read(struct file *file, char __user *frame, size_t count, loff_t *ppos) ++{ ++ ssize_t ret; ++ struct dahdi_transcoder_channel *dtc = file->private_data; ++ struct channel_pvt *cpvt = dtc->pvt; ++ struct wcdte *wc = cpvt->wc; ++ struct tcb *cmd; ++ struct rtp_packet *packet; ++ ssize_t payload_bytes; ++ ssize_t returned_bytes = 0; ++ unsigned long flags; ++ ++ BUG_ON(!dtc); ++ BUG_ON(!cpvt); ++ ++ if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) { ++ /* The shudown flags can also be set if there is a ++ * catastrophic failure. */ ++ return -EIO; ++ } ++ ++ cmd = get_ready_cmd(dtc); ++ if (!cmd) { ++ if (file->f_flags & O_NONBLOCK) ++ return -EAGAIN; ++ ret = wait_event_interruptible(dtc->ready, ++ dahdi_tc_is_data_waiting(dtc)); ++ if (-ERESTARTSYS == ret) ++ return -EINTR; ++ /* List went not empty. */ ++ cmd = get_ready_cmd(dtc); ++ } ++ ++ do { ++ BUG_ON(!cmd); ++ packet = cmd->data; ++ ++ payload_bytes = be16_to_cpu(packet->udphdr.len) - ++ sizeof(struct rtphdr) - ++ sizeof(struct udphdr); ++ ++ if (count < (payload_bytes + returned_bytes)) { ++ if (returned_bytes) { ++ /* If we have already returned at least one ++ * packets worth of data, we'll add this next ++ * packet to the head of the receive queue so ++ * it will be picked up next time. */ ++ spin_lock_irqsave(&cpvt->lock, flags); ++ list_add(&cmd->node, &cpvt->rx_queue); ++ dahdi_tc_set_data_waiting(dtc); ++ spin_unlock_irqrestore(&cpvt->lock, flags); ++ return returned_bytes; ++ } ++ ++ if (printk_ratelimit()) { ++ dev_err(&wc->pdev->dev, ++ "Cannot copy %zd bytes into %zd byte user " \ ++ "buffer.\n", payload_bytes, count); ++ } ++ free_cmd(cmd); ++ return -EFBIG; ++ } ++ ++ atomic_inc(&cpvt->stats.packets_received); ++ ++ ret = copy_to_user(&frame[returned_bytes], ++ &packet->payload[0], payload_bytes); ++ if (unlikely(ret)) { ++ dev_err(&wc->pdev->dev, "Failed to copy data in %s\n", ++ __func__); ++ free_cmd(cmd); ++ return -EFAULT; ++ } ++ ++ returned_bytes += payload_bytes; ++ ++ free_cmd(cmd); ++ ++ } while ((cmd = get_ready_cmd(dtc))); ++ ++ return returned_bytes; ++} ++ ++/* Called with a frame in the srcfmt to be transcoded into the dstfmt. */ ++static ssize_t ++wctc4xxp_write(struct file *file, const char __user *frame, ++ size_t count, loff_t *ppos) ++{ ++ struct dahdi_transcoder_channel *dtc = file->private_data; ++ struct channel_pvt *cpvt = dtc->pvt; ++ struct wcdte *wc = cpvt->wc; ++ struct tcb *cmd; ++ u32 samples; ++ unsigned long flags; ++ const unsigned long MAX_SAMPLES_IN_FLIGHT = 640; ++ const unsigned long MAX_RTP_PAYLOAD = 500; ++ ++ BUG_ON(!cpvt); ++ BUG_ON(!wc); ++ ++ if (unlikely(test_bit(DTE_SHUTDOWN, &wc->flags))) ++ return -EIO; ++ ++ if (!test_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags)) ++ return -EAGAIN; ++ ++ if (count < 2) { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, ++ "Cannot request to transcode a packet that is less than " \ ++ "2 bytes.\n"); ++ return -EINVAL; ++ } ++ ++ if (count > MAX_RTP_PAYLOAD) { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, ++ "Cannot transcode packet of %Zu bytes. This exceeds the maximum size of %lu bytes.\n", ++ count, MAX_RTP_PAYLOAD); ++ return -EINVAL; ++ } ++ ++ if (DAHDI_FORMAT_G723_1 == dtc->srcfmt) { ++ if ((G723_5K_BYTES != count) && (G723_6K_BYTES != count) && ++ (G723_SID_BYTES != count)) { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, ++ "Trying to transcode packet into G723 format " \ ++ "that is %Zu bytes instead of the expected " \ ++ "%d/%d/%d bytes.\n", count, G723_5K_BYTES, ++ G723_6K_BYTES, G723_SID_BYTES); ++ return -EINVAL; ++ } ++ } ++ ++ /* Do not flood the firmware with packets. This can result in out of ++ * memory conditions in the firmware. */ ++ spin_lock_irqsave(&cpvt->lock, flags); ++ if (time_after(jiffies, cpvt->send_time)) { ++ cpvt->samples_in_flight = max(0L, ++ cpvt->samples_in_flight - 160L); ++ } ++ samples = wctc4xxp_bytes_to_samples(dtc->srcfmt, count); ++ if ((cpvt->samples_in_flight + samples) > MAX_SAMPLES_IN_FLIGHT) { ++ spin_unlock_irqrestore(&cpvt->lock, flags); ++ /* This should most likely be an error, but it results in ++ * codec_dahdi spamming when it's not set to wait for new ++ * packets. Instead we will silently drop the bytes. */ ++ return count; ++ } ++ cpvt->send_time = jiffies + msecs_to_jiffies(20); ++ spin_unlock_irqrestore(&cpvt->lock, flags); ++ ++ cmd = wctc4xxp_create_rtp_cmd(wc, dtc, count); ++ if (!cmd) ++ return -ENOMEM; ++ /* Copy the data directly from user space into the command buffer. */ ++ if (copy_from_user(&((struct rtp_packet *)(cmd->data))->payload[0], ++ frame, count)) { ++ dev_err(&wc->pdev->dev, ++ "Failed to copy packet from userspace.\n"); ++ free_cmd(cmd); ++ return -EFAULT; ++ } ++ cpvt->seqno += 1; ++ ++ DTE_DEBUG(DTE_DEBUG_RTP_TX, ++ "Sending packet of %Zu byte on channel (%p).\n", count, dtc); ++ ++ atomic_inc(&cpvt->stats.packets_sent); ++ wctc4xxp_transmit_cmd(wc, cmd); ++ ++ return count; ++} ++ ++static void ++wctc4xxp_send_ack(struct wcdte *wc, u8 seqno, __be16 channel, __le16 function) ++{ ++ struct tcb *cmd; ++ struct csm_encaps_hdr *hdr; ++ cmd = __alloc_cmd(sizeof(*hdr), ALLOC_FLAGS, 0); ++ if (!cmd) { ++ WARN_ON(1); ++ return; ++ } ++ hdr = cmd->data; ++ BUG_ON(sizeof(*hdr) > cmd->data_len); ++ setup_common_header(wc, hdr); ++ hdr->op_code = cpu_to_be16(0x0001); ++ hdr->seq_num = seqno; ++ hdr->control = 0xe0; ++ hdr->channel = channel; ++ hdr->cmd.function = function; ++ ++ wctc4xxp_transmit_cmd(wc, cmd); ++} ++ ++ ++static void do_rx_response_packet(struct wcdte *wc, struct tcb *cmd) ++{ ++ struct csm_encaps_hdr *rxhdr; ++ const struct csm_encaps_hdr *listhdr; ++ struct tcb *pos, *temp; ++ unsigned long flags; ++ bool handled = false; ++ rxhdr = cmd->data; ++ ++ /* Check if duplicated response on the supervisor channel. */ ++ if (SUPERVISOR_CHANNEL == rxhdr->channel) { ++ if (rxhdr->seq_num == wc->last_rx_seq_num) { ++ free_cmd(cmd); ++ return; ++ } ++ wc->last_rx_seq_num = rxhdr->seq_num; ++ } ++ ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ list_for_each_entry_safe(pos, temp, ++ &wc->waiting_for_response_list, node) { ++ listhdr = pos->data; ++ if ((listhdr->cmd.function == rxhdr->cmd.function) && ++ (listhdr->channel == rxhdr->channel)) { ++ ++ /* If this is a channel command, do not complete it if ++ * the seq_num is the same as previous. */ ++ if (pos->cpvt) { ++ if (rxhdr->seq_num == ++ pos->cpvt->last_rx_seq_num) { ++ break; ++ } ++ pos->cpvt->last_rx_seq_num = rxhdr->seq_num; ++ } ++ ++ list_del_init(&pos->node); ++ pos->flags &= ~(WAIT_FOR_RESPONSE); ++ pos->response = cmd; ++ /* If this isn't TX_COMPLETE yet, then this packet will ++ * be completed in service_tx_ring. */ ++ if (pos->flags & TX_COMPLETE && pos->complete) ++ complete(pos->complete); ++ handled = true; ++ ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++ ++ if (!handled) { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, ++ "Freeing unhandled response ch:(%04x)\n", ++ be16_to_cpu(rxhdr->channel)); ++ free_cmd(cmd); ++ } ++} ++ ++static void ++do_rx_ack_packet(struct wcdte *wc, struct tcb *cmd) ++{ ++ const struct csm_encaps_hdr *listhdr, *rxhdr; ++ struct tcb *pos, *temp; ++ unsigned long flags; ++ ++ rxhdr = cmd->data; ++ ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ list_for_each_entry_safe(pos, temp, ++ &wc->waiting_for_response_list, node) { ++ listhdr = pos->data; ++ if (cpu_to_be16(0xefed) == listhdr->ethhdr.h_proto) { ++ wc->seq_num = (rxhdr->seq_num + 1) & 0xff; ++ WARN_ON(!(pos->complete)); ++ WARN_ON(!(pos->flags & TX_COMPLETE)); ++ list_del_init(&pos->node); ++ if (pos->complete) ++ complete(pos->complete); ++ } else if ((listhdr->seq_num == rxhdr->seq_num) && ++ (listhdr->channel == rxhdr->channel)) { ++ if (pos->flags & WAIT_FOR_RESPONSE) { ++ pos->flags &= ~(WAIT_FOR_ACK); ++ } else { ++ list_del_init(&pos->node); ++ ++ if (pos->complete) { ++ WARN_ON(!(pos->flags & TX_COMPLETE)); ++ complete(pos->complete); ++ } else { ++ free_cmd(pos); ++ } ++ } ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++ ++ /* There is never a reason to store up the ack packets. */ ++ free_cmd(cmd); ++} ++ ++static inline int ++is_response(const struct csm_encaps_hdr *hdr) ++{ ++ return ((0x02 == hdr->cmd.type) || ++ (0x04 == hdr->cmd.type) || ++ (0x0e == hdr->cmd.type) || ++ (0x00 == hdr->cmd.type)) ? 1 : 0; ++} ++ ++static void ++print_command(struct wcdte *wc, const struct csm_encaps_hdr *hdr) ++{ ++ int i, curlength; ++ char *buffer; ++ const int BUFFER_SIZE = 1024; ++ int parameters = ((hdr->cmd.length - 8)/sizeof(__le16)); ++ ++ buffer = kzalloc(BUFFER_SIZE + 1, GFP_ATOMIC); ++ if (!buffer) { ++ dev_info(&wc->pdev->dev, "Failed print_command\n"); ++ return; ++ } ++ curlength = snprintf(buffer, BUFFER_SIZE, ++ "opcode: %04x seq: %02x control: %02x " ++ "channel: %04x ", be16_to_cpu(hdr->op_code), ++ hdr->seq_num, hdr->control, be16_to_cpu(hdr->channel)); ++ curlength += snprintf(buffer + curlength, BUFFER_SIZE - curlength, ++ "length: %02x index: %02x type: %02x " ++ "class: %02x function: %04x", ++ hdr->cmd.length, hdr->cmd.index, hdr->cmd.type, hdr->cmd.class, ++ le16_to_cpu(hdr->cmd.function)); ++ for (i = 0; i < parameters; ++i) { ++ curlength += snprintf(buffer + curlength, ++ BUFFER_SIZE - curlength, " %04x", ++ le16_to_cpu(hdr->cmd.params[i])); ++ } ++ dev_info(&wc->pdev->dev, "%s\n", buffer); ++ kfree(buffer); ++} ++ ++static inline void wctc4xxp_reset_processor(struct wcdte *wc) ++{ ++ wctc4xxp_setctl(wc, 0x00A0, 0x04000000); ++} ++ ++ ++static void handle_csm_alert(struct wcdte *wc, ++ const struct csm_encaps_hdr *hdr) ++{ ++ const struct csm_encaps_cmd *c = &hdr->cmd; ++ if (c->function == 0x0000) { ++ u16 alert_type = le16_to_cpu(c->params[0]); ++ u16 action_required = le16_to_cpu(c->params[1]) >> 8; ++ const bool fatal_error = action_required != 0; ++ ++ dev_err(&wc->pdev->dev, ++ "Received alert (0x%04x) from dsp. Firmware will be reloaded when possible.\n", ++ alert_type); ++ ++ if (fatal_error) { ++ /* If any fatal errors are reported we'll just shut ++ * everything down so that we do not hang up any user ++ * process trying to wait for commands to complete. */ ++ wctc4xxp_reset_processor(wc); ++ set_bit(DTE_RELOAD, &wc->flags); ++ set_bit(DTE_SHUTDOWN, &wc->flags); ++ wctc4xxp_timeout_all_commands(wc); ++ } else { ++ /* For non-fatal errors we'll try to proceed and reload ++ * the firmware when all open channels are closed. This ++ * will prevent impacting any normal calls in progress. ++ * ++ */ ++ set_bit(DTE_RELOAD, &wc->flags); ++ } ++ } else { ++ if (debug) { ++ dev_warn(&wc->pdev->dev, ++ "Received diagnostic message:\n"); ++ } ++ } ++ ++ if (debug) { ++ print_command(wc, hdr); ++ } ++} ++ ++static void ++receive_csm_encaps_packet(struct wcdte *wc, struct tcb *cmd) ++{ ++ const struct csm_encaps_hdr *hdr = cmd->data; ++ const struct csm_encaps_cmd *c = &hdr->cmd; ++ ++ if (!(hdr->control & MESSAGE_PACKET)) { ++ const bool suppress_ack = ((hdr->control & SUPPRESS_ACK) > 0); ++ ++ if (!suppress_ack) { ++ wctc4xxp_send_ack(wc, hdr->seq_num, hdr->channel, ++ c->function); ++ } ++ ++ if (is_response(hdr)) { ++ ++ do_rx_response_packet(wc, cmd); ++ ++ } else if (0xc1 == c->type) { ++ ++ if (0x75 == c->class) { ++ dev_warn(&wc->pdev->dev, ++ "Received alert (0x%04x) from dsp\n", ++ le16_to_cpu(c->params[0])); ++ } ++ free_cmd(cmd); ++ } else if (0xd4 == c->type) { ++ if (c->params[0] != le16_to_cpu(0xffff)) { ++ dev_warn(&wc->pdev->dev, ++ "DTE Failed self test (%04x).\n", ++ le16_to_cpu(c->params[0])); ++ } else if ((c->params[1] != le16_to_cpu(0x000c)) && ++ (c->params[1] != le16_to_cpu(0x010c))) { ++ dev_warn(&wc->pdev->dev, ++ "Unexpected ERAM status (%04x).\n", ++ le16_to_cpu(c->params[1])); ++ } else { ++ wctc4xxp_set_ready(wc); ++ wake_up(&wc->waitq); ++ } ++ free_cmd(cmd); ++ } else if (MONITOR_LIVE_INDICATION_TYPE == c->type) { ++ handle_csm_alert(wc, hdr); ++ free_cmd(cmd); ++ } else { ++ dev_warn(&wc->pdev->dev, ++ "Unknown command type received. %02x\n", ++ c->type); ++ free_cmd(cmd); ++ } ++ } else { ++ do_rx_ack_packet(wc, cmd); ++ } ++} ++ ++static void ++queue_rtp_packet(struct wcdte *wc, struct tcb *cmd) ++{ ++ unsigned index; ++ struct dahdi_transcoder_channel *dtc; ++ struct channel_pvt *cpvt; ++ struct rtp_packet *packet = cmd->data; ++ unsigned long flags; ++ long samples; ++ ++ if (unlikely(ip_fast_csum((void *)(&packet->iphdr), ++ packet->iphdr.ihl))) { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, ++ "Invalid checksum in RTP packet %04x\n", ++ ip_fast_csum((void *)(&packet->iphdr), ++ packet->iphdr.ihl)); ++ free_cmd(cmd); ++ return; ++ } ++ ++ index = (be16_to_cpu(packet->udphdr.dest) - 0x5000) / 2; ++ if (unlikely(!(index < wc->numchannels))) { ++ dev_err(&wc->pdev->dev, ++ "Invalid channel number in response from DTE.\n"); ++ free_cmd(cmd); ++ return; ++ } ++ ++ switch (packet->rtphdr.type) { ++ case 0x00: ++ case 0x08: ++ dtc = &(wc->udecode->channels[index]); ++ break; ++ case 0x04: ++ case 0x12: ++ dtc = &(wc->uencode->channels[index]); ++ break; ++ default: ++ dev_err(&wc->pdev->dev, "Unknown codec in packet (0x%02x).\n",\ ++ packet->rtphdr.type); ++ free_cmd(cmd); ++ return; ++ } ++ ++ cpvt = dtc->pvt; ++ if (!dahdi_tc_is_busy(dtc)) { ++ free_cmd(cmd); ++ return; ++ } ++ ++ spin_lock_irqsave(&cpvt->lock, flags); ++ samples = wctc4xxp_bytes_to_samples(dtc->dstfmt, ++ be16_to_cpu(packet->udphdr.len) - ++ sizeof(struct rtphdr) - sizeof(struct udphdr)); ++ cpvt->samples_in_flight = max(cpvt->samples_in_flight - samples, 0L); ++ list_add_tail(&cmd->node, &cpvt->rx_queue); ++ dahdi_tc_set_data_waiting(dtc); ++ spin_unlock_irqrestore(&cpvt->lock, flags); ++ dahdi_transcoder_alert(dtc); ++ return; ++} ++ ++static void service_tx_ring(struct wcdte *wc) ++{ ++ struct tcb *cmd; ++ unsigned long flags; ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ while ((cmd = wctc4xxp_retrieve(wc->txd))) { ++ cmd->flags |= TX_COMPLETE; ++ if (!(cmd->flags & (WAIT_FOR_ACK | WAIT_FOR_RESPONSE))) { ++ /* If we're not waiting for an ACK or Response from ++ * the DTE, this message should not be sitting on any ++ * lists. */ ++ WARN_ON(!list_empty(&cmd->node)); ++ if (cmd->complete) { ++ WARN_ON(!(cmd->flags & TX_COMPLETE)); ++ complete(cmd->complete); ++ } else { ++ free_cmd(cmd); ++ } ++ } ++ ++ /* We've freed up a spot in the hardware ring buffer. If ++ * another packet is queued up, let's submit it to the ++ * hardware. */ ++ if (!list_empty(&wc->cmd_list)) { ++ cmd = list_entry(wc->cmd_list.next, struct tcb, node); ++ list_del_init(&cmd->node); ++ if (cmd->flags & (WAIT_FOR_ACK | WAIT_FOR_RESPONSE)) { ++ list_add_tail(&cmd->node, ++ &wc->waiting_for_response_list); ++ } ++ wctc4xxp_submit(wc->txd, cmd); ++ } ++ } ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++} ++ ++static void service_rx_ring(struct wcdte *wc) ++{ ++ struct tcb *cmd; ++ unsigned long flags; ++ LIST_HEAD(local_list); ++ spin_lock_irqsave(&wc->rx_list_lock, flags); ++ list_splice_init(&wc->rx_list, &local_list); ++ spin_unlock_irqrestore(&wc->rx_list_lock, flags); ++ ++ /* ++ * Process the received packets ++ */ ++ while (!list_empty(&local_list)) { ++ const struct ethhdr *ethhdr; ++ ++ cmd = container_of(local_list.next, struct tcb, node); ++ ethhdr = (const struct ethhdr *)(cmd->data); ++ list_del_init(&cmd->node); ++ ++ wctc4xxp_net_capture_cmd(wc, cmd); ++ if (cpu_to_be16(ETH_P_IP) == ethhdr->h_proto) { ++ queue_rtp_packet(wc, cmd); ++ } else if (cpu_to_be16(ETH_P_CSM_ENCAPS) == ethhdr->h_proto) { ++ receive_csm_encaps_packet(wc, cmd); ++ } else { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, ++ "Unknown packet protocol received: %04x.\n", ++ be16_to_cpu(ethhdr->h_proto)); ++ free_cmd(cmd); ++ } ++ } ++ wctc4xxp_receive_demand_poll(wc); ++} ++ ++static void deferred_work_func(struct work_struct *work) ++{ ++ struct wcdte *wc = container_of(work, struct wcdte, deferred_work); ++ service_rx_ring(wc); ++} ++ ++static irqreturn_t wctc4xxp_interrupt(int irq, void *dev_id) ++{ ++ struct wcdte *wc = dev_id; ++ bool packets_to_process = false; ++ u32 ints; ++#define NORMAL_INTERRUPT_SUMMARY (1<<16) ++#define ABNORMAL_INTERRUPT_SUMMARY (1<<15) ++ ++#define TX_COMPLETE_INTERRUPT 0x00000001 ++#define RX_COMPLETE_INTERRUPT 0x00000040 ++#define TIMER_INTERRUPT (1<<11) ++#define NORMAL_INTERRUPTS (TX_COMPLETE_INTERRUPT | RX_COMPLETE_INTERRUPT | \ ++ TIMER_INTERRUPT) ++ ++ /* Read and clear interrupts */ ++ ints = __wctc4xxp_getctl(wc, 0x0028); ++ ++ if (!(ints & (NORMAL_INTERRUPT_SUMMARY|ABNORMAL_INTERRUPT_SUMMARY))) ++ return IRQ_NONE; ++ ++ /* Clear all the pending interrupts. */ ++ __wctc4xxp_setctl(wc, 0x0028, ints); ++ ++ if (ints & (RX_COMPLETE_INTERRUPT | TIMER_INTERRUPT)) { ++ packets_to_process = wctc4xxp_handle_receive_ring(wc) > 0; ++ service_tx_ring(wc); ++ ++#if DEFERRED_PROCESSING == WORKQUEUE ++ if (packets_to_process) ++ schedule_work(&wc->deferred_work); ++#elif DEFERRED_PROCESSING == INTERRUPT ++#error "You will need to change the locks if you want to run the processing " \ ++ "in the interrupt handler." ++#else ++#error "Define a deferred processing function in kernel/wctc4xxp/wctc4xxp.h" ++#endif ++ ++ } else { ++ if ((ints & 0x00008000) && debug) ++ dev_info(&wc->pdev->dev, "Abnormal Interrupt.\n"); ++ ++ if (ints & 0x00002000) ++ dev_err(&wc->pdev->dev, "Fatal Bus Error Detected.\n"); ++ ++ if ((ints & 0x00000100) && debug) ++ dev_info(&wc->pdev->dev, "Receive Stopped INT\n"); ++ ++ if ((ints & 0x00000080) && debug) { ++ dev_info(&wc->pdev->dev, ++ "Receive Desciptor Unavailable INT " \ ++ "(%d)\n", wctc4xxp_getcount(wc->rxd)); ++ } ++ ++ if ((ints & 0x00000020) && debug) ++ dev_info(&wc->pdev->dev, "Transmit Under-flow INT\n"); ++ ++ if ((ints & 0x00000008) && debug) ++ dev_info(&wc->pdev->dev, "Jabber Timer Time-out INT\n"); ++ ++ if ((ints & 0x00000002) && debug) { ++ dev_info(&wc->pdev->dev, ++ "Transmit Processor Stopped INT\n"); ++ } ++ } ++ return IRQ_HANDLED; ++} ++ ++static int ++wctc4xxp_hardware_init(struct wcdte *wc) ++{ ++ /* Hardware stuff */ ++ enum { ++ /* Software Reset */ ++ SWR = (1 << 0), ++ /* Bus Arbitration (1 for priority transmit) */ ++ BAR = (1 << 1), ++ /* Memory Write Invalidate */ ++ MWI = (1 << 24), ++ /* Memory Read Line */ ++ MRL = (1 << 23), ++ /* Descriptor Skip Length */ ++ DSLShift = 2, ++ /* Cache Alignment */ ++ CALShift = 14, ++ /* Transmit Auto Pollling */ ++ TAPShift = 17, ++ }; ++ u32 reg; ++ unsigned long newjiffies; ++ u8 cache_line_size; ++ const u32 DEFAULT_PCI_ACCESS = (MWI | (11 << TAPShift)); ++ ++ if (pci_read_config_byte(wc->pdev, 0x0c, &cache_line_size)) ++ return -EIO; ++ ++ switch (cache_line_size) { ++ case 0x08: ++ reg = DEFAULT_PCI_ACCESS | (0x1 << CALShift); ++ break; ++ case 0x10: ++ reg = DEFAULT_PCI_ACCESS | (0x2 << CALShift); ++ break; ++ case 0x20: ++ reg = DEFAULT_PCI_ACCESS | (0x3 << CALShift); ++ break; ++ default: ++ reg = (11 << TAPShift); ++ break; ++ } ++ ++ reg |= ((wc->txd->padding / sizeof(u32)) << 2) & 0x7c; ++ ++ /* Reset the DTE... */ ++ wctc4xxp_setctl(wc, 0x0000, reg | 1); ++ newjiffies = jiffies + HZ; /* One second timeout */ ++ /* ...and wait for it to come out of reset. */ ++ while (((wctc4xxp_getctl(wc, 0x0000)) & 0x00000001) && ++ (newjiffies > jiffies)) ++ msleep(1); ++ ++ wctc4xxp_setctl(wc, 0x0000, reg | 0x60000); ++ ++ /* Configure watchdogs, access, etc */ ++ wctc4xxp_setctl(wc, 0x0030, 0x00280048); ++ wctc4xxp_setctl(wc, 0x0078, 0x00000013); ++ reg = wctc4xxp_getctl(wc, 0x00fc); ++ wctc4xxp_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); ++ reg = wctc4xxp_getctl(wc, 0x00fc); ++ return 0; ++} ++ ++static void ++wctc4xxp_start_dma(struct wcdte *wc) ++{ ++ int res; ++ int i; ++ u32 reg; ++ struct tcb *cmd; ++ ++ for (i = 0; i < wc->rxd->size; ++i) { ++ cmd = alloc_cmd(SFRAME_SIZE); ++ if (!cmd) { ++ WARN_ALWAYS(); ++ return; ++ } ++ WARN_ON(SFRAME_SIZE != cmd->data_len); ++ res = wctc4xxp_submit(wc->rxd, cmd); ++ if (res) { ++ /* When we're starting the DMA, we should always be ++ * able to fill the ring....so something is wrong ++ * here. */ ++ WARN_ALWAYS(); ++ free_cmd(cmd); ++ break; ++ } ++ } ++ wmb(); ++ wctc4xxp_setctl(wc, 0x0020, wc->txd->desc_dma); ++ wctc4xxp_setctl(wc, 0x0018, wc->rxd->desc_dma); ++ ++ /* Start receiver/transmitter */ ++ reg = wctc4xxp_getctl(wc, 0x0030); ++ wctc4xxp_setctl(wc, 0x0030, reg | 0x00002002); ++ wctc4xxp_receive_demand_poll(wc); ++ reg = wctc4xxp_getctl(wc, 0x0028); ++ wctc4xxp_setctl(wc, 0x0028, reg); ++ ++} ++ ++static void ++_wctc4xxp_stop_dma(struct wcdte *wc) ++{ ++ /* Disable interrupts and reset */ ++ unsigned int reg; ++ /* Disable interrupts */ ++ wctc4xxp_setintmask(wc, 0x00000000); ++ wctc4xxp_setctl(wc, 0x0084, 0x00000000); ++ wctc4xxp_setctl(wc, 0x0048, 0x00000000); ++ /* Reset the part to be on the safe side */ ++ reg = wctc4xxp_getctl(wc, 0x0000); ++ reg |= 0x00000001; ++ wctc4xxp_setctl(wc, 0x0000, reg); ++} ++ ++static void ++wctc4xxp_stop_dma(struct wcdte *wc) ++{ ++ unsigned long newjiffies; ++ ++ _wctc4xxp_stop_dma(wc); ++ newjiffies = jiffies + HZ; /* One second timeout */ ++ /* We'll wait here for the part to come out of reset */ ++ while (((wctc4xxp_getctl(wc, 0x0000)) & 0x00000001) && ++ (newjiffies > jiffies)) ++ msleep(1); ++} ++ ++#define MDIO_SHIFT_CLK 0x10000 ++#define MDIO_DATA_WRITE1 0x20000 ++#define MDIO_ENB 0x00000 ++#define MDIO_ENB_IN 0x40000 ++#define MDIO_DATA_READ 0x80000 ++ ++static int ++wctc4xxp_read_phy(struct wcdte *wc, int location) ++{ ++ int i; ++ long mdio_addr = 0x0048; ++ int read_cmd = (0xf6 << 10) | (1 << 5) | location; ++ int retval = 0; ++ ++ /* Establish sync by sending at least 32 logic ones. */ ++ for (i = 32; i >= 0; --i) { ++ wctc4xxp_setctl(wc, mdio_addr, ++ MDIO_ENB | MDIO_DATA_WRITE1); ++ wctc4xxp_getctl(wc, mdio_addr); ++ wctc4xxp_setctl(wc, mdio_addr, ++ MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); ++ wctc4xxp_getctl(wc, mdio_addr); ++ } ++ ++ /* Shift the read command bits out. */ ++ for (i = 17; i >= 0; --i) { ++ int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; ++ ++ wctc4xxp_setctl(wc, mdio_addr, MDIO_ENB | dataval); ++ wctc4xxp_getctl(wc, mdio_addr); ++ wctc4xxp_setctl(wc, mdio_addr, ++ MDIO_ENB | dataval | MDIO_SHIFT_CLK); ++ wctc4xxp_getctl(wc, mdio_addr); ++ } ++ ++ /* Read the two transition, 16 data, and wire-idle bits. */ ++ for (i = 19; i > 0; --i) { ++ wctc4xxp_setctl(wc, mdio_addr, MDIO_ENB_IN); ++ wctc4xxp_getctl(wc, mdio_addr); ++ retval = (retval << 1) | ++ ((wctc4xxp_getctl(wc, mdio_addr) & MDIO_DATA_READ) ? ++ 1 : 0); ++ wctc4xxp_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); ++ wctc4xxp_getctl(wc, mdio_addr); ++ } ++ retval = (retval>>1) & 0xffff; ++ return retval; ++} ++ ++static void ++wctc4xxp_write_phy(struct wcdte *wc, int location, int value) ++{ ++ int i; ++ int cmd = (0x5002 << 16) | (1 << 23) | (location<<18) | value; ++ long mdio_addr = 0x0048; ++ ++ /* Establish sync by sending 32 logic ones. */ ++ for (i = 32; i >= 0; --i) { ++ wctc4xxp_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); ++ wctc4xxp_getctl(wc, mdio_addr); ++ wctc4xxp_setctl(wc, mdio_addr, ++ MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); ++ wctc4xxp_getctl(wc, mdio_addr); ++ } ++ /* Shift the command bits out. */ ++ for (i = 31; i >= 0; --i) { ++ int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; ++ wctc4xxp_setctl(wc, mdio_addr, MDIO_ENB | dataval); ++ wctc4xxp_getctl(wc, mdio_addr); ++ wctc4xxp_setctl(wc, mdio_addr, ++ MDIO_ENB | dataval | MDIO_SHIFT_CLK); ++ wctc4xxp_getctl(wc, mdio_addr); ++ } ++ /* Clear out extra bits. */ ++ for (i = 2; i > 0; --i) { ++ wctc4xxp_setctl(wc, mdio_addr, MDIO_ENB_IN); ++ wctc4xxp_getctl(wc, mdio_addr); ++ wctc4xxp_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); ++ wctc4xxp_getctl(wc, mdio_addr); ++ } ++ return; ++} ++ ++static int ++wctc4xxp_wait_for_link(struct wcdte *wc) ++{ ++ int reg; ++ unsigned int delay_count = 0; ++ do { ++ reg = wctc4xxp_getctl(wc, 0x00fc); ++ msleep(2); ++ delay_count++; ++ ++ if (delay_count >= 5000) { ++ dev_err(&wc->pdev->dev, ++ "Failed to link to DTE processor!\n"); ++ return -EIO; ++ } ++ } while ((reg & 0xE0000000) != 0xE0000000); ++ return 0; ++} ++ ++static int ++wctc4xxp_load_firmware(struct wcdte *wc, const struct firmware *firmware) ++{ ++ unsigned int byteloc; ++ unsigned int length; ++ struct tcb *cmd; ++ DECLARE_COMPLETION_ONSTACK(done); ++ ++ byteloc = 17; ++ ++ cmd = alloc_cmd(SFRAME_SIZE); ++ if (!cmd) ++ return -ENOMEM; ++ ++#if defined(CONFIG_WCTC4XXP_POLLING) ++ wctc4xxp_enable_polling(wc); ++#endif ++ ++ clear_bit(DTE_READY, &wc->flags); ++ ++ while (byteloc < (firmware->size-20)) { ++ length = (firmware->data[byteloc] << 8) | ++ firmware->data[byteloc+1]; ++ byteloc += 2; ++ cmd->data_len = length; ++ BUG_ON(length > cmd->data_len); ++ memcpy(cmd->data, &firmware->data[byteloc], length); ++ byteloc += length; ++ cmd->flags = WAIT_FOR_ACK; ++ cmd->complete = &done; ++ wctc4xxp_transmit_cmd(wc, cmd); ++ wait_for_completion(&done); ++ if (cmd->flags & DTE_CMD_TIMEOUT) { ++ free_cmd(cmd); ++ dev_err(&wc->pdev->dev, "Failed to load firmware.\n"); ++#if defined(CONFIG_WCTC4XXP_POLLING) ++ wctc4xxp_disable_polling(wc); ++#endif ++ return -EIO; ++ } ++ } ++ free_cmd(cmd); ++ if (!wait_event_timeout(wc->waitq, wctc4xxp_is_ready(wc), 15*HZ)) { ++ dev_err(&wc->pdev->dev, "Failed to boot firmware.\n"); ++#if defined(CONFIG_WCTC4XXP_POLLING) ++ wctc4xxp_disable_polling(wc); ++#endif ++ return -EIO; ++ } ++ ++#if defined(CONFIG_WCTC4XXP_POLLING) ++ wctc4xxp_disable_polling(wc); ++#endif ++ return 0; ++} ++ ++static int ++wctc4xxp_turn_off_booted_led(struct wcdte *wc) ++{ ++ int ret = 0; ++ int reg; ++ /* Turn off auto negotiation */ ++ wctc4xxp_write_phy(wc, 0, 0x2100); ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "PHY register 0 = %X\n", ++ wctc4xxp_read_phy(wc, 0)); ++ ++ wctc4xxp_reset_processor(wc); ++ ++ /* Wait 4 ms to ensure processor reset */ ++ msleep(4); ++ ++ /* Clear reset */ ++ wctc4xxp_setctl(wc, 0x00A0, 0x04080000); ++ ++ /* Wait for the ethernet link */ ++ ret = wctc4xxp_wait_for_link(wc); ++ if (ret) ++ return ret; ++ ++ /* Turn off booted LED */ ++ wctc4xxp_setctl(wc, 0x00A0, 0x04084000); ++ reg = wctc4xxp_getctl(wc, 0x00fc); ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "LINK STATUS: reg(0xfc) = %X\n", reg); ++ ++ reg = wctc4xxp_getctl(wc, 0x00A0); ++ ++ return ret; ++} ++ ++static void ++wctc4xxp_turn_on_booted_led(struct wcdte *wc) ++{ ++ wctc4xxp_setctl(wc, 0x00A0, 0x04080000); ++} ++ ++static int ++wctc4xxp_boot_processor(struct wcdte *wc, const struct firmware *firmware) ++{ ++ int ret; ++ ++ wctc4xxp_turn_off_booted_led(wc); ++ ret = wctc4xxp_load_firmware(wc, firmware); ++ if (ret) ++ return ret; ++ ++ wctc4xxp_turn_on_booted_led(wc); ++ ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "Successfully booted DTE processor.\n"); ++ return 0; ++} ++ ++static void ++setup_half_channel(struct channel_pvt *pvt, struct tcb *cmd, u16 length) ++{ ++ setup_channel_header(pvt, cmd); ++ ++ append_set_ip_hdr_channel_cmd(cmd); ++ append_voip_vceopt_cmd(cmd, length); ++ append_voip_tonectl_cmd(cmd); ++ append_voip_dtmfopt_cmd(cmd); ++ append_voip_indctrl_cmd(cmd); ++ ++ /* To indicate the end of multiple messages. */ ++ cmd->data_len += 4; ++ WARN_ON(cmd->data_len >= SFRAME_SIZE); ++ ++ wctc4xxp_transmit_cmd(pvt->wc, cmd); ++} ++ ++static int wctc4xxp_setup_channels(struct wcdte *wc, ++ struct channel_pvt *encoder_pvt, ++ struct channel_pvt *decoder_pvt, ++ u16 length) ++{ ++ int res = 0; ++ struct tcb *encoder_cmd; ++ struct tcb *decoder_cmd; ++ DECLARE_COMPLETION_ONSTACK(encoder_done); ++ DECLARE_COMPLETION_ONSTACK(decoder_done); ++ ++ encoder_cmd = alloc_cmd(SFRAME_SIZE); ++ decoder_cmd = alloc_cmd(SFRAME_SIZE); ++ ++ if (!encoder_cmd || !decoder_cmd) { ++ res = -ENOMEM; ++ goto error_exit; ++ } ++ ++ encoder_cmd->complete = &encoder_done; ++ decoder_cmd->complete = &decoder_done; ++ ++ setup_half_channel(encoder_pvt, encoder_cmd, length); ++ setup_half_channel(decoder_pvt, decoder_cmd, length); ++ ++ wait_for_completion(&decoder_done); ++ wait_for_completion(&encoder_done); ++ ++ if (encoder_cmd->flags & DTE_CMD_TIMEOUT || ++ decoder_cmd->flags & DTE_CMD_TIMEOUT) { ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "Timeout waiting for command.\n"); ++ res = -EIO; ++ } ++ ++ if ((0x0000 != response_header(encoder_cmd)->cmd.params[0]) || ++ (0x0000 != response_header(encoder_cmd)->cmd.params[0])) ++ res = -EIO; ++ ++error_exit: ++ free_cmd(encoder_cmd); ++ free_cmd(decoder_cmd); ++ return res; ++} ++ ++static int wctc4xxp_enable_channels(struct wcdte *wc, ++ struct channel_pvt *encoder_pvt, ++ struct channel_pvt *decoder_pvt, ++ u8 complicated, u8 simple) ++{ ++ int res = 0; ++ struct tcb *encoder_cmd; ++ struct tcb *decoder_cmd; ++ DECLARE_COMPLETION_ONSTACK(encoder_done); ++ DECLARE_COMPLETION_ONSTACK(decoder_done); ++ ++ encoder_cmd = alloc_cmd(SFRAME_SIZE); ++ decoder_cmd = alloc_cmd(SFRAME_SIZE); ++ ++ if (!encoder_cmd || !decoder_cmd) { ++ res = -ENOMEM; ++ goto error_exit; ++ } ++ ++ encoder_cmd->complete = &encoder_done; ++ decoder_cmd->complete = &decoder_done; ++ ++ send_voip_vopena_cmd(encoder_pvt, encoder_cmd, complicated); ++ send_voip_vopena_cmd(decoder_pvt, decoder_cmd, simple); ++ ++ wait_for_completion(&decoder_done); ++ wait_for_completion(&encoder_done); ++ ++ if ((0x0000 != response_header(encoder_cmd)->cmd.params[0]) || ++ (0x0000 != response_header(decoder_cmd)->cmd.params[0])) ++ res = -EIO; ++ ++error_exit: ++ free_cmd(encoder_cmd); ++ free_cmd(decoder_cmd); ++ return res; ++} ++ ++static int ++wctc4xxp_create_channel_pair(struct wcdte *wc, struct channel_pvt *cpvt, ++ u8 simple, u8 complicated) ++{ ++ struct channel_pvt *encoder_pvt, *decoder_pvt; ++ u16 encoder_timeslot, decoder_timeslot; ++ u16 encoder_channel, decoder_channel; ++ struct tcb *cmd; ++ u16 length; ++ ++ cmd = alloc_cmd(SFRAME_SIZE); ++ if (!cmd) ++ return -ENOMEM; ++ ++ BUG_ON(!wc || !cpvt); ++ if (cpvt->encoder) { ++ encoder_timeslot = cpvt->timeslot_in_num; ++ decoder_timeslot = cpvt->timeslot_out_num; ++ } else { ++ u8 temp; ++ encoder_timeslot = cpvt->timeslot_out_num; ++ decoder_timeslot = cpvt->timeslot_in_num; ++ temp = simple; ++ simple = complicated; ++ complicated = temp; ++ } ++ ++ length = (DTE_FORMAT_G729A == complicated) ? G729_LENGTH : ++ (DTE_FORMAT_G723_1 == complicated) ? G723_LENGTH : 0; ++ ++ ++ BUG_ON(encoder_timeslot/2 >= wc->numchannels); ++ BUG_ON(decoder_timeslot/2 >= wc->numchannels); ++ encoder_pvt = wc->uencode->channels[encoder_timeslot/2].pvt; ++ decoder_pvt = wc->udecode->channels[decoder_timeslot/2].pvt; ++ BUG_ON(!encoder_pvt); ++ BUG_ON(!decoder_pvt); ++ encoder_pvt->last_rx_seq_num = 0xff; ++ decoder_pvt->last_rx_seq_num = 0xff; ++ ++ WARN_ON(encoder_timeslot == decoder_timeslot); ++ /* First, let's create two channels, one for the simple -> complex ++ * encoder and another for the complex->simple decoder. */ ++ if (send_create_channel_cmd(wc, cmd, encoder_timeslot, ++ &encoder_channel)) ++ goto error_exit; ++ ++ if (send_create_channel_cmd(wc, cmd, decoder_timeslot, ++ &decoder_channel)) ++ goto error_exit; ++ ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "DTE is using the following channels encoder_channel: " \ ++ "%d decoder_channel: %d\n", encoder_channel, decoder_channel); ++ ++ WARN_ON(encoder_channel == decoder_channel); ++ /* Now set all the default parameters for the encoder. */ ++ encoder_pvt->chan_in_num = encoder_channel; ++ encoder_pvt->chan_out_num = decoder_channel; ++ ++ decoder_pvt->chan_in_num = decoder_channel; ++ decoder_pvt->chan_out_num = encoder_channel; ++ ++ if (wctc4xxp_setup_channels(wc, encoder_pvt, decoder_pvt, length)) ++ goto error_exit; ++ ++ if (send_trans_connect_cmd(wc, cmd, encoder_channel, ++ decoder_channel, complicated, simple)) ++ goto error_exit; ++ ++ if (wctc4xxp_enable_channels(wc, encoder_pvt, decoder_pvt, ++ complicated, simple)) ++ goto error_exit; ++ ++ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP, ++ "DTE has completed setup and connected the " \ ++ "two channels together.\n"); ++ ++ free_cmd(cmd); ++ return 0; ++error_exit: ++ free_cmd(cmd); ++ return -EIO; ++} ++ ++static void print_vceinfo_packet(struct wcdte *wc, struct tcb *cmd) ++{ ++ int i; ++ struct device *const dev = &wc->pdev->dev; ++ ++ static const struct { ++ const char *name; ++ bool show; ++ } PARAMETERS[] = { ++ { "Format Revision ", false}, ++ { "Reserved ", false}, ++ { "Call Timer (seconds) ", false}, ++ { "Current Playout Delay [to PCM] ", false}, ++ { "Minimum Playout Delay [to PCM] ", false}, ++ { "Maximum Playout Delay [to PCM] ", false}, ++ { "Clock Offset ", false}, ++ { "PeakJitter (ms) ", true}, ++ { "Interpolative Concealment [to PCM] ", false}, ++ { "Silence Concealment [to PCM] ", false}, ++ { "Jitter Buffer Overflow Discard [from IP] ", true}, ++ { "End-point Detection Errors ", true}, ++ { "Number of Tx Voice Packets [to IP] ", true}, ++ { "Number of Tx Signalling Packets [to IP] ", true}, ++ { "Number of Tx Comfort Noise Packets [to IP] ", true}, ++ { "Total Transmit Duration [to IP] ", true}, ++ { "Voice Transmit Duration [to IP] ", true}, ++ { "Number of Rx Voice Packets [from IP] ", true}, ++ { "Number of Rx Signalling Packets [from IP] ", true}, ++ { "Number of Rx Comfort Noise Packets [from IP] ", true}, ++ { "Total Receive Duration [from IP] ", true}, ++ { "Voice Receive Duration [from IP] ", true}, ++ { "Packets Out of Sequence [from IP] ", true}, ++ { "Bad Protocol Headers [from IP] ", true}, ++ { "Late Packets [from IP] ", true}, ++ { "Reserved (Early Packets) always zero ", false}, ++ { "Number of Rx Voice bytes ", true}, ++ { "Number of Lost Packets [from IP] ", true}, ++ { "Current Transmit Power [from PCM] ", false}, ++ { "Mean Transmit Power [from PCM] ", false}, ++ { "Current Receive Power [to PCM] ", false}, ++ { "Mean Receive Power [to PCM] ", false}, ++ { "Background Noise [to PCM] ", false}, ++ { "ERL Level [to PCM] ", false}, ++ { "ACOM Level [from PCM] ", false}, ++ { "Current Transmit Activity [from PCM] ", false}, ++ { "Current Receive Activity [to PCM] ", false}, ++ { "Discarded Unexpected Packets ", true}, ++ { "Discard Packets Due to Rx Disabled ", true}, ++ { "Discarded Duplicate Packets ", true}, ++ { "Discarded Packets Due to Incorrect Payload Length ", true}, ++ { "Discarded Packets Due to Channel Inactive ", true}, ++ { "Discarded Packets Due to Insufficient Memory ", true} ++ }; ++ ++ u32 *parms = (u32 *)(&response_header(cmd)->cmd.params[0]); ++ for (i = 0; i < 43; ++i) { ++ if (PARAMETERS[i].show) ++ dev_info(dev, "%s%d\n", PARAMETERS[i].name, parms[i]); ++ } ++} ++ ++static void print_eth_statistics_packet(struct wcdte *wc, struct tcb *cmd) ++{ ++ int i; ++ struct device *const dev = &wc->pdev->dev; ++ ++ static const struct { ++ const char *name; ++ bool show; ++ } PARAMETERS[] = { ++ { "Format Revision ", true}, ++ { "Emitted Frames ", true}, ++ { "Received Frames ", true}, ++ { "Unknown Packet Type ", true}, ++ { "Received Broadcast Packets ", true}, ++ { "Unknown Broadcast ", true}, ++ { "Emitted VLAN frames ", true}, ++ { "Received VLAN frames ", true}, ++ { "Received VLAN frames with E-RIF ", true} ++ }; ++ ++ u32 *parms = (u32 *)(&response_header(cmd)->cmd.params[0]); ++ for (i = 0; i < sizeof(PARAMETERS)/sizeof(PARAMETERS[0]); ++i) { ++ if (PARAMETERS[i].show) ++ dev_info(dev, "%s%d\n", PARAMETERS[i].name, parms[i]); ++ } ++} ++ ++static int ++wctc4xxp_destroy_channel_pair(struct wcdte *wc, struct channel_pvt *cpvt) ++{ ++ struct dahdi_transcoder_channel *dtc1, *dtc2; ++ struct channel_pvt *encoder_pvt, *decoder_pvt; ++ int chan1, chan2, timeslot1, timeslot2; ++ struct tcb *cmd; ++ ++ cmd = alloc_cmd(SFRAME_SIZE); ++ if (!cmd) ++ return -ENOMEM; ++ ++ if (cpvt->encoder) { ++ chan1 = cpvt->chan_in_num; ++ timeslot1 = cpvt->timeslot_in_num; ++ chan2 = cpvt->chan_out_num; ++ timeslot2 = cpvt->timeslot_out_num; ++ } else { ++ chan1 = cpvt->chan_out_num; ++ timeslot1 = cpvt->timeslot_out_num; ++ chan2 = cpvt->chan_in_num; ++ timeslot2 = cpvt->timeslot_in_num; ++ } ++ ++ if (timeslot1/2 >= wc->numchannels || timeslot2/2 >= wc->numchannels) { ++ dev_warn(&wc->pdev->dev, ++ "Invalid channel numbers in %s. chan1:%d chan2: %d\n", ++ __func__, timeslot1/2, timeslot2/2); ++ return 0; ++ } ++ ++ dtc1 = &(wc->uencode->channels[timeslot1/2]); ++ dtc2 = &(wc->udecode->channels[timeslot2/2]); ++ encoder_pvt = dtc1->pvt; ++ decoder_pvt = dtc2->pvt; ++ ++ if (debug & DTE_DEBUG_ETH_STATS) { ++ if (send_voip_vceinfo_cmd(encoder_pvt, cmd)) ++ goto error_exit; ++ dev_warn(&wc->pdev->dev, ++ "****************************************\n"); ++ dev_warn(&wc->pdev->dev, ++ "Encoder stats (ch: %d):\n", ++ encoder_pvt->timeslot_in_num); ++ print_vceinfo_packet(wc, cmd); ++ ++ if (send_voip_vceinfo_cmd(decoder_pvt, cmd)) ++ goto error_exit; ++ dev_warn(&wc->pdev->dev, ++ "****************************************\n"); ++ dev_warn(&wc->pdev->dev, ++ "Decoder stats (ch: %d):\n", ++ decoder_pvt->timeslot_in_num); ++ print_vceinfo_packet(wc, cmd); ++ } ++ ++ if (send_voip_vopena_close_cmd(encoder_pvt, cmd)) ++ goto error_exit; ++ if (send_voip_vopena_close_cmd(decoder_pvt, cmd)) ++ goto error_exit; ++ if (send_trans_disconnect_cmd(wc, cmd, chan1, chan2, 0, 0)) ++ goto error_exit; ++ if (send_destroy_channel_cmd(wc, cmd, chan1)) ++ goto error_exit; ++ if (send_destroy_channel_cmd(wc, cmd, chan2)) ++ goto error_exit; ++ ++ if (debug & DTE_DEBUG_ETH_STATS) { ++ if (send_eth_statistics_cmd(wc, cmd)) ++ goto error_exit; ++ print_eth_statistics_packet(wc, cmd); ++ dev_info(&wc->pdev->dev, "AN983 tx packets: %d rx packets: %d\n", ++ wctc4xxp_get_packet_count(wc->txd), ++ wctc4xxp_get_packet_count(wc->rxd)); ++ } ++ ++ free_cmd(cmd); ++ return 0; ++error_exit: ++ free_cmd(cmd); ++ return -1; ++} ++ ++ ++static int wctc4xxp_setup_device(struct wcdte *wc) ++{ ++ struct tcb *cmd; ++ int tdm_bus; ++ ++ cmd = alloc_cmd(SFRAME_SIZE); ++ if (!cmd) ++ return -ENOMEM; ++ ++ if (send_set_arm_clk_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_set_spu_clk_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_tdm_select_bus_mode_cmd(wc, cmd)) ++ goto error_exit; ++ ++ for (tdm_bus = 0; tdm_bus < 4; ++tdm_bus) { ++ if (send_supvsr_setup_tdm_parms(wc, cmd, tdm_bus)) ++ goto error_exit; ++ } ++ ++ if (send_set_eth_header_cmd(wc, cmd, src_mac, dst_mac)) ++ goto error_exit; ++ ++ if (send_ip_service_config_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_arp_service_config_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_icmp_service_config_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_device_set_country_code_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_spu_features_control_cmd(wc, cmd, 0x02)) ++ goto error_exit; ++ ++ if (send_ip_options_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_spu_features_control_cmd(wc, cmd, 0x04)) ++ goto error_exit; ++ ++ if (send_csme_multi_cmd(wc, cmd)) ++ goto error_exit; ++ ++ if (send_tdm_opt_cmd(wc, cmd)) ++ goto error_exit; ++ ++ free_cmd(cmd); ++ return 0; ++error_exit: ++ free_cmd(cmd); ++ return -1; ++} ++ ++static void wctc4xxp_setup_file_operations(struct file_operations *fops) ++{ ++ fops->owner = THIS_MODULE; ++ fops->read = wctc4xxp_read; ++ fops->write = wctc4xxp_write; ++} ++ ++static int ++initialize_channel_pvt(struct wcdte *wc, int encoder, ++ struct channel_pvt **cpvt) ++{ ++ int chan; ++ *cpvt = kmalloc(sizeof(struct channel_pvt) * wc->numchannels, ++ GFP_KERNEL); ++ if (!(*cpvt)) ++ return -ENOMEM; ++ for (chan = 0; chan < wc->numchannels; ++chan) ++ wctc4xxp_init_state((*cpvt) + chan, encoder, chan, wc); ++ return 0; ++} ++ ++static int ++initialize_transcoder(struct wcdte *wc, unsigned int srcfmts, ++ unsigned int dstfmts, struct channel_pvt *pvts, ++ struct dahdi_transcoder **zt) ++{ ++ int chan; ++ *zt = dahdi_transcoder_alloc(wc->numchannels); ++ if (!(*zt)) ++ return -ENOMEM; ++ (*zt)->srcfmts = srcfmts; ++ (*zt)->dstfmts = dstfmts; ++ (*zt)->allocate = wctc4xxp_operation_allocate; ++ (*zt)->release = wctc4xxp_operation_release; ++ wctc4xxp_setup_file_operations(&((*zt)->fops)); ++ for (chan = 0; chan < wc->numchannels; ++chan) ++ (*zt)->channels[chan].pvt = &pvts[chan]; ++ return 0; ++} ++ ++static int initialize_encoders(struct wcdte *wc, unsigned int complexfmts) ++{ ++ int res; ++ res = initialize_channel_pvt(wc, 1, &wc->encoders); ++ if (res) ++ return res; ++ ++ res = initialize_transcoder(wc, DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW, ++ complexfmts, wc->encoders, &wc->uencode); ++ if (res) ++ return res; ++ sprintf(wc->uencode->name, "DTE Encoder"); ++ return res; ++} ++ ++static int ++initialize_decoders(struct wcdte *wc, unsigned int complexfmts) ++{ ++ int res; ++ res = initialize_channel_pvt(wc, 0, &wc->decoders); ++ if (res) ++ return res; ++ ++ res = initialize_transcoder(wc, complexfmts, ++ DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW, ++ wc->decoders, &wc->udecode); ++ if (res) ++ return res; ++ ++ sprintf(wc->udecode->name, "DTE Decoder"); ++ return res; ++} ++ ++static void ++wctc4xxp_send_commands(struct wcdte *wc, struct list_head *to_send) ++{ ++ struct tcb *cmd; ++ while (!list_empty(to_send)) { ++ cmd = container_of(to_send->next, struct tcb, node); ++ list_del_init(&cmd->node); ++ wctc4xxp_transmit_cmd(wc, cmd); ++ } ++} ++ ++static void ++wctc4xxp_watchdog(TIMER_DATA_TYPE timer) ++{ ++ struct wcdte *wc = from_timer(wc, timer, watchdog); ++ struct tcb *cmd, *temp; ++ LIST_HEAD(cmds_to_retry); ++ const int MAX_RETRIES = 5; ++ int reschedule_timer = 0; ++ unsigned long flags; ++ ++ service_tx_ring(wc); ++ ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ /* Go through the list of messages that are waiting for responses from ++ * the DTE, and complete or retry any that have timed out. */ ++ list_for_each_entry_safe(cmd, temp, ++ &wc->waiting_for_response_list, node) { ++ ++ if (!time_after(jiffies, cmd->timeout)) ++ continue; ++ ++ if (++cmd->retries > MAX_RETRIES) { ++ if (!(cmd->flags & TX_COMPLETE)) { ++ ++ cmd->flags |= DTE_CMD_TIMEOUT; ++ list_del_init(&cmd->node); ++ if (cmd->complete) ++ complete(cmd->complete); ++ ++ wctc4xxp_reset_processor(wc); ++ set_bit(DTE_SHUTDOWN, &wc->flags); ++ spin_unlock_irqrestore(&wc->cmd_list_lock, ++ flags); ++ _wctc4xxp_stop_dma(wc); ++ dev_err(&wc->pdev->dev, ++ "Board malfunctioning. Halting operation.\n"); ++ reschedule_timer = 0; ++ spin_lock_irqsave(&wc->cmd_list_lock, flags); ++ break; ++ } ++ /* ERROR: We've retried the command and ++ * haven't received the ACK or the response. ++ */ ++ cmd->flags |= DTE_CMD_TIMEOUT; ++ list_del_init(&cmd->node); ++ if (cmd->complete) ++ complete(cmd->complete); ++ } else if (cmd->flags & TX_COMPLETE) { ++ /* Move this to the local list because we're ++ * going to resend it once we free the locks ++ */ ++ list_move_tail(&cmd->node, &cmds_to_retry); ++ cmd->flags &= ~(TX_COMPLETE); ++ } else { ++ /* The command is still sitting on the tx ++ * descriptor ring. We don't want to move it ++ * off any lists, lets just reset the timeout ++ * and tell the hardware to look for another ++ * command . */ ++ dev_warn(&wc->pdev->dev, ++ "Retrying command that was still on descriptor list.\n"); ++ cmd->timeout = jiffies + HZ/4; ++ wctc4xxp_transmit_demand_poll(wc); ++ reschedule_timer = 1; ++ } ++ } ++ spin_unlock_irqrestore(&wc->cmd_list_lock, flags); ++ ++ if (list_empty(&cmds_to_retry) && reschedule_timer) ++ mod_timer(&wc->watchdog, jiffies + HZ/2); ++ else if (!list_empty(&cmds_to_retry)) ++ wctc4xxp_send_commands(wc, &cmds_to_retry); ++} ++ ++/** ++ * Insert an struct wcdte on the global list in sorted order ++ * ++ */ ++static int __devinit ++wctc4xxp_add_to_device_list(struct wcdte *wc) ++{ ++ struct wcdte *cur; ++ int pos = 0; ++ INIT_LIST_HEAD(&wc->node); ++ spin_lock(&wctc4xxp_list_lock); ++ list_for_each_entry(cur, &wctc4xxp_list, node) { ++ if (cur->pos != pos) { ++ /* Add the new entry before the one here */ ++ list_add_tail(&wc->node, &cur->node); ++ break; ++ } else { ++ ++pos; ++ } ++ } ++ /* If we didn't already add the new entry to the list, add it now */ ++ if (list_empty(&wc->node)) ++ list_add_tail(&wc->node, &wctc4xxp_list); ++ spin_unlock(&wctc4xxp_list_lock); ++ return pos; ++} ++ ++static void wctc4xxp_remove_from_device_list(struct wcdte *wc) ++{ ++ spin_lock(&wctc4xxp_list_lock); ++ list_del(&wc->node); ++ spin_unlock(&wctc4xxp_list_lock); ++} ++ ++struct wctc4xxp_desc { ++ const char *short_name; ++ const char *long_name; ++}; ++ ++static struct wctc4xxp_desc wctc400p = { ++ .short_name = "tc400b", ++ .long_name = "Wildcard TC400P+TC400M", ++}; ++ ++static struct wctc4xxp_desc wctce400 = { ++ .short_name = "tce400", ++ .long_name = "Wildcard TCE400+TC400M", ++}; ++ ++static void wctc4xxp_cleanup_channels(struct wcdte *wc); ++ ++static int wctc4xxp_reset_and_reload_firmware(struct wcdte *wc, ++ const struct firmware *firmware) ++{ ++ int res; ++ ++ wctc4xxp_cleanup_command_list(wc); ++ wctc4xxp_cleanup_channels(wc); ++ ++ res = wctc4xxp_boot_processor(wc, firmware); ++ if (res) ++ return res; ++ ++#if defined(CONFIG_WCTC4XXP_POLLING) ++ wctc4xxp_enable_polling(wc); ++#endif ++ res = wctc4xxp_setup_device(wc); ++ if (res) { ++ dev_err(&wc->pdev->dev, "Failed to setup DTE\n"); ++ return res; ++ } ++ ++ return 0; ++} ++ ++static int wctc4xxp_reset_driver_state(struct wcdte *wc) ++{ ++ int res; ++ struct firmware embedded_firmware; ++ unsigned long flags; ++ const struct firmware *firmware = &embedded_firmware; ++#if !defined(HOTPLUG_FIRMWARE) ++ extern void _binary_dahdi_fw_tc400m_bin_size; ++ extern u8 _binary_dahdi_fw_tc400m_bin_start[]; ++ embedded_firmware.data = _binary_dahdi_fw_tc400m_bin_start; ++ embedded_firmware.size = (size_t) &_binary_dahdi_fw_tc400m_bin_size; ++#else ++ static const char tc400m_firmware[] = "dahdi-fw-tc400m.bin"; ++ ++ res = request_firmware(&firmware, tc400m_firmware, &wc->pdev->dev); ++ if (res || !firmware) { ++ dev_err(&wc->pdev->dev, ++ "Firmware %s not available from userspace. (%d)\n", ++ tc400m_firmware, res); ++ return res; ++ } ++#endif ++ res = wctc4xxp_reset_and_reload_firmware(wc, firmware); ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ spin_lock_irqsave(&wc->rxd->lock, flags); ++ wc->rxd->packet_errors = 0; ++ wc->reported_packet_errors = 0; ++ spin_unlock_irqrestore(&wc->rxd->lock, flags); ++ return res; ++} ++ ++#ifdef EXPORT_FOR_ALERT_ATTRIBUTE ++ ++static ssize_t wctc4xxp_force_alert_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int res; ++ unsigned int alert_type; ++ struct wcdte *wc = dev_get_drvdata(dev); ++ struct tcb *cmd = alloc_cmd(SFRAME_SIZE); ++ u16 parameters[] = {0}; ++ if (!cmd) ++ return -ENOMEM; ++ ++ res = sscanf(buf, "%x", &alert_type); ++ if (1 != res) { ++ free_cmd(cmd); ++ return -EINVAL; ++ } ++ ++ dev_info(&wc->pdev->dev, "Forcing alert type: 0x%x\n", alert_type); ++ res = mutex_lock_killable(&wc->chanlock); ++ if (res) { ++ free_cmd(cmd); ++ return -EAGAIN; ++ } ++ ++ parameters[0] = alert_type; ++ ++ create_supervisor_cmd(wc, cmd, CONFIG_CHANGE_TYPE, ++ CONFIG_DEVICE_CLASS, 0x0409, parameters, ++ ARRAY_SIZE(parameters)); ++ ++ wctc4xxp_transmit_cmd(wc, cmd); ++ ++ mutex_unlock(&wc->chanlock); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(force_alert, 0200, NULL, wctc4xxp_force_alert_store); ++ ++static void wctc4xxp_create_sysfs_files(struct wcdte *wc) ++{ ++ int ret; ++ ret = device_create_file(&wc->pdev->dev, &dev_attr_force_alert); ++ if (ret) { ++ dev_info(&wc->pdev->dev, ++ "Failed to create device attributes.\n"); ++ } ++} ++ ++static void wctc4xxp_remove_sysfs_files(struct wcdte *wc) ++{ ++ device_remove_file(&wc->pdev->dev, &dev_attr_force_alert); ++} ++ ++#else ++static inline void wctc4xxp_create_sysfs_files(struct wcdte *wc) { return; } ++static inline void wctc4xxp_remove_sysfs_files(struct wcdte *wc) { return; } ++#endif ++ ++static int __devinit ++wctc4xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ int res, reg, position_on_list; ++ struct wcdte *wc = NULL; ++ struct wctc4xxp_desc *d = (struct wctc4xxp_desc *)ent->driver_data; ++ unsigned char g729_numchannels, g723_numchannels, min_numchannels; ++ unsigned char wctc4xxp_firmware_ver, wctc4xxp_firmware_ver_minor; ++ unsigned int complexfmts; ++ struct firmware embedded_firmware; ++ const struct firmware *firmware = &embedded_firmware; ++#if !defined(HOTPLUG_FIRMWARE) ++ extern void _binary_dahdi_fw_tc400m_bin_size; ++ extern u8 _binary_dahdi_fw_tc400m_bin_start[]; ++#else ++ static const char tc400m_firmware[] = "dahdi-fw-tc400m.bin"; ++#endif ++ ++ /* ------------------------------------------------------------------ ++ * Setup the pure software constructs internal to this driver. ++ * --------------------------------------------------------------- */ ++ ++ wc = kzalloc(sizeof(*wc), GFP_KERNEL); ++ if (!wc) ++ return -ENOMEM; ++ ++ position_on_list = wctc4xxp_add_to_device_list(wc); ++ snprintf(wc->board_name, sizeof(wc->board_name)-1, "%s%d", ++ d->short_name, position_on_list); ++ wc->iobase = pci_iomap(pdev, 1, 0); ++ wc->pdev = pdev; ++ wc->pos = position_on_list; ++ wc->variety = d->long_name; ++ wc->last_rx_seq_num = -1; ++ ++ if (!request_mem_region(pci_resource_start(pdev, 1), ++ pci_resource_len(pdev, 1), wc->board_name)) { ++ dev_err(&pdev->dev, "IO Registers are in use by another " ++ "module.\n"); ++ wctc4xxp_remove_from_device_list(wc); ++ kfree(wc); ++ return -EIO; ++ } ++ ++ mutex_init(&wc->chanlock); ++ spin_lock_init(&wc->reglock); ++ spin_lock_init(&wc->cmd_list_lock); ++ spin_lock_init(&wc->rx_list_lock); ++ spin_lock_init(&wc->rx_lock); ++ INIT_LIST_HEAD(&wc->cmd_list); ++ INIT_LIST_HEAD(&wc->waiting_for_response_list); ++ INIT_LIST_HEAD(&wc->rx_list); ++ INIT_WORK(&wc->deferred_work, deferred_work_func); ++ init_waitqueue_head(&wc->waitq); ++ ++ if (pci_set_dma_mask(wc->pdev, DMA_BIT_MASK(32))) { ++ release_mem_region(pci_resource_start(wc->pdev, 1), ++ pci_resource_len(wc->pdev, 1)); ++ if (wc->iobase) ++ pci_iounmap(wc->pdev, wc->iobase); ++ pci_clear_mwi(wc->pdev); ++ dev_warn(&wc->pdev->dev, "No suitable DMA available.\n"); ++ return -EIO; ++ } ++ ++ wc->txd = kmalloc(sizeof(*wc->txd), GFP_KERNEL); ++ if (!wc->txd) { ++ res = -ENOMEM; ++ goto error_exit_swinit; ++ } ++ ++ res = wctc4xxp_initialize_descriptor_ring(wc->pdev, wc->txd, ++ 0xe0800000, DMA_TO_DEVICE, DEFAULT_TX_DRING_SIZE); ++ if (res) ++ goto error_exit_swinit; ++ ++ wc->rxd = kmalloc(sizeof(*wc->rxd), GFP_KERNEL); ++ if (!wc->rxd) { ++ res = -ENOMEM; ++ goto error_exit_swinit; ++ } ++ ++ res = wctc4xxp_initialize_descriptor_ring(wc->pdev, wc->rxd, 0, ++ DMA_FROM_DEVICE, DEFAULT_RX_DRING_SIZE); ++ if (res) ++ goto error_exit_swinit; ++ ++#if defined(HOTPLUG_FIRMWARE) ++ res = request_firmware(&firmware, tc400m_firmware, &wc->pdev->dev); ++ if (res || !firmware) { ++ dev_err(&wc->pdev->dev, ++ "Firmware %s not available from userspace. (%d)\n", ++ tc400m_firmware, res); ++ goto error_exit_swinit; ++ } ++#else ++ embedded_firmware.data = _binary_dahdi_fw_tc400m_bin_start; ++ embedded_firmware.size = (size_t) &_binary_dahdi_fw_tc400m_bin_size; ++#endif ++ ++ wctc4xxp_firmware_ver = firmware->data[0]; ++ wctc4xxp_firmware_ver_minor = firmware->data[16]; ++ g729_numchannels = firmware->data[1]; ++ g723_numchannels = firmware->data[2]; ++ ++ min_numchannels = min(g723_numchannels, g729_numchannels); ++ ++ if (!mode || strlen(mode) < 4) { ++ sprintf(wc->complexname, "G.729a / G.723.1"); ++ complexfmts = DAHDI_FORMAT_G729A | DAHDI_FORMAT_G723_1; ++ wc->numchannels = min_numchannels; ++ } else if (mode[3] == '9') { /* "G.729" */ ++ sprintf(wc->complexname, "G.729a"); ++ complexfmts = DAHDI_FORMAT_G729A; ++ wc->numchannels = g729_numchannels; ++ } else if (mode[3] == '3') { /* "G.723.1" */ ++ sprintf(wc->complexname, "G.723.1"); ++ complexfmts = DAHDI_FORMAT_G723_1; ++ wc->numchannels = g723_numchannels; ++ } else { ++ sprintf(wc->complexname, "G.729a / G.723.1"); ++ complexfmts = DAHDI_FORMAT_G729A | DAHDI_FORMAT_G723_1; ++ wc->numchannels = min_numchannels; ++ } ++ ++ res = initialize_encoders(wc, complexfmts); ++ if (res) ++ goto error_exit_swinit; ++ res = initialize_decoders(wc, complexfmts); ++ if (res) ++ goto error_exit_swinit; ++ ++ if (DTE_DEBUG_NETWORK_IF & debug) { ++ res = wctc4xxp_net_register(wc); ++ if (res) ++ goto error_exit_swinit; ++ } ++ ++ timer_setup(&wc->watchdog, wctc4xxp_watchdog, 0); ++ ++ /* ------------------------------------------------------------------ ++ * Load the firmware and start the DTE. ++ * --------------------------------------------------------------- */ ++ ++ res = pci_enable_device(pdev); ++ if (res) { ++ dev_err(&wc->pdev->dev, "Failed to enable device.\n"); ++ goto error_exit_swinit;; ++ } ++ res = pci_set_mwi(wc->pdev); ++ if (res) { ++ dev_warn(&wc->pdev->dev, ++ "Failed to set Memory-Write Invalidate Command Bit..\n"); ++ } ++ pci_set_master(pdev); ++ pci_set_drvdata(pdev, wc); ++ res = request_irq(pdev->irq, wctc4xxp_interrupt, ++ IRQF_SHARED, wc->board_name, wc); ++ if (res) { ++ dev_err(&wc->pdev->dev, ++ "Unable to request IRQ %d\n", pdev->irq); ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ goto error_exit_hwinit; ++ } ++ res = wctc4xxp_hardware_init(wc); ++ if (res) { ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ goto error_exit_hwinit; ++ } ++ wctc4xxp_enable_interrupts(wc); ++ wctc4xxp_start_dma(wc); ++ ++ res = wctc4xxp_reset_and_reload_firmware(wc, firmware); ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ if (res) ++ goto error_exit_hwinit; ++ ++ /* \todo Read firmware version directly from tc400b.*/ ++ dev_info(&wc->pdev->dev, "(%s) Transcoder support LOADED " \ ++ "(firm ver = %d.%d)\n", wc->complexname, wctc4xxp_firmware_ver, ++ wctc4xxp_firmware_ver_minor); ++ ++ reg = wctc4xxp_getctl(wc, 0x00fc); ++ ++ DTE_DEBUG(DTE_DEBUG_GENERAL, ++ "debug: (post-boot) Reg fc is %08x\n", reg); ++ ++ dev_info(&wc->pdev->dev, "Installed a Wildcard TC: %s\n", wc->variety); ++ DTE_DEBUG(DTE_DEBUG_GENERAL, "Operating in DEBUG mode.\n"); ++ dahdi_transcoder_register(wc->uencode); ++ dahdi_transcoder_register(wc->udecode); ++ ++ wctc4xxp_match_packet_counts(wc); ++ ++ wctc4xxp_create_sysfs_files(wc); ++ ++ return 0; ++ ++error_exit_hwinit: ++#if defined(CONFIG_WCTC4XXP_POLLING) ++ wctc4xxp_disable_polling(wc); ++#endif ++ wctc4xxp_stop_dma(wc); ++ wctc4xxp_cleanup_command_list(wc); ++ free_irq(pdev->irq, wc); ++ pci_set_drvdata(pdev, NULL); ++error_exit_swinit: ++ wctc4xxp_net_unregister(wc); ++ kfree(wc->encoders); ++ kfree(wc->decoders); ++ dahdi_transcoder_free(wc->uencode); ++ dahdi_transcoder_free(wc->udecode); ++ wctc4xxp_cleanup_descriptor_ring(wc->txd); ++ kfree(wc->txd); ++ wctc4xxp_cleanup_descriptor_ring(wc->rxd); ++ kfree(wc->rxd); ++ release_mem_region(pci_resource_start(wc->pdev, 1), ++ pci_resource_len(wc->pdev, 1)); ++ if (wc->iobase) ++ pci_iounmap(wc->pdev, wc->iobase); ++ pci_clear_mwi(wc->pdev); ++ wctc4xxp_remove_from_device_list(wc); ++ kfree(wc); ++ return res; ++} ++ ++static void wctc4xxp_cleanup_channels(struct wcdte *wc) ++{ ++ int i; ++ struct dahdi_transcoder_channel *dtc_en, *dtc_de; ++ struct channel_pvt *cpvt; ++ ++ for (i = 0; i < wc->numchannels; ++i) { ++ dtc_en = &(wc->uencode->channels[i]); ++ wctc4xxp_cleanup_channel_private(wc, dtc_en); ++ dahdi_tc_clear_busy(dtc_en); ++ dahdi_tc_clear_built(dtc_en); ++ ++ dtc_en->built_fmts = 0; ++ cpvt = dtc_en->pvt; ++ cpvt->chan_in_num = INVALID; ++ cpvt->chan_out_num = INVALID; ++ ++ ++ dtc_de = &(wc->udecode->channels[i]); ++ wctc4xxp_cleanup_channel_private(wc, dtc_de); ++ dahdi_tc_clear_busy(dtc_de); ++ dahdi_tc_clear_built(dtc_de); ++ ++ dtc_de->built_fmts = 0; ++ cpvt = dtc_de->pvt; ++ cpvt->chan_in_num = INVALID; ++ cpvt->chan_out_num = INVALID; ++ } ++} ++ ++static void __devexit wctc4xxp_remove_one(struct pci_dev *pdev) ++{ ++ struct wcdte *wc = pci_get_drvdata(pdev); ++ ++ if (!wc) ++ return; ++ ++ wctc4xxp_remove_sysfs_files(wc); ++ ++ wctc4xxp_remove_from_device_list(wc); ++ ++ set_bit(DTE_SHUTDOWN, &wc->flags); ++ if (del_timer_sync(&wc->watchdog)) ++ del_timer_sync(&wc->watchdog); ++ ++ /* This should already be stopped, but it doesn't hurt to make sure. */ ++ clear_bit(DTE_POLLING, &wc->flags); ++ wctc4xxp_net_unregister(wc); ++ ++ /* Stop any DMA */ ++ wctc4xxp_stop_dma(wc); ++ ++ /* In case hardware is still there */ ++ wctc4xxp_disable_interrupts(wc); ++ ++ free_irq(pdev->irq, wc); ++ ++ /* There isn't anything that would run in the workqueue that will wait ++ * on an interrupt. */ ++ ++ dahdi_transcoder_unregister(wc->udecode); ++ dahdi_transcoder_unregister(wc->uencode); ++ ++ /* Free Resources */ ++ release_mem_region(pci_resource_start(wc->pdev, 1), ++ pci_resource_len(wc->pdev, 1)); ++ if (wc->iobase) ++ pci_iounmap(wc->pdev, wc->iobase); ++ pci_clear_mwi(wc->pdev); ++ wctc4xxp_cleanup_descriptor_ring(wc->txd); ++ kfree(wc->txd); ++ wctc4xxp_cleanup_descriptor_ring(wc->rxd); ++ kfree(wc->rxd); ++ ++ wctc4xxp_cleanup_command_list(wc); ++ wctc4xxp_cleanup_channels(wc); ++ ++ pci_set_drvdata(pdev, NULL); ++ ++ dahdi_transcoder_free(wc->uencode); ++ dahdi_transcoder_free(wc->udecode); ++ kfree(wc->encoders); ++ kfree(wc->decoders); ++ kfree(wc); ++} ++ ++static DEFINE_PCI_DEVICE_TABLE(wctc4xxp_pci_tbl) = { ++ { 0xd161, 0x3400, PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, (unsigned long) &wctc400p }, /* Digium board */ ++ { 0xd161, 0x8004, PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, (unsigned long) &wctce400 }, /* Digium board */ ++ { 0 } ++}; ++ ++MODULE_DEVICE_TABLE(pci, wctc4xxp_pci_tbl); ++ ++static int wctc4xxp_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ return -ENOSYS; ++} ++ ++static struct pci_driver wctc4xxp_driver = { ++ .name = "wctc4xxp", ++ .probe = wctc4xxp_init_one, ++ .remove = __devexit_p(wctc4xxp_remove_one), ++ .id_table = wctc4xxp_pci_tbl, ++ .suspend = wctc4xxp_suspend, ++}; ++ ++static int __init wctc4xxp_init(void) ++{ ++ int res; ++ unsigned long cache_flags; ++ ++ cache_flags = SLAB_HWCACHE_ALIGN; ++ ++ cmd_cache = kmem_cache_create(THIS_MODULE->name, sizeof(struct tcb), ++ 0, cache_flags, NULL); ++ if (!cmd_cache) ++ return -ENOMEM; ++ spin_lock_init(&wctc4xxp_list_lock); ++ INIT_LIST_HEAD(&wctc4xxp_list); ++ res = pci_register_driver(&wctc4xxp_driver); ++ if (res) { ++ kmem_cache_destroy(cmd_cache); ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++static void __exit wctc4xxp_cleanup(void) ++{ ++ pci_unregister_driver(&wctc4xxp_driver); ++ kmem_cache_destroy(cmd_cache); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++module_param(mode, charp, S_IRUGO); ++MODULE_PARM_DESC(mode, "'g729', 'g723.1', or 'any'. Default 'any'."); ++MODULE_DESCRIPTION("Wildcard TC400P+TC400M Driver"); ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_LICENSE("GPL"); ++ ++module_init(wctc4xxp_init); ++module_exit(wctc4xxp_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/wctdm24xxp/Kbuild linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/Kbuild +--- linux-source-4.19/drivers/dahdi/wctdm24xxp/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/Kbuild 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,5 @@ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp.o ++ ++EXTRA_CFLAGS += -I$(src)/.. -Wno-undef ++ ++wctdm24xxp-objs := base.o xhfc.o +diff -Nru linux-source-4.19/drivers/dahdi/wctdm24xxp/base.c linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/base.c +--- linux-source-4.19/drivers/dahdi/wctdm24xxp/base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/base.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,6206 @@ ++/* ++ * Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface ++ * ++ * Written by Mark Spencer ++ * Support for TDM800P and VPM150M by Matthew Fredrickson ++ * ++ * Support for Hx8 by Andrew Kohlsmith and Matthew ++ * Fredrickson ++ * ++ * Copyright (C) 2005 - 2012 Digium, Inc. ++ * All rights reserved. ++ * ++ * Sections for QRV cards written by Jim Dixon ++ * Copyright (C) 2006, Jim Dixon and QRV Communications ++ * 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. ++ */ ++ ++/* For QRV DRI cards, gain is signed short, expressed in hundredths of ++db (in reference to 1v Peak @ 1000Hz) , as follows: ++ ++Rx Gain: -11.99 to 15.52 db ++Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db ++Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) ++/* Define this if you would like to load the modules in parallel. While this ++ * can speed up loads when multiple cards handled by this driver are installed, ++ * it also makes it impossible to abort module loads with ctrl-c */ ++#undef USE_ASYNC_INIT ++#include ++#else ++#undef USE_ASYNC_INIT ++#endif ++ ++#include ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#include ++#endif /* 4.11.0 */ ++ ++#include "proslic.h" ++ ++#include "wctdm24xxp.h" ++#include "xhfc.h" ++ ++#include "adt_lec.h" ++ ++#include "voicebus/GpakCust.h" ++#include "voicebus/GpakApi.h" ++ ++#if VOICEBUS_SFRAME_SIZE != SFRAME_SIZE ++#error SFRAME_SIZE must match the VOICEBUS_SFRAME_SIZE ++#endif ++ ++/* ++ Experimental max loop current limit for the proslic ++ Loop current limit is from 20 mA to 41 mA in steps of 3 ++ (according to datasheet) ++ So set the value below to: ++ 0x00 : 20mA (default) ++ 0x01 : 23mA ++ 0x02 : 26mA ++ 0x03 : 29mA ++ 0x04 : 32mA ++ 0x05 : 35mA ++ 0x06 : 37mA ++ 0x07 : 41mA ++*/ ++static int loopcurrent = 20; ++ ++/* Following define is a logical exclusive OR to determine if the polarity of an fxs line is to be reversed. ++ * The items taken into account are: ++ * overall polarity reversal for the module, ++ * polarity reversal for the port, ++ * and the state of the line reversal MWI indicator ++ */ ++#define POLARITY_XOR(fxs) \ ++ ((reversepolarity != 0) ^ ((fxs)->reversepolarity != 0) ^ \ ++ ((fxs)->vmwi_linereverse != 0)) ++ ++static int reversepolarity = 0; ++ ++static alpha indirect_regs[] = ++{ ++{0,255,"DTMF_ROW_0_PEAK",0x55C2}, ++{1,255,"DTMF_ROW_1_PEAK",0x51E6}, ++{2,255,"DTMF_ROW2_PEAK",0x4B85}, ++{3,255,"DTMF_ROW3_PEAK",0x4937}, ++{4,255,"DTMF_COL1_PEAK",0x3333}, ++{5,255,"DTMF_FWD_TWIST",0x0202}, ++{6,255,"DTMF_RVS_TWIST",0x0202}, ++{7,255,"DTMF_ROW_RATIO_TRES",0x0198}, ++{8,255,"DTMF_COL_RATIO_TRES",0x0198}, ++{9,255,"DTMF_ROW_2ND_ARM",0x0611}, ++{10,255,"DTMF_COL_2ND_ARM",0x0202}, ++{11,255,"DTMF_PWR_MIN_TRES",0x00E5}, ++{12,255,"DTMF_OT_LIM_TRES",0x0A1C}, ++{13,0,"OSC1_COEF",0x7B30}, ++{14,1,"OSC1X",0x0063}, ++{15,2,"OSC1Y",0x0000}, ++{16,3,"OSC2_COEF",0x7870}, ++{17,4,"OSC2X",0x007D}, ++{18,5,"OSC2Y",0x0000}, ++{19,6,"RING_V_OFF",0x0000}, ++{20,7,"RING_OSC",0x7EF0}, ++{21,8,"RING_X",0x0160}, ++{22,9,"RING_Y",0x0000}, ++{23,255,"PULSE_ENVEL",0x2000}, ++{24,255,"PULSE_X",0x2000}, ++{25,255,"PULSE_Y",0x0000}, ++//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower ++{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower ++{27,14,"XMIT_DIGITAL_GAIN",0x4000}, ++//{27,14,"XMIT_DIGITAL_GAIN",0x2000}, ++{28,15,"LOOP_CLOSE_TRES",0x1000}, ++{29,16,"RING_TRIP_TRES",0x3600}, ++{30,17,"COMMON_MIN_TRES",0x1000}, ++{31,18,"COMMON_MAX_TRES",0x0200}, ++{32,19,"PWR_ALARM_Q1Q2",0x07C0}, ++{33,20,"PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */}, ++{34,21,"PWR_ALARM_Q5Q6",0x1B80}, ++{35,22,"LOOP_CLOSURE_FILTER",0x8000}, ++{36,23,"RING_TRIP_FILTER",0x0320}, ++{37,24,"TERM_LP_POLE_Q1Q2",0x008C}, ++{38,25,"TERM_LP_POLE_Q3Q4",0x0100}, ++{39,26,"TERM_LP_POLE_Q5Q6",0x0010}, ++{40,27,"CM_BIAS_RINGING",0x0C00}, ++{41,64,"DCDC_MIN_V",0x0C00}, ++{42,255,"DCDC_XTRA",0x1000}, ++{43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, ++}; ++ ++/* names of HWEC modules */ ++static const char *vpmadt032_name = "VPMADT032"; ++static const char *vpmoct_name = "VPMOCT032"; ++ ++/* Undefine to enable Power alarm / Transistor debug -- note: do not ++ enable for normal operation! */ ++/* #define PAQ_DEBUG */ ++ ++#define DEBUG_CARD (1 << 0) ++#define DEBUG_ECHOCAN (1 << 1) ++ ++#include "fxo_modes.h" ++ ++struct wctdm_desc { ++ const char *name; ++ const int flags; ++ const int ports; ++}; ++ ++static const struct wctdm_desc wctdm2400 = { "Wildcard TDM2400P", 0, 24 }; ++static const struct wctdm_desc wctdm800 = { "Wildcard TDM800P", 0, 8 }; ++static const struct wctdm_desc wctdm410 = { "Wildcard TDM410P", 0, 4 }; ++static const struct wctdm_desc wcaex2400 = { "Wildcard AEX2400", FLAG_EXPRESS, 24 }; ++static const struct wctdm_desc wcaex800 = { "Wildcard AEX800", FLAG_EXPRESS, 8 }; ++static const struct wctdm_desc wcaex410 = { "Wildcard AEX410", FLAG_EXPRESS, 4 }; ++static const struct wctdm_desc wcha80000 = { "HA8-0000", 0, 8 }; ++static const struct wctdm_desc wchb80000 = { "HB8-0000", FLAG_EXPRESS, 8 }; ++ ++static inline bool is_pcie(const struct wctdm *wc) ++{ ++ return (wc->desc->flags & FLAG_EXPRESS) > 0; ++} ++ ++/** ++ * Returns true if the card is one of the Hybrid Digital Analog Cards. ++ */ ++static inline bool is_hx8(const struct wctdm *wc) ++{ ++ return (&wcha80000 == wc->desc) || (&wchb80000 == wc->desc); ++} ++ ++static inline struct dahdi_chan * ++get_dahdi_chan(const struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ return wc->aspan->span.chans[mod->card]; ++} ++ ++static inline void ++mod_hooksig(struct wctdm *wc, struct wctdm_module *mod, enum dahdi_rxsig rxsig) ++{ ++ dahdi_hooksig(get_dahdi_chan(wc, mod), rxsig); ++} ++ ++struct wctdm *ifaces[WC_MAX_IFACES]; ++DEFINE_SEMAPHORE(ifacelock); ++ ++static void wctdm_release(struct wctdm *wc); ++ ++static int fxovoltage = 0; ++static unsigned int battdebounce; ++static unsigned int battalarm; ++static unsigned int battthresh; ++static int debug = 0; ++#ifdef DEBUG ++static int robust = 0; ++static int digitalloopback; ++#endif ++static int lowpower = 0; ++static int boostringer = 0; ++static int fastringer = 0; ++static int _opermode = 0; ++static char *opermode = "FCC"; ++static int fxshonormode = 0; ++static int alawoverride = 0; ++static char *companding = "auto"; ++static int fastpickup = -1; /* -1 auto, 0 no, 1 yes */ ++static int fxotxgain = 0; ++static int fxorxgain = 0; ++static int fxstxgain = 0; ++static int fxsrxgain = 0; ++static int nativebridge = 0; ++static int ringdebounce = DEFAULT_RING_DEBOUNCE; ++static int latency = VOICEBUS_DEFAULT_LATENCY; ++static unsigned int max_latency = VOICEBUS_DEFAULT_MAXLATENCY; ++static int forceload; ++ ++#define MS_PER_HOOKCHECK (1) ++#define NEONMWI_ON_DEBOUNCE (100/MS_PER_HOOKCHECK) ++static int neonmwi_monitor = 0; /* Note: this causes use of full wave ring detect */ ++static int neonmwi_level = 75; /* neon mwi trip voltage */ ++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 */ ++ ++static int vpmsupport = 1; ++ ++static int vpmnlptype = DEFAULT_NLPTYPE; ++static int vpmnlpthresh = DEFAULT_NLPTHRESH; ++static int vpmnlpmaxsupp = DEFAULT_NLPMAXSUPP; ++ ++static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++ ++static const struct dahdi_echocan_features vpm_ec_features = { ++ .NLP_automatic = 1, ++ .CED_tx_detect = 1, ++ .CED_rx_detect = 1, ++}; ++ ++static const struct dahdi_echocan_ops vpm_ec_ops = { ++ .echocan_free = echocan_free, ++}; ++ ++static int ++wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod, int fast, ++ int manual, int sane); ++ ++static void set_offsets(struct wctdm_module *const mod, int altcs) ++{ ++ int card = mod->card; ++ int bit; ++ ++ mod->subaddr = (altcs) ? 0 : (mod->card & 0x3); ++ ++ for (bit = 0; bit < ARRAY_SIZE(mod->offsets); ++bit) { ++ /* Let's add some trickery to make the TDM410 work */ ++ if (altcs == 3) { ++ if (card == 2) { ++ card = 4; ++ altcs = 0; ++ } else if (card == 3) { ++ card = 5; ++ altcs = 2; ++ } ++ } ++ mod->offsets[bit] = ((((card & 0x3) * 3 + bit) * 7) + ++ (card >> 2) + altcs + ++ ((altcs) ? -21 : 0)); ++ } ++} ++ ++static inline __attribute_const__ int ++CMD_BYTE(const struct wctdm_module *const mod, const int bit) ++{ ++ return mod->offsets[bit]; ++} ++ ++static inline __attribute_const__ int VPM_CMD_BYTE(int timeslot, int bit) ++{ ++ return ((((timeslot) & 0x3) * 3 + (bit)) * 7) + ((timeslot) >> 2); ++} ++ ++typedef int (*bg_work_func_t)(struct wctdm *wc, unsigned long data); ++ ++struct bg { ++ struct workqueue_struct *wq; ++ struct work_struct work; ++ struct completion complete; ++ struct wctdm *wc; ++ bg_work_func_t fn; ++ unsigned long param; ++ int ret; ++}; ++ ++static void bg_work_func(struct work_struct *work) ++{ ++ struct bg *bg = container_of(work, struct bg, work); ++ bg->ret = bg->fn(bg->wc, bg->param); ++ complete(&bg->complete); ++} ++ ++/** ++ * bg_create - Call a function running in a background thread. ++ * @wc: The board structure passed to fn ++ * @fn: The function to run in it's own thread. ++ * @parma: An extra parameter to pass to the fn. ++ * ++ * Returns NULL if the thread could not be created, otherwise a pointer to be ++ * passed to bg_join in order to get the return value. ++ * ++ * The function 'fn' will be run in a new thread. The return value is the ++ * return from the bg_join function. ++ * ++ * This would probably be best served by concurrency managed workqueues before ++ * merging, but this will at least work on the older kernels tht DAHDI ++ * supports. ++ */ ++static struct bg * ++bg_create(struct wctdm *wc, bg_work_func_t fn, unsigned long param) ++{ ++ struct bg *bg; ++ ++ bg = kzalloc(sizeof(*bg), GFP_KERNEL); ++ if (!bg) ++ return NULL; ++ ++ bg->wq = create_singlethread_workqueue("wctdm_bg"); ++ if (!bg->wq) { ++ kfree(bg); ++ return NULL; ++ } ++ ++ init_completion(&bg->complete); ++ INIT_WORK(&bg->work, bg_work_func); ++ ++ bg->wc = wc; ++ bg->fn = fn; ++ bg->param = param; ++ ++ queue_work(bg->wq, &bg->work); ++ ++ return bg; ++} ++ ++/** ++ * bg_join - Wait for a background function to complete and get the result. ++ * @bg: Pointer returned from the bg_create call. ++ * ++ * Returns the result of the function passed to bg_create. ++ */ ++static int bg_join(struct bg *bg) ++{ ++ int ret = -ERESTARTSYS; ++ ++ if (unlikely(!bg)) ++ return -EINVAL; ++ ++ while (ret) ++ ret = wait_for_completion_interruptible(&bg->complete); ++ ++ ret = bg->ret; ++ destroy_workqueue(bg->wq); ++ kfree(bg); ++ ++ return ret; ++} ++ ++static void ++setchanconfig_from_state(struct vpmadt032 *vpm, int channel, ++ GpakChannelConfig_t *chanconfig) ++{ ++ GpakEcanParms_t *p; ++ ++ BUG_ON(!vpm); ++ ++ 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; ++ ++ /* The software companding will be overridden on a channel by channel ++ * basis when the channel is enabled. */ ++ chanconfig->SoftwareCompand = cmpPCMU; ++ ++ chanconfig->FrameRate = rate2ms; ++ p = &chanconfig->EcanParametersA; ++ ++ vpmadt032_get_default_parameters(p); ++ ++ p->EcanNlpType = vpm->curecstate[channel].nlp_type; ++ p->EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold; ++ p->EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress; ++ ++ memcpy(&chanconfig->EcanParametersB, ++ &chanconfig->EcanParametersA, ++ sizeof(chanconfig->EcanParametersB)); ++} ++ ++struct vpmadt032_channel_setup { ++ struct work_struct work; ++ struct wctdm *wc; ++}; ++ ++static void vpm_setup_work_func(struct work_struct *work) ++{ ++ struct vpmadt032_channel_setup *setup = ++ container_of(work, struct vpmadt032_channel_setup, work); ++ int i; ++ int res; ++ GpakChannelConfig_t chanconfig; ++ GPAK_ChannelConfigStat_t cstatus; ++ GPAK_AlgControlStat_t algstatus; ++ GpakPortConfig_t portconfig = {0}; ++ gpakConfigPortStatus_t configportstatus; ++ GPAK_PortConfigStat_t pstatus; ++ struct vpmadt032 *vpm; ++ struct wctdm *const wc = setup->wc; ++ ++ WARN_ON(!wc); ++ WARN_ON(!wc->vpmadt032); ++ if (unlikely(!wc || !wc->vpmadt032)) ++ return; ++ vpm = wc->vpmadt032; ++ ++ /* 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))) { ++ dev_notice(&wc->vb.pdev->dev, "Configuration of ports failed (%d)!\n", configportstatus); ++ return; ++ } else { ++ if (vpm->options.debug & DEBUG_ECHOCAN) ++ dev_info(&wc->vb.pdev->dev, "Configured McBSP ports successfully\n"); ++ } ++ ++ res = gpakPingDsp(vpm->dspid, &vpm->version); ++ if (res) { ++ dev_notice(&wc->vb.pdev->dev, "Error pinging DSP (%d)\n", res); ++ return; ++ } ++ ++ for (i = 0; i < vpm->options.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; ++ vpm->curecstate[i].companding = ADT_COMP_ULAW; ++ vpm->setchanconfig_from_state(vpm, i, &chanconfig); ++ ++ res = gpakConfigureChannel(vpm->dspid, i, tdmToTdm, ++ &chanconfig, &cstatus); ++ if (res) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Unable to configure channel #%d (%d)", ++ i, res); ++ if (res == 1) ++ printk(KERN_CONT ", reason %d", cstatus); ++ printk(KERN_CONT "\n"); ++ goto exit; ++ } ++ ++ res = gpakAlgControl(vpm->dspid, i, BypassEcanA, &algstatus); ++ if (res) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Unable to disable echo can on channel %d " ++ "(reason %d:%d)\n", i + 1, res, algstatus); ++ goto exit; ++ } ++ ++ res = gpakAlgControl(vpm->dspid, i, ++ BypassSwCompanding, &algstatus); ++ if (res) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Unable to disable echo can on channel %d " ++ "(reason %d:%d)\n", i + 1, res, algstatus); ++ goto exit; ++ } ++ } ++ ++ res = gpakPingDsp(vpm->dspid, &vpm->version); ++ if (res) { ++ dev_notice(&wc->vb.pdev->dev, "Error pinging DSP (%d)\n", res); ++ goto exit; ++ } ++ ++ set_bit(VPM150M_ACTIVE, &vpm->control); ++ ++exit: ++ kfree(setup); ++} ++ ++static int config_vpmadt032(struct vpmadt032 *vpm, struct wctdm *wc) ++{ ++ struct vpmadt032_channel_setup *setup; ++ ++ /* Because the channel configuration can take such a long time, let's ++ * move this out onto the VPM workqueue so the system can proceeded ++ * with startup. */ ++ ++ setup = kzalloc(sizeof(*setup), GFP_KERNEL); ++ if (!setup) ++ return -ENOMEM; ++ ++ setup->wc = wc; ++ INIT_WORK(&setup->work, vpm_setup_work_func); ++ queue_work(vpm->wq, &setup->work); ++ ++ return 0; ++} ++ ++/** ++ * is_good_frame() - Whether the SFRAME received was one sent. ++ * ++ */ ++static inline bool is_good_frame(const u8 *sframe) ++{ ++ const u8 a = sframe[0*(EFRAME_SIZE+EFRAME_GAP) + (EFRAME_SIZE+1)]; ++ const u8 b = sframe[1*(EFRAME_SIZE+EFRAME_GAP) + (EFRAME_SIZE+1)]; ++ return a != b; ++} ++ ++static inline void cmd_dequeue_vpmoct(struct wctdm *wc, u8 *eframe) ++{ ++ struct vpmoct *vpm = wc->vpmoct; ++ struct vpmoct_cmd *cmd; ++ u8 i; ++ ++ /* Pop a command off pending list */ ++ spin_lock(&vpm->list_lock); ++ if (list_empty(&vpm->pending_list)) { ++ spin_unlock(&vpm->list_lock); ++ return; ++ } ++ ++ cmd = list_entry(vpm->pending_list.next, struct vpmoct_cmd, node); ++ if (is_vpmoct_cmd_read(cmd)) ++ list_move_tail(&cmd->node, &vpm->active_list); ++ else ++ list_del_init(&cmd->node); ++ ++ /* Skip audio (24 bytes) and ignore first 6 timeslots */ ++ eframe += 30; ++ ++ /* Save ident so we can match the return eframe */ ++ cmd->txident = wc->txident; ++ ++ /* We have four timeslots to work with for a regular spi packet */ ++ /* TODO: Create debug flag for this in dev */ ++ ++ /* The vpmoct requires a "sync" spi command as the first three bytes ++ * of an eframe */ ++ eframe[7*0] = 0x12; ++ eframe[7*1] = 0x34; ++ eframe[7*2] = 0x56; ++ eframe[7*3] = cmd->command; ++ eframe[7*4] = cmd->address; ++ eframe[7*5] = cmd->data[0]; ++ for (i = 1; i < cmd->chunksize; i++) ++ eframe[(7*5)+7*i] = cmd->data[i]; ++ ++ /* Clean up fire-and-forget messages from memory */ ++ if (list_empty(&cmd->node)) ++ kfree(cmd); ++ ++ spin_unlock(&vpm->list_lock); ++} ++ ++static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe) ++{ ++ struct vpmadt032_cmd *curcmd = NULL; ++ struct vpmadt032 *vpmadt032 = wc->vpmadt032; ++ int x; ++ unsigned char leds = ~((wc->framecount / 1000) % 8) & 0x7; ++ ++ /* Skip audio */ ++ eframe += 24; ++ ++ if (test_bit(VPM150M_HPIRESET, &vpmadt032->control)) { ++ if (debug & DEBUG_ECHOCAN) ++ dev_info(&wc->vb.pdev->dev, "HW Resetting VPMADT032...\n"); ++ for (x = 24; x < 28; x++) { ++ if (x == 24) { ++ if (test_and_clear_bit(VPM150M_HPIRESET, ++ &vpmadt032->control)) { ++ eframe[VPM_CMD_BYTE(x, 0)] = 0x0b; ++ } else { ++ eframe[VPM_CMD_BYTE(x, 0)] = leds; ++ } ++ } else { ++ eframe[VPM_CMD_BYTE(x, 0)] = leds; ++ } ++ eframe[VPM_CMD_BYTE(x, 1)] = 0; ++ eframe[VPM_CMD_BYTE(x, 2)] = 0x00; ++ } ++ return; ++ } ++ ++ if ((curcmd = vpmadt032_get_ready_cmd(vpmadt032))) { ++ curcmd->txident = wc->txident; ++#if 0 ++ // if (printk_ratelimit()) ++ dev_info(&wc->vb.pdev->dev, "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*/ ++ eframe[VPM_CMD_BYTE(24, 0)] = (0x8 << 4); ++ eframe[VPM_CMD_BYTE(24, 1)] = 0; ++ eframe[VPM_CMD_BYTE(24, 2)] = 0x20; ++ ++ /* Do a page write */ ++ if (curcmd->desc & __VPM150M_WR) ++ eframe[VPM_CMD_BYTE(25, 0)] = ((0x8 | 0x4) << 4); ++ else ++ eframe[VPM_CMD_BYTE(25, 0)] = ((0x8 | 0x4 | 0x1) << 4); ++ eframe[VPM_CMD_BYTE(25, 1)] = 0; ++ if (curcmd->desc & __VPM150M_WR) ++ eframe[VPM_CMD_BYTE(25, 2)] = curcmd->data & 0xf; ++ else ++ eframe[VPM_CMD_BYTE(25, 2)] = 0; ++ ++ /* Clear XADD */ ++ eframe[VPM_CMD_BYTE(26, 0)] = (0x8 << 4); ++ eframe[VPM_CMD_BYTE(26, 1)] = 0; ++ eframe[VPM_CMD_BYTE(26, 2)] = 0; ++ ++ /* Fill in to buffer to size */ ++ eframe[VPM_CMD_BYTE(27, 0)] = 0; ++ eframe[VPM_CMD_BYTE(27, 1)] = 0; ++ eframe[VPM_CMD_BYTE(27, 2)] = 0; ++ ++ } else { ++ /* Set address */ ++ eframe[VPM_CMD_BYTE(24, 0)] = ((0x8 | 0x4) << 4); ++ eframe[VPM_CMD_BYTE(24, 1)] = (curcmd->address >> 8) & 0xff; ++ eframe[VPM_CMD_BYTE(24, 2)] = curcmd->address & 0xff; ++ ++ /* Send/Get our data */ ++ eframe[VPM_CMD_BYTE(25, 0)] = (curcmd->desc & __VPM150M_WR) ? ++ ((0x8 | (0x3 << 1)) << 4) : ((0x8 | (0x3 << 1) | 0x1) << 4); ++ eframe[VPM_CMD_BYTE(25, 1)] = (curcmd->data >> 8) & 0xff; ++ eframe[VPM_CMD_BYTE(25, 2)] = curcmd->data & 0xff; ++ ++ eframe[VPM_CMD_BYTE(26, 0)] = 0; ++ eframe[VPM_CMD_BYTE(26, 1)] = 0; ++ eframe[VPM_CMD_BYTE(26, 2)] = 0; ++ ++ /* Fill in the rest */ ++ eframe[VPM_CMD_BYTE(27, 0)] = 0; ++ eframe[VPM_CMD_BYTE(27, 1)] = 0; ++ eframe[VPM_CMD_BYTE(27, 2)] = 0; ++ } ++ } else if (test_and_clear_bit(VPM150M_SWRESET, &vpmadt032->control)) { ++ for (x = 24; x < 28; x++) { ++ if (x == 24) ++ eframe[VPM_CMD_BYTE(x, 0)] = (0x8 << 4); ++ else ++ eframe[VPM_CMD_BYTE(x, 0)] = 0x00; ++ eframe[VPM_CMD_BYTE(x, 1)] = 0; ++ if (x == 24) ++ eframe[VPM_CMD_BYTE(x, 2)] = 0x01; ++ else ++ eframe[VPM_CMD_BYTE(x, 2)] = 0x00; ++ } ++ } else { ++ for (x = 24; x < 28; x++) { ++ eframe[VPM_CMD_BYTE(x, 0)] = 0x00; ++ eframe[VPM_CMD_BYTE(x, 1)] = 0x00; ++ eframe[VPM_CMD_BYTE(x, 2)] = 0x00; ++ } ++ } ++ ++ /* Add our leds in */ ++ for (x = 24; x < 28; x++) { ++ eframe[VPM_CMD_BYTE(x, 0)] |= leds; ++ } ++} ++ ++/* Call with wc->reglock held and local interrupts disabled */ ++static void _cmd_dequeue(struct wctdm *wc, u8 *eframe, int card, int pos) ++{ ++ struct wctdm_module *const mod = &wc->mods[card]; ++ unsigned int curcmd=0; ++ ++ /* QRV only use commands relating to the first channel */ ++ if ((card & 0x03) && (mod->type == QRV)) ++ return; ++ ++ /* Skip audio */ ++ eframe += 24; ++ /* Search for something waiting to transmit */ ++ if (pos) { ++ if (!list_empty(&mod->pending_cmds)) { ++ struct wctdm_cmd *const cmd = ++ list_entry(mod->pending_cmds.next, ++ struct wctdm_cmd, node); ++ curcmd = cmd->cmd; ++ cmd->ident = wc->txident; ++ list_move_tail(&cmd->node, &mod->active_cmds); ++ } ++ } ++ ++ if (!curcmd) { ++ /* If nothing else, use filler */ ++ switch (mod->type) { ++ case FXS: ++ curcmd = CMD_RD(LINE_STATE); ++ break; ++ case FXO: ++ curcmd = CMD_RD(12); ++ break; ++ case BRI: ++ curcmd = 0x101010; ++ break; ++ case QRV: ++ curcmd = CMD_RD(3); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ switch (mod->type) { ++ case FXS: ++ eframe[CMD_BYTE(mod, 0)] = (1 << (mod->subaddr)); ++ if (curcmd & __CMD_WR) ++ eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0x7f; ++ else ++ eframe[CMD_BYTE(mod, 1)] = 0x80 | ((curcmd >> 8) & 0x7f); ++ eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff; ++ break; ++ ++ case FXO: ++ { ++ static const int ADDRS[4] = {0x00, 0x08, 0x04, 0x0c}; ++ if (curcmd & __CMD_WR) ++ eframe[CMD_BYTE(mod, 0)] = 0x20 | ADDRS[mod->subaddr]; ++ else ++ eframe[CMD_BYTE(mod, 0)] = 0x60 | ADDRS[mod->subaddr]; ++ eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0xff; ++ eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff; ++ break; ++ } ++ case FXSINIT: ++ /* Special case, we initialize the FXS's into the three-byte command mode then ++ switch to the regular mode. To send it into thee byte mode, treat the path as ++ 6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules ++ read this as the command to switch to daisy chain mode and we're done. */ ++ eframe[CMD_BYTE(mod, 0)] = 0x00; ++ eframe[CMD_BYTE(mod, 1)] = 0x00; ++ if ((card & 0x1) == 0x1) ++ eframe[CMD_BYTE(mod, 2)] = 0x80; ++ else ++ eframe[CMD_BYTE(mod, 2)] = 0x00; ++ break; ++ ++ case BRI: ++ if (unlikely((curcmd != 0x101010) && (curcmd & 0x1010) == 0x1010)) /* b400m CPLD */ ++ eframe[CMD_BYTE(mod, 0)] = 0x55; ++ else /* xhfc */ ++ eframe[CMD_BYTE(mod, 0)] = 0x10; ++ eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0xff; ++ eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff; ++ break; ++ ++ case QRV: ++ eframe[CMD_BYTE(mod, 0)] = 0x00; ++ if (!curcmd) { ++ eframe[CMD_BYTE(mod, 1)] = 0x00; ++ eframe[CMD_BYTE(mod, 2)] = 0x00; ++ } else { ++ if (curcmd & __CMD_WR) ++ eframe[CMD_BYTE(mod, 1)] = 0x40 | ((curcmd >> 8) & 0x3f); ++ else ++ eframe[CMD_BYTE(mod, 1)] = 0xc0 | ((curcmd >> 8) & 0x3f); ++ eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff; ++ } ++ break; ++ ++ case NONE: ++ eframe[CMD_BYTE(mod, 0)] = 0x10; ++ eframe[CMD_BYTE(mod, 1)] = 0x10; ++ eframe[CMD_BYTE(mod, 2)] = 0x10; ++ break; ++ } ++} ++ ++static inline void cmd_decipher_vpmoct(struct wctdm *wc, const u8 *eframe) ++{ ++ struct vpmoct *vpm = wc->vpmoct; ++ struct vpmoct_cmd *cmd; ++ int i; ++ ++ /* Skip audio and first 6 timeslots */ ++ eframe += 30; ++ ++ spin_lock(&vpm->list_lock); ++ /* No command to handle, just exit */ ++ if (list_empty(&vpm->active_list)) { ++ spin_unlock(&vpm->list_lock); ++ return; ++ } ++ ++ cmd = list_entry(vpm->active_list.next, struct vpmoct_cmd, node); ++ if (wc->rxident == cmd->txident) ++ list_del_init(&cmd->node); ++ else ++ cmd = NULL; ++ spin_unlock(&vpm->list_lock); ++ ++ if (!cmd) ++ return; ++ ++ /* Store result, Ignoring the first "sync spi command" bytes */ ++ cmd->command = eframe[7*3]; ++ cmd->address = eframe[7*4]; ++ for (i = 0; i < cmd->chunksize; ++i) ++ cmd->data[i] = eframe[7*(5+i)]; ++ complete(&cmd->complete); ++} ++ ++static inline void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *eframe) ++{ ++ struct vpmadt032 *const 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(&vpm->list_lock); ++ 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(&vpm->list_lock); ++ ++ if (!cmd) ++ return; ++ ++ /* Skip audio */ ++ eframe += 24; ++ ++ /* Store result */ ++ cmd->data = (0xff & eframe[VPM_CMD_BYTE(25, 1)]) << 8; ++ cmd->data |= eframe[VPM_CMD_BYTE(25, 2)]; ++ if (cmd->desc & __VPM150M_WR) { ++ kfree(cmd); ++ } else { ++ cmd->desc |= __VPM150M_FIN; ++ complete(&cmd->complete); ++ } ++} ++ ++/** ++ * Call with the reglock held and local interrupts disabled ++ */ ++static void _cmd_decipher(struct wctdm *wc, const u8 *eframe, int card) ++{ ++ enum { TDM_BYTES = 24, }; ++ struct wctdm_module *const mod = &wc->mods[card]; ++ struct wctdm_cmd *cmd; ++ u8 address; ++ u8 value; ++ ++ if (list_empty(&mod->active_cmds)) ++ return; ++ ++ cmd = list_entry(mod->active_cmds.next, struct wctdm_cmd, node); ++ if (cmd->ident != wc->rxident) ++ return; ++ ++ list_del(&cmd->node); ++ ++ if (cmd->cmd & __CMD_WR) { ++ kfree(cmd); ++ return; ++ } ++ ++ address = (cmd->cmd >> 8) & 0xff; ++ ++ cmd->cmd = eframe[TDM_BYTES + CMD_BYTE(mod, 2)]; ++ ++ value = (cmd->cmd & 0xff); ++ ++ if (cmd->complete) { ++ complete(cmd->complete); ++ return; ++ } ++ ++ list_add(&cmd->node, &wc->free_isr_commands); ++ ++ switch (mod->type) { ++ case FXS: ++ if (68 == address) ++ mod->mod.fxs.hook_state_shadow = value; ++ else ++ mod->mod.fxs.linefeed_control_shadow = value; ++ break; ++ case FXO: ++ if (5 == address) ++ mod->mod.fxo.hook_ring_shadow = value; ++ else ++ mod->mod.fxo.line_voltage_status = value; ++ break; ++ case QRV: ++ /* wctdm_isr_getreg(wc, mod, 3); */ /* COR/CTCSS state */ ++ /* TODO: This looks broken to me, but I have no way to ++ * resolved it. */ ++ /* wc->mods[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); */ ++ break; ++ default: ++ break; ++ } ++} ++ ++/* Call with wc.reglock held and local interrupts disabled. */ ++static void ++wctdm_isr_getreg(struct wctdm *wc, struct wctdm_module *const mod, u8 address) ++{ ++ struct wctdm_cmd *cmd; ++ ++ if (!list_empty(&wc->free_isr_commands)) { ++ cmd = list_entry(wc->free_isr_commands.next, ++ struct wctdm_cmd, node); ++ list_del(&cmd->node); ++ } else { ++ cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); ++ if (unlikely(!cmd)) ++ return; ++ } ++ ++ cmd->cmd = CMD_RD(address); ++ cmd->complete = NULL; ++ ++ list_add(&cmd->node, &mod->pending_cmds); ++} ++ ++/* Must be called with wc.reglock held and local interrupts disabled */ ++static inline void ++wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod, int addr, int val) ++{ ++ struct wctdm_cmd *cmd; ++ ++ cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); ++ if (unlikely(!cmd)) ++ return; ++ ++ cmd->complete = NULL; ++ cmd->cmd = CMD_WR(addr, val); ++ ++ list_add_tail(&cmd->node, &mod->pending_cmds); ++} ++ ++ ++static void cmd_checkisr(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ if (mod->sethook) { ++ wctdm_setreg_intr(wc, mod, ((mod->sethook >> 8) & 0xff), ++ mod->sethook & 0xff); ++ mod->sethook = 0; ++ return; ++ } ++ ++ switch (mod->type) { ++ case FXS: ++ wctdm_isr_getreg(wc, mod, 68); /* Hook state */ ++#ifdef PAQ_DEBUG ++ wctdm_isr_getreg(wc, mod, 19); /* Transistor interrupts */ ++#else ++ wctdm_isr_getreg(wc, mod, LINE_STATE); ++#endif ++ break; ++ case FXO: ++ wctdm_isr_getreg(wc, mod, 5); /* Hook/Ring state */ ++ wctdm_isr_getreg(wc, mod, 29); /* Battery */ ++ break; ++ case QRV: ++ wctdm_isr_getreg(wc, mod, 3); /* COR/CTCSS state */ ++ /* TODO: This looks broken to me, but I have no way to ++ * resolved it. */ ++ /* wc->mods[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); */ ++ break; ++ case BRI: ++ /* TODO: Two calls needed here? */ ++ wctdm_bri_checkisr(wc, mod, 0); ++ wctdm_bri_checkisr(wc, mod, 1); ++ break; ++ default: ++ break; ++ } ++} ++ ++/** ++ * insert_tdm_data() - Move TDM data from channels to sframe. ++ * ++ */ ++static void insert_tdm_data(const struct wctdm *wc, u8 *sframe) ++{ ++ int i; ++ register u8 *chanchunk; ++ ++ for (i = 0; i < wc->avchannels; i += 4) { ++ chanchunk = &wc->chans[0 + i]->chan.writechunk[0]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6]; ++ sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7]; ++ ++ chanchunk = &wc->chans[1 + i]->chan.writechunk[0]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6]; ++ sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7]; ++ ++ chanchunk = &wc->chans[2 + i]->chan.writechunk[0]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6]; ++ sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7]; ++ ++ chanchunk = &wc->chans[3 + i]->chan.writechunk[0]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6]; ++ sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7]; ++ } ++} ++ ++static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe) ++{ ++ int x, y; ++ struct dahdi_span *s; ++ unsigned char *eframe = sframe; ++ ++ /* Calculate Transmission */ ++ if (likely(is_initialized(wc))) { ++ for (x = 0; x < MAX_SPANS; x++) { ++ if (wc->spans[x]) { ++ s = &wc->spans[x]->span; ++ _dahdi_transmit(s); ++ } ++ } ++ insert_tdm_data(wc, sframe); ++#ifdef CONFIG_VOICEBUS_ECREFERENCE ++ for (x = 0; x < wc->avchannels; ++x) { ++ __dahdi_fifo_put(wc->ec_reference[x], ++ wc->chans[x]->chan.writechunk, ++ DAHDI_CHUNKSIZE); ++ } ++#endif ++ } ++ ++ spin_lock(&wc->reglock); ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) { ++ /* Send a sample, as a 32-bit word */ ++ ++ /* TODO: ABK: hmm, this was originally mods_per_board, but we ++ * need to worry about all the active "voice" timeslots, since ++ * BRI modules have a different number of TDM channels than ++ * installed modules. */ ++ for (y = 0; y < wc->avchannels; y++) { ++ if (y < wc->mods_per_board) ++ _cmd_dequeue(wc, eframe, y, x); ++ } ++ ++ if (wc->vpmadt032) ++ cmd_dequeue_vpmadt032(wc, eframe); ++ else if (wc->vpmoct) ++ cmd_dequeue_vpmoct(wc, eframe); ++ ++ if (x < DAHDI_CHUNKSIZE - 1) { ++ eframe[EFRAME_SIZE] = wc->ctlreg; ++ eframe[EFRAME_SIZE + 1] = wc->txident++; ++ if (4 == wc->desc->ports) ++ eframe[EFRAME_SIZE + 2] = wc->tdm410leds; ++ } ++ eframe += (EFRAME_SIZE + EFRAME_GAP); ++ } ++ spin_unlock(&wc->reglock); ++} ++ ++int wctdm_setreg(struct wctdm *wc, struct wctdm_module *mod, int addr, int val) ++{ ++ struct wctdm_cmd *cmd; ++ unsigned long flags; ++ ++#if 0 /* TODO */ ++ /* QRV and BRI cards are only addressed at their first "port" */ ++ if ((card & 0x03) && ((wc->mods[card].type == QRV) || ++ (wc->mods[card].type == BRI))) ++ return 0; ++#endif ++ ++ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); ++ if (unlikely(!cmd)) ++ return -ENOMEM; ++ ++ cmd->complete = NULL; ++ cmd->cmd = CMD_WR(addr, val); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ list_add_tail(&cmd->node, &mod->pending_cmds); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return 0; ++} ++ ++int wctdm_getreg(struct wctdm *wc, struct wctdm_module *const mod, int addr) ++{ ++ unsigned long flags; ++ struct wctdm_cmd *cmd; ++ int val; ++ ++#if 0 /* TODO */ ++ /* if a QRV card, use only its first channel */ ++ if (wc->mods[card].type == QRV) { ++ if (card & 3) ++ return 0; ++ } ++#endif ++ ++ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ cmd->complete = kmalloc(sizeof(*cmd->complete), GFP_KERNEL); ++ if (!cmd->complete) { ++ kfree(cmd); ++ return -ENOMEM; ++ } ++ ++ init_completion(cmd->complete); ++ ++ cmd->cmd = CMD_RD(addr); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ list_add_tail(&cmd->node, &mod->pending_cmds); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ wait_for_completion(cmd->complete); ++ val = cmd->cmd & 0xff; ++ ++ kfree(cmd->complete); ++ kfree(cmd); ++ ++ return val; ++} ++ ++static int wctdm_getregs(struct wctdm *wc, struct wctdm_module *const mod, ++ int *const addresses, const size_t count) ++{ ++ int x; ++ unsigned long flags; ++ struct wctdm_cmd *cmd; ++ struct wctdm_cmd **cmds = kmalloc(sizeof(cmd) * count, GFP_KERNEL); ++ ++ if (!cmds) ++ return -ENOMEM; ++ ++ for (x = 0; x < count; ++x) { ++ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) { ++ kfree(cmds); ++ return -ENOMEM; ++ } ++ ++ cmd->complete = kmalloc(sizeof(*cmd->complete), GFP_KERNEL); ++ if (!cmd->complete) { ++ kfree(cmd); ++ kfree(cmds); ++ return -ENOMEM; ++ } ++ ++ init_completion(cmd->complete); ++ ++ cmd->cmd = CMD_RD(addresses[x]); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ list_add_tail(&cmd->node, &mod->pending_cmds); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ cmds[x] = cmd; ++ } ++ ++ for (x = count - 1; x >= 0; --x) { ++ cmd = cmds[x]; ++ wait_for_completion(cmd->complete); ++ addresses[x] = cmd->cmd & 0xff; ++ kfree(cmd->complete); ++ kfree(cmd); ++ } ++ ++ kfree(cmds); ++ return 0; ++} ++ ++/** ++ * call with wc->reglock held and interrupts disabled. ++ */ ++static void cmd_retransmit(struct wctdm *wc) ++{ ++ int x; ++ ++ for (x = 0; x < wc->mods_per_board; x++) { ++ struct wctdm_module *const mod = &wc->mods[x]; ++ if (mod->type == BRI) ++ continue; ++ list_splice_init(&mod->active_cmds, &mod->pending_cmds); ++ } ++ ++#ifdef VPM_SUPPORT ++ if (wc->vpmadt032) ++ vpmadt032_resend(wc->vpmadt032); ++#endif ++} ++ ++/** ++ * extract_tdm_data() - Move TDM data from sframe to channels. ++ * ++ */ ++static void extract_tdm_data(struct wctdm *wc, const u8 *sframe) ++{ ++ int i; ++ register u8 *chanchunk; ++ ++ for (i = 0; i < wc->avchannels; i += 4) { ++ chanchunk = &wc->chans[0 + i]->chan.readchunk[0]; ++ chanchunk[0] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0]; ++ chanchunk[1] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1]; ++ chanchunk[2] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2]; ++ chanchunk[3] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*3]; ++ chanchunk[4] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*4]; ++ chanchunk[5] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*5]; ++ chanchunk[6] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6]; ++ chanchunk[7] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7]; ++ ++ chanchunk = &wc->chans[1 + i]->chan.readchunk[0]; ++ chanchunk[0] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0]; ++ chanchunk[1] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1]; ++ chanchunk[2] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2]; ++ chanchunk[3] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*3]; ++ chanchunk[4] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*4]; ++ chanchunk[5] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*5]; ++ chanchunk[6] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6]; ++ chanchunk[7] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7]; ++ ++ chanchunk = &wc->chans[2 + i]->chan.readchunk[0]; ++ chanchunk[0] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0]; ++ chanchunk[1] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1]; ++ chanchunk[2] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2]; ++ chanchunk[3] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*3]; ++ chanchunk[4] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*4]; ++ chanchunk[5] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*5]; ++ chanchunk[6] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6]; ++ chanchunk[7] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7]; ++ ++ chanchunk = &wc->chans[3 + i]->chan.readchunk[0]; ++ chanchunk[0] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0]; ++ chanchunk[1] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1]; ++ chanchunk[2] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2]; ++ chanchunk[3] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*3]; ++ chanchunk[4] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*4]; ++ chanchunk[5] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*5]; ++ chanchunk[6] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*6]; ++ chanchunk[7] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*7]; ++ } ++ ++ /* Pre-echo with the vpmoct overwrites the 24th timeslot with the ++ * specified channel's pre-echo audio stream. This data is ignored ++ * on all but the 24xx card, so we store it in a temporary buffer. ++ */ ++ if (wc->vpmoct && wc->vpmoct->preecho_enabled) { ++ chanchunk = &wc->vpmoct->preecho_buf[0]; ++ chanchunk[0] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*0]; ++ chanchunk[1] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*1]; ++ chanchunk[2] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*2]; ++ chanchunk[3] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*3]; ++ chanchunk[4] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*4]; ++ chanchunk[5] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*5]; ++ chanchunk[6] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*6]; ++ chanchunk[7] = sframe[23 + (EFRAME_SIZE + EFRAME_GAP)*7]; ++ } ++} ++ ++static inline void wctdm_receiveprep(struct wctdm *wc, const u8 *sframe) ++{ ++ int x, y; ++ bool irqmiss = false; ++ unsigned char expected; ++ const u8 *eframe = sframe; ++ ++ if (unlikely(!is_good_frame(sframe))) ++ return; ++ ++ spin_lock(&wc->reglock); ++ ++ if (likely(is_initialized(wc))) ++ extract_tdm_data(wc, sframe); ++ ++ for (x = 0; x < DAHDI_CHUNKSIZE; x++) { ++ if (x < DAHDI_CHUNKSIZE - 1) { ++ expected = wc->rxident + 1; ++ wc->rxident = eframe[EFRAME_SIZE + 1]; ++ if (wc->rxident != expected) { ++ irqmiss = true; ++ cmd_retransmit(wc); ++ } ++ } ++ ++ for (y = 0; y < wc->avchannels; y++) ++ _cmd_decipher(wc, eframe, y); ++ ++ if (wc->vpmadt032) ++ cmd_decipher_vpmadt032(wc, eframe); ++ else if (wc->vpmoct) ++ cmd_decipher_vpmoct(wc, eframe); ++ ++ eframe += (EFRAME_SIZE + EFRAME_GAP); ++ } ++ spin_unlock(&wc->reglock); ++ ++ /* XXX We're wasting 8 taps. We should get closer :( */ ++ if (likely(is_initialized(wc))) { ++ for (x = 0; x < wc->avchannels; x++) { ++ struct wctdm_chan *const wchan = wc->chans[x]; ++ struct dahdi_chan *const c = &wchan->chan; ++#ifdef CONFIG_VOICEBUS_ECREFERENCE ++ unsigned char buffer[DAHDI_CHUNKSIZE]; ++ __dahdi_fifo_get(wc->ec_reference[x], buffer, ++ ARRAY_SIZE(buffer)); ++ _dahdi_ec_chunk(c, c->readchunk, buffer); ++#else ++ if ((wc->vpmoct) && ++ (wchan->timeslot == wc->vpmoct->preecho_timeslot) && ++ (wc->vpmoct->preecho_enabled)) { ++ __dahdi_ec_chunk(c, c->readchunk, ++ wc->vpmoct->preecho_buf, ++ c->writechunk); ++ } else { ++ __dahdi_ec_chunk(c, c->readchunk, c->readchunk, ++ c->writechunk); ++ } ++#endif ++ } ++ ++ for (x = 0; x < MAX_SPANS; x++) { ++ if (wc->spans[x]) { ++ struct dahdi_span *s = &wc->spans[x]->span; ++#if 1 ++ /* Check for digital spans */ ++ if (s->ops->chanconfig == b400m_chanconfig) { ++ BUG_ON(!is_hx8(wc)); ++ if (s->flags & DAHDI_FLAG_RUNNING) ++ b400m_dchan(s); ++ ++ } ++#endif ++ _dahdi_receive(s); ++ if (unlikely(irqmiss)) ++ wc->ddev->irqmisses++; ++ } ++ } ++ } ++} ++ ++static int wait_access(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ unsigned char data = 0; ++ int count = 0; ++ ++ #define MAX 10 /* attempts */ ++ ++ /* Wait for indirect access */ ++ while (count++ < MAX) { ++ data = wctdm_getreg(wc, mod, I_STATUS); ++ if (!data) ++ return 0; ++ } ++ ++ if (count > (MAX-1)) { ++ dev_notice(&wc->vb.pdev->dev, ++ " ##### Loop error (%02x) #####\n", data); ++ } ++ ++ return 0; ++} ++ ++static unsigned char translate_3215(unsigned char address) ++{ ++ int x; ++ for (x = 0; x < ARRAY_SIZE(indirect_regs); x++) { ++ if (indirect_regs[x].address == address) { ++ address = indirect_regs[x].altaddr; ++ break; ++ } ++ } ++ return address; ++} ++ ++static int ++wctdm_proslic_setreg_indirect(struct wctdm *wc, struct wctdm_module *const mod, ++ unsigned char address, unsigned short data) ++{ ++ int res = -1; ++ ++ address = translate_3215(address); ++ if (address == 255) ++ return 0; ++ ++ if (!wait_access(wc, mod)) { ++ wctdm_setreg(wc, mod, IDA_LO, (u8)(data & 0xFF)); ++ wctdm_setreg(wc, mod, IDA_HI, (u8)((data & 0xFF00)>>8)); ++ wctdm_setreg(wc, mod, IAA, address); ++ res = 0; ++ }; ++ return res; ++} ++ ++static int ++wctdm_proslic_getreg_indirect(struct wctdm *wc, struct wctdm_module *const mod, ++ unsigned char address) ++{ ++ int res = -1; ++ char *p=NULL; ++ ++ address = translate_3215(address); ++ if (address == 255) ++ return 0; ++ ++ if (!wait_access(wc, mod)) { ++ wctdm_setreg(wc, mod, IAA, address); ++ if (!wait_access(wc, mod)) { ++ int addresses[2] = {IDA_LO, IDA_HI}; ++ wctdm_getregs(wc, mod, addresses, ++ ARRAY_SIZE(addresses)); ++ res = addresses[0] | (addresses[1] << 8); ++ } else ++ p = "Failed to wait inside\n"; ++ } else ++ p = "failed to wait\n"; ++ if (p) ++ dev_notice(&wc->vb.pdev->dev, "%s", p); ++ return res; ++} ++ ++static int ++wctdm_proslic_init_indirect_regs(struct wctdm *wc, struct wctdm_module *mod) ++{ ++ unsigned char i; ++ ++ for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) { ++ if (wctdm_proslic_setreg_indirect(wc, mod, ++ indirect_regs[i].address, ++ indirect_regs[i].initial)) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++wctdm_proslic_verify_indirect_regs(struct wctdm *wc, struct wctdm_module *mod) ++{ ++ int passed = 1; ++ unsigned short i, initial; ++ int j; ++ ++ for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) { ++ j = wctdm_proslic_getreg_indirect(wc, mod, ++ (u8)indirect_regs[i].address); ++ if (j < 0) { ++ dev_notice(&wc->vb.pdev->dev, "Failed to read indirect register %d\n", i); ++ return -1; ++ } ++ initial = indirect_regs[i].initial; ++ ++ if ((j != initial) && (indirect_regs[i].altaddr != 255)) { ++ dev_notice(&wc->vb.pdev->dev, ++ "!!!!!!! %s iREG %X = %X should be %X\n", ++ indirect_regs[i].name, ++ indirect_regs[i].address, j, initial); ++ passed = 0; ++ } ++ } ++ ++ if (passed) { ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Init Indirect Registers completed successfully.\n"); ++ } ++ } else { ++ dev_notice(&wc->vb.pdev->dev, ++ " !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++/** ++ * wctdm_proslic_check_oppending - ++ * ++ * Ensures that a write to the line feed register on the SLIC has been ++ * processed. If it hasn't after the timeout value, then it will resend the ++ * command and wait for another timeout period. ++ * ++ */ ++static void ++wctdm_proslic_check_oppending(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ if (!(fxs->lasttxhook & SLIC_LF_OPPENDING)) ++ return; ++ ++ /* Monitor the Pending LF state change, for the next 100ms */ ++ spin_lock(&wc->reglock); ++ ++ ++ if (!(fxs->lasttxhook & SLIC_LF_OPPENDING)) { ++ spin_unlock(&wc->reglock); ++ return; ++ } ++ ++ if ((fxs->linefeed_control_shadow & SLIC_LF_SETMASK) == ++ (fxs->lasttxhook & SLIC_LF_SETMASK)) { ++ fxs->lasttxhook &= SLIC_LF_SETMASK; ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "SLIC_LF OK: card=%d shadow=%02x " ++ "lasttxhook=%02x framecount=%ld\n", mod->card, ++ fxs->linefeed_control_shadow, ++ fxs->lasttxhook, wc->framecount); ++ } ++ } else if (time_after(wc->framecount, fxs->oppending_timeout)) { ++ /* Check again in 100 ms */ ++ fxs->oppending_timeout = wc->framecount + 100; ++ ++ wctdm_setreg_intr(wc, mod, LINE_STATE, fxs->lasttxhook); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "SLIC_LF RETRY: card=%d shadow=%02x " ++ "lasttxhook=%02x framecount=%ld\n", mod->card, ++ fxs->linefeed_control_shadow, ++ fxs->lasttxhook, wc->framecount); ++ } ++ } ++ ++ spin_unlock(&wc->reglock); ++} ++ ++/* 256ms interrupt */ ++static void ++wctdm_proslic_recheck_sanity(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ int res; ++#ifdef PAQ_DEBUG ++ res = mod->isrshadow[1]; ++ res &= ~0x3; ++ if (res) { ++ mod->isrshadow[1] = 0; ++ fxs->palarms++; ++ if (fxs->palarms < MAX_ALARMS) { ++ dev_notice(&wc->vb.pdev->dev, "Power alarm (%02x) on module %d, resetting!\n", res, card + 1); ++ mod->sethook = CMD_WR(19, res); ++ /* Update shadow register to avoid extra power alarms until next read */ ++ mod->isrshadow[1] = 0; ++ } else { ++ if (fxs->palarms == MAX_ALARMS) ++ dev_notice(&wc->vb.pdev->dev, "Too many power alarms on card %d, NOT resetting!\n", card + 1); ++ } ++ } ++#else ++ spin_lock(&wc->reglock); ++ ++ /* reg 64 has to be zero at last isr read */ ++ res = !fxs->linefeed_control_shadow && ++ !(fxs->lasttxhook & SLIC_LF_OPPENDING) && /* not a transition */ ++ fxs->lasttxhook; /* not an intended zero */ ++ ++ if (res) { ++ fxs->palarms++; ++ if (fxs->palarms < MAX_ALARMS) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Power alarm on module %d, resetting!\n", ++ mod->card + 1); ++ if (fxs->lasttxhook == SLIC_LF_RINGING) { ++ fxs->lasttxhook = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD;; ++ } ++ fxs->lasttxhook |= SLIC_LF_OPPENDING; ++ mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ fxs->oppending_timeout = wc->framecount + 100; ++ ++ /* Update shadow register to avoid extra power alarms ++ * until next read */ ++ fxs->linefeed_control_shadow = fxs->lasttxhook; ++ } else { ++ if (fxs->palarms == MAX_ALARMS) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Too many power alarms on card %d, " ++ "NOT resetting!\n", mod->card + 1); ++ } ++ } ++ } ++ spin_unlock(&wc->reglock); ++#endif ++} ++ ++static void wctdm_qrvdri_check_hook(struct wctdm *wc, int card) ++{ ++ signed char b,b1; ++ int qrvcard = card & 0xfc; ++ ++ if (wc->mods[card].mod.qrv.debtime >= 2) ++ wc->mods[card].mod.qrv.debtime--; ++ b = wc->mods[qrvcard].mod.qrv.isrshadow[0]; /* Hook/Ring state */ ++ b &= 0xcc; /* use bits 3-4 and 6-7 only */ ++ ++ if (wc->mods[qrvcard].mod.qrv.radmode & RADMODE_IGNORECOR) ++ b &= ~4; ++ else if (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_INVERTCOR)) ++ b ^= 4; ++ if (wc->mods[qrvcard + 1].mod.qrv.radmode | RADMODE_IGNORECOR) ++ b &= ~0x40; ++ else if (!(wc->mods[qrvcard + 1].mod.qrv.radmode | RADMODE_INVERTCOR)) ++ b ^= 0x40; ++ ++ if ((wc->mods[qrvcard].mod.qrv.radmode & RADMODE_IGNORECT) || ++ (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_EXTTONE))) ++ b &= ~8; ++ else if (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_EXTINVERT)) ++ b ^= 8; ++ if ((wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_IGNORECT) || ++ (!(wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_EXTTONE))) ++ b &= ~0x80; ++ else if (!(wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_EXTINVERT)) ++ b ^= 0x80; ++ /* now b & MASK should be zero, if its active */ ++ /* check for change in chan 0 */ ++ if ((!(b & 0xc)) != wc->mods[qrvcard + 2].mod.qrv.hook) ++ { ++ wc->mods[qrvcard].mod.qrv.debtime = wc->mods[qrvcard].mod.qrv.debouncetime; ++ wc->mods[qrvcard + 2].mod.qrv.hook = !(b & 0xc); ++ } ++ /* if timed-out and ready */ ++ if (wc->mods[qrvcard].mod.qrv.debtime == 1) { ++ b1 = wc->mods[qrvcard + 2].mod.qrv.hook; ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "QRV channel %d rx state changed to %d\n", ++ qrvcard, wc->mods[qrvcard + 2].mod.qrv.hook); ++ } ++ dahdi_hooksig(wc->aspan->span.chans[qrvcard], ++ (b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK); ++ wc->mods[card].mod.qrv.debtime = 0; ++ } ++ /* check for change in chan 1 */ ++ if ((!(b & 0xc0)) != wc->mods[qrvcard + 3].mod.qrv.hook) ++ { ++ wc->mods[qrvcard + 1].mod.qrv.debtime = QRV_DEBOUNCETIME; ++ wc->mods[qrvcard + 3].mod.qrv.hook = !(b & 0xc0); ++ } ++ if (wc->mods[qrvcard + 1].mod.qrv.debtime == 1) { ++ b1 = wc->mods[qrvcard + 3].mod.qrv.hook; ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "QRV channel %d rx state changed to %d\n", ++ qrvcard + 1, wc->mods[qrvcard + 3].mod.qrv.hook); ++ } ++ dahdi_hooksig(wc->aspan->span.chans[qrvcard + 1], ++ (b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK); ++ wc->mods[card].mod.qrv.debtime = 0; ++ } ++ return; ++} ++ ++static inline bool is_fxo_ringing(const struct fxo *const fxo) ++{ ++ return ((fxo->hook_ring_shadow & 0x60) && ++ ((fxo->battery_state == BATTERY_PRESENT) || ++ (fxo->battery_state == BATTERY_DEBOUNCING_LOST))); ++} ++ ++static inline bool is_fxo_ringing_positive(const struct fxo *const fxo) ++{ ++ return (((fxo->hook_ring_shadow & 0x60) == 0x20) && ++ ((fxo->battery_state == BATTERY_PRESENT) || ++ (fxo->battery_state == BATTERY_DEBOUNCING_LOST))); ++} ++ ++static inline bool is_fxo_ringing_negative(const struct fxo *const fxo) ++{ ++ return (((fxo->hook_ring_shadow & 0x60) == 0x40) && ++ ((fxo->battery_state == BATTERY_PRESENT) || ++ (fxo->battery_state == BATTERY_DEBOUNCING_LOST))); ++} ++ ++static inline void set_ring(struct fxo *fxo, enum ring_detector_state new) ++{ ++ fxo->ring_state = new; ++} ++ ++static void wctdm_fxo_ring_detect(struct wctdm *wc, struct wctdm_module *mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ static const unsigned int POLARITY_CHANGES_NEEDED = 2; ++ ++ /* Look for ring status bits (Ring Detect Signal Negative and Ring ++ * Detect Signal Positive) to transition back and forth ++ * POLARITY_CHANGES_NEEDED times to indicate that a ring is occurring. ++ * Provide some number of samples to allow for the transitions to occur ++ * before giving up. NOTE: neon mwi voltages will trigger one of these ++ * bits to go active but not to have transitions between the two bits ++ * (i.e. no negative to positive or positive to negative traversals) */ ++ ++ switch (fxo->ring_state) { ++ case DEBOUNCING_RINGING_POSITIVE: ++ if (is_fxo_ringing_negative(fxo)) { ++ if (++fxo->ring_polarity_change_count > ++ POLARITY_CHANGES_NEEDED) { ++ mod_hooksig(wc, mod, DAHDI_RXSIG_RING); ++ set_ring(fxo, RINGING); ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "RING on %s!\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ } else { ++ set_ring(fxo, DEBOUNCING_RINGING_NEGATIVE); ++ } ++ } else if (time_after(wc->framecount, ++ fxo->ringdebounce_timer)) { ++ set_ring(fxo, RINGOFF); ++ } ++ break; ++ case DEBOUNCING_RINGING_NEGATIVE: ++ if (is_fxo_ringing_positive(fxo)) { ++ if (++fxo->ring_polarity_change_count > ++ POLARITY_CHANGES_NEEDED) { ++ mod_hooksig(wc, mod, DAHDI_RXSIG_RING); ++ set_ring(fxo, RINGING); ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "RING on %s!\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ } else { ++ set_ring(fxo, DEBOUNCING_RINGING_POSITIVE); ++ } ++ } else if (time_after(wc->framecount, ++ fxo->ringdebounce_timer)) { ++ set_ring(fxo, RINGOFF); ++ } ++ break; ++ case RINGING: ++ if (!is_fxo_ringing(fxo)) { ++ set_ring(fxo, DEBOUNCING_RINGOFF); ++ fxo->ringdebounce_timer = ++ wc->framecount + ringdebounce / 8; ++ } ++ break; ++ case DEBOUNCING_RINGOFF: ++ if (!is_fxo_ringing(fxo)) { ++ if (time_after(wc->framecount, ++ fxo->ringdebounce_timer)) { ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "NO RING on %s!\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK); ++ set_ring(fxo, RINGOFF); ++ } ++ } else { ++ set_ring(fxo, RINGING); ++ } ++ break; ++ case RINGOFF: ++ if (is_fxo_ringing(fxo)) { ++ /* Look for positive/negative crossings in ring status ++ * reg */ ++ if (is_fxo_ringing_positive(fxo)) ++ set_ring(fxo, DEBOUNCING_RINGING_POSITIVE); ++ else ++ set_ring(fxo, DEBOUNCING_RINGING_NEGATIVE); ++ fxo->ringdebounce_timer = ++ wc->framecount + ringdebounce / 8; ++ fxo->ring_polarity_change_count = 0; ++ } ++ break; ++ } ++} ++ ++#define MS_PER_CHECK_HOOK 1 ++ ++static void ++wctdm_check_battery_lost(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ /* possible existing states: ++ battery lost, no debounce timer ++ battery lost, debounce timer (going to battery present) ++ battery present or unknown, no debounce timer ++ battery present or unknown, debounce timer (going to battery lost) ++ */ ++ switch (fxo->battery_state) { ++ case BATTERY_DEBOUNCING_PRESENT_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_PRESENT: ++ fxo->battery_state = BATTERY_LOST; ++ break; ++ case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ break; ++ case BATTERY_UNKNOWN: ++ mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK); ++ case BATTERY_PRESENT: ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM: ++ case BATTERY_DEBOUNCING_LOST: /* Intentional drop through */ ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "NO BATTERY on %d/%d!\n", ++ wc->aspan->span.spanno, ++ mod->card + 1); ++ } ++#ifdef JAPAN ++ if (!wc->ohdebounce && wc->offhook) { ++ dahdi_hooksig(wc->aspan->chans[card], ++ DAHDI_RXSIG_ONHOOK); ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "Signalled On Hook\n"); ++ } ++#ifdef ZERO_BATT_RING ++ wc->onhook++; ++#endif ++ } ++#else ++ mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK); ++#endif ++ /* set the alarm timer, taking into account that part ++ * of its time period has already passed while ++ * debouncing occurred */ ++ fxo->battery_state = BATTERY_DEBOUNCING_LOST_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ } ++ break; ++ case BATTERY_DEBOUNCING_LOST_ALARM: ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ fxo->battery_state = BATTERY_LOST; ++ dahdi_alarm_channel(get_dahdi_chan(wc, mod), ++ DAHDI_ALARM_RED); ++ } ++ break; ++ case BATTERY_LOST: ++ break; ++ } ++} ++ ++static void ++wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ switch (fxo->battery_state) { ++ case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM: ++ case BATTERY_DEBOUNCING_PRESENT: /* intentional drop through */ ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "BATTERY on %d/%d (%s)!\n", ++ wc->aspan->span.spanno, mod->card + 1, ++ (fxo->line_voltage_status < 0) ? ++ "-" : "+"); ++ } ++#ifdef ZERO_BATT_RING ++ if (wc->onhook) { ++ wc->onhook = 0; ++ dahdi_hooksig(wc->aspan->chans[card], ++ DAHDI_RXSIG_OFFHOOK); ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "Signalled Off Hook\n"); ++ } ++ } ++#else ++ mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK); ++#endif ++ /* set the alarm timer, taking into account that part ++ * of its time period has already passed while ++ * debouncing occurred */ ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ } ++ break; ++ case BATTERY_DEBOUNCING_PRESENT_ALARM: ++ if (time_after(wc->framecount, fxo->battdebounce_timer)) { ++ fxo->battery_state = BATTERY_PRESENT; ++ dahdi_alarm_channel(get_dahdi_chan(wc, mod), ++ DAHDI_ALARM_NONE); ++ } ++ break; ++ case BATTERY_PRESENT: ++ break; ++ case BATTERY_DEBOUNCING_LOST_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM: ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM; ++ fxo->battdebounce_timer = wc->framecount + ++ battalarm - battdebounce; ++ break; ++ case BATTERY_DEBOUNCING_LOST: ++ fxo->battery_state = BATTERY_PRESENT; ++ break; ++ case BATTERY_UNKNOWN: ++ mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK); ++ case BATTERY_LOST: /* intentional drop through */ ++ fxo->battery_state = BATTERY_DEBOUNCING_PRESENT; ++ fxo->battdebounce_timer = wc->framecount + battdebounce; ++ break; ++ } ++} ++ ++static void ++wctdm_fxo_stop_debouncing_polarity(struct wctdm *wc, ++ struct wctdm_module *const mod) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ switch (fxo->polarity_state) { ++ case UNKNOWN_POLARITY: ++ break; ++ case POLARITY_DEBOUNCE_POSITIVE: ++ fxo->polarity_state = POLARITY_NEGATIVE; ++ break; ++ case POLARITY_POSITIVE: ++ break; ++ case POLARITY_DEBOUNCE_NEGATIVE: ++ fxo->polarity_state = POLARITY_POSITIVE; ++ break; ++ case POLARITY_NEGATIVE: ++ break; ++ }; ++} ++ ++static void ++wctdm_fxo_check_polarity(struct wctdm *wc, struct wctdm_module *const mod, ++ const bool positive_polarity) ++{ ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ switch (fxo->polarity_state) { ++ case UNKNOWN_POLARITY: ++ fxo->polarity_state = (positive_polarity) ? POLARITY_POSITIVE : ++ POLARITY_NEGATIVE; ++ break; ++ case POLARITY_DEBOUNCE_POSITIVE: ++ if (!positive_polarity) { ++ fxo->polarity_state = POLARITY_NEGATIVE; ++ } else if (time_after(wc->framecount, fxo->poldebounce_timer)) { ++ fxo->polarity_state = POLARITY_POSITIVE; ++ dahdi_qevent_lock(get_dahdi_chan(wc, mod), ++ DAHDI_EVENT_POLARITY); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "%s: Polarity NEGATIVE -> POSITIVE\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ } ++ break; ++ case POLARITY_POSITIVE: ++ if (!positive_polarity) { ++ fxo->polarity_state = POLARITY_DEBOUNCE_NEGATIVE; ++ fxo->poldebounce_timer = wc->framecount + ++ POLARITY_DEBOUNCE; ++ } ++ break; ++ case POLARITY_DEBOUNCE_NEGATIVE: ++ if (positive_polarity) { ++ fxo->polarity_state = POLARITY_POSITIVE; ++ } else if (time_after(wc->framecount, fxo->poldebounce_timer)) { ++ dahdi_qevent_lock(get_dahdi_chan(wc, mod), ++ DAHDI_EVENT_POLARITY); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "%s: Polarity POSITIVE -> NEGATIVE\n", ++ get_dahdi_chan(wc, mod)->name); ++ } ++ fxo->polarity_state = POLARITY_NEGATIVE; ++ } ++ break; ++ case POLARITY_NEGATIVE: ++ if (positive_polarity) { ++ fxo->polarity_state = POLARITY_DEBOUNCE_POSITIVE; ++ fxo->poldebounce_timer = wc->framecount + ++ POLARITY_DEBOUNCE; ++ } ++ break; ++ }; ++} ++ ++static void ++wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ signed char b; ++ u8 abs_voltage; ++ struct fxo *const fxo = &mod->mod.fxo; ++ ++ /* Try to track issues that plague slot one FXO's */ ++ b = fxo->hook_ring_shadow & 0x9b; ++ ++ if (fxo->offhook) { ++ if (b != 0x9) ++ wctdm_setreg_intr(wc, mod, 5, 0x9); ++ } else { ++ if (b != 0x8) ++ wctdm_setreg_intr(wc, mod, 5, 0x8); ++ ++ wctdm_fxo_ring_detect(wc, mod); ++ } ++ ++ abs_voltage = abs(fxo->line_voltage_status); ++ ++ if (fxovoltage && time_after(wc->framecount, fxo->display_fxovoltage)) { ++ /* Every 100 ms */ ++ fxo->display_fxovoltage = wc->framecount + 100; ++ dev_info(&wc->vb.pdev->dev, ++ "Port %d: Voltage: %d\n", ++ mod->card + 1, fxo->line_voltage_status); ++ } ++ ++ if (unlikely(DAHDI_RXSIG_INITIAL == get_dahdi_chan(wc, mod)->rxhooksig)) { ++ /* ++ * dahdi-base will set DAHDI_RXSIG_INITIAL after a ++ * DAHDI_STARTUP or DAHDI_CHANCONFIG ioctl so that new events ++ * will be queued on the channel with the current received ++ * hook state. Channels that use robbed-bit signalling always ++ * report the current received state via the dahdi_rbsbits ++ * call. Since we only call dahdi_hooksig when we've detected ++ * a change to report, let's forget our current state in order ++ * to force us to report it again via dahdi_hooksig. ++ * ++ */ ++ fxo->battery_state = BATTERY_UNKNOWN; ++ } ++ ++ if (abs_voltage < battthresh) { ++ wctdm_fxo_stop_debouncing_polarity(wc, mod); ++ wctdm_check_battery_lost(wc, mod); ++ } else { ++ wctdm_check_battery_present(wc, mod); ++ wctdm_fxo_check_polarity(wc, mod, ++ (fxo->line_voltage_status > 0)); ++ } ++ ++ /* Look for neon mwi pulse */ ++ if (neonmwi_monitor && !fxo->offhook) { ++ /* Look for 4 consecutive voltage readings ++ * where the voltage is over the neon limit but ++ * does not vary greatly from the last reading ++ */ ++ if (fxo->battery_state == BATTERY_PRESENT && ++ abs_voltage > neonmwi_level && ++ (0 == fxo->neonmwi_last_voltage || ++ (fxo->line_voltage_status >= fxo->neonmwi_last_voltage - neonmwi_envelope && ++ fxo->line_voltage_status <= fxo->neonmwi_last_voltage + neonmwi_envelope))) { ++ fxo->neonmwi_last_voltage = fxo->line_voltage_status; ++ if (NEONMWI_ON_DEBOUNCE == fxo->neonmwi_debounce) { ++ fxo->neonmwi_offcounter = neonmwi_offlimit_cycles; ++ if (0 == fxo->neonmwi_state) { ++ dahdi_qevent_lock(get_dahdi_chan(wc, mod), DAHDI_EVENT_NEONMWI_ACTIVE); ++ fxo->neonmwi_state = 1; ++ if (debug) ++ dev_info(&wc->vb.pdev->dev, "NEON MWI active for card %d\n", mod->card+1); ++ } ++ fxo->neonmwi_debounce++; /* terminate the processing */ ++ } else if (NEONMWI_ON_DEBOUNCE > fxo->neonmwi_debounce) { ++ fxo->neonmwi_debounce++; ++ } else { /* Insure the count gets reset */ ++ fxo->neonmwi_offcounter = neonmwi_offlimit_cycles; ++ } ++ } else { ++ fxo->neonmwi_debounce = 0; ++ fxo->neonmwi_last_voltage = 0; ++ } ++ /* If no neon mwi pulse for given period of time, indicte no neon mwi state */ ++ if (fxo->neonmwi_state && 0 < fxo->neonmwi_offcounter ) { ++ fxo->neonmwi_offcounter--; ++ if (0 == fxo->neonmwi_offcounter) { ++ dahdi_qevent_lock(get_dahdi_chan(wc, mod), DAHDI_EVENT_NEONMWI_INACTIVE); ++ fxo->neonmwi_state = 0; ++ if (debug) ++ dev_info(&wc->vb.pdev->dev, "NEON MWI cleared for card %d\n", mod->card+1); ++ } ++ } ++ } ++#undef MS_PER_CHECK_HOOK ++} ++ ++static void ++wctdm_fxs_hooksig(struct wctdm *wc, struct wctdm_module *const mod, ++ enum dahdi_txsig txsig) ++{ ++ int x = 0; ++ unsigned long flags; ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ switch (txsig) { ++ case DAHDI_TXSIG_ONHOOK: ++ switch (get_dahdi_chan(wc, mod)->sig) { ++ case DAHDI_SIG_FXOGS: ++ x = (POLARITY_XOR(fxs)) ? ++ SLIC_LF_RING_OPEN : ++ SLIC_LF_TIP_OPEN; ++ break; ++ case DAHDI_SIG_EM: ++ case DAHDI_SIG_FXOKS: ++ case DAHDI_SIG_FXOLS: ++ default: ++ x = fxs->idletxhookstate; ++ break; ++ } ++ break; ++ case DAHDI_TXSIG_OFFHOOK: ++ switch (get_dahdi_chan(wc, mod)->sig) { ++ case DAHDI_SIG_EM: ++ x = (POLARITY_XOR(fxs)) ? ++ SLIC_LF_ACTIVE_FWD : ++ SLIC_LF_ACTIVE_REV; ++ break; ++ default: ++ x = fxs->idletxhookstate; ++ break; ++ } ++ break; ++ case DAHDI_TXSIG_START: ++ x = SLIC_LF_RINGING; ++ break; ++ case DAHDI_TXSIG_KEWL: ++ x = SLIC_LF_OPEN; ++ break; ++ default: ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dev_notice(&wc->vb.pdev->dev, ++ "wctdm24xxp: Can't set tx state to %d\n", txsig); ++ return; ++ } ++ ++ if (x != fxs->lasttxhook) { ++ fxs->lasttxhook = x | SLIC_LF_OPPENDING; ++ mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ fxs->oppending_timeout = wc->framecount + 100; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, "Setting FXS hook state " ++ "to %d (%02x) framecount=%ld\n", txsig, x, ++ wc->framecount); ++ } ++ } else { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++} ++ ++static void wctdm_fxs_off_hook(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ if (debug & DEBUG_CARD) ++ dev_info(&wc->vb.pdev->dev, ++ "fxs_off_hook: Card %d Going off hook\n", mod->card); ++ switch (fxs->lasttxhook) { ++ case SLIC_LF_RINGING: /* Ringing */ ++ case SLIC_LF_OHTRAN_FWD: /* Forward On Hook Transfer */ ++ case SLIC_LF_OHTRAN_REV: /* Reverse On Hook Transfer */ ++ /* just detected OffHook, during Ringing or OnHookTransfer */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ break; ++ } ++ if ((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN) ++ wctdm_fxs_hooksig(wc, mod, DAHDI_TXSIG_OFFHOOK); ++ dahdi_hooksig(get_dahdi_chan(wc, mod), DAHDI_RXSIG_OFFHOOK); ++ ++#ifdef DEBUG ++ if (robust) ++ wctdm_init_proslic(wc, mod, 1, 0, 1); ++#endif ++} ++ ++/** ++ * wctdm_fxs_on_hook - Report on hook to DAHDI. ++ * @wc: Board hosting the module. ++ * @card: Index of the module / port to place on hook. ++ * ++ * If we are intentionally dropping battery to signal a forward ++ * disconnect we do not want to place the line "On-Hook". In this ++ * case, the core of DAHDI will place us on hook when one of the RBS ++ * timers expires. ++ * ++ */ ++static void wctdm_fxs_on_hook(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "fxs_on_hook: Card %d Going on hook\n", mod->card); ++ } ++ ++ if ((mod->mod.fxs.lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN) ++ wctdm_fxs_hooksig(wc, mod, DAHDI_TXSIG_ONHOOK); ++ dahdi_hooksig(get_dahdi_chan(wc, mod), DAHDI_RXSIG_ONHOOK); ++} ++ ++static const char *wctdm_echocan_name(const struct dahdi_chan *chan) ++{ ++ struct wctdm *wc = chan->pvt; ++ if (wc->vpmadt032) ++ return vpmadt032_name; ++ else if (wc->vpmoct) ++ return vpmoct_name; ++ ++ return NULL; ++} ++ ++static int wctdm_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ struct wctdm *wc = chan->pvt; ++ struct wctdm_chan *wchan = container_of(chan, struct wctdm_chan, chan); ++ const struct dahdi_echocan_ops *ops; ++ const struct dahdi_echocan_features *features; ++ enum adt_companding comp; ++ ++ ++#ifdef VPM_SUPPORT ++ if (!vpmsupport) ++ return -ENODEV; ++#endif ++ if (wc->vpmadt032) { ++ ops = &vpm_ec_ops; ++ features = &vpm_ec_features; ++ ++ *ec = &wchan->ec; ++ (*ec)->ops = ops; ++ (*ec)->features = *features; ++ ++ comp = (DAHDI_LAW_ALAW == chan->span->deflaw) ? ++ ADT_COMP_ALAW : ADT_COMP_ULAW; ++ ++ return vpmadt032_echocan_create(wc->vpmadt032, wchan->timeslot, ++ comp, ecp, p); ++ } else if (wc->vpmoct) { ++ ops = &vpm_ec_ops; ++ features = &vpm_ec_features; ++ ++ *ec = &wchan->ec; ++ (*ec)->ops = ops; ++ (*ec)->features = *features; ++ return vpmoct_echocan_create(wc->vpmoct, wchan->timeslot, ++ chan->span->deflaw); ++ } else { ++ return -ENODEV; ++ } ++} ++ ++static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) ++{ ++ struct wctdm *wc = chan->pvt; ++ struct wctdm_chan *wchan = container_of(chan, struct wctdm_chan, chan); ++ ++ if (wc->vpmadt032) { ++ memset(ec, 0, sizeof(*ec)); ++ vpmadt032_echocan_free(wc->vpmadt032, wchan->timeslot, ec); ++ } else if (wc->vpmoct) { ++ memset(ec, 0, sizeof(*ec)); ++ vpmoct_echocan_free(wc->vpmoct, wchan->timeslot); ++ } ++} ++ ++/* 1ms interrupt */ ++static void wctdm_isr_misc_fxs(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ if (time_after(wc->framecount, fxs->check_alarm)) { ++ /* Accept an alarm once per 10 seconds */ ++ fxs->check_alarm = wc->framecount + (1000*10); ++ if (fxs->palarms) ++ fxs->palarms--; ++ } ++ ++ if (fxs->off_hook && !(fxs->hook_state_shadow & 1)) { ++ wctdm_fxs_on_hook(wc, mod); ++ fxs->off_hook = 0; ++ } else if (!fxs->off_hook && (fxs->hook_state_shadow & 1)) { ++ wctdm_fxs_off_hook(wc, mod); ++ fxs->off_hook = 1; ++ } ++ ++ wctdm_proslic_check_oppending(wc, mod); ++ ++ if (time_after(wc->framecount, fxs->check_proslic)) { ++ fxs->check_proslic = wc->framecount + 250; /* every 250ms */ ++ wctdm_proslic_recheck_sanity(wc, mod); ++ } ++ ++ if (SLIC_LF_RINGING == fxs->lasttxhook) { ++ /* RINGing, prepare for OHT */ ++ fxs->ohttimer = wc->framecount + OHT_TIMER; ++ /* OHT mode when idle */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? SLIC_LF_OHTRAN_REV : ++ SLIC_LF_OHTRAN_FWD; ++ } else if (fxs->oht_active) { ++ /* check if still OnHook */ ++ if (!fxs->off_hook) { ++ if (time_before(wc->framecount, fxs->ohttimer)) ++ return; ++ ++ /* Switch to active */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ spin_lock(&wc->reglock); ++ if (SLIC_LF_OHTRAN_FWD == fxs->lasttxhook) { ++ /* Apply the change if appropriate */ ++ fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_ACTIVE_FWD; ++ /* Data enqueued here */ ++ mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d OnHookTransfer " ++ "stop\n", mod->card); ++ } ++ } else if (SLIC_LF_OHTRAN_REV == fxs->lasttxhook) { ++ /* Apply the change if appropriate */ ++ fxs->lasttxhook = SLIC_LF_OPPENDING | SLIC_LF_ACTIVE_REV; ++ /* Data enqueued here */ ++ mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d OnHookTransfer " ++ "stop\n", mod->card); ++ } ++ } ++ spin_unlock(&wc->reglock); ++ } else { ++ fxs->oht_active = 0; ++ /* Switch to active */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD; ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d OnHookTransfer abort\n", ++ mod->card); ++ } ++ } ++ ++ } ++} ++ ++/* 1ms interrupt */ ++static inline void wctdm_isr_misc(struct wctdm *wc) ++{ ++ int x; ++ ++ if (unlikely(!is_initialized(wc))) ++ return; ++ ++ for (x = 0; x < wc->mods_per_board; x++) { ++ struct wctdm_module *const mod = &wc->mods[x]; ++ ++ spin_lock(&wc->reglock); ++ cmd_checkisr(wc, mod); ++ spin_unlock(&wc->reglock); ++ ++ switch (mod->type) { ++ case FXS: ++ wctdm_isr_misc_fxs(wc, mod); ++ break; ++ case FXO: ++ wctdm_voicedaa_check_hook(wc, mod); ++ break; ++ case QRV: ++ wctdm_qrvdri_check_hook(wc, x); ++ break; ++ default: ++ break; ++ } ++ } ++} ++ ++static void handle_receive(struct voicebus *vb, struct list_head *buffers) ++{ ++ struct wctdm *wc = container_of(vb, struct wctdm, vb); ++ struct vbb *vbb; ++ list_for_each_entry(vbb, buffers, entry) ++ wctdm_receiveprep(wc, vbb->data); ++} ++ ++static void handle_transmit(struct voicebus *vb, struct list_head *buffers) ++{ ++ struct wctdm *wc = container_of(vb, struct wctdm, vb); ++ struct vbb *vbb; ++ ++ list_for_each_entry(vbb, buffers, entry) { ++ memset(vbb->data, 0, sizeof(vbb->data)); ++ wctdm_transmitprep(wc, vbb->data); ++ wctdm_isr_misc(wc); ++ wc->framecount++; ++ } ++} ++ ++struct sframe_packet { ++ struct list_head node; ++ u8 sframe[SFRAME_SIZE]; ++}; ++ ++/** ++ * handle_hx8_bootmode_receive() - queue up the receive packet for later... ++ * ++ * This function is called from interrupt context and isn't optimal, but it's ++ * not the main code path. ++ */ ++static void handle_hx8_bootmode_receive(struct wctdm *wc, const void *vbb) ++{ ++ struct sframe_packet *frame; ++ ++ frame = kzalloc(sizeof(*frame), GFP_ATOMIC); ++ if (unlikely(!frame)) { ++ WARN_ON(1); ++ return; ++ } ++ ++ memcpy(frame->sframe, vbb, sizeof(frame->sframe)); ++ spin_lock(&wc->frame_list_lock); ++ list_add_tail(&frame->node, &wc->frame_list); ++ spin_unlock(&wc->frame_list_lock); ++ ++ /* Wake up anyone waiting for a new packet. */ ++ wake_up(&wc->regq); ++ return; ++} ++ ++static void handle_hx8_receive(struct voicebus *vb, struct list_head *buffers) ++{ ++ struct wctdm *wc = container_of(vb, struct wctdm, vb); ++ struct vbb *vbb; ++ list_for_each_entry(vbb, buffers, entry) ++ handle_hx8_bootmode_receive(wc, vbb->data); ++} ++ ++static void handle_hx8_transmit(struct voicebus *vb, struct list_head *buffers) ++{ ++ struct vbb *vbb, *n; ++ ++ list_for_each_entry_safe(vbb, n, buffers, entry) { ++ list_del(&vbb->entry); ++ dma_pool_free(vb->pool, vbb, vbb->dma_addr); ++ } ++} ++ ++static int wctdm_voicedaa_insane(struct wctdm *wc, struct wctdm_module *mod) ++{ ++ int blah; ++ blah = wctdm_getreg(wc, mod, 2); ++ if (blah != 0x3) ++ return -2; ++ blah = wctdm_getreg(wc, mod, 11); ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "VoiceDAA System: %02x\n", blah & 0xf); ++ } ++ return 0; ++} ++ ++static int ++wctdm_proslic_insane(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ int blah, reg1, insane_report; ++ insane_report=0; ++ ++ blah = wctdm_getreg(wc, mod, 0); ++ if (blah != 0xff && (debug & DEBUG_CARD)) { ++ dev_info(&wc->vb.pdev->dev, ++ "ProSLIC on module %d, product %d, " ++ "version %d\n", mod->card, (blah & 0x30) >> 4, ++ (blah & 0xf)); ++ } ++ ++#if 0 ++ if ((blah & 0x30) >> 4) { ++ dev_info(&wc->vb.pdev->dev, ++ "ProSLIC on module %d is not a 3210.\n", mod->card); ++ return -1; ++ } ++#endif ++ if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { ++ /* SLIC not loaded */ ++ return -1; ++ } ++ ++ /* let's be really sure this is an FXS before we continue */ ++ reg1 = wctdm_getreg(wc, mod, 1); ++ if ((0x80 != (blah & 0xf0)) || (0x88 != reg1)) { ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "DEBUG: not FXS b/c reg0=%x or " ++ "reg1 != 0x88 (%x).\n", blah, reg1); ++ } ++ return -1; ++ } ++ ++ blah = wctdm_getreg(wc, mod, 8); ++ if (blah != 0x2) { ++ dev_notice(&wc->vb.pdev->dev, ++ "ProSLIC on module %d insane (1) %d should be 2\n", ++ mod->card, blah); ++ return -1; ++ } else if (insane_report) { ++ dev_notice(&wc->vb.pdev->dev, ++ "ProSLIC on module %d Reg 8 Reads %d Expected " ++ "is 0x2\n", mod->card, blah); ++ } ++ ++ blah = wctdm_getreg(wc, mod, 64); ++ if (blah != 0x0) { ++ dev_notice(&wc->vb.pdev->dev, ++ "ProSLIC on module %d insane (2)\n", ++ mod->card); ++ return -1; ++ } else if (insane_report) { ++ dev_notice(&wc->vb.pdev->dev, ++ "ProSLIC on module %d Reg 64 Reads %d Expected " ++ "is 0x0\n", mod->card, blah); ++ } ++ ++ blah = wctdm_getreg(wc, mod, 11); ++ if (blah != 0x33) { ++ dev_notice(&wc->vb.pdev->dev, ++ "ProSLIC on module %d insane (3)\n", mod->card); ++ return -1; ++ } else if (insane_report) { ++ dev_notice(&wc->vb.pdev->dev, ++ "ProSLIC on module %d Reg 11 Reads %d " ++ "Expected is 0x33\n", mod->card, blah); ++ } ++ ++ /* Just be sure it's setup right. */ ++ wctdm_setreg(wc, mod, 30, 0); ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "ProSLIC on module %d seems sane.\n", mod->card); ++ } ++ return 0; ++} ++ ++static int ++wctdm_proslic_powerleak_test(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ unsigned long start; ++ unsigned char vbat; ++ ++ /* Turn off linefeed */ ++ wctdm_setreg(wc, mod, LINE_STATE, 0); ++ ++ /* Power down */ ++ wctdm_setreg(wc, mod, 14, 0x10); ++ ++ start = jiffies; ++ ++ /* TODO: Why is this sleep necessary. Without it, the first read ++ * comes back with a 0 value. */ ++ msleep(20); ++ ++ while ((vbat = wctdm_getreg(wc, mod, 82)) > 0x6) { ++ if (time_after(jiffies, start + HZ/4)) ++ break; ++ } ++ ++ if (vbat < 0x06) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Excessive leakage detected on module %d: %d " ++ "volts (%02x) after %d ms\n", mod->card, ++ 376 * vbat / 1000, vbat, ++ (int)((jiffies - start) * 1000 / HZ)); ++ return -1; ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Post-leakage voltage: %d volts\n", 376 * vbat / 1000); ++ } ++ return 0; ++} ++ ++static int wctdm_powerup_proslic(struct wctdm *wc, ++ struct wctdm_module *mod, int fast) ++{ ++ unsigned char vbat; ++ unsigned long origjiffies; ++ int lim; ++ ++ /* Set period of DC-DC converter to 1/64 khz */ ++ wctdm_setreg(wc, mod, 92, 0xc0 /* was 0xff */); ++ ++ /* Wait for VBat to powerup */ ++ origjiffies = jiffies; ++ ++ /* Disable powerdown */ ++ wctdm_setreg(wc, mod, 14, 0); ++ ++ /* If fast, don't bother checking anymore */ ++ if (fast) ++ return 0; ++ ++ while ((vbat = wctdm_getreg(wc, mod, 82)) < 0xc0) { ++ /* Wait no more than 500ms */ ++ if ((jiffies - origjiffies) > HZ/2) { ++ break; ++ } ++ } ++ ++ if (vbat < 0xc0) { ++ dev_notice(&wc->vb.pdev->dev, "ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM CARD??\n", ++ mod->card, (int)(((jiffies - origjiffies) * 1000 / HZ)), ++ vbat * 375); ++ return -1; ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "ProSLIC on module %d powered up to -%d volts (%02x) " ++ "in %d ms\n", mod->card, vbat * 376 / 1000, vbat, ++ (int)(((jiffies - origjiffies) * 1000 / HZ))); ++ } ++ ++ /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */ ++ /* If out of range, just set it to the default value */ ++ lim = (loopcurrent - 20) / 3; ++ if ( loopcurrent > 41 ) { ++ lim = 0; ++ if (debug & DEBUG_CARD) ++ dev_info(&wc->vb.pdev->dev, "Loop current out of range! Setting to default 20mA!\n"); ++ } ++ else if (debug & DEBUG_CARD) ++ dev_info(&wc->vb.pdev->dev, "Loop current set to %dmA!\n",(lim*3)+20); ++ wctdm_setreg(wc, mod, LOOP_I_LIMIT, lim); ++ ++ /* Engage DC-DC converter */ ++ wctdm_setreg(wc, mod, 93, 0x19 /* was 0x19 */); ++ return 0; ++ ++} ++ ++static int ++wctdm_proslic_manual_calibrate(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ unsigned long origjiffies; ++ unsigned char i; ++ ++ /* Disable all interupts in DR21-23 */ ++ wctdm_setreg(wc, mod, 21, 0); ++ wctdm_setreg(wc, mod, 22, 0); ++ wctdm_setreg(wc, mod, 23, 0); ++ ++ wctdm_setreg(wc, mod, 64, 0); ++ ++ /* (0x18) Calibrations without the ADC and DAC offset and without ++ * common mode calibration. */ ++ wctdm_setreg(wc, mod, 97, 0x18); ++ ++ /* (0x47) Calibrate common mode and differential DAC mode DAC + ILIM */ ++ wctdm_setreg(wc, mod, 96, 0x47); ++ ++ origjiffies=jiffies; ++ while (wctdm_getreg(wc, mod, 96) != 0) { ++ if ((jiffies-origjiffies) > 80) ++ return -1; ++ } ++//Initialized DR 98 and 99 to get consistant results. ++// 98 and 99 are the results registers and the search should have same intial conditions. ++ ++/*******************************The following is the manual gain mismatch calibration****************************/ ++/*******************************This is also available as a function *******************************************/ ++ msleep(10); ++ wctdm_proslic_setreg_indirect(wc, mod, 88, 0); ++ wctdm_proslic_setreg_indirect(wc, mod, 89, 0); ++ wctdm_proslic_setreg_indirect(wc, mod, 90, 0); ++ wctdm_proslic_setreg_indirect(wc, mod, 91, 0); ++ wctdm_proslic_setreg_indirect(wc, mod, 92, 0); ++ wctdm_proslic_setreg_indirect(wc, mod, 93, 0); ++ ++ /* This is necessary if the calibration occurs other than at reset */ ++ wctdm_setreg(wc, mod, 98, 0x10); ++ wctdm_setreg(wc, mod, 99, 0x10); ++ ++ for ( i=0x1f; i>0; i--) ++ { ++ wctdm_setreg(wc, mod, 98, i); ++ msleep(40); ++ if ((wctdm_getreg(wc, mod, 88)) == 0) ++ break; ++ } // for ++ ++ for ( i=0x1f; i>0; i--) ++ { ++ wctdm_setreg(wc, mod, 99, i); ++ msleep(40); ++ if ((wctdm_getreg(wc, mod, 89)) == 0) ++ break; ++ }//for ++ ++/*******************************The preceding is the manual gain mismatch calibration****************************/ ++/**********************************The following is the longitudinal Balance Cal***********************************/ ++ wctdm_setreg(wc, mod, 64, 1); ++ msleep(100); ++ ++ wctdm_setreg(wc, mod, 64, 0); ++ ++ /* enable interrupt for the balance Cal */ ++ wctdm_setreg(wc, mod, 23, 0x4); ++ ++ /* this is a singular calibration bit for longitudinal calibration */ ++ wctdm_setreg(wc, mod, 97, 0x1); ++ wctdm_setreg(wc, mod, 96, 0x40); ++ ++ wctdm_getreg(wc, mod, 96); /* Read Reg 96 just cause */ ++ ++ wctdm_setreg(wc, mod, 21, 0xFF); ++ wctdm_setreg(wc, mod, 22, 0xFF); ++ wctdm_setreg(wc, mod, 23, 0xFF); ++ ++ /**The preceding is the longitudinal Balance Cal***/ ++ return(0); ++ ++} ++ ++static int ++wctdm_proslic_calibrate(struct wctdm *wc, struct wctdm_module *mod) ++{ ++ unsigned long origjiffies; ++ int x; ++ ++ /* Perform all calibrations */ ++ wctdm_setreg(wc, mod, 97, 0x1f); ++ ++ /* Begin, no speedup */ ++ wctdm_setreg(wc, mod, 96, 0x5f); ++ ++ /* Wait for it to finish */ ++ origjiffies = jiffies; ++ while (wctdm_getreg(wc, mod, 96)) { ++ if (time_after(jiffies, (origjiffies + (2*HZ)))) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Timeout waiting for calibration of " ++ "module %d\n", mod->card); ++ return -1; ++ } ++ } ++ ++ if (debug & DEBUG_CARD) { ++ /* Print calibration parameters */ ++ dev_info(&wc->vb.pdev->dev, ++ "Calibration Vector Regs 98 - 107:\n"); ++ for (x=98;x<108;x++) { ++ dev_info(&wc->vb.pdev->dev, ++ "%d: %02x\n", x, wctdm_getreg(wc, mod, x)); ++ } ++ } ++ return 0; ++} ++ ++/********************************************************************* ++ * Set the hwgain on the analog modules ++ * ++ * card = the card position for this module (0-23) ++ * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35) ++ * tx = (0 for rx; 1 for tx) ++ * ++ *******************************************************************/ ++static int ++wctdm_set_hwgain(struct wctdm *wc, struct wctdm_module *mod, ++ __s32 gain, __u32 tx) ++{ ++ if (mod->type != FXO) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Cannot adjust gain. Unsupported module type!\n"); ++ return -1; ++ } ++ ++ if (tx) { ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "setting FXO tx gain for card=%d to %d\n", ++ mod->card, gain); ++ } ++ if (gain >= -150 && gain <= 0) { ++ wctdm_setreg(wc, mod, 38, 16 + (gain / -10)); ++ wctdm_setreg(wc, mod, 40, 16 + (-gain % 10)); ++ } else if (gain <= 120 && gain > 0) { ++ wctdm_setreg(wc, mod, 38, gain/10); ++ wctdm_setreg(wc, mod, 40, (gain%10)); ++ } else { ++ dev_notice(&wc->vb.pdev->dev, ++ "FXO tx gain is out of range (%d)\n", gain); ++ return -1; ++ } ++ } else { /* rx */ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "setting FXO rx gain for card=%d to %d\n", ++ mod->card, gain); ++ } ++ if (gain >= -150 && gain <= 0) { ++ wctdm_setreg(wc, mod, 39, 16 + (gain / -10)); ++ wctdm_setreg(wc, mod, 41, 16 + (-gain % 10)); ++ } else if (gain <= 120 && gain > 0) { ++ wctdm_setreg(wc, mod, 39, gain/10); ++ wctdm_setreg(wc, mod, 41, (gain%10)); ++ } else { ++ dev_notice(&wc->vb.pdev->dev, ++ "FXO rx gain is out of range (%d)\n", gain); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int set_lasttxhook_interruptible(struct wctdm *wc, struct fxs *fxs, ++ unsigned newval, int *psethook) ++{ ++ int res = 0; ++ unsigned long flags; ++ int timeout = 0; ++ ++ do { ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (SLIC_LF_OPPENDING & fxs->lasttxhook) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ if (timeout++ > 100) ++ return -1; ++ msleep(1); ++ } else { ++ fxs->lasttxhook = (newval & SLIC_LF_SETMASK) | SLIC_LF_OPPENDING; ++ *psethook = CMD_WR(LINE_STATE, fxs->lasttxhook); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ } ++ } while (1); ++ ++ return res; ++} ++ ++/* Must be called from within an interruptible context */ ++static int set_vmwi(struct wctdm *wc, struct wctdm_module *const mod) ++{ ++ int x; ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ /* Presently only supports line reversal MWI */ ++ if ((fxs->vmwi_active_messages) && ++ (fxs->vmwisetting.vmwi_type & DAHDI_VMWI_LREV)) ++ fxs->vmwi_linereverse = 1; ++ else ++ fxs->vmwi_linereverse = 0; ++ ++ /* Set line polarity for new VMWI state */ ++ if (POLARITY_XOR(fxs)) { ++ fxs->idletxhookstate |= SLIC_LF_REVMASK; ++ /* Do not set while currently ringing or open */ ++ if (((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_RINGING) && ++ ((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN)) { ++ x = fxs->lasttxhook; ++ x |= SLIC_LF_REVMASK; ++ set_lasttxhook_interruptible(wc, fxs, x, &mod->sethook); ++ } ++ } else { ++ fxs->idletxhookstate &= ~SLIC_LF_REVMASK; ++ /* Do not set while currently ringing or open */ ++ if (((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_RINGING) && ++ ((fxs->lasttxhook & SLIC_LF_SETMASK) != SLIC_LF_OPEN)) { ++ x = fxs->lasttxhook; ++ x &= ~SLIC_LF_REVMASK; ++ set_lasttxhook_interruptible(wc, fxs, x, &mod->sethook); ++ } ++ } ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "Setting VMWI on channel %d, messages=%d, lrev=%d\n", ++ mod->card, fxs->vmwi_active_messages, ++ fxs->vmwi_linereverse); ++ } ++ return 0; ++} ++ ++static void ++wctdm_voicedaa_set_ts(struct wctdm *wc, struct wctdm_module *mod, int ts) ++{ ++ wctdm_setreg(wc, mod, 34, (ts * 8) & 0xff); ++ wctdm_setreg(wc, mod, 35, (ts * 8) >> 8); ++ wctdm_setreg(wc, mod, 36, (ts * 8) & 0xff); ++ wctdm_setreg(wc, mod, 37, (ts * 8) >> 8); ++ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "voicedaa: card %d new timeslot: %d\n", ++ mod->card + 1, ts); ++ } ++} ++ ++static int ++wctdm_init_voicedaa(struct wctdm *wc, struct wctdm_module *mod, ++ int fast, int manual, int sane) ++{ ++ unsigned char reg16=0, reg26=0, reg30=0, reg31=0; ++ unsigned long flags; ++ long newjiffies; ++ ++#if 0 /* TODO */ ++ if ((wc->mods[card & 0xfc].type == QRV) || ++ (wc->mods[card & 0xfc].type == BRI)) ++ return -2; ++#endif ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->type = NONE; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ msleep(20); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->type = FXO; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ msleep(20); ++ ++ memset(&mod->mod.fxo, 0, sizeof(mod->mod.fxo)); ++ ++ if (!sane && wctdm_voicedaa_insane(wc, mod)) ++ return -2; ++ ++ /* Software reset */ ++ wctdm_setreg(wc, mod, 1, 0x80); ++ msleep(100); ++ ++ /* Set On-hook speed, Ringer impedence, and ringer threshold */ ++ reg16 |= (fxo_modes[_opermode].ohs << 6); ++ reg16 |= (fxo_modes[_opermode].rz << 1); ++ reg16 |= (fxo_modes[_opermode].rt); ++ wctdm_setreg(wc, mod, 16, reg16); ++ ++ /* Enable ring detector full-wave rectifier mode */ ++ wctdm_setreg(wc, mod, 18, 2); ++ wctdm_setreg(wc, mod, 24, 0); ++ ++ /* Set DC Termination: ++ Tip/Ring voltage adjust, minimum operational current, current limitation */ ++ reg26 |= (fxo_modes[_opermode].dcv << 6); ++ reg26 |= (fxo_modes[_opermode].mini << 4); ++ reg26 |= (fxo_modes[_opermode].ilim << 1); ++ wctdm_setreg(wc, mod, 26, reg26); ++ ++ /* Set AC Impedence */ ++ reg30 = (fxo_modes[_opermode].acim); ++ wctdm_setreg(wc, mod, 30, reg30); ++ ++ /* Misc. DAA parameters */ ++ ++ /* If fast pickup is set, then the off hook counter will be set to 8 ++ * ms, otherwise 128 ms. */ ++ reg31 = (fastpickup) ? 0xe3 : 0xa3; ++ ++ reg31 |= (fxo_modes[_opermode].ohs2 << 3); ++ wctdm_setreg(wc, mod, 31, reg31); ++ ++ wctdm_voicedaa_set_ts(wc, mod, mod->card); ++ ++ /* Enable ISO-Cap */ ++ wctdm_setreg(wc, mod, 6, 0x00); ++ ++ /* Turn off the calibration delay when fastpickup is enabled. */ ++ if (fastpickup) ++ wctdm_setreg(wc, mod, 17, wctdm_getreg(wc, mod, 17) | 0x20); ++ ++ /* Wait 1000ms for ISO-cap to come up */ ++ newjiffies = jiffies; ++ newjiffies += 2 * HZ; ++ ++ while ((jiffies < newjiffies) && !(wctdm_getreg(wc, mod, 11) & 0xf0)) ++ msleep(100); ++ ++ if (!(wctdm_getreg(wc, mod, 11) & 0xf0)) { ++ dev_notice(&wc->vb.pdev->dev, "VoiceDAA did not bring up ISO link properly!\n"); ++ return -1; ++ } ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, "ISO-Cap is now up, line side: %02x rev %02x\n", ++ wctdm_getreg(wc, mod, 11) >> 4, ++ (wctdm_getreg(wc, mod, 13) >> 2) & 0xf); ++ } ++ ++ /* Enable on-hook line monitor */ ++ wctdm_setreg(wc, mod, 5, 0x08); ++ ++ /* Take values for fxotxgain and fxorxgain and apply them to module */ ++ wctdm_set_hwgain(wc, mod, fxotxgain, 1); ++ wctdm_set_hwgain(wc, mod, fxorxgain, 0); ++ ++#ifdef DEBUG ++ if (digitalloopback) { ++ dev_info(&wc->vb.pdev->dev, ++ "Turning on digital loopback for port %d.\n", ++ mod->card + 1); ++ wctdm_setreg(wc, mod, 10, 0x01); ++ } ++#endif ++ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", ++ (wctdm_getreg(wc, mod, 38)/16) ? ++ -(wctdm_getreg(wc, mod, 38) - 16) : ++ wctdm_getreg(wc, mod, 38), ++ (wctdm_getreg(wc, mod, 40)/16) ? ++ -(wctdm_getreg(wc, mod, 40) - 16) : ++ wctdm_getreg(wc, mod, 40), ++ (wctdm_getreg(wc, mod, 39)/16) ? ++ -(wctdm_getreg(wc, mod, 39) - 16) : ++ wctdm_getreg(wc, mod, 39), ++ (wctdm_getreg(wc, mod, 41)/16) ? ++ -(wctdm_getreg(wc, mod, 41) - 16) : ++ wctdm_getreg(wc, mod, 41)); ++ } ++ ++ return 0; ++} ++ ++static void ++wctdm_proslic_set_ts(struct wctdm *wc, struct wctdm_module *mod, int ts) ++{ ++ wctdm_setreg(wc, mod, 2, (ts * 8) & 0xff); /* Tx Start low byte 0 */ ++ wctdm_setreg(wc, mod, 3, (ts * 8) >> 8); /* Tx Start high byte 0 */ ++ wctdm_setreg(wc, mod, 4, (ts * 8) & 0xff); /* Rx Start low byte 0 */ ++ wctdm_setreg(wc, mod, 5, (ts * 8) >> 8); /* Rx Start high byte 0 */ ++ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "proslic: card %d new timeslot: %d\n", ++ mod->card + 1, ts); ++ } ++} ++ ++static int ++wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod, ++ int fast, int manual, int sane) ++{ ++ ++ struct fxs *const fxs = &mod->mod.fxs; ++ unsigned short tmp[5]; ++ unsigned long flags; ++ unsigned char r19,r9; ++ int x; ++ int fxsmode=0; ++ int addresses[NUM_CAL_REGS]; ++ ++#if 0 /* TODO */ ++ if (wc->mods[mod->card & 0xfc].type == QRV) ++ return -2; ++#endif ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->type = FXS; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* msleep(100); */ ++ ++ /* Sanity check the ProSLIC */ ++ if (!sane && wctdm_proslic_insane(wc, mod)) ++ return -2; ++ ++ /* Initialize VMWI settings */ ++ memset(fxs, 0, sizeof(*fxs)); ++ ++ /* By default, don't send on hook */ ++ if (!reversepolarity != !fxs->reversepolarity) ++ fxs->idletxhookstate = SLIC_LF_ACTIVE_REV; ++ else ++ fxs->idletxhookstate = SLIC_LF_ACTIVE_FWD; ++ ++ if (sane) { ++ /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ ++ wctdm_setreg(wc, mod, 14, 0x10); ++ } ++ ++ if (wctdm_proslic_init_indirect_regs(wc, mod)) { ++ dev_info(&wc->vb.pdev->dev, ++ "Indirect Registers failed to initialize on " ++ "module %d.\n", mod->card); ++ return -1; ++ } ++ ++ /* Clear scratch pad area */ ++ wctdm_proslic_setreg_indirect(wc, mod, 97, 0); ++ ++ /* Clear digital loopback */ ++ wctdm_setreg(wc, mod, 8, 0); ++ ++ /* Revision C optimization */ ++ wctdm_setreg(wc, mod, 108, 0xeb); ++ ++ /* Disable automatic VBat switching for safety to prevent ++ * Q7 from accidently turning on and burning out. ++ * If pulse dialing has trouble at high REN loads change this to 0x17 */ ++ wctdm_setreg(wc, mod, 67, 0x07); ++ ++ /* Turn off Q7 */ ++ wctdm_setreg(wc, mod, 66, 1); ++ ++ /* Flush ProSLIC digital filters by setting to clear, while ++ saving old values */ ++ for (x=0;x<5;x++) { ++ tmp[x] = wctdm_proslic_getreg_indirect(wc, mod, x + 35); ++ wctdm_proslic_setreg_indirect(wc, mod, x + 35, 0x8000); ++ } ++ ++ /* Power up the DC-DC converter */ ++ if (wctdm_powerup_proslic(wc, mod, fast)) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Unable to do INITIAL ProSLIC powerup on " ++ "module %d\n", mod->card); ++ return -1; ++ } ++ ++ if (!fast) { ++ /* Check for power leaks */ ++ if (wctdm_proslic_powerleak_test(wc, mod)) { ++ dev_notice(&wc->vb.pdev->dev, ++ "ProSLIC module %d failed leakage test. " ++ "Check for short circuit\n", mod->card); ++ } ++ /* Power up again */ ++ if (wctdm_powerup_proslic(wc, mod, fast)) { ++ dev_notice(&wc->vb.pdev->dev, ++ "Unable to do FINAL ProSLIC powerup on " ++ "module %d\n", mod->card); ++ return -1; ++ } ++#ifndef NO_CALIBRATION ++ /* Perform calibration */ ++ if (manual) { ++ if (wctdm_proslic_manual_calibrate(wc, mod)) { ++ //dev_notice(&wc->vb.pdev->dev, "Proslic failed on Manual Calibration\n"); ++ if (wctdm_proslic_manual_calibrate(wc, mod)) { ++ dev_notice(&wc->vb.pdev->dev, "Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); ++ return -1; ++ } ++ dev_info(&wc->vb.pdev->dev, "Proslic Passed Manual Calibration on Second Attempt\n"); ++ } ++ } ++ else { ++ if (wctdm_proslic_calibrate(wc, mod)) { ++ //dev_notice(&wc->vb.pdev->dev, "ProSlic died on Auto Calibration.\n"); ++ if (wctdm_proslic_calibrate(wc, mod)) { ++ dev_notice(&wc->vb.pdev->dev, "Proslic Failed on Second Attempt to Auto Calibrate\n"); ++ return -1; ++ } ++ dev_info(&wc->vb.pdev->dev, "Proslic Passed Auto Calibration on Second Attempt\n"); ++ } ++ } ++ /* Perform DC-DC calibration */ ++ wctdm_setreg(wc, mod, 93, 0x99); ++ r19 = wctdm_getreg(wc, mod, 107); ++ if ((r19 < 0x2) || (r19 > 0xd)) { ++ dev_notice(&wc->vb.pdev->dev, "DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); ++ wctdm_setreg(wc, mod, 107, 0x8); ++ } ++ ++ /* Save calibration vectors */ ++ for (x = 0; x < NUM_CAL_REGS; x++) ++ addresses[x] = 96 + x; ++ wctdm_getregs(wc, mod, addresses, ARRAY_SIZE(addresses)); ++ for (x = 0; x < NUM_CAL_REGS; x++) ++ fxs->calregs.vals[x] = addresses[x]; ++#endif ++ ++ } else { ++ /* Restore calibration registers */ ++ for (x = 0; x < NUM_CAL_REGS; x++) ++ wctdm_setreg(wc, mod, 96 + x, fxs->calregs.vals[x]); ++ } ++ /* Calibration complete, restore original values */ ++ for (x=0;x<5;x++) { ++ wctdm_proslic_setreg_indirect(wc, mod, x + 35, tmp[x]); ++ } ++ ++ if (wctdm_proslic_verify_indirect_regs(wc, mod)) { ++ dev_info(&wc->vb.pdev->dev, "Indirect Registers failed verification.\n"); ++ return -1; ++ } ++ ++ ++#if 0 ++ /* Disable Auto Power Alarm Detect and other "features" */ ++ wctdm_setreg(wc, card, 67, 0x0e); ++ blah = wctdm_getreg(wc, card, 67); ++#endif ++ ++#if 0 ++ if (wctdm_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix ++ dev_info(&wc->vb.pdev->dev, "ProSlic IndirectReg Died.\n"); ++ return -1; ++ } ++#endif ++ ++ /* U-Law 8-bit interface */ ++ wctdm_proslic_set_ts(wc, mod, mod->card); ++ ++ wctdm_setreg(wc, mod, 18, 0xff); /* clear all interrupt */ ++ wctdm_setreg(wc, mod, 19, 0xff); ++ wctdm_setreg(wc, mod, 20, 0xff); ++ wctdm_setreg(wc, mod, 22, 0xff); ++ wctdm_setreg(wc, mod, 73, 0x04); ++ ++ wctdm_setreg(wc, mod, 69, 0x4); ++ ++ if (fxshonormode) { ++ static const int ACIM2TISS[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, ++ 0x0, 0x0, 0x6, 0x0, 0x0, ++ 0x0, 0x2, 0x0, 0x3 }; ++ fxsmode = ACIM2TISS[fxo_modes[_opermode].acim]; ++ wctdm_setreg(wc, mod, 10, 0x08 | fxsmode); ++ if (fxo_modes[_opermode].ring_osc) { ++ wctdm_proslic_setreg_indirect(wc, mod, 20, ++ fxo_modes[_opermode].ring_osc); ++ } ++ if (fxo_modes[_opermode].ring_x) { ++ wctdm_proslic_setreg_indirect(wc, mod, 21, ++ fxo_modes[_opermode].ring_x); ++ } ++ } ++ if (lowpower) ++ wctdm_setreg(wc, mod, 72, 0x10); ++ ++#if 0 ++ wctdm_setreg(wc, card, 21, 0x00); // enable interrupt ++ wctdm_setreg(wc, card, 22, 0x02); // Loop detection interrupt ++ wctdm_setreg(wc, card, 23, 0x01); // DTMF detection interrupt ++#endif ++ ++#if 0 ++ /* Enable loopback */ ++ wctdm_setreg(wc, card, 8, 0x2); ++ wctdm_setreg(wc, card, 14, 0x0); ++ wctdm_setreg(wc, card, 64, 0x0); ++ wctdm_setreg(wc, card, 1, 0x08); ++#endif ++ ++ if (fastringer) { ++ /* Speed up Ringer */ ++ wctdm_proslic_setreg_indirect(wc, mod, 20, 0x7e6d); ++ wctdm_proslic_setreg_indirect(wc, mod, 21, 0x01b9); ++ /* Beef up Ringing voltage to 89V */ ++ if (boostringer) { ++ wctdm_setreg(wc, mod, 74, 0x3f); ++ if (wctdm_proslic_setreg_indirect(wc, mod, 21, 0x247)) ++ return -1; ++ dev_info(&wc->vb.pdev->dev, ++ "Boosting fast ringer on slot %d (89V peak)\n", ++ mod->card + 1); ++ } else if (lowpower) { ++ if (wctdm_proslic_setreg_indirect(wc, mod, 21, 0x14b)) ++ return -1; ++ dev_info(&wc->vb.pdev->dev, ++ "Reducing fast ring power on slot %d " ++ "(50V peak)\n", mod->card + 1); ++ } else ++ dev_info(&wc->vb.pdev->dev, ++ "Speeding up ringer on slot %d (25Hz)\n", ++ mod->card + 1); ++ } else { ++ /* Beef up Ringing voltage to 89V */ ++ if (boostringer) { ++ wctdm_setreg(wc, mod, 74, 0x3f); ++ if (wctdm_proslic_setreg_indirect(wc, mod, 21, 0x1d1)) ++ return -1; ++ dev_info(&wc->vb.pdev->dev, ++ "Boosting ringer on slot %d (89V peak)\n", ++ mod->card + 1); ++ } else if (lowpower) { ++ if (wctdm_proslic_setreg_indirect(wc, mod, 21, 0x108)) ++ return -1; ++ dev_info(&wc->vb.pdev->dev, ++ "Reducing ring power on slot %d " ++ "(50V peak)\n", mod->card + 1); ++ } ++ } ++ ++ if (fxstxgain || fxsrxgain) { ++ r9 = wctdm_getreg(wc, mod, 9); ++ switch (fxstxgain) { ++ ++ case 35: ++ r9+=8; ++ break; ++ case -35: ++ r9+=4; ++ break; ++ case 0: ++ break; ++ } ++ ++ switch (fxsrxgain) { ++ ++ case 35: ++ r9+=2; ++ break; ++ case -35: ++ r9+=1; ++ break; ++ case 0: ++ break; ++ } ++ wctdm_setreg(wc, mod, 9, r9); ++ } ++ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "DEBUG: fxstxgain:%s fxsrxgain:%s\n", ++ ((wctdm_getreg(wc, mod, 9) / 8) == 1) ? ++ "3.5" : (((wctdm_getreg(wc, mod, 9) / 4) == 1) ? ++ "-3.5" : "0.0"), ++ ((wctdm_getreg(wc, mod, 9) / 2) == 1) ? ++ "3.5" : ((wctdm_getreg(wc, mod, 9) % 2) ? ++ "-3.5" : "0.0")); ++ } ++ ++ fxs->lasttxhook = fxs->idletxhookstate; ++ wctdm_setreg(wc, mod, LINE_STATE, fxs->lasttxhook); ++ ++ /* Preset the shadow register so that we won't get a power alarm when ++ * we finish initialization, otherwise the line state register may not ++ * have been read yet. */ ++ fxs->linefeed_control_shadow = fxs->lasttxhook; ++ return 0; ++} ++ ++static void ++wctdm_qrvdri_set_ts(struct wctdm *wc, struct wctdm_module *mod, int ts) ++{ ++ wctdm_setreg(wc, mod, 0x13, ts + 0x80); /* codec 2 tx, ts0 */ ++ wctdm_setreg(wc, mod, 0x17, ts + 0x80); /* codec 0 rx, ts0 */ ++ wctdm_setreg(wc, mod, 0x14, ts + 0x81); /* codec 1 tx, ts1 */ ++ wctdm_setreg(wc, mod, 0x18, ts + 0x81); /* codec 1 rx, ts1 */ ++ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "qrvdri: card %d new timeslot: %d\n", ++ mod->card + 1, ts); ++ } ++} ++ ++static int wctdm_init_qrvdri(struct wctdm *wc, int card) ++{ ++ struct wctdm_module *const mod = &wc->mods[card]; ++ unsigned char x,y; ++ ++ if (BRI == wc->mods[card & 0xfc].type) ++ return -2; ++ ++ /* have to set this, at least for now */ ++ mod->type = QRV; ++ if (!(card & 3)) { /* if at base of card, reset and write it */ ++ struct qrv *const qrv = &mod->mod.qrv; ++ struct qrv *const qrv1 = &wc->mods[card + 1].mod.qrv; ++ struct qrv *const qrv2 = &wc->mods[card + 2].mod.qrv; ++ struct qrv *const qrv3 = &wc->mods[card + 3].mod.qrv; ++ ++ wctdm_setreg(wc, mod, 0, 0x80); ++ wctdm_setreg(wc, mod, 0, 0x55); ++ wctdm_setreg(wc, mod, 1, 0x69); ++ qrv->hook = qrv1->hook = 0; ++ qrv2->hook = qrv3->hook = 0xff; ++ qrv->debouncetime = qrv1->debouncetime = QRV_DEBOUNCETIME; ++ qrv->debtime = qrv1->debtime = 0; ++ qrv->radmode = qrv1->radmode = 0; ++ qrv->txgain = qrv1->txgain = 3599; ++ qrv->rxgain = qrv1->rxgain = 1199; ++ } else { /* channel is on same card as base, no need to test */ ++ if (wc->mods[card & 0x7c].type == QRV) { ++ /* only lower 2 are valid */ ++ if (!(card & 2)) ++ return 0; ++ } ++ mod->type = NONE; ++ return 1; ++ } ++ x = wctdm_getreg(wc, mod, 0); ++ y = wctdm_getreg(wc, mod, 1); ++ /* if not a QRV card, return as such */ ++ if ((x != 0x55) || (y != 0x69)) ++ { ++ mod->type = NONE; ++ return 1; ++ } ++ for (x = 0; x < 0x30; x++) { ++ if ((x >= 0x1c) && (x <= 0x1e)) ++ wctdm_setreg(wc, mod, x, 0xff); ++ else ++ wctdm_setreg(wc, mod, x, 0); ++ } ++ wctdm_setreg(wc, mod, 0, 0x80); ++ msleep(100); ++ wctdm_setreg(wc, mod, 0, 0x10); ++ wctdm_setreg(wc, mod, 0, 0x10); ++ msleep(100); ++ /* set up modes */ ++ wctdm_setreg(wc, mod, 0, 0x1c); ++ /* set up I/O directions */ ++ wctdm_setreg(wc, mod, 1, 0x33); ++ wctdm_setreg(wc, mod, 2, 0x0f); ++ wctdm_setreg(wc, mod, 5, 0x0f); ++ /* set up I/O to quiescent state */ ++ wctdm_setreg(wc, mod, 3, 0x11); /* D0-7 */ ++ wctdm_setreg(wc, mod, 4, 0xa); /* D8-11 */ ++ wctdm_setreg(wc, mod, 7, 0); /* CS outputs */ ++ ++ wctdm_qrvdri_set_ts(wc, mod, card); ++ ++ /* set up for max gains */ ++ wctdm_setreg(wc, mod, 0x26, 0x24); ++ wctdm_setreg(wc, mod, 0x27, 0x24); ++ wctdm_setreg(wc, mod, 0x0b, 0x01); /* "Transmit" gain codec 0 */ ++ wctdm_setreg(wc, mod, 0x0c, 0x01); /* "Transmit" gain codec 1 */ ++ wctdm_setreg(wc, mod, 0x0f, 0xff); /* "Receive" gain codec 0 */ ++ wctdm_setreg(wc, mod, 0x10, 0xff); /* "Receive" gain codec 1 */ ++ return 0; ++} ++ ++static void qrv_dosetup(struct dahdi_chan *chan, struct wctdm *wc) ++{ ++ struct wctdm_module *qrvmod; ++ struct wctdm_module *nextqrvmod; ++ int qrvcard; ++ unsigned char r; ++ long l; ++ ++ /* actually do something with the values */ ++ qrvcard = (chan->chanpos - 1) & 0xfc; ++ qrvmod = &wc->mods[qrvcard]; ++ nextqrvmod = &wc->mods[qrvcard + 1]; ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "@@@@@ radmodes: %d,%d rxgains: %d,%d " ++ "txgains: %d,%d\n", wc->mods[qrvcard].mod.qrv.radmode, ++ nextqrvmod->mod.qrv.radmode, ++ wc->mods[qrvcard].mod.qrv.rxgain, ++ nextqrvmod->mod.qrv.rxgain, ++ wc->mods[qrvcard].mod.qrv.txgain, ++ nextqrvmod->mod.qrv.txgain); ++ } ++ r = 0; ++ if (qrvmod->mod.qrv.radmode & RADMODE_DEEMP) ++ r |= 4; ++ if (nextqrvmod->mod.qrv.radmode & RADMODE_DEEMP) ++ r |= 8; ++ if (qrvmod->mod.qrv.rxgain < 1200) ++ r |= 1; ++ if (nextqrvmod->mod.qrv.rxgain < 1200) ++ r |= 2; ++ wctdm_setreg(wc, qrvmod, 7, r); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 7 to %02x hex\n",r); ++ r = 0; ++ if (qrvmod->mod.qrv.radmode & RADMODE_PREEMP) ++ r |= 3; ++ else if (qrvmod->mod.qrv.txgain >= 3600) ++ r |= 1; ++ else if (qrvmod->mod.qrv.txgain >= 1200) ++ r |= 2; ++ if (nextqrvmod->mod.qrv.radmode & RADMODE_PREEMP) ++ r |= 0xc; ++ else if (nextqrvmod->mod.qrv.txgain >= 3600) ++ r |= 4; ++ else if (nextqrvmod->mod.qrv.txgain >= 1200) ++ r |= 8; ++ wctdm_setreg(wc, qrvmod, 4, r); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 4 to %02x hex\n",r); ++ r = 0; ++ if (qrvmod->mod.qrv.rxgain >= 2400) ++ r |= 1; ++ if (nextqrvmod->mod.qrv.rxgain >= 2400) ++ r |= 2; ++ wctdm_setreg(wc, qrvmod, 0x25, r); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 0x25 to %02x hex\n",r); ++ r = 0; ++ if (qrvmod->mod.qrv.txgain < 2400) ++ r |= 1; ++ else ++ r |= 4; ++ if (nextqrvmod->mod.qrv.txgain < 2400) ++ r |= 8; ++ else ++ r |= 0x20; ++ wctdm_setreg(wc, qrvmod, 0x26, r); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 0x26 to %02x hex\n",r); ++ l = ((long)(qrvmod->mod.qrv.rxgain % 1200) * 10000) / 46875; ++ if (l == 0) l = 1; ++ if (qrvmod->mod.qrv.rxgain >= 2400) ++ l += 181; ++ wctdm_setreg(wc, qrvmod, 0x0b, (unsigned char)l); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 0x0b to %02x hex\n",(unsigned char)l); ++ l = ((long)(nextqrvmod->mod.qrv.rxgain % 1200) * 10000) / 46875; ++ if (l == 0) l = 1; ++ if (nextqrvmod->mod.qrv.rxgain >= 2400) ++ l += 181; ++ wctdm_setreg(wc, qrvmod, 0x0c, (unsigned char)l); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 0x0c to %02x hex\n",(unsigned char)l); ++ l = ((long)(qrvmod->mod.qrv.txgain % 1200) * 10000) / 46875; ++ if (l == 0) l = 1; ++ wctdm_setreg(wc, qrvmod, 0x0f, (unsigned char)l); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 0x0f to %02x hex\n", (unsigned char)l); ++ l = ((long)(nextqrvmod->mod.qrv.txgain % 1200) * 10000) / 46875; ++ if (l == 0) l = 1; ++ wctdm_setreg(wc, qrvmod, 0x10, (unsigned char)l); ++ if (debug) dev_info(&wc->vb.pdev->dev, "@@@@@ setting reg 0x10 to %02x hex\n",(unsigned char)l); ++ return; ++} ++ ++static void wctdm24xxp_get_fxs_regs(struct wctdm *wc, struct wctdm_module *mod, ++ struct wctdm_regs *regs) ++{ ++ int x; ++ ++ for (x = 0; x < NUM_INDIRECT_REGS; x++) ++ regs->indirect[x] = wctdm_proslic_getreg_indirect(wc, mod, x); ++ ++ for (x = 0; x < NUM_REGS; x++) ++ regs->direct[x] = wctdm_getreg(wc, mod, x); ++} ++ ++static void wctdm24xxp_get_fxo_regs(struct wctdm *wc, struct wctdm_module *mod, ++ struct wctdm_regs *regs) ++{ ++ int x; ++ for (x = 0; x < NUM_FXO_REGS; x++) ++ regs->direct[x] = wctdm_getreg(wc, mod, x); ++} ++ ++static void wctdm24xxp_get_qrv_regs(struct wctdm *wc, struct wctdm_module *mod, ++ struct wctdm_regs *regs) ++{ ++ int x; ++ for (x = 0; x < 0x32; x++) ++ regs->direct[x] = wctdm_getreg(wc, mod, x); ++} ++ ++static int wctdm_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) ++{ ++ struct wctdm_stats stats; ++ struct wctdm_regop regop; ++ struct wctdm_echo_coefs echoregs; ++ struct dahdi_hwgain hwgain; ++ struct wctdm *wc = chan->pvt; ++ int x; ++ union { ++ struct dahdi_radio_stat s; ++ struct dahdi_radio_param p; ++ } stack; ++ struct wctdm_module *const mod = &wc->mods[chan->chanpos - 1]; ++ struct fxs *const fxs = &mod->mod.fxs; ++ ++ switch (cmd) { ++ case DAHDI_ONHOOKTRANSFER: ++ if (mod->type != FXS) ++ return -EINVAL; ++ if (get_user(x, (__user int *) data)) ++ return -EFAULT; ++ ++ /* Active mode when idle */ ++ fxs->idletxhookstate = POLARITY_XOR(fxs) ? ++ SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ ++ if (((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_ACTIVE_FWD) || ++ ((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_ACTIVE_REV)) { ++ int res; ++ ++ res = set_lasttxhook_interruptible(wc, fxs, ++ (POLARITY_XOR(fxs) ? ++ SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD), ++ &mod->sethook); ++ ++ if (debug & DEBUG_CARD) { ++ if (res) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d TIMEOUT: " ++ "OnHookTransfer start\n", ++ chan->chanpos - 1); ++ } else { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d OnHookTransfer " ++ "start\n", chan->chanpos - 1); ++ } ++ } ++ ++ } ++ ++ fxs->ohttimer = wc->framecount + x; ++ fxs->oht_active = 1; ++ ++ break; ++ case DAHDI_VMWI_CONFIG: ++ if (mod->type != FXS) ++ return -EINVAL; ++ if (copy_from_user(&(fxs->vmwisetting), ++ (__user void *)data, ++ sizeof(fxs->vmwisetting))) ++ return -EFAULT; ++ set_vmwi(wc, mod); ++ break; ++ case DAHDI_VMWI: ++ if (mod->type != FXS) ++ return -EINVAL; ++ if (get_user(x, (__user int *) data)) ++ return -EFAULT; ++ if (0 > x) ++ return -EFAULT; ++ fxs->vmwi_active_messages = x; ++ set_vmwi(wc, mod); ++ break; ++ case WCTDM_GET_STATS: ++ if (mod->type == FXS) { ++ stats.tipvolt = wctdm_getreg(wc, mod, 80) * -376; ++ stats.ringvolt = wctdm_getreg(wc, mod, 81) * -376; ++ stats.batvolt = wctdm_getreg(wc, mod, 82) * -376; ++ } else if (mod->type == FXO) { ++ stats.tipvolt = (s8)wctdm_getreg(wc, mod, 29) * 1000; ++ stats.ringvolt = (s8)wctdm_getreg(wc, mod, 29) * 1000; ++ stats.batvolt = (s8)wctdm_getreg(wc, mod, 29) * 1000; ++ } else ++ return -EINVAL; ++ if (copy_to_user((__user void *) data, &stats, sizeof(stats))) ++ return -EFAULT; ++ break; ++ case WCTDM_GET_REGS: ++ { ++ struct wctdm_regs *regs = kzalloc(sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return -ENOMEM; ++ ++ if (mod->type == FXS) ++ wctdm24xxp_get_fxs_regs(wc, mod, regs); ++ else if (mod->type == QRV) ++ wctdm24xxp_get_qrv_regs(wc, mod, regs); ++ else ++ wctdm24xxp_get_fxo_regs(wc, mod, regs); ++ ++ if (copy_to_user((__user void *)data, regs, sizeof(*regs))) { ++ kfree(regs); ++ return -EFAULT; ++ } ++ ++ kfree(regs); ++ break; ++ } ++ case WCTDM_SET_REG: ++ if (copy_from_user(®op, (__user void *) data, sizeof(regop))) ++ return -EFAULT; ++ if (regop.indirect) { ++ if (mod->type != FXS) ++ return -EINVAL; ++ dev_info(&wc->vb.pdev->dev, "Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); ++ wctdm_proslic_setreg_indirect(wc, mod, regop.reg, ++ regop.val); ++ } else { ++ regop.val &= 0xff; ++ if (regop.reg == LINE_STATE) { ++ /* Set feedback register to indicate the new state that is being set */ ++ fxs->lasttxhook = (regop.val & 0x0f) | SLIC_LF_OPPENDING; ++ } ++ dev_info(&wc->vb.pdev->dev, "Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); ++ wctdm_setreg(wc, mod, regop.reg, regop.val); ++ } ++ break; ++ case WCTDM_SET_ECHOTUNE: ++ dev_info(&wc->vb.pdev->dev, "-- Setting echo registers: \n"); ++ if (copy_from_user(&echoregs, (__user void *) data, sizeof(echoregs))) ++ return -EFAULT; ++ ++ if (mod->type == FXO) { ++ /* Set the ACIM register */ ++ wctdm_setreg(wc, mod, 30, echoregs.acim); ++ ++ /* Set the digital echo canceller registers */ ++ wctdm_setreg(wc, mod, 45, echoregs.coef1); ++ wctdm_setreg(wc, mod, 46, echoregs.coef2); ++ wctdm_setreg(wc, mod, 47, echoregs.coef3); ++ wctdm_setreg(wc, mod, 48, echoregs.coef4); ++ wctdm_setreg(wc, mod, 49, echoregs.coef5); ++ wctdm_setreg(wc, mod, 50, echoregs.coef6); ++ wctdm_setreg(wc, mod, 51, echoregs.coef7); ++ wctdm_setreg(wc, mod, 52, echoregs.coef8); ++ ++ dev_info(&wc->vb.pdev->dev, "-- Set echo registers successfully\n"); ++ ++ break; ++ } else { ++ return -EINVAL; ++ ++ } ++ break; ++ case DAHDI_SET_HWGAIN: ++ if (copy_from_user(&hwgain, (__user void *) data, sizeof(hwgain))) ++ return -EFAULT; ++ ++ wctdm_set_hwgain(wc, mod, hwgain.newgain, hwgain.tx); ++ ++ if (debug) ++ dev_info(&wc->vb.pdev->dev, "Setting hwgain on channel %d to %d for %s direction\n", ++ chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx"); ++ break; ++#ifdef VPM_SUPPORT ++ case DAHDI_TONEDETECT: ++ /* Hardware DTMF detection is not supported. */ ++ return -ENOSYS; ++#endif ++ case DAHDI_SETPOLARITY: ++ if (get_user(x, (__user int *) data)) ++ return -EFAULT; ++ if (mod->type != FXS) ++ return -EINVAL; ++ /* Can't change polarity while ringing or when open */ ++ if (((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_RINGING) || ++ ((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_OPEN)) { ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d Unable to Set Polarity\n", chan->chanpos - 1); ++ } ++ return -EINVAL; ++ } ++ ++ fxs->reversepolarity = (x) ? 1 : 0; ++ ++ if (POLARITY_XOR(fxs)) { ++ fxs->idletxhookstate |= SLIC_LF_REVMASK; ++ x = fxs->lasttxhook & SLIC_LF_SETMASK; ++ x |= SLIC_LF_REVMASK; ++ if (x != fxs->lasttxhook) { ++ x = set_lasttxhook_interruptible(wc, fxs, x, ++ &mod->sethook); ++ if ((debug & DEBUG_CARD) && x) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d TIMEOUT: Set Reverse " ++ "Polarity\n", chan->chanpos - 1); ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d Set Reverse Polarity\n", ++ chan->chanpos - 1); ++ } ++ } ++ } else { ++ fxs->idletxhookstate &= ~SLIC_LF_REVMASK; ++ x = fxs->lasttxhook & SLIC_LF_SETMASK; ++ x &= ~SLIC_LF_REVMASK; ++ if (x != fxs->lasttxhook) { ++ x = set_lasttxhook_interruptible(wc, fxs, x, ++ &mod->sethook); ++ if ((debug & DEBUG_CARD) & x) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d TIMEOUT: Set Normal " ++ "Polarity\n", chan->chanpos - 1); ++ } else if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Channel %d Set Normal Polarity\n", ++ chan->chanpos - 1); ++ } ++ } ++ } ++ break; ++ case DAHDI_RADIO_GETPARAM: ++ if (mod->type != QRV) ++ return -ENOTTY; ++ if (copy_from_user(&stack.p, (__user void *) data, sizeof(stack.p))) ++ return -EFAULT; ++ stack.p.data = 0; /* start with 0 value in output */ ++ switch(stack.p.radpar) { ++ case DAHDI_RADPAR_INVERTCOR: ++ if (mod->mod.qrv.radmode & RADMODE_INVERTCOR) ++ stack.p.data = 1; ++ break; ++ case DAHDI_RADPAR_IGNORECOR: ++ if (mod->mod.qrv.radmode & RADMODE_IGNORECOR) ++ stack.p.data = 1; ++ break; ++ case DAHDI_RADPAR_IGNORECT: ++ if (mod->mod.qrv.radmode & RADMODE_IGNORECT) ++ stack.p.data = 1; ++ break; ++ case DAHDI_RADPAR_EXTRXTONE: ++ stack.p.data = 0; ++ if (mod->mod.qrv.radmode & RADMODE_EXTTONE) { ++ stack.p.data = 1; ++ if (mod->mod.qrv.radmode & RADMODE_EXTINVERT) ++ stack.p.data = 2; ++ } ++ break; ++ case DAHDI_RADPAR_DEBOUNCETIME: ++ stack.p.data = mod->mod.qrv.debouncetime; ++ break; ++ case DAHDI_RADPAR_RXGAIN: ++ stack.p.data = mod->mod.qrv.rxgain - 1199; ++ break; ++ case DAHDI_RADPAR_TXGAIN: ++ stack.p.data = mod->mod.qrv.txgain - 3599; ++ break; ++ case DAHDI_RADPAR_DEEMP: ++ stack.p.data = 0; ++ if (mod->mod.qrv.radmode & RADMODE_DEEMP) ++ stack.p.data = 1; ++ break; ++ case DAHDI_RADPAR_PREEMP: ++ stack.p.data = 0; ++ if (mod->mod.qrv.radmode & RADMODE_PREEMP) ++ stack.p.data = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (copy_to_user((__user void *) data, &stack.p, sizeof(stack.p))) ++ return -EFAULT; ++ break; ++ case DAHDI_RADIO_SETPARAM: ++ if (mod->type != QRV) ++ return -ENOTTY; ++ if (copy_from_user(&stack.p, (__user void *) data, sizeof(stack.p))) ++ return -EFAULT; ++ switch(stack.p.radpar) { ++ case DAHDI_RADPAR_INVERTCOR: ++ if (stack.p.data) ++ mod->mod.qrv.radmode |= RADMODE_INVERTCOR; ++ else ++ mod->mod.qrv.radmode &= ~RADMODE_INVERTCOR; ++ return 0; ++ case DAHDI_RADPAR_IGNORECOR: ++ if (stack.p.data) ++ mod->mod.qrv.radmode |= RADMODE_IGNORECOR; ++ else ++ mod->mod.qrv.radmode &= ~RADMODE_IGNORECOR; ++ return 0; ++ case DAHDI_RADPAR_IGNORECT: ++ if (stack.p.data) ++ mod->mod.qrv.radmode |= RADMODE_IGNORECT; ++ else ++ mod->mod.qrv.radmode &= ~RADMODE_IGNORECT; ++ return 0; ++ case DAHDI_RADPAR_EXTRXTONE: ++ if (stack.p.data) ++ mod->mod.qrv.radmode |= RADMODE_EXTTONE; ++ else ++ mod->mod.qrv.radmode &= ~RADMODE_EXTTONE; ++ if (stack.p.data > 1) ++ mod->mod.qrv.radmode |= RADMODE_EXTINVERT; ++ else ++ mod->mod.qrv.radmode &= ~RADMODE_EXTINVERT; ++ return 0; ++ case DAHDI_RADPAR_DEBOUNCETIME: ++ mod->mod.qrv.debouncetime = stack.p.data; ++ return 0; ++ case DAHDI_RADPAR_RXGAIN: ++ /* if out of range */ ++ if ((stack.p.data <= -1200) || (stack.p.data > 1552)) ++ { ++ return -EINVAL; ++ } ++ mod->mod.qrv.rxgain = stack.p.data + 1199; ++ break; ++ case DAHDI_RADPAR_TXGAIN: ++ /* if out of range */ ++ if (mod->mod.qrv.radmode & RADMODE_PREEMP) { ++ if ((stack.p.data <= -2400) || ++ (stack.p.data > 0)) ++ return -EINVAL; ++ } else { ++ if ((stack.p.data <= -3600) || ++ (stack.p.data > 1200)) ++ return -EINVAL; ++ } ++ mod->mod.qrv.txgain = stack.p.data + 3599; ++ break; ++ case DAHDI_RADPAR_DEEMP: ++ if (stack.p.data) ++ mod->mod.qrv.radmode |= RADMODE_DEEMP; ++ else ++ mod->mod.qrv.radmode &= ~RADMODE_DEEMP; ++ mod->mod.qrv.rxgain = 1199; ++ break; ++ case DAHDI_RADPAR_PREEMP: ++ if (stack.p.data) ++ mod->mod.qrv.radmode |= RADMODE_PREEMP; ++ else ++ mod->mod.qrv.radmode &= ~RADMODE_PREEMP; ++ mod->mod.qrv.txgain = 3599; ++ break; ++ default: ++ return -EINVAL; ++ } ++ qrv_dosetup(chan,wc); ++ return 0; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static int wctdm_open(struct dahdi_chan *chan) ++{ ++ struct wctdm *const wc = chan->pvt; ++ unsigned long flags; ++ struct wctdm_module *const mod = &wc->mods[chan->chanpos - 1]; ++ ++#if 0 ++ if (wc->dead) ++ return -ENODEV; ++#endif ++ if (mod->type == FXO) { ++ /* Reset the mwi indicators */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->mod.fxo.neonmwi_debounce = 0; ++ mod->mod.fxo.neonmwi_offcounter = 0; ++ mod->mod.fxo.neonmwi_state = 0; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++ ++ return 0; ++} ++ ++static inline struct wctdm *span_to_wctdm(struct dahdi_span *span) ++{ ++ struct wctdm_span *s = container_of(span, struct wctdm_span, span); ++ return s->wc; ++} ++ ++static int wctdm_watchdog(struct dahdi_span *span, int event) ++{ ++ struct wctdm *wc = span_to_wctdm(span); ++ dev_info(&wc->vb.pdev->dev, "TDM: Called watchdog\n"); ++ return 0; ++} ++ ++static int wctdm_close(struct dahdi_chan *chan) ++{ ++ struct wctdm *wc; ++ int x; ++ signed char reg; ++ ++ wc = chan->pvt; ++ for (x = 0; x < wc->mods_per_board; x++) { ++ struct wctdm_module *const mod = &wc->mods[x]; ++ if (FXS == mod->type) { ++ mod->mod.fxs.idletxhookstate = ++ POLARITY_XOR(&mod->mod.fxs) ? SLIC_LF_ACTIVE_REV : ++ SLIC_LF_ACTIVE_FWD; ++ } else if (QRV == mod->type) { ++ int qrvcard = x & 0xfc; ++ ++ mod->mod.qrv.hook = 0; ++ wc->mods[x + 2].mod.qrv.hook = 0xff; ++ mod->mod.qrv.debouncetime = QRV_DEBOUNCETIME; ++ mod->mod.qrv.debtime = 0; ++ mod->mod.qrv.radmode = 0; ++ mod->mod.qrv.txgain = 3599; ++ mod->mod.qrv.rxgain = 1199; ++ reg = 0; ++ if (!wc->mods[qrvcard].mod.qrv.hook) ++ reg |= 1; ++ if (!wc->mods[qrvcard + 1].mod.qrv.hook) ++ reg |= 0x10; ++ wc->mods[qrvcard].sethook = CMD_WR(3, reg); ++ qrv_dosetup(chan,wc); ++ } ++ } ++ ++ return 0; ++} ++ ++static int wctdm_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) ++{ ++ struct wctdm *wc = chan->pvt; ++ int reg = 0; ++ struct wctdm_module *const mod = &wc->mods[chan->chanpos - 1]; ++ ++ if (mod->type == QRV) { ++ const int qrvcard = (chan->chanpos - 1) & 0xfc; ++ ++ switch(txsig) { ++ case DAHDI_TXSIG_START: ++ case DAHDI_TXSIG_OFFHOOK: ++ mod->mod.qrv.hook = 1; ++ break; ++ case DAHDI_TXSIG_ONHOOK: ++ mod->mod.qrv.hook = 0; ++ break; ++ default: ++ dev_notice(&wc->vb.pdev->dev, "wctdm24xxp: Can't set tx state to %d\n", txsig); ++ } ++ reg = 0; ++ if (!wc->mods[qrvcard].mod.qrv.hook) ++ reg |= 1; ++ if (!wc->mods[qrvcard + 1].mod.qrv.hook) ++ reg |= 0x10; ++ wc->mods[qrvcard].sethook = CMD_WR(3, reg); ++ /* wctdm_setreg(wc, qrvcard, 3, reg); */ ++ } else if (mod->type == FXO) { ++ switch(txsig) { ++ case DAHDI_TXSIG_START: ++ case DAHDI_TXSIG_OFFHOOK: ++ mod->mod.fxo.offhook = 1; ++ mod->sethook = CMD_WR(5, 0x9); ++ /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); */ ++ break; ++ case DAHDI_TXSIG_ONHOOK: ++ mod->mod.fxo.offhook = 0; ++ mod->sethook = CMD_WR(5, 0x8); ++ /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); */ ++ break; ++ default: ++ dev_notice(&wc->vb.pdev->dev, "wctdm24xxp: Can't set tx state to %d\n", txsig); ++ } ++ } else if (mod->type == FXS) { ++ wctdm_fxs_hooksig(wc, mod, txsig); ++ } ++ return 0; ++} ++ ++static void wctdm_dacs_connect(struct wctdm *wc, int srccard, int dstcard) ++{ ++ struct wctdm_module *const srcmod = &wc->mods[srccard]; ++ struct wctdm_module *const dstmod = &wc->mods[dstcard]; ++ unsigned int type; ++ ++ if (wc->mods[dstcard].dacssrc > -1) { ++ dev_notice(&wc->vb.pdev->dev, "wctdm_dacs_connect: Can't have double sourcing yet!\n"); ++ return; ++ } ++ type = wc->mods[srccard].type; ++ if ((type == FXS) || (type == FXO)) { ++ dev_notice(&wc->vb.pdev->dev, ++ "wctdm_dacs_connect: Unsupported modtype for " ++ "card %d\n", srccard); ++ return; ++ } ++ type = wc->mods[dstcard].type; ++ if ((type != FXS) && (type != FXO)) { ++ dev_notice(&wc->vb.pdev->dev, ++ "wctdm_dacs_connect: Unsupported modtype " ++ "for card %d\n", dstcard); ++ return; ++ } ++ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "connect %d => %d\n", srccard, dstcard); ++ } ++ ++ dstmod->dacssrc = srccard; ++ ++ /* make srccard transmit to srccard+24 on the TDM bus */ ++ if (srcmod->type == FXS) { ++ /* proslic */ ++ wctdm_setreg(wc, srcmod, PCM_XMIT_START_COUNT_LSB, ++ ((srccard+24) * 8) & 0xff); ++ wctdm_setreg(wc, srcmod, PCM_XMIT_START_COUNT_MSB, ++ ((srccard+24) * 8) >> 8); ++ } else if (srcmod->type == FXO) { ++ /* daa TX */ ++ wctdm_setreg(wc, srcmod, 34, ((srccard+24) * 8) & 0xff); ++ wctdm_setreg(wc, srcmod, 35, ((srccard+24) * 8) >> 8); ++ } ++ ++ /* have dstcard receive from srccard+24 on the TDM bus */ ++ if (dstmod->type == FXS) { ++ /* proslic */ ++ wctdm_setreg(wc, dstmod, PCM_RCV_START_COUNT_LSB, ++ ((srccard+24) * 8) & 0xff); ++ wctdm_setreg(wc, dstmod, PCM_RCV_START_COUNT_MSB, ++ ((srccard+24) * 8) >> 8); ++ } else if (dstmod->type == FXO) { ++ /* daa RX */ ++ wctdm_setreg(wc, dstmod, 36, ((srccard+24) * 8) & 0xff); ++ wctdm_setreg(wc, dstmod, 37, ((srccard+24) * 8) >> 8); ++ } ++} ++ ++static void wctdm_dacs_disconnect(struct wctdm *wc, int card) ++{ ++ struct wctdm_module *const mod = &wc->mods[card]; ++ struct wctdm_module *dacssrc; ++ ++ if (mod->dacssrc <= -1) ++ return; ++ ++ dacssrc = &wc->mods[mod->dacssrc]; ++ ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, "wctdm_dacs_disconnect: " ++ "restoring TX for %d and RX for %d\n", ++ mod->dacssrc, card); ++ } ++ ++ /* restore TX (source card) */ ++ if (dacssrc->type == FXS) { ++ wctdm_setreg(wc, dacssrc, PCM_XMIT_START_COUNT_LSB, ++ (mod->dacssrc * 8) & 0xff); ++ wctdm_setreg(wc, dacssrc, PCM_XMIT_START_COUNT_MSB, ++ (mod->dacssrc * 8) >> 8); ++ } else if (dacssrc->type == FXO) { ++ wctdm_setreg(wc, mod, 34, (card * 8) & 0xff); ++ wctdm_setreg(wc, mod, 35, (card * 8) >> 8); ++ } else { ++ dev_warn(&wc->vb.pdev->dev, ++ "WARNING: wctdm_dacs_disconnect() called " ++ "on unsupported modtype\n"); ++ } ++ ++ /* restore RX (this card) */ ++ if (FXS == mod->type) { ++ wctdm_setreg(wc, mod, PCM_RCV_START_COUNT_LSB, ++ (card * 8) & 0xff); ++ wctdm_setreg(wc, mod, PCM_RCV_START_COUNT_MSB, ++ (card * 8) >> 8); ++ } else if (FXO == mod->type) { ++ wctdm_setreg(wc, mod, 36, (card * 8) & 0xff); ++ wctdm_setreg(wc, mod, 37, (card * 8) >> 8); ++ } else { ++ dev_warn(&wc->vb.pdev->dev, ++ "WARNING: wctdm_dacs_disconnect() called " ++ "on unsupported modtype\n"); ++ } ++ ++ mod->dacssrc = -1; ++} ++ ++static int wctdm_dacs(struct dahdi_chan *dst, struct dahdi_chan *src) ++{ ++ struct wctdm *wc; ++ ++ if (!nativebridge) ++ return 0; /* should this return -1 since unsuccessful? */ ++ ++ wc = dst->pvt; ++ ++ if (src) { ++ wctdm_dacs_connect(wc, src->chanpos - 1, dst->chanpos - 1); ++ if (debug) ++ dev_info(&wc->vb.pdev->dev, "dacs connecct: %d -> %d!\n\n", src->chanpos, dst->chanpos); ++ } else { ++ wctdm_dacs_disconnect(wc, dst->chanpos - 1); ++ if (debug) ++ dev_info(&wc->vb.pdev->dev, "dacs disconnect: %d!\n", dst->chanpos); ++ } ++ return 0; ++} ++ ++/** ++ * wctdm_wait_for_ready ++ * ++ * Check if the board has finished any setup and is ready to start processing ++ * calls. ++ */ ++int wctdm_wait_for_ready(struct wctdm *wc) ++{ ++ while (!is_initialized(wc)) { ++ if (fatal_signal_pending(current)) ++ return -EIO; ++ msleep_interruptible(250); ++ } ++ return 0; ++} ++ ++static int wctdm_enable_hw_preechocan(struct dahdi_chan *chan) ++{ ++ struct wctdm *wc = chan->pvt; ++ struct wctdm_chan *wchan = container_of(chan, struct wctdm_chan, chan); ++ ++ if (!wc->vpmoct) ++ return 0; ++ ++ return vpmoct_preecho_enable(wc->vpmoct, wchan->timeslot); ++} ++ ++static void wctdm_disable_hw_preechocan(struct dahdi_chan *chan) ++{ ++ struct wctdm *wc = chan->pvt; ++ struct wctdm_chan *wchan = container_of(chan, struct wctdm_chan, chan); ++ ++ if (!wc->vpmoct) ++ return; ++ ++ vpmoct_preecho_disable(wc->vpmoct, wchan->timeslot); ++} ++ ++/** ++ * wctdm_chanconfig - Called when the channels are being configured. ++ * ++ * Ensure that the card is completely ready to go before we allow the channels ++ * to be completely configured. This is to allow lengthy initialization ++ * actions to take place in background on driver load and ensure we're synced ++ * up by the time dahdi_cfg is run. ++ * ++ */ ++static int ++wctdm_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype) ++{ ++ struct wctdm *wc = chan->pvt; ++ ++ if ((file->f_flags & O_NONBLOCK) && !is_initialized(wc)) ++ return -EAGAIN; ++ ++ return wctdm_wait_for_ready(wc); ++} ++ ++static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = { ++ .owner = THIS_MODULE, ++ .hooksig = wctdm_hooksig, ++ .open = wctdm_open, ++ .close = wctdm_close, ++ .ioctl = wctdm_ioctl, ++ .watchdog = wctdm_watchdog, ++ .chanconfig = wctdm_chanconfig, ++ .dacs = wctdm_dacs, ++#ifdef VPM_SUPPORT ++ .enable_hw_preechocan = wctdm_enable_hw_preechocan, ++ .disable_hw_preechocan = wctdm_disable_hw_preechocan, ++ .echocan_create = wctdm_echocan_create, ++ .echocan_name = wctdm_echocan_name, ++#endif ++}; ++ ++static const struct dahdi_span_ops wctdm24xxp_digital_span_ops = { ++ .owner = THIS_MODULE, ++ .open = wctdm_open, ++ .close = wctdm_close, ++ .ioctl = wctdm_ioctl, ++ .watchdog = wctdm_watchdog, ++ .hdlc_hard_xmit = wctdm_hdlc_hard_xmit, ++ .spanconfig = b400m_spanconfig, ++ .chanconfig = b400m_chanconfig, ++ .dacs = wctdm_dacs, ++#ifdef VPM_SUPPORT ++ .enable_hw_preechocan = wctdm_enable_hw_preechocan, ++ .disable_hw_preechocan = wctdm_disable_hw_preechocan, ++ .echocan_create = wctdm_echocan_create, ++ .echocan_name = wctdm_echocan_name, ++#endif ++}; ++ ++static struct wctdm_chan * ++wctdm_init_chan(struct wctdm *wc, struct wctdm_span *s, int chanoffset, ++ int channo, unsigned int card_position) ++{ ++ struct wctdm_chan *c; ++ ++ c = kzalloc(sizeof(*c), GFP_KERNEL); ++ if (!c) ++ return NULL; ++ ++ /* Do not change the procfs representation for non-hx8 cards. */ ++ if (dahdi_is_digital_span(&s->span)) { ++ sprintf(c->chan.name, "WCBRI/%d/%d/%d", card_position, ++ s->spanno, channo); ++ } else { ++ sprintf(c->chan.name, "WCTDM/%d/%d", card_position, channo); ++ } ++ ++ c->chan.chanpos = channo+1; ++ c->chan.span = &s->span; ++ c->chan.pvt = wc; ++ c->timeslot = chanoffset + channo; ++ return c; ++} ++ ++#if 0 ++/** ++ * wctdm_span_count() - Return the number of spans exported by this board. ++ * ++ * This is only called during initialization so let's just count the spans each ++ * time we need this information as opposed to storing another variable in the ++ * wctdm structure. ++ */ ++static int wctdm_span_count(const struct wctdm *wc) ++{ ++ int i; ++ int count = 0; ++ for (i = 0; i < MAX_SPANS; ++i) { ++ if (wc->spans[i]) ++ ++count; ++ } ++ return count; ++} ++#endif ++ ++static struct wctdm_span * ++wctdm_init_span(struct wctdm *wc, int spanno, int chanoffset, int chancount, ++ int digital_span, unsigned int card_position) ++{ ++ int x; ++ struct wctdm_chan *c; ++ struct wctdm_span *s; ++ static int spancount; ++ ++ s = kzalloc(sizeof(*s), GFP_KERNEL); ++ if (!s) ++ return NULL; ++ ++ /* DAHDI stuff */ ++ s->span.offset = spanno; ++ ++ s->spanno = spancount++; ++ s->wc = wc; ++ ++ /* Do not change the procfs representation for non-hx8 cards. */ ++ if (digital_span) ++ sprintf(s->span.name, "WCBRI/%d/%d", card_position, s->spanno); ++ else ++ sprintf(s->span.name, "WCTDM/%d", card_position); ++ ++ snprintf(s->span.desc, sizeof(s->span.desc) - 1, "%s", wc->desc->name); ++ ++ if (wc->companding == DAHDI_LAW_DEFAULT) { ++ if (wc->digi_mods || digital_span) ++ /* If we have a BRI module, Auto set to alaw */ ++ s->span.deflaw = DAHDI_LAW_ALAW; ++ else ++ /* Auto set to ulaw */ ++ s->span.deflaw = DAHDI_LAW_MULAW; ++ } else if (wc->companding == DAHDI_LAW_ALAW) { ++ /* Force everything to alaw */ ++ s->span.deflaw = DAHDI_LAW_ALAW; ++ } else { ++ /* Auto set to ulaw */ ++ s->span.deflaw = DAHDI_LAW_MULAW; ++ } ++ ++ if (digital_span) { ++ s->span.ops = &wctdm24xxp_digital_span_ops; ++ s->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4; ++ s->span.linecompat |= DAHDI_CONFIG_ESF | DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4; ++ s->span.linecompat |= DAHDI_CONFIG_NTTE | DAHDI_CONFIG_TERM; ++ s->span.spantype = SPANTYPE_DIGITAL_BRI_TE; ++ } else { ++ s->span.ops = &wctdm24xxp_analog_span_ops; ++ s->span.flags = DAHDI_FLAG_RBS; ++ s->span.spantype = SPANTYPE_ANALOG_MIXED; ++ /* analog sigcap handled in fixup_analog_span() */ ++ } ++ ++ s->span.chans = kmalloc(sizeof(struct dahdi_chan *) * chancount, GFP_KERNEL); ++ if (!s->span.chans) ++ return NULL; ++ ++ /* allocate channels for the span */ ++ for (x = 0; x < chancount; x++) { ++ c = wctdm_init_chan(wc, s, chanoffset, x, card_position); ++ if (!c) ++ return NULL; ++ wc->chans[chanoffset + x] = c; ++ s->span.chans[x] = &c->chan; ++ } ++ ++ s->span.channels = chancount; ++ ++ if (digital_span) { ++ wc->chans[chanoffset + 0]->chan.sigcap = DAHDI_SIG_CLEAR; ++ wc->chans[chanoffset + 1]->chan.sigcap = DAHDI_SIG_CLEAR; ++ wc->chans[chanoffset + 2]->chan.sigcap = DAHDI_SIG_HARDHDLC; ++ } ++ ++ wc->spans[spanno] = s; ++ return s; ++} ++ ++/** ++ * should_set_alaw() - Should be called after all the spans are initialized. ++ * ++ * Returns true if the module companding should be set to alaw, otherwise ++ * false. ++ */ ++static bool should_set_alaw(const struct wctdm *wc) ++{ ++ if (DAHDI_LAW_DEFAULT == wc->companding) ++ return (wc->digi_mods > 0); ++ else if (DAHDI_LAW_ALAW == wc->companding) ++ return true; ++ else ++ return false; ++} ++ ++static void wctdm_fixup_analog_span(struct wctdm *wc, int spanno) ++{ ++ struct dahdi_span *s; ++ int x, y; ++ ++ /* Finalize signalling */ ++ y = 0; ++ s = &wc->spans[spanno]->span; ++ ++ for (x = 0; x < wc->desc->ports; x++) { ++ struct wctdm_module *const mod = &wc->mods[x]; ++ if (debug) { ++ dev_info(&wc->vb.pdev->dev, ++ "fixup_analog: x=%d, y=%d modtype=%d, " ++ "s->chans[%d]=%p\n", x, y, mod->type, ++ y, s->chans[y]); ++ } ++ if (mod->type == FXO) { ++ int val; ++ s->chans[y++]->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR; ++ val = should_set_alaw(wc) ? 0x20 : 0x28; ++#ifdef DEBUG ++ val = (digitalloopback) ? 0x30 : val; ++#endif ++ wctdm_setreg(wc, mod, 33, val); ++ } else if (mod->type == FXS) { ++ s->chans[y++]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; ++ wctdm_setreg(wc, mod, 1, ++ (should_set_alaw(wc) ? 0x20 : 0x28)); ++ } else if (mod->type == QRV) { ++ s->chans[y++]->sigcap = DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; ++ } else { ++ s->chans[y++]->sigcap = 0; ++ } ++ } ++} ++ ++static int wctdm_initialize_vpmadt032(struct wctdm *wc) ++{ ++ int res; ++ struct vpmadt032_options options; ++ struct vpmadt032 *vpm; ++ unsigned long flags; ++ ++ options.debug = debug; ++ options.vpmnlptype = vpmnlptype; ++ options.vpmnlpthresh = vpmnlpthresh; ++ options.vpmnlpmaxsupp = vpmnlpmaxsupp; ++ if (is_hx8(wc)) { ++ /* Hybrid cards potentially have 3 channels of EC on their ++ * ports since they may be BRI spans. */ ++ options.channels = 3 * wc->desc->ports; ++ } else { ++ options.channels = wc->desc->ports; ++ } ++ ++ BUG_ON(options.channels > 24); ++ ++ wc->vpmadt032 = vpmadt032_alloc(&options); ++ if (!wc->vpmadt032) ++ return -ENOMEM; ++ ++ wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state; ++ ++ /* Pull the configuration information from the span holding ++ * the analog channels. */ ++ res = vpmadt032_test(wc->vpmadt032, &wc->vb); ++ if (!res) ++ res = vpmadt032_init(wc->vpmadt032); ++ if (res) { ++ vpm = wc->vpmadt032; ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->vpmadt032 = NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ vpmadt032_free(vpm); ++ return res; ++ } ++ ++ /* Now we need to configure the VPMADT032 module for this ++ * particular board. */ ++ res = config_vpmadt032(wc->vpmadt032, wc); ++ if (res) { ++ vpm = wc->vpmadt032; ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->vpmadt032 = NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ vpmadt032_free(vpm); ++ return res; ++ } ++ ++ return 0; ++} ++ ++static void wctdm_vpm_load_complete(struct device *dev, bool operational) ++{ ++ unsigned long flags; ++ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); ++ struct wctdm *wc = pci_get_drvdata(pdev); ++ struct vpmoct *vpm = NULL; ++ ++ WARN_ON(!wc || !wc->not_ready); ++ if (!wc || !wc->not_ready) ++ return; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->not_ready--; ++ if (operational) { ++ wc->ctlreg |= 0x10; ++ } else { ++ vpm = wc->vpmoct; ++ wc->vpmoct = NULL; ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (vpm) ++ vpmoct_free(vpm); ++} ++ ++static int wctdm_initialize_vpm(struct wctdm *wc, unsigned long unused) ++{ ++ int res = 0; ++ ++ if (!vpmsupport) { ++ dev_notice(&wc->vb.pdev->dev, "VPM: Support Disabled\n"); ++ return 0; ++ } ++ ++ res = wctdm_initialize_vpmadt032(wc); ++ if (!res) { ++ wc->ctlreg |= 0x10; ++ return 0; ++ } else { ++ struct vpmoct *vpm; ++ unsigned long flags; ++ ++ vpm = vpmoct_alloc(); ++ if (!vpm) { ++ dev_info(&wc->vb.pdev->dev, ++ "Unable to allocate memory for struct vpmoct\n"); ++ return -ENOMEM; ++ } ++ ++ vpm->dev = &wc->vb.pdev->dev; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->vpmoct = vpm; ++ wc->not_ready++; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ res = vpmoct_init(vpm, wctdm_vpm_load_complete); ++ if (-EINVAL == res) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->vpmoct = NULL; ++ wc->not_ready--; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ vpmoct_free(vpm); ++ } ++ } ++ return 0; ++} ++ ++static int __wctdm_identify_module_group(struct wctdm *wc, unsigned long base) ++{ ++ int x; ++ unsigned long flags; ++ ++ for (x = base; x < base + 4; ++x) { ++ struct wctdm_module *const mod = &wc->mods[x]; ++ enum {SANE = 1, UNKNOWN = 0}; ++ int ret = 0, readi = 0; ++ bool altcs = false; ++ ++ if (fatal_signal_pending(current)) ++ break; ++retry: ++ ret = wctdm_init_proslic(wc, mod, 0, 0, UNKNOWN); ++ if (!ret) { ++ if (debug & DEBUG_CARD) { ++ readi = wctdm_getreg(wc, mod, LOOP_I_LIMIT); ++ dev_info(&wc->vb.pdev->dev, ++ "Proslic module %d loop current " ++ "is %dmA\n", x, ((readi*3) + 20)); ++ } ++ continue; ++ } ++ ++ if (ret != -2) { ++ /* Init with Manual Calibration */ ++ if (!wctdm_init_proslic(wc, mod, 0, 1, SANE)) { ++ ++ if (debug & DEBUG_CARD) { ++ readi = wctdm_getreg(wc, mod, ++ LOOP_I_LIMIT); ++ dev_info(&wc->vb.pdev->dev, ++ "Proslic module %d loop " ++ "current is %dmA\n", x, ++ ((readi*3)+20)); ++ } ++ } else { ++ dev_notice(&wc->vb.pdev->dev, ++ "Port %d: FAILED FXS (%s)\n", ++ x + 1, fxshonormode ? ++ fxo_modes[_opermode].name : "FCC"); ++ } ++ continue; ++ } ++ ++ ret = wctdm_init_voicedaa(wc, mod, 0, 0, UNKNOWN); ++ if (!ret) ++ continue; ++ ++ if (!wctdm_init_qrvdri(wc, x)) ++ continue; ++ ++ if (is_hx8(wc) && !wctdm_init_b400m(wc, x)) ++ continue; ++ ++ if ((wc->desc->ports != 24) && ((x&0x3) == 1) && !altcs) { ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ set_offsets(mod, 2); ++ altcs = true; ++ ++ if (wc->desc->ports == 4) { ++ set_offsets(&wc->mods[x+1], 3); ++ set_offsets(&wc->mods[x+2], 3); ++ } ++ ++ mod->type = FXSINIT; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ udelay(1000); ++ udelay(1000); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ mod->type = FXS; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (debug & DEBUG_CARD) { ++ dev_info(&wc->vb.pdev->dev, ++ "Trying port %d with alternate chip " ++ "select\n", x + 1); ++ } ++ goto retry; ++ } ++ ++ mod->type = NONE; ++ } ++ return 0; ++} ++ ++/** ++ * wctdm_print_moule_configuration - Print the configuration to the kernel log ++ * @wc: The card we're interested in. ++ * ++ * This is to ensure that the module configuration from each card shows up ++ * sequentially in the kernel log, as opposed to interleaved with one another. ++ * ++ */ ++static void wctdm_print_module_configuration(const struct wctdm *const wc) ++{ ++ int i; ++ static DEFINE_MUTEX(print); ++ ++ mutex_lock(&print); ++ for (i = 0; i < wc->mods_per_board; ++i) { ++ const struct wctdm_module *const mod = &wc->mods[i]; ++ ++ switch (mod->type) { ++ case FXO: ++ dev_info(&wc->vb.pdev->dev, "Port %d: Installed -- " ++ "AUTO FXO (%s mode)\n", i + 1, ++ fxo_modes[_opermode].name); ++ break; ++ case FXS: ++ dev_info(&wc->vb.pdev->dev, ++ "Port %d: Installed -- AUTO FXS/DPO\n", i + 1); ++ break; ++ case BRI: ++ dev_info(&wc->vb.pdev->dev, "Port %d: Installed -- BRI " ++ "quad-span module\n", i + 1); ++ break; ++ case QRV: ++ dev_info(&wc->vb.pdev->dev, ++ "Port %d: Installed -- QRV DRI card\n", i + 1); ++ break; ++ case NONE: ++ dev_info(&wc->vb.pdev->dev, ++ "Port %d: Not installed\n", i + 1); ++ break; ++ case FXSINIT: ++ break; ++ } ++ } ++ mutex_unlock(&print); ++} ++ ++static void wctdm_identify_modules(struct wctdm *wc) ++{ ++ int x; ++ unsigned long flags; ++ struct bg *bg_work[ARRAY_SIZE(wc->mods)/4 + 1] = {NULL, }; ++ ++ wc->ctlreg = 0x00; ++ ++ /* ++ * This looks a little weird. ++ * ++ * There are only 8 physical ports on the TDM/AEX800, but the code ++ * immediately below sets 24 modules up. This has to do with the ++ * altcs magic that allows us to have single-port and quad-port ++ * modules on these products. The variable "mods_per_board" is set to ++ * the appropriate value just below the next code block. ++ * ++ * Now why this is important: The FXS modules come out of reset in a ++ * two-byte, non-chainable SPI mode. This is currently incompatible ++ * with how we do things, so we need to set them to a chained, 3-byte ++ * command mode. This is done by setting the module type to FXSINIT ++ * for a little while so that cmd_dequeue will initialize the SLIC ++ * into the appropriate mode. ++ * ++ * This "go to 3-byte chained mode" command, however, wreaks havoc ++ * with HybridBRI. ++ * ++ * The solution: Since HybridBRI is only designed to work in an 8-port ++ * card, and since the single-port modules "show up" in SPI slots >= 8 ++ * in these cards, we only set SPI slots 8-23 to FXSINIT. The ++ * HybridBRI will never see the command that causes it to freak out ++ * and the single-port FXS cards get what they need so that when we ++ * probe with altcs we see them. ++ */ ++ ++ /* Make sure all units go into daisy chain mode */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ for (x = 0; x < ARRAY_SIZE(wc->mods); x++) ++ wc->mods[x].type = FXSINIT; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* Wait just a bit; this makes sure that cmd_dequeue is emitting SPI ++ * commands in the appropriate mode(s). */ ++ msleep(20); ++ ++ /* Now that all the cards have been reset, we can stop checking them ++ * all if there aren't as many */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->mods_per_board = wc->desc->ports; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ BUG_ON(wc->desc->ports % 4); ++ ++ /* Detecting and configuring the modules over voicebus takes a ++ * significant amount of time. We can speed things up by performing ++ * this in parallel for each group of four modules. */ ++ for (x = 0; x < wc->desc->ports/4; x++) ++ bg_work[x] = bg_create(wc, __wctdm_identify_module_group, x*4); ++ ++ for (x = 0; bg_work[x]; ++x) ++ bg_join(bg_work[x]); ++ ++ wctdm_print_module_configuration(wc); ++} ++ ++static struct pci_driver wctdm_driver; ++ ++static void wctdm_back_out_gracefully(struct wctdm *wc) ++{ ++ int i; ++ unsigned long flags; ++ struct vpmadt032 *vpm; ++ LIST_HEAD(local_list); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (wc->not_ready) { ++ wc->not_ready--; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ while (wctdm_wait_for_ready(wc)) ++ schedule(); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (wc->vpmadt032) { ++ flush_workqueue(wc->vpmadt032->wq); ++ clear_bit(VPM150M_ACTIVE, &wc->vpmadt032->control); ++ flush_workqueue(wc->vpmadt032->wq); ++ spin_lock_irqsave(&wc->reglock, flags); ++ vpm = wc->vpmadt032; ++ wc->vpmadt032 = NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ vpmadt032_free(vpm); ++ } ++ ++ voicebus_release(&wc->vb); ++#ifdef CONFIG_VOICEBUS_ECREFERENCE ++ for (i = 0; i < ARRAY_SIZE(wc->ec_reference); ++i) { ++ if (wc->ec_reference[i]) ++ dahdi_fifo_free(wc->ec_reference[i]); ++ } ++#endif ++ ++ for (i = 0; i < ARRAY_SIZE(wc->spans); ++i) { ++ if (wc->spans[i] && wc->spans[i]->span.chans) ++ kfree(wc->spans[i]->span.chans); ++ ++ kfree(wc->spans[i]); ++ wc->spans[i] = NULL; ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ for (i = 0; i < ARRAY_SIZE(wc->mods); ++i) { ++ struct wctdm_module *const mod = &wc->mods[i]; ++ kfree(wc->chans[i]); ++ wc->chans[i] = NULL; ++ list_splice_init(&mod->pending_cmds, &local_list); ++ list_splice_init(&mod->active_cmds, &local_list); ++ } ++ list_splice_init(&wc->free_isr_commands, &local_list); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ while (!list_empty(&local_list)) { ++ struct wctdm_cmd *cmd; ++ cmd = list_entry(local_list.next, ++ struct wctdm_cmd, node); ++ list_del(&cmd->node); ++ kfree(cmd->complete); ++ kfree(cmd); ++ } ++ ++ spin_lock_irqsave(&wc->frame_list_lock, flags); ++ list_splice(&wc->frame_list, &local_list); ++ spin_unlock_irqrestore(&wc->frame_list_lock, flags); ++ ++ while (!list_empty(&local_list)) { ++ struct sframe_packet *frame; ++ frame = list_entry(local_list.next, ++ struct sframe_packet, node); ++ list_del(&frame->node); ++ kfree(frame); ++ } ++ ++ kfree(wc->board_name); ++ kfree(wc->ddev->devicetype); ++ kfree(wc->ddev->location); ++ dahdi_free_device(wc->ddev); ++ kfree(wc); ++} ++ ++static const struct voicebus_operations voicebus_operations = { ++ .handle_receive = handle_receive, ++ .handle_transmit = handle_transmit, ++}; ++ ++static const struct voicebus_operations hx8_voicebus_operations = { ++ .handle_receive = handle_hx8_receive, ++ .handle_transmit = handle_hx8_transmit, ++}; ++ ++struct cmd_results { ++ u8 results[8]; ++}; ++ ++static int hx8_send_command(struct wctdm *wc, const u8 *command, ++ size_t count, int checksum, ++ int application, int bootloader, ++ struct cmd_results *results) ++{ ++ int ret = 0; ++ struct vbb *vbb; ++ struct sframe_packet *frame; ++ const int MAX_COMMAND_LENGTH = 264 + 4; ++ unsigned long flags; ++ dma_addr_t dma_addr; ++ ++ might_sleep(); ++ ++ /* can't boot both into the application and the bootloader at once. */ ++ WARN_ON((application > 0) && (bootloader > 0)); ++ if ((application > 0) && (bootloader > 0)) ++ return -EINVAL; ++ ++ WARN_ON(count > MAX_COMMAND_LENGTH); ++ if (count > MAX_COMMAND_LENGTH) ++ return -EINVAL; ++ ++ vbb = dma_pool_alloc(wc->vb.pool, GFP_KERNEL, &dma_addr); ++ WARN_ON(!vbb); ++ if (!vbb) ++ return -ENOMEM; ++ ++ vbb->dma_addr = dma_addr; ++ memset(vbb->data, 0, SFRAME_SIZE); ++ memcpy(&vbb->data[EFRAME_SIZE + EFRAME_GAP], command, count); ++ ++ vbb->data[EFRAME_SIZE] = 0x80 | ((application) ? 0 : 0x40) | ++ ((checksum) ? 0x20 : 0) | ((count & 0x100) >> 4); ++ vbb->data[EFRAME_SIZE + 1] = count & 0xff; ++ ++ if (bootloader) ++ vbb->data[EFRAME_SIZE + 3] = 0xAA; ++ ++ spin_lock_irqsave(&wc->vb.lock, flags); ++ voicebus_transmit(&wc->vb, vbb); ++ spin_unlock_irqrestore(&wc->vb.lock, flags); ++ ++ /* Do not wait for the response if the caller doesn't care about the ++ * results. */ ++ if (NULL == results) ++ return 0; ++ ++ if (!wait_event_timeout(wc->regq, !list_empty(&wc->frame_list), 2*HZ)) { ++ dev_err(&wc->vb.pdev->dev, "Timeout waiting " ++ "for receive frame.\n"); ++ ret = -EIO; ++ } ++ ++ /* We only want the last packet received. Throw away anything else on ++ * the list */ ++ frame = NULL; ++ spin_lock_irqsave(&wc->frame_list_lock, flags); ++ while (!list_empty(&wc->frame_list)) { ++ frame = list_entry(wc->frame_list.next, ++ struct sframe_packet, node); ++ list_del(&frame->node); ++ if (!list_empty(&wc->frame_list)) { ++ kfree(frame); ++ frame = NULL; ++ } ++ } ++ spin_unlock_irqrestore(&wc->frame_list_lock, flags); ++ ++ if (frame) { ++ memcpy(results->results, &frame->sframe[EFRAME_SIZE], ++ sizeof(results->results)); ++ } else { ++ ret = -EIO; ++ } ++ ++ return ret; ++ ++} ++ ++static int hx8_get_fpga_version(struct wctdm *wc, u8 *major, u8 *minor) ++{ ++ int ret; ++ struct cmd_results results; ++ u8 command[] = {0xD7, 0x00}; ++ ++ ret = hx8_send_command(wc, command, ARRAY_SIZE(command), ++ 0, 0, 0, &results); ++ if (ret) ++ return ret; ++ ++ *major = results.results[0]; ++ *minor = results.results[2]; ++ return 0; ++} ++ ++static void hx8_cleanup_frame_list(struct wctdm *wc) ++{ ++ unsigned long flags; ++ LIST_HEAD(local_list); ++ struct sframe_packet *frame; ++ ++ spin_lock_irqsave(&wc->frame_list_lock, flags); ++ list_splice_init(&wc->frame_list, &local_list); ++ spin_unlock_irqrestore(&wc->frame_list_lock, flags); ++ ++ while (!list_empty(&local_list)) { ++ frame = list_entry(local_list.next, struct sframe_packet, node); ++ list_del(&frame->node); ++ kfree(frame); ++ } ++} ++ ++static int hx8_switch_to_application(struct wctdm *wc) ++{ ++ int ret; ++ u8 command[] = {0xD7, 0x00}; ++ ++ ret = hx8_send_command(wc, command, ARRAY_SIZE(command), ++ 0, 1, 0, NULL); ++ if (ret) ++ return ret; ++ ++ msleep(1000); ++ hx8_cleanup_frame_list(wc); ++ ++ return 0; ++} ++ ++/** ++ * hx8_switch_to_bootloader() - Send packet to switch hx8 into bootloader ++ * ++ */ ++static int hx8_switch_to_bootloader(struct wctdm *wc) ++{ ++ int ret; ++ u8 command[] = {0xD7, 0x00}; ++ ++ ret = hx8_send_command(wc, command, ARRAY_SIZE(command), ++ 0, 0, 1, NULL); ++ if (ret) ++ return ret; ++ ++ /* It takes some time for the FPGA to reload and switch it's ++ * configuration. */ ++ msleep(300); ++ hx8_cleanup_frame_list(wc); ++ ++ return 0; ++} ++ ++struct ha80000_firmware { ++ u8 header[6]; ++ u8 major_ver; ++ u8 minor_ver; ++ u8 data[54648]; ++ __le32 chksum; ++} __attribute__((packed)); ++ ++static void hx8_send_dummy(struct wctdm *wc) ++{ ++ u8 command[] = {0xD7, 0x00}; ++ ++ hx8_send_command(wc, command, ARRAY_SIZE(command), ++ 0, 0, 0, NULL); ++} ++ ++static int hx8_read_status_register(struct wctdm *wc, u8 *status) ++{ ++ int ret; ++ struct cmd_results results; ++ u8 command[] = {0xD7, 0x00}; ++ ++ ret = hx8_send_command(wc, command, ARRAY_SIZE(command), ++ 0, 0, 0, &results); ++ if (ret) ++ return ret; ++ ++ *status = results.results[3]; ++ return 0; ++} ++ ++static const unsigned int HYBRID_PAGE_SIZE = 264; ++ ++static int hx8_write_buffer(struct wctdm *wc, const u8 *buffer, size_t size) ++{ ++ int ret = 0; ++ struct cmd_results results; ++ int padding_bytes = 0; ++ u8 *local_data; ++ u8 command[] = {0x84, 0, 0, 0}; ++ ++ if (size > HYBRID_PAGE_SIZE) ++ return -EINVAL; ++ ++ if (size < HYBRID_PAGE_SIZE) ++ padding_bytes = HYBRID_PAGE_SIZE - size; ++ ++ local_data = kmalloc(sizeof(command) + size + padding_bytes, GFP_KERNEL); ++ if (!local_data) ++ return -ENOMEM; ++ ++ memcpy(local_data, command, sizeof(command)); ++ memcpy(&local_data[sizeof(command)], buffer, size); ++ memset(&local_data[sizeof(command) + size], 0xff, padding_bytes); ++ ++ ret = hx8_send_command(wc, local_data, ++ sizeof(command) + size + padding_bytes, ++ 1, 0, 0, &results); ++ if (ret) ++ goto cleanup; ++ ++cleanup: ++ kfree(local_data); ++ return ret; ++} ++ ++static int hx8_buffer_to_page(struct wctdm *wc, const unsigned int page) ++{ ++ int ret; ++ struct cmd_results results; ++ u8 command[] = {0x83, (page & 0x180) >> 7, (page & 0x7f) << 1, 0x00}; ++ ++ ret = hx8_send_command(wc, command, sizeof(command), ++ 1, 0, 0, &results); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int hx8_wait_for_ready(struct wctdm *wc, const int timeout) ++{ ++ int ret; ++ u8 status; ++ unsigned long local_timeout = jiffies + timeout; ++ ++ do { ++ ret = hx8_read_status_register(wc, &status); ++ if (ret) ++ return ret; ++ if ((status & 0x80) > 0) ++ break; ++ } while (time_after(local_timeout, jiffies)); ++ ++ if (time_after(jiffies, local_timeout)) ++ return -EIO; ++ ++ return 0; ++} ++ ++/** ++ * hx8_reload_application - reload the application firmware ++ * ++ * NOTE: The caller should ensure that the board is in bootloader mode before ++ * calling this function. ++ */ ++static int hx8_reload_application(struct wctdm *wc, const struct ha80000_firmware *ha8_fw) ++{ ++ unsigned int cur_page; ++ const u8 *data; ++ u8 status; ++ int ret = 0; ++ const int HYBRID_PAGE_COUNT = (sizeof(ha8_fw->data)) / HYBRID_PAGE_SIZE; ++ ++ dev_info(&wc->vb.pdev->dev, "Reloading firmware. Do not power down " ++ "the system until the process is complete.\n"); ++ ++ BUG_ON(!ha8_fw); ++ might_sleep(); ++ ++ data = &ha8_fw->data[0]; ++ ret = hx8_read_status_register(wc, &status); ++ if (ret) ++ return ret; ++ ++ for (cur_page = 0; cur_page < HYBRID_PAGE_COUNT; ++cur_page) { ++ ret = hx8_write_buffer(wc, data, HYBRID_PAGE_SIZE); ++ if (ret) ++ return ret; ++ /* The application starts out at page 0x100 */ ++ ret = hx8_buffer_to_page(wc, 0x100 + cur_page); ++ if (ret) ++ return ret; ++ ++ /* wait no more than a second for the write to the page to ++ * finish */ ++ ret = hx8_wait_for_ready(wc, HZ); ++ if (ret) ++ return ret; ++ ++ data += HYBRID_PAGE_SIZE; ++ } ++ ++ return ret; ++} ++ ++static void print_hx8_recovery_message(struct device *dev) ++{ ++ dev_warn(dev, "The firmware may be corrupted. Please completely " ++ "power off your system, power on, and then reload the driver " ++ "with the 'forceload' module parameter set to 1 to attempt " ++ "recovery.\n"); ++} ++ ++/** ++ * hx8_check_firmware - Check the firmware version and load a new one possibly. ++ * ++ */ ++static int hx8_check_firmware(struct wctdm *wc) ++{ ++ int ret; ++ u8 major; ++ u8 minor; ++ const struct firmware *fw; ++ const struct ha80000_firmware *ha8_fw; ++ struct device *dev = &wc->vb.pdev->dev; ++ int retries = 10; ++ ++ BUG_ON(!is_hx8(wc)); ++ ++ might_sleep(); ++ ++ do { ++ hx8_send_dummy(wc); ++ ret = hx8_get_fpga_version(wc, &major, &minor); ++ if (!ret) ++ break; ++ if (fatal_signal_pending(current)) ++ return -EINTR; ++ } while (--retries); ++ ++ if (ret) { ++ print_hx8_recovery_message(dev); ++ return ret; ++ } ++ ++ /* If we're in the bootloader, try to jump into the application. */ ++ if ((1 == major) && (0x80 == minor) && !forceload) { ++ dev_dbg(dev, "Switching to application.\n"); ++ hx8_switch_to_application(wc); ++ ret = hx8_get_fpga_version(wc, &major, &minor); ++ if (ret) { ++ print_hx8_recovery_message(dev); ++ return ret; ++ } ++ } ++ ++ dev_dbg(dev, "FPGA VERSION: %02x.%02x\n", major, minor); ++ ++ ret = request_firmware(&fw, "dahdi-fw-hx8.bin", dev); ++ if (ret) { ++ dev_warn(dev, "Failed to load firmware from userspace, skipping " ++ "check. (%d)\n", ret); ++ return 0; ++ } ++ ha8_fw = (const struct ha80000_firmware *)fw->data; ++ ++ if ((fw->size != sizeof(*ha8_fw)) || ++ (0 != memcmp("DIGIUM", ha8_fw->header, sizeof(ha8_fw->header))) || ++ ((crc32(~0, (void *)ha8_fw, sizeof(*ha8_fw) - sizeof(u32)) ^ ~0) != ++ le32_to_cpu(ha8_fw->chksum))) { ++ dev_warn(dev, "Firmware file is invalid. Skipping load.\n"); ++ ret = 0; ++ goto cleanup; ++ } ++ ++ dev_dbg(dev, "FIRMWARE: %02x.%02x\n", ha8_fw->major_ver, ha8_fw->minor_ver); ++ ++ if (ha8_fw->major_ver == major && ++ ha8_fw->minor_ver == minor) { ++ dev_dbg(dev, "Firmware versions match, skipping load.\n"); ++ ret = 0; ++ goto cleanup; ++ } ++ ++ if (2 == major) { ++ hx8_switch_to_bootloader(wc); ++ ret = hx8_get_fpga_version(wc, &major, &minor); ++ if (ret) ++ goto cleanup; ++ } ++ ++ /* so now we're in boot loader mode, ready to load the new firmware. */ ++ ret = hx8_reload_application(wc, ha8_fw); ++ if (ret) ++ goto cleanup; ++ ++ dev_dbg(dev, "Firmware reloaded. Booting into application.\n"); ++ ++ hx8_switch_to_application(wc); ++ ret = hx8_get_fpga_version(wc, &major, &minor); ++ if (ret) ++ goto cleanup; ++ ++ dev_dbg(dev, "FPGA VERSION AFTER LOAD: %02x.%02x\n", major, minor); ++ ++ if (forceload) { ++ dev_warn(dev, "Please unset forceload if your card is able to " ++ "detect the installed modules.\n"); ++ } ++ ++cleanup: ++ release_firmware(fw); ++ dev_info(dev, "Hx8 firmware version: %d.%02d\n", major, minor); ++ return ret; ++} ++ ++#ifdef CONFIG_VOICEBUS_SYSFS ++static ssize_t ++voicebus_current_latency_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ struct wctdm *wc = dev_get_drvdata(dev); ++ unsigned int current_latency; ++ spin_lock_irqsave(&wc->vb.lock, flags); ++ current_latency = wc->vb.min_tx_buffer_count; ++ spin_unlock_irqrestore(&wc->vb.lock, flags); ++ return sprintf(buf, "%d\n", current_latency); ++} ++ ++static DEVICE_ATTR(voicebus_current_latency, 0400, ++ voicebus_current_latency_show, NULL); ++ ++static ssize_t vpm_firmware_version_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int res; ++ u16 version = 0; ++ struct wctdm *wc = dev_get_drvdata(dev); ++ ++ if (wc->vpmadt032) { ++ res = gpakPingDsp(wc->vpmadt032->dspid, &version); ++ if (res) { ++ dev_info(&wc->vb.pdev->dev, "Failed gpakPingDsp %d\n", res); ++ version = -1; ++ } ++ } ++ ++ return sprintf(buf, "%x.%02x\n", (version & 0xff00) >> 8, (version & 0xff)); ++} ++ ++static DEVICE_ATTR(vpm_firmware_version, 0400, ++ vpm_firmware_version_show, NULL); ++static ssize_t ++enable_vpm_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ struct wctdm *wc = dev_get_drvdata(dev); ++ unsigned int enable_vpm; ++ spin_lock_irqsave(&wc->reglock, flags); ++ enable_vpm = (wc->ctlreg & 0x10) != 0; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return sprintf(buf, "%d\n", enable_vpm); ++} ++ ++static ssize_t ++enable_vpm_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned long flags; ++ struct wctdm *wc = dev_get_drvdata(dev); ++ unsigned int enable_vpm; ++ if (count < 2) ++ return -EINVAL; ++ ++ if (('0' == buf[0]) || (0 == buf[0])) ++ enable_vpm = 0; ++ else ++ enable_vpm = 1; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (enable_vpm) ++ wc->ctlreg |= 0x10; ++ else ++ wc->ctlreg &= ~0x10; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return count; ++} ++ ++static DEVICE_ATTR(enable_vpm, 0644, ++ enable_vpm_show, enable_vpm_store); ++ ++static void create_sysfs_files(struct wctdm *wc) ++{ ++ int ret; ++ ret = device_create_file(&wc->vb.pdev->dev, ++ &dev_attr_voicebus_current_latency); ++ if (ret) { ++ dev_info(&wc->vb.pdev->dev, ++ "Failed to create device attributes.\n"); ++ } ++ ++ ret = device_create_file(&wc->vb.pdev->dev, ++ &dev_attr_vpm_firmware_version); ++ if (ret) { ++ dev_info(&wc->vb.pdev->dev, ++ "Failed to create device attributes.\n"); ++ } ++ ++ ret = device_create_file(&wc->vb.pdev->dev, ++ &dev_attr_enable_vpm); ++ if (ret) { ++ dev_info(&wc->vb.pdev->dev, ++ "Failed to create device attributes.\n"); ++ } ++} ++ ++static void remove_sysfs_files(struct wctdm *wc) ++{ ++ device_remove_file(&wc->vb.pdev->dev, ++ &dev_attr_enable_vpm); ++ ++ device_remove_file(&wc->vb.pdev->dev, ++ &dev_attr_vpm_firmware_version); ++ ++ device_remove_file(&wc->vb.pdev->dev, ++ &dev_attr_voicebus_current_latency); ++} ++ ++#else ++ ++static inline void create_sysfs_files(struct wctdm *wc) { return; } ++static inline void remove_sysfs_files(struct wctdm *wc) { return; } ++ ++#endif /* CONFIG_VOICEBUS_SYSFS */ ++ ++static void wctdm_set_tdm410_leds(struct wctdm *wc) ++{ ++ int i; ++ ++ if (4 != wc->desc->ports) ++ return; ++ ++ wc->tdm410leds = 0; /* all on by default */ ++ for (i = 0; i < wc->desc->ports; ++i) { ++ /* Turn off the LED for any module that isn't installed. */ ++ if (NONE == wc->mods[i].type) ++ wc->tdm410leds |= (1 << i); ++ } ++} ++ ++/** ++ * wctdm_allocate_irq_commands - Preallocate some commands for use in interrupt context. ++ * @wc: The board which we're allocating for. ++ * @count: The number of IRQ commands to allocate. ++ * ++ * We need a minimum of 4 * the current latency worth of commands for each ++ * analog module. When the latency grows, new commands will be allocated, but ++ * this just represents are best guess as to the number of commands we'll need ++ * after probing for modules, and reduces the chance that we'll allocate ++ * memory in interrupt context when the driver first loads. ++ * ++ */ ++static void wctdm_allocate_irq_commands(struct wctdm *wc, unsigned int count) ++{ ++ unsigned long flags; ++ LIST_HEAD(local_list); ++ ++ if (!count) ++ return; ++ ++ while (count--) { ++ struct wctdm_cmd *cmd; ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ break; ++ list_add(&cmd->node, &local_list); ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ list_splice(&local_list, &wc->free_isr_commands); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++#ifdef USE_ASYNC_INIT ++struct async_data { ++ struct pci_dev *pdev; ++ const struct pci_device_id *ent; ++}; ++static int __devinit ++__wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent, ++ async_cookie_t cookie) ++#else ++static int __devinit ++__wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++#endif ++{ ++ struct wctdm *wc; ++ unsigned int pos; ++ int i, ret; ++ struct bg *vpm_work; ++ int anamods, digimods, curchan, curspan; ++ ++ neonmwi_offlimit_cycles = neonmwi_offlimit / MS_PER_HOOKCHECK; ++ ++ wc = kzalloc(sizeof(*wc), GFP_KERNEL); ++ if (!wc) ++ return -ENOMEM; ++ ++ wc->not_ready = 1; ++ ++ down(&ifacelock); ++ /* \todo this is a candidate for removal... */ ++ for (pos = 0; pos < WC_MAX_IFACES; ++pos) { ++ if (!ifaces[pos]) { ++ ifaces[pos] = wc; ++ break; ++ } ++ } ++ up(&ifacelock); ++ ++ wc->desc = (struct wctdm_desc *)ent->driver_data; ++ ++ /* This is to insure that the analog span is given lowest priority */ ++ sema_init(&wc->syncsem, 1); ++ INIT_LIST_HEAD(&wc->frame_list); ++ spin_lock_init(&wc->frame_list_lock); ++ init_waitqueue_head(&wc->regq); ++ spin_lock_init(&wc->reglock); ++ INIT_LIST_HEAD(&wc->free_isr_commands); ++ wc->oldsync = -1; ++ ++ wc->board_name = kasprintf(GFP_KERNEL, "%s%d", wctdm_driver.name, pos); ++ if (!wc->board_name) { ++ wctdm_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ ++#ifdef CONFIG_VOICEBUS_ECREFERENCE ++ for (i = 0; i < ARRAY_SIZE(wc->ec_reference); ++i) { ++ /* 256 is the smallest power of 2 that will contains the ++ * maximum possible amount of latency. */ ++ wc->ec_reference[i] = dahdi_fifo_alloc(256, GFP_KERNEL); ++ ++ if (IS_ERR(wc->ec_reference[i])) { ++ ret = PTR_ERR(wc->ec_reference[i]); ++ wc->ec_reference[i] = NULL; ++ wctdm_back_out_gracefully(wc); ++ return ret; ++ } ++ } ++#endif ++ ++ pci_set_drvdata(pdev, wc); ++ wc->vb.ops = &voicebus_operations; ++ wc->vb.pdev = pdev; ++ wc->vb.debug = &debug; ++ ++#ifdef CONFIG_VOICEBUS_DISABLE_ASPM ++ if (is_pcie(wc)) { ++ pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S | ++ PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); ++ }; ++#endif ++ ++ if (is_hx8(wc)) { ++ wc->vb.ops = &hx8_voicebus_operations; ++ ret = voicebus_boot_init(&wc->vb, wc->board_name); ++ } else { ++ wc->vb.ops = &voicebus_operations; ++ ret = voicebus_init(&wc->vb, wc->board_name); ++ voicebus_set_minlatency(&wc->vb, latency); ++ voicebus_set_maxlatency(&wc->vb, max_latency); ++ } ++ ++ if (ret) { ++ wctdm_back_out_gracefully(wc); ++ return ret; ++ } ++ ++ create_sysfs_files(wc); ++ ++ voicebus_lock_latency(&wc->vb); ++ ++ wc->mods_per_board = NUM_MODULES; ++ wc->txident = 1; ++ ++ if (alawoverride) { ++ companding = "alaw"; ++ dev_info(&wc->vb.pdev->dev, "The module parameter alawoverride"\ ++ " has been deprecated. Please use the "\ ++ "parameter companding=alaw instead"); ++ } ++ ++ if (!strcasecmp(companding, "alaw")) ++ /* Force this card's companding to alaw */ ++ wc->companding = DAHDI_LAW_ALAW; ++ else if (!strcasecmp(companding, "ulaw")) ++ /* Force this card's companding to ulaw */ ++ wc->companding = DAHDI_LAW_MULAW; ++ else ++ /* Auto detect this card's companding */ ++ wc->companding = DAHDI_LAW_DEFAULT; ++ ++ for (i = 0; i < ARRAY_SIZE(wc->mods); i++) { ++ struct wctdm_module *const mod = &wc->mods[i]; ++ INIT_LIST_HEAD(&mod->pending_cmds); ++ INIT_LIST_HEAD(&mod->active_cmds); ++ mod->dacssrc = -1; ++ mod->card = i; ++ set_offsets(mod, 0); ++ } ++ ++ /* Start the hardware processing. */ ++ if (voicebus_start(&wc->vb)) { ++ BUG_ON(1); ++ } ++ ++ if (is_hx8(wc)) { ++ ret = hx8_check_firmware(wc); ++ if (ret) { ++ wctdm_back_out_gracefully(wc); ++ return -EIO; ++ } ++ ++ /* Switch to the normal operating mode for this card. */ ++ voicebus_stop(&wc->vb); ++ wc->vb.ops = &voicebus_operations; ++ voicebus_set_minlatency(&wc->vb, latency); ++ voicebus_set_maxlatency(&wc->vb, max_latency); ++ voicebus_set_hx8_mode(&wc->vb); ++ if (voicebus_start(&wc->vb)) ++ BUG_ON(1); ++ } ++ ++/* first we have to make sure that we process all module data, we'll fine-tune it later in this routine. */ ++ wc->avchannels = NUM_MODULES; ++ ++ vpm_work = bg_create(wc, wctdm_initialize_vpm, 0); ++ if (!vpm_work) { ++ wctdm_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ ++ /* Now track down what modules are installed */ ++ wctdm_identify_modules(wc); ++ ++ wctdm_set_tdm410_leds(wc); ++ ++ if (fatal_signal_pending(current)) { ++ wctdm_back_out_gracefully(wc); ++ bg_join(vpm_work); ++ return -EINTR; ++ } ++ ++ /* We need to wait for the vpm thread to finish before we setup the ++ * spans in order to ensure they are named properly. */ ++ bg_join(vpm_work); ++ ++/* ++ * Walk the module list and create a 3-channel span for every BRI module found. ++ * Empty and analog modules get a common span which is allocated outside of this loop. ++ */ ++ anamods = digimods = 0; ++ curchan = curspan = 0; ++ ++ for (i = 0; i < wc->mods_per_board; i++) { ++ struct wctdm_module *const mod = &wc->mods[i]; ++ struct b400m *b4; ++ ++ if (mod->type == NONE) { ++ ++curspan; ++ continue; ++ } else if (mod->type == BRI) { ++ if (!is_hx8(wc)) { ++ dev_info(&wc->vb.pdev->dev, "Digital modules " ++ "detected on a non-hybrid card. " ++ "This is unsupported.\n"); ++ wctdm_back_out_gracefully(wc); ++ bg_join(vpm_work); ++ return -EIO; ++ } ++ wc->spans[curspan] = wctdm_init_span(wc, curspan, ++ curchan, 3, 1, ++ pos); ++ if (!wc->spans[curspan]) { ++ wctdm_back_out_gracefully(wc); ++ bg_join(vpm_work); ++ return -EIO; ++ } ++ b4 = mod->mod.bri; ++ b400m_set_dahdi_span(b4, i & 0x03, wc->spans[curspan]); ++ ++ ++curspan; ++ curchan += 3; ++ if (!(i & 0x03)) { ++ b400m_post_init(b4); ++ ++digimods; ++ } ++ } else { ++/* ++ * FIXME: ABK: ++ * create a wctdm_chan for every analog module and link them into a span of their own down below. ++ * then evaluate all of the callbacks and hard-code whether they are receiving a dahdi_chan or wctdm_chan *. ++ * Finally, move the union from the wctdm structure to the dahdi_chan structure, and we should have something ++ * resembling a clean dynamic # of channels/dynamic # of spans driver. ++ */ ++ ++curspan; ++ ++anamods; ++ } ++ ++ if (digimods > 2) { ++ dev_info(&wc->vb.pdev->dev, "More than two digital modules detected. This is unsupported.\n"); ++ wctdm_back_out_gracefully(wc); ++ return -EIO; ++ } ++ } ++ ++ wc->digi_mods = digimods; ++ ++/* create an analog span if there are analog modules, or if there are no digital ones. */ ++ if (anamods || !digimods) { ++ if (!digimods) { ++ curspan = 0; ++ } ++ wctdm_init_span(wc, curspan, curchan, wc->desc->ports, 0, pos); ++ wctdm_fixup_analog_span(wc, curspan); ++ wc->aspan = wc->spans[curspan]; ++ curchan += wc->desc->ports; ++ ++curspan; ++ } ++ ++ /* Now fix up the timeslots for the analog modules, since the digital ++ * modules are always first */ ++ for (i = 0; i < wc->mods_per_board; i++) { ++ struct wctdm_module *const mod = &wc->mods[i]; ++ switch (mod->type) { ++ case FXS: ++ wctdm_proslic_set_ts(wc, mod, (digimods * 12) + i); ++ break; ++ case FXO: ++ wctdm_voicedaa_set_ts(wc, mod, (digimods * 12) + i); ++ break; ++ case QRV: ++ wctdm_qrvdri_set_ts(wc, mod, (digimods * 12) + i); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ /* This shouldn't ever occur, but if we don't try to trap it, the driver ++ * will be scribbling into memory it doesn't own. */ ++ BUG_ON(curchan > 24); ++ ++ wc->avchannels = curchan; ++ ++#ifdef USE_ASYNC_INIT ++ async_synchronize_cookie(cookie); ++#endif ++ wc->ddev = dahdi_create_device(); ++ wc->ddev->manufacturer = "Digium"; ++ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI%s Bus %02d Slot %02d", ++ (wc->desc->flags & FLAG_EXPRESS) ? ++ " Express" : "", ++ pdev->bus->number, ++ PCI_SLOT(pdev->devfn) + 1); ++ if (!wc->ddev->location) { ++ wctdm_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ ++ if (wc->vpmadt032) { ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPMADT032)", ++ wc->desc->name); ++ } else if (wc->vpmoct) { ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPMOCT032)", ++ wc->desc->name); ++ } else { ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", ++ wc->desc->name); ++ } ++ ++ if (!wc->ddev->devicetype) { ++ wctdm_back_out_gracefully(wc); ++ return -ENOMEM; ++ } ++ ++ /* We should be ready for DAHDI to come in now. */ ++ for (i = 0; i < MAX_SPANS; ++i) { ++ struct dahdi_span *span; ++ ++ if (!wc->spans[i]) ++ continue; ++ ++ span = &wc->spans[i]->span; ++ ++ list_add_tail(&span->device_node, &wc->ddev->spans); ++ } ++ ++ wctdm_allocate_irq_commands(wc, anamods * latency * 4); ++ ++ if (dahdi_register_device(wc->ddev, &wc->vb.pdev->dev)) { ++ dev_notice(&wc->vb.pdev->dev, "Unable to register device with DAHDI\n"); ++ wctdm_back_out_gracefully(wc); ++ return -1; ++ } ++ ++ WARN_ON(wc->not_ready <= 0); ++ --wc->not_ready; ++ ++ dev_info(&wc->vb.pdev->dev, ++ "Found a %s: %s (%d BRI spans, %d analog %s)\n", ++ (is_hx8(wc)) ? "Hybrid card" : "Wildcard TDM", ++ wc->desc->name, digimods*4, anamods, ++ (anamods == 1) ? "channel" : "channels"); ++ ret = 0; ++ ++ voicebus_unlock_latency(&wc->vb); ++ return 0; ++} ++ ++#ifdef USE_ASYNC_INIT ++static __devinit void ++wctdm_init_one_async(void *data, async_cookie_t cookie) ++{ ++ struct async_data *dat = data; ++ __wctdm_init_one(dat->pdev, dat->ent, cookie); ++ kfree(dat); ++} ++ ++static int __devinit ++wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ struct async_data *dat; ++ ++ dat = kmalloc(sizeof(*dat), GFP_KERNEL); ++ /* If we can't allocate the memory for the async_data, odds are we won't ++ * be able to initialize the device either, but let's try synchronously ++ * anyway... */ ++ if (!dat) ++ return __wctdm_init_one(pdev, ent, 0); ++ ++ dat->pdev = pdev; ++ dat->ent = ent; ++ async_schedule(wctdm_init_one_async, dat); ++ return 0; ++} ++#else ++static int __devinit ++wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ return __wctdm_init_one(pdev, ent); ++} ++#endif ++ ++ ++static void wctdm_release(struct wctdm *wc) ++{ ++ int i; ++ ++ if (is_initialized(wc)) ++ dahdi_unregister_device(wc->ddev); ++ ++ down(&ifacelock); ++ for (i = 0; i < WC_MAX_IFACES; i++) ++ if (ifaces[i] == wc) ++ break; ++ ifaces[i] = NULL; ++ up(&ifacelock); ++ ++ wctdm_back_out_gracefully(wc); ++} ++ ++static void __devexit wctdm_remove_one(struct pci_dev *pdev) ++{ ++ int i; ++ unsigned long flags; ++ struct wctdm *wc = pci_get_drvdata(pdev); ++ struct vpmadt032 *vpmadt032; ++ struct vpmoct *vpmoct; ++ ++ if (!wc) ++ return; ++ ++ vpmadt032 = wc->vpmadt032; ++ vpmoct = wc->vpmoct; ++ ++ remove_sysfs_files(wc); ++ ++ if (vpmadt032) { ++ flush_workqueue(vpmadt032->wq); ++ clear_bit(VPM150M_ACTIVE, &vpmadt032->control); ++ flush_workqueue(vpmadt032->wq); ++ } else if (vpmoct) { ++ while (wctdm_wait_for_ready(wc)) ++ schedule(); ++ } ++ ++ flush_scheduled_work(); ++ ++ /* shut down any BRI modules */ ++ for (i = 0; i < wc->mods_per_board; i += 4) { ++ if (wc->mods[i].type == BRI) ++ wctdm_unload_b400m(wc, i); ++ } ++ ++ voicebus_stop(&wc->vb); ++ ++ if (vpmadt032) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->vpmadt032 = NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ vpmadt032_free(vpmadt032); ++ } else if (vpmoct) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->vpmoct = NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ vpmoct_free(vpmoct); ++ } ++ ++ dev_info(&wc->vb.pdev->dev, "Freed a %s\n", ++ (is_hx8(wc)) ? "Hybrid card" : "Wildcard"); ++ ++ /* Release span */ ++ wctdm_release(wc); ++} ++ ++static DEFINE_PCI_DEVICE_TABLE(wctdm_pci_tbl) = { ++ { 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 }, ++ { 0xd161, 0x8003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex2400 }, ++ { 0xd161, 0x8007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcha80000 }, ++ { 0xd161, 0x8008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wchb80000 }, ++ { 0 } ++}; ++ ++static void wctdm_shutdown(struct pci_dev *pdev) ++{ ++ struct wctdm *wc = pci_get_drvdata(pdev); ++ voicebus_quiesce(&wc->vb); ++} ++ ++MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl); ++ ++static int wctdm_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ return -ENOSYS; ++} ++ ++static struct pci_driver wctdm_driver = { ++ .name = "wctdm24xxp", ++ .probe = wctdm_init_one, ++ .remove = __devexit_p(wctdm_remove_one), ++ .shutdown = wctdm_shutdown, ++ .suspend = wctdm_suspend, ++ .id_table = wctdm_pci_tbl, ++}; ++ ++static int __init wctdm_init(void) ++{ ++ int res; ++ int x; ++ ++ for (x = 0; x < ARRAY_SIZE(fxo_modes); x++) { ++ if (!strcmp(fxo_modes[x].name, opermode)) ++ break; ++ } ++ if (x < ARRAY_SIZE(fxo_modes)) { ++ _opermode = x; ++ } else { ++ printk(KERN_NOTICE "Invalid/unknown operating mode '%s' " ++ "specified. Please choose one of:\n", opermode); ++ for (x = 0; x < ARRAY_SIZE(fxo_modes); x++) ++ printk(KERN_CONT " %s\n", fxo_modes[x].name); ++ printk(KERN_NOTICE "Note this option is CASE SENSITIVE!\n"); ++ return -ENODEV; ++ } ++ ++ if (!strcmp(opermode, "AUSTRALIA")) { ++ boostringer = 1; ++ fxshonormode = 1; ++ } ++ ++ if (-1 == fastpickup) { ++ if (!strcmp(opermode, "JAPAN")) ++ fastpickup = 1; ++ else ++ fastpickup = 0; ++ } ++ ++ /* for the voicedaa_check_hook defaults, if the user has not overridden ++ them by specifying them as module parameters, then get the values ++ from the selected operating mode ++ */ ++ if (battdebounce == 0) { ++ battdebounce = fxo_modes[_opermode].battdebounce; ++ } ++ if (battalarm == 0) { ++ battalarm = fxo_modes[_opermode].battalarm; ++ } ++ if (battthresh == 0) { ++ battthresh = fxo_modes[_opermode].battthresh; ++ } ++ ++ b400m_module_init(); ++ ++ res = pci_register_driver(&wctdm_driver); ++ if (res) ++ return -ENODEV; ++ ++#ifdef USE_ASYNC_INIT ++ async_synchronize_full(); ++#endif ++ return 0; ++} ++ ++static void __exit wctdm_cleanup(void) ++{ ++ pci_unregister_driver(&wctdm_driver); ++} ++ ++ ++module_param(debug, int, 0600); ++module_param(fastpickup, int, 0400); ++MODULE_PARM_DESC(fastpickup, ++ "Set to 1 to shorten the calibration delay when taking " \ ++ "an FXO port off hook. This can be required for Type-II " \ ++ "CID. If -1 the calibration delay will depend on the " \ ++ "current opermode.\n"); ++module_param(fxovoltage, int, 0600); ++module_param(loopcurrent, int, 0600); ++module_param(reversepolarity, int, 0600); ++#ifdef DEBUG ++module_param(robust, int, 0600); ++module_param(digitalloopback, int, 0400); ++MODULE_PARM_DESC(digitalloopback, "Set to 1 to place FXO modules into " \ ++ "loopback mode for troubleshooting."); ++#endif ++module_param(opermode, charp, 0600); ++module_param(lowpower, int, 0600); ++module_param(boostringer, int, 0600); ++module_param(fastringer, int, 0600); ++module_param(fxshonormode, int, 0600); ++module_param(battdebounce, uint, 0600); ++module_param(battalarm, uint, 0600); ++module_param(battthresh, uint, 0600); ++module_param(nativebridge, int, 0600); ++module_param(fxotxgain, int, 0600); ++module_param(fxorxgain, int, 0600); ++module_param(fxstxgain, int, 0600); ++module_param(fxsrxgain, int, 0600); ++module_param(ringdebounce, int, 0600); ++module_param(latency, int, 0400); ++module_param(max_latency, int, 0400); ++module_param(neonmwi_monitor, int, 0600); ++module_param(neonmwi_level, int, 0600); ++module_param(neonmwi_envelope, int, 0600); ++module_param(neonmwi_offlimit, int, 0600); ++#ifdef VPM_SUPPORT ++module_param(vpmsupport, int, 0400); ++module_param(vpmnlptype, int, 0400); ++module_param(vpmnlpthresh, int, 0400); ++module_param(vpmnlpmaxsupp, int, 0400); ++#endif ++ ++/* Module parameters backed by code in xhfc.c */ ++module_param(bri_debug, int, 0600); ++MODULE_PARM_DESC(bri_debug, "bitmap: 1=general 2=dtmf 4=regops 8=fops 16=ec 32=st state 64=hdlc 128=alarm"); ++ ++module_param(bri_spanfilter, int, 0600); ++MODULE_PARM_DESC(bri_spanfilter, "debug filter for spans. bitmap: 1=port 1, 2=port 2, 4=port 3, 8=port 4"); ++ ++module_param(bri_alarmdebounce, int, 0600); ++MODULE_PARM_DESC(bri_alarmdebounce, "msec to wait before set/clear alarm condition"); ++ ++module_param(bri_teignorered, int, 0600); ++MODULE_PARM_DESC(bri_teignorered, "1=ignore (do not inform DAHDI) if a red alarm exists in TE mode"); ++ ++module_param(bri_persistentlayer1, int, 0600); ++MODULE_PARM_DESC(bri_persistentlayer1, "Set to 0 for disabling automatic layer 1 reactivation (when other end deactivates it)"); ++ ++module_param(timingcable, int, 0600); ++MODULE_PARM_DESC(timingcable, "Set to 1 for enabling timing cable. This means that *all* cards in the system are linked together with a single timing cable"); ++ ++module_param(forceload, int, 0600); ++MODULE_PARM_DESC(forceload, "Set to 1 in order to force an FPGA reload after power on (currently only for HA8/HB8 cards)."); ++ ++module_param(alawoverride, int, 0400); ++MODULE_PARM_DESC(alawoverride, "This option has been deprecated. Please use "\ ++ "the parameter \"companding\" instead"); ++ ++module_param(companding, charp, 0400); ++MODULE_PARM_DESC(companding, "Change the companding to \"auto\" or \"alaw\" " \ ++ "or \"ulaw\". Auto (default) will set everything to ulaw " \ ++ "unless a BRI module is installed. It will use alaw in that " ++ "case."); ++ ++MODULE_DESCRIPTION("VoiceBus Driver for Wildcard Analog and Hybrid Cards"); ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_ALIAS("wctdm8xxp"); ++MODULE_ALIAS("wctdm4xxp"); ++MODULE_ALIAS("wcaex24xx"); ++MODULE_ALIAS("wcaex8xx"); ++MODULE_ALIAS("wcaex4xx"); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(wctdm_init); ++module_exit(wctdm_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/wctdm24xxp/wctdm24xxp.h linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/wctdm24xxp.h +--- linux-source-4.19/drivers/dahdi/wctdm24xxp/wctdm24xxp.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/wctdm24xxp.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,319 @@ ++/* ++ * Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface ++ * ++ * Written by Mark Spencer ++ * Support for TDM800P and VPM150M by Matthew Fredrickson ++ * ++ * Copyright (C) 2005-2010 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 _WCTDM24XXP_H ++#define _WCTDM24XXP_H ++ ++#include ++ ++#include ++#include ++ ++#include "voicebus/voicebus.h" ++ ++#define NUM_FXO_REGS 60 ++ ++#define WC_MAX_IFACES 128 ++ ++/*! ++ * \brief Default ringer debounce (in ms) ++ */ ++#define DEFAULT_RING_DEBOUNCE 1024 ++#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */ ++ ++#define OHT_TIMER 6000 /* How long after RING to retain OHT */ ++ ++#define FLAG_EXPRESS (1 << 0) ++ ++#define EFRAME_SIZE 108L ++#define EFRAME_GAP 20L ++#define SFRAME_SIZE ((EFRAME_SIZE * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_CHUNKSIZE - 1))) ++ ++#define MAX_ALARMS 10 ++ ++#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ ++#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ ++#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ ++ ++#define SDI_CLK (0x00010000) ++#define SDI_DOUT (0x00020000) ++#define SDI_DREAD (0x00040000) ++#define SDI_DIN (0x00080000) ++ ++#define __CMD_RD (1 << 20) /* Read Operation */ ++#define __CMD_WR (1 << 21) /* Write Operation */ ++#define __CMD_FIN (1 << 22) /* Has finished receive */ ++#define __CMD_TX (1 << 23) /* Has been transmitted */ ++ ++#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR) ++#define CMD_RD(a) (((a) << 8) | __CMD_RD) ++ ++#if 0 ++#define CMD_BYTE(card,bit,altcs) (((((card) & 0x3) * 3 + (bit)) * 7) \ ++ + ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0)) ++#endif ++#define NUM_MODULES 24 ++#define NUM_SLOTS 6 ++#define MAX_SPANS 9 ++ ++#define NUM_CAL_REGS 12 ++ ++#define QRV_DEBOUNCETIME 20 ++ ++#define VPM150M_HPI_CONTROL 0x00 ++#define VPM150M_HPI_ADDRESS 0x02 ++#define VPM150M_HPI_DATA 0x03 ++ ++#define VPM_SUPPORT ++#define VPM150M_SUPPORT ++ ++#ifdef VPM150M_SUPPORT ++#include "voicebus/GpakCust.h" ++#endif ++ ++#include "voicebus/vpmoct.h" ++ ++struct calregs { ++ unsigned char vals[NUM_CAL_REGS]; ++}; ++ ++enum battery_state { ++ BATTERY_UNKNOWN = 0, ++ BATTERY_DEBOUNCING_PRESENT, ++ BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM, ++ BATTERY_DEBOUNCING_PRESENT_ALARM, ++ BATTERY_PRESENT, ++ BATTERY_DEBOUNCING_LOST, ++ BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM, ++ BATTERY_DEBOUNCING_LOST_ALARM, ++ BATTERY_LOST, ++}; ++ ++enum ring_detector_state { ++ RINGOFF = 0, ++ DEBOUNCING_RINGING_POSITIVE, ++ DEBOUNCING_RINGING_NEGATIVE, ++ RINGING, ++ DEBOUNCING_RINGOFF, ++}; ++ ++enum polarity_state { ++ UNKNOWN_POLARITY = 0, ++ POLARITY_DEBOUNCE_POSITIVE, ++ POLARITY_POSITIVE, ++ POLARITY_DEBOUNCE_NEGATIVE, ++ POLARITY_NEGATIVE, ++}; ++ ++struct wctdm_cmd { ++ struct list_head node; ++ struct completion *complete; ++ u32 cmd; ++ u8 ident; ++}; ++ ++/** ++ * struct wctdm_span - ++ * @span: dahdi_span to register. ++ * @timing_priority: What the priority of this span is relative to the other ++ * spans. ++ * @spanno: Which span on the card this is. ++ * ++ * NOTE: spanno would normally be taken care of by dahdi_span.offset, but ++ * appears to have meaning in xhfc.c, and that needs to be audited before ++ * changing. !!!TODO!!! ++ * ++ */ ++struct wctdm_span { ++ struct dahdi_span span; ++ int timing_priority; ++ int spanno; ++ struct wctdm *wc; ++ struct b400m_span *bspan; ++}; ++ ++struct wctdm_chan { ++ struct dahdi_chan chan; ++ struct dahdi_echocan_state ec; ++ int timeslot; ++ unsigned int hwpreec_enabled:1; ++}; ++ ++struct fxo { ++ enum ring_detector_state ring_state:4; ++ enum battery_state battery_state:4; ++ enum polarity_state polarity_state:4; ++ u8 ring_polarity_change_count:4; ++ u8 hook_ring_shadow; ++ s8 line_voltage_status; ++ int offhook; ++ int neonmwi_state; ++ int neonmwi_last_voltage; ++ unsigned int neonmwi_debounce; ++ unsigned int neonmwi_offcounter; ++ unsigned long display_fxovoltage; ++ unsigned long ringdebounce_timer; ++ unsigned long battdebounce_timer; ++ unsigned long poldebounce_timer; ++}; ++ ++struct fxs { ++ u8 oht_active:1; ++ u8 off_hook:1; ++ int idletxhookstate; /* IDLE changing hook state */ ++/* lasttxhook reflects the last value written to the proslic's reg ++* 64 (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last ++* write is pending i.e. it is in process of being written to the ++* register ++* NOTE: in order for this value to actually be written to the ++* proslic, the appropriate matching value must be written into the ++* sethook variable so that it gets queued and handled by the ++* voicebus ISR. ++*/ ++ int lasttxhook; ++ u8 linefeed_control_shadow; ++ u8 hook_state_shadow; ++ int palarms; ++ struct dahdi_vmwi_info vmwisetting; ++ int vmwi_active_messages; ++ int vmwi_linereverse; ++ int reversepolarity; /* polarity reversal */ ++ struct calregs calregs; ++ unsigned long check_alarm; ++ unsigned long check_proslic; ++ unsigned long oppending_timeout; ++ unsigned long ohttimer; ++}; ++ ++struct qrv { ++#define RADMODE_INVERTCOR 1 ++#define RADMODE_IGNORECOR 2 ++#define RADMODE_EXTTONE 4 ++#define RADMODE_EXTINVERT 8 ++#define RADMODE_IGNORECT 16 ++#define RADMODE_PREEMP 32 ++#define RADMODE_DEEMP 64 ++ char hook; ++ unsigned short debouncetime; ++ unsigned short debtime; ++ int radmode; ++ signed short rxgain; ++ signed short txgain; ++ u8 isrshadow[3]; ++}; ++ ++enum module_type { ++ NONE = 0, ++ FXS, ++ FXO, ++ FXSINIT, ++ QRV, ++ BRI, ++}; ++ ++struct wctdm_module { ++ union modtypes { ++ struct fxo fxo; ++ struct fxs fxs; ++ struct qrv qrv; ++ struct b400m *bri; ++ } mod; ++ ++ /* Protected by wctdm.reglock */ ++ struct list_head pending_cmds; ++ struct list_head active_cmds; ++ u8 offsets[3]; ++ u8 subaddr; ++ u8 card; ++ ++ enum module_type type; ++ int sethook; /* pending hook state command */ ++ int dacssrc; ++}; ++ ++struct wctdm { ++ const struct wctdm_desc *desc; ++ const char *board_name; ++ ++ spinlock_t frame_list_lock; ++ struct list_head frame_list; ++ ++ unsigned long framecount; ++ unsigned char txident; ++ unsigned char rxident; ++ ++ u8 ctlreg; ++ u8 tdm410leds; ++ ++ int mods_per_board; /* maximum number of modules for this board */ ++ int digi_mods; /* number of digital modules present */ ++ int avchannels; /* active "voice" (voice, B and D) channels */ ++ ++ spinlock_t reglock; /* held when accessing anything affecting the module array */ ++ wait_queue_head_t regq; ++ struct list_head free_isr_commands; ++ ++ struct wctdm_module mods[NUM_MODULES]; ++ ++ struct vpmadt032 *vpmadt032; ++ struct vpmoct *vpmoct; ++ struct voicebus vb; ++ struct wctdm_span *aspan; /* pointer to the spans[] holding the analog span */ ++ struct wctdm_span *spans[MAX_SPANS]; ++ struct wctdm_chan *chans[NUM_MODULES]; ++#ifdef CONFIG_VOICEBUS_ECREFERENCE ++ struct dahdi_fifo *ec_reference[NUM_MODULES]; ++#endif ++ ++ /* Only care about digital spans here */ ++ /* int span_timing_prio[MAX_SPANS - 1]; */ ++ struct semaphore syncsem; ++ int oldsync; ++ ++ int not_ready; /* 0 when the entire card is ready to go */ ++ unsigned long checkflag; /* Internal state flags and task bits */ ++ int companding; ++ struct dahdi_device *ddev; ++}; ++ ++static inline bool is_initialized(struct wctdm *wc) ++{ ++ WARN_ON(wc->not_ready < 0); ++ return (wc->not_ready == 0); ++} ++ ++/* Atomic flag bits for checkflag field */ ++#define WCTDM_CHECK_TIMING 0 ++ ++int wctdm_getreg(struct wctdm *wc, struct wctdm_module *const mod, int addr); ++int wctdm_setreg(struct wctdm *wc, struct wctdm_module *const mod, ++ int addr, int val); ++ ++int wctdm_wait_for_ready(struct wctdm *wc); ++ ++extern struct semaphore ifacelock; ++extern struct wctdm *ifaces[WC_MAX_IFACES]; ++ ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/wctdm24xxp/xhfc.c linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/xhfc.c +--- linux-source-4.19/drivers/dahdi/wctdm24xxp/xhfc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/xhfc.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,2771 @@ ++/* ++ * B400M Quad-BRI module Driver ++ * Written by Andrew Kohlsmith ++ * ++ * Copyright (C) 2010 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 ++#include ++#include ++ ++#define FAST_HDLC_NEED_TABLES ++#include ++#include ++ ++#include "wctdm24xxp.h" ++#include "xhfc.h" ++ ++#define HFC_NR_FIFOS 16 ++#define HFC_ZMIN 0x00 /* from datasheet */ ++#define HFC_ZMAX 0x7f ++#define HFC_FMIN 0x00 ++#define HFC_FMAX 0x07 ++ ++/* ++ * yuck. Any reg which is not mandated read/write or read-only is write-only. ++ * Also, there are dozens of registers with the same address. Additionally, ++ * there are array registers (A_) which have an index register These A_ ++ * registers require an index register to be written to indicate WHICH in the ++ * array you want. ++ */ ++ ++#define R_CIRM 0x00 /* WO */ ++#define R_CTRL 0x01 /* WO */ ++#define R_CLK_CFG 0x02 /* WO */ ++#define A_Z1 0x04 /* RO */ ++#define A_Z2 0x06 /* RO */ ++#define R_RAM_ADDR 0x08 /* WO */ ++#define R_RAM_CTRL 0x09 /* WO */ ++#define R_FIRST_FIFO 0x0b /* WO */ ++#define R_FIFO_THRES 0x0c /* WO */ ++#define A_F1 0x0c /* RO */ ++#define R_FIFO_MD 0x0d /* WO */ ++#define A_F2 0x0d /* RO */ ++#define A_INC_RES_FIFO 0x0e /* WO */ ++#define A_FIFO_STA 0x0e /* RO */ ++#define R_FSM_IDX 0x0f /* WO */ ++#define R_FIFO 0x0f /* WO */ ++ ++#define R_SLOT 0x10 /* WO */ ++#define R_IRQ_OVIEW 0x10 /* RO */ ++#define R_MISC_IRQMSK 0x11 /* WO */ ++#define R_MISC_IRQ 0x11 /* RO */ ++#define R_SU_IRQMSK 0x12 /* WO */ ++#define R_SU_IRQ 0x12 /* RO */ ++#define R_IRQ_CTRL 0x13 /* WO */ ++#define R_AF0_OVIEW 0x13 /* RO */ ++#define R_PCM_MD0 0x14 /* WO */ ++#define A_USAGE 0x14 /* RO */ ++#define R_MSS0 0x15 /* WO */ ++#define R_MSS1 0x15 /* WO */ ++#define R_PCM_MD1 0x15 /* WO */ ++#define R_PCM_MD2 0x15 /* WO */ ++#define R_SH0H 0x15 /* WO */ ++#define R_SH1H 0x15 /* WO */ ++#define R_SH0L 0x15 /* WO */ ++#define R_SH1L 0x15 /* WO */ ++#define R_SL_SEL0 0x15 /* WO */ ++#define R_SL_SEL1 0x15 /* WO */ ++#define R_SL_SEL7 0x15 /* WO */ ++#define R_RAM_USE 0x15 /* RO */ ++#define R_SU_SEL 0x16 /* WO */ ++#define R_CHIP_ID 0x16 /* RO */ ++#define R_SU_SYNC 0x17 /* WO */ ++#define R_BERT_STA 0x17 /* RO */ ++#define R_F0_CNTL 0x18 /* RO */ ++#define R_F0_CNTH 0x19 /* RO */ ++#define R_TI_WD 0x1a /* WO */ ++#define R_BERT_ECL 0x1a /* RO */ ++#define R_BERT_WD_MD 0x1b /* WO */ ++#define R_BERT_ECH 0x1b /* RO */ ++#define R_STATUS 0x1c /* RO */ ++#define R_SL_MAX 0x1d /* RO */ ++#define R_PWM_CFG 0x1e /* WO */ ++#define R_CHIP_RV 0x1f /* RO */ ++ ++#define R_FIFO_BL0_IRQ 0x20 /* RO */ ++#define R_FIFO_BL1_IRQ 0x21 /* RO */ ++#define R_FIFO_BL2_IRQ 0x22 /* RO */ ++#define R_FIFO_BL3_IRQ 0x23 /* RO */ ++#define R_FILL_BL0 0x24 /* RO */ ++#define R_FILL_BL1 0x25 /* RO */ ++#define R_FILL_BL2 0x26 /* RO */ ++#define R_FILL_BL3 0x27 /* RO */ ++#define R_CI_TX 0x28 /* WO */ ++#define R_CI_RX 0x28 /* RO */ ++#define R_CGI_CFG0 0x29 /* WO */ ++#define R_CGI_STA 0x29 /* RO */ ++#define R_CGI_CFG1 0x2a /* WO */ ++#define R_MON_RX 0x2a /* RO */ ++#define R_MON_TX 0x2b /* WO */ ++ ++#define A_SU_WR_STA 0x30 /* WO */ ++#define A_SU_RD_STA 0x30 /* RO */ ++#define A_SU_CTRL0 0x31 /* WO */ ++#define A_SU_DLYL 0x31 /* RO */ ++#define A_SU_CTRL1 0x32 /* WO */ ++#define A_SU_DLYH 0x32 /* RO */ ++#define A_SU_CTRL2 0x33 /* WO */ ++#define A_MS_TX 0x34 /* WO */ ++#define A_MS_RX 0x34 /* RO */ ++#define A_ST_CTRL3 0x35 /* WO */ ++#define A_UP_CTRL3 0x35 /* WO */ ++#define A_SU_STA 0x35 /* RO */ ++#define A_MS_DF 0x36 /* WO */ ++#define A_SU_CLK_DLY 0x37 /* WO */ ++#define R_PWM0 0x38 /* WO */ ++#define R_PWM1 0x39 /* WO */ ++#define A_B1_TX 0x3c /* WO */ ++#define A_B1_RX 0x3c /* RO */ ++#define A_B2_TX 0x3d /* WO */ ++#define A_B2_RX 0x3d /* RO */ ++#define A_D_TX 0x3e /* WO */ ++#define A_D_RX 0x3e /* RO */ ++#define A_BAC_S_TX 0x3f /* WO */ ++#define A_E_RX 0x3f /* RO */ ++ ++#define R_GPIO_OUT1 0x40 /* WO */ ++#define R_GPIO_IN1 0x40 /* RO */ ++#define R_GPIO_OUT3 0x41 /* WO */ ++#define R_GPIO_IN3 0x41 /* RO */ ++#define R_GPIO_EN1 0x42 /* WO */ ++#define R_GPIO_EN3 0x43 /* WO */ ++#define R_GPIO_SEL_BL 0x44 /* WO */ ++#define R_GPIO_OUT2 0x45 /* WO */ ++#define R_GPIO_IN2 0x45 /* RO */ ++#define R_PWM_MD 0x46 /* WO */ ++#define R_GPIO_EN2 0x47 /* WO */ ++#define R_GPIO_OUT0 0x48 /* WO */ ++#define R_GPIO_IN0 0x48 /* RO */ ++#define R_GPIO_EN0 0x4a /* WO */ ++#define R_GPIO_SEL 0x4c /* WO */ ++ ++#define R_PLL_CTRL 0x50 /* WO */ ++#define R_PLL_STA 0x50 /* RO */ ++#define R_PLL_P 0x51 /* RW */ ++#define R_PLL_N 0x52 /* RW */ ++#define R_PLL_S 0x53 /* RW */ ++ ++#define A_FIFO_DATA 0x80 /* RW */ ++#define A_FIFO_DATA_NOINC 0x84 /* RW */ ++ ++#define R_INT_DATA 0x88 /* RO */ ++ ++#define R_RAM_DATA 0xc0 /* RW */ ++ ++#define A_SL_CFG 0xd0 /* RW */ ++#define A_CH_MSK 0xf4 /* RW */ ++#define A_CON_HDLC 0xfa /* RW */ ++#define A_SUBCH_CFG 0xfb /* RW */ ++#define A_CHANNEL 0xfc /* RW */ ++#define A_FIFO_SEQ 0xfd /* RW */ ++#define A_FIFO_CTRL 0xff /* RW */ ++ ++/* R_CIRM bits */ ++#define V_CLK_OFF (1 << 0) /* 1=internal clocks disabled */ ++#define V_WAIT_PROC (1 << 1) /* 1=additional /WAIT after write access */ ++#define V_WAIT_REG (1 << 2) /* 1=additional /WAIT for internal BUSY phase */ ++#define V_SRES (1 << 3) /* soft reset (group 0) */ ++#define V_HFC_RES (1 << 4) /* HFC reset (group 1) */ ++#define V_PCM_RES (1 << 5) /* PCM reset (group 2) */ ++#define V_SU_RES (1 << 6) /* S/T reset (group 3) */ ++#define XHFC_FULL_RESET (V_SRES | V_HFC_RES | V_PCM_RES | V_SU_RES) ++ ++/* R_STATUS bits */ ++#define V_BUSY (1 << 0) /* 1=HFC busy, limited register access */ ++#define V_PROC (1 << 1) /* 1=HFC in processing phase */ ++#define V_LOST_STA (1 << 3) /* 1=frames have been lost */ ++#define V_PCM_INIT (1 << 4) /* 1=PCM init in progress */ ++#define V_WAK_STA (1 << 5) /* state of WAKEUP pin wien V_WAK_EN=1 */ ++#define V_MISC_IRQSTA (1 << 6) /* 1=misc interrupt has occurred */ ++#define V_FR_IRQSTA (1 << 7) /* 1=fifo interrupt has occured */ ++#define XHFC_INTS (V_MISC_IRQSTA | V_FR_IRQSTA) ++ ++/* R_FIFO_BLx_IRQ bits */ ++#define V_FIFOx_TX_IRQ (1 << 0) /* FIFO TX interrupt occurred */ ++#define V_FIFOx_RX_IRQ (1 << 1) /* FIFO RX interrupt occurred */ ++#define FIFOx_TXRX_IRQ (V_FIFOx_TX_IRQ | V_FIFOx_RX_IRQ) ++ ++/* R_FILL_BLx bits */ ++#define V_FILL_FIFOx_TX (1 << 0) /* TX FIFO reached V_THRES_TX level */ ++#define V_FILL_FIFOx_RX (1 << 1) /* RX FIFO reached V_THRES_RX level */ ++#define FILL_FIFOx_TXRX (V_FILL_FIFOx_TX | V_FILL_FIFOx_RX) ++ ++/* R_MISC_IRQ / R_MISC_IRQMSK bits */ ++#define V_SLP_IRQ (1 << 0) /* frame sync pulse flips */ ++#define V_TI_IRQ (1 << 1) /* timer elapsed */ ++#define V_PROC_IRQ (1 << 2) /* processing/non-processing transition */ ++#define V_CI_IRQ (1 << 4) /* indication bits changed */ ++#define V_WAK_IRQ (1 << 5) /* WAKEUP pin */ ++#define V_MON_TX_IRQ (1 << 6) /* monitor byte can be written */ ++#define V_MON_RX_IRQ (1 << 7) /* monitor byte received */ ++ ++/* R_SU_IRQ/R_SU_IRQMSK bits */ ++#define V_SU0_IRQ (1 << 0) /* interrupt/mask port 1 */ ++#define V_SU1_IRQ (1 << 1) /* interrupt/mask port 2 */ ++#define V_SU2_IRQ (1 << 2) /* interrupt/mask port 3 */ ++#define V_SU3_IRQ (1 << 3) /* interrupt/mask port 4 */ ++ ++/* R_IRQ_CTRL bits */ ++#define V_FIFO_IRQ_EN (1 << 0) /* enable any unmasked FIFO IRQs */ ++#define V_GLOB_IRQ_EN (1 << 3) /* enable any unmasked IRQs */ ++#define V_IRQ_POL (1 << 4) /* 1=IRQ active high */ ++ ++/* R_BERT_WD_MD bits */ ++#define V_BERT_ERR (1 << 3) /* 1=generate an error bit in BERT stream */ ++#define V_AUTO_WD_RES (1 << 5) /* 1=automatically kick the watchdog */ ++#define V_WD_RES (1 << 7) /* 1=kick the watchdog (bit auto clears) */ ++ ++/* R_TI_WD bits */ ++#define V_EV_TS_SHIFT (0) ++#define V_EV_TS_MASK (0x0f) ++#define V_WD_TS_SHIFT (4) ++#define V_WD_TS_MASK (0xf0) ++ ++/* A_FIFO_CTRL bits */ ++#define V_FIFO_IRQMSK (1 << 0) /* 1=FIFO can generate interrupts */ ++#define V_BERT_EN (1 << 1) /* 1=BERT data replaces FIFO data */ ++#define V_MIX_IRQ (1 << 2) /* IRQ when 0=end of frame only, 1=also when Z1==Z2 */ ++#define V_FR_ABO (1 << 3) /* 1=generate frame abort/frame abort detected */ ++#define V_NO_CRC (1 << 4) /* 1=do not send CRC at end of frame */ ++#define V_NO_REP (1 << 5) /* 1=frame deleted after d-chan contention */ ++ ++/* R_CLK_CFG bits */ ++#define V_CLK_PLL (1 << 0) /* Sysclk select 0=OSC_IN, 1=PLL output */ ++#define V_CLKO_HI (1 << 1) /* CLKOUT selection 0=PLL/8, 1=PLL */ ++#define V_CLKO_PLL (1 << 2) /* CLKOUT source 0=divider or PLL input, 1=PLL output */ ++#define V_PCM_CLK (1 << 5) /* 1=PCM clk = OSC, 0 = PCM clk is 2x OSC */ ++#define V_CLKO_OFF (1 << 6) /* CLKOUT enable 0=enabled */ ++#define V_CLK_F1 (1 << 7) /* PLL input pin 0=OSC_IN, 1=F1_1 */ ++ ++/* R_PCM_MD0 bits */ ++#define V_PCM_MD (1 << 0) /* 1=PCM master */ ++#define V_C4_POL (1 << 1) /* 1=F0IO sampled on rising edge of C4IO */ ++#define V_F0_NEG (1 << 2) /* 1=negative polarity of F0IO */ ++#define V_F0_LEN (1 << 3) /* 1=F0IO active for 2 C4IO clocks */ ++#define V_PCM_IDX_SEL0 (0x0 << 4) /* reg15 = R_SL_SEL0 */ ++#define V_PCM_IDX_SEL1 (0x1 << 4) /* reg15 = R_SL_SEL1 */ ++#define V_PCM_IDX_SEL7 (0x7 << 4) /* reg15 = R_SL_SEL7 */ ++#define V_PCM_IDX_MSS0 (0x8 << 4) /* reg15 = R_MSS0 */ ++#define V_PCM_IDX_MD1 (0x9 << 4) /* reg15 = R_PCM_MD1 */ ++#define V_PCM_IDX_MD2 (0xa << 4) /* reg15 = R_PCM_MD2 */ ++#define V_PCM_IDX_MSS1 (0xb << 4) /* reg15 = R_MSS1 */ ++#define V_PCM_IDX_SH0L (0xc << 4) /* reg15 = R_SH0L */ ++#define V_PCM_IDX_SH0H (0xd << 4) /* reg15 = R_SH0H */ ++#define V_PCM_IDX_SH1L (0xe << 4) /* reg15 = R_SH1L */ ++#define V_PCM_IDX_SH1H (0xf << 4) /* reg15 = R_SH1H */ ++#define V_PCM_IDX_MASK (0xf0) ++ ++/* R_PCM_MD1 bits */ ++#define V_PLL_ADJ_00 (0x0 << 2) /* adj 4 times by 0.5 system clk cycles */ ++#define V_PLL_ADJ_01 (0x1 << 2) /* adj 3 times by 0.5 system clk cycles */ ++#define V_PLL_ADJ_10 (0x2 << 2) /* adj 2 times by 0.5 system clk cycles */ ++#define V_PLL_ADJ_11 (0x3 << 2) /* adj 1 time by 0.5 system clk cycles */ ++#define V_PCM_DR_2048 (0x0 << 4) /* 2.048Mbps, 32 timeslots */ ++#define V_PCM_DR_4096 (0x1 << 4) /* 4.096Mbps, 64 timeslots */ ++#define V_PCM_DR_8192 (0x2 << 4) /* 8.192Mbps, 128 timeslots */ ++#define V_PCM_DR_075 (0x3 << 4) /* 0.75Mbps, 12 timeslots */ ++#define V_PCM_LOOP (1 << 6) /* 1=internal loopback */ ++#define V_PCM_SMPL (1 << 7) /* 0=sample at middle of bit cell, 1=sample at 3/4 point */ ++#define V_PLL_ADJ_MASK (0x3 << 2) ++#define V_PCM_DR_MASK (0x3 << 4) ++ ++/* R_PCM_MD2 bits */ ++#define V_SYNC_OUT1 (1 << 1) /* SYNC_O source 0=SYNC_I or FSX_RX, 1=512kHz from PLL or multiframe */ ++#define V_SYNC_SRC (1 << 2) /* 0=line interface, 1=SYNC_I */ ++#define V_SYNC_OUT2 (1 << 3) /* SYNC_O source 0=rx sync or FSC_RX 1=SYNC_I or received superframe */ ++#define V_C2O_EN (1 << 4) /* C2IO output enable (when V_C2I_EN=0) */ ++#define V_C2I_EN (1 << 5) /* PCM controller clock source 0=C4IO, 1=C2IO */ ++#define V_PLL_ICR (1 << 6) /* 0=reduce PCM frame time, 1=increase */ ++#define V_PLL_MAN (1 << 7) /* 0=auto, 1=manual */ ++ ++/* A_SL_CFG bits */ ++#define V_CH_SDIR (1 << 0) /* 1=HFC channel receives data from PCM TS */ ++#define V_ROUT_TX_DIS (0x0 << 6) /* disabled, output disabled */ ++#define V_ROUT_TX_LOOP (0x1 << 6) /* internally looped, output disabled */ ++#define V_ROUT_TX_STIO1 (0x2 << 6) /* output data to STIO1 */ ++#define V_ROUT_TX_STIO2 (0x3 << 6) /* output data to STIO2 */ ++#define V_ROUT_RX_DIS (0x0 << 6) /* disabled, input data ignored */ ++#define V_ROUT_RX_LOOP (0x1 << 6) /* internally looped, input data ignored */ ++#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data comes from STIO1 */ ++#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data comes from STIO2 */ ++#define V_CH_SNUM_SHIFT (1) ++#define V_CH_SNUM_MASK (31 << 1) ++ ++/* A_CON_HDLC bits */ ++#define V_IFF (1 << 0) /* Inter-Frame Fill: 0=0x7e, 1=0xff */ ++#define V_HDLC_TRP (1 << 1) /* 0=HDLC mode, 1=transparent */ ++#define V_TRP_DISABLED (0x0 << 2) /* FIFO disabled, no interrupt */ ++#define V_TRP_IRQ_64 (0x1 << 2) /* FIFO enabled, int @ 8 bytes */ ++#define V_TRP_IRQ_128 (0x2 << 2) /* FIFO enabled, int @ 16 bytes */ ++#define V_TRP_IRQ_256 (0x3 << 2) /* FIFO enabled, int @ 32 bytes */ ++#define V_TRP_IRQ_512 (0x4 << 2) /* FIFO enabled, int @ 64 bytes */ ++#define V_TRP_IRQ_1024 (0x5 << 2) /* FIFO enabled, int @ 128 bytes */ ++#define V_TRP_NO_IRQ (0x7 << 2) /* FIFO enabled, no interrupt */ ++#define V_HDLC_IRQ (0x3 << 2) /* HDLC: FIFO enabled, interrupt at end of frame or when FIFO > 16 byte boundary (Mixed IRQ) */ ++#define V_DATA_FLOW_000 (0x0 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_001 (0x1 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_010 (0x2 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_011 (0x3 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_100 (0x4 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_101 (0x5 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_110 (0x6 << 5) /* see A_CON_HDLC reg description in datasheet */ ++#define V_DATA_FLOW_111 (0x7 << 5) /* see A_CON_HDLC reg description in datasheet */ ++ ++/* R_FIFO bits */ ++#define V_FIFO_DIR (1 << 0) /* 1=RX FIFO data */ ++#define V_REV (1 << 7) /* 1=MSB first */ ++#define V_FIFO_NUM_SHIFT (1) ++#define V_FIFO_NUM_MASK (0x3e) ++ ++/* A_CHANNEL bits */ ++#define V_CH_FDIR (1 << 0) /* 1=HFC chan for RX data */ ++#define V_CH_FNUM_SHIFT (1) ++#define V_CH_FNUM_MASK (0x3e) ++ ++/* R_SLOT bits */ ++#define V_SL_DIR (1 << 0) /* 1=timeslot will RX PCM data from bus */ ++#define V_SL_NUM_SHIFT (1) ++#define V_SL_NUM_MASK (0xfe) ++ ++/* A_INC_RES_FIFO bits */ ++#define V_INC_F (1 << 0) /* 1=increment FIFO F-counter (bit auto-clears) */ ++#define V_RES_FIFO (1 << 1) /* 1=reset FIFO (bit auto-clears) */ ++#define V_RES_LOST (1 << 2) /* 1=reset LOST error (bit auto-clears) */ ++#define V_RES_FIFO_ERR (1 << 3) /* 1=reset FIFO error (bit auto-clears), check V_ABO_DONE before setting */ ++ ++/* R_FIFO_MD bits */ ++#define V_FIFO_MD_00 (0x0 << 0) /* 16 FIFOs, 64 bytes TX/RX, 128 TX or RX if V_UNIDIR_RX */ ++#define V_FIFO_MD_01 (0x1 << 0) /* 8 FIFOs, 128 bytes TX/RX, 256 TX or RX if V_UNIDIR_RX */ ++#define V_FIFO_MD_10 (0x2 << 0) /* 4 FIFOs, 256 bytes TX/RX, invalid mode with V_UNIDIR_RX */ ++#define V_DF_MD_SM (0x0 << 2) /* simple data flow mode */ ++#define V_DF_MD_CSM (0x1 << 2) /* channel select mode */ ++#define V_DF_MD_FSM (0x3 << 2) /* FIFO sequence mode */ ++#define V_UNIDIR_MD (1 << 4) /* 1=unidirectional FIFO mode */ ++#define V_UNIDIR_RX (1 << 5) /* 1=unidirection FIFO is RX */ ++ ++/* A_SUBCH_CFG bits */ ++#define V_BIT_CNT_8BIT (0) /* process 8 bits */ ++#define V_BIT_CNT_1BIT (1) /* process 1 bit */ ++#define V_BIT_CNT_2BIT (2) /* process 2 bits */ ++#define V_BIT_CNT_3BIT (3) /* process 3 bits */ ++#define V_BIT_CNT_4BIT (4) /* process 4 bits */ ++#define V_BIT_CNT_5BIT (5) /* process 5 bits */ ++#define V_BIT_CNT_6BIT (6) /* process 6 bits */ ++#define V_BIT_CNT_7BIT (7) /* process 7 bits */ ++#define V_LOOP_FIFO (1 << 6) /* loop FIFO data */ ++#define V_INV_DATA (1 << 7) /* invert FIFO data */ ++#define V_START_BIT_SHIFT (3) ++#define V_START_BIT_MASK (0x38) ++ ++/* R_SU_SYNC bits */ ++#define V_SYNC_SEL_PORT0 (0x0 << 0) /* sync to TE port 0 */ ++#define V_SYNC_SEL_PORT1 (0x1 << 0) /* sync to TE port 1 */ ++#define V_SYNC_SEL_PORT2 (0x2 << 0) /* sync to TE port 2 */ ++#define V_SYNC_SEL_PORT3 (0x3 << 0) /* sync to TE port 3 */ ++#define V_SYNC_SEL_SYNCI (0x4 << 0) /* sync to SYNC_I */ ++#define V_MAN_SYNC (1 << 3) /* 1=manual sync mode */ ++#define V_AUTO_SYNCI (1 << 4) /* 1=SYNC_I used if FSC_RX not found */ ++#define V_D_MERGE_TX (1 << 5) /* 1=all 4 dchan taken from one byte in TX */ ++#define V_E_MERGE_RX (1 << 6) /* 1=all 4 echan combined in RX direction */ ++#define V_D_MERGE_RX (1 << 7) /* 1=all 4 dchan combined in RX direction */ ++#define V_SYNC_SEL_MASK (0x03) ++ ++/* A_SU_WR_STA bits */ ++#define V_SU_SET_STA_MASK (0x0f) ++#define V_SU_LD_STA (1 << 4) /* 1=force SU_SET_STA mode, must be manually cleared 6us later */ ++#define V_SU_ACT_NOP (0x0 << 5) /* NOP */ ++#define V_SU_ACT_DEACTIVATE (0x2 << 5) /* start deactivation. auto-clears */ ++#define V_SU_ACT_ACTIVATE (0x3 << 5) /* start activation. auto-clears. */ ++#define V_SET_G2_G3 (1 << 7) /* 1=auto G2->G3 in NT mode. auto-clears after transition. */ ++ ++/* A_SU_RD_STA */ ++#define V_SU_STA_MASK (0x0f) ++#define V_SU_FR_SYNC (1 << 4) /* 1=synchronized */ ++#define V_SU_T2_EXP (1 << 5) /* 1=T2 expired (NT only) */ ++#define V_SU_INFO0 (1 << 6) /* 1=INFO0 */ ++#define V_G2_G3 (1 << 7) /* 1=allows G2->G3 (NT only, auto-clears) */ ++ ++/* A_SU_CLK_DLY bits */ ++#define V_SU_DLY_MASK (0x0f) ++#define V_SU_SMPL_MASK (0xf0) ++#define V_SU_SMPL_SHIFT (4) ++ ++/* A_SU_CTRL0 bits */ ++#define V_B1_TX_EN (1 << 0) /* 1=B1-channel transmit */ ++#define V_B2_TX_EN (1 << 1) /* 1=B2-channel transmit */ ++#define V_SU_MD (1 << 2) /* 0=TE, 1=NT */ ++#define V_ST_D_LPRIO (1 << 3) /* D-Chan priority 0=high, 1=low */ ++#define V_ST_SQ_EN (1 << 4) /* S/Q bits transmit (1=enabled) */ ++#define V_SU_TST_SIG (1 << 5) /* 1=transmit test signal */ ++#define V_ST_PU_CTRL (1 << 6) /* 1=enable end of pulse control */ ++#define V_SU_STOP (1 << 7) /* 1=power down */ ++ ++/* A_SU_CTRL1 bits */ ++#define V_G2_G3_EN (1 << 0) /* 1=G2->G3 allowed without V_SET_G2_G3 */ ++#define V_D_RES (1 << 2) /* 1=D-chan reset */ ++#define V_ST_E_IGNO (1 << 3) /* TE:1=ignore Echan, NT:should always be 1. */ ++#define V_ST_E_LO (1 << 4) /* NT only: 1=force Echan low */ ++#define V_BAC_D (1 << 6) /* 1=BAC bit controls Dchan TX */ ++#define V_B12_SWAP (1 << 7) /* 1=swap B1/B2 */ ++ ++/* A_SU_CTRL2 bits */ ++#define V_B1_RX_EN (1 << 0) /* 1=enable B1 RX */ ++#define V_B2_RX_EN (1 << 1) /* 1=enable B2 RX */ ++#define V_MS_SSYNC2 (1 << 2) /* 0 normally, see datasheet */ ++#define V_BAC_S_SEL (1 << 3) /* see datasheet */ ++#define V_SU_SYNC_NT (1 << 4) /* 0=sync pulses generated only in TE, 1=in TE and NT */ ++#define V_SU_2KHZ (1 << 5) /* 0=96kHz test tone, 1=2kHz */ ++#define V_SU_TRI (1 << 6) /* 1=tristate output buffer */ ++#define V_SU_EXCHG (1 << 7) /* 1=invert output drivers */ ++ ++/* R_IRQ_OVIEW bits */ ++#define V_FIFO_BL0_IRQ (1 << 0) /* FIFO 0-3 IRQ */ ++#define V_FIFO_BL1_IRQ (1 << 1) /* FIFO 4-7 IRQ */ ++#define V_FIFO_BL2_IRQ (1 << 2) /* FIFO 8-11 IRQ */ ++#define V_FIFO_BL3_IRQ (1 << 3) /* FIFO 12-15 IRQ */ ++#define V_MISC_IRQ (1 << 4) /* R_MISC_IRQ changed */ ++#define V_STUP_IRQ (1 << 5) /* R_SU_IRQ changed */ ++#define V_FIFO_BLx_IRQ (V_FIFO_BL0_IRQ | V_FIFO_BL1_IRQ | V_FIFO_BL2_IRQ | V_FIFO_BL3_IRQ) ++ ++/* R_FIRST_FIFO bits */ ++#define V_FIRST_FIFO_NUM_SHIFT (1) ++ ++/* A_FIFO_SEQ bits */ ++#define V_NEXT_FIFO_NUM_SHIFT (1) ++#define V_SEQ_END (1 << 6) ++ ++#if (DAHDI_CHUNKSIZE != 8) ++#error Sorry, the b400m does not support chunksize != 8 ++#endif ++ ++/* general debug messages */ ++#define DEBUG_GENERAL (1 << 0) ++/* emit DTMF detector messages */ ++#define DEBUG_DTMF (1 << 1) ++/* emit register read/write, but only if the kernel's DEBUG is defined */ ++#define DEBUG_REGS (1 << 2) ++/* emit file operation messages */ ++#define DEBUG_FOPS (1 << 3) ++#define DEBUG_ECHOCAN (1 << 4) ++/* S/T state machine */ ++#define DEBUG_ST_STATE (1 << 5) ++/* HDLC controller */ ++#define DEBUG_HDLC (1 << 6) ++/* alarm changes */ ++#define DEBUG_ALARM (1 << 7) ++/* Timing related changes */ ++#define DEBUG_TIMING (1 << 8) ++ ++#define DBG (bri_debug & DEBUG_GENERAL) ++#define DBG_DTMF (bri_debug & DEBUG_DTMF) ++#define DBG_REGS (bri_debug & DEBUG_REGS) ++#define DBG_FOPS (bri_debug & DEBUG_FOPS) ++#define DBG_EC (bri_debug & DEBUG_ECHOCAN) ++#define DBG_ST (bri_debug & DEBUG_ST_STATE) ++#define DBG_HDLC (bri_debug & DEBUG_HDLC) ++#define DBG_ALARM (bri_debug & DEBUG_ALARM) ++#define DBG_TIMING (bri_debug & DEBUG_TIMING) ++ ++#define DBG_SPANFILTER ((1 << bspan->port) & bri_spanfilter) ++ ++/* #define HARDHDLC_RX */ ++ ++/* Any static variables not initialized by default should be set ++ * to 0 automatically */ ++int bri_debug; ++int bri_spanfilter = 9; ++int bri_teignorered = 1; ++int bri_alarmdebounce; ++int bri_persistentlayer1; ++int timingcable; ++ ++static int synccard = -1; ++static int syncspan = -1; ++ ++static const int TIMER_3_MS = 30000; ++ ++#define b4_info(b4, format, arg...) \ ++ dev_info(&(b4)->wc->vb.pdev->dev , format , ## arg) ++ ++/* if defined, swaps ports 2 and 3 on the B400M module */ ++#define SWAP_PORTS ++ ++#define XHFC_T1 0 ++#define XHFC_T2 1 ++#define XHFC_T3 2 ++/* T4 - Special timer, used for debug purposes for monitoring of L1 state during activation attempt. */ ++#define XHFC_T4 3 ++ ++#define B400M_CHANNELS_PER_SPAN 3 /* 2 B-channels and 1 D-Channel for each BRI span */ ++#define B400M_HDLC_BUF_LEN 128 /* arbitrary, just the max # of byts we will send to DAHDI per call */ ++ ++#define get_F(f1, f2, flen) { \ ++ f1 = hfc_readcounter8(b4, A_F1); \ ++ f2 = hfc_readcounter8(b4, A_F2); \ ++ flen = f1 - f2; \ ++ \ ++ if (flen < 0) \ ++ flen += (HFC_FMAX - HFC_FMIN) + 1; \ ++ } ++ ++#define get_Z(z1, z2, zlen) { \ ++ z1 = hfc_readcounter8(b4, A_Z1); \ ++ z2 = hfc_readcounter8(b4, A_Z2); \ ++ zlen = z1 - z2; \ ++ \ ++ if (zlen < 0) \ ++ zlen += (HFC_ZMAX - HFC_ZMIN) + 1; \ ++ } ++ ++struct b400m_span { ++ struct b400m *parent; ++ unsigned int port; /* which S/T port this span belongs to */ ++ ++ int oldstate; /* old state machine state */ ++ int newalarm; /* alarm to send to DAHDI once alarm timer expires */ ++ unsigned long alarmtimer; ++ ++ unsigned int te_mode:1; /* 1=TE, 0=NT */ ++ unsigned int term_on:1; /* 1= 390 ohm termination enable, 0 = disabled */ ++ unsigned long hfc_timers[B400M_CHANNELS_PER_SPAN+1]; /* T1, T2, T3 */ ++ int hfc_timer_on[B400M_CHANNELS_PER_SPAN+1]; /* 1=timer active */ ++ int fifos[B400M_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */ ++ ++ /* HDLC controller fields */ ++ struct wctdm_span *wspan; /* pointer to the actual dahdi_span */ ++ struct dahdi_chan *sigchan; /* pointer to the signalling channel for this span */ ++ int sigactive; /* nonzero means we're in the middle of sending an HDLC frame */ ++ atomic_t hdlc_pending; /* hdlc_hard_xmit() increments, hdlc_tx_frame() decrements */ ++ unsigned int frames_out; ++ unsigned int frames_in; ++ ++ struct fasthdlc_state rxhdlc; ++ int infcs; ++ int f_sz; ++}; ++ ++/* This structure exists one per module */ ++struct b400m { ++ char name[10]; ++ int position; /* module position in carrier board */ ++ int b400m_no; /* 0-based B400M number in system */ ++ ++ struct wctdm *wc; /* parent structure */ ++ ++ spinlock_t reglock; /* lock for all register accesses */ ++ ++ unsigned long ticks; ++ ++ unsigned long fifo_en_rxint; /* each bit is the RX int enable for that FIFO */ ++ unsigned long fifo_en_txint; /* each bit is the TX int enable for that FIFO */ ++ unsigned char fifo_irqstatus; /* top-half ORs in new interrupts, bottom-half ANDs them out */ ++ ++ int setsyncspan; /* Span reported from HFC for sync on this card */ ++ int reportedsyncspan; /* Span reported from HFC for sync on this card */ ++ ++ unsigned int running:1; /* interrupts are enabled */ ++ unsigned int shutdown:1; /* 1=bottom half doesn't process anything, just returns */ ++ unsigned int inited:1; /* FIXME: temporary */ ++ unsigned int misc_irq_mask:1; /* 1= interrupt is valid */ ++ ++ struct b400m_span spans[4]; /* Individual spans */ ++ ++ struct workqueue_struct *xhfc_ws; ++ struct work_struct xhfc_wq; ++ ++ unsigned char irq_oview; /* copy of r_irq_oview */ ++ unsigned char fifo_fill; /* copy of R_FILL_BL0 */ ++ ++ struct semaphore regsem; /* lock for low-level register accesses */ ++ struct semaphore fifosem; /* lock for fifo accesses */ ++ ++ unsigned char lastreg; /* last XHFC register accessed (used to speed up multiple address "hits" */ ++}; ++ ++static void hfc_start_st(struct b400m_span *s); ++static void hfc_stop_st(struct b400m_span *s); ++ ++void b400m_set_dahdi_span(struct b400m *b4, int spanno, ++ struct wctdm_span *wspan) ++{ ++ b4->spans[spanno].wspan = wspan; ++ wspan->bspan = &b4->spans[spanno]; ++} ++ ++static inline void flush_hw(void) ++{ ++} ++ ++static int xhfc_getreg(struct wctdm *wc, struct wctdm_module *const mod, ++ int addr, u8 *lastreg) ++{ ++ int x; ++ ++ if (*lastreg != (unsigned char)addr) { ++ wctdm_setreg(wc, mod, 0x60, addr); ++ *lastreg = (unsigned char)addr; ++ } ++ x = wctdm_getreg(wc, mod, 0x80); ++ return x; ++} ++ ++static int xhfc_setreg(struct wctdm *wc, struct wctdm_module *const mod, ++ int addr, int val, u8 *lastreg) ++{ ++ if (*lastreg != (unsigned char)addr) { ++ wctdm_setreg(wc, mod, 0x60, addr); ++ *lastreg = (unsigned char)addr; ++ } ++ return wctdm_setreg(wc, mod, 0x00, val); ++} ++ ++static inline struct wctdm_module *get_mod(struct b400m *b4) ++{ ++ return &b4->wc->mods[b4->position]; ++} ++ ++static int b400m_getreg(struct b400m *b4, int addr) ++{ ++ int x; ++ ++ if (down_trylock(&b4->regsem)) { ++ if (down_interruptible(&b4->regsem)) { ++ b4_info(b4, "b400m_getreg(0x%02x) interrupted\n", ++ addr); ++ return -1; ++ } ++ } ++ ++ x = xhfc_getreg(b4->wc, get_mod(b4), addr, &b4->lastreg); ++ up(&b4->regsem); ++ ++ return x; ++} ++ ++static int b400m_setreg(struct b400m *b4, const int addr, const int val) ++{ ++ int x; ++ ++ if (down_trylock(&b4->regsem)) { ++ if (down_interruptible(&b4->regsem)) { ++ b4_info(b4, "b400m_setreg(0x%02x -> 0x%02x) " ++ "interrupted\n", val, addr); ++ return -1; ++ } ++ } ++ ++ x = xhfc_setreg(b4->wc, get_mod(b4), addr, val, &b4->lastreg); ++ up(&b4->regsem); ++ ++ return x; ++} ++ ++ ++/* ++ * A lot of the registers in the XHFC are indexed. ++ * this function sets the index, and then writes to the indexed register. ++ */ ++static void b400m_setreg_ra(struct b400m *b4, u8 r, u8 rd, u8 a, u8 ad) ++{ ++ if (down_trylock(&b4->regsem)) { ++ if (down_interruptible(&b4->regsem)) { ++ b4_info(b4, "b400m_setreg_ra(0x%02x -> 0x%02x) " ++ "interrupted\n", a, ad); ++ return; ++ } ++ } ++ ++ xhfc_setreg(b4->wc, get_mod(b4), r, rd, &b4->lastreg); ++ xhfc_setreg(b4->wc, get_mod(b4), a, ad, &b4->lastreg); ++ up(&b4->regsem); ++} ++ ++static u8 b400m_getreg_ra(struct b400m *b4, u8 r, u8 rd, u8 a) ++{ ++ unsigned char res; ++ if (down_trylock(&b4->regsem)) { ++ if (down_interruptible(&b4->regsem)) { ++ b4_info(b4, "b400m_getreg_ra(0x%02x) interrupted\n", ++ a); ++ return -1; ++ } ++ } ++ ++ xhfc_setreg(b4->wc, get_mod(b4), r, rd, &b4->lastreg); ++ res = xhfc_getreg(b4->wc, get_mod(b4), a, &b4->lastreg); ++ up(&b4->regsem); ++ return res; ++} ++ ++ ++/* ++ * XHFC-4S GPIO routines ++ * ++ * the xhfc doesn't use its gpio for anything. :-) ++ */ ++ ++/* ++ * initialize XHFC GPIO. ++ * GPIO 0-7 are output, low (unconnected, or used for their primary function). ++ */ ++static void hfc_gpio_init(struct b400m *b4) ++{ ++ /* GPIO0..3,7 are GPIO, 4,5,6 primary function */ ++ b400m_setreg(b4, R_GPIO_SEL, 0x8f); ++ /* GPIO0..7 drivers set low */ ++ b400m_setreg(b4, R_GPIO_OUT0, 0x00); ++ /* GPIO0..7 drivers enabled */ ++ b400m_setreg(b4, R_GPIO_EN0, 0xff); ++ /* all other GPIO set to primary function */ ++ b400m_setreg(b4, R_GPIO_SEL_BL, 0x00); ++ ++} ++ ++ ++/* performs a register write and then waits for the HFC "busy" bit to clear ++ * NOTE: doesn't actually read status, since busy bit is 1us typically, and ++ * we're much, much slower than that. */ ++static void hfc_setreg_waitbusy(struct b400m *b4, const unsigned int reg, ++ const unsigned int val) ++{ ++ b400m_setreg(b4, reg, val); ++} ++ ++/* ++ * reads an 8-bit register over over and over until the same value is read ++ * twice, then returns that value. ++ */ ++static unsigned char hfc_readcounter8(struct b400m *b4, const unsigned int reg) ++{ ++ unsigned char r1, r2; ++ unsigned long maxwait = 1048576; ++ ++ do { ++ r1 = b400m_getreg(b4, reg); ++ r2 = b400m_getreg(b4, reg); ++ } while ((r1 != r2) && maxwait--); ++ ++ if (!maxwait) { ++ if (printk_ratelimit()) { ++ dev_warn(&b4->wc->vb.pdev->dev, ++ "hfc_readcounter8(reg 0x%02x) timed out " \ ++ "waiting for data to settle!\n", reg); ++ } ++ } ++ ++ return r1; ++} ++ ++/* performs a soft-reset of the HFC-4S. */ ++static void hfc_reset(struct b400m *b4) ++{ ++ unsigned long start; ++ int TIMEOUT = HZ; /* 1s */ ++ ++ /* Set the FIFOs to 8 128 bytes FIFOs, bidirectional, and set up the ++ * flow controller for channel select mode. */ ++ /* Note, this reg has to be set *before* the SW reset */ ++ b400m_setreg(b4, R_FIFO_MD, V_FIFO_MD_01 | V_DF_MD_FSM); ++ ++ msleep(1); /* wait a bit for clock to settle */ ++/* reset everything, wait 100ms, then allow the XHFC to come out of reset */ ++ b400m_setreg(b4, R_CIRM, V_SRES); ++ flush_hw(); ++ ++ msleep(100); ++ ++ b400m_setreg(b4, R_CIRM, 0x00); ++ flush_hw(); ++ ++ /* wait for XHFC to come out of reset. */ ++ start = jiffies; ++ while (b400m_getreg(b4, R_STATUS) & (V_BUSY | V_PCM_INIT)) { ++ if (time_after(jiffies, start + TIMEOUT)) { ++ b4_info(b4, "hfc_reset() Module won't come out of " ++ "reset... continuing.\n"); ++ break; ++ } ++ }; ++ ++ /* Disable the output clock pin, and also the PLL (it's not needed) */ ++ b400m_setreg(b4, R_CTRL, 0x00); ++} ++ ++static void hfc_enable_fifo_irqs(struct b400m *b4) ++{ ++ b400m_setreg(b4, R_IRQ_CTRL, V_FIFO_IRQ_EN | V_GLOB_IRQ_EN); ++ flush_hw(); ++} ++ ++static void hfc_enable_interrupts(struct b400m *b4) ++{ ++ b4->running = 1; ++ ++ /* mask all misc interrupts */ ++ b4->misc_irq_mask = 0x01; ++ b400m_setreg(b4, R_MISC_IRQMSK, b4->misc_irq_mask); ++ ++/* clear any pending interrupts */ ++ b400m_getreg(b4, R_STATUS); ++ b400m_getreg(b4, R_MISC_IRQ); ++ b400m_getreg(b4, R_FIFO_BL0_IRQ); ++ b400m_getreg(b4, R_FIFO_BL1_IRQ); ++ b400m_getreg(b4, R_FIFO_BL2_IRQ); ++ b400m_getreg(b4, R_FIFO_BL3_IRQ); ++ ++ hfc_enable_fifo_irqs(b4); ++} ++ ++static inline void hfc_reset_fifo(struct b400m *b4) ++{ ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, ++ V_RES_FIFO | V_RES_LOST | V_RES_FIFO_ERR); ++} ++ ++static void hfc_setup_fifo(struct b400m *b4, int fifo) ++{ ++ if (fifo < 4) { ++ /* TX */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b400m_setreg(b4, A_CON_HDLC, ++ V_HDLC_IRQ | V_DATA_FLOW_000 | V_IFF); ++ hfc_reset_fifo(b4); ++ ++ /* RX */ ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b400m_setreg(b4, A_CON_HDLC, ++ V_HDLC_IRQ | V_DATA_FLOW_000 | V_IFF); ++ hfc_reset_fifo(b4); ++ } else { ++ /* TX */ ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ b400m_setreg(b4, A_CON_HDLC, ++ V_HDLC_TRP | V_TRP_NO_IRQ | V_DATA_FLOW_110); ++ hfc_reset_fifo(b4); ++ ++ /* RX */ ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ b400m_setreg(b4, A_CON_HDLC, ++ V_HDLC_TRP | V_TRP_NO_IRQ | V_DATA_FLOW_110); ++ hfc_reset_fifo(b4); ++ } ++} ++ ++static void hfc_setup_pcm(struct b400m *b4, int port) ++{ ++ int physport; ++ int offset; ++ int hfc_chan; ++ int ts; ++#ifdef HARDHDLC_RX ++ const int MAX_OFFSET = 2; ++#else ++ const int MAX_OFFSET = 3; ++#endif ++ ++#ifdef SWAP_PORTS ++ /* swap the middle ports */ ++ physport = (1 == port) ? 2 : (2 == port) ? 1 : port; ++#else ++ physport = port; ++#endif ++ ++ for (offset = 0; offset < MAX_OFFSET; offset++) { ++ hfc_chan = (port * 4) + offset; ++ ts = (physport * 3) + offset; ++ ts += (b4->b400m_no * 12); ++ b400m_setreg(b4, R_SLOT, (ts << V_SL_NUM_SHIFT)); ++ b400m_setreg(b4, A_SL_CFG, ++ (hfc_chan << V_CH_SNUM_SHIFT) | ++ V_ROUT_TX_STIO2); ++ ++ if (offset < 2) { ++ b400m_setreg(b4, R_SLOT, ++ (ts << V_SL_NUM_SHIFT) | ++ V_SL_DIR); ++ b400m_setreg(b4, A_SL_CFG, ++ (hfc_chan << V_CH_SNUM_SHIFT) | ++ V_ROUT_RX_STIO1 | V_CH_SDIR); ++ } ++ } ++} ++ ++#ifdef SWAP_PORTS ++#ifdef HARDHDLC_RX ++static const int fifos[24] = {0, 0, 2, 2, 1, 1, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, ++ 5, 5, 5, 5, 7, 7, 7, 7 }; ++#else ++static const int fifos[24] = {0, 4, 2, 6, 1, 5, 3, 7, 4, 4, 4, 4, 6, 6, 6, 6, ++ 5, 5, 5, 5, 7, 7, 7, 7 }; ++#endif ++static const int hfc_chans[12] = {2, 10, 6, 14, 0, 1, 8, 9, 4, 5, 12, 13 }; ++#else ++#ifdef HARDHDLC_RX ++static const int fifos[24] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, ++ 6, 6, 6, 6, 7, 7, 7, 7 }; ++#else ++static const int fifos[24] = {0, 4, 1, 5, 2, 6, 3, 7, 4, 4, 4, 4, 5, 5, 5, 5, ++ 6, 6, 6, 6, 7, 7, 7, 7 }; ++#endif ++static const int hfc_chans[12] = { 2, 6, 10, 14, 0, 1, 4, 5, 8, 9, 12, 13 }; ++#endif ++ ++static void hfc_setup_fifo_arrays(struct b400m *b4, int fifo) ++{ ++ int val; ++ if (!fifo) { ++ val = (fifos[fifo] << V_FIRST_FIFO_NUM_SHIFT) | (fifo & 1); ++ b400m_setreg(b4, R_FIRST_FIFO, val); ++ } else { ++#ifdef HARDHDLC_RX ++ val = (fifos[fifo] << V_NEXT_FIFO_NUM_SHIFT) | (fifo & 1); ++#else ++ val = (fifo < 8) ? (fifos[fifo] << V_NEXT_FIFO_NUM_SHIFT) : ++ (fifos[fifo] << V_NEXT_FIFO_NUM_SHIFT) | ++ (fifo&1); ++#endif ++ b400m_setreg(b4, A_FIFO_SEQ, val); ++ } ++ ++ b400m_setreg(b4, R_FSM_IDX, fifo); ++ val = (fifo < 8) ? (hfc_chans[fifo>>1] << V_CH_FNUM_SHIFT) : ++ (hfc_chans[fifo>>1] << V_CH_FNUM_SHIFT) | ++ (fifo & 1); ++ ++ b400m_setreg(b4, A_CHANNEL, val); ++ b400m_setreg(b4, A_SUBCH_CFG, 0x02); ++} ++ ++static void hfc_setup_fsm(struct b400m *b4) ++{ ++ int chan, fifo, port, offset; ++#ifdef SWAP_PORTS ++ const int chan_to_fifo[12] = { 4, 4, 0, 6, 6, 2, 5, 5, 1, 7, 7, 3 }; ++#else ++ const int chan_to_fifo[12] = { 4, 4, 0, 5, 5, 1, 6, 6, 2, 7, 7, 3 }; ++#endif ++ ++ for (port = 0; port < 4; port++) { ++ for (offset = 0; offset < 3; offset++) { ++ b4->spans[port].fifos[offset] = ++ chan_to_fifo[(port * 3) + offset]; ++ } ++ } ++ ++ for (chan = 0; chan < ARRAY_SIZE(fifos); chan++) ++ hfc_setup_fifo_arrays(b4, chan); ++ ++ b400m_setreg(b4, A_FIFO_SEQ, V_SEQ_END); ++ ++ for (fifo = 0; fifo < 8; fifo++) ++ hfc_setup_fifo(b4, fifo); ++ ++ for (port = 0; port < 4; port++) ++ hfc_setup_pcm(b4, port); ++} ++ ++/* takes a read/write fifo pair and optionally resets it, optionally enabling ++ * the rx/tx interrupt */ ++static void hfc_reset_fifo_pair(struct b400m *b4, int fifo, ++ int reset, int force_no_irq) ++{ ++ unsigned char b; ++ ++ if (down_interruptible(&b4->fifosem)) { ++ b4_info(b4, "Unable to retrieve fifo sem\n"); ++ return; ++ } ++ b = (!force_no_irq && b4->fifo_en_txint & (1 << fifo)) ? ++ V_FIFO_IRQMSK : 0; ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ ++ if (fifo < 4) ++ b |= V_MIX_IRQ; ++ ++ b400m_setreg(b4, A_FIFO_CTRL, b); ++ ++ if (reset) ++ hfc_reset_fifo(b4); ++ ++ b = (!force_no_irq && b4->fifo_en_rxint & (1 << fifo)) ? ++ V_FIFO_IRQMSK : 0; ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ ++ if (fifo < 4) ++ b |= V_MIX_IRQ; ++ ++ b400m_setreg(b4, A_FIFO_CTRL, b); ++ ++ if (reset) ++ hfc_reset_fifo(b4); ++ ++ up(&b4->fifosem); ++} ++ ++static void xhfc_set_sync_src(struct b400m *b4, int port) ++{ ++ int b; ++ ++ /* -2 means we need to go back and try again later */ ++ if (port == -2) ++ return; ++ ++ if (port == b4->setsyncspan) ++ return; ++ else ++ b4->setsyncspan = port; ++ ++ b4_info(b4, "xhfc_set_sync_src - modpos %d: setting sync to " ++ "be port %d\n", b4->position, port); ++ ++ if (port == -1) /* automatic */ ++ b = 0; ++ else { ++#ifdef SWAP_PORTS ++ port = (1 == port) ? 2 : (2 == port) ? 1 : port; ++#endif ++ b = (port & V_SYNC_SEL_MASK) | V_MAN_SYNC; ++ } ++ ++ b400m_setreg(b4, R_SU_SYNC, b); ++} ++ ++static void wctdm_change_card_sync_src(struct wctdm *wc, int newsrc, int master) ++{ ++ int newctlreg; ++ ++ newctlreg = wc->ctlreg; ++ ++ if (master) ++ newctlreg |= (1 << 5); ++ else ++ newctlreg &= ~(1 << 5); ++ ++ newctlreg &= 0xfc; ++ ++ newctlreg |= newsrc; ++ ++ if (DBG_TIMING) { ++ dev_info(&wc->vb.pdev->dev, ++ "Final ctlreg before swap: %02x\n", newctlreg); ++ } ++ ++ wc->ctlreg = newctlreg; ++ wc->oldsync = newsrc; ++ ++ msleep(10); ++} ++ ++static void wctdm_change_system_sync_src(int oldsync, int oldspan, ++ int newsync, int newspan) ++{ ++ struct wctdm *wc; ++ struct wctdm *oldsyncwc = NULL, *newsyncwc = NULL; ++ int newspot; ++ int i; ++ int max_latency = 0; ++ ++ if (oldsync > -1) ++ oldsyncwc = ifaces[oldsync]; ++ ++ if (newsync > -1) ++ newsyncwc = ifaces[newsync]; ++ ++ if (newsync == -1) { ++ BUG_ON(!ifaces[0]); ++ ++ newsyncwc = ifaces[0]; ++ newsync = 0; ++ } ++ ++ newspot = (-1 == newspan) ? 0 : 2 | (newspan >> 2); ++ ++ if ((oldsync == newsync) && (oldspan == newspan)) { ++ dev_info(&newsyncwc->vb.pdev->dev, ++ "No need for timing change. All is same\n"); ++ return; ++ } ++ ++ /* First we set all sources to local timing */ ++ for (i = 0; i < WC_MAX_IFACES; i++) { ++ wc = ifaces[i]; ++ if ((wc != oldsyncwc) && wc) { ++ wctdm_change_card_sync_src(wc, 0, 0); ++ if (voicebus_current_latency(&wc->vb) > max_latency) ++ max_latency = voicebus_current_latency(&wc->vb); ++ } ++ } ++ msleep(max_latency << 1); ++ ++ /* Set the old sync source to local timing, not driving timing */ ++ if (oldsyncwc) { ++ wctdm_change_card_sync_src(oldsyncwc, 0, 0); ++ msleep(voicebus_current_latency(&oldsyncwc->vb) << 1); ++ } ++ ++ dev_info(&newsyncwc->vb.pdev->dev, ++ "Setting new card %d now to be timing master\n", newsync); ++ /* Finally, set the new sync source to broadcast master timing */ ++ wctdm_change_card_sync_src(newsyncwc, newspot, 1); ++ msleep(voicebus_current_latency(&newsyncwc->vb) << 1); ++ ++ /* Last we double verify and set all the remaining cards to be timing ++ * slaves */ ++ for (i = 0; (i < WC_MAX_IFACES) && ifaces[i]; i++) { ++ wc = ifaces[i]; ++ if (i == newsync) ++ continue; ++ ++ dev_info(&wc->vb.pdev->dev, ++ "Setting card %d to be timing slave\n", i); ++ wctdm_change_card_sync_src(wc, 1, 0); ++ } ++ msleep(max_latency << 1); ++ synccard = newsync; ++ syncspan = newspan; ++} ++ ++static int xhfc_find_sync_with_timingcable(struct b400m *b4) ++{ ++ struct wctdm *wc = b4->wc; ++ int i, j, osrc, src = -1; ++ int lowestprio = 10000; ++ int lowestcard = -1; ++ ++ if (down_trylock(&ifacelock)) { ++ set_bit(WCTDM_CHECK_TIMING, &wc->checkflag); ++ return -2; ++ } ++ ++ for (j = 0; j < WC_MAX_IFACES && ifaces[j]; j++) { ++ if (is_initialized(ifaces[j])) { ++ set_bit(WCTDM_CHECK_TIMING, &wc->checkflag); ++ osrc = -2; ++ goto out; ++ } else { ++ for (i = 0; i < (MAX_SPANS - 1); i++) { ++ struct wctdm_span *wspan = ifaces[j]->spans[i]; ++ if (wspan && ++ wspan->timing_priority && ++ !wspan->span.alarms && ++ (wspan->timing_priority < ++ lowestprio)) { ++ src = i; ++ lowestprio = wspan->timing_priority; ++ lowestcard = j; ++ } ++ } ++ } ++ } ++ ++ if (lowestcard != synccard) { ++ b4_info(b4, "Found new timing master, card " ++ "%d. Old is card %d\n", lowestcard, synccard); ++ } else if (src != syncspan) { ++ b4_info(b4, "Timing change, but only from %d to %d on " ++ "card %d\n", syncspan, src, lowestcard); ++ } ++ ++ wctdm_change_system_sync_src(synccard, syncspan, ++ lowestcard, src); ++ ++ osrc = -1; ++ ++ if (wc == ifaces[lowestcard]) { ++ if (src < (b4->position + 4) && (src >= b4->position)) ++ osrc = src - b4->position; ++ } ++ ++out: ++ up(&ifacelock); ++ ++ return osrc; ++} ++ ++static int xhfc_find_sync_without_timingcable(struct b400m *b4) ++{ ++ struct wctdm *wc = b4->wc; ++ int i, osrc, src = -1; ++ int lowestprio = 10000; ++ int newctlregmux; ++ ++ if (down_trylock(&wc->syncsem)) { ++ set_bit(WCTDM_CHECK_TIMING, &wc->checkflag); ++ return -2; ++ } ++ ++ /* Find lowest slave timing priority on digital spans */ ++ for (i = 0; i < (MAX_SPANS - 1); i++) { ++ struct wctdm_span *const wspan = wc->spans[i]; ++ if (wspan && wspan->timing_priority && ++ !wspan->span.alarms && ++ (wspan->timing_priority < lowestprio)) { ++ src = i; ++ lowestprio = wspan->timing_priority; ++ } ++ } ++ ++ if (src < 0) { ++ if (DBG_TIMING) ++ b4_info(b4, "Picked analog span\n"); ++ osrc = src; ++ goto check_card_timing; ++ } else { ++ if (DBG_TIMING) { ++ b4_info(b4, "Picked span offset %d to be timing " ++ "source\n", src); ++ } ++ } ++ ++ osrc = ((src < (b4->position + 4)) && (src >= b4->position)) ? ++ src - b4->position : -1; ++ ++ if (DBG_TIMING) { ++ b4_info(b4, "For b4->position %d timing is %d\n", ++ b4->position, osrc); ++ } ++ ++check_card_timing: ++ ++ if (src != -1) ++ newctlregmux = 2 | (src >> 2); ++ else ++ newctlregmux = 0; ++ ++ if ((newctlregmux & 3) != (wc->ctlreg & 3)) { ++ if (DBG_TIMING) { ++ b4_info(b4, "!!!Need to change timing " ++ "on baseboard to spot %d!!!\n", ++ src >> 2); ++ } ++ ++ wctdm_change_card_sync_src(wc, newctlregmux, 0); ++ } else { ++ if (DBG_TIMING) { ++ dev_info(&b4->wc->vb.pdev->dev, "!!!No need to change timing " \ ++ "on baseboard to spot %d, already there!!!\n", ++ src >> 2); ++ ++ } ++ } ++ ++ ++ up(&wc->syncsem); ++ ++ return osrc; ++} ++ ++/* ++ * Finds the highest-priority sync span that is not in alarm and returns it. ++ * Note: the span #s in b4->spans[].sync are 1-based, and this returns a ++ * 0-based span, or -1 if no spans are found. ++ */ ++static inline int xhfc_find_sync(struct b400m *b4) ++{ ++ if (timingcable) ++ return xhfc_find_sync_with_timingcable(b4); ++ else ++ return xhfc_find_sync_without_timingcable(b4); ++} ++ ++/* ++ * allocates memory and pretty-prints a given S/T state engine state to it. ++ * calling routine is responsible for freeing the pointer returned! Performs ++ * no hardware access whatsoever, but does use GFP_KERNEL so do not call from ++ * IRQ context. if full == 1, prints a "full" dump; otherwise just prints ++ * current state. ++ */ ++static char *hfc_decode_st_state(struct b400m *b4, struct b400m_span *span, ++ unsigned char state, int full) ++{ ++ int nt, sta; ++ char s[128], *str; ++ const char *ststr[2][16] = { /* TE, NT */ ++ { "RESET", "?", "SENSING", "DEACT.", ++ "AWAIT.SIG", "IDENT.INPUT", "SYNCD", "ACTIVATED", ++ "LOSTFRAMING", "?", "?", "?", ++ "?", "?", "?", "?" }, ++ { "RESET", "DEACT.", "PEND.ACT", "ACTIVE", ++ "PEND.DEACT", "?", "?", "?", ++ "?", "?", "?", "?", ++ "?", "?", "?", "?" } ++ }; ++ ++ str = kmalloc(256, GFP_KERNEL); ++ if (!str) { ++ dev_warn(&b4->wc->vb.pdev->dev, ++ "could not allocate mem for ST state decode " \ ++ "string!\n"); ++ return NULL; ++ } ++ ++ nt = (span->te_mode == 0); ++ sta = (state & V_SU_STA_MASK); ++ ++ sprintf(str, "P%d: %s state %c%d (%s)", span->port + 1, ++ (nt ? "NT" : "TE"), (nt ? 'G' : 'F'), sta, ++ ststr[nt][sta]); ++ ++ if (full) { ++ sprintf(s, " SYNC: %s, RX INFO0: %s", ++ ((state & V_SU_FR_SYNC) ? "yes" : "no"), ++ ((state & V_SU_INFO0) ? "yes" : "no")); ++ strcat(str, s); ++ ++ if (nt) { ++ sprintf(s, ", T2 %s, auto G2->G3: %s", ++ ((state & V_SU_T2_EXP) ? "expired" : "OK"), ++ ((state & V_G2_G3) ? "yes" : "no")); ++ strcat(str, s); ++ } ++ } ++ ++ return str; ++} ++ ++/* ++ * sets an S/T port state machine to a given state. if 'auto' is nonzero, ++ * will put the state machine back in auto mode after setting the state. ++ */ ++static void hfc_handle_state(struct b400m_span *s); ++static void hfc_force_st_state(struct b400m *b4, struct b400m_span *s, ++ int state, int resume_auto) ++{ ++ b400m_setreg_ra(b4, R_SU_SEL, s->port, A_SU_WR_STA, ++ state | V_SU_LD_STA); ++ ++ if (resume_auto) ++ b400m_setreg_ra(b4, R_SU_SEL, s->port, A_SU_WR_STA, state); ++ ++ if (DBG_ST && ((1 << s->port) & bri_spanfilter)) { ++ char *x; ++ ++ x = hfc_decode_st_state(b4, s, state, 1); ++ b4_info(b4, "forced port %d to state %d (auto: %d), " ++ "new decode: %s\n", s->port + 1, state, ++ resume_auto, x); ++ kfree(x); ++ } ++ ++ /* make sure that we activate any timers/etc needed by this state ++ * change */ ++ hfc_handle_state(s); ++} ++ ++/* figures out what to do when an S/T port's timer expires. */ ++static void hfc_timer_expire(struct b400m_span *s, int t_no) ++{ ++ struct b400m *b4 = s->parent; ++ ++ if (DBG_ST && ((1 << s->port) & bri_spanfilter)) { ++ b4_info(b4, "%lu: hfc_timer_expire, Port %d T%d " ++ "expired (value=%lu ena=%d)\n", b4->ticks, ++ s->port + 1, t_no + 1, s->hfc_timers[t_no], ++ s->hfc_timer_on[t_no]); ++ } ++ /* ++ * there are three timers associated with every HFC S/T port. ++ * ++ * T1 is used by the NT state machine, and is the maximum time the NT ++ * side should wait for G3 (active) state. ++ * ++ * T2 is not actually used in the driver, it is handled by the HFC-4S ++ * internally. ++ * ++ * T3 is used by the TE state machine; it is the maximum time the TE ++ * side should wait for the INFO4 (activated) signal. ++ */ ++ ++ /* First, disable the expired timer; hfc_force_st_state() may activate ++ * it again. */ ++ s->hfc_timer_on[t_no] = 0; ++ ++ switch (t_no) { ++ case XHFC_T1: /* switch to G4 (pending deact.), resume auto mode */ ++ hfc_force_st_state(b4, s, 4, 1); ++ break; ++ case XHFC_T2: /* switch to G1 (deactivated), resume auto mode */ ++ hfc_force_st_state(b4, s, 1, 1); ++ break; ++ case XHFC_T3: /* switch to F3 (deactivated), resume auto mode */ ++ hfc_stop_st(s); ++ if (bri_persistentlayer1) ++ hfc_start_st(s); ++ break; ++ case XHFC_T4: /* switch to F3 (deactivated), resume auto mode */ ++ hfc_handle_state(s); ++ s->hfc_timers[XHFC_T4] = b4->ticks + 1000; ++ s->hfc_timer_on[XHFC_T4] = 1; ++ break; ++ default: ++ if (printk_ratelimit()) { ++ dev_warn(&b4->wc->vb.pdev->dev, ++ "hfc_timer_expire found an unknown expired " ++ "timer (%d)??\n", t_no); ++ } ++ } ++} ++ ++/* ++ * Run through the active timers on a card and deal with any expiries. ++ * Also see if the alarm debounce time has expired and if it has, tell DAHDI. ++ */ ++static void hfc_update_st_timers(struct b400m *b4) ++{ ++ int i, j; ++ struct b400m_span *s; ++ ++ for (i = 0; i < 4; i++) { ++ s = &b4->spans[i]; ++ ++ for (j = XHFC_T1; j <= XHFC_T4; j++) { ++ ++ /* we don't really do timer2, it is expired by the ++ * state change handler */ ++ if (j == XHFC_T2) ++ continue; ++ ++ if (s->hfc_timer_on[j] && ++ time_after_eq(b4->ticks, s->hfc_timers[j])) ++ hfc_timer_expire(s, j); ++ } ++ ++ if (s->wspan && s->newalarm != s->wspan->span.alarms && ++ time_after_eq(b4->ticks, s->alarmtimer)) { ++ s->wspan->span.alarms = s->newalarm; ++ if ((!s->newalarm && bri_teignorered) || (!bri_teignorered)) ++ dahdi_alarm_notify(&s->wspan->span); ++ ++ if (DBG_ALARM) { ++ dev_info(&b4->wc->vb.pdev->dev, "span %d: alarm " \ ++ "%d debounced\n", i + 1, ++ s->newalarm); ++ } ++ set_bit(WCTDM_CHECK_TIMING, &b4->wc->checkflag); ++ } ++ } ++ ++ if (test_and_clear_bit(WCTDM_CHECK_TIMING, &b4->wc->checkflag)) ++ xhfc_set_sync_src(b4, xhfc_find_sync(b4)); ++} ++ ++/* this is the driver-level state machine for an S/T port */ ++static void hfc_handle_state(struct b400m_span *s) ++{ ++ struct b400m *b4; ++ unsigned char state, sta; ++ int nt, newsync, oldalarm; ++ unsigned long oldtimer; ++ ++ b4 = s->parent; ++ nt = !s->te_mode; ++ ++ state = b400m_getreg_ra(b4, R_SU_SEL, s->port, A_SU_RD_STA); ++ sta = (state & V_SU_STA_MASK); ++ ++ if (DBG_ST && ((1 << s->port) & bri_spanfilter)) { ++ char *x; ++ ++ x = hfc_decode_st_state(b4, s, state, 1); ++ b4_info(b4, "port %d A_SU_RD_STA old=0x%02x " ++ "now=0x%02x, decoded: %s\n", s->port + 1, ++ s->oldstate, state, x); ++ kfree(x); ++ } ++ ++ oldalarm = s->newalarm; ++ oldtimer = s->alarmtimer; ++ ++ if (nt) { ++ switch (sta) { ++ default: /* Invalid NT state */ ++ case 0x0: /* NT state G0: Reset */ ++ case 0x1: /* NT state G1: Deactivated */ ++ case 0x4: /* NT state G4: Pending Deactivation */ ++ s->newalarm = DAHDI_ALARM_RED; ++ break; ++ case 0x2: /* NT state G2: Pending Activation */ ++ s->newalarm = DAHDI_ALARM_YELLOW; ++ break; ++ case 0x3: /* NT state G3: Active */ ++ s->hfc_timer_on[XHFC_T1] = 0; ++ s->newalarm = 0; ++ break; ++ } ++ } else { ++ switch (sta) { ++ default: /* Invalid TE state */ ++ case 0x0: /* TE state F0: Reset */ ++ case 0x2: /* TE state F2: Sensing */ ++ case 0x3: /* TE state F3: Deactivated */ ++ case 0x4: /* TE state F4: Awaiting Signal */ ++ case 0x8: /* TE state F8: Lost Framing */ ++ s->newalarm = DAHDI_ALARM_RED; ++ break; ++ case 0x5: /* TE state F5: Identifying Input */ ++ case 0x6: /* TE state F6: Synchronized */ ++ s->newalarm = DAHDI_ALARM_YELLOW; ++ break; ++ case 0x7: /* TE state F7: Activated */ ++ s->hfc_timer_on[XHFC_T3] = 0; ++ s->hfc_timer_on[XHFC_T4] = 0; ++ s->newalarm = 0; ++ break; ++ } ++ } ++ ++ s->alarmtimer = b4->ticks + bri_alarmdebounce; ++ s->oldstate = state; ++ ++ if (DBG_ALARM) { ++ b4_info(b4, "span %d: old alarm %d expires %ld, " ++ "new alarm %d expires %ld\n", s->port + 1, oldalarm, ++ oldtimer, s->newalarm, s->alarmtimer); ++ } ++ ++ /* we only care about T2 expiry in G4. */ ++ if (nt && (sta == 4) && (state & V_SU_T2_EXP)) { ++ if (s->hfc_timer_on[XHFC_T2]) ++ hfc_timer_expire(s, XHFC_T2); /* handle T2 expiry */ ++ } ++ ++ /* If we're in F3 and receiving INFO0, start T3 and jump to F4 */ ++ if (!nt && (sta == 3) && (state & V_SU_INFO0)) { ++ if (bri_persistentlayer1) { ++ s->hfc_timers[XHFC_T3] = b4->ticks + TIMER_3_MS; ++ s->hfc_timer_on[XHFC_T3] = 1; ++ if (DBG_ST) { ++ b4_info(b4, "port %d: receiving " ++ "INFO0 in state 3, setting T3 and " ++ "jumping to F4\n", s->port + 1); ++ } ++ hfc_start_st(s); ++ } ++ } ++ ++ /* read in R_BERT_STA to determine where our current sync source is */ ++ newsync = b400m_getreg(b4, R_BERT_STA) & 0x07; ++ if (newsync != b4->reportedsyncspan) { ++ if (DBG_TIMING) { ++ if (newsync == 5) { ++ b4_info(b4, "new card sync source: SYNC_I\n"); ++ } else { ++ b4_info(b4, "Card position %d: new " ++ "sync source: port %d\n", ++ b4->position, newsync); ++ } ++ } ++ ++ b4->reportedsyncspan = newsync; ++ } ++} ++ ++static void hfc_stop_all_timers(struct b400m_span *s) ++{ ++ s->hfc_timer_on[XHFC_T4] = 0; ++ s->hfc_timer_on[XHFC_T3] = 0; ++ s->hfc_timer_on[XHFC_T2] = 0; ++ s->hfc_timer_on[XHFC_T1] = 0; ++} ++ ++static void hfc_stop_st(struct b400m_span *s) ++{ ++ struct b400m *b4 = s->parent; ++ ++ hfc_stop_all_timers(s); ++ ++ b400m_setreg_ra(b4, R_SU_SEL, s->port, A_SU_WR_STA, V_SU_ACT_DEACTIVATE); ++} ++ ++/* ++ * resets an S/T interface to a given NT/TE mode ++ */ ++static void hfc_reset_st(struct b400m_span *s) ++{ ++ int b; ++ struct b400m *b4; ++ ++ b4 = s->parent; ++ ++ hfc_stop_st(s); ++ ++ /* force state G0/F0 (reset), then force state 1/2 ++ * (deactivated/sensing) */ ++ b400m_setreg_ra(b4, R_SU_SEL, s->port, A_SU_WR_STA, V_SU_LD_STA); ++ flush_hw(); /* make sure write hit hardware */ ++ ++ s->wspan->span.alarms = DAHDI_ALARM_RED; ++ s->newalarm = DAHDI_ALARM_RED; ++ dahdi_alarm_notify(&s->wspan->span); ++ ++ /* set up the clock control register. Must be done before we activate ++ * the interface. */ ++ if (s->te_mode) ++ b = 0x0e; ++ else ++ b = 0x0c | (6 << V_SU_SMPL_SHIFT); ++ ++ b400m_setreg(b4, A_SU_CLK_DLY, b); ++ ++ /* set TE/NT mode, enable B and D channels. */ ++ b400m_setreg(b4, A_SU_CTRL0, V_B1_TX_EN | V_B2_TX_EN | ++ (s->te_mode ? 0 : V_SU_MD) | V_ST_PU_CTRL); ++ b400m_setreg(b4, A_SU_CTRL1, V_G2_G3_EN); ++ b400m_setreg(b4, A_SU_CTRL2, V_B1_RX_EN | V_B2_RX_EN); ++ b400m_setreg(b4, A_ST_CTRL3, (0x7c << 1)); ++ ++ /* enable the state machine. */ ++ b400m_setreg(b4, A_SU_WR_STA, 0x00); ++ flush_hw(); ++} ++ ++static void hfc_start_st(struct b400m_span *s) ++{ ++ struct b400m *b4 = s->parent; ++ ++ b400m_setreg_ra(b4, R_SU_SEL, s->port, A_SU_WR_STA, V_SU_ACT_ACTIVATE); ++ ++ /* start T1 if in NT mode, T3 if in TE mode */ ++ if (s->te_mode) { ++ /* 500ms wait first time, TIMER_3_MS afterward. */ ++ s->hfc_timers[XHFC_T3] = b4->ticks + TIMER_3_MS; ++ s->hfc_timer_on[XHFC_T3] = 1; ++ s->hfc_timer_on[XHFC_T1] = 0; ++ ++ s->hfc_timers[XHFC_T4] = b4->ticks + 1000; ++ s->hfc_timer_on[XHFC_T4] = 1; ++ ++ if (DBG_ST) { ++ b4_info(b4, "setting port %d t3 timer to %lu\n", ++ s->port + 1, s->hfc_timers[XHFC_T3]); ++ } ++ } else { ++ static const int TIMER_1_MS = 2000; ++ s->hfc_timers[XHFC_T1] = b4->ticks + TIMER_1_MS; ++ s->hfc_timer_on[XHFC_T1] = 1; ++ s->hfc_timer_on[XHFC_T3] = 0; ++ if (DBG_ST) { ++ b4_info(b4, "setting port %d t1 timer to %lu\n", ++ s->port + 1, s->hfc_timers[XHFC_T1]); ++ } ++ } ++} ++ ++/* ++ * read in the HFC GPIO to determine each port's mode (TE or NT). ++ * Then, reset and start the port. ++ * the flow controller should be set up before this is called. ++ */ ++static int hdlc_start(struct b400m *b4, int fifo); ++static void hfc_init_all_st(struct b400m *b4) ++{ ++ int i; ++ struct b400m_span *s; ++ ++ for (i = 0; i < 4; i++) { ++ s = &b4->spans[i]; ++ s->parent = b4; ++ ++#ifdef SWAP_PORTS ++ s->port = (1 == i) ? 2 : (2 == i) ? 1 : i; ++#else ++ s->port = i; ++#endif ++ s->te_mode = 1; ++ ++ hdlc_start(b4, s->fifos[2]); ++ } ++ ++} ++ ++/* NOTE: assumes fifo lock is held */ ++#define debug_fz(b4, fifo, prefix, buf) \ ++do { \ ++ sprintf(buf, "%s: (fifo %d): f1/f2/flen=%d/%d/%d, " \ ++ "z1/z2/zlen=%d/%d/%d\n", prefix, fifo, f1, f2, flen, z1, \ ++ z2, zlen); \ ++} while (0) ++ ++/* enable FIFO RX int and reset the FIFO */ ++static int hdlc_start(struct b400m *b4, int fifo) ++{ ++ b4->fifo_en_txint |= (1 << fifo); ++ b4->fifo_en_rxint |= (1 << fifo); ++ ++ hfc_reset_fifo_pair(b4, fifo, 1, 0); ++ return 0; ++} ++ ++#ifdef HARDHDLC_RX ++ ++/** ++ * hdlc_signal_complete() - Signal dahdi that we have a complete frame. ++ * ++ * @bpan: The span which received the frame. ++ * @stat: The frame status from the XHFC controller. ++ * ++ */ ++static void hdlc_signal_complete(struct b400m_span *bspan, u8 stat) ++{ ++ struct b400m *b4 = bspan->parent; ++ ++ /* if STAT != 0, indicates bad frame */ ++ if (stat != 0x00) { ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "(span %d) STAT=0x%02x indicates " \ ++ "frame problem: %s\n", bspan->port + 1, stat, ++ (0xff == stat) ? "HDLC Abort" : "Bad FCS"); ++ } ++ ++ dahdi_hdlc_abort(bspan->sigchan, (0xff == stat) ? ++ DAHDI_EVENT_ABORT : DAHDI_EVENT_BADFCS); ++ /* STAT == 0, means frame was OK */ ++ } else { ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "(span %d) Frame %d is good!\n", ++ bspan->port + 1, bspan->frames_in); ++ } ++ dahdi_hdlc_finish(bspan->sigchan); ++ } ++} ++ ++/* ++ * Inner loop for D-channel receive function. Retrieves HDLC data from the ++ * hardware. If the hardware indicates that the frame is complete, we check ++ * the HDLC engine's STAT byte and update DAHDI as needed. ++ * ++ * Returns the number of HDLC frames left in the FIFO, or -1 if we couldn't ++ * get the lock. ++ */ ++static int hdlc_rx_frame(struct b400m_span *bspan) ++{ ++ int fifo, i, j, x, zleft; ++ int z1, z2, zlen, f1, f2, flen, new_flen; ++ unsigned char buf[B400M_HDLC_BUF_LEN]; ++ char debugbuf[256]; ++ struct b400m *b4 = bspan->parent; ++ ++ fifo = bspan->fifos[2]; ++ ++ if (DBG_HDLC && DBG_SPANFILTER) ++ b4_info(b4, "hdlc_rx_frame fifo %d: start\n", fifo); ++ ++ if (down_trylock(&b4->fifosem) && DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "rx_frame: fifo %d 1: couldn't get lock\n", ++ fifo); ++ return -1; ++ } ++ ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ get_F(f1, f2, flen); ++ get_Z(z1, z2, zlen); ++ debug_fz(b4, fifo, "hdlc_rx_frame", debugbuf); ++ up(&b4->fifosem); ++ ++ if (DBG_HDLC && DBG_SPANFILTER) ++ pr_info("%s", debugbuf); ++ ++ /* if we have at least one complete frame, increment zleft to include ++ * status byte */ ++ zleft = zlen; ++ if (flen) ++ zleft++; ++ ++ do { ++ if (zleft > B400M_HDLC_BUF_LEN) ++ j = B400M_HDLC_BUF_LEN; ++ else ++ j = zleft; ++ ++ if (down_trylock(&b4->fifosem) && DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, ++ "rx_frame fifo %d 2: couldn't get lock\n", ++ fifo); ++ return -1; ++ } ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ for (i = 0; i < j; i++) ++ buf[i] = b400m_getreg(b4, A_FIFO_DATA); ++ up(&b4->fifosem); ++ ++ /* don't send STAT byte to DAHDI */ ++ x = j; ++ if (bspan->sigchan) { ++ if ((j != B400M_HDLC_BUF_LEN) && flen) ++ x--; ++ if (x) ++ dahdi_hdlc_putbuf(bspan->sigchan, buf, x); ++ } ++ ++ zleft -= j; ++ ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "transmitted %d bytes to dahdi, " \ ++ "zleft=%d\n", x, zleft); ++ } ++ ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ /* !!! */ ++ b4_info(b4, "hdlc_rx_frame(span %d): " \ ++ "z1/z2/zlen=%d/%d/%d, zleft=%d\n", ++ bspan->port + 1, z1, z2, zlen, zleft); ++ for (i = 0; i < j; i++) { ++ b4_info(b4, "%02x%c", buf[i], ++ (i < (j - 1)) ? ' ' : '\n'); ++ } ++ } ++ } while (zleft > 0); ++ ++ /* Frame received, increment F2 and get an updated count of frames ++ * left */ ++ if (down_trylock(&b4->fifosem) && DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "rx_frame fifo %d 3: couldn't get lock\n", ++ fifo); ++ return 0; ++ } ++ ++ /* go get the F count again, just in case another frame snuck in while ++ * we weren't looking. */ ++ if (flen) { ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F); ++ ++bspan->frames_in; ++ get_F(f1, f2, new_flen); ++ } else ++ new_flen = flen; ++ ++ up(&b4->fifosem); ++ ++ /* If this channel is not configured with a signalling span we don't ++ * need to notify the rest of dahdi about this frame. */ ++ if (!bspan->sigchan) { ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "hdlc_rx_frame fifo %d: " \ ++ "new_flen %d, early end.\n", fifo, new_flen); ++ } ++ return new_flen; ++ } ++ ++ if (flen) { ++ /* disable < 3 check for now */ ++ if (0 && zlen < 3) { ++ if (DBG_HDLC && DBG_SPANFILTER) ++ b4_info(b4, "odd, zlen less then 3?\n"); ++ dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_ABORT); ++ } else { ++ hdlc_signal_complete(bspan, buf[i - 1]); ++ } ++ } ++ ++ if (DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "hdlc_rx_frame fifo %d: new_flen=%d end.\n", ++ fifo, new_flen); ++ } ++ ++ return new_flen; ++} ++ ++#endif /* HARDHDLC_RX */ ++ ++ ++/* ++ * Takes one blob of data from DAHDI and shoots it out to the hardware. The ++ * blob may or may not be a complete HDLC frame. If it isn't, the D-channel ++ * FIFO interrupt handler will take care of pulling the rest. Returns nonzero ++ * if there is still data to send in the current HDLC frame. ++ */ ++static int hdlc_tx_frame(struct b400m_span *bspan) ++{ ++ struct b400m *b4 = bspan->parent; ++ int res, i, fifo; ++ int z1, z2, zlen; ++ int f1 = -1, f2 = -1, flen = -1; ++ unsigned char buf[B400M_HDLC_BUF_LEN]; ++ unsigned int size = ARRAY_SIZE(buf); ++ char debugbuf[256]; ++ ++ /* if we're ignoring TE red alarms and we are in alarm, restart the ++ * S/T state machine */ ++ if (bspan->te_mode && (bspan->newalarm != 0)) { ++ hfc_start_st(bspan); ++ } ++ ++ fifo = bspan->fifos[2]; ++ res = dahdi_hdlc_getbuf(bspan->sigchan, buf, &size); ++ ++ if (down_interruptible(&b4->fifosem)) { ++ static int arg; ++ b4_info(b4, "b400m: arg (%d), grabbed data from DAHDI " \ ++ "but couldn't grab the lock!\n", ++arg); ++ /* TODO: Inform DAHDI that we have grabbed data and can't use ++ * it */ ++ dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_OVERRUN); ++ return 1; /* return 1 so we keep trying */ ++ } ++ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); ++ ++ get_Z(z1, z2, zlen); ++ debug_fz(b4, fifo, __func__, debugbuf); ++ ++ /* TODO: check zlen, etc. */ ++ if ((HFC_ZMAX-zlen) < size) { ++ static int arg; ++ b4_info(b4, "b400m: arg (%d), zlen (%d) < what we " \ ++ "grabbed from DAHDI (%d)!\n", ++arg, zlen, size); ++ size = zlen; ++ dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_OVERRUN); ++ } ++ ++ if (size > 0) { ++ bspan->sigactive = 1; ++ ++ for (i = 0; i < size; i++) ++ b400m_setreg(b4, A_FIFO_DATA, buf[i]); ++ /* ++ * If we got a full frame from DAHDI, increment F and ++ * decrement our HDLC pending counter. Otherwise, select the ++ * FIFO again (to start transmission) and make sure the TX IRQ ++ * is enabled so we will get called again to finish off the ++ * data ++ */ ++ if (res != 0) { ++ ++bspan->frames_out; ++ bspan->sigactive = 0; ++ hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F); ++ atomic_dec(&bspan->hdlc_pending); ++ } else { ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (fifo << V_FIFO_NUM_SHIFT)); ++ } ++ } ++ ++ up(&b4->fifosem); ++ ++ if (0 && DBG_HDLC && DBG_SPANFILTER) { ++ b4_info(b4, "%s", debugbuf); ++ ++ b4_info(b4, "hdlc_tx_frame(span %d): DAHDI gave %d " \ ++ "bytes for FIFO %d (res = %d)\n", ++ bspan->port + 1, size, fifo, res); ++ ++ for (i = 0; i < size; i++) ++ b4_info(b4, ++ "%02x%c\n", buf[i], ++ (i < (size - 1)) ? ' ' : '\n'); ++ ++ if (size && res != 0) { ++ pr_info("Transmitted frame %d on span %d\n", ++ bspan->frames_out - 1, bspan->port); ++ } ++ } ++ ++ return (res == 0); ++} ++ ++/* ++ * b400m lowlevel functions These are functions which impact more than just ++ * the HFC controller. (those are named hfc_xxx()) ++ */ ++ ++/* ++ * Performs a total reset of the card, reinitializes GPIO. The card is ++ * initialized enough to have LEDs running, and that's about it. Anything to ++ * do with audio and enabling any kind of processing is done in stage2. ++ */ ++static void xhfc_init_stage1(struct b400m *b4) ++{ ++ int i; ++ ++ hfc_reset(b4); ++ hfc_gpio_init(b4); ++ ++ /* make sure interrupts are disabled */ ++ b400m_setreg(b4, R_IRQ_CTRL, 0x00); ++ ++ /* make sure write hits hardware */ ++ flush_hw(); ++ ++ /* disable all FIFO interrupts */ ++ for (i = 0; i < HFC_NR_FIFOS; i++) { ++ hfc_setreg_waitbusy(b4, R_FIFO, (i << V_FIFO_NUM_SHIFT)); ++ /* disable the interrupt */ ++ b400m_setreg(b4, A_FIFO_CTRL, 0x00); ++ hfc_setreg_waitbusy(b4, R_FIFO, ++ (i << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); ++ /* disable the interrupt */ ++ b400m_setreg(b4, A_FIFO_CTRL, 0x00); ++ flush_hw(); ++ } ++ ++ /* set fill threshhold to 16 bytes */ ++ b400m_setreg(b4, R_FIFO_THRES, 0x11); ++ ++ /* clear any pending FIFO interrupts */ ++ b400m_getreg(b4, R_FIFO_BL2_IRQ); ++ b400m_getreg(b4, R_FIFO_BL3_IRQ); ++ ++ b4->misc_irq_mask = 0x00; ++ b400m_setreg(b4, R_MISC_IRQMSK, b4->misc_irq_mask); ++ b400m_setreg(b4, R_IRQ_CTRL, 0); ++} ++ ++/* ++ * Stage 2 hardware init. Sets up the flow controller, PCM and FIFOs. ++ * Initializes the echo cancellers. S/T interfaces are not initialized here, ++ * that is done later, in hfc_init_all_st(). Interrupts are enabled and once ++ * the s/t interfaces are configured, chip should be pretty much operational. ++ */ ++static void xhfc_init_stage2(struct b400m *b4) ++{ ++ /* ++ * set up PCM bus. XHFC is PCM slave C2IO is the clock, auto sync, ++ * SYNC_O follows SYNC_I. 128 timeslots, long frame sync positive ++ * polarity, sample on falling clock edge. STIO2 is transmit-only, ++ * STIO1 is receive-only. ++ */ ++ b400m_setreg(b4, R_PCM_MD0, V_PCM_IDX_MD1); ++ b400m_setreg(b4, R_PCM_MD1, V_PCM_DR_8192 | (0x3 << 2)); ++ b400m_setreg(b4, R_PCM_MD0, V_PCM_IDX_MD2); ++ b400m_setreg(b4, R_PCM_MD2, V_C2I_EN | V_SYNC_OUT1); ++ b400m_setreg(b4, R_SU_SYNC, V_SYNC_SEL_PORT0); ++ ++ /* Now set up the flow controller. */ ++ hfc_setup_fsm(b4); ++ ++ /* ++ * At this point, everything's set up and ready to go. Don't actually ++ * enable the global interrupt pin. DAHDI still needs to start up the ++ * spans, and we don't know exactly when. ++ */ ++} ++ ++static inline struct b400m_span *bspan_from_dspan(struct dahdi_span *span) ++{ ++ return container_of(span, struct wctdm_span, span)->bspan; ++} ++ ++static int xhfc_startup(struct dahdi_span *span) ++{ ++ struct b400m_span *bspan = bspan_from_dspan(span); ++ struct b400m *b4 = bspan->parent; ++ if (!b4->running) ++ hfc_enable_interrupts(bspan->parent); ++ ++ return 0; ++} ++ ++/* resets all the FIFOs for a given span. Disables IRQs for the span FIFOs */ ++static void xhfc_reset_span(struct b400m_span *bspan) ++{ ++ int i; ++ struct b400m *b4 = bspan->parent; ++ ++ /* b4_info(b4, "xhfc_reset_span()\n"); */ ++ for (i = 0; i < 3; i++) ++ hfc_reset_fifo_pair(b4, bspan->fifos[i], (i == 2) ? 1 : 0, 1); ++} ++ ++static void b400m_enable_workqueues(struct wctdm *wc) ++{ ++ struct b400m *b4s[2]; ++ int i, numb4s = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ for (i = 0; i < wc->mods_per_board; i += 4) { ++ if (wc->mods[i].type == BRI) ++ b4s[numb4s++] = wc->mods[i].mod.bri; ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ for (i = 0; i < numb4s; i++) { ++ if (b4s[i]) ++ b4s[i]->shutdown = 0; ++ } ++ ++} ++ ++static void b400m_disable_workqueues(struct wctdm *wc) ++{ ++ struct b400m *b4s[2]; ++ int i, numb4s = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ for (i = 0; i < wc->mods_per_board; i += 4) { ++ if (wc->mods[i].type == BRI) ++ b4s[numb4s++] = wc->mods[i].mod.bri; ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ for (i = 0; i < numb4s; i++) { ++ if (b4s[i]) { ++ down(&wc->syncsem); ++ b4s[i]->shutdown = 1; ++ up(&wc->syncsem); ++ flush_workqueue(b4s[i]->xhfc_ws); ++ } ++ } ++} ++/* ++ * Software selectable NT and TE mode settings on the B400M. ++ * ++ * mode - bitwise selection of NT vs TE mode ++ * 1 = NT; 0 = TE; ++ * bit 0 is port 0 ++ * bit 1 is port 1 ++ * ... ++ * term - termination resistance ++ * 0 = no termination resistance ++ * 1 = 390 ohm termination resistance switched on ++ */ ++static int b400m_set_ntte(struct b400m_span *bspan, int te_mode, int term_on) ++{ ++ struct b400m *b4 = bspan->parent; ++ unsigned char data; ++ unsigned char addr; ++ int all_modes = 0, all_terms = 0; ++ int i; ++ ++ bspan->wspan->span.spantype = (te_mode > 0) ++ ? SPANTYPE_DIGITAL_BRI_TE ++ : SPANTYPE_DIGITAL_BRI_NT; ++ ++ bspan->te_mode = te_mode; ++ bspan->term_on = term_on; ++ ++ for (i = 0; i < 4; i++) { ++ if (!b4->spans[i].te_mode) ++ all_modes |= (1 << i); ++ if (b4->spans[i].term_on) ++ all_terms |= (1 << i); ++ } ++ ++ data = 0x10 | ((all_terms << 4) & 0xc0) | ((all_terms << 2) & 0x0c); ++ addr = 0x10 | all_modes; ++ ++ msleep(voicebus_current_latency(&b4->wc->vb) + 2); ++ wctdm_setreg(b4->wc, get_mod(b4), addr, data); ++ ++ b4->lastreg = 0xff; ++ msleep(voicebus_current_latency(&b4->wc->vb) + 2); ++ ++ hfc_reset_st(bspan); ++ ++ if (bri_persistentlayer1) ++ hfc_start_st(bspan); ++ ++ return 0; ++} ++ ++/* spanconfig for us means ...? */ ++int b400m_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ struct b400m_span *bspan; ++ struct b400m *b4; ++ struct wctdm *wc; ++ int te_mode, term; ++ int pos; ++ int res; ++ ++ bspan = bspan_from_dspan(span); ++ b4 = bspan->parent; ++ wc = b4->wc; ++ ++ if ((file->f_flags & O_NONBLOCK) && !is_initialized(wc)) ++ return -EAGAIN; ++ ++ res = wctdm_wait_for_ready(wc); ++ if (res) ++ return res; ++ ++ b400m_disable_workqueues(b4->wc); ++ ++ te_mode = (lc->lineconfig & DAHDI_CONFIG_NTTE) ? 0 : 1; ++ ++ term = (lc->lineconfig & DAHDI_CONFIG_TERM) ? 1 : 0; ++ ++ b4_info(b4, "xhfc: Configuring port %d span %d in %s " \ ++ "mode with termination resistance %s\n", bspan->port, ++ span->spanno, (te_mode) ? "TE" : "NT", ++ (term) ? "ENABLED" : "DISABLED"); ++ ++ b400m_set_ntte(bspan, te_mode, term); ++ if (lc->sync < 0) { ++ b4_info(b4, "Span %d has invalid sync priority (%d), " \ ++ "removing from sync source list\n", span->spanno, ++ lc->sync); ++ lc->sync = 0; ++ } ++ ++ if (span->offset >= 4) { ++ pos = span->offset; ++ } else { ++ /* This is tricky. Have to figure out if we're slot 1 or slot ++ * 2 */ ++ pos = span->offset + b4->position; ++ } ++ ++ if (!te_mode && lc->sync) { ++ b4_info(b4, "NT Spans cannot be timing sources. " \ ++ "Span %d requested to be timing source of " \ ++ "priority %d. Changing priority to 0\n", pos, ++ lc->sync); ++ lc->sync = 0; ++ } ++ ++ wc->spans[pos]->timing_priority = lc->sync; ++ ++ bspan->wspan = container_of(span, struct wctdm_span, span); ++ xhfc_reset_span(bspan); ++ ++ /* call startup() manually here, because DAHDI won't call the startup ++ * function unless it receives an IOCTL to do so, and dahdi_cfg ++ * doesn't. */ ++ xhfc_startup(span); ++ ++ span->flags |= DAHDI_FLAG_RUNNING; ++ ++ set_bit(WCTDM_CHECK_TIMING, &wc->checkflag); ++ ++ b400m_enable_workqueues(b4->wc); ++ ++ return 0; ++} ++ ++/* chanconfig for us means to configure the HDLC controller, if appropriate ++ * ++ * NOTE: apparently the DAHDI ioctl function calls us with a interrupts ++ * disabled. This means we cannot actually touch the hardware, because all ++ * register accesses are wrapped up in a mutex that can sleep. ++ * ++ * The solution to that is to simply increment the span's "restart" flag, and ++ * the driver's workqueue will do the dirty work on our behalf. ++ */ ++int b400m_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype) ++{ ++ int alreadyrunning; ++ struct b400m_span *bspan = bspan_from_dspan(chan->span); ++ struct b400m *b4 = bspan->parent; ++ int res; ++ ++ if ((file->f_flags & O_NONBLOCK) && !is_initialized(b4->wc)) ++ return -EAGAIN; ++ ++ res = wctdm_wait_for_ready(b4->wc); ++ if (res) ++ return res; ++ ++ alreadyrunning = bspan->wspan->span.flags & DAHDI_FLAG_RUNNING; ++ ++ if (DBG_FOPS) { ++ b4_info(b4, "%s channel %d (%s) sigtype %08x\n", ++ alreadyrunning ? "Reconfigured" : "Configured", ++ chan->channo, chan->name, sigtype); ++ } ++ ++ switch (sigtype) { ++ case DAHDI_SIG_HARDHDLC: ++ if (DBG_FOPS) { ++ b4_info(b4, "%sonfiguring hardware HDLC on %s\n", ++ ((sigtype == DAHDI_SIG_HARDHDLC) ? "C" : ++ "Unc"), chan->name); ++ } ++ bspan->sigchan = chan; ++ bspan->sigactive = 0; ++ atomic_set(&bspan->hdlc_pending, 0); ++ res = 0; ++ break; ++ case DAHDI_SIG_HDLCFCS: ++ case DAHDI_SIG_HDLCNET: ++ case DAHDI_SIG_HDLCRAW: ++ /* Only HARDHDLC is supported for the signalling channel on BRI ++ * spans. */ ++ res = -EINVAL; ++ break; ++ default: ++ res = 0; ++ break; ++ }; ++ ++ return res; ++} ++ ++int b400m_dchan(struct dahdi_span *span) ++{ ++ struct b400m_span *bspan; ++ struct b400m *b4; ++ unsigned char *rxb; ++ int res; ++ int i; ++ ++ bspan = bspan_from_dspan(span); ++ b4 = bspan->parent; ++#ifdef HARDHDLC_RX ++ return 0; ++#else ++#endif ++ ++ if (!bspan->sigchan) ++ return 0; ++ ++ rxb = bspan->sigchan->readchunk; ++ ++ if (!rxb) { ++ b4_info(b4, "No RXB!\n"); ++ return 0; ++ } ++ ++ for (i = 0; i < DAHDI_CHUNKSIZE; i++) { ++ fasthdlc_rx_load_nocheck(&bspan->rxhdlc, *(rxb++)); ++ res = fasthdlc_rx_run(&bspan->rxhdlc); ++ /* If there is nothing there, continue */ ++ if (res & RETURN_EMPTY_FLAG) ++ continue; ++ else if (res & RETURN_COMPLETE_FLAG) { ++ ++ if (!bspan->f_sz) ++ continue; ++ ++ /* Only count this if it's a non-empty frame */ ++ if (bspan->infcs != PPP_GOODFCS) { ++ dahdi_hdlc_abort(bspan->sigchan, ++ DAHDI_EVENT_BADFCS); ++ } else { ++ dahdi_hdlc_finish(bspan->sigchan); ++ } ++ bspan->infcs = PPP_INITFCS; ++ bspan->f_sz = 0; ++ continue; ++ } else if (res & RETURN_DISCARD_FLAG) { ++ ++ if (!bspan->f_sz) ++ continue; ++ ++ dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_ABORT); ++ bspan->infcs = PPP_INITFCS; ++ bspan->f_sz = 0; ++ break; ++ } else { ++ unsigned char rxc = res; ++ bspan->infcs = PPP_FCS(bspan->infcs, rxc); ++ bspan->f_sz++; ++ dahdi_hdlc_putbuf(bspan->sigchan, &rxc, 1); ++ } ++ } ++ ++ return 0; ++} ++ ++/* internal functions, not specific to the hardware or DAHDI */ ++ ++/* ++ */ ++static void xhfc_work(struct work_struct *work) ++{ ++ struct b400m *b4 = container_of(work, struct b400m, xhfc_wq); ++ int i, j, k, fifo; ++ unsigned char b, b2; ++ ++ if (b4->shutdown || !is_initialized(b4->wc)) ++ return; ++ ++ b4->irq_oview = b400m_getreg(b4, R_IRQ_OVIEW); ++ b4->fifo_fill = b400m_getreg(b4, R_FILL_BL0); ++ ++ if (b4->irq_oview & V_FIFO_BL0_IRQ) { ++ b4->fifo_irqstatus |= b400m_getreg(b4, R_FIFO_BL0_IRQ); ++ b4->irq_oview &= ~V_FIFO_BL0_IRQ; ++ } ++ ++ /* only look at BL0, we put all D channel FIFOs in the first block. */ ++ b = b2 = b4->fifo_irqstatus; ++ ++ for (j = 0; j < 4; j++) { ++#ifdef SWAP_PORTS ++ fifo = (1 == j) ? 2 : (2 == j) ? 1 : j; ++#else ++ fifo = j; ++#endif ++ ++#ifdef HARDHDLC_RX ++ if (b & V_FIFOx_RX_IRQ) { ++ if (fifo < 4) { /* d-channel FIFO */ ++ ++ /* ++ * I have to loop here until hdlc_rx_frame ++ * says there are no more frames waiting. for ++ * whatever reason, the HFC will not generate ++ * another interrupt if there are still HDLC ++ * frames waiting to be received. i.e. I get ++ * an int when F1 changes, not when F1 != F2. ++ * ++ */ ++ do { ++ k = hdlc_rx_frame(&b4->spans[fifo]); ++ } while (k); ++ } ++ } ++ ++#endif ++ b >>= 2; ++ } ++ ++ /* zero the bits we just processed */ ++ b4->fifo_irqstatus &= ~b2; ++ b4->fifo_fill &= ~b2; ++ ++ ++#if 1 ++ /* All four D channel FIFOs are in BL0. */ ++ b = b2 = b4->fifo_fill; ++ ++ for (j = 0; j < 4; j++) { ++#ifdef SWAP_PORTS ++ fifo = (1 == j) ? 2 : (2 == j) ? 1 : j; ++#else ++ fifo = j; ++#endif ++ if (b4->spans[fifo].sigactive && (b & V_FIFOx_TX_IRQ)) ++ hdlc_tx_frame(&b4->spans[fifo]); ++ ++#ifdef HARDHDLC_RX ++ if (b & V_FIFOx_RX_IRQ) ++ hdlc_rx_frame(&b4->spans[fifo]); ++#endif ++ ++ b >>= 2; ++ } ++#endif ++ ++ /* Check for outgoing HDLC frame requests The HFC does not generate TX ++ * interrupts when there is room to send, so I use an atomic counter ++ * that is incremented every time DAHDI wants to send a frame, and ++ * decremented every time I send a frame. It'd be better if I could ++ * just use the interrupt handler, but the HFC seems to trigger a FIFO ++ * TX IRQ only when it has finished sending a frame, not when one can ++ * be sent. ++ */ ++ for (i = 0; i < ARRAY_SIZE(b4->spans); i++) { ++ struct b400m_span *bspan = &b4->spans[i]; ++ ++ if (atomic_read(&bspan->hdlc_pending)) { ++ do { ++ k = hdlc_tx_frame(bspan); ++ } while (k); ++ } ++ } ++ ++ b = b400m_getreg(b4, R_SU_IRQ); ++ ++ if (b) { ++ for (i = 0; i < ARRAY_SIZE(b4->spans); i++) { ++ int physport; ++ ++#ifdef SWAP_PORTS ++ if (i == 1) ++ physport = 2; ++ else if (i == 2) ++ physport = 1; ++ else ++ physport = i; ++#else ++ physport = i; ++#endif ++ if (b & (1 << i)) ++ hfc_handle_state(&b4->spans[physport]); ++ } ++ } ++ ++ hfc_update_st_timers(b4); ++} ++ ++void wctdm_bri_checkisr(struct wctdm *wc, struct wctdm_module *const mod, ++ int offset) ++{ ++ struct b400m *b4 = mod->mod.bri; ++ ++ /* don't do anything for non-base card slots */ ++ if (mod->card & 0x03) ++ return; ++ ++ /* DEFINITELY don't do anything if our structures aren't ready! */ ++ if (!is_initialized(wc) || !b4 || !b4->inited) ++ return; ++ ++ if (offset == 0) { ++ if (!b4->shutdown) ++ queue_work(b4->xhfc_ws, &b4->xhfc_wq); ++ b4->ticks++; ++ } ++ return; ++} ++ ++/* DAHDI calls this when it has data it wants to send to the HDLC controller */ ++void wctdm_hdlc_hard_xmit(struct dahdi_chan *chan) ++{ ++ struct b400m *b4; ++ struct b400m_span *bspan; ++ struct dahdi_span *dspan; ++ int span; ++ ++ dspan = chan->span; ++ bspan = bspan_from_dspan(dspan); ++ b4 = bspan->parent; ++ span = bspan->port; ++ ++ if ((DBG_FOPS || DBG_HDLC) && DBG_SPANFILTER) { ++ b4_info(b4, "hdlc_hard_xmit on chan %s (%i/%i), " \ ++ "span=%i (sigchan=%p, chan=%p)\n", chan->name, ++ chan->channo, chan->chanpos, span + 1, ++ bspan->sigchan, chan); ++ } ++ ++ /* Increment the hdlc_pending counter and trigger the bottom-half so ++ * it will be picked up and sent. */ ++ if (bspan->sigchan == chan) ++ atomic_inc(&bspan->hdlc_pending); ++} ++ ++static int b400m_probe(struct wctdm *wc, int modpos) ++{ ++ unsigned char id, x; ++ struct b400m *b4; ++ unsigned long flags; ++ int chiprev; ++ ++ wctdm_setreg(wc, &wc->mods[modpos], 0x10, 0x10); ++ id = xhfc_getreg(wc, &wc->mods[modpos], R_CHIP_ID, &x); ++ ++ /* chip ID high 7 bits must be 0x62, see datasheet */ ++ if ((id & 0xfe) != 0x62) ++ return -2; ++ ++ b4 = kzalloc(sizeof(struct b400m), GFP_KERNEL); ++ if (!b4) { ++ dev_err(&wc->vb.pdev->dev, ++ "Couldn't allocate memory for b400m structure!\n"); ++ return -ENOMEM; ++ } ++ ++ /* card found, enabled and main struct allocated. Fill it out. */ ++ b4->wc = wc; ++ b4->position = modpos; ++ ++ /* which B400M in the system is this one? count all of them found so ++ * far */ ++ for (x = 0; x < modpos; x += 4) { ++ if (wc->mods[x].type == BRI) ++ ++b4->b400m_no; ++ } ++ ++ spin_lock_init(&b4->reglock); ++ sema_init(&b4->regsem, 1); ++ sema_init(&b4->fifosem, 1); ++ ++ for (x = 0; x < 4; x++) { ++ fasthdlc_init(&b4->spans[x].rxhdlc, FASTHDLC_MODE_16); ++ b4->spans[x].infcs = PPP_INITFCS; ++ } ++ ++ b4->lastreg = 0xff; /* a register we won't hit right off the bat */ ++ ++ chiprev = b400m_getreg(b4, R_CHIP_RV); ++ ++ b4->setsyncspan = -1; /* sync span is unknown */ ++ b4->reportedsyncspan = -1; /* sync span is unknown */ ++ ++ if (DBG) { ++ b4_info(b4, "Identified controller rev %d in module %d.\n", ++ chiprev, b4->position); ++ } ++ ++ xhfc_init_stage1(b4); ++ ++ xhfc_init_stage2(b4); ++ hfc_init_all_st(b4); ++ ++ hfc_enable_interrupts(b4); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->mods[modpos].mod.bri = (void *)b4; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return 0; ++} ++ ++void b400m_post_init(struct b400m *b4) ++{ ++ snprintf(b4->name, sizeof(b4->name) - 1, "b400m-%d", ++ b4->b400m_no); ++ b4->xhfc_ws = create_singlethread_workqueue(b4->name); ++ INIT_WORK(&b4->xhfc_wq, xhfc_work); ++ b4->inited = 1; ++} ++ ++/* functions called from the wctdm code */ ++int wctdm_init_b400m(struct wctdm *wc, int card) ++{ ++ int ret = 0; ++ unsigned long flags; ++ ++ if (wc->mods[card & 0xfc].type == QRV) ++ return -2; ++ ++ if (!(card & 0x03)) { /* only init if at lowest port in module */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->mods[card + 0].type = BRI; ++ wc->mods[card + 0].mod.bri = NULL; ++ wc->mods[card + 1].type = BRI; ++ wc->mods[card + 1].mod.bri = NULL; ++ wc->mods[card + 2].type = BRI; ++ wc->mods[card + 2].mod.bri = NULL; ++ wc->mods[card + 3].type = BRI; ++ wc->mods[card + 3].mod.bri = NULL; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ msleep(20); ++ ++ if (b400m_probe(wc, card) != 0) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->mods[card + 0].type = NONE; ++ wc->mods[card + 1].type = NONE; ++ wc->mods[card + 2].type = NONE; ++ wc->mods[card + 3].type = NONE; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ret = -2; ++ } ++ } else { /* for the "sub-cards" */ ++ if (wc->mods[card & 0xfc].type == BRI) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->mods[card].type = BRI; ++ wc->mods[card].mod.bri = wc->mods[card & 0xfc].mod.bri; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else { ++ ret = -2; ++ } ++ } ++ ++ return ret; ++} ++ ++void wctdm_unload_b400m(struct wctdm *wc, int card) ++{ ++ struct b400m *b4 = wc->mods[card].mod.bri; ++ int i; ++ ++ /* TODO: shutdown once won't work if just a single card is hotswapped ++ * out. But since most of the time this is called because the entire ++ * driver is in the process of unloading, I'll leave it here. */ ++ static int shutdown_once; ++ ++ ++ /* only really unload with the 'base' card number. base+1/2/3 aren't ++ * real. */ ++ if (card & 0x03) ++ return; ++ ++ if (timingcable && !shutdown_once) { ++ b4_info(b4, "Disabling all workqueues for B400Ms\n"); ++ /* Gotta shut down timing change potential during this */ ++ for (i = 0; i < WC_MAX_IFACES; i++) { ++ if (ifaces[i]) ++ b400m_disable_workqueues(ifaces[i]); ++ } ++ b4_info(b4, "Forcing sync to card 0\n"); ++ /* Put the timing configuration in a known state: card 0 is ++ * master */ ++ wctdm_change_system_sync_src(synccard, syncspan, -1, -1); ++ /* Change all other cards in the system to self time before ++ * card 0 is removed */ ++ b4_info(b4, "Setting all cards to return to self sync\n"); ++ for (i = 1; i < WC_MAX_IFACES; i++) { ++ if (ifaces[i]) ++ wctdm_change_card_sync_src(ifaces[i], 0, 0); ++ } ++ ++ b4_info(b4, ++ "Finished preparing timing linked cards for " ++ "shutdown\n"); ++ ++ shutdown_once = 1; ++ } ++ ++ if (b4) { ++ b4->inited = 0; ++ ++ msleep(100); ++ ++ /* TODO: wait for tdm24xx driver to unregister the spans */ ++ /* do { ... } while(not_unregistered); */ ++ ++ /* Change sync source back to base board so we don't freeze up ++ * when we reset the XHFC */ ++ b400m_disable_workqueues(wc); ++ ++ for (i = 0; i < (MAX_SPANS - 1); i++) { ++ if (wc->spans[i]) ++ wc->spans[i]->timing_priority = 0; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(b4->spans); i++) ++ b4->spans[i].wspan->span.flags &= ~DAHDI_FLAG_RUNNING; ++ ++ wctdm_change_card_sync_src(b4->wc, 0, 0); ++ ++ xhfc_init_stage1(b4); ++ ++ destroy_workqueue(b4->xhfc_ws); ++ ++ /* Set these to NONE to ensure that our checkisr ++ * routines are not entered */ ++ wc->mods[card].type = NONE; ++ wc->mods[card + 1].type = NONE; ++ wc->mods[card + 2].type = NONE; ++ wc->mods[card + 3].type = NONE; ++ ++ wc->mods[card].mod.bri = NULL; ++ wc->mods[card + 1].mod.bri = NULL; ++ wc->mods[card + 2].mod.bri = NULL; ++ wc->mods[card + 3].mod.bri = NULL; ++ ++ msleep(voicebus_current_latency(&wc->vb) << 1); ++ b4_info(b4, "Driver unloaded.\n"); ++ kfree(b4); ++ } ++ ++} ++ ++void b400m_module_init(void) ++{ ++ fasthdlc_precalc(); ++} ++ ++void b400m_module_cleanup(void) ++{ ++} +diff -Nru linux-source-4.19/drivers/dahdi/wctdm24xxp/xhfc.h linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/xhfc.h +--- linux-source-4.19/drivers/dahdi/wctdm24xxp/xhfc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wctdm24xxp/xhfc.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,52 @@ ++/* ++ * B400M Quad-BRI module Driver ++ * Written by Andrew Kohlsmith ++ * ++ * Copyright (C) 2010 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 _B4XXM_H_ ++#define _B4XXM_H_ ++ ++extern int bri_debug; ++extern int bri_spanfilter; ++extern int bri_teignorered; ++extern int bri_alarmdebounce; ++extern int bri_persistentlayer1; ++extern int timingcable; ++ ++struct b400m; ++ ++/* probes the given card to see if it's a B400M */ ++int wctdm_init_b400m(struct wctdm *wc, int card); ++void wctdm_bri_checkisr(struct wctdm *wc, ++ struct wctdm_module *const mod, int offset); ++void wctdm_unload_b400m(struct wctdm *wc, int card); ++void wctdm_hdlc_hard_xmit(struct dahdi_chan *chan); ++int b400m_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc); ++int b400m_dchan(struct dahdi_span *span); ++int b400m_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype); ++void b400m_post_init(struct b400m *b4); ++void b400m_set_dahdi_span(struct b400m *b4, int spanno, ++ struct wctdm_span *wspan); ++void b400m_module_init(void); ++void b400m_module_cleanup(void); ++ ++#endif /* _B4XX_H_ */ +diff -Nru linux-source-4.19/drivers/dahdi/wcte13xp-base.c linux-source-4.19-dahdi/drivers/dahdi/wcte13xp-base.c +--- linux-source-4.19/drivers/dahdi/wcte13xp-base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcte13xp-base.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,2823 @@ ++/* ++ * Digium, Inc. Wildcard te13xp T1/E1 card Driver ++ * ++ * Written by Russ Meyerriecks ++ * Copyright (C) 2012 - 2013, 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. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "wct4xxp/wct4xxp.h" /* For certain definitions */ ++#include "wcxb.h" ++#include "wcxb_spi.h" ++#include "wcxb_flash.h" ++ ++static const char *TE133_FW_FILENAME = "dahdi-fw-te133.bin"; ++static const char *TE134_FW_FILENAME = "dahdi-fw-te134.bin"; ++static const u32 TE133_FW_VERSION = 0x7a001e; ++static const u32 TE134_FW_VERSION = 0x780017; ++ ++#define WC_MAX_IFACES 8 ++ ++enum linemode { ++ T1 = 1, ++ E1, ++ J1, ++}; ++ ++/* FPGA Status definitions */ ++#define OCT_CPU_RESET (1 << 0) ++#define OCT_CPU_DRAM_CKE (1 << 1) ++#define STATUS_LED_GREEN (1 << 9) ++#define STATUS_LED_RED (1 << 10) ++#define FALC_CPU_RESET (1 << 11) ++ ++/* Descriptor ring definitions */ ++#define DRING_SIZE (1 << 7) /* Must be in multiples of 2 */ ++#define DMA_CHAN_SIZE 128 ++ ++/* Interrupt definitions */ ++#define INTERRUPT_CONTROL 0x300 ++#define IER (INTERRUPT_CONTROL + 0x8) ++#define FALC_INT (1<<3) ++ ++struct t13x { ++ spinlock_t reglock; ++ ++ u8 latency; ++ ++ const struct t13x_desc *devtype; ++ struct { ++ unsigned int nmf:1; ++ unsigned int sendingyellow:1; ++ } flags; ++ unsigned char txsigs[16]; /* Copy of tx sig registers */ ++ unsigned long lofalarmtimer; ++ unsigned long losalarmtimer; ++ unsigned long aisalarmtimer; ++ unsigned long yelalarmtimer; ++ unsigned long recoverytimer; ++ unsigned long blinktimer; ++ unsigned long loopuptimer; ++ unsigned long loopdntimer; ++ const char *name; ++#define INITIALIZED 1 ++#define SHUTDOWN 2 ++#define READY 3 ++#define HAVE_OPEN_CHANNELS 4 ++ unsigned long bit_flags; ++ u32 ledstate; ++ struct dahdi_device *ddev; ++ struct dahdi_span span; /* Span */ ++ struct dahdi_chan *chans[32]; /* Channels */ ++ struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */ ++ ++ /* protected by t1.reglock */ ++ struct timer_list timer; ++ struct work_struct timer_work; ++ struct workqueue_struct *wq; ++ struct vpm450m *vpm; ++ struct mutex lock; ++ struct wcxb xb; ++ u32 lineconfig_fingerprint; ++}; ++ ++static void te13x_handle_transmit(struct wcxb *xb, void *vfp); ++static void te13x_handle_receive(struct wcxb *xb, void *vfp); ++static void te13x_handle_interrupt(struct wcxb *xb, u32 pending); ++ ++static void te13x_handle_error(struct wcxb *xb) ++{ ++ struct t13x *wc = container_of(xb, struct t13x, xb); ++ wc->ddev->irqmisses++; ++} ++ ++static struct wcxb_operations xb_ops = { ++ .handle_receive = te13x_handle_receive, ++ .handle_transmit = te13x_handle_transmit, ++ .handle_interrupt = te13x_handle_interrupt, ++ .handle_error = te13x_handle_error, ++}; ++ ++/* Maintenance Mode Registers */ ++#define LIM0 0x36 ++#define LIM0_LL (1<<1) ++#define LIM1 0x37 ++#define LIM1_RL (1<<1) ++#define LIM1_JATT (1<<2) ++#define FMR3_T 0x21 /* T1 Framer 3 register */ ++#define FMR3_E 0x31 /* E1 Framer 3 register */ ++#define LOOPUP (1<<4) /* Transmit loopup code */ ++#define LOOPDOWN (1<<5) /* Transmit loopdown code */ ++ ++/* Clear Channel Registers */ ++#define CCB1 0x2f ++#define CCB2 0x30 ++#define CCB3 0x31 ++ ++#define FECL_T 0x50 /* Framing Error Counter Lower Byte */ ++#define FECH_T 0x51 /* Framing Error Counter Higher Byte */ ++#define CVCL_T 0x52 /* Code Violation Counter Lower Byte */ ++#define CVCH_T 0x53 /* Code Violation Counter Higher Byte */ ++#define CEC1L_T 0x54 /* CRC Error Counter 1 Lower Byte */ ++#define CEC1H_T 0x55 /* CRC Error Counter 1 Higher Byte */ ++#define EBCL_T 0x56 /* E-Bit Error Counter Lower Byte */ ++#define EBCH_T 0x57 /* E-Bit Error Counter Higher Byte */ ++#define BECL_T 0x58 /* Bit Error Counter Lower Byte */ ++#define BECH_T 0x59 /* Bit Error Counter Higher Byte */ ++#define COEC_T 0x5A /* COFA Event Counter */ ++#define PRBSSTA_T 0xDA /* PRBS Status Register */ ++#define FRS1_T 0x4D /* Framer Receive Status Reg 1 */ ++ ++#define ISR3_SEC (1 << 6) /* Internal one-second interrupt bit mask */ ++#define ISR3_ES (1 << 7) /* Errored Second interrupt bit mask */ ++#define IERR_T 0x1B /* Single Bit Defect Insertion Register */ ++#define IBV (1 << 0) /* Bipolar violation */ ++#define IPE (1 << 1) /* PRBS defect */ ++#define ICASE (1 << 2) /* CAS defect */ ++#define ICRCE (1 << 3) /* CRC defect */ ++#define IMFE (1 << 4) /* Multiframe defect */ ++#define IFASE (1 << 5) /* FAS defect */ ++ ++#define IMR0 0x14 ++#define CCR1 0x09 ++ ++/* pci memory map offsets */ ++#define FRAMER_BASE 0x00000800 /* framer's address space */ ++ ++static int debug; ++static int alarmdebounce = 2500; /* LOF/LFA def to 2.5s AT&T TR54016*/ ++static int losalarmdebounce = 2500; /* LOS def to 2.5s AT&T TR54016*/ ++static int aisalarmdebounce = 2500; /* AIS(blue) def to 2.5s AT&T TR54016*/ ++static int yelalarmdebounce = 500; /* RAI(yellow) def to 0.5s AT&T devguide */ ++static char *default_linemode = "t1"; /* 'e1', 't1', or 'j1' */ ++static int force_firmware; ++static int latency = WCXB_DEFAULT_LATENCY; ++static unsigned int max_latency = WCXB_DEFAULT_MAXLATENCY; ++ ++struct t13x_firm_header { ++ u8 header[6]; ++ __le32 chksum; ++ u8 pad[18]; ++ __le32 version; ++} __packed; ++ ++ ++static void t13x_check_alarms(struct t13x *wc); ++static void t13x_check_sigbits(struct t13x *wc); ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define ECHOCAN_NUM_CHANS 32 ++ ++#define FLAGBIT_DTMF 1 ++#define FLAGBIT_MUTE 2 ++#define FLAGBIT_ECHO 3 ++#define FLAGBIT_ALAW 4 ++ ++#define OCT_CHIP_ID 0 ++#define OCT_MAX_TDM_STREAMS 4 ++#define OCT_TONEEVENT_BUFFER_SIZE 128 ++#define SOUT_STREAM 1 ++#define RIN_STREAM 0 ++ ++#define SIN_STREAM 2 ++#define OCT_OFFSET (wc->xb.membase + 0x10000) ++#define OCT_CONTROL_REG (OCT_OFFSET + 0) ++#define OCT_DATA_REG (OCT_OFFSET + 0x4) ++#define OCT_ADDRESS_HIGH_REG (OCT_OFFSET + 0x8) ++#define OCT_ADDRESS_LOW_REG (OCT_OFFSET + 0xa) ++#define OCT_DIRECT_WRITE_MASK 0x3001 ++#define OCT_INDIRECT_READ_MASK 0x0101 ++#define OCT_INDIRECT_WRITE_MASK 0x3101 ++ ++ ++static int vpmsupport = 1; ++static const char *vpm_name = "VPMOCT032"; ++static void t13x_vpm_init(struct t13x *wc); ++static void echocan_free(struct dahdi_chan *chan, ++ struct dahdi_echocan_state *ec); ++static const struct dahdi_echocan_features vpm_ec_features = { ++ .NLP_automatic = 1, ++ .CED_tx_detect = 1, ++ .CED_rx_detect = 1, ++}; ++static const struct dahdi_echocan_ops vpm_ec_ops = { ++ .echocan_free = echocan_free, ++}; ++ ++struct vpm450m { ++ tPOCT6100_INSTANCE_API pApiInstance; ++ struct oct612x_context context; ++ UINT32 aulEchoChanHndl[ECHOCAN_NUM_CHANS]; ++ int ecmode[ECHOCAN_NUM_CHANS]; ++ unsigned long chanflags[ECHOCAN_NUM_CHANS]; ++}; ++ ++static void oct_reset(struct t13x *wc) ++{ ++ wcxb_gpio_clear(&wc->xb, OCT_CPU_RESET); ++ msleep_interruptible(1); ++ wcxb_gpio_set(&wc->xb, OCT_CPU_RESET); ++ ++ dev_info(&wc->xb.pdev->dev, "Reset octasic\n"); ++} ++ ++static void oct_enable_dram(struct t13x *wc) ++{ ++ wcxb_gpio_set(&wc->xb, OCT_CPU_DRAM_CKE); ++} ++ ++static unsigned int oct_get_reg_indirect(void *data, uint32_t address) ++{ ++ struct t13x *wc = data; ++ uint16_t highaddress = ((address >> 20) & 0xfff); ++ uint16_t lowaddress = ((address >> 4) & 0xfffff); ++ unsigned long stop = jiffies + HZ/10; ++ unsigned long flags; ++ uint16_t ret; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ iowrite16be(highaddress, OCT_ADDRESS_HIGH_REG); ++ iowrite16be(lowaddress, OCT_ADDRESS_LOW_REG); ++ ++ iowrite16be(OCT_INDIRECT_READ_MASK | ((address & 0xe) << 8), ++ OCT_CONTROL_REG); ++ do { ++ ret = ioread16be(OCT_CONTROL_REG); ++ } while ((ret & (1<<8)) && time_before(jiffies, stop)); ++ ++ WARN_ON_ONCE(time_after_eq(jiffies, stop)); ++ ++ ret = ioread16be(OCT_DATA_REG); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return ret; ++} ++ ++static void oct_set_reg_indirect(void *data, uint32_t address, uint16_t val) ++{ ++ struct t13x *wc = data; ++ unsigned long flags; ++ uint16_t ret; ++ uint16_t highaddress = ((address >> 20) & 0xfff); ++ uint16_t lowaddress = ((address >> 4) & 0xffff); ++ unsigned long stop = jiffies + HZ/10; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ iowrite16be(highaddress, OCT_ADDRESS_HIGH_REG); ++ iowrite16be(lowaddress, OCT_ADDRESS_LOW_REG); ++ ++ iowrite16be(val, OCT_DATA_REG); ++ iowrite16be(OCT_INDIRECT_WRITE_MASK | ((address & 0xe) << 8), ++ OCT_CONTROL_REG); ++ ++ /* No write should take longer than 100ms */ ++ do { ++ ret = ioread16be(OCT_CONTROL_REG); ++ } while ((ret & (1<<8)) && time_before(jiffies, stop)); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ WARN_ON_ONCE(time_after_eq(jiffies, stop)); ++} ++ ++static int t13x_oct612x_write(struct oct612x_context *context, ++ u32 address, u16 value) ++{ ++ oct_set_reg_indirect(dev_get_drvdata(context->dev), address, value); ++ return 0; ++} ++ ++static int t13x_oct612x_read(struct oct612x_context *context, u32 address, ++ u16 *value) ++{ ++ *value = oct_get_reg_indirect(dev_get_drvdata(context->dev), address); ++ return 0; ++} ++ ++static int t13x_oct612x_write_smear(struct oct612x_context *context, ++ u32 address, u16 value, size_t count) ++{ ++ unsigned int i; ++ struct t13x *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ oct_set_reg_indirect(wc, address + (i << 1), value); ++ return 0; ++} ++ ++static int t13x_oct612x_write_burst(struct oct612x_context *context, ++ u32 address, const u16 *buffer, ++ size_t count) ++{ ++ unsigned int i; ++ struct t13x *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ oct_set_reg_indirect(wc, address + (i << 1), buffer[i]); ++ return 0; ++} ++ ++static int t13x_oct612x_read_burst(struct oct612x_context *context, ++ u32 address, u16 *buffer, size_t count) ++{ ++ unsigned int i; ++ struct t13x *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ buffer[i] = oct_get_reg_indirect(wc, address + (i << 1)); ++ return 0; ++} ++ ++static const struct oct612x_ops t13x_oct612x_ops = { ++ .write = t13x_oct612x_write, ++ .read = t13x_oct612x_read, ++ .write_smear = t13x_oct612x_write_smear, ++ .write_burst = t13x_oct612x_write_burst, ++ .read_burst = t13x_oct612x_read_burst, ++}; ++ ++static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ ++ if (vpm450m->ecmode[channel] == mode) ++ return; ++ modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); ++ if (!modify) { ++ pr_notice("Unable to allocate memory for setec!\n"); ++ return; ++ } ++ Oct6100ChannelModifyDef(modify); ++ modify->ulEchoOperationMode = mode; ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n", ++ vpm450m->aulEchoChanHndl[channel], channel, ulResult); ++ } else { ++#ifdef OCTASIC_DEBUG ++ pr_debug("Echo can on channel %d set to %d\n", channel, mode); ++#endif ++ vpm450m->ecmode[channel] = mode; ++ } ++ kfree(modify); ++} ++ ++static void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel, ++ bool alaw) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ UINT32 law_to_use = (alaw) ? cOCT6100_PCM_A_LAW : ++ cOCT6100_PCM_U_LAW; ++ ++ /* If we're already in this companding mode, no need to do anything. */ ++ if (alaw == (test_bit(FLAGBIT_ALAW, &vpm450m->chanflags[channel]) > 0)) ++ return; ++ ++ modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); ++ if (!modify) { ++ pr_notice("Unable to allocate memory for setec!\n"); ++ return; ++ } ++ ++ Oct6100ChannelModifyDef(modify); ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ modify->fTdmConfigModified = TRUE; ++ modify->TdmConfig.ulSinPcmLaw = law_to_use; ++ modify->TdmConfig.ulRinPcmLaw = law_to_use; ++ modify->TdmConfig.ulSoutPcmLaw = law_to_use; ++ modify->TdmConfig.ulRoutPcmLaw = law_to_use; ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n", ++ vpm450m->aulEchoChanHndl[channel], channel, ulResult); ++ } else { ++ pr_info("Changed companding on channel %d to %s.\n", channel, ++ (alaw) ? "alaw" : "ulaw"); ++ if (alaw) ++ set_bit(FLAGBIT_ALAW, &vpm450m->chanflags[channel]); ++ else ++ clear_bit(FLAGBIT_ALAW, &vpm450m->chanflags[channel]); ++ } ++ kfree(modify); ++} ++ ++static void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen) ++{ ++ if (eclen) { ++ set_bit(FLAGBIT_ECHO, &vpm450m->chanflags[channel]); ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_NORMAL); ++ } else { ++ unsigned long *flags = &vpm450m->chanflags[channel]; ++ clear_bit(FLAGBIT_ECHO, &vpm450m->chanflags[channel]); ++ if (test_bit(FLAGBIT_DTMF, flags) || ++ test_bit(FLAGBIT_MUTE, flags)) { ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_HT_RESET); ++ } else { ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_POWER_DOWN); ++ } ++ } ++} ++ ++static UINT32 tdmmode_chan_to_slot_map(int channel) ++{ ++ /* Four phases on the tdm bus, skip three of them per channel */ ++ /* Due to a bug in the octasic, we had to move the data onto phase 2 */ ++ return 1+(channel*4); ++} ++ ++static int echocan_initialize_channel( ++ struct vpm450m *vpm, int channel, int mode) ++{ ++ tOCT6100_CHANNEL_OPEN ChannelOpen; ++ UINT32 law_to_use = (mode) ? cOCT6100_PCM_A_LAW : ++ cOCT6100_PCM_U_LAW; ++ UINT32 tdmslot_setting; ++ UINT32 ulResult; ++ ++ if (0 > channel || ECHOCAN_NUM_CHANS <= channel) ++ return -1; ++ ++ tdmslot_setting = tdmmode_chan_to_slot_map(channel); ++ ++ /* Fill Open channel structure with defaults */ ++ Oct6100ChannelOpenDef(&ChannelOpen); ++ ++ /* Assign the handle memory.*/ ++ ChannelOpen.pulChannelHndl = &vpm->aulEchoChanHndl[channel]; ++ ChannelOpen.ulUserChanId = channel; ++ /* Enable Tone disabling for Fax and Modems */ ++ ChannelOpen.fEnableToneDisabler = TRUE; ++ ++ /* Passthrough TDM data by default, no echocan */ ++ ChannelOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; ++ ++ /* Configure the TDM settings.*/ ++ /* Input from the framer */ ++ ChannelOpen.TdmConfig.ulSinStream = SIN_STREAM; ++ ChannelOpen.TdmConfig.ulSinTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulSinPcmLaw = law_to_use; ++ ++ /* Input from the Host (pre-framer) */ ++ ChannelOpen.TdmConfig.ulRinStream = RIN_STREAM; ++ ChannelOpen.TdmConfig.ulRinTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulRinPcmLaw = law_to_use; ++ ++ /* Output to the Host */ ++ ChannelOpen.TdmConfig.ulSoutStream = SOUT_STREAM; ++ ChannelOpen.TdmConfig.ulSoutTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulSoutPcmLaw = law_to_use; ++ ++ /* From asterisk after echo-cancellation - goes nowhere */ ++ ChannelOpen.TdmConfig.ulRoutStream = cOCT6100_UNASSIGNED; ++ ChannelOpen.TdmConfig.ulRoutTimeslot = cOCT6100_UNASSIGNED; ++ ChannelOpen.TdmConfig.ulRoutPcmLaw = law_to_use; ++ ++ /* Set the desired VQE features.*/ ++ ChannelOpen.VqeConfig.fEnableNlp = TRUE; ++ ChannelOpen.VqeConfig.fRinDcOffsetRemoval = TRUE; ++ ChannelOpen.VqeConfig.fSinDcOffsetRemoval = TRUE; ++ ChannelOpen.VqeConfig.ulComfortNoiseMode = ++ cOCT6100_COMFORT_NOISE_NORMAL; ++ ++ /* Open the channel.*/ ++ ulResult = Oct6100ChannelOpen(vpm->pApiInstance, &ChannelOpen); ++ ++ return ulResult; ++} ++ ++static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw, ++ const struct firmware *firmware) ++{ ++ tOCT6100_CHIP_OPEN *ChipOpen; ++ tOCT6100_GET_INSTANCE_SIZE InstanceSize; ++ tOCT6100_CHANNEL_OPEN *ChannelOpen; ++ UINT32 ulResult; ++ struct vpm450m *vpm450m; ++ int x, i; ++ ++ vpm450m = kzalloc(sizeof(struct vpm450m), GFP_KERNEL); ++ if (!vpm450m) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate vpm450m struct\n"); ++ return NULL; ++ } ++ ++ vpm450m->context.dev = &wc->xb.pdev->dev; ++ vpm450m->context.ops = &t13x_oct612x_ops; ++ ++ ChipOpen = kzalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL); ++ if (!ChipOpen) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate ChipOpen\n"); ++ kfree(vpm450m); ++ return NULL; ++ } ++ ++ ChannelOpen = kzalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL); ++ if (!ChannelOpen) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate ChannelOpen\n"); ++ kfree(vpm450m); ++ kfree(ChipOpen); ++ return NULL; ++ } ++ ++ for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++) ++ vpm450m->ecmode[x] = -1; ++ ++ dev_info(&wc->xb.pdev->dev, "Echo cancellation for %d channels\n", ++ ECHOCAN_NUM_CHANS); ++ ++ Oct6100ChipOpenDef(ChipOpen); ++ ChipOpen->pProcessContext = &vpm450m->context; ++ ++ /* Change default parameters as needed */ ++ /* upclk oscillator is at 33.33 Mhz */ ++ ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; ++ ++ /* mclk will be generated by internal PLL at 133 Mhz */ ++ ChipOpen->fEnableMemClkOut = TRUE; ++ ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; ++ ++ /* User defined Chip ID.*/ ++ ChipOpen->ulUserChipId = OCT_CHIP_ID; ++ ++ /* Set the maximums that the chip needs to support */ ++ ChipOpen->ulMaxChannels = ECHOCAN_NUM_CHANS; ++ ChipOpen->ulMaxTdmStreams = OCT_MAX_TDM_STREAMS; ++ ++ /* External Memory Settings */ ++ /* Use DDR memory.*/ ++ ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; ++ ChipOpen->ulNumMemoryChips = 1; ++ ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; ++ ++ ChipOpen->pbyImageFile = (PUINT8) firmware->data; ++ ChipOpen->ulImageSize = firmware->size; ++ ++ /* Set TDM data stream frequency */ ++ for (i = 0; i < ChipOpen->ulMaxTdmStreams; i++) ++ ChipOpen->aulTdmStreamFreqs[i] = cOCT6100_TDM_STREAM_FREQ_8MHZ; ++ ++ /* Configure TDM sampling */ ++ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; ++ /* Disable to save RAM footprint space */ ++ ChipOpen->fEnableChannelRecording = FALSE; ++ ++ /* In this example we will maintain the API using polling so ++ interrupts must be disabled */ ++ ChipOpen->InterruptConfig.ulErrorH100Config = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulErrorMemoryConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulFatalGeneralConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulFatalMemoryConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ++ ChipOpen->ulSoftToneEventsBufSize = OCT_TONEEVENT_BUFFER_SIZE; ++ ++ /* Inserting default values into tOCT6100_GET_INSTANCE_SIZE ++ structure parameters. */ ++ Oct6100GetInstanceSizeDef(&InstanceSize); ++ ++ /* Reset octasic device */ ++ oct_reset(wc); ++ ++ /* Get the size of the OCT6100 instance structure. */ ++ ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize); ++ if (ulResult != cOCT6100_ERR_OK) { ++ dev_info(&wc->xb.pdev->dev, "Unable to get instance size: %x\n", ++ ulResult); ++ return NULL; ++ } ++ ++ vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); ++ if (!vpm450m->pApiInstance) { ++ dev_info(&wc->xb.pdev->dev, ++ "Out of memory (can't allocate %d bytes)!\n", ++ InstanceSize.ulApiInstanceSize); ++ return NULL; ++ } ++ ++ /* Perform the actual configuration of the chip. */ ++ oct_enable_dram(wc); ++ ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen); ++ if (ulResult != cOCT6100_ERR_OK) { ++ dev_info(&wc->xb.pdev->dev, "Unable to Oct6100ChipOpen: %x\n", ++ ulResult); ++ return NULL; ++ } ++ ++ /* OCT6100 is now booted and channels can be opened */ ++ /* Open all channels */ ++ for (i = 0; i < ECHOCAN_NUM_CHANS; i++) { ++ ulResult = echocan_initialize_channel(vpm450m, i, isalaw); ++ if (0 != ulResult) { ++ dev_info(&wc->xb.pdev->dev, ++ "Unable to echocan_initialize_channel: %x\n", ++ ulResult); ++ return NULL; ++ } else if (isalaw) { ++ set_bit(FLAGBIT_ALAW, &vpm450m->chanflags[i]); ++ } ++ } ++ ++ if (vpmsupport) ++ wcxb_enable_echocan(&wc->xb); ++ ++ kfree(ChipOpen); ++ kfree(ChannelOpen); ++ return vpm450m; ++} ++ ++static void release_vpm450m(struct vpm450m *vpm450m) ++{ ++ UINT32 ulResult; ++ tOCT6100_CHIP_CLOSE ChipClose; ++ ++ Oct6100ChipCloseDef(&ChipClose); ++ ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose); ++ if (ulResult != cOCT6100_ERR_OK) ++ pr_notice("Failed to close chip, code %08x!\n", ulResult); ++ vfree(vpm450m->pApiInstance); ++ kfree(vpm450m); ++} ++ ++static const char *__t13x_echocan_name(struct t13x *wc) ++{ ++ if (wc->vpm) ++ return vpm_name; ++ else ++ return NULL; ++} ++ ++static const char *t13x_echocan_name(const struct dahdi_chan *chan) ++{ ++ struct t13x *wc = chan->pvt; ++ return __t13x_echocan_name(wc); ++} ++ ++static int t13x_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ struct t13x *wc = chan->pvt; ++ const int channel = chan->chanpos - 1; ++ const struct dahdi_echocan_ops *ops; ++ const struct dahdi_echocan_features *features; ++ const bool alaw = (chan->span->deflaw == 2); ++ ++ if (!vpmsupport || !wc->vpm) ++ return -ENODEV; ++ ++ ops = &vpm_ec_ops; ++ features = &vpm_ec_features; ++ ++ if (ecp->param_count > 0) { ++ dev_warn(&wc->xb.pdev->dev, "%s echo canceller does not support parameters; failing request\n", ++ chan->ec_factory->get_name(chan)); ++ return -EINVAL; ++ } ++ ++ *ec = wc->ec[channel]; ++ (*ec)->ops = ops; ++ (*ec)->features = *features; ++ ++ vpm450m_set_alaw_companding(wc->vpm, channel, alaw); ++ vpm450m_setec(wc->vpm, channel, ecp->tap_length); ++ return 0; ++} ++ ++static void echocan_free(struct dahdi_chan *chan, ++ struct dahdi_echocan_state *ec) ++{ ++ struct t13x *wc = chan->pvt; ++ const int channel = chan->chanpos - 1; ++ if (!wc->vpm) ++ return; ++ memset(ec, 0, sizeof(*ec)); ++ vpm450m_setec(wc->vpm, channel, 0); ++} ++ ++static void t13x_vpm_init(struct t13x *wc) ++{ ++ int companding = 0; ++ struct firmware embedded_firmware; ++ const struct firmware *firmware = &embedded_firmware; ++#if !defined(HOTPLUG_FIRMWARE) ++ extern void _binary_dahdi_fw_oct6114_032_bin_size; ++ extern u8 _binary_dahdi_fw_oct6114_032_bin_start[]; ++#else ++ static const char oct032_firmware[] = "dahdi-fw-oct6114-032.bin"; ++#endif ++ ++ if (!vpmsupport) { ++ dev_info(&wc->xb.pdev->dev, "VPM450: Support Disabled\n"); ++ return; ++ } ++ ++#if defined(HOTPLUG_FIRMWARE) ++ if ((request_firmware(&firmware, oct032_firmware, ++ &wc->xb.pdev->dev) != 0) || !firmware) { ++ dev_notice(&wc->xb.pdev->dev, "VPM450: firmware %s not available from userspace\n", ++ oct032_firmware); ++ return; ++ } ++#else ++ embedded_firmware.data = _binary_dahdi_fw_oct6114_032_bin_start; ++ /* Yes... this is weird. objcopy gives us a symbol containing ++ the size of the firmware, not a pointer a variable containing ++ the size. The only way we can get the value of the symbol ++ is to take its address, so we define it as a pointer and ++ then cast that value to the proper type. ++ */ ++ embedded_firmware.size = (size_t)&_binary_dahdi_fw_oct6114_032_bin_size; ++#endif ++ ++ companding = dahdi_is_e1_span(&wc->span); ++ ++ wc->vpm = init_vpm450m(wc, companding, firmware); ++ if (!wc->vpm) { ++ dev_notice(&wc->xb.pdev->dev, "VPM450: Failed to initialize\n"); ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ return; ++ } ++ ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ ++ dev_info(&wc->xb.pdev->dev, ++ "VPM450: Present and operational servicing %d span\n", 1); ++ ++} ++ ++static int t13x_clear_maint(struct dahdi_span *span); ++ ++static struct t13x *ifaces[WC_MAX_IFACES]; ++ ++struct t13x_desc { ++ const char *name; ++}; ++ ++static const struct t13x_desc te133 = {"Wildcard TE131/TE133"}; /* pci express*/ ++static const struct t13x_desc te134 = {"Wildcard TE132/TE134"}; /* legacy pci */ ++ ++static inline bool is_pcie(const struct t13x *t1) ++{ ++ return t1->devtype == &te133; ++} ++ ++static int __t13x_pci_get(struct t13x *wc, unsigned int addr) ++{ ++ unsigned int res = ioread8(wc->xb.membase + addr); ++ return res; ++} ++ ++static inline int __t13x_pci_set(struct t13x *wc, unsigned int addr, int val) ++{ ++ iowrite8(val, wc->xb.membase + addr); ++ __t13x_pci_get(wc, 0); ++ return 0; ++} ++ ++static inline int t13x_pci_get(struct t13x *wc, int addr) ++{ ++ unsigned int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ret = __t13x_pci_get(wc, addr); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return ret; ++} ++ ++static inline int t13x_pci_set(struct t13x *wc, int addr, int val) ++{ ++ unsigned long flags; ++ unsigned int ret; ++ spin_lock_irqsave(&wc->reglock, flags); ++ ret = __t13x_pci_set(wc, addr, val); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return ret; ++} ++ ++static inline int __t13x_framer_set(struct t13x *wc, int addr, int val) ++{ ++ return __t13x_pci_set(wc, FRAMER_BASE + addr, val); ++} ++ ++static inline int t13x_framer_set(struct t13x *wc, int addr, int val) ++{ ++ return t13x_pci_set(wc, FRAMER_BASE + addr, val); ++} ++ ++static inline int __t13x_framer_get(struct t13x *wc, int addr) ++{ ++ return __t13x_pci_get(wc, FRAMER_BASE + addr); ++} ++ ++static inline int t13x_framer_get(struct t13x *wc, int addr) ++{ ++ return t13x_pci_get(wc, FRAMER_BASE + addr); ++} ++ ++static void t13x_framer_reset(struct t13x *wc) ++{ ++ /* ++ * When the framer is reset, RCLK will stop. The FPGA must be switched ++ * to it's internal clock when this happens, but it's only safe to ++ * switch the clock source on the FPGA when the DMA engine is stopped. ++ * ++ */ ++ wcxb_stop_dma(&wc->xb); ++ wcxb_wait_for_stop(&wc->xb, 50); ++ wcxb_set_clksrc(&wc->xb, WCXB_CLOCK_SELF); ++ wcxb_gpio_clear(&wc->xb, FALC_CPU_RESET); ++ msleep_interruptible(100); ++ wcxb_gpio_set(&wc->xb, FALC_CPU_RESET); ++} ++ ++static void t13x_setleds(struct t13x *wc, u32 leds) ++{ ++ static const u32 LED_MASK = 0x600; ++ wcxb_gpio_set(&wc->xb, leds & LED_MASK); ++ wcxb_gpio_clear(&wc->xb, ~leds & LED_MASK); ++} ++ ++static void __t13x_set_clear(struct t13x *wc) ++{ ++ int i, offset; ++ int reg; ++ unsigned long flags; ++ bool span_has_cas_channel = false; ++ ++ if (dahdi_is_e1_span(&wc->span)) { ++ span_has_cas_channel = !(wc->span.lineconfig&DAHDI_CONFIG_CCS); ++ } else { ++ unsigned char ccb[3] = {0, 0, 0}; ++ /* Sort out channels that use CAS signalling */ ++ for (i = 0; i < wc->span.channels; i++) { ++ offset = i/8; ++ if (offset >= ARRAY_SIZE(ccb)) { ++ WARN_ON(1); ++ break; ++ } ++ if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR) ++ ccb[offset] |= 1 << (7 - (i % 8)); ++ else ++ ccb[offset] &= ~(1 << (7 - (i % 8))); ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t13x_framer_set(wc, CCB1, ccb[0]); ++ __t13x_framer_set(wc, CCB2, ccb[1]); ++ __t13x_framer_set(wc, CCB3, ccb[2]); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if ((~ccb[0]) | (~ccb[1]) | (~ccb[2])) ++ span_has_cas_channel = true; ++ } ++ ++ /* Unmask CAS RX interrupt if any single channel is in CAS mode */ ++ /* This interrupt is called RSC in T1 and CASC in E1 */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, IMR0); ++ if (span_has_cas_channel) ++ __t13x_framer_set(wc, IMR0, reg & ~0x08); ++ else ++ __t13x_framer_set(wc, IMR0, reg | 0x08); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++/** ++ * _t13x_free_channels - Free the memory allocated for the channels. ++ * ++ * Must be called with wc->reglock held. ++ * ++ */ ++static void _t13x_free_channels(struct t13x *wc) ++{ ++ int x; ++ for (x = 0; x < ARRAY_SIZE(wc->chans); x++) { ++ kfree(wc->chans[x]); ++ kfree(wc->ec[x]); ++ wc->chans[x] = NULL; ++ wc->ec[x] = NULL; ++ } ++} ++ ++static void free_wc(struct t13x *wc) ++{ ++ unsigned long flags; ++ LIST_HEAD(list); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ _t13x_free_channels(wc); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (wc->wq) ++ destroy_workqueue(wc->wq); ++ ++ kfree(wc->ddev->location); ++ kfree(wc->ddev->devicetype); ++ kfree(wc->ddev->hardware_id); ++ if (wc->ddev) ++ dahdi_free_device(wc->ddev); ++ kfree(wc->name); ++ kfree(wc); ++} ++ ++static void t13x_serial_setup(struct t13x *wc) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t13x_framer_set(wc, 0x85, 0xe0); /* GPC1: Multiplex mode ++ enabled, FSC is output, ++ active low, RCLK from ++ channel 0 */ ++ __t13x_framer_set(wc, 0x08, 0x05); /* IPC: Interrupt push/pull ++ active low */ ++ ++ /* Global clocks (8.192 Mhz CLK) */ ++ __t13x_framer_set(wc, 0x92, 0x00); ++ __t13x_framer_set(wc, 0x93, 0x18); ++ __t13x_framer_set(wc, 0x94, 0xfb); ++ __t13x_framer_set(wc, 0x95, 0x0b); ++ __t13x_framer_set(wc, 0x96, 0x00); ++ __t13x_framer_set(wc, 0x97, 0x0b); ++ __t13x_framer_set(wc, 0x98, 0xdb); ++ __t13x_framer_set(wc, 0x99, 0xdf); ++ ++ /* Configure interrupts */ ++ __t13x_framer_set(wc, 0x46, 0xc0); /* GCR: Interrupt on ++ Activation/Deactivation of ++ AIX, LOS */ ++ ++ /* Configure system interface */ ++ __t13x_framer_set(wc, 0x3e, 0xc2); /* SIC1: 8.192 Mhz clock/bus, ++ double buffer receive / ++ transmit, byte interleaved ++ */ ++ __t13x_framer_set(wc, 0x3f, 0x02); /* SIC2: No FFS, no center ++ receive eliastic buffer, ++ phase 1 */ ++ __t13x_framer_set(wc, 0x40, 0x04); /* SIC3: Edges for capture */ ++ __t13x_framer_set(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz ++ dejittered */ ++ __t13x_framer_set(wc, 0x45, 0x00); /* CMR2: We provide sync and ++ clock for tx and rx. */ ++ __t13x_framer_set(wc, 0x22, 0x00); /* XC0: Normal operation of ++ Sa-bits */ ++ __t13x_framer_set(wc, 0x23, 0x02); /* XC1: 0 offset */ ++ __t13x_framer_set(wc, 0x24, 0x00); /* RC0: Just shy of 255 */ ++ __t13x_framer_set(wc, 0x25, 0x03); /* RC1: The rest of RC0 */ ++ ++ /* Configure ports */ ++ __t13x_framer_set(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on ++ RPA/XPA */ ++ __t13x_framer_set(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input ++ on RPB/XPB */ ++ __t13x_framer_set(wc, 0x82, 0x65); /* PC3: Unused stuff */ ++ __t13x_framer_set(wc, 0x83, 0x35); /* PC4: Unused stuff */ ++ __t13x_framer_set(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR ++ is input, RCLK is output */ ++ __t13x_framer_set(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock ++ output, CLK2 is 8.192 Mhz ++ from DCO-R */ ++ __t13x_framer_set(wc, 0x3b, 0x00); /* Clear LCR1 */ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static void t13x_configure_t1(struct t13x *wc, int lineconfig, int txlevel) ++{ ++ unsigned int fmr4, fmr2, fmr1, fmr0, lim2; ++ char *framing, *line; ++ int mytxlevel; ++ unsigned long flags; ++ ++ if ((txlevel > 7) || (txlevel < 4)) ++ mytxlevel = 0; ++ else ++ mytxlevel = txlevel - 4; ++ fmr1 = 0x9c; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system ++ data rate, no XAIS */ ++ fmr2 = 0x20; /* FMR2: no payload loopback, don't auto yellow alarm */ ++ ++ ++ if (SPANTYPE_DIGITAL_J1 == wc->span.spantype) ++ fmr4 = 0x1c; ++ else ++ fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, ++ auto resync */ ++ ++ lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ ++ lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ __t13x_framer_set(wc, 0x1d, fmr1); ++ __t13x_framer_set(wc, 0x1e, fmr2); ++ ++ /* Configure line interface */ ++ if (lineconfig & DAHDI_CONFIG_AMI) { ++ line = "AMI"; ++ fmr0 = 0xa0; ++ } else { ++ line = "B8ZS"; ++ fmr0 = 0xf0; ++ } ++ if (lineconfig & DAHDI_CONFIG_D4) { ++ framing = "D4"; ++ } else { ++ framing = "ESF"; ++ fmr4 |= 0x2; ++ fmr2 |= 0xc0; ++ } ++ __t13x_framer_set(wc, 0x1c, fmr0); ++ ++ __t13x_framer_set(wc, 0x20, fmr4); ++ __t13x_framer_set(wc, FMR3_T, 0x40); /* FMR5: Enable RBS mode */ ++ ++ __t13x_framer_set(wc, 0x37, 0xf8); /* LIM1: Clear data in case of ++ LOS, Set receiver threshold ++ (0.5V), No remote loop, no ++ DRS */ ++ __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Enable auto long haul ++ mode, no local loop (must be ++ after LIM1) */ ++ ++ __t13x_framer_set(wc, 0x02, 0x50); /* CMDR: Reset the receiver and ++ transmitter line interface ++ */ ++ __t13x_framer_set(wc, 0x02, 0x00); /* CMDR: Reset the receiver and ++ transmitter line interface ++ */ ++ ++ __t13x_framer_set(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is ++ a "1" */ ++ __t13x_framer_set(wc, 0x38, 0x0a); /* PCD: LOS after 176 ++ consecutive "zeros" */ ++ __t13x_framer_set(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ ++ ++ if (SPANTYPE_DIGITAL_J1 == wc->span.spantype) ++ __t13x_framer_set(wc, 0x24, 0x80); /* J1 overide */ ++ ++ /* Generate pulse mask for T1 */ ++ switch (mytxlevel) { ++ case 3: ++ __t13x_framer_set(wc, 0x26, 0x07); /* XPM0 */ ++ __t13x_framer_set(wc, 0x27, 0x01); /* XPM1 */ ++ __t13x_framer_set(wc, 0x28, 0x00); /* XPM2 */ ++ break; ++ case 2: ++ __t13x_framer_set(wc, 0x26, 0x8c); /* XPM0 */ ++ __t13x_framer_set(wc, 0x27, 0x11); /* XPM1 */ ++ __t13x_framer_set(wc, 0x28, 0x01); /* XPM2 */ ++ break; ++ case 1: ++ __t13x_framer_set(wc, 0x26, 0x8c); /* XPM0 */ ++ __t13x_framer_set(wc, 0x27, 0x01); /* XPM1 */ ++ __t13x_framer_set(wc, 0x28, 0x00); /* XPM2 */ ++ break; ++ case 0: ++ default: ++ __t13x_framer_set(wc, 0x26, 0x1a); /* XPM0 */ ++ __t13x_framer_set(wc, 0x27, 0x1f); /* XPM1 */ ++ __t13x_framer_set(wc, 0x28, 0x01); /* XPM2 */ ++ break; ++ } ++ ++ __t13x_framer_set(wc, 0x14, 0xff); /* IMR0 */ ++ __t13x_framer_set(wc, 0x15, 0xff); /* IMR1 */ ++ ++ __t13x_framer_set(wc, 0x16, 0x00); /* IMR2: All the alarms */ ++ __t13x_framer_set(wc, 0x17, 0x34); /* IMR3: ++ ES, SEC, LLBSC, rx slips */ ++ __t13x_framer_set(wc, 0x18, 0x3f); /* IMR4: Slips on transmit */ ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dev_info(&wc->xb.pdev->dev, "Span configured for %s/%s\n", framing, line); ++} ++ ++static void t13x_configure_e1(struct t13x *wc, int lineconfig) ++{ ++ unsigned int fmr2, fmr1, fmr0; ++ unsigned int cas = 0; ++ unsigned int imr3extra = 0; ++ char *crc4 = ""; ++ char *framing, *line; ++ unsigned long flags; ++ ++ fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, ++ 8.192 Mhz backplane, no XAIS */ ++ fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of ++ multiframe recovery, no payload loopback */ ++ ++ if (lineconfig & DAHDI_CONFIG_CRC4) { ++ fmr1 |= 0x08; /* CRC4 transmit */ ++ fmr2 |= 0xc0; /* CRC4 receive */ ++ crc4 = "/CRC4"; ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ __t13x_framer_set(wc, 0x1d, fmr1); ++ __t13x_framer_set(wc, 0x1e, fmr2); ++ ++ /* Configure line interface */ ++ if (lineconfig & DAHDI_CONFIG_AMI) { ++ line = "AMI"; ++ fmr0 = 0xa0; ++ } else { ++ line = "HDB3"; ++ fmr0 = 0xf0; ++ } ++ if (lineconfig & DAHDI_CONFIG_CCS) { ++ framing = "CCS"; ++ imr3extra = 0x28; ++ } else { ++ framing = "CAS"; ++ cas = 0x40; ++ } ++ __t13x_framer_set(wc, 0x1c, fmr0); ++ ++ __t13x_framer_set(wc, 0x37, 0xf0); /* LIM1: Clear data in case of ++ LOS, Set receiver threshold ++ (0.5V), No remote loop, no ++ DRS */ ++ __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Enable auto long haul ++ mode, no local loop (must be ++ after LIM1) */ ++ ++ __t13x_framer_set(wc, 0x02, 0x50); /* CMDR: Reset the receiver and ++ transmitter line interface ++ */ ++ __t13x_framer_set(wc, 0x02, 0x00); /* CMDR: Reset the receiver and ++ transmitter line interface ++ */ ++ ++ /* Condition receive line interface for E1 after reset */ ++ __t13x_framer_set(wc, 0xbb, 0x17); ++ __t13x_framer_set(wc, 0xbc, 0x55); ++ __t13x_framer_set(wc, 0xbb, 0x97); ++ __t13x_framer_set(wc, 0xbb, 0x11); ++ __t13x_framer_set(wc, 0xbc, 0xaa); ++ __t13x_framer_set(wc, 0xbb, 0x91); ++ __t13x_framer_set(wc, 0xbb, 0x12); ++ __t13x_framer_set(wc, 0xbc, 0x55); ++ __t13x_framer_set(wc, 0xbb, 0x92); ++ __t13x_framer_set(wc, 0xbb, 0x0c); ++ __t13x_framer_set(wc, 0xbb, 0x00); ++ __t13x_framer_set(wc, 0xbb, 0x8c); ++ ++ __t13x_framer_set(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is ++ a "1" */ ++ __t13x_framer_set(wc, 0x38, 0x0a); /* PCD: LOS after 176 ++ consecutive "zeros" */ ++ __t13x_framer_set(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ ++ ++ __t13x_framer_set(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ ++ __t13x_framer_set(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. ++ AXS auto, XSIF to 1 */ ++ ++ /* Generate pulse mask for E1 */ ++ __t13x_framer_set(wc, 0x26, 0x74); /* XPM0 */ ++ __t13x_framer_set(wc, 0x27, 0x02); /* XPM1 */ ++ __t13x_framer_set(wc, 0x28, 0x00); /* XPM2 */ ++ ++ __t13x_framer_set(wc, 0x14, 0xff); /* IMR0 */ ++ __t13x_framer_set(wc, 0x15, 0xff); /* IMR1 */ ++ ++ __t13x_framer_set(wc, 0x16, 0x00); /* IMR2: all the ++ alarm stuff! */ ++ __t13x_framer_set(wc, 0x17, 0x04 | imr3extra); /* IMR3: AIS */ ++ __t13x_framer_set(wc, 0x18, 0x3f); /* IMR4: slips on ++ transmit */ ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dev_info(&wc->xb.pdev->dev, ++ "Span configured for %s/%s%s\n", framing, line, crc4); ++} ++ ++static void t13x_framer_start(struct t13x *wc) ++{ ++ if (dahdi_is_e1_span(&wc->span)) { ++ t13x_configure_e1(wc, wc->span.lineconfig); ++ } else { /* is a T1 card */ ++ t13x_configure_t1(wc, wc->span.lineconfig, wc->span.txlevel); ++ } ++ __t13x_set_clear(wc); ++ ++ /* Give RCLK a short bit of time to settle */ ++ udelay(1); ++ set_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags); ++} ++ ++/** ++ * te13xp_check_for_interrupts - Return 0 if the card is generating interrupts. ++ * @wc: The card to check. ++ * ++ * If the card is not generating interrupts, this function will also place all ++ * the spans on the card into red alarm. ++ * ++ */ ++static int te13xp_check_for_interrupts(struct t13x *wc) ++{ ++ unsigned int starting_framecount = wc->xb.framecount; ++ unsigned long stop_time = jiffies + HZ*2; ++ unsigned long flags; ++ ++ msleep(20); ++ spin_lock_irqsave(&wc->reglock, flags); ++ while (starting_framecount == wc->xb.framecount) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ if (time_after(jiffies, stop_time)) { ++ wc->span.alarms = DAHDI_ALARM_RED; ++ dev_err(&wc->xb.pdev->dev, "Interrupts not detected.\n"); ++ return -EIO; ++ } ++ msleep(100); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return 0; ++} ++ ++static bool have_open_channels(const struct t13x *wc) ++{ ++ int x, j; ++ for (x = 0, j = 0; x < wc->span.channels; x++) { ++ const struct dahdi_chan *chan = wc->span.chans[x]; ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags) || ++ dahdi_have_netdev(chan)) ++ return true; ++ } ++ return false; ++} ++ ++static int t13x_startup(struct file *file, struct dahdi_span *span) ++{ ++ struct t13x *wc = container_of(span, struct t13x, span); ++ unsigned long flags; ++ int ret; ++ ++ /* Stop the DMA since the clock source may have changed. */ ++ wcxb_stop_dma(&wc->xb); ++ ret = wcxb_wait_for_stop(&wc->xb, 50); ++ if (ret) { ++ dev_err(&wc->xb.pdev->dev, "Timeout waiting for DMA to stop.\n"); ++ return ret; ++ } ++ ++ /* Reset framer with proper parameters and start */ ++ t13x_framer_start(wc); ++ ++ /* Reset span alarm state to RED to prevent false ++ * temporary GREEN state on span bringup */ ++ span->alarms |= DAHDI_ALARM_RED; ++ ++ /* Do we want to SYNC on receive or not. This must always happen after ++ * the framer is fully reset. */ ++ wcxb_set_clksrc(&wc->xb, ++ (span->syncsrc) ? WCXB_CLOCK_RECOVER : WCXB_CLOCK_SELF); ++ ++ wcxb_start(&wc->xb); ++ ret = te13xp_check_for_interrupts(wc); ++ if (ret) ++ return ret; ++ ++ dev_info(&wc->xb.pdev->dev, ++ "Calling startup (flags is %lu)\n", span->flags); ++ ++ /* Check for "open channels" here in case some channels have netdev. */ ++ if (have_open_channels(wc)) ++ clear_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags); ++ else ++ set_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags); ++ ++ /* Get this party started */ ++ local_irq_save(flags); ++ t13x_check_alarms(wc); ++ t13x_check_sigbits(wc); ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static int t13x_chanconfig(struct file *file, ++ struct dahdi_chan *chan, int sigtype) ++{ ++ struct t13x *wc = chan->pvt; ++ ++ if (file->f_flags & O_NONBLOCK) ++ return -EAGAIN; ++ ++ if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) && ++ dahdi_is_t1_span(&wc->span)) { ++ __t13x_set_clear(wc); ++ } ++ return 0; ++} ++ ++static int t13x_rbsbits(struct dahdi_chan *chan, int bits) ++{ ++ u_char m, c; ++ int n, b; ++ struct t13x *wc = chan->pvt; ++ unsigned long flags; ++ ++ if (dahdi_is_e1_span(&wc->span)) { /* do it E1 way */ ++ if (chan->chanpos == 16) ++ return 0; ++ ++ n = chan->chanpos - 1; ++ if (chan->chanpos > 15) ++ n--; ++ b = (n % 15); ++ spin_lock_irqsave(&wc->reglock, flags); ++ c = wc->txsigs[b]; ++ m = (n / 15) << 2; /* nibble selector */ ++ c &= (0xf << m); /* keep the other nibble */ ++ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ ++ wc->txsigs[b] = c; ++ /* output them to the chip */ ++ __t13x_framer_set(wc, 0x71 + b, c); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else if (wc->span.lineconfig & DAHDI_CONFIG_D4) { ++ n = chan->chanpos - 1; ++ b = (n / 4); ++ spin_lock_irqsave(&wc->reglock, flags); ++ c = wc->txsigs[b]; ++ m = ((3 - (n % 4)) << 1); /* nibble selector */ ++ c &= ~(0x3 << m); /* keep the other nibble */ ++ c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ ++ wc->txsigs[b] = c; ++ /* output them to the chip */ ++ __t13x_framer_set(wc, 0x70 + b, c); ++ __t13x_framer_set(wc, 0x70 + b + 6, c); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else if (wc->span.lineconfig & DAHDI_CONFIG_ESF) { ++ n = chan->chanpos - 1; ++ b = (n / 2); ++ spin_lock_irqsave(&wc->reglock, flags); ++ c = wc->txsigs[b]; ++ m = ((n % 2) << 2); /* nibble selector */ ++ c &= (0xf << m); /* keep the other nibble */ ++ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ ++ wc->txsigs[b] = c; ++ /* output them to the chip */ ++ __t13x_framer_set(wc, 0x70 + b, c); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++ ++ return 0; ++} ++ ++static void t13x_check_sigbits(struct t13x *wc) ++{ ++ int a, i, rxs; ++ ++ if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags))) ++ return; ++ if (dahdi_is_e1_span(&wc->span)) { ++ for (i = 0; i < 15; i++) { ++ a = t13x_framer_get(wc, 0x71 + i); ++ if (a > -1) { ++ /* Get high channel in low bits */ ++ rxs = (a & 0xf); ++ if (!(wc->span.chans[i+16]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i+16]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i+16], rxs); ++ ++ rxs = (a >> 4) & 0xf; ++ if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i], rxs); ++ } ++ } ++ } else if (wc->span.lineconfig & DAHDI_CONFIG_D4) { ++ for (i = 0; i < 24; i += 4) { ++ a = t13x_framer_get(wc, 0x70 + (i>>2)); ++ if (a > -1) { ++ /* Get high channel in low bits */ ++ rxs = (a & 0x3) << 2; ++ if (!(wc->span.chans[i+3]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i+3]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i+3], rxs); ++ ++ rxs = (a & 0xc); ++ if (!(wc->span.chans[i+2]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i+2]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i+2], rxs); ++ ++ rxs = (a >> 2) & 0xc; ++ if (!(wc->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i+1]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i+1], rxs); ++ ++ rxs = (a >> 4) & 0xc; ++ if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i], rxs); ++ } ++ } ++ } else { ++ for (i = 0; i < 24; i += 2) { ++ a = t13x_framer_get(wc, 0x70 + (i>>1)); ++ if (a > -1) { ++ /* Get high channel in low bits */ ++ rxs = (a & 0xf); ++ if (!(wc->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i+1]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i+1], rxs); ++ ++ rxs = (a >> 4) & 0xf; ++ if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) ++ if (wc->span.chans[i]->rxsig != rxs) ++ dahdi_rbsbits(wc->span.chans[i], rxs); ++ } ++ } ++ } ++} ++ ++static void t13x_reset_counters(struct dahdi_span *span) ++{ ++ memset(&span->count, 0, sizeof(span->count)); ++} ++ ++static int t13x_maint(struct dahdi_span *span, int cmd) ++{ ++ struct t13x *wc = container_of(span, struct t13x, span); ++ int reg = 0; ++ unsigned long flags; ++ ++ switch (cmd) { ++ case DAHDI_MAINT_NONE: ++ dev_info(&wc->xb.pdev->dev, "Clearing all maint modes\n"); ++ t13x_clear_maint(span); ++ break; ++ case DAHDI_MAINT_LOCALLOOP: ++ dev_info(&wc->xb.pdev->dev, "Turning on local loopback\n"); ++ t13x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, LIM0); ++ __t13x_framer_set(wc, LIM0, reg | LIM0_LL); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on network line loopback\n"); ++ t13x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, LIM1); ++ __t13x_framer_set(wc, LIM1, reg | LIM1_RL); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on network payload loopback\n"); ++ t13x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, LIM1); ++ __t13x_framer_set(wc, LIM1, reg | (LIM1_RL | LIM1_JATT)); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_LOOPUP: ++ dev_info(&wc->xb.pdev->dev, "Transmitting loopup code\n"); ++ t13x_clear_maint(span); ++ if (dahdi_is_e1_span(&wc->span)) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, FMR3_E); ++ __t13x_framer_set(wc, FMR3_E, reg | LOOPUP); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else { ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, FMR3_T); ++ __t13x_framer_set(wc, FMR3_T, reg | LOOPUP); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++ break; ++ case DAHDI_MAINT_LOOPDOWN: ++ dev_info(&wc->xb.pdev->dev, "Transmitting loopdown code\n"); ++ t13x_clear_maint(span); ++ if (dahdi_is_e1_span(&wc->span)) { ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, FMR3_E); ++ __t13x_framer_set(wc, FMR3_E, reg | LOOPDOWN); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else { ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, FMR3_T); ++ __t13x_framer_set(wc, FMR3_T, reg | LOOPDOWN); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++ break; ++ case DAHDI_MAINT_FAS_DEFECT: ++ t13x_framer_set(wc, IERR_T, IFASE); ++ break; ++ case DAHDI_MAINT_MULTI_DEFECT: ++ t13x_framer_set(wc, IERR_T, IMFE); ++ break; ++ case DAHDI_MAINT_CRC_DEFECT: ++ t13x_framer_set(wc, IERR_T, ICRCE); ++ break; ++ case DAHDI_MAINT_CAS_DEFECT: ++ t13x_framer_set(wc, IERR_T, ICASE); ++ break; ++ case DAHDI_MAINT_PRBS_DEFECT: ++ t13x_framer_set(wc, IERR_T, IPE); ++ break; ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ t13x_framer_set(wc, IERR_T, IBV); ++ break; ++ case DAHDI_RESET_COUNTERS: ++ t13x_reset_counters(span); ++ break; ++ default: ++ dev_info(&wc->xb.pdev->dev, ++ "Unknown maint command: %d\n", cmd); ++ return -ENOSYS; ++ } ++ ++ /* update DAHDI_ALARM_LOOPBACK status bit and check timing source */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (!span->maintstat) ++ span->alarms &= ~DAHDI_ALARM_LOOPBACK; ++ dahdi_alarm_notify(span); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return 0; ++} ++ ++static int t13x_clear_maint(struct dahdi_span *span) ++{ ++ struct t13x *wc = container_of(span, struct t13x, span); ++ int reg = 0; ++ unsigned long flags; ++ ++ /* Turn off local loop */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t13x_framer_get(wc, LIM0); ++ __t13x_framer_set(wc, LIM0, reg & ~LIM0_LL); ++ ++ /* Turn off remote loop & jitter attenuator */ ++ reg = __t13x_framer_get(wc, LIM1); ++ __t13x_framer_set(wc, LIM1, reg & ~(LIM1_RL | LIM1_JATT)); ++ ++ /* Clear loopup/loopdown signals on the line */ ++ if (dahdi_is_e1_span(&wc->span)) { ++ reg = __t13x_framer_get(wc, FMR3_E); ++ __t13x_framer_set(wc, FMR3_E, reg & ~(LOOPDOWN | LOOPUP)); ++ } else { ++ reg = __t13x_framer_get(wc, FMR3_T); ++ __t13x_framer_set(wc, FMR3_T, reg & ~(LOOPDOWN | LOOPUP)); ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return 0; ++} ++ ++ ++static int t13x_ioctl(struct dahdi_chan *chan, unsigned int cmd, ++ unsigned long data) ++{ ++ struct t4_regs regs; ++ unsigned int x; ++ struct t13x *wc; ++ ++ switch (cmd) { ++ case WCT4_GET_REGS: ++ wc = chan->pvt; ++ for (x = 0; x < sizeof(regs.regs) / sizeof(regs.regs[0]); x++) ++ regs.regs[x] = t13x_framer_get(wc, x); ++ ++ if (copy_to_user((void __user *) data, ®s, sizeof(regs))) ++ return -EFAULT; ++ break; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static void t13x_chan_set_sigcap(struct dahdi_span *span, int x) ++{ ++ struct t13x *wc = container_of(span, struct t13x, span); ++ struct dahdi_chan *chan = wc->chans[x]; ++ chan->sigcap = DAHDI_SIG_CLEAR; ++ /* E&M variant supported depends on span type */ ++ if (dahdi_is_e1_span(&wc->span)) { ++ /* E1 sigcap setup */ ++ if (span->lineconfig & DAHDI_CONFIG_CCS) { ++ /* CCS setup */ ++ chan->sigcap |= DAHDI_SIG_MTP2 | DAHDI_SIG_SF; ++ return; ++ } ++ /* clear out sig and sigcap for channel 16 on E1 CAS ++ * lines, otherwise, set it correctly */ ++ if (x == 15) { ++ /* CAS signaling channel setup */ ++ wc->chans[15]->sigcap = 0; ++ wc->chans[15]->sig = 0; ++ return; ++ } ++ /* normal CAS setup */ ++ chan->sigcap |= DAHDI_SIG_EM_E1 | DAHDI_SIG_FXSLS | ++ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_SF | ++ DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | ++ DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS; ++ } else { ++ /* T1 sigcap setup */ ++ chan->sigcap |= DAHDI_SIG_EM | DAHDI_SIG_FXSLS | ++ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_MTP2 | ++ DAHDI_SIG_SF | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | ++ DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS; ++ } ++} ++ ++static bool t13x_lineconfig_changed(struct t13x *wc, ++ const struct dahdi_lineconfig *lc) ++{ ++ unsigned long flags; ++ bool result; ++ u32 crc = crc32(~0, lc, sizeof(*lc)); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ result = (crc != wc->lineconfig_fingerprint); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return result; ++} ++ ++static void t13x_save_lineconfig(struct t13x *wc, ++ const struct dahdi_lineconfig *lc) ++{ ++ unsigned long flags; ++ u32 crc = crc32(~0, lc, sizeof(*lc)); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->lineconfig_fingerprint = crc; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static int ++t13x_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ struct t13x *wc = container_of(span, struct t13x, span); ++ int i; ++ int res = 0; ++ ++ if (file->f_flags & O_NONBLOCK) ++ return -EAGAIN; ++ ++ /* Set recover timing mode */ ++ span->syncsrc = lc->sync; ++ ++ /* make sure that sigcaps gets updated if necessary */ ++ for (i = 0; i < wc->span.channels; i++) ++ t13x_chan_set_sigcap(span, i); ++ ++ /* If already running, apply changes immediately */ ++ if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags) && ++ t13x_lineconfig_changed(wc, lc)) { ++ res = t13x_startup(file, span); ++ if (!res) ++ t13x_save_lineconfig(wc, lc); ++ } ++ return res; ++} ++ ++/** ++ * t13x_software_init - Initialize the board for the given type. ++ * @wc: The board to initialize. ++ * @type: The type of board we are, T1 / E1 ++ * ++ * This function is called at startup and when the type of the span is changed ++ * via the dahdi_device before the span is assigned a number. ++ * ++ */ ++static int t13x_software_init(struct t13x *wc, enum linemode type) ++{ ++ int x; ++ struct dahdi_chan *chans[32] = {NULL,}; ++ struct dahdi_echocan_state *ec[32] = {NULL,}; ++ unsigned long flags; ++ int res = 0; ++ ++ /* We may already be setup properly. */ ++ if (wc->span.channels == ((E1 == type) ? 31 : 24)) ++ return 0; ++ ++ for (x = 0; x < ((E1 == type) ? 31 : 24); x++) { ++ chans[x] = kzalloc(sizeof(*chans[x]), GFP_KERNEL); ++ ec[x] = kzalloc(sizeof(*ec[x]), GFP_KERNEL); ++ if (!chans[x] || !ec[x]) ++ goto error_exit; ++ } ++ ++ /* Because the interrupt handler is running, we need to atomically ++ * swap the channel arrays. */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ _t13x_free_channels(wc); ++ memcpy(wc->chans, chans, sizeof(wc->chans)); ++ memcpy(wc->ec, ec, sizeof(wc->ec)); ++ memset(chans, 0, sizeof(chans)); ++ memset(ec, 0, sizeof(ec)); ++ ++ switch (type) { ++ case E1: ++ wc->span.channels = 31; ++ wc->span.spantype = SPANTYPE_DIGITAL_E1; ++ wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 | ++ DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4; ++ wc->span.deflaw = DAHDI_LAW_ALAW; ++ break; ++ case T1: ++ wc->span.channels = 24; ++ wc->span.spantype = SPANTYPE_DIGITAL_T1; ++ wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | ++ DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF; ++ wc->span.deflaw = DAHDI_LAW_MULAW; ++ break; ++ case J1: ++ wc->span.channels = 24; ++ wc->span.spantype = SPANTYPE_DIGITAL_J1; ++ wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | ++ DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF; ++ wc->span.deflaw = DAHDI_LAW_MULAW; ++ break; ++ default: ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ res = -EINVAL; ++ goto error_exit; ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ dev_info(&wc->xb.pdev->dev, "Setting up global serial parameters for %s\n", ++ dahdi_spantype2str(wc->span.spantype)); ++ ++ t13x_serial_setup(wc); ++ set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags); ++ for (x = 0; x < wc->span.channels; x++) { ++ snprintf(wc->chans[x]->name, sizeof(wc->chans[x]->name), ++ "%s/%d", wc->span.name, x + 1); ++ t13x_chan_set_sigcap(&wc->span, x); ++ wc->chans[x]->pvt = wc; ++ wc->chans[x]->chanpos = x + 1; ++ } ++ ++ return 0; ++ ++error_exit: ++ for (x = 0; x < ARRAY_SIZE(chans); ++x) { ++ kfree(chans[x]); ++ kfree(ec[x]); ++ } ++ return res; ++} ++ ++/** ++ * t13x_set_linemode - Change the type of span before assignment. ++ * @span: The span to change. ++ * @linemode: Text string for the line mode. ++ * ++ * This function may be called after the dahdi_device is registered but ++ * before the spans are assigned numbers (and are visible to the rest of ++ * DAHDI). ++ * ++ */ ++static int t13x_set_linemode(struct dahdi_span *span, enum spantypes linemode) ++{ ++ int res; ++ struct t13x *wc = container_of(span, struct t13x, span); ++ ++ /* We may already be set to the requested type. */ ++ if (span->spantype == linemode) { ++ span->alarms = DAHDI_ALARM_NONE; ++ return 0; ++ } ++ ++ mutex_lock(&wc->lock); ++ ++ /* Stop the processing of the channels since we're going to change ++ * them. */ ++ clear_bit(INITIALIZED, &wc->bit_flags); ++ disable_irq(wc->xb.pdev->irq); ++ ++ smp_mb__after_atomic(); ++ del_timer_sync(&wc->timer); ++ flush_workqueue(wc->wq); ++ ++ t13x_framer_reset(wc); ++ t13x_serial_setup(wc); ++ ++ switch (linemode) { ++ case SPANTYPE_DIGITAL_T1: ++ dev_info(&wc->xb.pdev->dev, ++ "Changing from %s to T1 line mode.\n", ++ dahdi_spantype2str(wc->span.spantype)); ++ res = t13x_software_init(wc, T1); ++ break; ++ case SPANTYPE_DIGITAL_E1: ++ dev_info(&wc->xb.pdev->dev, ++ "Changing from %s to E1 line mode.\n", ++ dahdi_spantype2str(wc->span.spantype)); ++ res = t13x_software_init(wc, E1); ++ break; ++ case SPANTYPE_DIGITAL_J1: ++ dev_info(&wc->xb.pdev->dev, ++ "Changing from %s to E1 line mode.\n", ++ dahdi_spantype2str(wc->span.spantype)); ++ res = t13x_software_init(wc, J1); ++ default: ++ dev_err(&wc->xb.pdev->dev, ++ "Got invalid linemode '%s' from dahdi\n", ++ dahdi_spantype2str(linemode)); ++ res = -EINVAL; ++ } ++ ++ /* Since we probably reallocated the channels we need to make ++ * sure they are configured before setting INITIALIZED again. */ ++ if (!res) { ++ dahdi_init_span(span); ++ set_bit(INITIALIZED, &wc->bit_flags); ++ mod_timer(&wc->timer, jiffies + HZ/5); ++ } ++ wcxb_lock_latency(&wc->xb); ++ enable_irq(wc->xb.pdev->irq); ++ mutex_unlock(&wc->lock); ++ msleep(10); ++ wcxb_unlock_latency(&wc->xb); ++ return res; ++} ++ ++static int t13x_hardware_post_init(struct t13x *wc, enum linemode *type) ++{ ++ int reg; ++ int x; ++ ++ if (!strcasecmp(default_linemode, "e1")) { ++ *type = E1; ++ } else if (!strcasecmp(default_linemode, "t1")) { ++ *type = T1; ++ } else if (!strcasecmp(default_linemode, "j1")) { ++ *type = J1; ++ } else { ++ dev_warn(&wc->xb.pdev->dev, ++ "'%s' is an unknown linemode. Defaulting to 't1'\n", ++ default_linemode); ++ *type = T1; ++ } ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, "linemode: %s\n", ++ (*type == T1) ? "T1" : ((J1 == *type) ? "J1" : "E1")); ++ } ++ ++ /* what version of the FALC are we using? */ ++ wcxb_gpio_set(&wc->xb, FALC_CPU_RESET); ++ reg = t13x_framer_get(wc, 0x4a); ++ if (reg < 0) { ++ dev_info(&wc->xb.pdev->dev, ++ "Failed to read FALC version (%x)\n", reg); ++ return -EIO; ++ } ++ dev_info(&wc->xb.pdev->dev, "FALC version: %1x\n", reg); ++ ++ /* make sure reads and writes work */ ++ for (x = 0; x < 256; x++) { ++ t13x_framer_set(wc, 0x14, x); ++ reg = t13x_framer_get(wc, 0x14); ++ if (reg < 0) { ++ dev_info(&wc->xb.pdev->dev, ++ "Failed register read (%d)\n", reg); ++ return -EIO; ++ } ++ if (reg != x) { ++ dev_info(&wc->xb.pdev->dev, ++ "Register test failed. Wrote '%x' but read '%x'\n", ++ x, reg); ++ return -EIO; ++ } ++ } ++ ++ /* Enable all the GPIO outputs. */ ++ t13x_setleds(wc, wc->ledstate); ++ ++ return 0; ++} ++ ++static void t13x_check_alarms(struct t13x *wc) ++{ ++ unsigned char c, d; ++ int alarms; ++ ++ if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags))) ++ return; ++ ++ spin_lock(&wc->reglock); ++ ++ c = __t13x_framer_get(wc, 0x4c); ++ d = __t13x_framer_get(wc, 0x4d); ++ ++ /* start with existing span alarms */ ++ alarms = wc->span.alarms; ++ ++ if (dahdi_is_e1_span(&wc->span)) { ++ if (c & 0x04) { ++ /* No multiframe found, force RAI high after 400ms only ++ * if we haven't found a multiframe since last loss of ++ * frame */ ++ if (!wc->flags.nmf) { ++ /* LIM0: Force RAI High */ ++ __t13x_framer_set(wc, 0x20, 0x9f | 0x20); ++ wc->flags.nmf = 1; ++ dev_info(&wc->xb.pdev->dev, "NMF workaround on!\n"); ++ } ++ __t13x_framer_set(wc, 0x1e, 0xc3); /* Reset to CRC4 mode */ ++ __t13x_framer_set(wc, 0x1c, 0xf2); /* Force Resync */ ++ __t13x_framer_set(wc, 0x1c, 0xf0); /* Force Resync */ ++ } else if (!(c & 0x02)) { ++ if (wc->flags.nmf) { ++ /* LIM0: Clear forced RAI */ ++ __t13x_framer_set(wc, 0x20, 0x9f); ++ wc->flags.nmf = 0; ++ dev_info(&wc->xb.pdev->dev, ++ "NMF workaround off!\n"); ++ } ++ } ++ } ++ ++ if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { ++ if (!test_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags)) ++ alarms |= DAHDI_ALARM_NOTOPEN; ++ else ++ alarms &= ~DAHDI_ALARM_NOTOPEN; ++ } ++ ++ if (c & 0x20) { /* LOF/LFA */ ++ if (!(alarms & DAHDI_ALARM_RED) && (0 == wc->lofalarmtimer)) ++ wc->lofalarmtimer = (jiffies + msecs_to_jiffies(alarmdebounce)) ?: 1; ++ } else { ++ wc->lofalarmtimer = 0; ++ } ++ ++ if (c & 0x80) { /* LOS */ ++ if (!(alarms & DAHDI_ALARM_RED) && (0 == wc->losalarmtimer)) ++ wc->losalarmtimer = (jiffies + msecs_to_jiffies(losalarmdebounce)) ?: 1; ++ } else { ++ wc->losalarmtimer = 0; ++ } ++ ++ if (!(c & (0x80|0x20))) ++ alarms &= ~DAHDI_ALARM_RED; ++ ++ if (c & 0x40) { /* AIS */ ++ if (!(alarms & DAHDI_ALARM_BLUE) && (0 == wc->aisalarmtimer)) ++ wc->aisalarmtimer = (jiffies + msecs_to_jiffies(aisalarmdebounce)) ?: 1; ++ } else { ++ wc->aisalarmtimer = 0; ++ alarms &= ~DAHDI_ALARM_BLUE; ++ } ++ ++ /* Keep track of recovering */ ++ if (alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE|DAHDI_ALARM_NOTOPEN)) { ++ wc->recoverytimer = 0; ++ alarms &= ~DAHDI_ALARM_RECOVER; ++ } else if (wc->span.alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE)) { ++ if (0 == wc->recoverytimer) { ++ wc->recoverytimer = (jiffies + 5*HZ) ?: 1; ++ alarms |= DAHDI_ALARM_RECOVER; ++ } ++ } ++ ++ if (c & 0x10) { /* receiving yellow (RAI) */ ++ if (!(alarms & DAHDI_ALARM_YELLOW) && (0 == wc->yelalarmtimer)) ++ wc->yelalarmtimer = (jiffies + msecs_to_jiffies(yelalarmdebounce)) ?: 1; ++ } else { ++ wc->yelalarmtimer = 0; ++ alarms &= ~DAHDI_ALARM_YELLOW; ++ } ++ ++ if (wc->span.alarms != alarms) { ++ wc->span.alarms = alarms; ++ spin_unlock(&wc->reglock); ++ dahdi_alarm_notify(&wc->span); ++ } else { ++ spin_unlock(&wc->reglock); ++ } ++} ++ ++static void t13x_check_loopcodes(struct t13x *wc) ++{ ++ unsigned char frs1; ++ ++ frs1 = t13x_framer_get(wc, 0x4d); ++ ++ /* Detect loopup code if we're not sending one */ ++ if ((wc->span.maintstat != DAHDI_MAINT_LOOPUP) && (frs1 & 0x08)) { ++ /* Loop-up code detected */ ++ if ((wc->span.maintstat != DAHDI_MAINT_REMOTELOOP) && ++ (0 == wc->loopuptimer)) ++ wc->loopuptimer = (jiffies + msecs_to_jiffies(800)) ?: 1; ++ } else { ++ wc->loopuptimer = 0; ++ } ++ ++ /* Same for loopdown code */ ++ if ((wc->span.maintstat != DAHDI_MAINT_LOOPDOWN) && (frs1 & 0x10)) { ++ /* Loop-down code detected */ ++ if ((wc->span.maintstat == DAHDI_MAINT_REMOTELOOP) && ++ (0 == wc->loopdntimer)) ++ wc->loopdntimer = (jiffies + msecs_to_jiffies(800)) ?: 1; ++ } else { ++ wc->loopdntimer = 0; ++ } ++} ++ ++static void t13x_debounce_alarms(struct t13x *wc) ++{ ++ int alarms; ++ unsigned long flags; ++ unsigned int fmr4; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ alarms = wc->span.alarms; ++ ++ if (wc->lofalarmtimer && time_after(jiffies, wc->lofalarmtimer)) { ++ alarms |= DAHDI_ALARM_RED; ++ wc->lofalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "LOF alarm detected\n"); ++ } ++ ++ if (wc->losalarmtimer && time_after(jiffies, wc->losalarmtimer)) { ++ alarms |= DAHDI_ALARM_RED; ++ wc->losalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "LOS alarm detected\n"); ++ } ++ ++ if (wc->aisalarmtimer && time_after(jiffies, wc->aisalarmtimer)) { ++ alarms |= DAHDI_ALARM_BLUE; ++ wc->aisalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "AIS alarm detected\n"); ++ } ++ ++ if (wc->yelalarmtimer && time_after(jiffies, wc->yelalarmtimer)) { ++ alarms |= DAHDI_ALARM_YELLOW; ++ wc->yelalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "YEL alarm detected\n"); ++ } ++ ++ if (wc->recoverytimer && time_after(jiffies, wc->recoverytimer)) { ++ alarms &= ~(DAHDI_ALARM_RECOVER); ++ wc->recoverytimer = 0; ++ dev_info(&wc->xb.pdev->dev, "Alarms cleared\n"); ++ } ++ ++ if (alarms != wc->span.alarms) { ++ wc->span.alarms = alarms; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dahdi_alarm_notify(&wc->span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ ++ /* If receiving alarms (except Yellow), go into Yellow alarm state */ ++ if (alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE| ++ DAHDI_ALARM_NOTOPEN|DAHDI_ALARM_RECOVER)) { ++ if (!wc->flags.sendingyellow) { ++ dev_info(&wc->xb.pdev->dev, "Setting yellow alarm\n"); ++ /* We manually do yellow alarm to handle RECOVER ++ * and NOTOPEN, otherwise it's auto anyway */ ++ fmr4 = __t13x_framer_get(wc, 0x20); ++ __t13x_framer_set(wc, 0x20, fmr4 | 0x20); ++ wc->flags.sendingyellow = 1; ++ } ++ } else { ++ if (wc->flags.sendingyellow) { ++ dev_info(&wc->xb.pdev->dev, "Clearing yellow alarm\n"); ++ /* We manually do yellow alarm to handle RECOVER */ ++ fmr4 = __t13x_framer_get(wc, 0x20); ++ __t13x_framer_set(wc, 0x20, fmr4 & ~0x20); ++ wc->flags.sendingyellow = 0; ++ } ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static void t13x_debounce_loopcodes(struct t13x *wc) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (wc->loopuptimer && time_after(jiffies, wc->loopuptimer)) { ++ /* Loop-up code debounced */ ++ dev_info(&wc->xb.pdev->dev, "Loopup detected, enabling remote loop\n"); ++ __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Disable ++ any local loop */ ++ __t13x_framer_set(wc, 0x37, 0xf6); /* LIM1: Enable ++ remote loop */ ++ wc->span.maintstat = DAHDI_MAINT_REMOTELOOP; ++ wc->loopuptimer = 0; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dahdi_alarm_notify(&wc->span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ ++ if (wc->loopdntimer && time_after(jiffies, wc->loopdntimer)) { ++ /* Loop-down code debounced */ ++ dev_info(&wc->xb.pdev->dev, "Loopdown detected, disabling remote loop\n"); ++ __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Disable ++ any local loop */ ++ __t13x_framer_set(wc, 0x37, 0xf0); /* LIM1: Disable ++ remote loop */ ++ wc->span.maintstat = DAHDI_MAINT_NONE; ++ wc->loopdntimer = 0; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dahdi_alarm_notify(&wc->span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static void handle_leds(struct t13x *wc) ++{ ++ u32 led; ++ unsigned long flags; ++#define SET_LED_RED(a) ((a | STATUS_LED_RED) & ~STATUS_LED_GREEN) ++#define SET_LED_GREEN(a) ((a | STATUS_LED_GREEN) & ~STATUS_LED_RED) ++#define UNSET_LED_REDGREEN(a) (a & ~(STATUS_LED_RED | STATUS_LED_GREEN)) ++#define SET_LED_YELLOW(a) (a | STATUS_LED_RED | STATUS_LED_GREEN) ++ ++ led = wc->ledstate; ++ ++ if ((wc->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE)) || ++ wc->losalarmtimer) { ++ /* When we're in red alarm, blink the led once a second. */ ++ if (time_after(jiffies, wc->blinktimer)) { ++ led = (led & STATUS_LED_RED) ? UNSET_LED_REDGREEN(led) : ++ SET_LED_RED(led); ++ } ++ } else if (wc->span.alarms & DAHDI_ALARM_YELLOW) { ++ led = SET_LED_YELLOW(led); ++ } else { ++ if (test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)) ++ led = SET_LED_GREEN(led); ++ else ++ led = UNSET_LED_REDGREEN(led); ++ } ++ ++ if (led != wc->ledstate) { ++ wc->blinktimer = jiffies + HZ/2; ++ /* TODO: set ledstate in t13x_setleds() */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ wc->ledstate = led; ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ t13x_setleds(wc, led); ++ } ++} ++ ++static void te13x_handle_receive(struct wcxb *xb, void *vfp) ++{ ++ int i, j; ++ u_char *frame = (u_char *) vfp; ++ struct t13x *wc = container_of(xb, struct t13x, xb); ++ ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) { ++ for (i = 0; i < wc->span.channels; i++) { ++ wc->chans[i]->readchunk[j] = ++ frame[j*DMA_CHAN_SIZE+(1+i*4)]; ++ } ++ } ++ ++ if (!vpmsupport || !wc->vpm) { ++ for (i = 0; i < wc->span.channels; i++) { ++ struct dahdi_chan *const c = wc->span.chans[i]; ++ __dahdi_ec_chunk(c, c->readchunk, c->readchunk, ++ c->writechunk); ++ } ++ } ++ ++ _dahdi_receive(&wc->span); ++} ++ ++static void te13x_handle_transmit(struct wcxb *xb, void *vfp) ++{ ++ int i, j; ++ u_char *frame = (u_char *) vfp; ++ struct t13x *wc = container_of(xb, struct t13x, xb); ++ ++ _dahdi_transmit(&wc->span); ++ ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) { ++ for (i = 0; i < wc->span.channels; i++) { ++ frame[j*DMA_CHAN_SIZE+(1+i*4)] = ++ wc->chans[i]->writechunk[j]; ++ } ++ } ++} ++ ++#define SPAN_DEBOUNCE \ ++ (wc->lofalarmtimer || wc->losalarmtimer || \ ++ wc->aisalarmtimer || wc->yelalarmtimer || \ ++ wc->recoverytimer || \ ++ wc->loopuptimer || wc->loopdntimer) ++ ++#define SPAN_ALARMS \ ++ (wc->span.alarms & ~DAHDI_ALARM_NOTOPEN) ++ ++static void timer_work_func(struct work_struct *work) ++{ ++ struct t13x *wc = container_of(work, struct t13x, timer_work); ++ static int work_count; ++ ++ if (debug) ++ dev_notice(&wc->xb.pdev->dev, "Timer work: %d!\n", ++ ++work_count); ++ ++ t13x_debounce_alarms(wc); ++ if (!dahdi_is_e1_span(&wc->span)) ++ t13x_debounce_loopcodes(wc); ++ handle_leds(wc); ++ if (test_bit(INITIALIZED, &wc->bit_flags)) { ++ if (SPAN_DEBOUNCE || SPAN_ALARMS) ++ mod_timer(&wc->timer, jiffies + HZ/10); ++ } ++} ++ ++static void handle_falc_int(struct t13x *wc) ++{ ++ unsigned char gis, isr0, isr1, isr2, isr3, isr4; ++ unsigned long flags; ++ static int intcount; ++ bool start_timer; ++ bool recheck_sigbits = false; ++ ++ intcount++; ++ start_timer = FALSE; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ gis = __t13x_framer_get(wc, FRMR_GIS); ++ isr0 = (gis & FRMR_GIS_ISR0) ? __t13x_framer_get(wc, FRMR_ISR0) : 0; ++ isr1 = (gis & FRMR_GIS_ISR1) ? __t13x_framer_get(wc, FRMR_ISR1) : 0; ++ isr2 = (gis & FRMR_GIS_ISR2) ? __t13x_framer_get(wc, FRMR_ISR2) : 0; ++ isr3 = (gis & FRMR_GIS_ISR3) ? __t13x_framer_get(wc, FRMR_ISR3) : 0; ++ isr4 = (gis & FRMR_GIS_ISR4) ? __t13x_framer_get(wc, FRMR_ISR4) : 0; ++ ++ if ((debug) && !(isr3 & ISR3_SEC)) { ++ dev_info(&wc->xb.pdev->dev, "gis: %02x, isr0: %02x, isr1: %02x, "\ ++ "isr2: %02x, isr3: %02x, isr4: %02x, intcount=%u\n", ++ gis, isr0, isr1, isr2, isr3, isr4, intcount); ++ } ++ ++ /* Collect performance counters once per second */ ++ if (isr3 & ISR3_SEC) { ++ wc->span.count.fe += __t13x_framer_get(wc, FECL_T); ++ wc->span.count.crc4 += __t13x_framer_get(wc, CEC1L_T); ++ wc->span.count.cv += __t13x_framer_get(wc, CVCL_T); ++ wc->span.count.ebit += __t13x_framer_get(wc, EBCL_T); ++ wc->span.count.be += __t13x_framer_get(wc, BECL_T); ++ wc->span.count.prbs = __t13x_framer_get(wc, FRS1_T); ++ ++ if (DAHDI_RXSIG_INITIAL == wc->span.chans[0]->rxhooksig) ++ recheck_sigbits = true; ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* Collect errored second counter once per second */ ++ if (isr3 & ISR3_ES) ++ wc->span.count.errsec += 1; ++ ++ if ((isr0 & 0x08) || recheck_sigbits) ++ t13x_check_sigbits(wc); ++ ++ if (dahdi_is_e1_span(&wc->span)) { ++ /* E1 checks */ ++ if ((isr3 & 0x68) || isr2 || (isr1 & 0x7f)) { ++ t13x_check_alarms(wc); ++ start_timer = TRUE; ++ } ++ } else { ++ /* T1 checks */ ++ if (isr2) { ++ t13x_check_alarms(wc); ++ start_timer = TRUE; ++ } ++ if (isr3 & 0x08) { /* T1 LLBSC */ ++ t13x_check_loopcodes(wc); ++ start_timer = TRUE; ++ } ++ } ++ ++ if (!wc->span.alarms) { ++ if ((isr3 & 0x3) || (isr4 & 0xc0)) ++ wc->span.count.timingslips++; ++ } else ++ wc->span.count.timingslips = 0; ++ ++ if (start_timer && !timer_pending(&wc->timer) && ++ test_bit(INITIALIZED, &wc->bit_flags)) { ++ mod_timer(&wc->timer, jiffies + HZ/10); ++ } ++} ++ ++static void te13x_handle_interrupt(struct wcxb *xb, u32 pending) ++{ ++ struct t13x *wc = container_of(xb, struct t13x, xb); ++ ++ if (pending & FALC_INT) { ++ handle_falc_int(wc); ++ } ++} ++ ++static void te13xp_timer(TIMER_DATA_TYPE timer) ++{ ++ struct t13x *wc = from_timer(wc, timer, timer); ++ ++ if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags))) ++ return; ++ ++ queue_work(wc->wq, &wc->timer_work); ++ return; ++} ++ ++static inline void create_sysfs_files(struct t13x *wc) { return; } ++static inline void remove_sysfs_files(struct t13x *wc) { return; } ++ ++static int t13x_open(struct dahdi_chan *chan) ++{ ++ struct t13x *wc = chan->pvt; ++ unsigned long flags; ++ ++ if (!(wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN)) ++ return 0; ++ ++ if (!test_and_set_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags)) { ++ local_irq_save(flags); ++ t13x_check_alarms(wc); ++ local_irq_restore(flags); ++ } ++ ++ return 0; ++} ++ ++static int t13x_close(struct dahdi_chan *chan) ++{ ++ struct t13x *wc = chan->pvt; ++ unsigned long flags; ++ ++ if (!(wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN)) ++ return 0; ++ ++ if (!have_open_channels(wc)) { ++ if (test_and_clear_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags)) { ++ local_irq_save(flags); ++ t13x_check_alarms(wc); ++ local_irq_restore(flags); ++ } ++ } ++ return 0; ++} ++ ++static const struct dahdi_span_ops t13x_span_ops = { ++ .owner = THIS_MODULE, ++ .spanconfig = t13x_spanconfig, ++ .chanconfig = t13x_chanconfig, ++ .startup = t13x_startup, ++ .rbsbits = t13x_rbsbits, ++ .maint = t13x_maint, ++ .ioctl = t13x_ioctl, ++ .set_spantype = t13x_set_linemode, ++ .echocan_create = t13x_echocan_create, ++ .echocan_name = t13x_echocan_name, ++ .open = t13x_open, ++ .close = t13x_close, ++}; ++ ++#define SPI_BASE 0x200 ++#define SPISRR (SPI_BASE + 0x40) ++#define SPICR (SPI_BASE + 0x60) ++#define SPISR (SPI_BASE + 0x64) ++#define SPIDTR (SPI_BASE + 0x68) ++#define SPIDRR (SPI_BASE + 0x6c) ++#define SPISSR (SPI_BASE + 0x70) ++ ++/** ++ * t13x_read_serial - Returns the serial number of the board. ++ * @wc: The board whos serial number we are reading. ++ * ++ * The buffer returned is dynamically allocated and must be kfree'd by the ++ * caller. If memory could not be allocated, NULL is returned. ++ * ++ * Must be called in process context. ++ * ++ * TODO: Move this up into wcxb.c ++ */ ++static char *t13x_read_serial(struct t13x *wc) ++{ ++ int i; ++ static const int MAX_SERIAL = 20*5; ++ const unsigned int SERIAL_ADDRESS = 0x1f0000; ++ unsigned char *serial = kzalloc(MAX_SERIAL + 1, GFP_KERNEL); ++ struct wcxb const *xb = &wc->xb; ++ struct wcxb_spi_master *flash_spi_master = NULL; ++ struct wcxb_spi_device *flash_spi_device = NULL; ++ ++ if (!serial) ++ return NULL; ++ ++ flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev, ++ xb->membase + SPI_BASE, ++ false); ++ if (!flash_spi_master) ++ return NULL; ++ ++ flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0); ++ if (!flash_spi_device) ++ goto error_exit; ++ ++ wcxb_flash_read(flash_spi_device, SERIAL_ADDRESS, ++ serial, MAX_SERIAL); ++ ++ for (i = 0; i < MAX_SERIAL; ++i) { ++ if ((serial[i] < 0x20) || (serial[i] > 0x7e)) { ++ serial[i] = '\0'; ++ break; ++ } ++ } ++ ++ if (!i) { ++ kfree(serial); ++ serial = NULL; ++ } else { ++ /* Limit the size of the buffer to just what is needed to ++ * actually hold the serial number. */ ++ unsigned char *new_serial; ++ new_serial = kasprintf(GFP_KERNEL, "%s", serial); ++ kfree(serial); ++ serial = new_serial; ++ } ++ ++error_exit: ++ wcxb_spi_device_destroy(flash_spi_device); ++ wcxb_spi_master_destroy(flash_spi_master); ++ return serial; ++} ++ ++static int te13xp_check_firmware(struct t13x *wc) ++{ ++ const char *filename; ++ u32 expected_version; ++ enum wcxb_reset_option reset; ++ ++ if (is_pcie(wc)) { ++ filename = TE133_FW_FILENAME; ++ expected_version = TE133_FW_VERSION; ++ } else { ++ filename = TE134_FW_FILENAME; ++ expected_version = TE134_FW_VERSION; ++ } ++ ++ /* Specific firmware requires power cycle to properly reset */ ++ if (0x6f0017 == wcxb_get_firmware_version(&wc->xb)) ++ reset = WCXB_RESET_LATER; ++ else ++ reset = WCXB_RESET_NOW; ++ ++ return wcxb_check_firmware(&wc->xb, expected_version, filename, ++ force_firmware, reset); ++} ++ ++static int __devinit te13xp_init_one(struct pci_dev *pdev, ++ const struct pci_device_id *ent) ++{ ++ struct t13x *wc; ++ const struct t13x_desc *d = (struct t13x_desc *) ent->driver_data; ++ unsigned int x; ++ int res; ++ unsigned int index = -1; ++ enum linemode type; ++ bool vpmcapable = false; ++ ++ for (x = 0; x < ARRAY_SIZE(ifaces); x++) { ++ if (!ifaces[x]) { ++ index = x; ++ break; ++ } ++ } ++ ++ if (-1 == index) { ++ pr_info("Too many interfaces\n"); ++ pci_disable_device(pdev); ++ return -EIO; ++ } ++ ++ wc = kzalloc(sizeof(*wc), GFP_KERNEL); ++ if (!wc) { ++ return -ENOMEM; ++ } ++ ++ wc->devtype = d; ++ dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ ++ /* Set the performance counters to 0 */ ++ t13x_reset_counters(&wc->span); ++ ++ ifaces[index] = wc; ++ ++ sprintf(wc->span.name, "WCT13x/%d", index); ++ snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", ++ d->name, index); ++ wc->ledstate = -1; ++ spin_lock_init(&wc->reglock); ++ mutex_init(&wc->lock); ++ timer_setup(&wc->timer, te13xp_timer, 0); ++ ++ INIT_WORK(&wc->timer_work, timer_work_func); ++ ++ wc->ddev = dahdi_create_device(); ++ if (!wc->ddev) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ wc->ddev->manufacturer = "Digium"; ++ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d", ++ pdev->bus->number, ++ PCI_SLOT(pdev->devfn) + 1); ++ if (!wc->ddev->location) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ ++ wc->name = kasprintf(GFP_KERNEL, "wcte13xp%d", index); ++ if (!wc->name) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ ++ pci_set_drvdata(pdev, wc); ++ ++ /* Setup wcxb library */ ++ wc->xb.pdev = pdev; ++ wc->xb.ops = &xb_ops; ++ wc->xb.debug = &debug; ++ res = wcxb_init(&wc->xb, wc->name, 0); ++ if (res) ++ goto fail_exit; ++ ++ res = te13xp_check_firmware(wc); ++ if (res) ++ goto fail_exit; ++ ++ wc->ddev->hardware_id = t13x_read_serial(wc); ++ if (!wc->ddev->hardware_id) { ++ dev_info(&wc->xb.pdev->dev, "No serial number found.\n"); ++ res = -EIO; ++ goto fail_exit; ++ } ++ ++ /* Check for hardware echo cancel support */ ++ if (!strncmp("TE133", wc->ddev->hardware_id+1, 5) || ++ !strncmp("TE134", wc->ddev->hardware_id+1, 5)) { ++ vpmcapable = true; ++ } ++ ++ wc->wq = create_singlethread_workqueue(wc->name); ++ if (!wc->wq) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ ++ /* Initial buffer latency size, ++ adjustable on load by modparam "latency" */ ++ if (latency > 0 && latency < DRING_SIZE) { ++ wcxb_set_minlatency(&wc->xb, latency); ++ if (WCXB_DEFAULT_LATENCY != latency) ++ dev_info(&wc->xb.pdev->dev, ++ "latency manually overridden to %d\n", ++ latency); ++ } else { ++ dev_info(&wc->xb.pdev->dev, ++ "latency module parameter must be between 1 and %d\n", ++ DRING_SIZE); ++ res = -EPERM; ++ goto fail_exit; ++ } ++ ++ wcxb_set_minlatency(&wc->xb, latency); ++ wcxb_set_maxlatency(&wc->xb, max_latency); ++ ++ create_sysfs_files(wc); ++ ++ res = t13x_hardware_post_init(wc, &type); ++ if (res) ++ goto fail_exit; ++ ++ wc->span.chans = wc->chans; ++ ++ res = t13x_software_init(wc, type); ++ if (res) ++ goto fail_exit; ++ ++ if (!wc->vpm && vpmsupport && vpmcapable) ++ t13x_vpm_init(wc); ++ ++ if (wc->vpm) ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, ++ "%s (VPMOCT032)", wc->devtype->name); ++ else ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", ++ wc->devtype->name); ++ ++ wc->span.ops = &t13x_span_ops; ++ list_add_tail(&wc->span.device_node, &wc->ddev->spans); ++ ++ /* Span is in red alarm by default */ ++ wc->span.alarms = DAHDI_ALARM_NONE; ++ ++ res = dahdi_register_device(wc->ddev, &wc->xb.pdev->dev); ++ if (res) { ++ dev_info(&wc->xb.pdev->dev, "Unable to register with DAHDI\n"); ++ goto fail_exit; ++ } ++ ++ set_bit(INITIALIZED, &wc->bit_flags); ++ mod_timer(&wc->timer, jiffies + HZ/5); ++ ++ if (wc->ddev->hardware_id) { ++ dev_info(&wc->xb.pdev->dev, "Found a %s (SN: %s)\n", ++ wc->devtype->name, wc->ddev->hardware_id); ++ } else { ++ dev_info(&wc->xb.pdev->dev, "Found a %s\n", ++ wc->devtype->name); ++ } ++ ++ return 0; ++ ++fail_exit: ++ if (&wc->xb) ++ wcxb_release(&wc->xb); ++ ++ free_wc(wc); ++ return res; ++} ++ ++static void __devexit te13xp_remove_one(struct pci_dev *pdev) ++{ ++ struct t13x *wc = pci_get_drvdata(pdev); ++ dev_info(&wc->xb.pdev->dev, "Removing a Wildcard TE13xP.\n"); ++ if (!wc) ++ return; ++ ++ clear_bit(INITIALIZED, &wc->bit_flags); ++ smp_mb__after_atomic(); ++ ++ /* Quiesce DMA engine interrupts */ ++ wcxb_stop(&wc->xb); ++ ++ /* Leave framer in reset so it no longer transmits */ ++ wcxb_gpio_clear(&wc->xb, FALC_CPU_RESET); ++ ++ del_timer_sync(&wc->timer); ++ flush_workqueue(wc->wq); ++ del_timer_sync(&wc->timer); ++ ++ /* Turn off status LED */ ++ t13x_setleds(wc, 0); ++ ++ if (wc->vpm) ++ release_vpm450m(wc->vpm); ++ wc->vpm = NULL; ++ ++ dahdi_unregister_device(wc->ddev); ++ ++ remove_sysfs_files(wc); ++ ++ wcxb_release(&wc->xb); ++ free_wc(wc); ++} ++ ++static DEFINE_PCI_DEVICE_TABLE(te13xp_pci_tbl) = { ++ { 0xd161, 0x800a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te133}, ++ { 0xd161, 0x800b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te134}, ++ { 0 } ++}; ++ ++static void te13xp_shutdown(struct pci_dev *pdev) ++{ ++ struct t13x *wc = pci_get_drvdata(pdev); ++ dev_info(&wc->xb.pdev->dev, "Quiescing a Wildcard TE13xP.\n"); ++ if (!wc) ++ return; ++ ++ /* Quiesce and mask DMA engine interrupts */ ++ wcxb_stop(&wc->xb); ++} ++ ++static int te13xp_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ return -ENOSYS; ++} ++ ++MODULE_DEVICE_TABLE(pci, te13xp_pci_tbl); ++ ++static struct pci_driver te13xp_driver = { ++ .name = "wcte13xp", ++ .probe = te13xp_init_one, ++ .remove = __devexit_p(te13xp_remove_one), ++ .shutdown = te13xp_shutdown, ++ .suspend = te13xp_suspend, ++ .id_table = te13xp_pci_tbl, ++}; ++ ++static int __init te13xp_init(void) ++{ ++ int res; ++ ++ if (strcasecmp(default_linemode, "t1") && ++ strcasecmp(default_linemode, "j1") && ++ strcasecmp(default_linemode, "e1")) { ++ pr_err("'%s' is an unknown span type.\n", default_linemode); ++ default_linemode = "t1"; ++ return -EINVAL; ++ } ++ ++ res = pci_register_driver(&te13xp_driver); ++ if (res) ++ return -ENODEV; ++ ++ return 0; ++} ++ ++ ++static void __exit te13xp_cleanup(void) ++{ ++ pci_unregister_driver(&te13xp_driver); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++module_param(default_linemode, charp, S_IRUGO); ++MODULE_PARM_DESC(default_linemode, "\"t1\"(default), \"e1\", or \"j1\"."); ++module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(losalarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(aisalarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(yelalarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(vpmsupport, int, 0600); ++module_param(force_firmware, int, S_IRUGO); ++module_param(latency, int, S_IRUGO); ++MODULE_PARM_DESC(latency, "How many milliseconds of audio to buffer between card and host (3ms default). This number will increase during runtime, dynamically, if dahdi detects that it is too small. This is commonly refered to as a \"latency bump\""); ++module_param(max_latency, int, 0600); ++MODULE_PARM_DESC(max_latency, "The maximum amount of latency that the driver will permit."); ++ ++MODULE_DESCRIPTION("Wildcard Digital Card Driver"); ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(te13xp_init); ++module_exit(te13xp_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/wcte43x-base.c linux-source-4.19-dahdi/drivers/dahdi/wcte43x-base.c +--- linux-source-4.19/drivers/dahdi/wcte43x-base.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcte43x-base.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,3648 @@ ++/* ++ * Digium, Inc. Wildcard te43x T1/E1 card Driver ++ * ++ * Written by Russ Meyerriecks ++ * Copyright (C) 2012 - 2013, 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. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) ++#include ++#endif /* 4.11.0 */ ++ ++#include "wct4xxp/wct4xxp.h" /* For certain definitions */ ++#include "wcxb.h" ++#include "wcxb_spi.h" ++#include "wcxb_flash.h" ++ ++static const char *TE435_FW_FILENAME = "dahdi-fw-te435.bin"; ++static const char *TE436_FW_FILENAME = "dahdi-fw-te436.bin"; ++static const u32 TE435_VERSION = 0x13001e; ++static const u32 TE436_VERSION = 0x10017; ++ ++/* #define RPC_RCLK */ ++ ++enum linemode { ++ T1 = 1, ++ E1, ++ J1, ++}; ++ ++#define STATUS_LED_GREEN (1 << 9) ++#define STATUS_LED_RED (1 << 10) ++#define STATUS_LED_YELLOW (STATUS_LED_RED | STATUS_LED_GREEN) ++#define LED_MASK 0x7f8 ++#define FALC_CPU_RESET (1 << 11) ++ ++/* Interrupt definitions */ ++#define FALC_INT (1<<3) ++#define SPI_INT (1<<4) ++#define DMA_STOPPED (1<<5) ++ ++struct t43x; ++ ++struct t43x_span { ++ struct t43x *owner; ++ struct dahdi_span span; ++#define NMF_FLAGBIT 1 ++#define SENDINGYELLOW_FLAGBIT 2 ++#define HAVE_OPEN_CHANNELS_FLAGBIT 3 ++ unsigned long bit_flags; ++ unsigned char txsigs[16]; /* Copy of tx sig registers */ ++ unsigned long lofalarmtimer; ++ unsigned long losalarmtimer; ++ unsigned long aisalarmtimer; ++ unsigned long yelalarmtimer; ++ unsigned long recoverytimer; ++ unsigned long loopuptimer; ++ unsigned long loopdntimer; ++ ++ struct dahdi_chan *chans[32]; /* Channels */ ++ struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */ ++ ++ bool debounce; ++ int syncpos; ++ int sync; ++ u32 lineconfig_fingerprint; ++}; ++ ++struct t43x_clksrc_work { ++ struct delayed_work work; ++ spinlock_t lock; ++ enum wcxb_clock_sources clksrc; ++ bool is_timing_master; ++}; ++ ++/* One structure per card */ ++struct t43x { ++ spinlock_t reglock; ++ ++ const struct t43x_desc *devtype; ++ unsigned long blinktimer; ++ bool blink; ++ struct dahdi_device *ddev; ++ struct t43x_span *tspans[4]; ++ int numspans; /* Number of spans on the card */ ++ int spansstarted; /* Number of spans started */ ++ ++ /* protected by t1.reglock */ ++ struct timer_list timer; ++ struct work_struct timer_work; ++ struct workqueue_struct *wq; ++ struct t43x_clksrc_work clksrc_work; ++ unsigned int not_ready; /* 0 when entire card is ready to go */ ++ struct vpm450m *vpm; ++ char *vpm_name; ++ struct mutex lock; ++ bool latency_locked; ++ int syncsrc; ++ int num; /* card index */ ++ int intr_span; /* span to service next interrupt */ ++ ++ struct wcxb xb; ++ struct list_head card_node; ++}; ++ ++static void t43x_handle_transmit(struct wcxb *xb, void *vfp); ++static void t43x_handle_receive(struct wcxb *xb, void *vfp); ++static void t43x_handle_interrupt(struct wcxb *xb, u32 pending); ++ ++static void t43x_handle_error(struct wcxb *xb) ++{ ++ struct t43x *wc = container_of(xb, struct t43x, xb); ++ wc->ddev->irqmisses++; ++} ++ ++static struct wcxb_operations xb_ops = { ++ .handle_receive = t43x_handle_receive, ++ .handle_transmit = t43x_handle_transmit, ++ .handle_interrupt = t43x_handle_interrupt, ++ .handle_error = t43x_handle_error, ++}; ++ ++/* Maintenance Mode Registers */ ++#define LIM0 0x36 ++#define LIM0_LL (1<<1) ++#define LIM1 0x37 ++#define LIM1_RL (1<<1) ++#define LIM1_JATT (1<<2) ++ ++/* Clear Channel Registers */ ++#define CCB1 0x2f ++#define CCB2 0x30 ++#define CCB3 0x31 ++ ++#define FECL_T 0x50 /* Framing Error Counter Lower Byte */ ++#define FECH_T 0x51 /* Framing Error Counter Higher Byte */ ++#define CVCL_T 0x52 /* Code Violation Counter Lower Byte */ ++#define CVCH_T 0x53 /* Code Violation Counter Higher Byte */ ++#define CEC1L_T 0x54 /* CRC Error Counter 1 Lower Byte */ ++#define CEC1H_T 0x55 /* CRC Error Counter 1 Higher Byte */ ++#define EBCL_T 0x56 /* E-Bit Error Counter Lower Byte */ ++#define EBCH_T 0x57 /* E-Bit Error Counter Higher Byte */ ++#define BECL_T 0x58 /* Bit Error Counter Lower Byte */ ++#define BECH_T 0x59 /* Bit Error Counter Higher Byte */ ++#define COEC_T 0x5A /* COFA Event Counter */ ++#define PRBSSTA_T 0xDA /* PRBS Status Register */ ++#define FRS1_T 0x4D /* Framer Receive Status Reg 1 */ ++ ++#define ISR3_SEC (1 << 6) /* Internal one-second interrupt bit mask */ ++#define ISR3_ES (1 << 7) /* Errored Second interrupt bit mask */ ++ ++#define IMR0 0x14 ++ ++/* pci memory map offsets */ ++#define DMA1 0x00 /* dma addresses */ ++#define DMA2 0x04 ++#define DMA3 0x08 ++#define CNTL 0x0C /* fpga control register */ ++#define INT_MASK 0x10 /* interrupt vectors from oct and framer */ ++#define INT_STAT 0x14 ++#define FRAMER_BASE 0x00000800 /* framer's address space */ ++ ++#define NOSYNC_ALARMS (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | \ ++ DAHDI_ALARM_LOOPBACK) ++ ++static int debug; ++static int timingcable; ++static int force_firmware; ++static int alarmdebounce = 2500; /* LOF/LFA def to 2.5s AT&T TR54016*/ ++static int losalarmdebounce = 2500; /* LOS def to 2.5s AT&T TR54016*/ ++static int aisalarmdebounce = 2500; /* AIS(blue) def to 2.5s AT&T TR54016*/ ++static int yelalarmdebounce = 500; /* RAI(yellow) def to 0.5s AT&T guide */ ++static char *default_linemode = "t1"; /* 'e1', 't1', or 'j1' */ ++static int latency = WCXB_DEFAULT_LATENCY; ++static int max_latency = WCXB_DEFAULT_MAXLATENCY; ++ ++struct t43x_firm_header { ++ u8 header[6]; ++ __le32 chksum; ++ u8 pad[18]; ++ __le32 version; ++} __packed; ++ ++static int t43x_check_for_interrupts(struct t43x *wc); ++static void t43x_check_alarms(struct t43x *wc, int span_idx); ++static void t43x_check_sigbits(struct t43x *wc, int span_idx); ++static const struct dahdi_span_ops t43x_span_ops; ++static void __t43x_set_timing_source_auto(struct t43x *wc); ++ ++static int vpmsupport = 1; ++ ++#include "oct6100api/oct6100_api.h" ++ ++#define ECHOCAN_NUM_CHANS 128 ++ ++#define FLAGBIT_DTMF 1 ++#define FLAGBIT_MUTE 2 ++#define FLAGBIT_ECHO 3 ++#define FLAGBIT_ALAW 4 ++ ++#define OCT_CHIP_ID 0 ++#define OCT_MAX_TDM_STREAMS 4 ++#define OCT_TONEEVENT_BUFFER_SIZE 128 ++#define SOUT_STREAM 1 ++#define RIN_STREAM 0 ++#define SIN_STREAM 2 ++ ++static void t43x_vpm_init(struct t43x *wc); ++static void echocan_free(struct dahdi_chan *chan, ++ struct dahdi_echocan_state *ec); ++static const struct dahdi_echocan_features vpm_ec_features = { ++ .NLP_automatic = 1, ++ .CED_tx_detect = 1, ++ .CED_rx_detect = 1, ++}; ++static const struct dahdi_echocan_ops vpm_ec_ops = { ++ .echocan_free = echocan_free, ++}; ++ ++struct vpm450m { ++ tPOCT6100_INSTANCE_API pApiInstance; ++ struct oct612x_context context; ++ UINT32 aulEchoChanHndl[ECHOCAN_NUM_CHANS]; ++ int ecmode[ECHOCAN_NUM_CHANS]; ++ unsigned long chanflags[ECHOCAN_NUM_CHANS]; ++}; ++ ++static int t43x_oct612x_write(struct oct612x_context *context, ++ u32 address, u16 value) ++{ ++ struct t43x *wc = dev_get_drvdata(context->dev); ++ wcxb_set_echocan_reg(&wc->xb, address, value); ++ return 0; ++} ++ ++static int t43x_oct612x_read(struct oct612x_context *context, u32 address, ++ u16 *value) ++{ ++ struct t43x *wc = dev_get_drvdata(context->dev); ++ *value = wcxb_get_echocan_reg(&wc->xb, address); ++ return 0; ++} ++ ++static int t43x_oct612x_write_smear(struct oct612x_context *context, ++ u32 address, u16 value, size_t count) ++{ ++ unsigned int i; ++ struct t43x *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ wcxb_set_echocan_reg(&wc->xb, address + (i << 1), value); ++ return 0; ++} ++ ++static int t43x_oct612x_write_burst(struct oct612x_context *context, ++ u32 address, const u16 *buffer, ++ size_t count) ++{ ++ unsigned int i; ++ struct t43x *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ wcxb_set_echocan_reg(&wc->xb, address + (i << 1), buffer[i]); ++ return 0; ++} ++ ++static int t43x_oct612x_read_burst(struct oct612x_context *context, ++ u32 address, u16 *buffer, size_t count) ++{ ++ unsigned int i; ++ struct t43x *wc = dev_get_drvdata(context->dev); ++ for (i = 0; i < count; ++i) ++ buffer[i] = wcxb_get_echocan_reg(&wc->xb, address + (i << 1)); ++ return 0; ++} ++ ++static const struct oct612x_ops t43x_oct612x_ops = { ++ .write = t43x_oct612x_write, ++ .read = t43x_oct612x_read, ++ .write_smear = t43x_oct612x_write_smear, ++ .write_burst = t43x_oct612x_write_burst, ++ .read_burst = t43x_oct612x_read_burst, ++}; ++ ++static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ ++ if (vpm450m->ecmode[channel] == mode) ++ return; ++ modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); ++ if (!modify) { ++ pr_notice("Unable to allocate memory for setec!\n"); ++ return; ++ } ++ Oct6100ChannelModifyDef(modify); ++ modify->ulEchoOperationMode = mode; ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n", ++ vpm450m->aulEchoChanHndl[channel], channel, ulResult); ++ } else { ++#ifdef OCTASIC_DEBUG ++ pr_debug("Echo can on channel %d set to %d\n", channel, mode); ++#endif ++ vpm450m->ecmode[channel] = mode; ++ } ++ kfree(modify); ++} ++ ++static void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel, ++ bool alaw) ++{ ++ tOCT6100_CHANNEL_MODIFY *modify; ++ UINT32 ulResult; ++ UINT32 law_to_use = (alaw) ? cOCT6100_PCM_A_LAW : ++ cOCT6100_PCM_U_LAW; ++ ++ /* If we're already in this companding mode, no need to do anything. */ ++ if (alaw == (test_bit(FLAGBIT_ALAW, &vpm450m->chanflags[channel]) > 0)) ++ return; ++ ++ modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); ++ if (!modify) { ++ pr_notice("Unable to allocate memory for setec!\n"); ++ return; ++ } ++ ++ Oct6100ChannelModifyDef(modify); ++ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ++ modify->fTdmConfigModified = TRUE; ++ modify->TdmConfig.ulSinPcmLaw = law_to_use; ++ modify->TdmConfig.ulRinPcmLaw = law_to_use; ++ modify->TdmConfig.ulSoutPcmLaw = law_to_use; ++ modify->TdmConfig.ulRoutPcmLaw = law_to_use; ++ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); ++ if (ulResult != GENERIC_OK) { ++ pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n", ++ vpm450m->aulEchoChanHndl[channel], channel, ulResult); ++ } else { ++ if (debug) { ++ pr_info("Changed companding on channel %d to %s.\n", ++ channel, (alaw) ? "alaw" : "ulaw"); ++ } ++ if (alaw) ++ set_bit(FLAGBIT_ALAW, &vpm450m->chanflags[channel]); ++ else ++ clear_bit(FLAGBIT_ALAW, &vpm450m->chanflags[channel]); ++ } ++ kfree(modify); ++} ++ ++static void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen) ++{ ++ if (eclen) { ++ set_bit(FLAGBIT_ECHO, &vpm450m->chanflags[channel]); ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_NORMAL); ++ } else { ++ unsigned long *flags = &vpm450m->chanflags[channel]; ++ clear_bit(FLAGBIT_ECHO, &vpm450m->chanflags[channel]); ++ if (test_bit(FLAGBIT_DTMF, flags) || ++ test_bit(FLAGBIT_MUTE, flags)) { ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_HT_RESET); ++ } else { ++ vpm450m_setecmode(vpm450m, channel, ++ cOCT6100_ECHO_OP_MODE_POWER_DOWN); ++ } ++ } ++} ++ ++static UINT32 tdmmode_chan_to_slot_map(int channel) ++{ ++ /* Four phases on the tdm bus, skip three of them per channel */ ++ /* Due to a bug in the octasic, we had to move the data onto phase 2 */ ++ return 1 + ((channel % 32) * 4) + (channel / 32); ++} ++ ++static int echocan_initialize_channel( ++ struct vpm450m *vpm, int channel, int mode) ++{ ++ tOCT6100_CHANNEL_OPEN ChannelOpen; ++ UINT32 law_to_use = (mode) ? cOCT6100_PCM_A_LAW : ++ cOCT6100_PCM_U_LAW; ++ UINT32 tdmslot_setting; ++ UINT32 ulResult; ++ ++ tdmslot_setting = tdmmode_chan_to_slot_map(channel); ++ ++ /* Fill Open channel structure with defaults */ ++ Oct6100ChannelOpenDef(&ChannelOpen); ++ ++ /* Assign the handle memory.*/ ++ ChannelOpen.pulChannelHndl = &vpm->aulEchoChanHndl[channel]; ++ ChannelOpen.ulUserChanId = channel; ++ /* Enable Tone disabling for Fax and Modems */ ++ ChannelOpen.fEnableToneDisabler = TRUE; ++ ++ /* Passthrough TDM data by default, no echocan */ ++ ChannelOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; ++ ++ /* Configure the TDM settings.*/ ++ /* Input from the framer */ ++ ChannelOpen.TdmConfig.ulSinStream = SIN_STREAM; ++ ChannelOpen.TdmConfig.ulSinTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulSinPcmLaw = law_to_use; ++ ++ /* Input from the Host (pre-framer) */ ++ ChannelOpen.TdmConfig.ulRinStream = RIN_STREAM; ++ ChannelOpen.TdmConfig.ulRinTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulRinPcmLaw = law_to_use; ++ ++ /* Output to the Host */ ++ ChannelOpen.TdmConfig.ulSoutStream = SOUT_STREAM; ++ ChannelOpen.TdmConfig.ulSoutTimeslot = tdmslot_setting; ++ ChannelOpen.TdmConfig.ulSoutPcmLaw = law_to_use; ++ ++ /* From asterisk after echo-cancellation - goes nowhere */ ++ ChannelOpen.TdmConfig.ulRoutStream = cOCT6100_UNASSIGNED; ++ ChannelOpen.TdmConfig.ulRoutTimeslot = cOCT6100_UNASSIGNED; ++ ChannelOpen.TdmConfig.ulRoutPcmLaw = law_to_use; ++ ++ /* Set the desired VQE features.*/ ++ ChannelOpen.VqeConfig.fEnableNlp = TRUE; ++ ChannelOpen.VqeConfig.fRinDcOffsetRemoval = TRUE; ++ ChannelOpen.VqeConfig.fSinDcOffsetRemoval = TRUE; ++ ChannelOpen.VqeConfig.ulComfortNoiseMode = ++ cOCT6100_COMFORT_NOISE_NORMAL; ++ ++ /* Open the channel.*/ ++ ulResult = Oct6100ChannelOpen(vpm->pApiInstance, &ChannelOpen); ++ ++ return ulResult; ++} ++ ++static struct vpm450m *init_vpm450m(struct t43x *wc, int *laws, int numspans, ++ const struct firmware *firmware) ++{ ++ tOCT6100_CHIP_OPEN *ChipOpen; ++ tOCT6100_GET_INSTANCE_SIZE InstanceSize; ++ tOCT6100_CHANNEL_OPEN *ChannelOpen; ++ UINT32 ulResult; ++ struct vpm450m *vpm450m; ++ int x, i; ++ ++ vpm450m = kzalloc(sizeof(struct vpm450m), GFP_KERNEL); ++ if (!vpm450m) { ++ dev_info(&wc->xb.pdev->dev, ++ "Unable to allocate vpm450m struct\n"); ++ return NULL; ++ } ++ ++ vpm450m->context.dev = &wc->xb.pdev->dev; ++ vpm450m->context.ops = &t43x_oct612x_ops; ++ ++ ChipOpen = kzalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL); ++ if (!ChipOpen) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate ChipOpen\n"); ++ kfree(vpm450m); ++ return NULL; ++ } ++ ++ ChannelOpen = kzalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL); ++ if (!ChannelOpen) { ++ dev_info(&wc->xb.pdev->dev, "Unable to allocate ChannelOpen\n"); ++ kfree(vpm450m); ++ kfree(ChipOpen); ++ return NULL; ++ } ++ ++ for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++) ++ vpm450m->ecmode[x] = -1; ++ ++ dev_info(&wc->xb.pdev->dev, "Echo cancellation for %d channels\n", ++ wc->numspans * 32); ++ ++ Oct6100ChipOpenDef(ChipOpen); ++ ChipOpen->pProcessContext = &vpm450m->context; ++ ++ /* Change default parameters as needed */ ++ /* upclk oscillator is at 33.33 Mhz */ ++ ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; ++ ++ /* mclk will be generated by internal PLL at 133 Mhz */ ++ ChipOpen->fEnableMemClkOut = TRUE; ++ ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; ++ ++ /* User defined Chip ID.*/ ++ ChipOpen->ulUserChipId = OCT_CHIP_ID; ++ ++ /* Set the maximums that the chip needs to support */ ++ ChipOpen->ulMaxChannels = wc->numspans * 32; ++ ChipOpen->ulMaxTdmStreams = OCT_MAX_TDM_STREAMS; ++ ++ /* External Memory Settings */ ++ /* Use DDR memory.*/ ++ ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; ++ ChipOpen->ulNumMemoryChips = 1; ++ ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; ++ ++ ChipOpen->pbyImageFile = (PUINT8) firmware->data; ++ ChipOpen->ulImageSize = firmware->size; ++ ++ /* Set TDM data stream frequency */ ++ for (i = 0; i < ChipOpen->ulMaxTdmStreams; i++) ++ ChipOpen->aulTdmStreamFreqs[i] = cOCT6100_TDM_STREAM_FREQ_8MHZ; ++ ++ /* Configure TDM sampling */ ++ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; ++ /* Disable to save RAM footprint space */ ++ ChipOpen->fEnableChannelRecording = false; ++ ++ /* In this example we will maintain the API using polling so ++ interrupts must be disabled */ ++ ChipOpen->InterruptConfig.ulErrorH100Config = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulErrorMemoryConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulFatalGeneralConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ChipOpen->InterruptConfig.ulFatalMemoryConfig = ++ cOCT6100_INTERRUPT_DISABLE; ++ ++ ChipOpen->ulSoftToneEventsBufSize = OCT_TONEEVENT_BUFFER_SIZE; ++ ++ /* Inserting default values into tOCT6100_GET_INSTANCE_SIZE ++ structure parameters. */ ++ Oct6100GetInstanceSizeDef(&InstanceSize); ++ ++ /* Reset octasic device */ ++ wcxb_reset_echocan(&wc->xb); ++ ++ /* Get the size of the OCT6100 instance structure. */ ++ ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize); ++ if (ulResult != cOCT6100_ERR_OK) { ++ dev_info(&wc->xb.pdev->dev, "Unable to get instance size: %x\n", ++ ulResult); ++ return NULL; ++ } ++ ++ vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); ++ if (!vpm450m->pApiInstance) { ++ dev_info(&wc->xb.pdev->dev, ++ "Out of memory (can't allocate %d bytes)!\n", ++ InstanceSize.ulApiInstanceSize); ++ return NULL; ++ } ++ ++ /* Perform the actual configuration of the chip. */ ++ wcxb_enable_echocan_dram(&wc->xb); ++ ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen); ++ if (ulResult != cOCT6100_ERR_OK) { ++ dev_info(&wc->xb.pdev->dev, "Unable to Oct6100ChipOpen: %x\n", ++ ulResult); ++ return NULL; ++ } ++ ++ /* OCT6100 is now booted and channels can be opened */ ++ /* Open 31 channels/span since we're skipping the first on the VPM */ ++ for (x = 0; x < numspans; x++) { ++ for (i = 0; i < 31; i++) { ++ ulResult = echocan_initialize_channel(vpm450m, ++ (x*32)+i, ++ laws[x]); ++ if (0 != ulResult) { ++ dev_info(&wc->xb.pdev->dev, ++ "Unable to echocan_initialize_channel: %d %x\n", ++ (x*32)+i, ulResult); ++ return NULL; ++ } else if (laws[x]) { ++ set_bit(FLAGBIT_ALAW, ++ &vpm450m->chanflags[(x*32)+i]); ++ } ++ } ++ } ++ ++ if (vpmsupport != 0) ++ wcxb_enable_echocan(&wc->xb); ++ ++ kfree(ChipOpen); ++ kfree(ChannelOpen); ++ return vpm450m; ++} ++ ++static void release_vpm450m(struct vpm450m *vpm450m) ++{ ++ UINT32 ulResult; ++ tOCT6100_CHIP_CLOSE ChipClose; ++ ++ Oct6100ChipCloseDef(&ChipClose); ++ ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose); ++ if (ulResult != cOCT6100_ERR_OK) ++ pr_notice("Failed to close chip, code %08x!\n", ulResult); ++ vfree(vpm450m->pApiInstance); ++ kfree(vpm450m); ++} ++ ++static const char *__t43x_echocan_name(struct t43x *wc) ++{ ++ if (wc->vpm) ++ return wc->vpm_name; ++ else ++ return NULL; ++} ++ ++static const char *t43x_echocan_name(const struct dahdi_chan *chan) ++{ ++ struct t43x *wc = chan->pvt; ++ return __t43x_echocan_name(wc); ++} ++ ++static int t43x_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ struct t43x *wc = chan->pvt; ++ struct t43x_span *ts = container_of(chan->span, struct t43x_span, span); ++ int channel = chan->chanpos - 1; ++ const bool alaw = (chan->span->deflaw == 2); ++ ++ if (!vpmsupport || !wc->vpm) ++ return -ENODEV; ++ ++ if (ecp->param_count > 0) { ++ dev_warn(&wc->xb.pdev->dev, ++ "%s echo canceller does not support parameters; failing request\n", ++ chan->ec_factory->get_name(chan)); ++ return -EINVAL; ++ } ++ ++ *ec = ts->ec[channel]; ++ (*ec)->ops = &vpm_ec_ops; ++ (*ec)->features = vpm_ec_features; ++ ++ channel += (32*chan->span->offset); ++ vpm450m_set_alaw_companding(wc->vpm, channel, alaw); ++ vpm450m_setec(wc->vpm, channel, ecp->tap_length); ++ return 0; ++} ++ ++static void echocan_free(struct dahdi_chan *chan, ++ struct dahdi_echocan_state *ec) ++{ ++ struct t43x *wc = chan->pvt; ++ int channel = chan->chanpos - 1; ++ if (!wc->vpm) ++ return; ++ memset(ec, 0, sizeof(*ec)); ++ channel += (32*chan->span->offset); ++ vpm450m_setec(wc->vpm, channel, 0); ++} ++ ++static void t43x_vpm_init(struct t43x *wc) ++{ ++ int laws[8] = {0, }; ++ int x; ++ ++ struct firmware embedded_firmware; ++ const struct firmware *firmware = &embedded_firmware; ++#if !defined(HOTPLUG_FIRMWARE) ++ extern void _binary_dahdi_fw_oct6114_064_bin_size; ++ extern u8 _binary_dahdi_fw_oct6114_064_bin_start[]; ++ extern void _binary_dahdi_fw_oct6114_128_bin_size; ++ extern u8 _binary_dahdi_fw_oct6114_128_bin_start[]; ++#else ++ static const char oct064_firmware[] = "dahdi-fw-oct6114-064.bin"; ++ static const char oct128_firmware[] = "dahdi-fw-oct6114-128.bin"; ++ const char *oct_firmware; ++#endif ++ ++ if (!vpmsupport) { ++ dev_info(&wc->xb.pdev->dev, "VPM450: Support Disabled\n"); ++ return; ++ } ++ ++#if defined(HOTPLUG_FIRMWARE) ++ if (wc->numspans == 2) { ++ wc->vpm_name = "VPMOCT064"; ++ oct_firmware = oct064_firmware; ++ } else { ++ wc->vpm_name = "VPMOCT128"; ++ oct_firmware = oct128_firmware; ++ } ++ if ((request_firmware(&firmware, oct_firmware, &wc->xb.pdev->dev) != 0) ++ || !firmware) { ++ dev_notice(&wc->xb.pdev->dev, ++ "VPM450: firmware %s not available from userspace\n", ++ oct_firmware); ++ return; ++ } ++#else ++ /* Yes... this is weird. objcopy gives us a symbol containing ++ the size of the firmware, not a pointer a variable containing ++ the size. The only way we can get the value of the symbol ++ is to take its address, so we define it as a pointer and ++ then cast that value to the proper type. ++ */ ++ if (wc->numspans == 2) { ++ embedded_firmware.data = _binary_dahdi_fw_oct6114_064_bin_start; ++ embedded_firmware.size = ++ (size_t)&_binary_dahdi_fw_oct6114_064_bin_size; ++ } else { ++ embedded_firmware.size = ++ (size_t)&_binary_dahdi_fw_oct6114_128_bin_size; ++ embedded_firmware.data = _binary_dahdi_fw_oct6114_128_bin_start; ++ } ++#endif ++ ++ /* Setup alaw vs ulaw rules */ ++ for (x = 0; x < wc->numspans; x++) { ++ if (wc->tspans[x]->span.channels > 24) ++ laws[x] = 1; ++ } ++ ++ wc->vpm = init_vpm450m(wc, laws, wc->numspans, firmware); ++ ++ if (!wc->vpm) { ++ dev_notice(&wc->xb.pdev->dev, "VPM450: Failed to initialize\n"); ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ return; ++ } ++ ++ if (firmware != &embedded_firmware) ++ release_firmware(firmware); ++ ++ dev_info(&wc->xb.pdev->dev, ++ "VPM450: Present and operational servicing %d span(s)\n", ++ wc->numspans); ++ ++} ++ ++static int t43x_clear_maint(struct dahdi_span *span); ++ ++static DEFINE_MUTEX(card_list_lock); ++static LIST_HEAD(card_list); ++ ++struct t43x_desc { ++ const char *name; ++}; ++ ++static const struct t43x_desc te435 = {"Wildcard TE435"}; /* pci express quad */ ++static const struct t43x_desc te235 = {"Wildcard TE235"}; /* pci express dual */ ++static const struct t43x_desc te436 = {"Wildcard TE436"}; /* pci quad */ ++static const struct t43x_desc te236 = {"Wildcard TE236"}; /* pci dual */ ++ ++static int __t43x_pci_get(struct t43x *wc, unsigned int addr) ++{ ++ unsigned int res = ioread8(wc->xb.membase + addr); ++ return res; ++} ++ ++static inline int __t43x_pci_set(struct t43x *wc, unsigned int addr, int val) ++{ ++ iowrite8(val, wc->xb.membase + addr); ++ __t43x_pci_get(wc, 0); ++ return 0; ++} ++ ++static inline int t43x_pci_get(struct t43x *wc, int addr) ++{ ++ unsigned int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ret = __t43x_pci_get(wc, addr); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return ret; ++} ++ ++static inline int t43x_pci_set(struct t43x *wc, int addr, int val) ++{ ++ unsigned long flags; ++ unsigned int ret; ++ spin_lock_irqsave(&wc->reglock, flags); ++ ret = __t43x_pci_set(wc, addr, val); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return ret; ++} ++ ++static inline int ++__t43x_framer_set(struct t43x *wc, int unit, int addr, int val) ++{ ++ return __t43x_pci_set(wc, FRAMER_BASE + (unit << 8) + addr, val); ++} ++ ++static inline int t43x_framer_set(struct t43x *wc, int unit, int addr, int val) ++{ ++ return t43x_pci_set(wc, FRAMER_BASE + (unit << 8) + addr, val); ++} ++ ++static inline int __t43x_framer_get(struct t43x *wc, int unit, int addr) ++{ ++ return __t43x_pci_get(wc, FRAMER_BASE + (unit << 8) + addr); ++} ++ ++static inline int t43x_framer_get(struct t43x *wc, int unit, int addr) ++{ ++ return t43x_pci_get(wc, FRAMER_BASE + (unit << 8) + addr); ++} ++ ++static void t43x_framer_reset(struct t43x *wc) ++{ ++ /* ++ * When the framer is reset, RCLK will stop. The FPGA must be switched ++ * to it's internal clock when this happens, but it's only safe to ++ * switch the clock source on the FPGA when the DMA engine is stopped. ++ * ++ */ ++ wcxb_stop_dma(&wc->xb); ++ wcxb_wait_for_stop(&wc->xb, 50); ++ wcxb_set_clksrc(&wc->xb, WCXB_CLOCK_SELF); ++ wcxb_gpio_clear(&wc->xb, FALC_CPU_RESET); ++ msleep_interruptible(100); ++ wcxb_gpio_set(&wc->xb, FALC_CPU_RESET); ++} ++ ++static void t43x_setleds(struct t43x *wc, u32 leds) ++{ ++ wcxb_gpio_set(&wc->xb, leds & LED_MASK); ++ wcxb_gpio_clear(&wc->xb, ~leds & LED_MASK); ++} ++ ++static void t43x_set_cas_mode(struct t43x *wc, int span_idx) ++{ ++ struct t43x_span *ts = wc->tspans[span_idx]; ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ int i, offset; ++ int reg; ++ unsigned long flags; ++ bool span_has_cas_channel = false; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s span: %d\n", __func__, ++ span_idx); ++ ++ if (dahdi_is_e1_span(&ts->span)) { ++ span_has_cas_channel = !(ts->span.lineconfig&DAHDI_CONFIG_CCS); ++ } else { ++ unsigned char ccb[3] = {0, 0, 0}; ++ /* Sort out channels that use CAS signalling */ ++ for (i = 0; i < ts->span.channels; i++) { ++ offset = i/8; ++ if (offset >= ARRAY_SIZE(ccb)) { ++ WARN_ON(1); ++ break; ++ } ++ if (ts->span.chans[i]->flags & DAHDI_FLAG_CLEAR) ++ ccb[offset] |= 1 << (7 - (i % 8)); ++ else ++ ccb[offset] &= ~(1 << (7 - (i % 8))); ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t43x_framer_set(wc, fidx, CCB1, ccb[0]); ++ __t43x_framer_set(wc, fidx, CCB2, ccb[1]); ++ __t43x_framer_set(wc, fidx, CCB3, ccb[2]); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if ((~ccb[0]) | (~ccb[1]) | (~ccb[2])) ++ span_has_cas_channel = true; ++ } ++ ++ /* Unmask CAS RX interrupt if any single channel is in CAS mode */ ++ /* This interrupt is called RSC in T1 and CASC in E1 */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, IMR0); ++ if (span_has_cas_channel) ++ __t43x_framer_set(wc, fidx, IMR0, reg & ~0x08); ++ else ++ __t43x_framer_set(wc, fidx, IMR0, reg | 0x08); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++/** ++ * _t43x_free_channels - Free the memory allocated for the channels. ++ * ++ * Must be called with wc->reglock held. ++ * ++ */ ++static void _t43x_free_channels(struct t43x *wc) ++{ ++ unsigned int x, y; ++ ++ for (x = 0; x < ARRAY_SIZE(wc->tspans); x++) { ++ if (!wc->tspans[x]) ++ continue; ++ for (y = 0; y < ARRAY_SIZE(wc->tspans[x]->chans); y++) { ++ kfree(wc->tspans[x]->chans[y]); ++ kfree(wc->tspans[x]->ec[y]); ++ } ++ kfree(wc->tspans[x]); ++ } ++} ++ ++static void free_wc(struct t43x *wc) ++{ ++ unsigned long flags; ++ LIST_HEAD(list); ++ ++ mutex_lock(&card_list_lock); ++ list_del(&wc->card_node); ++ mutex_unlock(&card_list_lock); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ _t43x_free_channels(wc); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ if (wc->wq) ++ destroy_workqueue(wc->wq); ++ kfree(wc->ddev->location); ++ kfree(wc->ddev->devicetype); ++ kfree(wc->ddev->hardware_id); ++ if (wc->ddev) ++ dahdi_free_device(wc->ddev); ++ kfree(wc); ++} ++ ++static void t43x_serial_setup(struct t43x *wc) ++{ ++ unsigned long flags; ++ int slot, fidx; ++ ++ dev_info(&wc->xb.pdev->dev, ++ "Setting up global serial parameters for card %d\n", wc->num); ++ ++ t43x_framer_reset(wc); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from ++ * channel 0 */ ++ __t43x_framer_set(wc, 0, 0x85, 0xe0); ++ /* GPC3: Enable Multi Purpose Switches */ ++ __t43x_framer_set(wc, 0, 0xd3, 0xa1); ++ /* GPC4: Enable Multi Purpose Switches */ ++ __t43x_framer_set(wc, 0, 0xd4, 0x83); ++ /* GPC5: Enable Multi Purpose Switches */ ++ __t43x_framer_set(wc, 0, 0xd5, 0xe5); ++ /* GPC4: Enable Multi Purpose Switches */ ++ __t43x_framer_set(wc, 0, 0xd6, 0x87); ++ /* IPC: Interrupt push/pull active low, 8KHz ref clk */ ++ __t43x_framer_set(wc, 0, 0x08, 0x05); ++ ++ /* Global clocks (8.192 Mhz CLK) */ ++ __t43x_framer_set(wc, 0, 0x92, 0x00); ++ __t43x_framer_set(wc, 0, 0x93, 0x18); ++ __t43x_framer_set(wc, 0, 0x94, 0xfb); ++ __t43x_framer_set(wc, 0, 0x95, 0x0b); ++ __t43x_framer_set(wc, 0, 0x96, 0x00); ++ __t43x_framer_set(wc, 0, 0x97, 0x0b); ++ __t43x_framer_set(wc, 0, 0x98, 0xdb); ++ __t43x_framer_set(wc, 0, 0x99, 0xdf); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ for (fidx = 0; fidx < 4; fidx++) { ++ /* For dual-span, put the second and third framers ++ * onto the first and second timeslots */ ++ if (wc->numspans == 2) ++ slot = (fidx - 1) & 3; ++ else ++ slot = fidx; ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ /* Configure interrupts */ ++ ++ /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ ++ __t43x_framer_set(wc, fidx, 0x46, 0xc0); ++ ++ /* Configure system interface */ ++ ++ /* SIC1: 8.192 Mhz clock/bus, double buffer receive / ++ * transmit, byte interleaved */ ++ __t43x_framer_set(wc, fidx, 0x3e, 0xc2); ++ /* SIC2: No FFS, no CRB, SSC2 = 0, phase = unit */ ++ __t43x_framer_set(wc, fidx, 0x3f, (slot << 1)); ++ ++ /* SIC3: Edges for capture - original rx rising edge */ ++ __t43x_framer_set(wc, fidx, 0x40, 0x04); ++ /* SIC4: CES high, SYPR opposite edge */ ++ __t43x_framer_set(wc, fidx, 0x2a, 0x06); ++ ++#ifndef RPC_RCLK ++ /* CMR1: RCLK is at 8.192 Mhz dejittered */ ++ __t43x_framer_set(wc, fidx, 0x44, 0x30); ++#else ++ /* CMR1: RCLK is at 8.192 Mhz dejittered, ref clock is this ++ * channel */ ++ __t43x_framer_set(wc, fidx, 0x44, 0x38 | (fidx << 6)); ++#endif ++ ++ /* CMR2: We provide sync and clock for tx and rx. */ ++ __t43x_framer_set(wc, fidx, 0x45, 0x00); ++ ++ /* XC0: Normal operation of Sa-bits */ ++ __t43x_framer_set(wc, fidx, 0x22, 0x07); ++ __t43x_framer_set(wc, fidx, 0x23, 0xfa); /* XC1 */ ++ ++ __t43x_framer_set(wc, fidx, 0x24, 0x07); /* RC0 */ ++ __t43x_framer_set(wc, fidx, 0x25, 0xfa); /* RC1 */ ++ ++ /* Configure ports */ ++ /* PC1: SPYR/SPYX input on RPA/XPA */ ++ __t43x_framer_set(wc, fidx, 0x80, 0x00); ++ /* PC2: Unused stuff */ ++ __t43x_framer_set(wc, fidx, 0x81, 0xBB); ++#ifndef RPC_RCLK ++ /* PC3: Unused stuff */ ++ __t43x_framer_set(wc, fidx, 0x82, 0xBB); ++#else ++ /* PC3: RPC is RCLK, XPC is low output */ ++ __t43x_framer_set(wc, fidx, 0x82, 0xFB); ++#endif ++ /* PC4: Unused stuff */ ++ __t43x_framer_set(wc, fidx, 0x83, 0xBB); ++ /* PC5: XMFS active low, SCLKR is input, RCLK is output */ ++ __t43x_framer_set(wc, fidx, 0x84, 0x01); ++ __t43x_framer_set(wc, fidx, 0x3b, 0x00); /* Clear LCR1 */ ++ ++ /* Make sure unused ports are set to T1 configuration as a ++ * default. This is required in order to make clock recovery ++ * works on spans that are actually configured. */ ++ ++ __t43x_framer_set(wc, fidx, 0x1c, 0xf0); ++ __t43x_framer_set(wc, fidx, 0x1d, 0x9c); ++ __t43x_framer_set(wc, fidx, 0x1e, 0x20); ++ __t43x_framer_set(wc, fidx, 0x20, 0x0c); ++ /* FMR5: Enable RBS mode */ ++ __t43x_framer_set(wc, fidx, 0x21, 0x40); ++ ++ __t43x_framer_set(wc, fidx, 0x36, 0x08); ++ __t43x_framer_set(wc, fidx, 0x37, 0xf0); ++ __t43x_framer_set(wc, fidx, 0x3a, 0x21); ++ ++ __t43x_framer_set(wc, fidx, 0x02, 0x50); ++ __t43x_framer_set(wc, fidx, 0x02, 0x00); ++ ++ __t43x_framer_set(wc, fidx, 0x38, 0x0a); ++ __t43x_framer_set(wc, fidx, 0x39, 0x15); ++ /* Tri-state the TX output for the port */ ++ __t43x_framer_set(wc, fidx, 0x28, 0x40); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++} ++ ++/** ++ * t43x_span_assigned - Called when the span is assigned by DAHDI. ++ * @span: Span that has been assigned. ++ * ++ * When this function is called, the span has a valid spanno and all the ++ * channels on the span have valid channel numbers assigned. ++ * ++ * This function is necessary because a device may be registered, and ++ * then user space may then later decide to assign span numbers and the ++ * channel numbers. ++ * ++ */ ++static void t43x_span_assigned(struct dahdi_span *span) ++{ ++ struct t43x_span *tspan = container_of(span, struct t43x_span, span); ++ struct t43x *wc = tspan->owner; ++ struct dahdi_span *pos; ++ unsigned int unassigned_spans = 0; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s\n", __func__); ++ ++ span->alarms = DAHDI_ALARM_NONE; ++ ++ /* We use this to make sure all the spans are assigned before ++ * running the serial setup. */ ++ list_for_each_entry(pos, &wc->ddev->spans, device_node) { ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &pos->flags)) ++ ++unassigned_spans; ++ } ++ ++ if (0 == unassigned_spans) { ++ /* Now all the spans are assigned so we can go ahead and start ++ * things up. */ ++ t43x_serial_setup(wc); ++ } ++} ++ ++static int syncsrc; ++static int syncnum; ++static int syncspan; ++static DEFINE_SPINLOCK(synclock); ++ ++static void __t43x_set_rclk_src(struct t43x *wc, int span) ++{ ++#ifndef RPC_RCLK ++ int cmr1 = 0x38; /* Clock Mode: RCLK sourced by DCO-R1 ++ by default, Disable Clock-Switching */ ++ int fidx; ++ ++ if (2 == wc->numspans) { ++ u8 reg; ++ ++ /* Since the clock always comes from the first span (which is ++ * not connected to a physical port on the dual span) we can ++ * always set the framer mode register to match whatever span ++ * we're currently sourcing the timing from. This ensures that ++ * the DCO-R is always expecting the right clock speed from the ++ * line. */ ++ ++ fidx = span+1; ++ ++ reg = __t43x_framer_get(wc, fidx, 0x1d); ++ __t43x_framer_set(wc, 0, 0x1d, reg); ++ ++ reg = __t43x_framer_get(wc, fidx, 0x1e); ++ __t43x_framer_set(wc, 0, 0x1e, reg); ++ ++ } else { ++ fidx = span; ++ } ++ ++ cmr1 |= (fidx) << 6; ++ __t43x_framer_set(wc, 0, 0x44, cmr1); ++#else ++ int fidx = (2 == wc->numspans) ? span+1 : span; ++ int gpc1 = __t43x_framer_get(wc, 0, 0x85); ++ ++ gpc1 &= ~3; ++ gpc1 |= fidx & 3; ++ ++ t43x_framer_set(wc, 0, 0x85, gpc1); ++#endif ++ dev_info(&wc->xb.pdev->dev, "RCLK source set to span %d\n", span+1); ++} ++ ++/* This is called from the workqueue to wait for the TDM engine stop */ ++ ++static void t43x_clksrc_work_fn(struct work_struct *data) ++{ ++ struct t43x_clksrc_work *work = container_of(data, ++ struct t43x_clksrc_work, work.work); ++ struct t43x *wc = container_of(work, struct t43x, clksrc_work); ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "t43x_clksrc_work() called from queue\n"); ++ } ++ ++ if (wcxb_is_stopped(&wc->xb)) { ++ ++ /* Set new clock select */ ++ if (work->is_timing_master) ++ wcxb_enable_timing_header_driver(&wc->xb); ++ else ++ wcxb_disable_timing_header_driver(&wc->xb); ++ wcxb_set_clksrc(&wc->xb, work->clksrc); ++ ++ /* Restart DMA processing */ ++ wcxb_start(&wc->xb); ++ } else { ++ /* Stop DMA again in case DMA underrun int restarted it */ ++ wcxb_stop_dma(&wc->xb); ++ queue_delayed_work(wc->wq, &work->work, msecs_to_jiffies(10)); ++ } ++} ++ ++/** ++ * __t43x_set_sclk_src - Change the current source of the source clock. ++ * @wc: The board to change the clock source on. ++ * @mode: The clock mode that we would like to move to. ++ * @master: If true, drive the clock on the timing header. ++ * ++ * The clock source cannot be changed while DMA is active, so this function ++ * will stop the DMA, then queue a delayed work item in order to come back and ++ * check that DMA was actually stopped before changing the source of the clock. ++ * ++ */ ++static void ++__t43x_set_sclk_src(struct t43x *wc, enum wcxb_clock_sources mode, bool master) ++{ ++ struct t43x_clksrc_work *const work = &wc->clksrc_work; ++ unsigned long flags; ++ bool changed = false; ++ ++ /* Cannot drive the clock on the header while also slaving from it. */ ++ WARN_ON(master && (mode == WCXB_CLOCK_SLAVE)); ++ ++ spin_lock_irqsave(&work->lock, flags); ++ if (!delayed_work_pending(&work->work)) { ++ /* We want to check the actual settings. */ ++ changed = (wcxb_get_clksrc(&wc->xb) != mode) || ++ (wcxb_is_timing_header_driver_enabled(&wc->xb) != master); ++ } else { ++ /* Otherwise, we'll check if delayed work is going to set it to ++ * the same value. */ ++ ++ changed = (work->clksrc != mode) || ++ (work->is_timing_master != master); ++ } ++ if (changed) { ++ work->clksrc = mode; ++ work->is_timing_master = master; ++ } ++ spin_unlock_irqrestore(&work->lock, flags); ++ ++ if (!changed) { ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "Clock source is unchanged\n"); ++ return; ++ } ++ ++ wcxb_stop_dma(&wc->xb); ++ ++ dev_dbg(&wc->xb.pdev->dev, ++ "Queueing delayed work for clock source change\n"); ++ ++ queue_delayed_work(wc->wq, &work->work, msecs_to_jiffies(10)); ++} ++ ++static ssize_t t43x_timing_master_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct t43x *wc = dev_get_drvdata(dev); ++ ++ if (wcxb_is_timing_header_driver_enabled(&wc->xb)) ++ return sprintf(buf, "%d\n", wc->syncsrc); ++ else ++ return sprintf(buf, "%d\n", -1); ++} ++ ++static DEVICE_ATTR(timing_master, 0400, t43x_timing_master_show, NULL); ++ ++static void create_sysfs_files(struct t43x *wc) ++{ ++ int ret; ++ ret = device_create_file(&wc->xb.pdev->dev, ++ &dev_attr_timing_master); ++ if (ret) { ++ dev_info(&wc->xb.pdev->dev, ++ "Failed to create device attributes.\n"); ++ } ++} ++ ++static void remove_sysfs_files(struct t43x *wc) ++{ ++ device_remove_file(&wc->xb.pdev->dev, &dev_attr_timing_master); ++} ++ ++static inline void __t43x_update_timing(struct t43x *wc) ++{ ++ int i; ++ ++ /* update sync src info */ ++ if (wc->syncsrc != syncsrc) { ++ dev_info(&wc->xb.pdev->dev, "Swapping card %d from %d to %d\n", ++ wc->num, wc->syncsrc, syncsrc); ++ wc->syncsrc = syncsrc; ++ /* Update sync sources */ ++ for (i = 0; i < wc->numspans; i++) ++ wc->tspans[i]->span.syncsrc = wc->syncsrc; ++ if (syncnum == wc->num) { ++ __t43x_set_rclk_src(wc, syncspan-1); ++ __t43x_set_sclk_src(wc, WCXB_CLOCK_RECOVER, 1); ++ if (debug) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Card %d, using sync span %d, master\n", ++ wc->num, syncspan); ++ } ++ } else { ++ __t43x_set_sclk_src(wc, WCXB_CLOCK_SLAVE, 0); ++ if (debug) { ++ dev_notice(&wc->xb.pdev->dev, ++ "Card %d, using Timing Bus, NOT master\n", ++ wc->num); ++ } ++ } ++ } ++} ++ ++static int __t43x_findsync(struct t43x *wc) ++{ ++ int i; ++ unsigned long flags; ++ int p; ++ int nonzero; ++ int newsyncsrc = 0; /* DAHDI span number */ ++ int newsyncnum = 0; /* wct4xxp card number */ ++ int newsyncspan = 0; /* span on given wct4xxp card */ ++ struct t43x *cur; ++ ++ spin_lock_irqsave(&synclock, flags); ++ if (!wc->num) { ++ /* If we're the first card, go through all the motions, up to 8 ++ * levels of sync source */ ++ p = 1; ++ while (p < 8) { ++ nonzero = 0; ++ list_for_each_entry(cur, &card_list, card_node) { ++ for (i = 0; i < cur->numspans; i++) { ++ struct t43x_span *const ts = ++ cur->tspans[i]; ++ struct dahdi_span *const s = ++ &cur->tspans[i]->span; ++ if (!ts->syncpos) ++ continue; ++ nonzero = 1; ++ if ((ts->syncpos == p) && ++ !(s->alarms & NOSYNC_ALARMS) && ++ (s->flags & DAHDI_FLAG_RUNNING)) { ++ /* This makes a good sync ++ * source */ ++ newsyncsrc = s->spanno; ++ newsyncnum = cur->num; ++ newsyncspan = i + 1; ++ /* Jump out */ ++ goto found; ++ } ++ } ++ } ++ if (nonzero) ++ p++; ++ else ++ break; ++ } ++found: ++ if ((syncnum != newsyncnum) || ++ (syncsrc != newsyncsrc) || ++ (newsyncspan != syncspan)) { ++ if (debug) { ++ dev_notice(&wc->xb.pdev->dev, ++ "New syncnum: %d (was %d), syncsrc: %d (was %d), syncspan: %d (was %d)\n", ++ newsyncnum, syncnum, newsyncsrc, ++ syncsrc, newsyncspan, syncspan); ++ } ++ syncnum = newsyncnum; ++ syncsrc = newsyncsrc; ++ syncspan = newsyncspan; ++ nonzero = 0; ++ list_for_each_entry(cur, &card_list, card_node) ++ __t43x_update_timing(cur); ++ } ++ } ++ __t43x_update_timing(wc); ++ spin_unlock_irqrestore(&synclock, flags); ++ return 0; ++} ++ ++static void __t43x_set_timing_source_auto(struct t43x *wc) ++{ ++ int x, i; ++ int firstprio, secondprio; ++ firstprio = secondprio = 4; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "timing source auto\n"); ++ ++ if (timingcable) { ++ __t43x_findsync(wc); ++ } else { ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, ++ "Evaluating spans for timing source\n"); ++ for (x = 0; x < wc->numspans; x++) { ++ if ((wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) && ++ !(wc->tspans[x]->span.alarms & (DAHDI_ALARM_RED | ++ DAHDI_ALARM_BLUE))) { ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "span %d is green : syncpos %d\n", ++ x+1, wc->tspans[x]->syncpos); ++ } ++ if (wc->tspans[x]->syncpos) { ++ /* Valid rsync source in recovered ++ timing mode */ ++ if (firstprio == 4) ++ firstprio = x; ++ else if (wc->tspans[x]->syncpos < ++ wc->tspans[firstprio]->syncpos) ++ firstprio = x; ++ } else { ++ /* Valid rsync source in system timing ++ mode */ ++ if (secondprio == 4) ++ secondprio = x; ++ } ++ } ++ } ++ if (firstprio != 4) { ++ wc->syncsrc = firstprio; ++ __t43x_set_rclk_src(wc, firstprio); ++ __t43x_set_sclk_src(wc, WCXB_CLOCK_RECOVER, 0); ++ dev_info(&wc->xb.pdev->dev, ++ "Recovered timing mode, RCLK set to span %d\n", ++ firstprio+1); ++ } else if (secondprio != 4) { ++ wc->syncsrc = -1; ++ __t43x_set_rclk_src(wc, secondprio); ++ __t43x_set_sclk_src(wc, WCXB_CLOCK_SELF, 0); ++ dev_info(&wc->xb.pdev->dev, ++ "System timing mode, RCLK set to span %d\n", ++ secondprio+1); ++ } else { ++ wc->syncsrc = -1; ++ dev_info(&wc->xb.pdev->dev, ++ "All spans in alarm : No valid span to source RCLK from\n"); ++ /* Default rclk to lock with span 1 */ ++ __t43x_set_rclk_src(wc, 0); ++ __t43x_set_sclk_src(wc, WCXB_CLOCK_SELF, 0); ++ } ++ ++ /* Propagate sync selection to dahdi_span struct ++ * this is read by dahdi_tool to display the span's ++ * master/slave sync information */ ++ for (i = 0; i < wc->numspans; i++) ++ wc->tspans[i]->span.syncsrc = wc->syncsrc + 1; ++ } ++} ++ ++static void ++t43x_configure_t1(struct t43x *wc, int span_idx, int lineconfig, int txlevel) ++{ ++ struct t43x_span *ts = wc->tspans[span_idx]; ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ unsigned int fmr4, fmr2, fmr1, fmr0, lim2; ++ char *framing, *line; ++ int mytxlevel, reg; ++ unsigned long flags; ++ ++ if ((txlevel > 7) || (txlevel < 4)) ++ mytxlevel = 0; ++ else ++ mytxlevel = txlevel - 4; ++ ++ /* FMR1: Mode 0, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, ++ * no XAIS */ ++ fmr1 = 0x9c; ++ /* FMR2: no payload loopback, don't auto yellow alarm */ ++ fmr2 = 0x20; ++ ++ if (SPANTYPE_DIGITAL_J1 == ts->span.spantype) { ++ fmr4 = 0x1c; ++ } else { ++ /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ ++ fmr4 = 0x0c; ++ } ++ ++ /* LIM2: 50% peak is a "1", Advanced Loss Recovery, Multi Purpose ++ * Analog Switch enabled */ ++ lim2 = 0x23; ++ /* LIM2: Add line buildout */ ++ lim2 |= (mytxlevel << 6); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ __t43x_framer_set(wc, fidx, 0x1d, fmr1); ++ __t43x_framer_set(wc, fidx, 0x1e, fmr2); ++ ++ /* Configure line interface */ ++ if (lineconfig & DAHDI_CONFIG_AMI) { ++ line = "AMI"; ++ /* WCT4XX has workaround for errata fmr0 = 0xb0 */ ++ /* was fmr0 = 0xa0; */ ++ fmr0 = 0xb0; ++ } else { ++ line = "B8ZS"; ++ fmr0 = 0xf0; ++ } ++ if (lineconfig & DAHDI_CONFIG_D4) { ++ framing = "D4"; ++ } else { ++ framing = "ESF"; ++ fmr4 |= 0x2; ++ fmr2 |= 0xc0; ++ } ++ ++ /* Suppress RSC interrupt for cleared channels */ ++ __t43x_framer_set(wc, fidx, 0x09, 0x80); ++ __t43x_framer_set(wc, fidx, 0x1c, fmr0); ++ ++ __t43x_framer_set(wc, fidx, 0x20, fmr4); ++ /* FMR5: Enable RBS mode */ ++ __t43x_framer_set(wc, fidx, 0x21, 0x40); ++ ++ /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No ++ * remote loop, no DRS */ ++ __t43x_framer_set(wc, fidx, 0x37, 0xf0); ++ /* LIM0: Enable auto long haul mode, no local loop (set after LIM1) */ ++ __t43x_framer_set(wc, fidx, 0x36, 0x08); ++ ++ /* CMDR: Reset the receiver and transmitter line interface */ ++ __t43x_framer_set(wc, fidx, 0x02, 0x50); ++ /* CMDR: Reset the receiver and transmitter line interface */ ++ __t43x_framer_set(wc, fidx, 0x02, 0x00); ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, ++ "card %d span %d: setting Rtx to 0ohm for T1\n", ++ wc->num, span_idx); ++ } ++ /* PC6: set Rtx to 0ohm for T1 */ ++ __t43x_framer_set(wc, fidx, 0x86, 0x00); ++ ++ /* Bugfix register for errata #3 */ ++ __t43x_framer_set(wc, fidx, 0xbd, 0x05); ++ ++ /* LIM2: 50% peak amplitude is a "1" */ ++ __t43x_framer_set(wc, fidx, 0x3a, lim2); ++ /* PCD: LOS after 176 consecutive "zeros" */ ++ __t43x_framer_set(wc, fidx, 0x38, 0x0a); ++ /* PCR: 22 "ones" clear LOS */ ++ __t43x_framer_set(wc, fidx, 0x39, 0x15); ++ ++ reg = __t43x_framer_get(wc, fidx, 0x24); ++ if (SPANTYPE_DIGITAL_J1 == ts->span.spantype) { ++ /* set J1 overide */ ++ __t43x_framer_set(wc, fidx, 0x24, reg | 0x80); ++ } else { ++ /* clear J1 overide */ ++ __t43x_framer_set(wc, fidx, 0x24, reg & ~0x80); ++ } ++ ++ /* Generate pulse mask for T1 */ ++ switch (mytxlevel) { ++ case 3: ++ __t43x_framer_set(wc, fidx, 0x26, 0x07); /* XPM0 */ ++ __t43x_framer_set(wc, fidx, 0x27, 0x01); /* XPM1 */ ++ __t43x_framer_set(wc, fidx, 0x28, 0x00); /* XPM2 */ ++ break; ++ case 2: ++ __t43x_framer_set(wc, fidx, 0x26, 0x8c); /* XPM0 */ ++ __t43x_framer_set(wc, fidx, 0x27, 0x11); /* XPM1 */ ++ __t43x_framer_set(wc, fidx, 0x28, 0x01); /* XPM2 */ ++ break; ++ case 1: ++ __t43x_framer_set(wc, fidx, 0x26, 0x8c); /* XPM0 */ ++ __t43x_framer_set(wc, fidx, 0x27, 0x01); /* XPM1 */ ++ __t43x_framer_set(wc, fidx, 0x28, 0x00); /* XPM2 */ ++ break; ++ case 0: ++ default: ++ __t43x_framer_set(wc, fidx, 0x26, 0x1a); /* XPM0 */ ++ __t43x_framer_set(wc, fidx, 0x27, 0x27); /* XPM1 */ ++ __t43x_framer_set(wc, fidx, 0x28, 0x01); /* XPM2 */ ++ break; ++ } ++ ++ __t43x_framer_set(wc, fidx, 0x14, 0xff); /* IMR0 */ ++ __t43x_framer_set(wc, fidx, 0x15, 0xff); /* IMR1 */ ++ ++ /* IMR2: All the alarms */ ++ __t43x_framer_set(wc, fidx, 0x16, 0x00); ++ /* IMR3: ES, SEC, LLBSC, rx slips */ ++ __t43x_framer_set(wc, fidx, 0x17, 0x34); ++ /* IMR4: Slips on transmit */ ++ __t43x_framer_set(wc, fidx, 0x18, 0x3f); ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dev_info(&wc->xb.pdev->dev, "Span %d configured for %s/%s\n", ++ span_idx, framing, line); ++} ++ ++static void t43x_configure_e1(struct t43x *wc, int span_idx, int lineconfig) ++{ ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ unsigned int fmr2, fmr1, fmr0; ++ unsigned int cas = 0; ++ unsigned int imr3extra = 0; ++ char *crc4 = ""; ++ char *framing, *line; ++ unsigned long flags; ++ ++ fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, ++ 8.192 Mhz backplane, no XAIS */ ++ fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of ++ multiframe recovery, no payload loopback */ ++ ++ if (lineconfig & DAHDI_CONFIG_CRC4) { ++ fmr1 |= 0x08; /* CRC4 transmit */ ++ fmr2 |= 0xc0; /* CRC4 receive */ ++ crc4 = "/CRC4"; ++ } ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ ++ __t43x_framer_set(wc, fidx, 0x1d, fmr1); ++ __t43x_framer_set(wc, fidx, 0x1e, fmr2); ++ ++ /* Configure line interface */ ++ if (lineconfig & DAHDI_CONFIG_AMI) { ++ line = "AMI"; ++ /* workaround for errata #2 in ES v3 09-10-16 */ ++ fmr0 = 0xb0; ++ } else { ++ line = "HDB3"; ++ fmr0 = 0xf0; ++ } ++ ++ if (lineconfig & DAHDI_CONFIG_CCS) { ++ framing = "CCS"; ++ imr3extra = 0x28; ++ } else { ++ framing = "CAS"; ++ cas = 0x40; ++ } ++ ++ __t43x_framer_set(wc, fidx, 0x1c, fmr0); ++ ++ /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No ++ * remote loop, no DRS */ ++ __t43x_framer_set(wc, fidx, 0x37, 0xf0); ++ /* LIM0: Enable auto long haul mode, no local loop (must be after ++ * LIM1) */ ++ __t43x_framer_set(wc, fidx, 0x36, 0x08); ++ ++ /* CMDR: Reset the receiver and transmitter line interface */ ++ __t43x_framer_set(wc, fidx, 0x02, 0x50); ++ /* CMDR: Reset the receiver and transmitter line interface */ ++ __t43x_framer_set(wc, fidx, 0x02, 0x00); ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, ++ "setting Rtx to 7.5ohm for E1\n"); ++ /* PC6: turn on 7.5ohm Rtx for E1 */ ++ __t43x_framer_set(wc, fidx, 0x86, 0x40); ++ ++ /* Condition receive line interface for E1 after reset */ ++ __t43x_framer_set(wc, fidx, 0xbb, 0x17); ++ __t43x_framer_set(wc, fidx, 0xbc, 0x55); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x97); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x11); ++ __t43x_framer_set(wc, fidx, 0xbc, 0xaa); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x91); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x12); ++ __t43x_framer_set(wc, fidx, 0xbc, 0x55); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x92); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x0c); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x00); ++ __t43x_framer_set(wc, fidx, 0xbb, 0x8c); ++ ++ /* LIM2: 50% peak amplitude isa "1", Multi Purpose Analog Switch ++ * enabled */ ++ __t43x_framer_set(wc, fidx, 0x3a, 0x22); ++ ++ /* PCD: LOS after 176 consecutive "zeros" */ ++ __t43x_framer_set(wc, fidx, 0x38, 0x0a); ++ /* PCR: 22 "ones" clear LOS */ ++ __t43x_framer_set(wc, fidx, 0x39, 0x15); ++ ++ /* XSW: Spare bits all to 1 */ ++ __t43x_framer_set(wc, fidx, 0x20, 0x9f); ++ /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ ++ __t43x_framer_set(wc, fidx, 0x21, 0x1c|cas); ++ ++ /* Generate pulse mask for E1 */ ++ __t43x_framer_set(wc, fidx, 0x26, 0xb5); /* XPM0 */ ++ __t43x_framer_set(wc, fidx, 0x27, 0x02); /* XPM1 */ ++ __t43x_framer_set(wc, fidx, 0x28, 0x00); /* XPM2 */ ++ ++ __t43x_framer_set(wc, fidx, 0x14, 0xff); /* IMR0 */ ++ __t43x_framer_set(wc, fidx, 0x15, 0xff); /* IMR1 */ ++ ++ __t43x_framer_set(wc, fidx, 0x16, 0x00); /* IMR2: the alarm stuff! */ ++ __t43x_framer_set(wc, fidx, 0x17, 0x04 | imr3extra); /* IMR3: AIS */ ++ __t43x_framer_set(wc, fidx, 0x18, 0x3f); /* IMR4: slips on transmit */ ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dev_info(&wc->xb.pdev->dev, "Span configured for %s/%s%s\n", ++ framing, line, crc4); ++} ++ ++static bool have_open_channels(const struct t43x_span *ts) ++{ ++ int x, j; ++ for (x = 0, j = 0; x < ts->span.channels; x++) { ++ const struct dahdi_chan *chan = ts->span.chans[x]; ++ if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags) || ++ dahdi_have_netdev(chan)) ++ return true; ++ } ++ return false; ++} ++ ++static void t43x_framer_start(struct t43x *wc) ++{ ++ int unit; ++ unsigned long flags; ++ int res; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s\n", __func__); ++ ++ /* Disable fpga hardware interrupts */ ++ wcxb_disable_interrupts(&wc->xb); ++ ++ /* Disable DMA */ ++ wcxb_stop_dma(&wc->xb); ++ res = wcxb_wait_for_stop(&wc->xb, 50); ++ if (res) ++ dev_warn(&wc->xb.pdev->dev, "DMA engine did not stop.\n"); ++ ++ for (unit = 0; unit < wc->numspans; unit++) { ++ struct t43x_span *ts = wc->tspans[unit]; ++ if (dahdi_is_e1_span(&ts->span)) { ++ t43x_configure_e1(wc, unit, ts->span.lineconfig); ++ } else { /* is a T1 card */ ++ t43x_configure_t1(wc, unit, ts->span.lineconfig, ++ ts->span.txlevel); ++ } ++ t43x_set_cas_mode(wc, unit); ++ ++ set_bit(DAHDI_FLAGBIT_RUNNING, &ts->span.flags); ++ ++ /* Reset span alarm state to RED to prevent false ++ * temporary GREEN state on span bringup */ ++ ts->span.alarms |= DAHDI_ALARM_RED; ++ } ++ ++ for (unit = 0; unit < wc->numspans; unit++) { ++ /* Get this party started */ ++ struct t43x_span *ts = wc->tspans[unit]; ++ ++ /* Check for "open channels" here in case some channels have ++ * netdev. */ ++ if (have_open_channels(ts)) ++ clear_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags); ++ else ++ set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags); ++ ++ local_irq_save(flags); ++ t43x_check_alarms(wc, unit); ++ t43x_check_sigbits(wc, unit); ++ local_irq_restore(flags); ++ } ++ ++ dev_info(&wc->xb.pdev->dev, "Enabling DMA controller and interrupts\n"); ++ ++ /* start interrupts and DMA processing */ ++ wcxb_start(&wc->xb); ++ ++ t43x_check_for_interrupts(wc); ++ ++ /* force re-evaluation of timing source */ ++ wc->syncsrc = -1; ++ spin_lock_irqsave(&wc->reglock, flags); ++ __t43x_set_timing_source_auto(wc); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ /* Clear all counters */ ++ for (unit = 0; unit < wc->numspans; unit++) { ++ struct t43x_span *ts = wc->tspans[unit]; ++ memset(&ts->span.count, 0, sizeof(ts->span.count)); ++ } ++ ++ /* Invoke timer function to set leds */ ++ mod_timer(&wc->timer, jiffies); ++} ++ ++#ifndef RPC_RCLK ++/** ++ * t43x_check_spanconfig - Return 0 if the span configuration is valid. ++ * @wc - The card to check. ++ * ++ * The TE435 cannot sync timing from a span in a different line mode than the ++ * first span. This function should be called after the spans are configured to ++ * ensure that the are not configured in this mode. ++ * ++ */ ++static int t43x_check_spanconfig(const struct t43x *wc) ++{ ++ unsigned int i; ++ bool span_1_is_e1; ++ ++ if (&te435 != wc->devtype) ++ return 0; ++ ++ span_1_is_e1 = dahdi_is_e1_span(&wc->tspans[0]->span); ++ ++ for (i = 1; i < wc->numspans; ++i) { ++ struct t43x_span *ts = wc->tspans[i]; ++ ++ /* We only need to check spans that we could be a sync source */ ++ if (!ts->syncpos) ++ continue; ++ ++ if ((bool)dahdi_is_e1_span(&ts->span) == span_1_is_e1) ++ continue; ++ ++ dev_warn(&wc->xb.pdev->dev, ++ "Local span %d is configured as a sync source but the line mode does not match local span 1.\n", ++ ts->span.offset + 1); ++ dev_warn(&wc->xb.pdev->dev, ++ "Please configure local span 1 as a sync src and ensure all other local sync sources match the line config of span 1.\n"); ++ ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++#endif ++ ++static int t43x_startup(struct file *file, struct dahdi_span *span) ++{ ++ struct t43x_span *ts = container_of(span, struct t43x_span, span); ++ struct t43x *wc = ts->owner; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s\n", __func__); ++ ++#ifndef RPC_RCLK ++ if (t43x_check_spanconfig(wc)) ++ return -EINVAL; ++#endif ++ ++ /* Reset framer with proper parameters and start */ ++ dev_info(&wc->xb.pdev->dev, ++ "Calling startup (flags is %lu)\n", span->flags); ++ t43x_framer_start(wc); ++ ++ return 0; ++} ++ ++static inline bool is_initialized(struct t43x *wc) ++{ ++ WARN_ON(wc->not_ready < 0); ++ return (wc->not_ready == 0); ++} ++ ++/** ++ * t43x_wait_for_ready ++ * ++ * Check if the board has finished any setup and is ready to start processing ++ * calls. ++ */ ++static int t43x_wait_for_ready(struct t43x *wc) ++{ ++ while (!is_initialized(wc)) { ++ if (fatal_signal_pending(current)) ++ return -EIO; ++ msleep_interruptible(250); ++ } ++ return 0; ++} ++ ++static int t43x_chanconfig(struct file *file, ++ struct dahdi_chan *chan, int sigtype) ++{ ++ struct t43x *wc = chan->pvt; ++ ++ if (file->f_flags & O_NONBLOCK && !is_initialized(wc)) ++ return -EAGAIN; ++ else ++ t43x_wait_for_ready(wc); ++ ++ if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags)) ++ t43x_set_cas_mode(wc, chan->span->offset); ++ return 0; ++} ++ ++static int t43x_rbsbits(struct dahdi_chan *chan, int bits) ++{ ++ u_char m, c; ++ int n, b; ++ struct t43x *wc = chan->pvt; ++ struct t43x_span *ts = container_of(chan->span, struct t43x_span, span); ++ int fidx = (2 == wc->numspans) ? ++ chan->span->offset+1 : chan->span->offset; ++ unsigned long flags; ++ ++ if (dahdi_is_e1_span(&ts->span)) { /* do it E1 way */ ++ if (chan->chanpos == 16) ++ return 0; ++ ++ n = chan->chanpos - 1; ++ if (chan->chanpos > 15) ++ n--; ++ b = (n % 15); ++ spin_lock_irqsave(&wc->reglock, flags); ++ c = ts->txsigs[b]; ++ m = (n / 15) << 2; /* nibble selector */ ++ c &= (0xf << m); /* keep the other nibble */ ++ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ ++ ts->txsigs[b] = c; ++ /* output them to the chip */ ++ __t43x_framer_set(wc, fidx, 0x71 + b, c); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) { ++ n = chan->chanpos - 1; ++ b = (n / 4); ++ spin_lock_irqsave(&wc->reglock, flags); ++ c = ts->txsigs[b]; ++ m = ((3 - (n % 4)) << 1); /* nibble selector */ ++ c &= ~(0x3 << m); /* keep the other nibble */ ++ c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ ++ ts->txsigs[b] = c; ++ /* output them to the chip */ ++ __t43x_framer_set(wc, fidx, 0x70 + b, c); ++ __t43x_framer_set(wc, fidx, 0x70 + b + 6, c); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } else if (ts->span.lineconfig & DAHDI_CONFIG_ESF) { ++ n = chan->chanpos - 1; ++ b = (n / 2); ++ spin_lock_irqsave(&wc->reglock, flags); ++ c = ts->txsigs[b]; ++ m = ((n % 2) << 2); /* nibble selector */ ++ c &= (0xf << m); /* keep the other nibble */ ++ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ ++ ts->txsigs[b] = c; ++ /* output them to the chip */ ++ __t43x_framer_set(wc, fidx, 0x70 + b, c); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ } ++ ++ return 0; ++} ++ ++static inline void t43x_dahdi_rbsbits(struct dahdi_chan *c, const int rxs) ++{ ++ if (!(c->sig & DAHDI_SIG_CLEAR) && (c->rxsig != rxs)) ++ dahdi_rbsbits(c, rxs); ++} ++ ++static void t43x_check_sigbits(struct t43x *wc, int span_idx) ++{ ++ int a, i, rxs; ++ struct t43x_span *ts = wc->tspans[span_idx]; ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ ++ if (dahdi_is_e1_span(&ts->span)) { ++ for (i = 0; i < 15; i++) { ++ a = t43x_framer_get(wc, fidx, 0x71 + i); ++ rxs = (a & 0xf); ++ t43x_dahdi_rbsbits(ts->span.chans[i+16], rxs); ++ ++ rxs = (a >> 4) & 0xf; ++ t43x_dahdi_rbsbits(ts->span.chans[i], rxs); ++ } ++ } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) { ++ for (i = 0; i < 24; i += 4) { ++ a = t43x_framer_get(wc, fidx, 0x70 + (i>>2)); ++ rxs = (a & 0x3) << 2; ++ t43x_dahdi_rbsbits(ts->span.chans[i+3], rxs); ++ ++ rxs = (a & 0xc); ++ t43x_dahdi_rbsbits(ts->span.chans[i+2], rxs); ++ ++ rxs = (a >> 2) & 0xc; ++ t43x_dahdi_rbsbits(ts->span.chans[i+1], rxs); ++ ++ rxs = (a >> 4) & 0xc; ++ t43x_dahdi_rbsbits(ts->span.chans[i], rxs); ++ } ++ } else { ++ for (i = 0; i < 24; i += 2) { ++ a = t43x_framer_get(wc, fidx, 0x70 + (i>>1)); ++ rxs = (a & 0xf); ++ t43x_dahdi_rbsbits(ts->span.chans[i+1], rxs); ++ ++ rxs = (a >> 4) & 0xf; ++ t43x_dahdi_rbsbits(ts->span.chans[i], rxs); ++ } ++ } ++} ++ ++struct maint_work_struct { ++ struct work_struct work; ++ struct t43x *wc; ++ int cmd; ++ struct dahdi_span *span; ++}; ++ ++static void t43x_maint_work(struct work_struct *work) ++{ ++ struct maint_work_struct *w = container_of(work, ++ struct maint_work_struct, work); ++ ++ struct t43x *wc = w->wc; ++ struct dahdi_span *span = w->span; ++ int reg = 0; ++ int cmd = w->cmd; ++ unsigned long flags; ++ int fidx = (wc->numspans == 2) ? span->offset+1 : span->offset; ++ ++ if (dahdi_is_e1_span(span)) { ++ switch (cmd) { ++ case DAHDI_MAINT_NONE: ++ dev_info(&wc->xb.pdev->dev, ++ "Clearing all maint modes\n"); ++ t43x_clear_maint(span); ++ break; ++ case DAHDI_MAINT_LOCALLOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on local loopback\n"); ++ t43x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, LIM0); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ goto cleanup; ++ } ++ __t43x_framer_set(wc, fidx, LIM0, reg | LIM0_LL); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on network line loopback\n"); ++ t43x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, LIM1); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ goto cleanup; ++ } ++ __t43x_framer_set(wc, fidx, LIM1, reg | LIM1_RL); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on network payload loopback\n"); ++ t43x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, LIM1); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ goto cleanup; ++ } ++ __t43x_framer_set(wc, fidx, LIM1, ++ reg | (LIM1_RL | LIM1_JATT)); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_FAS_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 5)); ++ break; ++ case DAHDI_MAINT_MULTI_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 4)); ++ break; ++ case DAHDI_MAINT_CRC_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 3)); ++ break; ++ case DAHDI_MAINT_CAS_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 2)); ++ break; ++ case DAHDI_MAINT_PRBS_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 1)); ++ break; ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 0)); ++ break; ++ default: ++ dev_info(&wc->xb.pdev->dev, ++ "Unknown E1 maint command: %d\n", cmd); ++ goto cleanup; ++ } ++ } else { ++ switch (cmd) { ++ case DAHDI_MAINT_NONE: ++ dev_info(&wc->xb.pdev->dev, ++ "Clearing all maint modes\n"); ++ t43x_clear_maint(span); ++ break; ++ case DAHDI_MAINT_LOCALLOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on local loopback\n"); ++ t43x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, LIM0); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ goto cleanup; ++ } ++ __t43x_framer_set(wc, fidx, LIM0, reg | LIM0_LL); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on network line loopback\n"); ++ t43x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, LIM1); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ goto cleanup; ++ } ++ __t43x_framer_set(wc, fidx, LIM1, reg | LIM1_RL); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ dev_info(&wc->xb.pdev->dev, ++ "Turning on network payload loopback\n"); ++ t43x_clear_maint(span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, LIM1); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ goto cleanup; ++ } ++ __t43x_framer_set(wc, fidx, LIM1, ++ reg | (LIM1_RL | LIM1_JATT)); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ break; ++ case DAHDI_MAINT_LOOPUP: ++ dev_info(&wc->xb.pdev->dev, ++ "Transmitting loopup code\n"); ++ t43x_clear_maint(span); ++ t43x_framer_set(wc, fidx, 0x21, 0x50); ++ break; ++ case DAHDI_MAINT_LOOPDOWN: ++ dev_info(&wc->xb.pdev->dev, ++ "Transmitting loopdown code\n"); ++ t43x_clear_maint(span); ++ t43x_framer_set(wc, fidx, 0x21, 0x60); ++ break; ++ case DAHDI_MAINT_FAS_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 5)); ++ break; ++ case DAHDI_MAINT_MULTI_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 4)); ++ break; ++ case DAHDI_MAINT_CRC_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 3)); ++ break; ++ case DAHDI_MAINT_CAS_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 2)); ++ break; ++ case DAHDI_MAINT_PRBS_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 1)); ++ break; ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ t43x_framer_set(wc, fidx, 0x1b, (1 << 0)); ++ break; ++ default: ++ dev_info(&wc->xb.pdev->dev, ++ "Unknown T1 maint command: %d\n", cmd); ++ return; ++ } ++ } ++ ++ /* update DAHDI_ALARM_LOOPBACK status bit and check timing source */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (!span->maintstat) ++ span->alarms &= ~DAHDI_ALARM_LOOPBACK; ++ dahdi_alarm_notify(span); ++ __t43x_set_timing_source_auto(wc); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++cleanup: ++ kfree(w); ++ return; ++} ++ ++static int t43x_reset_counters(struct dahdi_span *span) ++{ ++ struct t43x_span *ts = container_of(span, struct t43x_span, span); ++ memset(&ts->span.count, 0, sizeof(ts->span.count)); ++ return 0; ++} ++ ++static int t43x_maint(struct dahdi_span *span, int cmd) ++{ ++ struct maint_work_struct *work; ++ struct t43x_span *ts = container_of(span, struct t43x_span, span); ++ struct t43x *wc = ts->owner; ++ ++ if (dahdi_is_e1_span(span)) { ++ switch (cmd) { ++ case DAHDI_MAINT_NONE: ++ case DAHDI_MAINT_LOCALLOOP: ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ case DAHDI_MAINT_FAS_DEFECT: ++ case DAHDI_MAINT_MULTI_DEFECT: ++ case DAHDI_MAINT_CRC_DEFECT: ++ case DAHDI_MAINT_CAS_DEFECT: ++ case DAHDI_MAINT_PRBS_DEFECT: ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ break; ++ case DAHDI_MAINT_LOOPUP: ++ case DAHDI_MAINT_LOOPDOWN: ++ dev_info(&wc->xb.pdev->dev, ++ "Only local loop supported in E1 mode\n"); ++ return -ENOSYS; ++ case DAHDI_RESET_COUNTERS: ++ t43x_reset_counters(span); ++ return 0; ++ default: ++ dev_info(&wc->xb.pdev->dev, ++ "Unknown E1 maint command: %d\n", cmd); ++ return -ENOSYS; ++ } ++ } else { ++ switch (cmd) { ++ case DAHDI_MAINT_NONE: ++ case DAHDI_MAINT_LOCALLOOP: ++ case DAHDI_MAINT_NETWORKLINELOOP: ++ case DAHDI_MAINT_NETWORKPAYLOADLOOP: ++ case DAHDI_MAINT_LOOPUP: ++ case DAHDI_MAINT_LOOPDOWN: ++ case DAHDI_MAINT_FAS_DEFECT: ++ case DAHDI_MAINT_MULTI_DEFECT: ++ case DAHDI_MAINT_CRC_DEFECT: ++ case DAHDI_MAINT_CAS_DEFECT: ++ case DAHDI_MAINT_PRBS_DEFECT: ++ case DAHDI_MAINT_BIPOLAR_DEFECT: ++ break; ++ case DAHDI_RESET_COUNTERS: ++ t43x_reset_counters(span); ++ return 0; ++ default: ++ dev_info(&wc->xb.pdev->dev, ++ "Unknown T1 maint command: %d\n", cmd); ++ return -ENOSYS; ++ } ++ } ++ ++ work = kzalloc(sizeof(*work), GFP_ATOMIC); ++ if (!work) { ++ dev_info(&wc->xb.pdev->dev, ++ "Failed to allocate memory for workqueue\n"); ++ return -ENOMEM; ++ } ++ ++ work->span = span; ++ work->wc = wc; ++ work->cmd = cmd; ++ ++ INIT_WORK(&work->work, t43x_maint_work); ++ queue_work(wc->wq, &work->work); ++ return 0; ++} ++ ++static int t43x_clear_maint(struct dahdi_span *span) ++{ ++ struct t43x_span *ts = container_of(span, struct t43x_span, span); ++ struct t43x *wc = ts->owner; ++ int reg = 0; ++ unsigned long flags; ++ int fidx = (wc->numspans == 2) ? span->offset+1 : span->offset; ++ ++ /* Turn off local loop */ ++ spin_lock_irqsave(&wc->reglock, flags); ++ reg = __t43x_framer_get(wc, fidx, LIM0); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return -EIO; ++ } ++ __t43x_framer_set(wc, fidx, LIM0, reg & ~LIM0_LL); ++ ++ /* Turn off remote loop & jitter attenuator */ ++ reg = __t43x_framer_get(wc, fidx, LIM1); ++ if (reg < 0) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return -EIO; ++ } ++ __t43x_framer_set(wc, fidx, LIM1, reg & ~(LIM1_RL | LIM1_JATT)); ++ ++ /* Clear loopup/loopdown signals on the line */ ++ __t43x_framer_set(wc, fidx, 0x21, 0x40); ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ return 0; ++} ++ ++static int t43x_ioctl(struct dahdi_chan *chan, unsigned int cmd, ++ unsigned long data) ++{ ++ struct t4_regs regs; ++ unsigned int x; ++ struct t43x *wc; ++ int fidx; ++ ++ switch (cmd) { ++ case WCT4_GET_REGS: ++ wc = chan->pvt; ++ fidx = (wc->numspans == 2) ? chan->span->offset+1 : ++ chan->span->offset; ++ for (x = 0; x < sizeof(regs.regs) / sizeof(regs.regs[0]); x++) ++ regs.regs[x] = t43x_framer_get(wc, fidx, x); ++ ++ if (copy_to_user((void __user *) data, ®s, sizeof(regs))) ++ return -EFAULT; ++ break; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static void t43x_chan_set_sigcap(struct dahdi_span *span, int x) ++{ ++ struct t43x_span *ts = container_of(span, struct t43x_span, span); ++ struct dahdi_chan *chan = ts->chans[x]; ++ ++ chan->sigcap = DAHDI_SIG_CLEAR; ++ /* E&M variant supported depends on span type */ ++ if (dahdi_is_e1_span(span)) { ++ /* E1 sigcap setup */ ++ if (span->lineconfig & DAHDI_CONFIG_CCS) { ++ /* CCS setup */ ++ chan->sigcap |= DAHDI_SIG_MTP2 | DAHDI_SIG_SF; ++ return; ++ } ++ /* clear out sig and sigcap for channel 16 on E1 CAS ++ * lines, otherwise, set it correctly */ ++ if (x == 15) { ++ /* CAS signaling channel setup */ ++ ts->chans[15]->sigcap = 0; ++ ts->chans[15]->sig = 0; ++ return; ++ } ++ /* normal CAS setup */ ++ chan->sigcap |= DAHDI_SIG_EM_E1 | DAHDI_SIG_FXSLS | ++ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_SF | ++ DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | ++ DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS; ++ } else { ++ /* T1 sigcap setup */ ++ chan->sigcap |= DAHDI_SIG_EM | DAHDI_SIG_FXSLS | ++ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_MTP2 | ++ DAHDI_SIG_SF | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | ++ DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS; ++ } ++} ++ ++static bool t43x_lineconfig_changed(struct t43x_span *ts, ++ const struct dahdi_lineconfig *lc) ++{ ++ unsigned long flags; ++ bool result; ++ u32 crc = crc32(~0, lc, sizeof(*lc)); ++ ++ spin_lock_irqsave(&ts->owner->reglock, flags); ++ result = (crc != ts->lineconfig_fingerprint); ++ spin_unlock_irqrestore(&ts->owner->reglock, flags); ++ return result; ++} ++ ++static void t43x_save_lineconfig(struct t43x_span *ts, ++ const struct dahdi_lineconfig *lc) ++{ ++ unsigned long flags; ++ u32 crc = crc32(~0, lc, sizeof(*lc)); ++ ++ spin_lock_irqsave(&ts->owner->reglock, flags); ++ ts->lineconfig_fingerprint = crc; ++ spin_unlock_irqrestore(&ts->owner->reglock, flags); ++} ++ ++static int ++t43x_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ struct t43x_span *ts = container_of(span, struct t43x_span, span); ++ struct t43x *wc = ts->owner; ++ int i; ++ int res = 0; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s\n", __func__); ++ ++ if (file->f_flags & O_NONBLOCK) { ++ if (!is_initialized(wc)) ++ return -EAGAIN; ++ } else { ++ t43x_wait_for_ready(wc); ++ } ++ ++ if (lc->sync < 0) ++ lc->sync = 0; ++ if (lc->sync > wc->numspans) { ++ dev_warn(&wc->xb.pdev->dev, ++ "WARNING: Cannot set priority on span %d to %d. Please set to a number between 1 and %d\n", ++ span->spanno, lc->sync, wc->numspans); ++ lc->sync = 0; ++ } ++ ++ /* remove this span number from the current sync sources, if there */ ++ for (i = 0; i < wc->numspans; i++) { ++ if (wc->tspans[i]->sync == span->spanno) ++ wc->tspans[i]->sync = 0; ++ } ++ ++ wc->tspans[span->offset]->syncpos = lc->sync; ++ /* if a sync src, put it in proper place */ ++ if (lc->sync) ++ wc->tspans[lc->sync - 1]->sync = span->spanno; ++ ++ /* make sure that sigcaps gets updated if necessary */ ++ for (i = 0; i < span->channels; i++) ++ t43x_chan_set_sigcap(span, i); ++ ++ /* If already running, apply changes immediately */ ++ if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags) && ++ t43x_lineconfig_changed(ts, lc)) { ++ res = t43x_startup(file, span); ++ if (!res) ++ t43x_save_lineconfig(ts, lc); ++ } ++ return res; ++} ++ ++/* ++ * Initialize a span ++ * ++ */ ++static int ++t43x_init_one_span(struct t43x *wc, struct t43x_span *ts, enum linemode type) ++{ ++ int x; ++ struct dahdi_chan *chans[32] = {NULL,}; ++ struct dahdi_echocan_state *ec[32] = {NULL,}; ++ unsigned long flags; ++ int res = 0; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s\n", __func__); ++ ++ for (x = 0; x < ((E1 == type) ? 31 : 24); x++) { ++ chans[x] = kzalloc(sizeof(*chans[x]), GFP_KERNEL); ++ ec[x] = kzalloc(sizeof(*ec[x]), GFP_KERNEL); ++ if (!chans[x] || !ec[x]) ++ goto error_exit; ++ } ++ ++ /* Stop the interrupt handler so that we may swap the channel array. */ ++ disable_irq(wc->xb.pdev->irq); ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ for (x = 0; x < ARRAY_SIZE(ts->chans); x++) { ++ kfree(ts->chans[x]); ++ kfree(ts->ec[x]); ++ ts->chans[x] = NULL; ++ ts->ec[x] = NULL; ++ } ++ memcpy(ts->chans, chans, sizeof(ts->chans)); ++ memcpy(ts->ec, ec, sizeof(ts->ec)); ++ ++ switch (type) { ++ case E1: ++ ts->span.channels = 31; ++ ts->span.spantype = SPANTYPE_DIGITAL_E1; ++ ts->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 | ++ DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4; ++ ts->span.deflaw = DAHDI_LAW_ALAW; ++ break; ++ case T1: ++ ts->span.channels = 24; ++ ts->span.spantype = SPANTYPE_DIGITAL_T1; ++ ts->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | ++ DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF; ++ ts->span.deflaw = DAHDI_LAW_MULAW; ++ break; ++ case J1: ++ ts->span.channels = 24; ++ ts->span.spantype = SPANTYPE_DIGITAL_J1; ++ ts->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | ++ DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF; ++ ts->span.deflaw = DAHDI_LAW_MULAW; ++ break; ++ default: ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ res = -EINVAL; ++ enable_irq(wc->xb.pdev->irq); ++ goto error_exit; ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ set_bit(DAHDI_FLAGBIT_RBS, &ts->span.flags); ++ for (x = 0; x < ts->span.channels; x++) { ++ snprintf(ts->chans[x]->name, sizeof(ts->chans[x]->name), ++ "%s/%d", ts->span.name, x + 1); ++ t43x_chan_set_sigcap(&ts->span, x); ++ ts->chans[x]->pvt = wc; ++ ts->chans[x]->chanpos = x + 1; ++ } ++ ++ t43x_reset_counters(&ts->span); ++ ++ /* Span is in red alarm by default ? */ ++ ts->span.alarms = DAHDI_ALARM_NONE; ++ ++ enable_irq(wc->xb.pdev->irq); ++ return 0; ++ ++error_exit: ++ ++ for (x = 0; x < ARRAY_SIZE(chans); ++x) { ++ kfree(chans[x]); ++ kfree(ec[x]); ++ } ++ return res; ++} ++ ++/* ++ * Initialize all spans (one time) ++ */ ++ ++static void t43x_init_spans(struct t43x *wc, enum linemode type) ++{ ++ struct t43x_span *ts; ++ int x; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s\n", __func__); ++ ++ for (x = 0; x < wc->numspans; x++) { ++ ts = wc->tspans[x]; ++ sprintf(ts->span.name, ++ "WCTE%d/%d/%d", wc->numspans, wc->num, x + 1); ++ snprintf(ts->span.desc, sizeof(ts->span.desc) - 1, ++ "WCTE%d3X (PCI) Card %d Span %d", ++ wc->numspans, wc->num, x + 1); ++ ++ ts->span.chans = ts->chans; ++ ts->span.flags = DAHDI_FLAG_RBS; ++ ts->span.ops = &t43x_span_ops; ++ ts->span.offset = x; ++ ++ ts->owner = wc; ++ ++ t43x_init_one_span(wc, ts, type); ++ ++ list_add_tail(&ts->span.device_node, &wc->ddev->spans); ++ } ++} ++ ++/** ++ * t1xx_set_linemode - Change the type of span before assignment. ++ * @span: The span to change. ++ * @linemode: Text string for the line mode. ++ * ++ * This function may be called after the dahdi_device is registered but ++ * before the spans are assigned numbers (and are visible to the rest of ++ * DAHDI). ++ * ++ */ ++static int t43x_set_linemode(struct dahdi_span *span, enum spantypes linemode) ++{ ++ int res; ++ struct t43x_span *ts = container_of(span, struct t43x_span, span); ++ struct t43x *wc = ts->owner; ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "%s\n", __func__); ++ ++ /* We may already be set to the requested type. */ ++ if (span->spantype == linemode) { ++ ts->span.alarms = DAHDI_ALARM_NONE; ++ return 0; ++ } ++ ++ res = t43x_wait_for_ready(wc); ++ if (res) ++ return res; ++ ++ mutex_lock(&wc->lock); ++ ++ switch (linemode) { ++ case SPANTYPE_DIGITAL_T1: ++ dev_info(&wc->xb.pdev->dev, ++ "Changing from %s to T1 line mode.\n", ++ dahdi_spantype2str(span->spantype)); ++ res = t43x_init_one_span(wc, ts, T1); ++ break; ++ case SPANTYPE_DIGITAL_E1: ++ dev_info(&wc->xb.pdev->dev, ++ "Changing from %s to E1 line mode.\n", ++ dahdi_spantype2str(span->spantype)); ++ res = t43x_init_one_span(wc, ts, E1); ++ break; ++ case SPANTYPE_DIGITAL_J1: ++ dev_info(&wc->xb.pdev->dev, ++ "Changing from %s to J1 line mode.\n", ++ dahdi_spantype2str(span->spantype)); ++ res = t43x_init_one_span(wc, ts, J1); ++ break; ++ default: ++ dev_err(&wc->xb.pdev->dev, ++ "Got invalid linemode '%s' from dahdi\n", ++ dahdi_spantype2str(linemode)); ++ res = -EINVAL; ++ } ++ ++ /* Since we probably reallocated the channels we need to make ++ * sure they are configured before setting INITIALIZED again. */ ++ if (!res) ++ dahdi_init_span(span); ++ ++ mutex_unlock(&wc->lock); ++ return res; ++} ++ ++static int t43x_hardware_post_init(struct t43x *wc, enum linemode *type) ++{ ++ int reg; ++ int x; ++ ++ if (!strcasecmp(default_linemode, "e1")) { ++ *type = E1; ++ } else if (!strcasecmp(default_linemode, "t1")) { ++ *type = T1; ++ } else if (!strcasecmp(default_linemode, "j1")) { ++ *type = J1; ++ } else { ++ dev_warn(&wc->xb.pdev->dev, ++ "'%s' is an unknown linemode. Defaulting to 't1'\n", ++ default_linemode); ++ *type = T1; ++ } ++ ++ if (debug) { ++ dev_info(&wc->xb.pdev->dev, "linemode: %s\n", ++ (*type == T1) ? "T1" : ((J1 == *type) ? "J1" : "E1")); ++ } ++ ++ /* what version of the FALC are we using? */ ++ wcxb_gpio_set(&wc->xb, FALC_CPU_RESET); ++ reg = t43x_framer_get(wc, 0, 0x4a); ++ if (reg < 0) { ++ dev_info(&wc->xb.pdev->dev, ++ "Failed to read FALC version (%x)\n", reg); ++ return -EIO; ++ } ++ dev_info(&wc->xb.pdev->dev, "FALC version: %1x\n", reg); ++ ++ /* make sure reads and writes work */ ++ for (x = 0; x < 256; x++) { ++ t43x_framer_set(wc, 0, 0x14, x); ++ reg = t43x_framer_get(wc, 0, 0x14); ++ if (reg < 0) { ++ dev_info(&wc->xb.pdev->dev, ++ "Failed register read (%d)\n", reg); ++ return -EIO; ++ } ++ if (reg != x) { ++ dev_info(&wc->xb.pdev->dev, ++ "Register test failed. Wrote '%x' but read '%x'\n", ++ x, reg); ++ return -EIO; ++ } ++ } ++ ++ /* Enable all the GPIO outputs. */ ++ t43x_setleds(wc, -1); ++ ++ return 0; ++} ++ ++static void t43x_check_alarms(struct t43x *wc, int span_idx) ++{ ++ struct t43x_span *ts = wc->tspans[span_idx]; ++ unsigned char c, d; ++ int alarms; ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ ++ if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &ts->span.flags))) ++ return; ++ ++ spin_lock(&wc->reglock); ++ ++ c = __t43x_framer_get(wc, fidx, 0x4c); ++ d = __t43x_framer_get(wc, fidx, 0x4d); ++ ++ /* start with existing span alarms */ ++ alarms = ts->span.alarms; ++ ++ if (dahdi_is_e1_span(&ts->span)) { ++ if (c & 0x04) { ++ /* No multiframe found, force RAI high after 400ms only ++ * if we haven't found a multiframe since last loss of ++ * frame */ ++ if (!test_and_set_bit(NMF_FLAGBIT, &ts->bit_flags)) { ++ /* LIM0: Force RAI High */ ++ __t43x_framer_set(wc, fidx, 0x20, 0x9f | 0x20); ++ dev_info(&wc->xb.pdev->dev, ++ "NMF workaround on!\n"); ++ } ++ /* Reset to CRC4 mode */ ++ __t43x_framer_set(wc, fidx, 0x1e, 0xc3); ++ /* Force Resync */ ++ __t43x_framer_set(wc, fidx, 0x1c, 0xf2); ++ /* Force Resync */ ++ __t43x_framer_set(wc, fidx, 0x1c, 0xf0); ++ } else if (!(c & 0x02)) { ++ if (test_and_clear_bit(NMF_FLAGBIT, &ts->bit_flags)) { ++ /* LIM0: Clear forced RAI */ ++ __t43x_framer_set(wc, fidx, 0x20, 0x9f); ++ dev_info(&wc->xb.pdev->dev, ++ "NMF workaround off!\n"); ++ } ++ } ++ } ++ ++ if (ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { ++ if (!test_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) ++ alarms |= DAHDI_ALARM_NOTOPEN; ++ else ++ alarms &= ~DAHDI_ALARM_NOTOPEN; ++ } ++ ++ if (c & 0x20) { /* LOF/LFA */ ++ if (!(alarms & DAHDI_ALARM_RED) && (0 == ts->lofalarmtimer)) { ++ ts->lofalarmtimer = (jiffies + ++ msecs_to_jiffies(alarmdebounce)) ?: 1; ++ } ++ } else { ++ ts->lofalarmtimer = 0; ++ } ++ ++ if (c & 0x80) { /* LOS */ ++ if (!(alarms & DAHDI_ALARM_RED) && (0 == ts->losalarmtimer)) { ++ ts->losalarmtimer = (jiffies + ++ msecs_to_jiffies(losalarmdebounce)) ?: 1; ++ } ++ } else { ++ ts->losalarmtimer = 0; ++ } ++ ++ if (!(c & (0x80|0x20))) ++ alarms &= ~DAHDI_ALARM_RED; ++ ++ if (c & 0x40) { /* AIS */ ++ if (!(alarms & DAHDI_ALARM_BLUE) && (0 == ts->aisalarmtimer)) ++ ts->aisalarmtimer = (jiffies + ++ msecs_to_jiffies(aisalarmdebounce)) ?: 1; ++ } else { ++ ts->aisalarmtimer = 0; ++ alarms &= ~DAHDI_ALARM_BLUE; ++ } ++ ++ /* Keep track of recovering */ ++ if (alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE|DAHDI_ALARM_NOTOPEN)) { ++ ts->recoverytimer = 0; ++ alarms &= ~DAHDI_ALARM_RECOVER; ++ } else if (ts->span.alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE)) { ++ if (0 == ts->recoverytimer) { ++ ts->recoverytimer = (jiffies + 5*HZ) ?: 1; ++ alarms |= DAHDI_ALARM_RECOVER; ++ } ++ } ++ ++ if (c & 0x10) { /* receiving yellow (RAI) */ ++ if (!(alarms & DAHDI_ALARM_YELLOW) && !ts->yelalarmtimer) { ++ ts->yelalarmtimer = (jiffies + ++ msecs_to_jiffies(yelalarmdebounce)) ?: 1; ++ } ++ } else { ++ ts->yelalarmtimer = 0; ++ alarms &= ~DAHDI_ALARM_YELLOW; ++ } ++ ++ if (ts->span.alarms != alarms) { ++ /* re-evaluate timing source if alarm state is changed */ ++ if ((alarms ^ ts->span.alarms) & NOSYNC_ALARMS) { ++ ts->span.alarms = alarms; ++ __t43x_set_timing_source_auto(wc); ++ } else { ++ ts->span.alarms = alarms; ++ } ++ ++ spin_unlock(&wc->reglock); ++ ++ dahdi_alarm_notify(&ts->span); ++ } else { ++ spin_unlock(&wc->reglock); ++ } ++} ++ ++static void t43x_check_loopcodes(struct t43x *wc, int span_idx) ++{ ++ struct t43x_span *ts = wc->tspans[span_idx]; ++ unsigned char frs1; ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ ++ frs1 = t43x_framer_get(wc, fidx, 0x4d); ++ ++ /* Detect loopup code if we're not sending one */ ++ if ((ts->span.maintstat != DAHDI_MAINT_LOOPUP) && (frs1 & 0x08)) { ++ /* Loop-up code detected */ ++ if ((ts->span.maintstat != DAHDI_MAINT_REMOTELOOP) && ++ (0 == ts->loopuptimer)) ++ ts->loopuptimer = (jiffies + msecs_to_jiffies(800)) | 1; ++ } else { ++ ts->loopuptimer = 0; ++ } ++ ++ /* Same for loopdown code */ ++ if ((ts->span.maintstat != DAHDI_MAINT_LOOPDOWN) && (frs1 & 0x10)) { ++ /* Loop-down code detected */ ++ if ((ts->span.maintstat == DAHDI_MAINT_REMOTELOOP) && ++ (0 == ts->loopdntimer)) ++ ts->loopdntimer = (jiffies + msecs_to_jiffies(800)) | 1; ++ } else { ++ ts->loopdntimer = 0; ++ } ++} ++ ++static void t43x_debounce_alarms(struct t43x *wc, int span_idx) ++{ ++ struct t43x_span *ts = wc->tspans[span_idx]; ++ int alarms; ++ unsigned long flags; ++ unsigned int fmr4; ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ alarms = ts->span.alarms; ++ ++ if (ts->lofalarmtimer && time_after(jiffies, ts->lofalarmtimer)) { ++ alarms |= DAHDI_ALARM_RED; ++ ts->lofalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "LOF alarm detected\n"); ++ } ++ ++ if (ts->losalarmtimer && time_after(jiffies, ts->losalarmtimer)) { ++ alarms |= DAHDI_ALARM_RED; ++ ts->losalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "LOS alarm detected\n"); ++ } ++ ++ if (ts->aisalarmtimer && time_after(jiffies, ts->aisalarmtimer)) { ++ alarms |= DAHDI_ALARM_BLUE; ++ ts->aisalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "AIS alarm detected\n"); ++ } ++ ++ if (ts->yelalarmtimer && time_after(jiffies, ts->yelalarmtimer)) { ++ alarms |= DAHDI_ALARM_YELLOW; ++ ts->yelalarmtimer = 0; ++ dev_info(&wc->xb.pdev->dev, "YEL alarm detected\n"); ++ } ++ ++ if (ts->recoverytimer && time_after(jiffies, ts->recoverytimer)) { ++ alarms &= ~(DAHDI_ALARM_RECOVER); ++ ts->recoverytimer = 0; ++ memset(&ts->span.count, 0, sizeof(ts->span.count)); ++ dev_info(&wc->xb.pdev->dev, "Alarms cleared\n"); ++ } ++ ++ if (alarms != ts->span.alarms) { ++ /* re-evaluate timing source if alarm state is changed */ ++ if ((alarms ^ ts->span.alarms) & NOSYNC_ALARMS) { ++ ts->span.alarms = alarms; ++ __t43x_set_timing_source_auto(wc); ++ } else { ++ ts->span.alarms = alarms; ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ dahdi_alarm_notify(&ts->span); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ ++ /* If receiving alarms (except Yellow), go into Yellow alarm state */ ++ if (alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE| ++ DAHDI_ALARM_NOTOPEN|DAHDI_ALARM_RECOVER)) { ++ if (!test_and_set_bit(SENDINGYELLOW_FLAGBIT, &ts->bit_flags)) { ++ dev_info(&wc->xb.pdev->dev, "Setting yellow alarm\n"); ++ /* We manually do yellow alarm to handle RECOVER ++ * and NOTOPEN, otherwise it's auto anyway */ ++ fmr4 = __t43x_framer_get(wc, fidx, 0x20); ++ __t43x_framer_set(wc, fidx, 0x20, fmr4 | 0x20); ++ } ++ } else { ++ if (test_and_clear_bit(SENDINGYELLOW_FLAGBIT, &ts->bit_flags)) { ++ dev_info(&wc->xb.pdev->dev, "Clearing yellow alarm\n"); ++ /* We manually do yellow alarm to handle RECOVER */ ++ fmr4 = __t43x_framer_get(wc, fidx, 0x20); ++ __t43x_framer_set(wc, fidx, 0x20, fmr4 & ~0x20); ++ } ++ } ++ ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static void t43x_debounce_loopcodes(struct t43x *wc, int span_idx) ++{ ++ struct t43x_span *ts = wc->tspans[span_idx]; ++ unsigned long flags; ++ int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; ++ ++ spin_lock_irqsave(&wc->reglock, flags); ++ if (ts->loopuptimer && time_after(jiffies, ts->loopuptimer)) { ++ /* Loop-up code debounced */ ++ dev_info(&wc->xb.pdev->dev, "Loopup detected, enabling remote loop\n"); ++ __t43x_framer_set(wc, fidx, 0x36, 0x08); /* LIM0: Disable ++ any local loop */ ++ __t43x_framer_set(wc, fidx, 0x37, 0xf6); /* LIM1: Enable ++ remote loop */ ++ ts->span.maintstat = DAHDI_MAINT_REMOTELOOP; ++ ts->loopuptimer = 0; ++ dahdi_alarm_notify(&ts->span); ++ __t43x_set_timing_source_auto(wc); ++ } ++ ++ if (ts->loopdntimer && time_after(jiffies, ts->loopdntimer)) { ++ /* Loop-down code debounced */ ++ dev_info(&wc->xb.pdev->dev, "Loopdown detected, disabling remote loop\n"); ++ __t43x_framer_set(wc, fidx, 0x36, 0x08); /* LIM0: Disable ++ any local loop */ ++ __t43x_framer_set(wc, fidx, 0x37, 0xf0); /* LIM1: Disable ++ remote loop */ ++ ts->span.maintstat = DAHDI_MAINT_NONE; ++ ts->loopdntimer = 0; ++ dahdi_alarm_notify(&ts->span); ++ __t43x_set_timing_source_auto(wc); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++} ++ ++static void handle_leds(struct t43x *wc) ++{ ++ u32 led = 0; ++ struct t43x_span *ts; ++ int span_idx; ++ ++ if (time_after(jiffies, wc->blinktimer)) { ++ wc->blink = !wc->blink; ++ wc->blinktimer = jiffies + HZ/2; ++ } ++ ++ for (span_idx = wc->numspans-1; span_idx >= 0; span_idx--) { ++ led >>= 2; ++ ts = wc->tspans[span_idx]; ++ if ((ts->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE)) || ++ ts->losalarmtimer) { ++ /* When we're in red alarm, blink the led once a ++ * second. */ ++ if (wc->blink) ++ led |= STATUS_LED_RED; ++ } else if (ts->span.alarms & DAHDI_ALARM_YELLOW) { ++ led |= STATUS_LED_YELLOW; ++ } else { ++ if (test_bit(DAHDI_FLAGBIT_RUNNING, &ts->span.flags)) ++ led |= STATUS_LED_GREEN; ++ } ++ } ++ ++ if (wc->numspans == 2) ++ led >>= 2; ++ ++ if (led != (ioread32be(wc->xb.membase) & LED_MASK)) ++ t43x_setleds(wc, led); ++} ++ ++static void t43x_handle_receive(struct wcxb *xb, void *vfp) ++{ ++ int i, j, s; ++ u_char *frame = (u_char *) vfp; ++ struct t43x *wc = container_of(xb, struct t43x, xb); ++ struct t43x_span *ts; ++ ++ for (s = 0; s < wc->numspans; s++) { ++ ts = wc->tspans[s]; ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &ts->span.flags)) ++ continue; ++ ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) { ++ for (i = 0; i < ts->span.channels; i++) { ++ ts->chans[i]->readchunk[j] = ++ frame[j*WCXB_DMA_CHAN_SIZE+(s+1+i*4)]; ++ } ++ } ++ ++ if (0 == vpmsupport) { ++ for (i = 0; i < ts->span.channels; i++) { ++ struct dahdi_chan *const c = ts->span.chans[i]; ++ __dahdi_ec_chunk(c, c->readchunk, c->readchunk, ++ c->writechunk); ++ } ++ } ++ ++ _dahdi_receive(&ts->span); ++ } ++} ++ ++static void t43x_handle_transmit(struct wcxb *xb, void *vfp) ++{ ++ int i, j, s; ++ u_char *frame = (u_char *) vfp; ++ struct t43x *wc = container_of(xb, struct t43x, xb); ++ struct t43x_span *ts; ++ ++ for (s = 0; s < wc->numspans; s++) { ++ ts = wc->tspans[s]; ++ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, ++ &ts->span.flags)) { ++ continue; ++ } ++ ++ _dahdi_transmit(&ts->span); ++ ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) ++ for (i = 0; i < ts->span.channels; i++) ++ frame[j*WCXB_DMA_CHAN_SIZE+(s+1+i*4)] = ++ ts->chans[i]->writechunk[j]; ++ } ++} ++ ++#define SPAN_DEBOUNCE \ ++ (ts->lofalarmtimer || ts->losalarmtimer || \ ++ ts->aisalarmtimer || ts->yelalarmtimer || \ ++ ts->recoverytimer || \ ++ ts->loopuptimer || ts->loopdntimer) ++ ++#define SPAN_ALARMS \ ++ (ts->span.alarms & ~DAHDI_ALARM_NOTOPEN) ++ ++static void timer_work_func(struct work_struct *work) ++{ ++ struct t43x *wc = container_of(work, struct t43x, timer_work); ++ struct t43x_span *ts; ++ int x; ++ bool start_timer = false; ++ ++ for (x = 0; x < wc->numspans; x++) { ++ ts = wc->tspans[x]; ++ if (ts->debounce) { ++ /* Clear it now in case the interrupt needs to set it ++ * again */ ++ ts->debounce = false; ++ t43x_debounce_alarms(wc, x); ++ if (!dahdi_is_e1_span(&ts->span)) ++ t43x_debounce_loopcodes(wc, x); ++ if (SPAN_DEBOUNCE || SPAN_ALARMS) ++ ts->debounce = true; ++ if (ts->debounce) ++ start_timer = true; ++ } ++ } ++ ++ handle_leds(wc); ++ if (start_timer) ++ mod_timer(&wc->timer, jiffies + HZ/10); ++} ++ ++static void handle_falc_int(struct t43x *wc, int unit) ++{ ++ struct t43x_span *ts = wc->tspans[unit]; ++ unsigned char gis, isr0, isr1, isr2, isr3, isr4; ++ static int intcount; ++ bool start_timer; ++ bool recheck_sigbits = false; ++ int fidx = (wc->numspans == 2) ? unit+1 : unit; ++ ++ intcount++; ++ start_timer = false; ++ ++ spin_lock(&wc->reglock); ++ gis = __t43x_framer_get(wc, fidx, FRMR_GIS); ++ isr0 = (gis&FRMR_GIS_ISR0) ? __t43x_framer_get(wc, fidx, FRMR_ISR0) : 0; ++ isr1 = (gis&FRMR_GIS_ISR1) ? __t43x_framer_get(wc, fidx, FRMR_ISR1) : 0; ++ isr2 = (gis&FRMR_GIS_ISR2) ? __t43x_framer_get(wc, fidx, FRMR_ISR2) : 0; ++ isr3 = (gis&FRMR_GIS_ISR3) ? __t43x_framer_get(wc, fidx, FRMR_ISR3) : 0; ++ isr4 = (gis&FRMR_GIS_ISR4) ? __t43x_framer_get(wc, fidx, FRMR_ISR4) : 0; ++ ++ if ((debug) && !(isr3 & ISR3_SEC)) { ++ dev_info(&wc->xb.pdev->dev, ++ "span: %d gis: %02x, isr0: %02x, isr1: %02x, isr2: %02x, isr3: %02x, isr4: %02x, intcount=%u\n", ++ unit, gis, isr0, isr1, isr2, isr3, isr4, intcount); ++ } ++ ++ /* Collect performance counters once per second */ ++ if (isr3 & ISR3_SEC) { ++ ts->span.count.fe += __t43x_framer_get(wc, fidx, FECL_T); ++ ts->span.count.crc4 += __t43x_framer_get(wc, fidx, CEC1L_T); ++ ts->span.count.cv += __t43x_framer_get(wc, fidx, CVCL_T); ++ ts->span.count.ebit += __t43x_framer_get(wc, fidx, EBCL_T); ++ ts->span.count.be += __t43x_framer_get(wc, fidx, BECL_T); ++ ts->span.count.prbs = __t43x_framer_get(wc, fidx, FRS1_T); ++ ++ if (DAHDI_RXSIG_INITIAL == ts->span.chans[0]->rxhooksig) ++ recheck_sigbits = true; ++ } ++ spin_unlock(&wc->reglock); ++ ++ /* Collect errored second counter once per second */ ++ if (isr3 & ISR3_ES) ++ ts->span.count.errsec += 1; ++ ++ /* RSC/CASC: Received Signaling Information Changed */ ++ /* This interrupt is enabled by set_cas_mode() for CAS channels */ ++ if (isr0 & 0x08 || recheck_sigbits) ++ t43x_check_sigbits(wc, unit); ++ ++ if (dahdi_is_e1_span(&ts->span)) { ++ /* E1 checks */ ++ if ((isr3 & 0x68) || isr2 || (isr1 & 0x7f)) { ++ t43x_check_alarms(wc, unit); ++ start_timer = true; ++ } ++ } else { ++ /* T1 checks */ ++ if (isr2) { ++ t43x_check_alarms(wc, unit); ++ start_timer = true; ++ } ++ if (isr3 & 0x08) { /* T1 LLBSC */ ++ t43x_check_loopcodes(wc, unit); ++ start_timer = true; ++ } ++ } ++ ++ if (!ts->span.alarms) { ++ if ((isr3 & 0x3) || (isr4 & 0xc0)) ++ ts->span.count.timingslips++; ++ } ++ ++ if (start_timer) { ++ ts->debounce = true; ++ if (!timer_pending(&wc->timer)) ++ mod_timer(&wc->timer, jiffies + HZ/10); ++ } ++} ++ ++static void t43x_handle_interrupt(struct wcxb *xb, u32 pending) ++{ ++ u32 status; ++ struct t43x *wc = container_of(xb, struct t43x, xb); ++ ++ if (!(pending & FALC_INT)) ++ return; ++ ++ /* Service at most one framer per interrupt cycle */ ++ status = t43x_framer_get(wc, 0, FRMR_CIS); ++ if (status & (1 << (wc->intr_span + ((wc->numspans == 2) ? 1 : 0)))) ++ handle_falc_int(wc, wc->intr_span); ++ if (++wc->intr_span >= wc->numspans) ++ wc->intr_span = 0; ++} ++ ++static void t43x_timer(TIMER_DATA_TYPE timer) ++{ ++ struct t43x *wc = from_timer(wc, timer, timer); ++ ++ if (!is_initialized(wc)) ++ return; ++ ++ queue_work(wc->wq, &wc->timer_work); ++ return; ++} ++ ++static int t43x_open(struct dahdi_chan *chan) ++{ ++ struct t43x *wc = chan->pvt; ++ struct t43x_span *ts = container_of(chan->span, struct t43x_span, span); ++ unsigned long flags; ++ ++ if (!(ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN)) ++ return 0; ++ ++ if (!test_and_set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) { ++ local_irq_save(flags); ++ t43x_check_alarms(wc, ts->span.offset); ++ local_irq_restore(flags); ++ } ++ ++ return 0; ++} ++ ++static int t43x_close(struct dahdi_chan *chan) ++{ ++ struct t43x *wc = chan->pvt; ++ struct t43x_span *ts = container_of(chan->span, struct t43x_span, span); ++ unsigned long flags; ++ ++ if (!(ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN)) ++ return 0; ++ ++ if (have_open_channels(ts)) ++ return 0; ++ ++ if (!test_and_set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) { ++ local_irq_save(flags); ++ t43x_check_alarms(wc, ts->span.offset); ++ local_irq_restore(flags); ++ } ++ ++ return 0; ++} ++ ++static const struct dahdi_span_ops t43x_span_ops = { ++ .owner = THIS_MODULE, ++ .spanconfig = t43x_spanconfig, ++ .chanconfig = t43x_chanconfig, ++ .startup = t43x_startup, ++ .rbsbits = t43x_rbsbits, ++ .maint = t43x_maint, ++ .ioctl = t43x_ioctl, ++ .assigned = t43x_span_assigned, ++ .set_spantype = t43x_set_linemode, ++ .echocan_create = t43x_echocan_create, ++ .echocan_name = t43x_echocan_name, ++ .open = t43x_open, ++ .close = t43x_close, ++}; ++ ++/** ++ * t43x_check_for_interrupts - Return 0 if the card is generating interrupts. ++ * @wc: The card to check. ++ * ++ * If the card is not generating interrupts, this function will also place all ++ * the spans on the card into red alarm. ++ * ++ */ ++static int t43x_check_for_interrupts(struct t43x *wc) ++{ ++ unsigned int starting_framecount = wc->xb.framecount; ++ unsigned long stop_time = jiffies + HZ*2; ++ unsigned long flags; ++ int x; ++ ++ msleep(20); ++ spin_lock_irqsave(&wc->reglock, flags); ++ while (starting_framecount == wc->xb.framecount) { ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ if (time_after(jiffies, stop_time)) { ++ for (x = 0; x < wc->numspans; x++) ++ wc->tspans[x]->span.alarms = DAHDI_ALARM_RED; ++ dev_err(&wc->xb.pdev->dev, "Interrupts not detected.\n"); ++ return -EIO; ++ } ++ msleep(100); ++ spin_lock_irqsave(&wc->reglock, flags); ++ } ++ spin_unlock_irqrestore(&wc->reglock, flags); ++ ++ return 0; ++} ++ ++/** ++ * t43x_read_serial - Returns the serial number of the board. ++ * @wc: The board whos serial number we are reading. ++ * ++ * The buffer returned is dynamically allocated and must be kfree'd by the ++ * caller. If memory could not be allocated, NULL is returned. ++ * ++ * Must be called in process context. ++ * ++ */ ++static char *t43x_read_serial(struct t43x *wc) ++{ ++ int i; ++ static const int MAX_SERIAL = 20*5; ++ const unsigned int SERIAL_ADDRESS = 0x1f0000; ++ unsigned char *serial = kzalloc(MAX_SERIAL + 1, GFP_KERNEL); ++ struct wcxb const *xb = &wc->xb; ++ struct wcxb_spi_master *flash_spi_master = NULL; ++ struct wcxb_spi_device *flash_spi_device = NULL; ++ const unsigned int FLASH_SPI_BASE = 0x200; ++ ++ if (!serial) ++ return NULL; ++ ++ flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev, ++ xb->membase + FLASH_SPI_BASE, ++ false); ++ if (!flash_spi_master) ++ return NULL; ++ ++ flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0); ++ if (!flash_spi_device) ++ goto error_exit; ++ ++ wcxb_flash_read(flash_spi_device, SERIAL_ADDRESS, ++ serial, MAX_SERIAL); ++ ++ for (i = 0; i < MAX_SERIAL; ++i) { ++ if ((serial[i] < 0x20) || (serial[i] > 0x7e)) { ++ serial[i] = '\0'; ++ break; ++ } ++ } ++ ++ if (!i) { ++ kfree(serial); ++ serial = NULL; ++ } else { ++ /* Limit the size of the buffer to just what is needed to ++ * actually hold the serial number. */ ++ unsigned char *new_serial; ++ new_serial = kasprintf(GFP_KERNEL, "%s", serial); ++ kfree(serial); ++ serial = new_serial; ++ } ++ ++error_exit: ++ wcxb_spi_device_destroy(flash_spi_device); ++ wcxb_spi_master_destroy(flash_spi_master); ++ return serial; ++} ++ ++ ++/** ++ * t43x_assign_num - Assign wc->num a unique value and place on card_list ++ * ++ */ ++static void t43x_assign_num(struct t43x *wc) ++{ ++ mutex_lock(&card_list_lock); ++ if (list_empty(&card_list)) { ++ wc->num = 0; ++ list_add(&wc->card_node, &card_list); ++ } else { ++ struct t43x *cur; ++ struct list_head *insert_pos; ++ int new_num = 0; ++ ++ insert_pos = &card_list; ++ list_for_each_entry(cur, &card_list, card_node) { ++ if (new_num != cur->num) ++ break; ++ new_num++; ++ insert_pos = &cur->card_node; ++ } ++ ++ wc->num = new_num; ++ list_add_tail(&wc->card_node, insert_pos); ++ } ++ mutex_unlock(&card_list_lock); ++} ++ ++/* ++ * Initialize the card (one time) ++ * ++ */ ++static int __devinit t43x_init_one(struct pci_dev *pdev, ++ const struct pci_device_id *ent) ++{ ++ struct t43x *wc; ++ struct t43x_span *ts; ++ unsigned int x; ++ int res; ++ enum linemode type; ++ ++ wc = kzalloc(sizeof(*wc), GFP_KERNEL); ++ if (!wc) { ++ pci_disable_device(pdev); ++ return -ENOMEM; ++ } ++ ++ t43x_assign_num(wc); ++ ++ wc->blinktimer = jiffies; ++ dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ wc->not_ready = 1; ++ ++ spin_lock_init(&wc->reglock); ++ ++ pci_set_drvdata(pdev, wc); ++ wc->xb.pdev = pdev; ++ wc->xb.ops = &xb_ops; ++ wc->xb.debug = &debug; ++ ++ res = wcxb_init(&wc->xb, KBUILD_MODNAME, 0); ++ if (res) ++ goto fail_exit; ++ ++ mutex_init(&wc->lock); ++ timer_setup(&wc->timer, t43x_timer, 0); ++ ++ INIT_WORK(&wc->timer_work, timer_work_func); ++ INIT_DELAYED_WORK(&wc->clksrc_work.work, t43x_clksrc_work_fn); ++ spin_lock_init(&wc->clksrc_work.lock); ++ ++ wc->ddev = dahdi_create_device(); ++ if (!wc->ddev) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ wc->ddev->manufacturer = "Digium"; ++ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d", ++ pdev->bus->number, ++ PCI_SLOT(pdev->devfn) + 1); ++ if (!wc->ddev->location) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ ++ wc->ddev->hardware_id = t43x_read_serial(wc); ++ ++ if (wc->ddev->hardware_id == NULL) { ++ dev_info(&wc->xb.pdev->dev, "Unable to read valid serial number\n"); ++ res = -EIO; ++ goto fail_exit; ++ } ++ ++ if (strncmp(wc->ddev->hardware_id, "1TE435F", 7) == 0) { ++ /* Quad-span PCIE */ ++ wc->numspans = 4; ++ wc->devtype = &te435; ++ } else if (strncmp(wc->ddev->hardware_id, "1TE235F", 7) == 0) { ++ /* Dual-span PCIE */ ++ wc->numspans = 2; ++ wc->devtype = &te235; ++ } else if (strncmp(wc->ddev->hardware_id, "1TE436F", 7) == 0) { ++ /* Quad-span PCI */ ++ wc->numspans = 4; ++ wc->devtype = &te436; ++ } else if (strncmp(wc->ddev->hardware_id, "1TE236F", 7) == 0) { ++ /* Dual-span PCI */ ++ wc->numspans = 2; ++ wc->devtype = &te236; ++ } else { ++ dev_info(&wc->xb.pdev->dev, ++ "Unable to identify board type from serial number %s\n", ++ wc->ddev->hardware_id); ++ res = -EIO; ++ goto fail_exit; ++ } ++ ++ /* Check for field updatable firmware */ ++ if ((wc->devtype == &te435) || (wc->devtype == &te235)) { ++ res = wcxb_check_firmware(&wc->xb, TE435_VERSION, ++ TE435_FW_FILENAME, force_firmware, WCXB_RESET_NOW); ++ } else if ((wc->devtype == &te436) || (wc->devtype == &te236)) { ++ res = wcxb_check_firmware(&wc->xb, TE436_VERSION, ++ TE436_FW_FILENAME, force_firmware, WCXB_RESET_NOW); ++ } else { ++ res = -EIO; ++ } ++ ++ if (res) ++ goto fail_exit; ++ ++ for (x = 0; x < wc->numspans; x++) { ++ ts = kzalloc(sizeof(*wc->tspans[x]), GFP_KERNEL); ++ if (!ts) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ wc->tspans[x] = ts; ++ } ++ ++ wc->wq = create_singlethread_workqueue(KBUILD_MODNAME); ++ if (!wc->wq) { ++ res = -ENOMEM; ++ goto fail_exit; ++ } ++ ++ wcxb_set_minlatency(&wc->xb, latency); ++ wcxb_set_maxlatency(&wc->xb, max_latency); ++ ++ create_sysfs_files(wc); ++ ++ res = t43x_hardware_post_init(wc, &type); ++ if (res) ++ goto fail_exit; ++ ++ t43x_init_spans(wc, type); ++ ++ if (!wc->vpm) ++ t43x_vpm_init(wc); ++ ++ if (wc->vpm) { ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, ++ "%s (%s)", wc->devtype->name, ++ wc->vpm_name); ++ } else { ++ wc->ddev->devicetype = kasprintf(GFP_KERNEL, ++ "%s", wc->devtype->name); ++ } ++ ++ res = dahdi_register_device(wc->ddev, &wc->xb.pdev->dev); ++ if (res) { ++ dev_info(&wc->xb.pdev->dev, "Unable to register with DAHDI\n"); ++ goto fail_exit; ++ } ++ ++ if (wc->ddev->hardware_id) { ++ dev_info(&wc->xb.pdev->dev, "Found a %s (SN: %s)\n", ++ wc->devtype->name, wc->ddev->hardware_id); ++ } else { ++ dev_info(&wc->xb.pdev->dev, "Found a %s\n", ++ wc->devtype->name); ++ } ++ ++ wc->not_ready = 0; ++ return 0; ++ ++fail_exit: ++ if (&wc->xb) ++ wcxb_release(&wc->xb); ++ ++ if (debug) ++ dev_info(&wc->xb.pdev->dev, "***At fail_exit in init_one***\n"); ++ ++ for (x = 0; x < wc->numspans; x++) ++ kfree(wc->tspans[x]); ++ ++ free_wc(wc); ++ return res; ++} ++ ++static void __devexit t43x_remove_one(struct pci_dev *pdev) ++{ ++ struct t43x *wc = pci_get_drvdata(pdev); ++ dev_info(&wc->xb.pdev->dev, "Removing a Wildcard TE43x.\n"); ++ ++ if (!wc) ++ return; ++ ++ wc->not_ready = 1; ++ smp_mb__after_atomic(); ++ ++ /* Stop everything */ ++ wcxb_stop(&wc->xb); ++ ++ /* Leave framer in reset so it no longer transmits */ ++ wcxb_gpio_clear(&wc->xb, FALC_CPU_RESET); ++ ++ /* Turn off status LEDs */ ++ t43x_setleds(wc, 0); ++ ++ if (wc->vpm) ++ release_vpm450m(wc->vpm); ++ wc->vpm = NULL; ++ ++ cancel_delayed_work_sync(&wc->clksrc_work.work); ++ ++ del_timer_sync(&wc->timer); ++ flush_workqueue(wc->wq); ++ del_timer_sync(&wc->timer); ++ ++ dahdi_unregister_device(wc->ddev); ++ ++ remove_sysfs_files(wc); ++ ++ wcxb_release(&wc->xb); ++ free_wc(wc); ++} ++ ++static DEFINE_PCI_DEVICE_TABLE(t43x_pci_tbl) = { ++ { 0xd161, 0x800e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, ++ { 0xd161, 0x8013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, ++ { 0 } ++}; ++ ++static void t43x_shutdown(struct pci_dev *pdev) ++{ ++ struct t43x *wc = pci_get_drvdata(pdev); ++ dev_info(&wc->xb.pdev->dev, "Quiescing a Wildcard TE43x.\n"); ++ if (!wc) ++ return; ++ ++ /* Stop everything */ ++ wcxb_stop(&wc->xb); ++ ++} ++ ++static int t43x_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ return -ENOSYS; ++} ++ ++MODULE_DEVICE_TABLE(pci, t43x_pci_tbl); ++ ++static struct pci_driver t43x_driver = { ++ .name = "wcte43x", ++ .probe = t43x_init_one, ++ .remove = __devexit_p(t43x_remove_one), ++ .shutdown = t43x_shutdown, ++ .suspend = t43x_suspend, ++ .id_table = t43x_pci_tbl, ++}; ++ ++static int __init t43x_init(void) ++{ ++ int res; ++ ++ if (strcasecmp(default_linemode, "t1") && ++ strcasecmp(default_linemode, "j1") && ++ strcasecmp(default_linemode, "e1")) { ++ pr_err("'%s' is an unknown span type.\n", default_linemode); ++ default_linemode = "t1"; ++ return -EINVAL; ++ } ++ ++ res = pci_register_driver(&t43x_driver); ++ if (res) ++ return -ENODEV; ++ ++ return 0; ++} ++ ++ ++static void __exit t43x_cleanup(void) ++{ ++ pci_unregister_driver(&t43x_driver); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++module_param(timingcable, int, 0600); ++module_param(default_linemode, charp, S_IRUGO); ++MODULE_PARM_DESC(default_linemode, "\"t1\"(default), \"e1\", or \"j1\"."); ++module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(losalarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(aisalarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(yelalarmdebounce, int, S_IRUGO | S_IWUSR); ++module_param(vpmsupport, int, 0600); ++module_param(force_firmware, int, S_IRUGO); ++module_param(latency, int, S_IRUGO); ++MODULE_PARM_DESC(latency, "How many milliseconds of audio to buffer between card and host (3ms default). This number will increase during runtime, dynamically, if dahdi detects that it is too small. This is commonly refered to as a \"latency bump\""); ++module_param(max_latency, int, 0600); ++MODULE_PARM_DESC(max_latency, "The maximum amount of latency that the driver will permit."); ++ ++MODULE_DESCRIPTION("Wildcard Digital Card Driver"); ++MODULE_AUTHOR("Digium Incorporated "); ++MODULE_LICENSE("GPL v2"); ++ ++module_init(t43x_init); ++module_exit(t43x_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/wcxb.c linux-source-4.19-dahdi/drivers/dahdi/wcxb.c +--- linux-source-4.19/drivers/dahdi/wcxb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcxb.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,1047 @@ ++/* ++ * wcxb SPI library ++ * ++ * Copyright (C) 2013 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HAVE_RATELIMIT ++#include ++ ++#include ++ ++#include ++ ++#include "wcxb.h" ++#include "wcxb_spi.h" ++#include "wcxb_flash.h" ++ ++/* The definition for Surprise Down was added in Linux 3.6 in (a0dee2e PCI: misc ++ * pci_reg additions). It may be backported though so we won't check for the ++ * version. Same with PCI_EXP_SLTCTL_PDCE. */ ++#ifndef PCI_ERR_UNC_SURPDN ++#define PCI_ERR_UNC_SURPDN 0x20 ++#endif ++#ifndef PCI_EXP_SLTCTL_PDCE ++#define PCI_EXP_SLTCTL_PDCE 0x8 ++#endif ++ ++/* FPGA Status definitions */ ++#define OCT_CPU_RESET (1 << 0) ++#define OCT_CPU_DRAM_CKE (1 << 1) ++#define STATUS_LED_GREEN (1 << 9) ++#define STATUS_LED_RED (1 << 10) ++#define FALC_CPU_RESET (1 << 11) ++ ++/* Descriptor ring definitions */ ++#define DRING_SIZE (1 << 7) /* Must be in multiples of 2 */ ++#define DRING_SIZE_MASK (DRING_SIZE-1) ++#define DESC_EOR (1 << 0) ++#define DESC_INT (1 << 1) ++#define DESC_OWN (1 << 31) ++#define DESC_DEFAULT_STATUS 0xdeadbe00 ++#define DMA_CHAN_SIZE 128 ++ ++/* Echocan definitions */ ++#define OCT_OFFSET (xb->membase + 0x10000) ++#define OCT_CONTROL_REG (OCT_OFFSET + 0) ++#define OCT_DATA_REG (OCT_OFFSET + 0x4) ++#define OCT_ADDRESS_HIGH_REG (OCT_OFFSET + 0x8) ++#define OCT_ADDRESS_LOW_REG (OCT_OFFSET + 0xa) ++#define OCT_DIRECT_WRITE_MASK 0x3001 ++#define OCT_INDIRECT_READ_MASK 0x0101 ++#define OCT_INDIRECT_WRITE_MASK 0x3101 ++ ++ ++/* DMA definitions */ ++#define TDM_DRING_ADDR 0x2000 ++#define TDM_CONTROL (TDM_DRING_ADDR + 0x4) ++#define ENABLE_ECHOCAN_TDM (1 << 0) ++#define TDM_RECOVER_CLOCK (1 << 1) ++#define ENABLE_DMA (1 << 2) ++#define DMA_RUNNING (1 << 3) ++#define DMA_LOOPBACK (1 << 4) ++#define AUTHENTICATED (1 << 5) ++#define TDM_VERSION (TDM_DRING_ADDR + 0x24) ++ ++/* Interrupt definitions */ ++#define INTERRUPT_CONTROL 0x300 ++#define ISR (INTERRUPT_CONTROL + 0x0) ++#define IPR (INTERRUPT_CONTROL + 0x4) ++#define IER (INTERRUPT_CONTROL + 0x8) ++#define IAR (INTERRUPT_CONTROL + 0xc) ++#define SIE (INTERRUPT_CONTROL + 0x10) ++#define CIE (INTERRUPT_CONTROL + 0x14) ++#define IVR (INTERRUPT_CONTROL + 0x18) ++#define MER (INTERRUPT_CONTROL + 0x1c) ++#define MER_ME (1<<0) ++#define MER_HIE (1<<1) ++#define DESC_UNDERRUN (1<<0) ++#define DESC_COMPLETE (1<<1) ++#define OCT_INT (1<<2) ++#define FALC_INT (1<<3) ++#define SPI_INT (1<<4) ++ ++#define FLASH_SPI_BASE 0x200 ++ ++struct wcxb_hw_desc { ++ volatile __be32 status; ++ __be32 tx_buf; ++ __be32 rx_buf; ++ volatile __be32 control; ++} __packed; ++ ++struct wcxb_meta_desc { ++ void *tx_buf_virt; ++ void *rx_buf_virt; ++}; ++ ++static inline bool wcxb_is_pcie(const struct wcxb *xb) ++{ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 33) ++ return pci_is_pcie(xb->pdev); ++#else ++ return (xb->pdev->is_pcie > 0); ++#endif ++} ++ ++static const unsigned int CLK_SRC_MASK = ((1 << 13) | (1 << 12) | (1 << 1)); ++ ++enum wcxb_clock_sources wcxb_get_clksrc(struct wcxb *xb) ++{ ++ static const u32 SELF = 0x0; ++ static const u32 RECOVER = (1 << 1); ++ static const u32 SLAVE = (1 << 12) | (1 << 1); ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase + TDM_CONTROL) & CLK_SRC_MASK; ++ spin_unlock_irqrestore(&xb->lock, flags); ++ ++ if (SELF == reg) ++ return WCXB_CLOCK_SELF; ++ else if (RECOVER == reg) ++ return WCXB_CLOCK_RECOVER; ++ else if (SLAVE == reg) ++ return WCXB_CLOCK_SLAVE; ++ else ++ WARN_ON(1); ++ return WCXB_CLOCK_SELF; ++} ++ ++void wcxb_set_clksrc(struct wcxb *xb, enum wcxb_clock_sources clksrc) ++{ ++ unsigned long flags; ++ u32 clkbits = 0; ++ ++ switch (clksrc) { ++ case WCXB_CLOCK_RECOVER: ++ if (xb->flags.drive_timing_cable) ++ clkbits = (1<<13) | (1 << 1); ++ else ++ clkbits = (1 << 1); ++ break; ++ case WCXB_CLOCK_SELF: ++ if (xb->flags.drive_timing_cable) ++ clkbits = (1<<13); ++ else ++ clkbits = 0; ++ break; ++ case WCXB_CLOCK_SLAVE: ++ /* When we're slave, do not ever drive the timing cable. */ ++ clkbits = (1<<12) | (1 << 1); ++ break; ++ }; ++ ++ /* set new clock select */ ++ spin_lock_irqsave(&xb->lock, flags); ++ if (!wcxb_is_stopped(xb)) { ++ dev_err(&xb->pdev->dev, "ERROR: Cannot set clock source while DMA engine is running.\n"); ++ } else { ++ u32 reg; ++ reg = ioread32be(xb->membase + TDM_CONTROL); ++ reg &= ~CLK_SRC_MASK; ++ reg |= (clkbits & CLK_SRC_MASK); ++ iowrite32be(reg, xb->membase + TDM_CONTROL); ++ } ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++void wcxb_enable_echocan(struct wcxb *xb) ++{ ++ u32 reg; ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase + TDM_CONTROL); ++ reg |= ENABLE_ECHOCAN_TDM; ++ iowrite32be(reg, xb->membase + TDM_CONTROL); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++void wcxb_disable_echocan(struct wcxb *xb) ++{ ++ u32 reg; ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase + TDM_CONTROL); ++ reg &= ~ENABLE_ECHOCAN_TDM; ++ iowrite32be(reg, xb->membase + TDM_CONTROL); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++void wcxb_reset_echocan(struct wcxb *xb) ++{ ++ unsigned long flags; ++ int reg; ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase); ++ iowrite32be((reg & ~OCT_CPU_RESET), xb->membase); ++ spin_unlock_irqrestore(&xb->lock, flags); ++ ++ msleep_interruptible(1); ++ ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase); ++ iowrite32be((reg | OCT_CPU_RESET), xb->membase); ++ spin_unlock_irqrestore(&xb->lock, flags); ++ ++ dev_dbg(&xb->pdev->dev, "Reset octasic\n"); ++} ++ ++bool wcxb_is_echocan_present(struct wcxb *xb) ++{ ++ return 0x1 == ioread16be(OCT_CONTROL_REG); ++} ++ ++void wcxb_enable_echocan_dram(struct wcxb *xb) ++{ ++ unsigned long flags; ++ int reg; ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase); ++ iowrite32be((reg | OCT_CPU_DRAM_CKE), xb->membase); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++u16 wcxb_get_echocan_reg(struct wcxb *xb, u32 address) ++{ ++ uint16_t highaddress = ((address >> 20) & 0xfff); ++ uint16_t lowaddress = ((address >> 4) & 0xfffff); ++ unsigned long stop = jiffies + HZ/10; ++ unsigned long flags; ++ u16 ret; ++ ++ spin_lock_irqsave(&xb->lock, flags); ++ iowrite16be(highaddress, OCT_ADDRESS_HIGH_REG); ++ iowrite16be(lowaddress, OCT_ADDRESS_LOW_REG); ++ ++ iowrite16be(OCT_INDIRECT_READ_MASK | ((address & 0xe) << 8), ++ OCT_CONTROL_REG); ++ do { ++ ret = ioread16be(OCT_CONTROL_REG); ++ } while ((ret & (1<<8)) && time_before(jiffies, stop)); ++ ++ WARN_ON_ONCE(time_after_eq(jiffies, stop)); ++ ++ ret = ioread16be(OCT_DATA_REG); ++ spin_unlock_irqrestore(&xb->lock, flags); ++ ++ return ret; ++} ++ ++void wcxb_set_echocan_reg(struct wcxb *xb, u32 address, u16 val) ++{ ++ unsigned long flags; ++ uint16_t ret; ++ uint16_t highaddress = ((address >> 20) & 0xfff); ++ uint16_t lowaddress = ((address >> 4) & 0xffff); ++ unsigned long stop = jiffies + HZ/10; ++ ++ spin_lock_irqsave(&xb->lock, flags); ++ iowrite16be(highaddress, OCT_ADDRESS_HIGH_REG); ++ iowrite16be(lowaddress, OCT_ADDRESS_LOW_REG); ++ ++ iowrite16be(val, OCT_DATA_REG); ++ iowrite16be(OCT_INDIRECT_WRITE_MASK | ((address & 0xe) << 8), ++ OCT_CONTROL_REG); ++ ++ /* No write should take longer than 100ms */ ++ do { ++ ret = ioread16be(OCT_CONTROL_REG); ++ } while ((ret & (1<<8)) && time_before(jiffies, stop)); ++ spin_unlock_irqrestore(&xb->lock, flags); ++ ++ WARN_ON_ONCE(time_after_eq(jiffies, stop)); ++} ++ ++#ifdef HAVE_RATELIMIT ++static DEFINE_RATELIMIT_STATE(_underrun_rl, DEFAULT_RATELIMIT_INTERVAL, ++ DEFAULT_RATELIMIT_BURST); ++#endif ++ ++/* wcxb_reset_dring needs to be called with xb->lock held. */ ++static void _wcxb_reset_dring(struct wcxb *xb) ++{ ++ int x; ++ struct wcxb_meta_desc *mdesc; ++ struct wcxb_hw_desc *hdesc = NULL; ++ ++ xb->dma_head = xb->dma_tail = 0; ++ ++ if (unlikely(xb->latency > DRING_SIZE)) { ++#ifdef HAVE_RATELIMIT ++ if (__ratelimit(&_underrun_rl)) { ++#else ++ if (printk_ratelimit()) { ++#endif ++ dev_info(&xb->pdev->dev, ++ "Oops! Tried to increase latency past buffer size.\n"); ++ } ++ xb->latency = DRING_SIZE; ++ } ++ ++ for (x = 0; x < xb->latency; x++) { ++ dma_addr_t dma_tmp; ++ ++ mdesc = &xb->meta_dring[x]; ++ hdesc = &xb->hw_dring[x]; ++ ++ hdesc->status = cpu_to_be32(DESC_DEFAULT_STATUS); ++ if (!mdesc->tx_buf_virt) { ++ mdesc->tx_buf_virt = ++ dma_pool_alloc(xb->pool, GFP_ATOMIC, &dma_tmp); ++ hdesc->tx_buf = cpu_to_be32(dma_tmp); ++ mdesc->rx_buf_virt = ++ dma_pool_alloc(xb->pool, GFP_ATOMIC, &dma_tmp); ++ hdesc->rx_buf = cpu_to_be32(dma_tmp); ++ } ++ hdesc->control = cpu_to_be32(DESC_INT|DESC_OWN); ++ BUG_ON(!mdesc->tx_buf_virt || !mdesc->rx_buf_virt); ++ } ++ ++ BUG_ON(!hdesc); ++ /* Set end of ring bit in last descriptor to force hw to loop around */ ++ hdesc->control |= cpu_to_be32(DESC_EOR); ++#ifdef DEBUG ++ xb->last_retry_count = 0; ++ xb->max_retry_count = 0; ++ xb->last_dma_time = 0; ++ xb->max_dma_time = 0; ++#endif ++ iowrite32be(xb->hw_dring_phys, xb->membase + TDM_DRING_ADDR); ++} ++ ++static void wcxb_handle_dma(struct wcxb *xb) ++{ ++ struct wcxb_meta_desc *mdesc; ++ struct wcxb_hw_desc *tail = &(xb->hw_dring[xb->dma_tail]); ++ ++ while (!(tail->control & cpu_to_be32(DESC_OWN))) { ++ u_char *frame; ++ ++#ifdef DEBUG ++ xb->last_retry_count = ++ ((be32_to_cpu(tail->control) & 0x0000ff00) >> 8); ++ xb->last_dma_time = (be32_to_cpu(tail->status)); ++#endif ++ ++ mdesc = &xb->meta_dring[xb->dma_tail]; ++ frame = mdesc->rx_buf_virt; ++ ++ xb->ops->handle_receive(xb, frame); ++ ++ xb->dma_tail = ++ (xb->dma_tail == xb->latency-1) ? 0 : xb->dma_tail + 1; ++ tail = &(xb->hw_dring[xb->dma_tail]); ++ ++ mdesc = &xb->meta_dring[xb->dma_head]; ++ frame = mdesc->tx_buf_virt; ++ ++ xb->ops->handle_transmit(xb, frame); ++ ++ wmb(); ++ xb->hw_dring[xb->dma_head].control |= cpu_to_be32(DESC_OWN); ++ xb->dma_head = ++ (xb->dma_head == xb->latency-1) ? 0 : xb->dma_head + 1; ++ } ++ ++#ifdef DEBUG ++ if (xb->last_retry_count > xb->max_retry_count) { ++ xb->max_retry_count = xb->last_retry_count; ++ dev_info(&xb->pdev->dev, ++ "New DMA max retries detected: %d\n", ++ xb->max_retry_count); ++ } ++ if (xb->last_dma_time > xb->max_dma_time) { ++ xb->max_dma_time = xb->last_dma_time; ++ dev_info(&xb->pdev->dev, ++ "New DMA max transfer time detected: %d\n", ++ xb->max_dma_time); ++ } ++#endif ++} ++ ++static irqreturn_t _wcxb_isr(int irq, void *dev_id) ++{ ++ struct wcxb *xb = dev_id; ++ unsigned int limit = 8; ++ u32 pending; ++ ++ pending = ioread32be(xb->membase + ISR); ++ if (!pending) ++ return IRQ_NONE; ++ ++ do { ++ iowrite32be(pending, xb->membase + IAR); ++ ++ if (pending & DESC_UNDERRUN) { ++ u32 reg; ++ ++ /* Report the error in case drivers have any custom ++ * methods for indicating potential data corruption. An ++ * underrun means data loss in the TDM channel. */ ++ if (xb->ops->handle_error) ++ xb->ops->handle_error(xb); ++ ++ spin_lock(&xb->lock); ++ ++ if (!xb->flags.latency_locked) { ++ /* bump latency */ ++ ++ xb->latency = min(xb->latency + 1, ++ xb->max_latency); ++#ifdef HAVE_RATELIMIT ++ if (__ratelimit(&_underrun_rl)) { ++#else ++ if (printk_ratelimit()) { ++#endif ++ if (xb->latency != xb->max_latency) { ++ dev_info(&xb->pdev->dev, ++ "Underrun detected by hardware. Latency bumped to: %dms\n", ++ xb->latency); ++ } else { ++ dev_info(&xb->pdev->dev, ++ "Underrun detected by hardware. Latency at max of %dms.\n", ++ xb->latency); ++ } ++ } ++ } ++ ++ /* re-setup dma ring */ ++ _wcxb_reset_dring(xb); ++ ++ /* set dma enable bit */ ++ reg = ioread32be(xb->membase + TDM_CONTROL); ++ reg |= ENABLE_DMA; ++ iowrite32be(reg, xb->membase + TDM_CONTROL); ++ ++ spin_unlock(&xb->lock); ++ } ++ ++ if (pending & DESC_COMPLETE) { ++ xb->framecount++; ++ wcxb_handle_dma(xb); ++ } ++ ++ if (NULL != xb->ops->handle_interrupt) ++ xb->ops->handle_interrupt(xb, pending); ++ ++ pending = ioread32be(xb->membase + ISR); ++ } while (pending && --limit); ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t wcxb_isr(int irq, void *dev_id) ++{ ++ irqreturn_t ret; ++ unsigned long flags; ++ local_irq_save(flags); ++ ret = _wcxb_isr(irq, dev_id); ++ local_irq_restore(flags); ++ return ret; ++} ++ ++static int wcxb_alloc_dring(struct wcxb *xb, const char *board_name) ++{ ++ xb->meta_dring = ++ kzalloc(sizeof(struct wcxb_meta_desc) * DRING_SIZE, ++ GFP_KERNEL); ++ if (!xb->meta_dring) ++ return -ENOMEM; ++ ++ xb->hw_dring = dma_alloc_coherent(&xb->pdev->dev, ++ sizeof(struct wcxb_hw_desc) * DRING_SIZE, ++ &xb->hw_dring_phys, ++ GFP_KERNEL); ++ if (!xb->hw_dring) { ++ kfree(xb->meta_dring); ++ return -ENOMEM; ++ } ++ ++ xb->pool = dma_pool_create(board_name, &xb->pdev->dev, ++ PAGE_SIZE, PAGE_SIZE, 0); ++ if (!xb->pool) { ++ kfree(xb->meta_dring); ++ dma_free_coherent(&xb->pdev->dev, ++ sizeof(struct wcxb_hw_desc) * DRING_SIZE, ++ xb->hw_dring, ++ xb->hw_dring_phys); ++ return -ENOMEM; ++ } ++ return 0; ++} ++ ++/** ++ * wcxb_soft_reset - Set interface registers back to known good values. ++ * ++ * This represents the normal default state after a reset of the FPGA. This ++ * function is preferred over the hard reset function. ++ * ++ */ ++static void wcxb_soft_reset(struct wcxb *xb) ++{ ++ /* digium_gpo */ ++ iowrite32be(0x0, xb->membase); ++ ++ /* xps_intc */ ++ iowrite32be(0x0, xb->membase + 0x300); ++ iowrite32be(0x0, xb->membase + 0x308); ++ iowrite32be(0x0, xb->membase + 0x310); ++ iowrite32be(0x0, xb->membase + 0x31C); ++ ++ /* xps_spi_config_flash */ ++ iowrite32be(0xA, xb->membase + 0x200); ++ ++ /* tdm engine */ ++ iowrite32be(0x0, xb->membase + 0x2000); ++ iowrite32be(0x0, xb->membase + 0x2004); ++} ++ ++static void _wcxb_hard_reset(struct wcxb *xb) ++{ ++ struct pci_dev *const pdev = xb->pdev; ++ u32 microblaze_version; ++ unsigned long stop_time = jiffies + msecs_to_jiffies(2000); ++ ++ pci_save_state(pdev); ++ iowrite32be(0xe00, xb->membase + TDM_CONTROL); ++ ++ /* This sleep is to give FPGA time to bring up the PCI/PCIe interface */ ++ msleep(200); ++ ++ pci_restore_state(pdev); ++ ++ /* Wait for the Microblaze CPU to complete it's startup */ ++ do { ++ msleep(20); ++ /* Can return either 0xffff or 0 before it's fully booted */ ++ microblaze_version = ioread32be(xb->membase + 0x2018) ?: 0xffff; ++ } while (time_before(jiffies, stop_time) ++ && 0xffff == microblaze_version); ++} ++ ++/* ++ * Since the FPGA hard reset drops the PCIe link we need to disable ++ * error reporting on the upsteam link. Otherwise Surprise Down errors ++ * may be reported in reponse to the link going away. ++ * ++ * NOTE: We cannot use pci_disable_pcie_error_reporting() because it will not ++ * disable error reporting if the system firmware is attached to the advanced ++ * error reporting mechanism. ++ */ ++static void _wcxb_pcie_hard_reset(struct wcxb *xb) ++{ ++ struct pci_dev *const parent = xb->pdev->bus->self; ++ u32 aer_mask; ++ u16 sltctl; ++ int pos_err; ++ int pos_exp; ++ ++ if (!wcxb_is_pcie(xb)) ++ return; ++ ++ pos_err = pci_find_ext_capability(parent, PCI_EXT_CAP_ID_ERR); ++ if (pos_err) { ++ pci_read_config_dword(parent, pos_err + PCI_ERR_UNCOR_MASK, ++ &aer_mask); ++ pci_write_config_dword(parent, pos_err + PCI_ERR_UNCOR_MASK, ++ aer_mask | PCI_ERR_UNC_SURPDN); ++ } ++ ++ /* Also disable any presence change reporting. */ ++ pos_exp = pci_find_capability(parent, PCI_CAP_ID_EXP); ++ if (pos_exp) { ++ pci_read_config_word(parent, pos_exp + PCI_EXP_SLTCTL, ++ &sltctl); ++ pci_write_config_word(parent, pos_exp + PCI_EXP_SLTCTL, ++ sltctl & ~PCI_EXP_SLTCTL_PDCE); ++ } ++ ++ _wcxb_hard_reset(xb); ++ ++ if (pos_exp) ++ pci_write_config_word(parent, pos_exp + PCI_EXP_SLTCTL, sltctl); ++ ++ if (pos_err) { ++ pci_write_config_dword(parent, pos_err + PCI_ERR_UNCOR_MASK, ++ aer_mask); ++ ++ /* Clear the error as well from the status register. */ ++ pci_write_config_dword(parent, pos_err + PCI_ERR_UNCOR_STATUS, ++ PCI_ERR_UNC_SURPDN); ++ } ++ ++ return; ++} ++ ++/** ++ * wcxb_hard_reset - Reset FPGA and reload firmware. ++ * ++ * This may be called in the context of device probe and therefore the PCI ++ * device may be locked. ++ * ++ */ ++static void wcxb_hard_reset(struct wcxb *xb) ++{ ++ if (wcxb_is_pcie(xb)) ++ _wcxb_pcie_hard_reset(xb); ++ else ++ _wcxb_hard_reset(xb); ++} ++ ++int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode) ++{ ++ int res = 0; ++ struct pci_dev *pdev = xb->pdev; ++ u32 tdm_control; ++ ++ if (pci_enable_device(pdev)) ++ return -EIO; ++ ++ pci_set_master(pdev); ++ ++ WARN_ON(!pdev); ++ if (!pdev) ++ return -EINVAL; ++ ++ xb->latency = WCXB_DEFAULT_LATENCY; ++ xb->max_latency = WCXB_DEFAULT_MAXLATENCY; ++ ++ spin_lock_init(&xb->lock); ++ ++ xb->membase = pci_iomap(pdev, 0, 0); ++ if (pci_request_regions(pdev, board_name)) ++ dev_info(&xb->pdev->dev, "Unable to request regions\n"); ++ ++ wcxb_soft_reset(xb); ++ ++ res = wcxb_alloc_dring(xb, board_name); ++ if (res) { ++ dev_err(&xb->pdev->dev, ++ "Failed to allocate descriptor rings.\n"); ++ goto fail_exit; ++ } ++ ++ /* Enable writes to fpga status register */ ++ iowrite32be(0, xb->membase + 0x04); ++ ++ xb->flags.have_msi = (int_mode) ? 0 : (0 == pci_enable_msi(pdev)); ++ ++ if (request_irq(pdev->irq, wcxb_isr, ++ (xb->flags.have_msi) ? 0 : IRQF_SHARED, ++ board_name, xb)) { ++ dev_notice(&xb->pdev->dev, "Unable to request IRQ %d\n", ++ pdev->irq); ++ res = -EIO; ++ goto fail_exit; ++ } ++ ++ iowrite32be(0, xb->membase + TDM_CONTROL); ++ tdm_control = ioread32be(xb->membase + TDM_CONTROL); ++ if (!(tdm_control & 0x20)) { ++ dev_err(&xb->pdev->dev, ++ "This board is not authenticated and may not function properly.\n"); ++ msleep(1000); ++ } else { ++ dev_dbg(&xb->pdev->dev, "Authenticated. %08x\n", tdm_control); ++ } ++ ++ return res; ++fail_exit: ++ pci_release_regions(xb->pdev); ++ return res; ++} ++ ++void wcxb_stop_dma(struct wcxb *xb) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ /* Quiesce DMA engine interrupts */ ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase + TDM_CONTROL); ++ reg &= ~ENABLE_DMA; ++ iowrite32be(reg, xb->membase + TDM_CONTROL); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++int wcxb_wait_for_stop(struct wcxb *xb, unsigned long timeout_ms) ++{ ++ unsigned long stop; ++ stop = jiffies + msecs_to_jiffies(timeout_ms); ++ do { ++ if (time_after(jiffies, stop)) ++ return -EIO; ++ else ++ cpu_relax(); ++ } while (!wcxb_is_stopped(xb)); ++ ++ return 0; ++} ++ ++void wcxb_disable_interrupts(struct wcxb *xb) ++{ ++ iowrite32be(0, xb->membase + IER); ++} ++ ++void wcxb_stop(struct wcxb *xb) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ /* Stop everything */ ++ iowrite32be(0, xb->membase + TDM_CONTROL); ++ iowrite32be(0, xb->membase + IER); ++ iowrite32be(0, xb->membase + MER); ++ iowrite32be(-1, xb->membase + IAR); ++ /* Flush quiesce commands before exit */ ++ ioread32be(xb->membase); ++ spin_unlock_irqrestore(&xb->lock, flags); ++ synchronize_irq(xb->pdev->irq); ++} ++ ++bool wcxb_is_stopped(struct wcxb *xb) ++{ ++ return !(ioread32be(xb->membase + TDM_CONTROL) & DMA_RUNNING); ++} ++ ++static void wcxb_free_dring(struct wcxb *xb) ++{ ++ struct wcxb_meta_desc *mdesc; ++ struct wcxb_hw_desc *hdesc; ++ int i; ++ ++ /* Free tx/rx buffs */ ++ for (i = 0; i < DRING_SIZE; i++) { ++ mdesc = &xb->meta_dring[i]; ++ hdesc = &xb->hw_dring[i]; ++ if (mdesc->tx_buf_virt) { ++ dma_pool_free(xb->pool, ++ mdesc->tx_buf_virt, ++ be32_to_cpu(hdesc->tx_buf)); ++ dma_pool_free(xb->pool, ++ mdesc->rx_buf_virt, ++ be32_to_cpu(hdesc->rx_buf)); ++ } ++ } ++ ++ dma_pool_destroy(xb->pool); ++ dma_free_coherent(&xb->pdev->dev, ++ sizeof(struct wcxb_hw_desc) * DRING_SIZE, ++ xb->hw_dring, ++ xb->hw_dring_phys); ++ kfree(xb->meta_dring); ++} ++ ++void wcxb_release(struct wcxb *xb) ++{ ++ wcxb_stop(xb); ++ synchronize_irq(xb->pdev->irq); ++ free_irq(xb->pdev->irq, xb); ++ if (xb->flags.have_msi) ++ pci_disable_msi(xb->pdev); ++ if (xb->membase) ++ pci_iounmap(xb->pdev, xb->membase); ++ wcxb_free_dring(xb); ++ pci_release_regions(xb->pdev); ++ pci_disable_device(xb->pdev); ++ return; ++} ++ ++int wcxb_start(struct wcxb *xb) ++{ ++ u32 reg; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&xb->lock, flags); ++ _wcxb_reset_dring(xb); ++ /* Enable hardware interrupts */ ++ iowrite32be(-1, xb->membase + IAR); ++ iowrite32be(DESC_UNDERRUN|DESC_COMPLETE, xb->membase + IER); ++ /* iowrite32be(0x3f7, xb->membase + IER); */ ++ iowrite32be(MER_ME|MER_HIE, xb->membase + MER); ++ ++ /* Start the DMA engine processing. */ ++ reg = ioread32be(xb->membase + TDM_CONTROL); ++ reg |= ENABLE_DMA; ++ iowrite32be(reg, xb->membase + TDM_CONTROL); ++ ++ spin_unlock_irqrestore(&xb->lock, flags); ++ ++ return 0; ++} ++ ++struct wcxb_meta_block { ++ __le32 chksum; ++ __le32 version; ++ __le32 size; ++} __packed; ++ ++struct wcxb_firm_header { ++ u8 header[6]; ++ __le32 chksum; ++ u8 pad[18]; ++ __le32 version; ++} __packed; ++ ++u32 wcxb_get_firmware_version(struct wcxb *xb) ++{ ++ u32 version = 0; ++ ++ /* Two version registers are read and catenated into one */ ++ /* Firmware version goes in bits upper byte */ ++ version = ((ioread32be(xb->membase + 0x400) & 0xffff)<<16); ++ ++ /* Microblaze version goes in lower word */ ++ version += ioread32be(xb->membase + 0x2018); ++ ++ return version; ++} ++ ++static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw, ++ const char *filename, ++ enum wcxb_reset_option reset) ++{ ++ u32 tdm_control; ++ static const int APPLICATION_ADDRESS = 0x200000; ++ static const int META_BLOCK_OFFSET = 0x170000; ++ static const int ERASE_BLOCK_SIZE = 0x010000; ++ static const int END_OFFSET = APPLICATION_ADDRESS + META_BLOCK_OFFSET + ++ ERASE_BLOCK_SIZE; ++ struct wcxb_spi_master *flash_spi_master; ++ struct wcxb_spi_device *flash_spi_device; ++ struct wcxb_meta_block meta; ++ int offset; ++ struct wcxb_firm_header *head = (struct wcxb_firm_header *)(fw->data); ++ ++ if (fw->size > (META_BLOCK_OFFSET + sizeof(*head))) { ++ dev_err(&xb->pdev->dev, ++ "Firmware is too large to fit in available space.\n"); ++ ++ return -EINVAL; ++ } ++ ++ meta.size = cpu_to_le32(fw->size); ++ meta.version = head->version; ++ meta.chksum = head->chksum; ++ ++ flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev, ++ xb->membase + FLASH_SPI_BASE, ++ false); ++ ++ flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0); ++ ++ dev_info(&xb->pdev->dev, ++ "Uploading %s. This can take up to 30 seconds.\n", filename); ++ ++ ++ /* First erase all the blocks in the application area. */ ++ offset = APPLICATION_ADDRESS; ++ while (offset < END_OFFSET) { ++ wcxb_flash_sector_erase(flash_spi_device, offset); ++ offset += ERASE_BLOCK_SIZE; ++ } ++ ++ /* Then write the new firmware file. */ ++ wcxb_flash_write(flash_spi_device, APPLICATION_ADDRESS, ++ &fw->data[sizeof(struct wcxb_firm_header)], ++ fw->size - sizeof(struct wcxb_firm_header)); ++ ++ /* Finally, update the meta block. */ ++ wcxb_flash_write(flash_spi_device, ++ APPLICATION_ADDRESS + META_BLOCK_OFFSET, ++ &meta, sizeof(meta)); ++ ++ if (WCXB_RESET_NOW == reset) { ++ /* Reset fpga after loading firmware */ ++ dev_info(&xb->pdev->dev, ++ "Firmware load complete. Reseting device.\n"); ++ tdm_control = ioread32be(xb->membase + TDM_CONTROL); ++ ++ wcxb_hard_reset(xb); ++ ++ iowrite32be(0, xb->membase + 0x04); ++ iowrite32be(tdm_control, xb->membase + TDM_CONTROL); ++ } else { ++ dev_info(&xb->pdev->dev, ++ "Delaying reset. Firmware load requires a power cycle\n"); ++ } ++ ++ wcxb_spi_device_destroy(flash_spi_device); ++ wcxb_spi_master_destroy(flash_spi_master); ++ return 0; ++} ++ ++int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version, ++ const char *firmware_filename, bool force_firmware, ++ enum wcxb_reset_option reset) ++{ ++ const struct firmware *fw; ++ const struct wcxb_firm_header *header; ++ static const int APPLICATION_ADDRESS = 0x200000; ++ static const int META_BLOCK_OFFSET = 0x170000; ++ struct wcxb_spi_master *flash_spi_master; ++ struct wcxb_spi_device *flash_spi_device; ++ struct wcxb_meta_block meta; ++ int res = 0; ++ u32 crc; ++ u32 version = 0; ++ ++ version = wcxb_get_firmware_version(xb); ++ ++ if (0xff000000 == (version & 0xff000000)) { ++ dev_info(&xb->pdev->dev, ++ "Invalid firmware %x. Please check your hardware.\n", ++ version); ++ return -EIO; ++ } ++ ++ if ((expected_version == version) && !force_firmware) { ++ dev_info(&xb->pdev->dev, "Firmware version: %x\n", version); ++ return 0; ++ } ++ ++ /* Check meta firmware version for a not-booted application image */ ++ flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev, ++ xb->membase + FLASH_SPI_BASE, ++ false); ++ flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0); ++ res = wcxb_flash_read(flash_spi_device, ++ APPLICATION_ADDRESS + META_BLOCK_OFFSET, ++ &meta, sizeof(meta)); ++ if (res) { ++ dev_info(&xb->pdev->dev, "Unable to read flash\n"); ++ return -EIO; ++ } ++ ++ if ((meta.version == cpu_to_le32(expected_version)) ++ && !force_firmware) { ++ dev_info(&xb->pdev->dev, ++ "Detected previous firmware updated to current version %x, but %x is currently running on card. You likely need to power cycle your system.\n", ++ expected_version, version); ++ return 0; ++ } ++ ++ if (force_firmware) { ++ dev_info(&xb->pdev->dev, ++ "force_firmware module parameter is set. Forcing firmware load, regardless of version\n"); ++ } else { ++ dev_info(&xb->pdev->dev, ++ "Firmware version %x is running, but we require version %x.\n", ++ version, expected_version); ++ } ++ ++ res = request_firmware(&fw, firmware_filename, &xb->pdev->dev); ++ if (res) { ++ dev_info(&xb->pdev->dev, ++ "Firmware '%s' not available from userspace.\n", ++ firmware_filename); ++ goto cleanup; ++ } ++ ++ header = (const struct wcxb_firm_header *)fw->data; ++ ++ /* Check the crc */ ++ crc = crc32(~0, &fw->data[10], fw->size - 10) ^ ~0; ++ if (memcmp("DIGIUM", header->header, sizeof(header->header)) || ++ (le32_to_cpu(header->chksum) != crc)) { ++ dev_info(&xb->pdev->dev, ++ "%s is invalid. Please reinstall.\n", ++ firmware_filename); ++ goto cleanup; ++ } ++ ++ /* Check the file vs required firmware versions */ ++ if (le32_to_cpu(header->version) != expected_version) { ++ dev_err(&xb->pdev->dev, ++ "Existing firmware file %s is version %x, but we require %x. Please install the correct firmware file.\n", ++ firmware_filename, le32_to_cpu(header->version), ++ expected_version); ++ res = -EIO; ++ goto cleanup; ++ } ++ ++ dev_info(&xb->pdev->dev, "Found %s (version: %x) Preparing for flash\n", ++ firmware_filename, header->version); ++ ++ res = wcxb_update_firmware(xb, fw, firmware_filename, reset); ++ ++ version = wcxb_get_firmware_version(xb); ++ if (WCXB_RESET_NOW == reset) { ++ dev_info(&xb->pdev->dev, ++ "Reset into firmware version: %x\n", version); ++ } else { ++ dev_info(&xb->pdev->dev, ++ "Running firmware version: %x\n", version); ++ dev_info(&xb->pdev->dev, ++ "Loaded firmware version: %x (Will load after next power cycle)\n", ++ header->version); ++ } ++ ++ if ((WCXB_RESET_NOW == reset) && (expected_version != version) ++ && !force_firmware) { ++ /* On the off chance that the interface is in a state where it ++ * cannot boot into the updated firmware image, power cycling ++ * the card can recover. A simple "reset" of the computer is not ++ * sufficient, power has to be removed completely. */ ++ dev_err(&xb->pdev->dev, ++ "The wrong firmware is running after update. Please power cycle and try again.\n"); ++ res = -EIO; ++ goto cleanup; ++ } ++ ++ if (res) { ++ dev_info(&xb->pdev->dev, ++ "Failed to load firmware %s\n", firmware_filename); ++ } ++ ++cleanup: ++ release_firmware(fw); ++ return res; ++} +diff -Nru linux-source-4.19/drivers/dahdi/wcxb.h linux-source-4.19-dahdi/drivers/dahdi/wcxb.h +--- linux-source-4.19/drivers/dahdi/wcxb.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcxb.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,193 @@ ++/* ++ * wcxb SPI library ++ * ++ * Copyright (C) 2013 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 __WCXB_H__ ++#define __WCXB_H__ ++ ++#define WCXB_DEFAULT_LATENCY 3U ++#define WCXB_DEFAULT_MAXLATENCY 12U ++#define WCXB_DMA_CHAN_SIZE 128 ++ ++struct wcxb; ++ ++struct wcxb_operations { ++ void (*handle_receive)(struct wcxb *xb, void *frame); ++ void (*handle_transmit)(struct wcxb *xb, void *frame); ++ void (*handle_error)(struct wcxb *xb); ++ void (*handle_interrupt)(struct wcxb *xb, u32 pending); ++}; ++ ++struct wcxb_meta_desc; ++struct wcxb_hw_desc; ++ ++/** ++ * struct wcxb - Interface to wcxb firmware. ++ * @last_retry_count: Running count of times firmware had to retry host DMA ++ * transaction. Debugging aide. ++ */ ++struct wcxb { ++ struct pci_dev *pdev; ++ spinlock_t lock; ++ const struct wcxb_operations *ops; ++ unsigned int *debug; ++ unsigned int max_latency; ++ unsigned int latency; ++ struct { ++ u32 have_msi:1; ++ u32 latency_locked:1; ++ u32 drive_timing_cable:1; ++ u32 dma_ins:1; ++ } flags; ++ void __iomem *membase; ++ struct wcxb_meta_desc *meta_dring; ++ struct wcxb_hw_desc *hw_dring; ++ unsigned int dma_head; ++ unsigned int dma_tail; ++ dma_addr_t hw_dring_phys; ++ struct dma_pool *pool; ++ unsigned long framecount; ++#ifdef DEBUG ++ u8 last_retry_count; ++ u8 max_retry_count; ++ u32 last_dma_time; ++ u32 max_dma_time; ++#endif ++}; ++ ++extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode); ++extern void wcxb_release(struct wcxb *xb); ++extern int wcxb_start(struct wcxb *xb); ++extern void wcxb_stop(struct wcxb *xb); ++extern int wcxb_wait_for_stop(struct wcxb *xb, unsigned long timeout_ms); ++extern bool wcxb_is_stopped(struct wcxb *xb); ++ ++enum wcxb_clock_sources { ++ WCXB_CLOCK_SELF, /* Use the internal oscillator for timing. */ ++ WCXB_CLOCK_RECOVER, /* Recover the clock from a framer. */ ++#ifdef RPC_RCLK ++ WCXB_CLOCK_RECOVER_ALT, /* Recover the clock from a framer. */ ++#endif ++ WCXB_CLOCK_SLAVE /* Recover clock from any timing header. */ ++}; ++ ++extern enum wcxb_clock_sources wcxb_get_clksrc(struct wcxb *xb); ++extern void wcxb_set_clksrc(struct wcxb *xb, enum wcxb_clock_sources clksrc); ++ ++static inline void wcxb_enable_timing_header_driver(struct wcxb *xb) ++{ ++ xb->flags.drive_timing_cable = 1; ++} ++static inline bool wcxb_is_timing_header_driver_enabled(struct wcxb *xb) ++{ ++ return 1 == xb->flags.drive_timing_cable; ++} ++ ++static inline void wcxb_disable_timing_header_driver(struct wcxb *xb) ++{ ++ xb->flags.drive_timing_cable = 0; ++} ++ ++enum wcxb_reset_option { ++ WCXB_RESET_NOW, ++ WCXB_RESET_LATER ++}; ++ ++extern u32 wcxb_get_firmware_version(struct wcxb *xb); ++extern int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version, ++ const char *firmware_filename, ++ bool force_firmware, ++ enum wcxb_reset_option reset); ++ ++extern void wcxb_stop_dma(struct wcxb *xb); ++extern void wcxb_disable_interrupts(struct wcxb *xb); ++ ++static inline void wcxb_gpio_set(struct wcxb *xb, u32 bits) ++{ ++ u32 reg; ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase); ++ iowrite32be(reg | bits, xb->membase); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++static inline void wcxb_gpio_clear(struct wcxb *xb, u32 bits) ++{ ++ u32 reg; ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ reg = ioread32be(xb->membase); ++ iowrite32be(reg & (~bits), xb->membase); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++static inline void ++wcxb_set_maxlatency(struct wcxb *xb, unsigned int max_latency) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ xb->max_latency = clamp(max_latency, ++ xb->latency, ++ WCXB_DEFAULT_MAXLATENCY); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++static inline void ++wcxb_set_minlatency(struct wcxb *xb, unsigned int min_latency) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ xb->latency = clamp(min_latency, WCXB_DEFAULT_LATENCY, ++ WCXB_DEFAULT_MAXLATENCY); ++ spin_unlock_irqrestore(&xb->lock, flags); ++} ++ ++static inline void ++wcxb_lock_latency(struct wcxb *xb) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ xb->flags.latency_locked = 1; ++ spin_unlock_irqrestore(&xb->lock, flags); ++ return; ++} ++ ++static inline void ++wcxb_unlock_latency(struct wcxb *xb) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&xb->lock, flags); ++ xb->flags.latency_locked = 0; ++ spin_unlock_irqrestore(&xb->lock, flags); ++ return; ++} ++ ++/* Interface for the echocan block */ ++extern void wcxb_enable_echocan(struct wcxb *xb); ++extern void wcxb_disable_echocan(struct wcxb *xb); ++extern void wcxb_reset_echocan(struct wcxb *xb); ++extern void wcxb_enable_echocan_dram(struct wcxb *xb); ++extern bool wcxb_is_echocan_present(struct wcxb *xb); ++extern u16 wcxb_get_echocan_reg(struct wcxb *xb, u32 address); ++extern void wcxb_set_echocan_reg(struct wcxb *xb, u32 address, u16 val); ++ ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/wcxb_flash.c linux-source-4.19-dahdi/drivers/dahdi/wcxb_flash.c +--- linux-source-4.19/drivers/dahdi/wcxb_flash.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcxb_flash.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,170 @@ ++/* ++ * wcxb SPI library ++ * ++ * Copyright (C) 2013 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 ++ ++#include "wcxb_spi.h" ++#include "wcxb_flash.h" ++ ++#define FLASH_PAGE_PROGRAM 0x02 ++#define FLASH_READ 0x03 ++#define FLASH_READ_STATUS 0x05 ++#define FLASH_WRITE_ENABLE 0x06 ++#define FLASH_SECTOR_ERASE 0xd8 ++ ++static int wcxb_flash_read_status_register(struct wcxb_spi_device *spi, ++ u8 *status) ++{ ++ u8 command[] = { ++ FLASH_READ_STATUS, ++ }; ++ struct wcxb_spi_transfer t_cmd = { ++ .tx_buf = command, ++ .len = sizeof(command), ++ }; ++ struct wcxb_spi_transfer t_serial = { ++ .rx_buf = status, ++ .len = 1, ++ }; ++ struct wcxb_spi_message m; ++ wcxb_spi_message_init(&m); ++ wcxb_spi_message_add_tail(&t_cmd, &m); ++ wcxb_spi_message_add_tail(&t_serial, &m); ++ return wcxb_spi_sync(spi, &m); ++} ++ ++int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address, ++ void *data, size_t len) ++{ ++ u8 command[] = { ++ FLASH_READ, ++ (address & 0xff0000) >> 16, ++ (address & 0xff00) >> 8, ++ (address & 0xff) ++ }; ++ struct wcxb_spi_transfer t_cmd = { ++ .tx_buf = command, ++ .len = sizeof(command), ++ }; ++ struct wcxb_spi_transfer t_serial = { ++ .rx_buf = data, ++ .len = len, ++ }; ++ struct wcxb_spi_message m; ++ wcxb_spi_message_init(&m); ++ wcxb_spi_message_add_tail(&t_cmd, &m); ++ wcxb_spi_message_add_tail(&t_serial, &m); ++ return wcxb_spi_sync(spi, &m); ++} ++ ++static int wcxb_flash_wait_until_not_busy(struct wcxb_spi_device *spi) ++{ ++ int res; ++ u8 status; ++ unsigned long stop = jiffies + 5*HZ; ++ do { ++ res = wcxb_flash_read_status_register(spi, &status); ++ } while (!res && (status & 0x1) && time_before(jiffies, stop)); ++ if (!res) ++ return res; ++ if (time_after_eq(jiffies, stop)) ++ return -EIO; ++ return 0; ++} ++ ++static int wcxb_flash_write_enable(struct wcxb_spi_device *spi) ++{ ++ u8 command = FLASH_WRITE_ENABLE; ++ return wcxb_spi_write(spi, &command, 1); ++} ++ ++int wcxb_flash_sector_erase(struct wcxb_spi_device *spi, ++ unsigned int address) ++{ ++ int res; ++ u8 command[] = {FLASH_SECTOR_ERASE, (address >> 16)&0xff, 0x00, 0x00}; ++ /* Sector must be on 64KB boundary. */ ++ if (address & 0xffff) ++ return -EINVAL; ++ /* Start the erase. */ ++ res = wcxb_flash_write_enable(spi); ++ if (res) ++ return res; ++ res = wcxb_spi_write(spi, &command, sizeof(command)); ++ if (res) ++ return res; ++ return wcxb_flash_wait_until_not_busy(spi); ++} ++ ++int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address, ++ const void *data, size_t len) ++{ ++ int res; ++ const size_t FLASH_PAGE_SIZE = 256; ++ u8 command[] = { ++ FLASH_PAGE_PROGRAM, ++ (address & 0xff0000) >> 16, ++ (address & 0xff00) >> 8, ++ 0x00, ++ }; ++ struct wcxb_spi_transfer t_cmd = { ++ .tx_buf = command, ++ .len = sizeof(command), ++ }; ++ struct wcxb_spi_transfer t_data = { ++ .tx_buf = data, ++ .len = len, ++ }; ++ struct wcxb_spi_message m; ++ ++ /* We need to write on page size boundaries */ ++ WARN_ON(address & 0xff); ++ ++ wcxb_spi_message_init(&m); ++ wcxb_spi_message_add_tail(&t_cmd, &m); ++ wcxb_spi_message_add_tail(&t_data, &m); ++ ++ while (len) { ++ res = wcxb_flash_write_enable(spi); ++ if (res) ++ return res; ++ command[1] = (address >> 16) & 0xff; ++ command[2] = (address >> 8) & 0xff; ++ t_data.tx_buf = data; ++ t_data.len = min(len, FLASH_PAGE_SIZE); ++ res = wcxb_spi_sync(spi, &m); ++ WARN_ON(res); ++ if (res) ++ return res; ++ res = wcxb_flash_wait_until_not_busy(spi); ++ WARN_ON(res); ++ if (res) ++ return res; ++ len -= t_data.len; ++ address += t_data.len; ++ data += t_data.len; ++ } ++ return 0; ++} +diff -Nru linux-source-4.19/drivers/dahdi/wcxb_flash.h linux-source-4.19-dahdi/drivers/dahdi/wcxb_flash.h +--- linux-source-4.19/drivers/dahdi/wcxb_flash.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcxb_flash.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,34 @@ ++/* ++ * wcxb SPI library ++ * ++ * Copyright (C) 2013 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 __WCXB_FLASH_H__ ++#define __WCXB_FLASH_H__ ++ ++extern int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address, ++ void *data, size_t len); ++ ++extern int wcxb_flash_sector_erase(struct wcxb_spi_device *spi, unsigned int ++ address); ++extern int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address, ++ const void *data, size_t len); ++ ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/wcxb_spi.c linux-source-4.19-dahdi/drivers/dahdi/wcxb_spi.c +--- linux-source-4.19/drivers/dahdi/wcxb_spi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcxb_spi.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,387 @@ ++/* ++ * wcxb SPI library ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include "wcxb_spi.h" ++ ++#define BBIT(n) (1UL << (31UL - (n))) ++ ++#define SPISRR 0x40 ++#define SPISRR_RESET 0x0000000a /* Resets Device */ ++ ++#define SPICR 0x60 ++#define SPICR_LSB_FIRST BBIT(22) /* LSB First. 0=MSB first transfer */ ++#define SPICR_MASTER_INHIBIT BBIT(23) /* Master Transaction Inhibit */ ++#define SPICR_SLAVE_SELECT BBIT(24) /* Manual Slave Select Assert Enable */ ++#define SPICR_RX_FIFO_RESET BBIT(25) /* Receive FIFO Reset */ ++#define SPICR_TX_FIFO_RESET BBIT(26) /* Transmit FIFO Reset */ ++#define SPICR_CPHA BBIT(27) /* Clock Phase */ ++#define SPICR_CPOL BBIT(28) /* Clock Polarity 0=Active High */ ++#define SPICR_MASTER BBIT(29) /* Master Enable */ ++#define SPICR_SPE BBIT(30) /* SPI System Enable */ ++#define SPICR_LOOP BBIT(31) /* Local Loopback Mode */ ++ ++#define SPICR_START_TRANSFER (SPICR_CPHA | SPICR_CPOL | \ ++ SPICR_MASTER | SPICR_SPE) ++#define SPICR_READY_TRANSFER (SPICR_MASTER_INHIBIT | SPICR_START_TRANSFER) ++ ++#define SPISR 0x64 /* SPI Status Register */ ++#define SPISR_SLAVE_MODE_SEL BBIT(26) /* Slave Mode Select Flag */ ++#define SPISR_MODF BBIT(27) /* Mode-Fault Error Flag */ ++#define SPISR_TX_FULL BBIT(28) /* Transmit FIFO Full */ ++#define SPISR_TX_EMPTY BBIT(29) /* Transmit FIFO Empty */ ++#define SPISR_RX_FULL BBIT(30) /* Receive FIFO Full */ ++#define SPISR_RX_EMPTY BBIT(31) /* Receive FIFO Empty */ ++ ++#define SPIDTR 0x68 /* SPI Data Transmit Register */ ++#define SPIDRR 0x6c /* SPI Data Receive Register */ ++ ++#define SPISSR 0x70 /* SPI Slave Select Register */ ++ ++#undef SUCCESS ++#define SUCCESS 0 ++ ++struct wcxb_spi_master { ++ struct device *parent; ++ struct list_head message_queue; ++ spinlock_t lock; ++ void __iomem *base; ++ struct wcxb_spi_message *cur_msg; ++ struct wcxb_spi_transfer *cur_transfer; ++ u16 bytes_left; ++ u16 bytes_in_fifo; ++ const u8 *cur_tx_byte; ++ u8 *cur_rx_byte; ++ u16 auto_cs:1; ++}; ++ ++static inline void _wcxb_assert_chip_select(struct wcxb_spi_master *master, ++ unsigned int cs) ++{ ++ const int cs_mask = ~(1UL << cs); ++ iowrite32be(cs_mask, master->base + SPISSR); ++ ioread32be(master->base + SPISSR); ++} ++ ++static inline void _wcxb_clear_chip_select(struct wcxb_spi_master *master) ++{ ++ iowrite32be(~(0), master->base + SPISSR); ++ ioread32(master->base + SPISSR); ++} ++ ++static inline void wcxb_spi_reset_controller(struct wcxb_spi_master *master) ++{ ++ u32 spicr = SPICR_READY_TRANSFER; ++ spicr |= (master->auto_cs) ? 0 : SPICR_SLAVE_SELECT; ++ iowrite32be(SPISRR_RESET, master->base + SPISRR); ++ iowrite32be(spicr, master->base + SPICR); ++ iowrite32be(0xffffffff, master->base + SPISSR); ++} ++ ++struct wcxb_spi_master *wcxb_spi_master_create(struct device *parent, ++ void __iomem *membase, ++ bool auto_cs) ++{ ++ struct wcxb_spi_master *master = NULL; ++ master = kzalloc(sizeof(struct wcxb_spi_master), GFP_KERNEL); ++ if (!master) ++ goto error_exit; ++ ++ spin_lock_init(&master->lock); ++ INIT_LIST_HEAD(&master->message_queue); ++ master->base = membase; ++ master->parent = parent; ++ ++ master->auto_cs = (auto_cs) ? 1 : 0; ++ wcxb_spi_reset_controller(master); ++ return master; ++ ++error_exit: ++ kfree(master); ++ return NULL; ++} ++ ++void wcxb_spi_master_destroy(struct wcxb_spi_master *master) ++{ ++ struct wcxb_spi_message *m; ++ if (!master) ++ return; ++ while (!list_empty(&master->message_queue)) { ++ m = list_first_entry(&master->message_queue, ++ struct wcxb_spi_message, node); ++ list_del(&m->node); ++ if (m->complete) ++ m->complete(m->arg); ++ } ++ kfree(master); ++ return; ++} ++ ++static inline bool is_txfifo_empty(const struct wcxb_spi_master *master) ++{ ++ return ((ioread32(master->base + SPISR) & ++ cpu_to_be32(SPISR_TX_EMPTY)) > 0); ++} ++ ++static const u8 DUMMY_TX = 0xff; ++static u8 DUMMY_RX; ++ ++static void _wcxb_spi_transfer_to_fifo(struct wcxb_spi_master *master) ++{ ++ const unsigned int FIFO_SIZE = 16; ++ u32 spicr; ++ while (master->bytes_left && master->bytes_in_fifo < FIFO_SIZE) { ++ iowrite32be(*master->cur_tx_byte, master->base + SPIDTR); ++ master->bytes_in_fifo++; ++ master->bytes_left--; ++ if (&DUMMY_TX != master->cur_tx_byte) ++ master->cur_tx_byte++; ++ } ++ ++ spicr = (master->auto_cs) ? SPICR_START_TRANSFER : ++ SPICR_START_TRANSFER | SPICR_SLAVE_SELECT; ++ iowrite32be(spicr, master->base + SPICR); ++} ++ ++static void _wcxb_spi_transfer_from_fifo(struct wcxb_spi_master *master) ++{ ++ u32 spicr; ++ while (master->bytes_in_fifo) { ++ *master->cur_rx_byte = ioread32be(master->base + SPIDRR); ++ if (&DUMMY_RX != master->cur_rx_byte) ++ master->cur_rx_byte++; ++ --master->bytes_in_fifo; ++ } ++ ++ spicr = SPICR_START_TRANSFER; ++ spicr |= (master->auto_cs) ? 0 : SPICR_SLAVE_SELECT; ++ iowrite32be(spicr | SPICR_MASTER_INHIBIT, master->base + SPICR); ++} ++ ++static void _wcxb_spi_start_transfer(struct wcxb_spi_master *master, ++ struct wcxb_spi_transfer *t) ++{ ++#ifdef DEBUG ++ if (!t || !master || (!t->tx_buf && !t->rx_buf) || ++ master->cur_transfer) { ++ WARN_ON(1); ++ return; ++ } ++#endif ++ ++ master->cur_transfer = t; ++ master->bytes_left = t->len; ++ master->cur_tx_byte = (t->tx_buf) ?: &DUMMY_TX; ++ master->cur_rx_byte = (t->rx_buf) ?: &DUMMY_RX; ++ ++ _wcxb_spi_transfer_to_fifo(master); ++} ++ ++/** ++ * _wcxb_spi_start_message - Start a new message transferring. ++ * ++ * Must be called with master->lock held. ++ * ++ */ ++static int _wcxb_spi_start_message(struct wcxb_spi_master *master, ++ struct wcxb_spi_message *message) ++{ ++ struct wcxb_spi_transfer *t; ++ ++ if (master->cur_msg) { ++ /* There is already a message in progress. Queue for later. */ ++ list_add_tail(&message->node, &master->message_queue); ++ return 0; ++ } ++ ++ if (!message->spi) { ++ dev_dbg(master->parent, ++ "Queueing message without SPI device specified?\n"); ++ return -EINVAL; ++ }; ++ ++ master->cur_msg = message; ++ ++ _wcxb_assert_chip_select(master, message->spi->chip_select); ++ t = list_first_entry(&message->transfers, ++ struct wcxb_spi_transfer, node); ++ _wcxb_spi_start_transfer(master, t); ++ ++ return 0; ++} ++ ++/** ++ * wcxb_spi_complete_message - Complete the current message. ++ * ++ * Called after all transfers in current message have been completed. This will ++ * complete the current message and start the next queued message if there are ++ * any. ++ * ++ * Must be called with the master->lock held. ++ * ++ */ ++static void _wcxb_spi_complete_cur_msg(struct wcxb_spi_master *master) ++{ ++ struct wcxb_spi_message *message; ++ if (!master->cur_msg) ++ return; ++ message = master->cur_msg; ++ message->status = SUCCESS; ++ _wcxb_clear_chip_select(master); ++ master->cur_msg = NULL; ++ if (!list_empty(&master->message_queue)) { ++ message = list_first_entry(&master->message_queue, ++ struct wcxb_spi_message, node); ++ list_del(&message->node); ++ _wcxb_spi_start_message(master, message); ++ } ++ return; ++} ++ ++static inline bool ++_wcxb_spi_is_last_transfer(const struct wcxb_spi_transfer *t, ++ const struct wcxb_spi_message *message) ++{ ++ return t->node.next == &message->transfers; ++} ++ ++static inline struct wcxb_spi_transfer * ++_wcxb_spi_next_transfer(struct wcxb_spi_transfer *t) ++{ ++ return list_entry(t->node.next, struct wcxb_spi_transfer, node); ++} ++ ++/** ++ * wcxb_spi_handle_interrupt - Drives the transfers forward. ++ * ++ * Doesn't necessarily need to be called in the context of a real interrupt, but ++ * should be called with interrupts disabled on the local CPU. ++ * ++ */ ++void wcxb_spi_handle_interrupt(struct wcxb_spi_master *master) ++{ ++ struct wcxb_spi_message *msg; ++ struct wcxb_spi_transfer *t; ++ void (*complete)(void *arg) = NULL; ++ unsigned long flags; ++ ++ /* Check if we're not in the middle of a transfer, or not finished with ++ * a part of one. */ ++ spin_lock_irqsave(&master->lock, flags); ++ ++ t = master->cur_transfer; ++ msg = master->cur_msg; ++ ++ if (!msg || !is_txfifo_empty(master)) ++ goto done; ++ ++#ifdef DEBUG ++ if (!t) { ++ dev_dbg(master->parent, ++ "No current transfer in %s\n", __func__); ++ goto done; ++ } ++#endif ++ ++ /* First read any data out of the receive FIFO into the current ++ * transfer. */ ++ _wcxb_spi_transfer_from_fifo(master); ++ if (master->bytes_left) { ++ /* The current transfer isn't finished. */ ++ _wcxb_spi_transfer_to_fifo(master); ++ goto done; ++ } ++ ++ /* The current transfer is finished. Check for another transfer in this ++ * message or complete it and look for another message to start. */ ++ master->cur_transfer = NULL; ++ ++ if (_wcxb_spi_is_last_transfer(t, msg)) { ++ complete = msg->complete; ++ _wcxb_spi_complete_cur_msg(master); ++ } else { ++ t = _wcxb_spi_next_transfer(t); ++ _wcxb_spi_start_transfer(master, t); ++ } ++done: ++ spin_unlock_irqrestore(&master->lock, flags); ++ /* Do not call the complete call back under the bus lock. */ ++ if (complete) ++ complete(msg->arg); ++ return; ++} ++ ++int wcxb_spi_async(struct wcxb_spi_device *spi, ++ struct wcxb_spi_message *message) ++{ ++ int res; ++ unsigned long flags; ++ WARN_ON(!spi || !message || !spi->master); ++ ++ if (list_empty(&message->transfers)) { ++ /* No transfers in this message? */ ++ if (message->complete) ++ message->complete(message->arg); ++ message->status = -EINVAL; ++ return 0; ++ } ++ message->status = -EINPROGRESS; ++ message->spi = spi; ++ spin_lock_irqsave(&spi->master->lock, flags); ++ res = _wcxb_spi_start_message(spi->master, message); ++ spin_unlock_irqrestore(&spi->master->lock, flags); ++ return res; ++} ++ ++static void wcxb_spi_complete_message(void *arg) ++{ ++ complete((struct completion *)arg); ++} ++ ++int wcxb_spi_sync(struct wcxb_spi_device *spi, struct wcxb_spi_message *message) ++{ ++ DECLARE_COMPLETION_ONSTACK(done); ++ WARN_ON(!spi || !spi->master); ++ message->complete = wcxb_spi_complete_message; ++ message->arg = &done; ++ wcxb_spi_async(spi, message); ++ ++ /* TODO: There has got to be a better way to do this. */ ++ while (!try_wait_for_completion(&done)) { ++ wcxb_spi_handle_interrupt(spi->master); ++ cpu_relax(); ++ } ++ return message->status; ++} +diff -Nru linux-source-4.19/drivers/dahdi/wcxb_spi.h linux-source-4.19-dahdi/drivers/dahdi/wcxb_spi.h +--- linux-source-4.19/drivers/dahdi/wcxb_spi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/wcxb_spi.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,116 @@ ++/* ++ * wcxb SPI library ++ * ++ * Copyright (C) 2013 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 __WCXB_SPI_H ++#define __WCXB_SPI_H ++ ++#include ++#include ++ ++struct wcxb_spi_transfer { ++ const void *tx_buf; ++ void *rx_buf; ++ u32 len:16; ++ u16 delay_usecs; ++ struct list_head node; ++}; ++ ++struct wcxb_spi_message { ++ struct list_head transfers; ++ struct list_head node; ++ struct wcxb_spi_device *spi; ++ void (*complete)(void *arg); ++ void *arg; ++ int status; ++}; ++ ++struct wcxb_spi_master; ++ ++struct wcxb_spi_device { ++ struct wcxb_spi_master *master; ++ u16 chip_select; ++}; ++ ++extern struct wcxb_spi_master *wcxb_spi_master_create(struct device *parent, ++ void __iomem *base, bool auto_cs); ++extern void wcxb_spi_master_destroy(struct wcxb_spi_master *master); ++extern int wcxb_spi_sync(struct wcxb_spi_device *spi, ++ struct wcxb_spi_message *message); ++extern int wcxb_spi_async(struct wcxb_spi_device *spi, ++ struct wcxb_spi_message *message); ++extern void wcxb_spi_handle_interrupt(struct wcxb_spi_master *master); ++ ++static inline struct wcxb_spi_device * ++wcxb_spi_device_create(struct wcxb_spi_master *master, u16 chip_select) ++{ ++ struct wcxb_spi_device *spi = kzalloc(sizeof(*spi), GFP_KERNEL); ++ if (!spi) ++ return NULL; ++ spi->master = master; ++ spi->chip_select = chip_select; ++ return spi; ++} ++ ++static inline void wcxb_spi_device_destroy(struct wcxb_spi_device *spi) ++{ ++ kfree(spi); ++} ++ ++static inline void wcxb_spi_message_init(struct wcxb_spi_message *m) ++{ ++ memset(m, 0, sizeof(*m)); ++ INIT_LIST_HEAD(&m->transfers); ++} ++ ++static inline void wcxb_spi_message_add_tail(struct wcxb_spi_transfer *t, ++ struct wcxb_spi_message *m) ++{ ++ list_add_tail(&t->node, &m->transfers); ++} ++ ++static inline int ++wcxb_spi_write(struct wcxb_spi_device *spi, const void *buffer, size_t len) ++{ ++ struct wcxb_spi_transfer t = { ++ .tx_buf = buffer, ++ .len = len, ++ }; ++ struct wcxb_spi_message m; ++ wcxb_spi_message_init(&m); ++ wcxb_spi_message_add_tail(&t, &m); ++ return wcxb_spi_sync(spi, &m); ++} ++ ++static inline int ++wcxb_spi_read(struct wcxb_spi_device *spi, void *buffer, size_t len) ++{ ++ struct wcxb_spi_transfer t = { ++ .rx_buf = buffer, ++ .len = len, ++ }; ++ struct wcxb_spi_message m; ++ wcxb_spi_message_init(&m); ++ wcxb_spi_message_add_tail(&t, &m); ++ return wcxb_spi_sync(spi, &m); ++} ++ ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/xpp/Changelog_xpp linux-source-4.19-dahdi/drivers/dahdi/xpp/Changelog_xpp +--- linux-source-4.19/drivers/dahdi/xpp/Changelog_xpp 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/Changelog_xpp 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,31 @@ ++Sun Mar 1 2009 Oron Peled - xpp.r6795 ++ * Fix cases where the command_queue overflowed during initialization. ++ - Also add a 'command_queue_length' parameter to xpp.ko ++ * More migrations to sysfs: ++ - Add a 'transport' attribute to our astribank devices which ++ points to the usb device we use. E.g: ++ /sys/bus/astribanks/devices/xbus-00/transport is symlinked to ++ ../../../../../../devices/pci0000:00/0000:00:10.4/usb5/5-4 ++ - Move /proc/xpp/XBUS-??/XPD-??/span to ++ /sys/bus/xpds/devices/??:?:?/span ++ - Migrate from /proc/xpp/sync to: ++ /sys/bus/astribanks/drivers/xppdrv/sync ++ - New 'offhook' attribute in: ++ /sys/bus/xpds/devices/??:?:?/offhook ++ * PRI: change the "timing" priority to match the convention used by ++ other PRI cards -- I.e: lower numbers (not 0) have higher ++ priority. ++ * FXO: ++ - Power denial: create two module parameters instead of hard-coded ++ constants (power_denial_safezone, power_denial_minlen). ++ For sites that get non-standard power-denial signals from central ++ office on offhook. ++ - Don't hangup on power-denial, just notify Dahdi and wait for ++ - Fix caller-id detection for the case central office sends it before ++ first ring without any indication before. ++ Asterisk's desicion. ++ * USB_FW.hex: ++ - Fixes cases where firmware loading would fail. ++ ++Thu, Aug 14 2008 Oron Peled - xpp.r6056 ++ * First DAHDI-linux release. +diff -Nru linux-source-4.19/drivers/dahdi/xpp/Kbuild linux-source-4.19-dahdi/drivers/dahdi/xpp/Kbuild +--- linux-source-4.19/drivers/dahdi/xpp/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/Kbuild 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,81 @@ ++EXTRA_CFLAGS = $(XPP_LOCAL_CFLAGS) \ ++ -DDEBUG \ ++ -DPOLL_DIGITAL_INPUTS \ ++ -DDEBUG_PCMTX \ ++ -DPROTOCOL_DEBUG \ ++ -g ++ # ++ ++WITH_BRISTUFF := $(shell grep -c '^[[:space:]]*\#[[:space:]]*define[[:space:]]\+CONFIG_DAHDI_BRI_DCHANS\>' $(src)/../../../include/dahdi/dahdi_config.h) ++ ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_FXS) += xpd_fxs.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_FXO) += xpd_fxo.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_PRI) += xpd_pri.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_BRI) += xpd_bri.o ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_ECHO) += xpd_echo.o ++ ++# Build only supported modules ++ifneq (,$(filter y m,$(CONFIG_USB))) ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_XPP_USB) += xpp_usb.o ++endif ++ifneq (,$(filter y m,$(CONFIG_BF537))) ++obj-$(DAHDI_BUILD_ALL)$(CONFIG_XPP_MMAP) += xpp_mmap.o ++endif ++ ++xpp-objs += xbus-core.o xbus-sysfs.o xbus-pcm.o xframe_queue.o xpp_dahdi.o xproto.o card_global.o dahdi_debug.o ++xpd_fxs-objs += card_fxs.o ++xpd_fxo-objs += card_fxo.o ++xpd_bri-objs += card_bri.o ++xpd_pri-objs += card_pri.o ++xpd_echo-objs += card_echo.o ++xpp_mmap-objs += mmapbus.o mmapdrv.o ++ ++ifeq (y,$(PARPORT_DEBUG)) ++EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT ++obj-m += parport_debug.o ++endif ++ ++# Just in case it was left from an older version: ++clean-files += xpp_version.h ++ ++# Validations: ++# - Syntactic verification of perl scripts ++# - Handle country table validation for init_card_2_* ++ ++XPP_PROTOCOL_VERSION := $(shell grep XPP_PROTOCOL_VERSION $(src)/xproto.h | sed -e 's/^.*XPP_PROTOCOL_VERSION[ \t]*//') ++ ++xpp_verifications = \ ++ init_card_1_$(XPP_PROTOCOL_VERSION) \ ++ init_card_2_$(XPP_PROTOCOL_VERSION) \ ++ init_card_3_$(XPP_PROTOCOL_VERSION) \ ++ init_card_4_$(XPP_PROTOCOL_VERSION) \ ++ init_fxo_modes ++ ++xpp_verified = $(foreach file, $(xpp_verifications), $(file).verified) ++ ++FXO_MODES = $(src)/../fxo_modes.h ++FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes ++ ++hostprogs-y := print_fxo_modes ++always := $(xpp_verified) ++print_fxo_modes-objs := print_fxo_modes.o ++HOSTCFLAGS_print_fxo_modes.o += -include $(FXO_MODES) ++ ++clean-files += print_fxo_modes init_fxo_modes $(xpp_verified) ++ ++$(obj)/init_fxo_modes: $(obj)/print_fxo_modes ++ @echo ' GEN $@' ++ $(Q)$(obj)/print_fxo_modes >$@ || (rm -f $@; exit 1) ++ ++$(obj)/init_fxo_modes.verified: $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) $(obj)/init_fxo_modes ++ @echo ' CHECK $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION)' ++ $(Q)$(FXO_VERIFY) || (rm -f $@; exit 1) ++ $(Q)touch $@ ++ ++$(obj)/init_card_%_$(XPP_PROTOCOL_VERSION).verified: $(src)/init_card_%_$(XPP_PROTOCOL_VERSION) ++ @echo ' VERIFY $<' ++ $(Q)perl -c $< 2> $@ || (cat $@; rm -f $@; exit 1) ++ ++.PHONY: FORCE ++FORCE: +diff -Nru linux-source-4.19/drivers/dahdi/xpp/Kconfig linux-source-4.19-dahdi/drivers/dahdi/xpp/Kconfig +--- linux-source-4.19/drivers/dahdi/xpp/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/Kconfig 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,82 @@ ++# ++# XPP configuration ++# ++ ++menuconfig DAHDI_XPP ++ tristate "Xorcom Astribank Support" ++ depends on DAHDI ++ default DAHDI ++ ---help--- ++ Infrastructure support for Xorcom Astribank products. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called xpp. ++ ++ If unsure, say Y. ++ ++config DAHDI_XPP_USB ++ tristate "Astribank USB transport" ++ depends on DAHDI_XPP && USB ++ default DAHDI_XPP ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called xpp_usb. ++ ++ If unsure, say Y. ++ ++config DAHDI_XPP_MMAP ++ tristate "Astribank Blackfin transport" ++ depends on DAHDI_XPP && BF537 ++ default DAHDI_XPP ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called xpp_mmap. ++ ++ This module can be compiled only on Blackfin architecture ++ (with uClinux). ++ ++ If unsure, say N. ++ ++config DAHDI_XPD_FXS ++ tristate "FXS port Support" ++ depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP) ++ default DAHDI_XPP ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called xpd_fxs. ++ ++ If unsure, say Y. ++ ++config DAHDI_XPD_FXO ++ tristate "FXO port Support" ++ depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP) ++ default DAHDI_XPP ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called xpd_fxo. ++ ++ If unsure, say Y. ++ ++config DAHDI_XPD_BRI ++ tristate "BRI port Support" ++ depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP) ++ default DAHDI_XPP ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called xpd_pri. ++ ++ Note: this driver will be automatically excluded ++ from compilation if dahdi driver does not ++ contain the "bristuff" patch. ++ ++ If unsure, say Y. ++ ++config DAHDI_XPD_PRI ++ tristate "PRI port Support" ++ depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP) ++ default DAHDI_XPP ++ ---help--- ++ To compile this driver as a module, choose M here: the ++ module will be called xpd_pri. ++ ++ If unsure, say Y. +diff -Nru linux-source-4.19/drivers/dahdi/xpp/Makefile linux-source-4.19-dahdi/drivers/dahdi/xpp/Makefile +--- linux-source-4.19/drivers/dahdi/xpp/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/Makefile 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,7 @@ ++# We only get here on kernels 2.6.0-2.6.9 . ++# For newer kernels, Kbuild will be included directly by the kernel ++# build system. ++-include $(src)/Kbuild ++ ++ctags: ++ ctags *.[ch] +diff -Nru linux-source-4.19/drivers/dahdi/xpp/XppConfig.pm linux-source-4.19-dahdi/drivers/dahdi/xpp/XppConfig.pm +--- linux-source-4.19/drivers/dahdi/xpp/XppConfig.pm 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/XppConfig.pm 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,38 @@ ++package XppConfig; ++# ++# Written by Oron Peled ++# Copyright (C) 2008, Xorcom ++# This program is free software; you can redistribute and/or ++# modify it under the same terms as Perl itself. ++# ++# $Id$ ++# ++use strict; ++ ++my $conf_file = "/etc/dahdi/xpp.conf"; ++ ++sub import { ++ my $pack = shift || die "Import without package?"; ++ my $init_dir = shift || die "$pack::import -- missing init_dir parameter"; ++ my $local_conf = "$init_dir/xpp.conf"; ++ $conf_file = $local_conf if -r $local_conf; ++} ++ ++sub read_config($) { ++ my $opts = shift || die; ++ ++ open(F, $conf_file) || return (); ++ while() { ++ chomp; ++ s/#.*//; # strip comments ++ next unless /\S/; ++ s/\s*$//; # Trim trailing whitespace ++ my ($key, $value) = split(/\s+/, $_, 2); ++ $opts->{$key} = $value; ++ } ++ close F; ++ $opts->{'xppconf'} = $conf_file; ++ return %{$opts}; ++} ++ ++1; +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_bri.c linux-source-4.19-dahdi/drivers/dahdi/xpp/card_bri.c +--- linux-source-4.19/drivers/dahdi/xpp/card_bri.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_bri.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,1821 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * Parts derived from Cologne demo driver for the chip. ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++#include "xproto.h" ++#include "xpp_dahdi.h" ++#include "card_bri.h" ++#include "dahdi_debug.h" ++#include "xbus-core.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++#ifndef DAHDI_SIG_HARDHDLC ++#error Cannot build BRI without HARDHDLC supprt ++#endif ++ ++/* must be before dahdi_debug.h */ ++static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++static DEF_PARM(uint, poll_interval, 500, 0644, ++ "Poll channel state interval in milliseconds (0 - disable)"); ++static DEF_PARM_BOOL(nt_keepalive, 1, 0644, ++ "Force BRI_NT to keep trying connection"); ++ ++enum xhfc_states { ++ ST_RESET = 0, /* G/F0 */ ++ /* TE */ ++ ST_TE_SENSING = 2, /* F2 */ ++ ST_TE_DEACTIVATED = 3, /* F3 */ ++ ST_TE_SIGWAIT = 4, /* F4 */ ++ ST_TE_IDENT = 5, /* F5 */ ++ ST_TE_SYNCED = 6, /* F6 */ ++ ST_TE_ACTIVATED = 7, /* F7 */ ++ ST_TE_LOST_FRAMING = 8, /* F8 */ ++ /* NT */ ++ ST_NT_DEACTIVATED = 1, /* G1 */ ++ ST_NT_ACTIVATING = 2, /* G2 */ ++ ST_NT_ACTIVATED = 3, /* G3 */ ++ ST_NT_DEACTIVTING = 4, /* G4 */ ++}; ++ ++#ifdef CONFIG_PROC_FS ++static const char *xhfc_state_name(bool is_nt, enum xhfc_states state) ++{ ++ const char *p; ++ ++#define _E(x) [ST_ ## x] = #x ++ static const char *te_names[] = { ++ _E(RESET), ++ _E(TE_SENSING), ++ _E(TE_DEACTIVATED), ++ _E(TE_SIGWAIT), ++ _E(TE_IDENT), ++ _E(TE_SYNCED), ++ _E(TE_ACTIVATED), ++ _E(TE_LOST_FRAMING), ++ }; ++ static const char *nt_names[] = { ++ _E(RESET), ++ _E(NT_DEACTIVATED), ++ _E(NT_ACTIVATING), ++ _E(NT_ACTIVATED), ++ _E(NT_DEACTIVTING), ++ }; ++#undef _E ++ if (is_nt) { ++ if (state > ST_NT_DEACTIVTING) ++ p = "NT ???"; ++ else ++ p = nt_names[state]; ++ } else { ++ if (state > ST_TE_LOST_FRAMING) ++ p = "TE ???"; ++ else ++ p = te_names[state]; ++ } ++ return p; ++} ++#endif ++ ++/* xhfc Layer1 physical commands */ ++#define HFC_L1_ACTIVATE_TE 0x01 ++#define HFC_L1_FORCE_DEACTIVATE_TE 0x02 ++#define HFC_L1_ACTIVATE_NT 0x03 ++#define HFC_L1_DEACTIVATE_NT 0x04 ++ ++#define HFC_L1_ACTIVATING 1 ++#define HFC_L1_ACTIVATED 2 ++#define HFC_TIMER_T1 2500 ++#define HFC_TIMER_T3 8000 /* 8s activation timer T3 */ ++#define HFC_TIMER_OFF -1 /* timer disabled */ ++ ++#define A_SU_WR_STA 0x30 /* ST/Up state machine register */ ++#define V_SU_LD_STA 0x10 ++#define V_SU_ACT 0x60 /* start activation/deactivation */ ++#define STA_DEACTIVATE 0x40 /* start deactivation in A_SU_WR_STA */ ++#define STA_ACTIVATE 0x60 /* start activation in A_SU_WR_STA */ ++#define V_SU_SET_G2_G3 0x80 ++ ++#define A_SU_RD_STA 0x30 ++typedef union { ++ struct { ++ __u8 v_su_sta:4; ++ __u8 v_su_fr_sync:1; ++ __u8 v_su_t2_exp:1; ++ __u8 v_su_info0:1; ++ __u8 v_g2_g3:1; ++ } bits; ++ __u8 reg; ++} su_rd_sta_t; ++ ++#define REG30_LOST 3 /* in polls */ ++#define DCHAN_LOST 15000 /* in ticks */ ++ ++#define BRI_DCHAN_SIGCAP DAHDI_SIG_HARDHDLC ++#define BRI_BCHAN_SIGCAP (DAHDI_SIG_CLEAR | DAHDI_SIG_DACS) ++ ++#define IS_NT(xpd) (PHONEDEV(xpd).direction == TO_PHONE) ++#define BRI_PORT(xpd) ((xpd)->addr.subunit) ++ ++/* shift in PCM highway */ ++#define SUBUNIT_PCM_SHIFT 4 ++#define PCM_SHIFT(mask, sunit) ((mask) << (SUBUNIT_PCM_SHIFT * (sunit))) ++ ++/*---------------- BRI Protocol Commands ----------------------------------*/ ++ ++static int write_state_register(xpd_t *xpd, __u8 value); ++static bool bri_packet_is_valid(xpacket_t *pack); ++static void bri_packet_dump(const char *msg, xpacket_t *pack); ++#ifdef CONFIG_PROC_FS ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_bri_info_ops; ++#else ++static const struct file_operations proc_bri_info_ops; ++#endif ++#endif ++static int bri_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc); ++static int bri_chanconfig(struct file *file, struct dahdi_chan *chan, ++ int sigtype); ++static int bri_startup(struct file *file, struct dahdi_span *span); ++static int bri_shutdown(struct dahdi_span *span); ++ ++#define PROC_BRI_INFO_FNAME "bri_info" ++ ++enum led_state { ++ BRI_LED_OFF = 0x0, ++ BRI_LED_ON = 0x1, ++ /* ++ * We blink by software from driver, so that ++ * if the driver malfunction that blink would stop. ++ */ ++ // BRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ ++ // BRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ ++}; ++ ++enum bri_led_names { ++ GREEN_LED = 0, ++ RED_LED = 1 ++}; ++ ++#define NUM_LEDS 2 ++#define LED_TICKS 100 ++ ++struct bri_leds { ++ __u8 state:2; ++ __u8 led_sel:1; /* 0 - GREEN, 1 - RED */ ++ __u8 reserved:5; ++}; ++ ++#ifndef MAX_DFRAME_LEN_L1 ++#define MAX_DFRAME_LEN_L1 300 ++#endif ++ ++#define DCHAN_BUFSIZE MAX_DFRAME_LEN_L1 ++ ++struct BRI_priv_data { ++ struct proc_dir_entry *bri_info; ++ su_rd_sta_t state_register; ++ bool initialized; ++ bool dchan_is_open; ++ int t1; /* timer 1 for NT deactivation */ ++ int t3; /* timer 3 for TE activation */ ++ ulong l1_flags; ++ bool reg30_good; ++ uint reg30_ticks; ++ bool layer1_up; ++ ++ /* ++ * D-Chan: buffers + extra state info. ++ */ ++ atomic_t hdlc_pending; ++ bool txframe_begin; ++ ++ uint tick_counter; ++ uint poll_counter; ++ uint dchan_tx_counter; ++ uint dchan_rx_counter; ++ uint dchan_rx_drops; ++ bool dchan_alive; ++ uint dchan_alive_ticks; ++ uint dchan_notx_ticks; ++ uint dchan_norx_ticks; ++ enum led_state ledstate[NUM_LEDS]; ++}; ++ ++static xproto_table_t PROTO_TABLE(BRI); ++ ++DEF_RPACKET_DATA(BRI, SET_LED, /* Set one of the LED's */ ++ struct bri_leds bri_leds;); ++ ++static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, enum bri_led_names which_led, ++ enum led_state to_led_state); ++ ++#define DO_LED(xpd, which, tostate) \ ++ CALL_PROTO(BRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate)) ++ ++#define DEBUG_BUF_SIZE (100) ++static void dump_hex_buf(xpd_t *xpd, char *msg, __u8 *buf, size_t len) ++{ ++ char debug_buf[DEBUG_BUF_SIZE + 1]; ++ int i; ++ int n = 0; ++ ++ debug_buf[0] = '\0'; ++ for (i = 0; i < len && n < DEBUG_BUF_SIZE; i++) ++ n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ", ++ buf[i]); ++ XPD_NOTICE(xpd, "%s[0..%zd]: %s%s\n", msg, len - 1, debug_buf, ++ (n >= DEBUG_BUF_SIZE) ? "..." : ""); ++} ++ ++static void dump_dchan_packet(xpd_t *xpd, bool transmit, __u8 *buf, int len) ++{ ++ struct BRI_priv_data *priv; ++ char msgbuf[MAX_PROC_WRITE]; ++ char ftype = '?'; ++ char *direction; ++ int frame_begin; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (transmit) { ++ direction = "TX"; ++ frame_begin = priv->txframe_begin; ++ } else { ++ direction = "RX"; ++ frame_begin = 1; ++ } ++ if (frame_begin) { /* Packet start */ ++ if (!IS_SET(buf[0], 7)) ++ ftype = 'I'; /* Information */ ++ else if (IS_SET(buf[0], 7) && !IS_SET(buf[0], 6)) ++ ftype = 'S'; /* Supervisory */ ++ else if (IS_SET(buf[0], 7) && IS_SET(buf[0], 6)) ++ ftype = 'U'; /* Unnumbered */ ++ else ++ XPD_NOTICE(xpd, "Unknown frame type 0x%X\n", buf[0]); ++ ++ snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = (%c) ", direction, ++ ftype); ++ } else { ++ snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = ", direction); ++ } ++ dump_hex_buf(xpd, msgbuf, buf, len); ++} ++ ++static void set_bri_timer(xpd_t *xpd, const char *name, int *bri_timer, ++ int value) ++{ ++ if (value == HFC_TIMER_OFF) ++ XPD_DBG(SIGNAL, xpd, "Timer %s DISABLE\n", name); ++ else ++ XPD_DBG(SIGNAL, xpd, "Timer %s: set to %d\n", name, value); ++ *bri_timer = value; ++} ++ ++static void dchan_state(xpd_t *xpd, bool up) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (priv->dchan_alive == up) ++ return; ++ if (up) { ++ XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n"); ++ priv->dchan_alive = 1; ++ } else { ++ XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n"); ++ priv->dchan_rx_counter = priv->dchan_tx_counter = ++ priv->dchan_rx_drops = 0; ++ priv->dchan_alive = 0; ++ priv->dchan_alive_ticks = 0; ++ } ++} ++ ++static void layer1_state(xpd_t *xpd, bool up) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (priv->layer1_up == up) ++ return; ++ priv->layer1_up = up; ++ XPD_DBG(SIGNAL, xpd, "STATE CHANGE: Layer1 %s\n", (up) ? "UP" : "DOWN"); ++ if (!up) ++ dchan_state(xpd, 0); ++} ++ ++static void te_activation(xpd_t *xpd, bool on) ++{ ++ struct BRI_priv_data *priv; ++ __u8 curr_state; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ curr_state = priv->state_register.bits.v_su_sta; ++ XPD_DBG(SIGNAL, xpd, "%s\n", (on) ? "ON" : "OFF"); ++ if (on) { ++ if (curr_state == ST_TE_DEACTIVATED) { ++ XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_TE\n"); ++ set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); ++ write_state_register(xpd, STA_ACTIVATE); ++ set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_T3); ++ } else { ++ XPD_DBG(SIGNAL, xpd, ++ "HFC_L1_ACTIVATE_TE (state %d, ignored)\n", ++ curr_state); ++ } ++ } else { /* happen only because of T3 expiry */ ++ switch (curr_state) { ++ case ST_TE_DEACTIVATED: /* F3 */ ++ case ST_TE_SYNCED: /* F6 */ ++ case ST_TE_ACTIVATED: /* F7 */ ++ XPD_DBG(SIGNAL, xpd, ++ "HFC_L1_FORCE_DEACTIVATE_TE " ++ "(state %d, ignored)\n", ++ curr_state); ++ break; ++ case ST_TE_SIGWAIT: /* F4 */ ++ case ST_TE_IDENT: /* F5 */ ++ case ST_TE_LOST_FRAMING: /* F8 */ ++ XPD_DBG(SIGNAL, xpd, "HFC_L1_FORCE_DEACTIVATE_TE\n"); ++ write_state_register(xpd, STA_DEACTIVATE); ++ break; ++ default: ++ XPD_NOTICE(xpd, "Bad TE state: %d\n", curr_state); ++ break; ++ } ++ } ++} ++ ++static void nt_activation(xpd_t *xpd, bool on) ++{ ++ struct BRI_priv_data *priv; ++ __u8 curr_state; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ curr_state = priv->state_register.bits.v_su_sta; ++ XPD_DBG(SIGNAL, xpd, "%s\n", (on) ? "ON" : "OFF"); ++ if (on) { ++ switch (curr_state) { ++ case ST_RESET: /* F/G 0 */ ++ case ST_NT_DEACTIVATED: /* G1 */ ++ case ST_NT_DEACTIVTING: /* G4 */ ++ XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_NT\n"); ++ set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_T1); ++ set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); ++ write_state_register(xpd, STA_ACTIVATE); ++ break; ++ case ST_NT_ACTIVATING: /* G2 */ ++ case ST_NT_ACTIVATED: /* G3 */ ++ XPD_DBG(SIGNAL, xpd, ++ "HFC_L1_ACTIVATE_NT (in state %d, ignored)\n", ++ curr_state); ++ break; ++ } ++ } else { ++ switch (curr_state) { ++ case ST_RESET: /* F/G 0 */ ++ case ST_NT_DEACTIVATED: /* G1 */ ++ case ST_NT_DEACTIVTING: /* G4 */ ++ XPD_DBG(SIGNAL, xpd, ++ "HFC_L1_DEACTIVATE_NT (in state %d, ignored)\n", ++ curr_state); ++ break; ++ case ST_NT_ACTIVATING: /* G2 */ ++ case ST_NT_ACTIVATED: /* G3 */ ++ XPD_DBG(SIGNAL, xpd, "HFC_L1_DEACTIVATE_NT\n"); ++ write_state_register(xpd, STA_DEACTIVATE); ++ break; ++ default: ++ XPD_NOTICE(xpd, "Bad NT state: %d\n", curr_state); ++ break; ++ } ++ } ++} ++ ++/* ++ * D-Chan receive ++ */ ++static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, __u8 *buf, ++ int len) ++{ ++ struct BRI_priv_data *priv; ++ __u8 status; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (len <= 0) { ++ XPD_NOTICE(xpd, "D-Chan RX DROP: short frame (len=%d)\n", len); ++ dahdi_hdlc_abort(dchan, DAHDI_EVENT_ABORT); ++ return -EPROTO; ++ } ++ status = buf[len - 1]; ++ if (status) { ++ int event = DAHDI_EVENT_ABORT; ++ ++ if (status == 0xFF) { ++ XPD_NOTICE(xpd, "D-Chan RX DROP: ABORT: %d\n", status); ++ } else { ++ XPD_NOTICE(xpd, "D-Chan RX DROP: BADFCS: %d\n", status); ++ event = DAHDI_EVENT_BADFCS; ++ } ++ dump_hex_buf(xpd, "D-Chan RX: current packet", buf, len); ++ dahdi_hdlc_abort(dchan, event); ++ return -EPROTO; ++ } ++ return 0; ++} ++ ++static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd) ++{ ++ struct BRI_priv_data *priv; ++ __u8 *src; ++ struct dahdi_chan *dchan; ++ uint len; ++ bool eoframe; ++ int ret = 0; ++ ++ src = REG_XDATA(regcmd); ++ len = regcmd->h.bytes; ++ eoframe = regcmd->h.eoframe; ++ if (len <= 0) ++ return 0; ++ if (!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */ ++ return 0; ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ dchan = XPD_CHAN(xpd, 2); ++ if (!IS_OFFHOOK(xpd, 2)) { /* D-chan is used? */ ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1000) == 0) ++ XPD_DBG(SIGNAL, xpd, "D-Chan unused\n"); ++ goto out; ++ } ++ XPD_DBG(GENERAL, xpd, "D-Chan RX: eoframe=%d len=%d\n", eoframe, len); ++ dahdi_hdlc_putbuf(dchan, src, (eoframe) ? len - 1 : len); ++ if (!eoframe) ++ goto out; ++ if ((ret = bri_check_stat(xpd, dchan, src, len)) < 0) ++ goto out; ++ /* ++ * Tell Dahdi that we received len-1 bytes. ++ * They include the data and a 2-byte checksum. ++ * The last byte (that we don't pass on) is 0 if the ++ * checksum is correct. If it were wrong, we would drop the ++ * packet in the "if (src[len-1])" above. ++ */ ++ dahdi_hdlc_finish(dchan); ++ priv->dchan_rx_counter++; ++ priv->dchan_norx_ticks = 0; ++out: ++ return ret; ++} ++ ++/* ++ * D-Chan transmit ++ */ ++/* ++ * DAHDI calls this when it has data it wants to send to ++ * the HDLC controller ++ */ ++static void bri_hdlc_hard_xmit(struct dahdi_chan *chan) ++{ ++ xpd_t *xpd = chan->pvt; ++ struct dahdi_chan *dchan; ++ struct BRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ dchan = XPD_CHAN(xpd, 2); ++ if (dchan == chan) ++ atomic_inc(&priv->hdlc_pending); ++} ++ ++static int send_dchan_frame(xpd_t *xpd, xframe_t *xframe, bool is_eof) ++{ ++ struct BRI_priv_data *priv; ++ int ret; ++ ++ XPD_DBG(COMMANDS, xpd, "eoframe=%d\n", is_eof); ++ priv = xpd->priv; ++ if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) ++ && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { ++ XPD_DBG(SIGNAL, xpd, ++ "Want to transmit: Kick D-Channel transmiter\n"); ++ if (!IS_NT(xpd)) ++ te_activation(xpd, 1); ++ else ++ nt_activation(xpd, 1); ++ } ++ dump_xframe("send_dchan_frame", xpd->xbus, xframe, debug); ++ ret = send_cmd_frame(xpd->xbus, xframe); ++ if (ret < 0) ++ XPD_ERR(xpd, "%s: failed sending xframe\n", __func__); ++ if (is_eof) { ++ atomic_dec(&priv->hdlc_pending); ++ priv->dchan_tx_counter++; ++ priv->txframe_begin = 1; ++ } else ++ priv->txframe_begin = 0; ++ priv->dchan_notx_ticks = 0; ++ return ret; ++} ++ ++/* ++ * Fill a single multibyte REGISTER_REQUEST ++ */ ++static void fill_multibyte(xpd_t *xpd, xpacket_t *pack, ++ bool eoframe, char *buf, int len) ++{ ++ reg_cmd_t *reg_cmd; ++ char *p; ++ ++ XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0); ++ XPACKET_LEN(pack) = XFRAME_CMD_LEN(REG); ++ reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); ++ reg_cmd->h.bytes = len; ++ reg_cmd->h.is_multibyte = 1; ++ reg_cmd->h.portnum = xpd->addr.subunit; ++ reg_cmd->h.eoframe = eoframe; ++ p = REG_XDATA(reg_cmd); ++ memcpy(p, buf, len); ++ if (debug) ++ dump_dchan_packet(xpd, 1, p, len); ++} ++ ++/* ++ * Transmit available D-Channel frames ++ * ++ * - FPGA firmware expect to get this as a sequence of REGISTER_REQUEST ++ * multibyte commands. ++ * - The payload of each command is limited to MULTIBYTE_MAX_LEN bytes. ++ * - We batch several REGISTER_REQUEST packets into a single xframe. ++ * - The xframe is terminated when we get a bri "end of frame" ++ * or when the xframe is full (should not happen). ++ */ ++static int tx_dchan(xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ xframe_t *xframe; ++ xpacket_t *pack; ++ int packet_count; ++ int eoframe; ++ int ret; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (atomic_read(&priv->hdlc_pending) == 0) ++ return 0; ++ if (!SPAN_REGISTERED(xpd) ++ || !(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING)) ++ return 0; ++ /* Allocate frame */ ++ xframe = ALLOC_SEND_XFRAME(xpd->xbus); ++ if (!xframe) { ++ XPD_NOTICE(xpd, "%s: failed to allocate new xframe\n", ++ __func__); ++ return -ENOMEM; ++ } ++ for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) { ++ int packet_len = XFRAME_CMD_LEN(REG); ++ char buf[MULTIBYTE_MAX_LEN]; ++ int len = MULTIBYTE_MAX_LEN; ++ ++ /* Reserve packet */ ++ pack = xframe_next_packet(xframe, packet_len); ++ if (!pack) { ++ BUG_ON(!packet_count); ++ /* ++ * A split. Send what we currently have. ++ */ ++ XPD_NOTICE(xpd, "%s: xframe is full (%d packets)\n", ++ __func__, packet_count); ++ break; ++ } ++ /* Get data from DAHDI */ ++ eoframe = dahdi_hdlc_getbuf(XPD_CHAN(xpd, 2), buf, &len); ++ if (len <= 0) { ++ /* ++ * Already checked priv->hdlc_pending, ++ * should never get here. ++ */ ++ if (printk_ratelimit()) ++ XPD_ERR(xpd, ++ "%s: hdlc_pending, but nothing " ++ "to transmit?\n", __func__); ++ FREE_SEND_XFRAME(xpd->xbus, xframe); ++ return -EINVAL; ++ } ++ BUG_ON(len > MULTIBYTE_MAX_LEN); ++ fill_multibyte(xpd, pack, eoframe != 0, buf, len); ++ } ++ return send_dchan_frame(xpd, xframe, eoframe != 0); ++ return ret; ++} ++ ++/*---------------- BRI: Methods -------------------------------------------*/ ++ ++static void bri_proc_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ XPD_DBG(PROC, xpd, "\n"); ++#ifdef CONFIG_PROC_FS ++ if (priv->bri_info) { ++ XPD_DBG(PROC, xpd, "Removing '%s'\n", PROC_BRI_INFO_FNAME); ++ remove_proc_entry(PROC_BRI_INFO_FNAME, xpd->proc_xpd_dir); ++ } ++#endif ++} ++ ++static int bri_proc_create(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ XPD_DBG(PROC, xpd, "\n"); ++#ifdef CONFIG_PROC_FS ++ XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME); ++ priv->bri_info = proc_create_data(PROC_BRI_INFO_FNAME, 0444, ++ xpd->proc_xpd_dir, &proc_bri_info_ops, xpd); ++ if (!priv->bri_info) { ++ XPD_ERR(xpd, "Failed to create proc file '%s'\n", ++ PROC_BRI_INFO_FNAME); ++ bri_proc_remove(xbus, xpd); ++ return -EINVAL; ++ } ++ SET_PROC_DIRENTRY_OWNER(priv->bri_info); ++#endif ++ return 0; ++} ++ ++static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, ++ const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ bool to_phone) ++{ ++ xpd_t *xpd = NULL; ++ int channels = min(3, CHANNELS_PERXPD); ++ ++ if ((unit_descriptor->ports_per_chip < 1) || ++ (unit_descriptor->ports_per_chip > 4)) { ++ XBUS_ERR(xbus, "Bad ports_per_chip=%d\n", ++ unit_descriptor->ports_per_chip); ++ return NULL; ++ } ++ if ((unit_descriptor->numchips) < 1 || ++ (unit_descriptor->numchips > 2)) { ++ XBUS_ERR(xbus, "Bad numchips=%d\n", ++ unit_descriptor->numchips); ++ return NULL; ++ } ++ XBUS_DBG(GENERAL, xbus, "\n"); ++ xpd = ++ xpd_alloc(xbus, unit, subunit, ++ sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels); ++ if (!xpd) ++ return NULL; ++ PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN; ++ xpd->type_name = (to_phone) ? "BRI_NT" : "BRI_TE"; ++ xbus->sync_mode_default = SYNC_MODE_AB; ++ if (bri_proc_create(xbus, xpd) < 0) ++ goto err; ++ return xpd; ++err: ++ xpd_free(xpd); ++ return NULL; ++} ++ ++static int BRI_card_init(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ priv = xpd->priv; ++ DO_LED(xpd, GREEN_LED, BRI_LED_OFF); ++ DO_LED(xpd, RED_LED, BRI_LED_OFF); ++ set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); ++ write_state_register(xpd, 0); /* Enable L1 state machine */ ++ priv->initialized = 1; ++ return 0; ++} ++ ++static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ bri_proc_remove(xbus, xpd); ++ return 0; ++} ++ ++#ifdef DAHDI_AUDIO_NOTIFY ++static int bri_audio_notify(struct dahdi_chan *chan, int on) ++{ ++ xpd_t *xpd = chan->pvt; ++ int pos = chan->chanpos - 1; ++ ++ BUG_ON(!xpd); ++ LINE_DBG(SIGNAL, xpd, pos, "BRI-AUDIO: %s\n", (on) ? "on" : "off"); ++ mark_offhook(xpd, pos, on); ++ return 0; ++} ++#endif ++ ++static const struct dahdi_span_ops BRI_span_ops = { ++ .owner = THIS_MODULE, ++ .spanconfig = bri_spanconfig, ++ .chanconfig = bri_chanconfig, ++ .startup = bri_startup, ++ .shutdown = bri_shutdown, ++ .hdlc_hard_xmit = bri_hdlc_hard_xmit, ++ .open = xpp_open, ++ .close = xpp_close, ++ .hooksig = xpp_hooksig, /* Only with RBS bits */ ++ .ioctl = xpp_ioctl, ++ .maint = xpp_maint, ++ .echocan_create = xpp_echocan_create, ++ .echocan_name = xpp_echocan_name, ++ .assigned = xpp_span_assigned, ++#ifdef DAHDI_SYNC_TICK ++ .sync_tick = dahdi_sync_tick, ++#endif ++#ifdef CONFIG_DAHDI_WATCHDOG ++ .watchdog = xpp_watchdog, ++#endif ++ ++#ifdef DAHDI_AUDIO_NOTIFY ++ .audio_notify = bri_audio_notify, ++#endif ++}; ++ ++static int BRI_card_dahdi_preregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ struct BRI_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ BUG_ON(!xbus); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ if (!on) { ++ /* Nothing to do yet */ ++ return 0; ++ } ++ PHONEDEV(xpd).span.spantype = ++ (PHONEDEV(xpd).direction == TO_PHONE) ++ ? SPANTYPE_DIGITAL_BRI_NT ++ : SPANTYPE_DIGITAL_BRI_TE; ++ PHONEDEV(xpd).span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; ++ PHONEDEV(xpd).span.deflaw = DAHDI_LAW_ALAW; ++ BIT_SET(PHONEDEV(xpd).digital_signalling, 2); /* D-Channel */ ++ for_each_line(xpd, i) { ++ struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i); ++ ++ XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i); ++ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d", ++ xpd->type_name, xbus->num, xpd->addr.unit, ++ xpd->addr.subunit, i); ++ cur_chan->chanpos = i + 1; ++ cur_chan->pvt = xpd; ++ if (i == 2) { /* D-CHAN */ ++ cur_chan->sigcap = BRI_DCHAN_SIGCAP; ++ clear_bit(DAHDI_FLAGBIT_HDLC, &cur_chan->flags); ++ priv->txframe_begin = 1; ++ atomic_set(&priv->hdlc_pending, 0); ++ } else { ++ cur_chan->sigcap = BRI_BCHAN_SIGCAP; ++ } ++ } ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ PHONEDEV(xpd).span.ops = &BRI_span_ops; ++ return 0; ++} ++ ++static int BRI_card_dahdi_postregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ return (0); ++} ++ ++static int BRI_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig) ++{ ++ LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); ++ return 0; ++} ++ ++/* ++ * LED managment is done by the driver now: ++ * - Turn constant ON RED/GREEN led to indicate NT/TE port ++ * - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel) ++ * - Constant blink (1/2 sec cycle) to indicate D-Channel alive. ++ */ ++static void handle_leds(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ unsigned int timer_count; ++ int which_led; ++ int other_led; ++ int mod; ++ ++ BUG_ON(!xpd); ++ if (IS_NT(xpd)) { ++ which_led = RED_LED; ++ other_led = GREEN_LED; ++ } else { ++ which_led = GREEN_LED; ++ other_led = RED_LED; ++ } ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ timer_count = xpd->timer_count; ++ if (xpd->blink_mode) { ++ if ((timer_count % DEFAULT_LED_PERIOD) == 0) { ++ // led state is toggled ++ if (priv->ledstate[which_led] == BRI_LED_OFF) { ++ DO_LED(xpd, which_led, BRI_LED_ON); ++ DO_LED(xpd, other_led, BRI_LED_ON); ++ } else { ++ DO_LED(xpd, which_led, BRI_LED_OFF); ++ DO_LED(xpd, other_led, BRI_LED_OFF); ++ } ++ } ++ return; ++ } ++ if (priv->ledstate[other_led] != BRI_LED_OFF) ++ DO_LED(xpd, other_led, BRI_LED_OFF); ++ if (priv->dchan_alive) { ++ mod = timer_count % 1000; ++ switch (mod) { ++ case 0: ++ DO_LED(xpd, which_led, BRI_LED_ON); ++ break; ++ case 500: ++ DO_LED(xpd, which_led, BRI_LED_OFF); ++ break; ++ } ++ } else if (priv->layer1_up) { ++ mod = timer_count % 1000; ++ switch (mod) { ++ case 0: ++ case 100: ++ DO_LED(xpd, which_led, BRI_LED_ON); ++ break; ++ case 50: ++ case 150: ++ DO_LED(xpd, which_led, BRI_LED_OFF); ++ break; ++ } ++ } else { ++ if (priv->ledstate[which_led] != BRI_LED_ON) ++ DO_LED(xpd, which_led, BRI_LED_ON); ++ } ++} ++ ++static void handle_bri_timers(xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (IS_NT(xpd)) { ++ if (priv->t1 > HFC_TIMER_OFF) { ++ if (--priv->t1 == 0) { ++ set_bri_timer(xpd, "T1", &priv->t1, ++ HFC_TIMER_OFF); ++ if (!nt_keepalive) { ++ /* G2 */ ++ if (priv->state_register.bits.v_su_sta == ST_NT_ACTIVATING) { ++ XPD_DBG(SIGNAL, xpd, ++ "T1 Expired. " ++ "Deactivate NT\n"); ++ clear_bit(HFC_L1_ACTIVATING, ++ &priv->l1_flags); ++ /* Deactivate NT */ ++ nt_activation(xpd, 0); ++ } else ++ XPD_DBG(SIGNAL, xpd, ++ "T1 Expired. " ++ "(state %d, ignored)\n", ++ priv->state_register. ++ bits.v_su_sta); ++ } ++ } ++ } ++ } else { ++ if (priv->t3 > HFC_TIMER_OFF) { ++ /* timer expired ? */ ++ if (--priv->t3 == 0) { ++ XPD_DBG(SIGNAL, xpd, ++ "T3 expired. Deactivate TE\n"); ++ set_bri_timer(xpd, "T3", &priv->t3, ++ HFC_TIMER_OFF); ++ clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); ++ te_activation(xpd, 0); /* Deactivate TE */ ++ } ++ } ++ } ++} ++ ++/* Poll the register ST/Up-State-machine Register, to see if the cable ++ * if a cable is connected to the port. ++ */ ++static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!priv->initialized || !xbus->self_ticking) ++ return 0; ++ if (poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) { ++ // XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter); ++ priv->poll_counter++; ++ xpp_register_request(xbus, xpd, ++ BRI_PORT(xpd), /* portno */ ++ 0, /* writing */ ++ A_SU_RD_STA, /* regnum */ ++ 0, /* do_subreg */ ++ 0, /* subreg */ ++ 0, /* data_low */ ++ 0, /* do_datah */ ++ 0, /* data_high */ ++ 0, /* should_reply */ ++ 0 /* do_expander */ ++ ); ++ ++ if (IS_NT(xpd) && nt_keepalive ++ && !test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) ++ && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { ++ XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n"); ++ nt_activation(xpd, 1); ++ } ++ } ++ /* Detect D-Channel disconnect heuristic */ ++ priv->dchan_notx_ticks++; ++ priv->dchan_norx_ticks++; ++ priv->dchan_alive_ticks++; ++ if (priv->dchan_alive ++ && (priv->dchan_notx_ticks > DCHAN_LOST ++ || priv->dchan_norx_ticks > DCHAN_LOST)) { ++ /* ++ * No tx_dchan() or rx_dchan() for many ticks ++ * This D-Channel is probabelly dead. ++ */ ++ dchan_state(xpd, 0); ++ } else if (priv->dchan_rx_counter > 1 && priv->dchan_tx_counter > 1) { ++ if (!priv->dchan_alive) ++ dchan_state(xpd, 1); ++ } ++ /* Detect Layer1 disconnect */ ++ if (priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) { ++ /* No reply for 1/2 a second */ ++ XPD_ERR(xpd, "Lost state tracking for %d ticks\n", ++ priv->reg30_ticks); ++ priv->reg30_good = 0; ++ layer1_state(xpd, 0); ++ } ++ handle_leds(xbus, xpd); ++ handle_bri_timers(xpd); ++ tx_dchan(xpd); ++ priv->tick_counter++; ++ priv->reg30_ticks++; ++ return 0; ++} ++ ++static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, ++ unsigned long arg) ++{ ++ BUG_ON(!xpd); ++ if (!XBUS_IS(xpd->xbus, READY)) ++ return -ENODEV; ++ switch (cmd) { ++ case DAHDI_TONEDETECT: ++ /* ++ * Asterisk call all span types with this (FXS specific) ++ * call. Silently ignore it. ++ */ ++ LINE_DBG(SIGNAL, xpd, pos, "BRI: Starting a call\n"); ++ return -ENOTTY; ++ default: ++ report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static int BRI_card_open(xpd_t *xpd, lineno_t pos) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ if (pos == 2) { ++ priv->dchan_is_open = 1; ++ LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK the whole span\n"); ++ BIT_SET(PHONEDEV(xpd).offhook_state, 0); ++ BIT_SET(PHONEDEV(xpd).offhook_state, 1); ++ BIT_SET(PHONEDEV(xpd).offhook_state, 2); ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ } ++ return 0; ++} ++ ++static int BRI_card_close(xpd_t *xpd, lineno_t pos) ++{ ++ struct BRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ /* Clear D-Channel pending data */ ++ if (pos == 2) { ++ LINE_DBG(SIGNAL, xpd, pos, "ONHOOK the whole span\n"); ++ BIT_CLR(PHONEDEV(xpd).offhook_state, 0); ++ BIT_CLR(PHONEDEV(xpd).offhook_state, 1); ++ BIT_CLR(PHONEDEV(xpd).offhook_state, 2); ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ priv->dchan_is_open = 0; ++ } else if (!priv->dchan_is_open) ++ mark_offhook(xpd, pos, 0); /* e.g: patgen/pattest */ ++ return 0; ++} ++ ++/* ++ * Called only for 'span' keyword in /etc/dahdi/system.conf ++ */ ++static int bri_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ const char *framingstr = ""; ++ const char *codingstr = ""; ++ const char *crcstr = ""; ++ ++ /* framing first */ ++ if (lc->lineconfig & DAHDI_CONFIG_B8ZS) ++ framingstr = "B8ZS"; ++ else if (lc->lineconfig & DAHDI_CONFIG_AMI) ++ framingstr = "AMI"; ++ else if (lc->lineconfig & DAHDI_CONFIG_HDB3) ++ framingstr = "HDB3"; ++ /* then coding */ ++ if (lc->lineconfig & DAHDI_CONFIG_ESF) ++ codingstr = "ESF"; ++ else if (lc->lineconfig & DAHDI_CONFIG_D4) ++ codingstr = "D4"; ++ else if (lc->lineconfig & DAHDI_CONFIG_CCS) ++ codingstr = "CCS"; ++ /* E1's can enable CRC checking */ ++ if (lc->lineconfig & DAHDI_CONFIG_CRC4) ++ crcstr = "CRC4"; ++ XPD_DBG(GENERAL, xpd, ++ "[%s]: span=%d (%s) lbo=%d lineconfig=%s/%s/%s (0x%X) sync=%d\n", ++ IS_NT(xpd) ? "NT" : "TE", lc->span, lc->name, lc->lbo, ++ framingstr, codingstr, crcstr, lc->lineconfig, lc->sync); ++ PHONEDEV(xpd).timing_priority = lc->sync; ++ elect_syncer("BRI-spanconfig"); ++ /* ++ * FIXME: validate ++ */ ++ span->lineconfig = lc->lineconfig; ++ return 0; ++} ++ ++/* ++ * Set signalling type (if appropriate) ++ * Called from dahdi with spinlock held on chan. Must not call back ++ * dahdi functions. ++ */ ++static int bri_chanconfig(struct file *file, struct dahdi_chan *chan, ++ int sigtype) ++{ ++ DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, ++ sig2str(sigtype)); ++ // FIXME: sanity checks: ++ // - should be supported (within the sigcap) ++ // - should not replace fxs <->fxo ??? (covered by previous?) ++ return 0; ++} ++ ++/* ++ * Called only for 'span' keyword in /etc/dahdi/system.conf ++ */ ++static int bri_startup(struct file *file, struct dahdi_span *span) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ struct BRI_priv_data *priv; ++ struct dahdi_chan *dchan; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!XBUS_IS(xpd->xbus, READY)) { ++ XPD_DBG(GENERAL, xpd, ++ "Startup called by dahdi. No Hardware. Ignored\n"); ++ return -ENODEV; ++ } ++ XPD_DBG(GENERAL, xpd, "STARTUP\n"); ++ // Turn on all channels ++ CALL_PHONE_METHOD(card_state, xpd, 1); ++ if (SPAN_REGISTERED(xpd)) { ++ dchan = XPD_CHAN(xpd, 2); ++ span->flags |= DAHDI_FLAG_RUNNING; ++ /* ++ * Dahdi (wrongly) assume that D-Channel need HDLC decoding ++ * and during dahdi registration override our flags. ++ * ++ * Don't Get Mad, Get Even: Now we override dahdi :-) ++ */ ++ clear_bit(DAHDI_FLAGBIT_HDLC, &dchan->flags); ++ } ++ return 0; ++} ++ ++/* ++ * Called only for 'span' keyword in /etc/dahdi/system.conf ++ */ ++static int bri_shutdown(struct dahdi_span *span) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!XBUS_IS(xpd->xbus, READY)) { ++ XPD_DBG(GENERAL, xpd, ++ "Shutdown called by dahdi. No Hardware. Ignored\n"); ++ return -ENODEV; ++ } ++ XPD_DBG(GENERAL, xpd, "SHUTDOWN\n"); ++ // Turn off all channels ++ CALL_PHONE_METHOD(card_state, xpd, 0); ++ return 0; ++} ++ ++static void BRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t dont_care) ++{ ++ int i; ++ int line_count; ++ xpp_line_t pcm_mask; ++ uint pcm_len; ++ xpd_t *main_xpd; ++ unsigned long flags; ++ ++ BUG_ON(!xpd); ++ main_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, 0); ++ if (!main_xpd) { ++ XPD_DBG(DEVICES, xpd, ++ "Unit 0 is already gone. Ignore request\n"); ++ return; ++ } ++ /* ++ * We calculate all subunits, so use the main lock ++ * as a mutex for the whole operation. ++ */ ++ spin_lock_irqsave(&PHONEDEV(main_xpd).lock_recompute_pcm, flags); ++ line_count = 0; ++ pcm_mask = 0; ++ for (i = 0; i < MAX_SUBUNIT; i++) { ++ xpd_t *sub_xpd = xpd_byaddr(xpd->xbus, main_xpd->addr.unit, i); ++ ++ if (sub_xpd) { ++ xpp_line_t lines = ++ PHONEDEV(sub_xpd). ++ offhook_state & ~(PHONEDEV(sub_xpd). ++ digital_signalling); ++ ++ if (lines) { ++ pcm_mask |= PCM_SHIFT(lines, i); ++ line_count += 2; ++ } ++ /* subunits have fake pcm_len and wanted_pcm_mask */ ++ if (i > 0) ++ update_wanted_pcm_mask(sub_xpd, lines, 0); ++ } ++ } ++ /* ++ * FIXME: Workaround a bug in sync code of the Astribank. ++ * Send dummy PCM for sync. ++ */ ++ if (main_xpd->addr.unit == 0 && line_count == 0) { ++ pcm_mask = BIT(0); ++ line_count = 1; ++ } ++ /* ++ * The main unit account for all subunits (pcm_len and wanted_pcm_mask). ++ */ ++ pcm_len = (line_count) ++ ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + ++ line_count * DAHDI_CHUNKSIZE : 0L; ++ update_wanted_pcm_mask(main_xpd, pcm_mask, pcm_len); ++ spin_unlock_irqrestore(&PHONEDEV(main_xpd).lock_recompute_pcm, flags); ++} ++ ++static void BRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack) ++{ ++ __u8 *pcm; ++ unsigned long flags; ++ int i; ++ int subunit; ++ xpp_line_t pcm_mask = 0; ++ xpp_line_t wanted_lines; ++ ++ BUG_ON(!xpd); ++ BUG_ON(!pack); ++ pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); ++ for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) { ++ xpd_t *tmp_xpd; ++ ++ tmp_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, subunit); ++ if (!tmp_xpd || !tmp_xpd->card_present) ++ continue; ++ spin_lock_irqsave(&tmp_xpd->lock, flags); ++ wanted_lines = PHONEDEV(tmp_xpd).wanted_pcm_mask; ++ for_each_line(tmp_xpd, i) { ++ struct dahdi_chan *chan = XPD_CHAN(tmp_xpd, i); ++ ++ if (IS_SET(wanted_lines, i)) { ++ if (SPAN_REGISTERED(tmp_xpd)) { ++#ifdef DEBUG_PCMTX ++ int channo = chan->channo; ++ ++ if (pcmtx >= 0 && pcmtx_chan == channo) ++ memset((u_char *)pcm, pcmtx, ++ DAHDI_CHUNKSIZE); ++ else ++#endif ++ memcpy((u_char *)pcm, ++ chan->writechunk, ++ DAHDI_CHUNKSIZE); ++ } else ++ memset((u_char *)pcm, 0x7F, ++ DAHDI_CHUNKSIZE); ++ pcm += DAHDI_CHUNKSIZE; ++ } ++ } ++ pcm_mask |= PCM_SHIFT(wanted_lines, subunit); ++ XPD_COUNTER(tmp_xpd, PCM_WRITE)++; ++ spin_unlock_irqrestore(&tmp_xpd->lock, flags); ++ } ++ RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = pcm_mask; ++} ++ ++static void BRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack) ++{ ++ __u8 *pcm; ++ xpp_line_t pcm_mask; ++ unsigned long flags; ++ int subunit; ++ int i; ++ ++ /* ++ * Subunit 0 handle all other subunits ++ */ ++ if (xpd->addr.subunit != 0) ++ return; ++ if (!SPAN_REGISTERED(xpd)) ++ return; ++ pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); ++ pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines); ++ for (subunit = 0; subunit < MAX_SUBUNIT; ++ subunit++, pcm_mask >>= SUBUNIT_PCM_SHIFT) { ++ xpd_t *tmp_xpd; ++ ++ if (!pcm_mask) ++ break; /* optimize */ ++ tmp_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, subunit); ++ if (!tmp_xpd || !tmp_xpd->card_present ++ || !SPAN_REGISTERED(tmp_xpd)) ++ continue; ++ spin_lock_irqsave(&tmp_xpd->lock, flags); ++ for (i = 0; i < 2; i++) { ++ xpp_line_t tmp_mask = pcm_mask & (BIT(0) | BIT(1)); ++ volatile u_char *r; ++ ++ if (IS_SET(tmp_mask, i)) { ++ r = XPD_CHAN(tmp_xpd, i)->readchunk; ++#if 0 ++ /* DEBUG */ ++ memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); ++#endif ++ memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE); ++ pcm += DAHDI_CHUNKSIZE; ++ } ++ } ++ XPD_COUNTER(tmp_xpd, PCM_READ)++; ++ spin_unlock_irqrestore(&tmp_xpd->lock, flags); ++ } ++} ++ ++static int BRI_timing_priority(xpd_t *xpd) ++{ ++ struct BRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (priv->layer1_up) ++ return PHONEDEV(xpd).timing_priority; ++ XPD_DBG(SYNC, xpd, "No timing priority (no layer1)\n"); ++ return -ENOENT; ++} ++ ++static int BRI_echocancel_timeslot(xpd_t *xpd, int pos) ++{ ++ return xpd->addr.subunit * 4 + pos; ++} ++ ++static int BRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask) ++{ ++ struct BRI_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask); ++ if (!ECHOOPS(xpd->xbus)) { ++ XPD_DBG(GENERAL, xpd, ++ "No echo canceller in XBUS: Doing nothing.\n"); ++ return -EINVAL; ++ } ++ for (i = 0; i < PHONEDEV(xpd).channels - 1; i++) { ++ int on = BIT(i) & ec_mask; ++ ++ CALL_EC_METHOD(ec_set, xpd->xbus, xpd, i, on); ++ } ++ CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus); ++ return 0; ++} ++ ++/*---------------- BRI: HOST COMMANDS -------------------------------------*/ ++ ++static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led, ++ enum led_state to_led_state) ++{ ++ int ret = 0; ++ xframe_t *xframe; ++ xpacket_t *pack; ++ struct bri_leds *bri_leds; ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xbus); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(LEDS, xpd, "%s -> %d\n", (which_led) ? "RED" : "GREEN", ++ to_led_state); ++ XFRAME_NEW_CMD(xframe, pack, xbus, BRI, SET_LED, xpd->xbus_idx); ++ bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds); ++ bri_leds->state = to_led_state; ++ bri_leds->led_sel = which_led; ++ XPACKET_LEN(pack) = RPACKET_SIZE(BRI, SET_LED); ++ ret = send_cmd_frame(xbus, xframe); ++ priv->ledstate[which_led] = to_led_state; ++ return ret; ++} ++ ++static int write_state_register(xpd_t *xpd, __u8 value) ++{ ++ int ret; ++ ++ XPD_DBG(REGS, xpd, "value = 0x%02X\n", value); ++ ret = xpp_register_request(xpd->xbus, xpd, ++ BRI_PORT(xpd), /* portno */ ++ 1, /* writing */ ++ A_SU_WR_STA, /* regnum */ ++ 0, /* do_subreg */ ++ 0, /* subreg */ ++ value, /* data_low */ ++ 0, /* do_datah */ ++ 0, /* data_high */ ++ 0, /* should_reply */ ++ 0 /* do_expander */ ++ ); ++ return ret; ++} ++ ++/*---------------- BRI: Astribank Reply Handlers --------------------------*/ ++static void su_new_state(xpd_t *xpd, __u8 reg_x30) ++{ ++ struct BRI_priv_data *priv; ++ su_rd_sta_t new_state; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!priv->initialized) { ++ XPD_ERR(xpd, "%s called on uninitialized AB\n", __func__); ++ return; ++ } ++ new_state.reg = reg_x30; ++ if (new_state.bits.v_su_t2_exp) ++ XPD_NOTICE(xpd, "T2 Expired\n"); ++ priv->reg30_ticks = 0; ++ priv->reg30_good = 1; ++ if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta) ++ return; /* same same */ ++ XPD_DBG(SIGNAL, xpd, "%02X ---> %02X (info0=%d) (%s%i)\n", ++ priv->state_register.reg, reg_x30, new_state.bits.v_su_info0, ++ IS_NT(xpd) ? "G" : "F", new_state.bits.v_su_sta); ++ if (!IS_NT(xpd)) { ++ switch (new_state.bits.v_su_sta) { ++ case ST_TE_DEACTIVATED: /* F3 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_TE_DEACTIVATED (F3)\n"); ++ clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags); ++ layer1_state(xpd, 0); ++ break; ++ case ST_TE_SIGWAIT: /* F4 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_TE_SIGWAIT (F4)\n"); ++ layer1_state(xpd, 0); ++ break; ++ case ST_TE_IDENT: /* F5 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_TE_IDENT (F5)\n"); ++ layer1_state(xpd, 0); ++ break; ++ case ST_TE_SYNCED: /* F6 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_TE_SYNCED (F6)\n"); ++ layer1_state(xpd, 0); ++ break; ++ case ST_TE_ACTIVATED: /* F7 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_TE_ACTIVATED (F7)\n"); ++ set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_OFF); ++ clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); ++ set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); ++ layer1_state(xpd, 1); ++ update_xpd_status(xpd, DAHDI_ALARM_NONE); ++ break; ++ case ST_TE_LOST_FRAMING: /* F8 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_TE_LOST_FRAMING (F8)\n"); ++ layer1_state(xpd, 0); ++ break; ++ default: ++ XPD_NOTICE(xpd, "Bad TE state: %d\n", ++ new_state.bits.v_su_sta); ++ break; ++ } ++ ++ } else { ++ switch (new_state.bits.v_su_sta) { ++ case ST_NT_DEACTIVATED: /* G1 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVATED (G1)\n"); ++ clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags); ++ set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); ++ layer1_state(xpd, 0); ++ break; ++ case ST_NT_ACTIVATING: /* G2 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATING (G2)\n"); ++ layer1_state(xpd, 0); ++ if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) ++ nt_activation(xpd, 1); ++ break; ++ case ST_NT_ACTIVATED: /* G3 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATED (G3)\n"); ++ clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); ++ set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); ++ set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); ++ layer1_state(xpd, 1); ++ update_xpd_status(xpd, DAHDI_ALARM_NONE); ++ break; ++ case ST_NT_DEACTIVTING: /* G4 */ ++ XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVTING (G4)\n"); ++ set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF); ++ layer1_state(xpd, 0); ++ break; ++ default: ++ XPD_NOTICE(xpd, "Bad NT state: %d\n", ++ new_state.bits.v_su_sta); ++ break; ++ } ++ } ++ priv->state_register.reg = new_state.reg; ++} ++ ++static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) ++{ ++ unsigned long flags; ++ struct BRI_priv_data *priv; ++ struct xpd_addr addr; ++ xpd_t *orig_xpd; ++ int ret; ++ ++ /* Map UNIT + PORTNUM to XPD */ ++ orig_xpd = xpd; ++ addr.unit = orig_xpd->addr.unit; ++ addr.subunit = info->h.portnum; ++ xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); ++ if (!xpd) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) < 5) ++ notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname); ++ return -EPROTO; ++ } ++ spin_lock_irqsave(&xpd->lock, flags); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (REG_FIELD(info, do_subreg)) { ++ XPD_DBG(REGS, xpd, "RI %02X %02X %02X\n", ++ REG_FIELD(info, regnum), REG_FIELD(info, subreg), ++ REG_FIELD(info, data_low)); ++ } else { ++ if (REG_FIELD(info, regnum) != A_SU_RD_STA) ++ XPD_DBG(REGS, xpd, "RD %02X %02X\n", ++ REG_FIELD(info, regnum), REG_FIELD(info, ++ data_low)); ++ else ++ XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n", ++ REG_FIELD(info, data_low)); ++ } ++ if (info->h.is_multibyte) { ++ XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n", ++ info->h.bytes, info->h.eoframe); ++ ret = rx_dchan(xpd, info); ++ if (ret < 0) { ++ priv->dchan_rx_drops++; ++ if (atomic_read(&PHONEDEV(xpd).open_counter) > 0) ++ XPD_NOTICE(xpd, "Multibyte Drop: errno=%d\n", ++ ret); ++ } ++ goto end; ++ } ++ if (REG_FIELD(info, regnum) == A_SU_RD_STA) ++ su_new_state(xpd, REG_FIELD(info, data_low)); ++ ++ /* Update /proc info only if reply relate to the last slic read request */ ++ if (REG_FIELD(&xpd->requested_reply, regnum) == ++ REG_FIELD(info, regnum) ++ && REG_FIELD(&xpd->requested_reply, do_subreg) == ++ REG_FIELD(info, do_subreg) ++ && REG_FIELD(&xpd->requested_reply, subreg) == ++ REG_FIELD(info, subreg)) { ++ xpd->last_reply = *info; ++ } ++ ++end: ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++static int BRI_card_state(xpd_t *xpd, bool on) ++{ ++ struct BRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF"); ++ if (on) { ++ if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) { ++ if (!IS_NT(xpd)) ++ te_activation(xpd, 1); ++ else ++ nt_activation(xpd, 1); ++ } ++ } else if (IS_NT(xpd)) ++ nt_activation(xpd, 0); ++ return 0; ++} ++ ++static const struct xops bri_xops = { ++ .card_new = BRI_card_new, ++ .card_init = BRI_card_init, ++ .card_remove = BRI_card_remove, ++ .card_tick = BRI_card_tick, ++ .card_register_reply = BRI_card_register_reply, ++}; ++ ++static const struct phoneops bri_phoneops = { ++ .card_dahdi_preregistration = BRI_card_dahdi_preregistration, ++ .card_dahdi_postregistration = BRI_card_dahdi_postregistration, ++ .card_hooksig = BRI_card_hooksig, ++ .card_pcm_recompute = BRI_card_pcm_recompute, ++ .card_pcm_fromspan = BRI_card_pcm_fromspan, ++ .card_pcm_tospan = BRI_card_pcm_tospan, ++ .card_timing_priority = BRI_timing_priority, ++ .echocancel_timeslot = BRI_echocancel_timeslot, ++ .echocancel_setmask = BRI_echocancel_setmask, ++ .card_ioctl = BRI_card_ioctl, ++ .card_open = BRI_card_open, ++ .card_close = BRI_card_close, ++ .card_state = BRI_card_state, ++}; ++ ++static xproto_table_t PROTO_TABLE(BRI) = { ++ .owner = THIS_MODULE, ++ .entries = { ++ /* Table Card Opcode */ ++ }, ++ .name = "BRI", /* protocol name */ ++ .ports_per_subunit = 1, ++ .type = XPD_TYPE_BRI, ++ .xops = &bri_xops, ++ .phoneops = &bri_phoneops, ++ .packet_is_valid = bri_packet_is_valid, ++ .packet_dump = bri_packet_dump, ++}; ++ ++static bool bri_packet_is_valid(xpacket_t *pack) ++{ ++ const xproto_entry_t *xe = NULL; ++ // DBG(GENERAL, "\n"); ++ xe = xproto_card_entry(&PROTO_TABLE(BRI), XPACKET_OP(pack)); ++ return xe != NULL; ++} ++ ++static void bri_packet_dump(const char *msg, xpacket_t *pack) ++{ ++ DBG(GENERAL, "%s\n", msg); ++} ++ ++/*------------------------- REGISTER Handling --------------------------*/ ++ ++#ifdef CONFIG_PROC_FS ++static int proc_bri_info_show(struct seq_file *sfile, void *not_used) ++{ ++ unsigned long flags; ++ xpd_t *xpd = sfile->private; ++ struct BRI_priv_data *priv; ++ ++ DBG(PROC, "\n"); ++ if (!xpd) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ seq_printf(sfile, "%05d Layer 1: ", priv->poll_counter); ++ if (priv->reg30_good) { ++ seq_printf(sfile, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN"); ++ seq_printf(sfile, ++ "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n", ++ IS_NT(xpd) ? 'G' : 'F', ++ priv->state_register.bits.v_su_sta, ++ xhfc_state_name(IS_NT(xpd), ++ priv->state_register.bits.v_su_sta), ++ priv->state_register.bits.v_su_fr_sync, ++ priv->state_register.bits.v_su_t2_exp, ++ priv->state_register.bits.v_su_info0, ++ priv->state_register.bits.v_g2_g3); ++ } else { ++ seq_printf(sfile, "Unknown\n"); ++ } ++ if (IS_NT(xpd)) ++ seq_printf(sfile, "T1 Timer: %d\n", priv->t1); ++ else ++ seq_printf(sfile, "T3 Timer: %d\n", priv->t3); ++ seq_printf(sfile, "Tick Counter: %d\n", priv->tick_counter); ++ seq_printf(sfile, "Last Poll Reply: %d ticks ago\n", ++ priv->reg30_ticks); ++ seq_printf(sfile, "reg30_good=%d\n", priv->reg30_good); ++ seq_printf(sfile, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ", ++ priv->dchan_tx_counter, priv->dchan_rx_counter, ++ priv->dchan_rx_drops); ++ if (priv->dchan_alive) { ++ seq_printf(sfile, "(alive %d K-ticks)\n", ++ priv->dchan_alive_ticks / 1000); ++ } else { ++ seq_printf(sfile, "(dead)\n"); ++ } ++ seq_printf(sfile, "dchan_notx_ticks: %d\n", ++ priv->dchan_notx_ticks); ++ seq_printf(sfile, "dchan_norx_ticks: %d\n", ++ priv->dchan_norx_ticks); ++ seq_printf(sfile, "LED: %-10s = %d\n", "GREEN", ++ priv->ledstate[GREEN_LED]); ++ seq_printf(sfile, "LED: %-10s = %d\n", "RED", ++ priv->ledstate[RED_LED]); ++ seq_printf(sfile, "\nDCHAN:\n"); ++ seq_printf(sfile, "\n"); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++static int proc_bri_info_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_bri_info_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_bri_info_ops = { ++ .proc_open = proc_bri_info_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations proc_bri_info_ops = { ++ .owner = THIS_MODULE, ++ .open = proc_bri_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++#endif ++ ++static int bri_xpd_probe(struct device *dev) ++{ ++ xpd_t *xpd; ++ ++ xpd = dev_to_xpd(dev); ++ /* Is it our device? */ ++ if (xpd->xpd_type != XPD_TYPE_BRI) { ++ XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev), ++ xpd->xpd_type); ++ return -EINVAL; ++ } ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ return 0; ++} ++ ++static int bri_xpd_remove(struct device *dev) ++{ ++ xpd_t *xpd; ++ ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ return 0; ++} ++ ++static struct xpd_driver bri_driver = { ++ .xpd_type = XPD_TYPE_BRI, ++ .driver = { ++ .name = "bri", ++ .owner = THIS_MODULE, ++ .probe = bri_xpd_probe, ++ .remove = bri_xpd_remove} ++}; ++ ++static int __init card_bri_startup(void) ++{ ++ int ret; ++ ++ if ((ret = xpd_driver_register(&bri_driver.driver)) < 0) ++ return ret; ++ xproto_register(&PROTO_TABLE(BRI)); ++ return 0; ++} ++ ++static void __exit card_bri_cleanup(void) ++{ ++ DBG(GENERAL, "\n"); ++ xproto_unregister(&PROTO_TABLE(BRI)); ++ xpd_driver_unregister(&bri_driver.driver); ++} ++ ++MODULE_DESCRIPTION("XPP BRI Card Driver"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_XPD(XPD_TYPE_BRI); ++ ++module_init(card_bri_startup); ++module_exit(card_bri_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_bri.h linux-source-4.19-dahdi/drivers/dahdi/xpp/card_bri.h +--- linux-source-4.19/drivers/dahdi/xpp/card_bri.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_bri.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,31 @@ ++#ifndef CARD_BRI_H ++#define CARD_BRI_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++ ++enum bri_opcodes { ++ XPROTO_NAME(BRI, SET_LED) = 0x33, ++}; ++ ++#endif /* CARD_BRI_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_echo.c linux-source-4.19-dahdi/drivers/dahdi/xpp/card_echo.c +--- linux-source-4.19/drivers/dahdi/xpp/card_echo.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_echo.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,363 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2011, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++#include "xproto.h" ++#include "card_echo.h" ++#include "xpp_dahdi.h" ++#include "dahdi_debug.h" ++#include "xpd.h" ++#include "xbus-core.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++/* must be before dahdi_debug.h: */ ++static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++ ++/*---------------- ECHO Protocol Commands ----------------------------------*/ ++ ++static bool echo_packet_is_valid(xpacket_t *pack); ++static void echo_packet_dump(const char *msg, xpacket_t *pack); ++ ++DEF_RPACKET_DATA(ECHO, SET, __u8 timeslots[ECHO_TIMESLOTS];); ++ ++DEF_RPACKET_DATA(ECHO, SET_REPLY, __u8 status; __u8 reserved;); ++ ++struct ECHO_priv_data { ++}; ++ ++static xproto_table_t PROTO_TABLE(ECHO); ++ ++/*---------------- ECHO: Methods -------------------------------------------*/ ++ ++static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit, ++ const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ bool to_phone) ++{ ++ xpd_t *xpd = NULL; ++ int channels = 0; ++ ++ if (unit_descriptor->ports_per_chip != 1) { ++ XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip); ++ return NULL; ++ } ++ XBUS_DBG(GENERAL, xbus, "\n"); ++ xpd = ++ xpd_alloc(xbus, unit, subunit, ++ sizeof(struct ECHO_priv_data), proto_table, unit_descriptor, channels); ++ if (!xpd) ++ return NULL; ++ xpd->type_name = "ECHO"; ++ return xpd; ++} ++ ++static int ECHO_card_init(xbus_t *xbus, xpd_t *xpd) ++{ ++ int ret = 0; ++ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ xpd->xpd_type = XPD_TYPE_ECHO; ++ XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name); ++ ret = CALL_EC_METHOD(ec_update, xbus, xbus); ++ return ret; ++} ++ ++static int ECHO_card_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ return 0; ++} ++ ++static int ECHO_card_tick(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct ECHO_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ return 0; ++} ++ ++static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) ++{ ++ unsigned long flags; ++ struct xpd_addr addr; ++ xpd_t *orig_xpd; ++ ++ /* Map UNIT + PORTNUM to XPD */ ++ orig_xpd = xpd; ++ addr.unit = orig_xpd->addr.unit; ++ addr.subunit = info->h.portnum; ++ xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); ++ if (!xpd) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) < 5) ++ notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname); ++ return -EPROTO; ++ } ++ spin_lock_irqsave(&xpd->lock, flags); ++ /* Update /proc info only if reply related to last reg read request */ ++ if (REG_FIELD(&xpd->requested_reply, regnum) == ++ REG_FIELD(info, regnum) ++ && REG_FIELD(&xpd->requested_reply, do_subreg) == ++ REG_FIELD(info, do_subreg) ++ && REG_FIELD(&xpd->requested_reply, subreg) == ++ REG_FIELD(info, subreg)) { ++ xpd->last_reply = *info; ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++/*---------------- ECHO: HOST COMMANDS -------------------------------------*/ ++ ++static /* 0x39 */ HOSTCMD(ECHO, SET) ++{ ++ struct xbus_echo_state *es; ++ __u8 *ts; ++ xframe_t *xframe; ++ xpacket_t *pack; ++ int ret; ++ uint16_t frm_len; ++ int xpd_idx; ++ ++ BUG_ON(!xbus); ++ /* ++ * Find echo canceller XPD address ++ */ ++ es = &xbus->echo_state; ++ xpd_idx = es->xpd_idx; ++ XFRAME_NEW_CMD(xframe, pack, xbus, ECHO, SET, xpd_idx); ++ ts = RPACKET_FIELD(pack, ECHO, SET, timeslots); ++ memcpy(ts, es->timeslots, ECHO_TIMESLOTS); ++ frm_len = XFRAME_LEN(xframe); ++ XBUS_DBG(GENERAL, xbus, "ECHO SET: (len = %d)\n", frm_len); ++ ret = send_cmd_frame(xbus, xframe); ++ return ret; ++} ++ ++static int ECHO_ec_set(xpd_t *xpd, int pos, bool on) ++{ ++ int ts_number; ++ int ts_mask; ++ __u8 *ts; ++ ++ ts = xpd->xbus->echo_state.timeslots; ++ /* ++ * ts_number = PCM time slot ("channel number" in the PCM XPP packet) ++ * ++ * Bit 0 is for UNIT=0 ++ * PRI: ts_number * 4 + SUBUNIT ++ * BRI: ts_number ++ * FXS/FXO(all units): UNIT * 32 + ts_number ++ * ++ * Bit 1 is for UNIT=1-3: FXS/FXO ++ * ++ */ ++ ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2; /* Which bit? */ ++ ts_number = CALL_PHONE_METHOD(echocancel_timeslot, xpd, pos); ++ if (ts_number >= ECHO_TIMESLOTS || ts_number < 0) { ++ XPD_ERR(xpd, "Bad ts_number=%d\n", ts_number); ++ return -EINVAL; ++ } else { ++ if (on) ++ ts[ts_number] |= ts_mask; ++ else ++ ts[ts_number] &= ~ts_mask; ++ } ++ LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n", ++ __func__, on, ts_number, ts_mask); ++ return 0; ++} ++ ++static int ECHO_ec_get(xpd_t *xpd, int pos) ++{ ++ int ts_number; ++ int ts_mask; ++ int is_on; ++ __u8 *ts; ++ ++ ts = xpd->xbus->echo_state.timeslots; ++ ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2; /* Which bit? */ ++ ts_number = CALL_PHONE_METHOD(echocancel_timeslot, xpd, pos); ++ if (ts_number >= ECHO_TIMESLOTS || ts_number < 0) { ++ XPD_ERR(xpd, "Bad ts_number=%d\n", ts_number); ++ return -EINVAL; ++ } else { ++ is_on = ts[ts_number] & ts_mask; ++ } ++#if 0 ++ LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n", ++ is_on, ts_number, ts_mask); ++#endif ++ return is_on; ++} ++ ++static void ECHO_ec_dump(xbus_t *xbus) ++{ ++ __u8 *ts; ++ int i; ++ ++ ts = xbus->echo_state.timeslots; ++ for (i = 0; i + 15 < ECHO_TIMESLOTS; i += 16) { ++ XBUS_DBG(GENERAL, xbus, ++ "EC-DUMP[%03d]: " ++ "0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X " ++ "0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", ++ i, ts[i + 0], ts[i + 1], ts[i + 2], ts[i + 3], ++ ts[i + 4], ts[i + 5], ts[i + 6], ts[i + 7], ts[i + 8], ++ ts[i + 9], ts[i + 10], ts[i + 11], ts[i + 12], ++ ts[i + 13], ts[i + 14], ts[i + 15] ++ ); ++ } ++} ++ ++static int ECHO_ec_update(xbus_t *xbus) ++{ ++ XBUS_DBG(GENERAL, xbus, "%s\n", __func__); ++ //ECHO_ec_dump(xbus); ++ return CALL_PROTO(ECHO, SET, xbus, NULL); ++} ++ ++/*---------------- ECHO: Astribank Reply Handlers --------------------------*/ ++HANDLER_DEF(ECHO, SET_REPLY) ++{ ++ __u8 status; ++ ++ BUG_ON(!xpd); ++ status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status); ++ XPD_DBG(GENERAL, xpd, "status=0x%X\n", status); ++ return 0; ++} ++ ++static const struct xops echo_xops = { ++ .card_new = ECHO_card_new, ++ .card_init = ECHO_card_init, ++ .card_remove = ECHO_card_remove, ++ .card_tick = ECHO_card_tick, ++ .card_register_reply = ECHO_card_register_reply, ++}; ++ ++static const struct echoops echoops = { ++ .ec_set = ECHO_ec_set, ++ .ec_get = ECHO_ec_get, ++ .ec_update = ECHO_ec_update, ++ .ec_dump = ECHO_ec_dump, ++}; ++ ++static xproto_table_t PROTO_TABLE(ECHO) = { ++ .owner = THIS_MODULE, ++ .entries = { ++ /* Table Card Opcode */ ++ XENTRY( ECHO, ECHO, SET_REPLY ), ++ }, ++ .name = "ECHO", ++ .ports_per_subunit = 1, ++ .type = XPD_TYPE_ECHO, ++ .xops = &echo_xops, ++ .echoops = &echoops, ++ .packet_is_valid = echo_packet_is_valid, ++ .packet_dump = echo_packet_dump, ++}; ++ ++static bool echo_packet_is_valid(xpacket_t *pack) ++{ ++ const xproto_entry_t *xe = NULL; ++ // DBG(GENERAL, "\n"); ++ xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack)); ++ return xe != NULL; ++} ++ ++static void echo_packet_dump(const char *msg, xpacket_t *pack) ++{ ++ DBG(GENERAL, "%s\n", msg); ++} ++ ++/*------------------------- sysfs stuff --------------------------------*/ ++static int echo_xpd_probe(struct device *dev) ++{ ++ xpd_t *ec_xpd; ++ int ret = 0; ++ ++ ec_xpd = dev_to_xpd(dev); ++ /* Is it our device? */ ++ if (ec_xpd->xpd_type != XPD_TYPE_ECHO) { ++ XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev), ++ ec_xpd->xpd_type); ++ return -EINVAL; ++ } ++ XPD_DBG(DEVICES, ec_xpd, "SYSFS\n"); ++ return ret; ++} ++ ++static int echo_xpd_remove(struct device *dev) ++{ ++ xpd_t *ec_xpd; ++ ++ ec_xpd = dev_to_xpd(dev); ++ XPD_DBG(DEVICES, ec_xpd, "SYSFS\n"); ++ return 0; ++} ++ ++static struct xpd_driver echo_driver = { ++ .xpd_type = XPD_TYPE_ECHO, ++ .driver = { ++ .name = "echo", ++ .owner = THIS_MODULE, ++ .probe = echo_xpd_probe, ++ .remove = echo_xpd_remove} ++}; ++ ++static int __init card_echo_startup(void) ++{ ++ int ret; ++ ++ ret = xpd_driver_register(&echo_driver.driver); ++ if (ret < 0) ++ return ret; ++ INFO("FEATURE: WITH Octasic echo canceller\n"); ++ xproto_register(&PROTO_TABLE(ECHO)); ++ return 0; ++} ++ ++static void __exit card_echo_cleanup(void) ++{ ++ DBG(GENERAL, "\n"); ++ xproto_unregister(&PROTO_TABLE(ECHO)); ++ xpd_driver_unregister(&echo_driver.driver); ++} ++ ++MODULE_DESCRIPTION("XPP ECHO Card Driver"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_XPD(XPD_TYPE_ECHO); ++ ++module_init(card_echo_startup); ++module_exit(card_echo_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_echo.h linux-source-4.19-dahdi/drivers/dahdi/xpp/card_echo.h +--- linux-source-4.19/drivers/dahdi/xpp/card_echo.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_echo.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,31 @@ ++#ifndef CARD_ECHO_H ++#define CARD_ECHO_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2011, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++ ++enum echo_opcodes { ++ XPROTO_NAME(ECHO, SET) = 0x39, ++ XPROTO_NAME(ECHO, SET_REPLY) = 0x3A, ++}; ++ ++#endif /* CARD_ECHO_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_fxo.c linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxo.c +--- linux-source-4.19/drivers/dahdi/xpp/card_fxo.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxo.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,1669 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++#include "xproto.h" ++#include "xpp_dahdi.h" ++#include "card_fxo.h" ++#include "dahdi_debug.h" ++#include "xbus-core.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++static DEF_PARM(uint, poll_battery_interval, 500, 0644, ++ "Poll battery interval in milliseconds (0 - disable)"); ++static DEF_PARM_BOOL(use_polrev_firmware, 1, 0444, ++ "Use firmware reports of polarity reversal"); ++static DEF_PARM_BOOL(squelch_polrev, 0, 0644, ++ "Never report polarity reversal"); ++#ifdef WITH_METERING ++static DEF_PARM(uint, poll_metering_interval, 500, 0644, ++ "Poll metering interval in milliseconds (0 - disable)"); ++#endif ++static DEF_PARM(int, ring_debounce, 50, 0644, ++ "Number of ticks to debounce a false RING indication"); ++static DEF_PARM(int, caller_id_style, 0, 0444, ++ "Caller-Id detection style: " ++ "0 - [BELL], " ++ "1 - [ETSI_FSK], " ++ "2 - [ETSI_DTMF], " ++ "3 - [PASSTHROUGH]"); ++static DEF_PARM(int, power_denial_safezone, 650, 0644, ++ "msec after offhook to ignore power-denial ( (0 - disable power-denial)"); ++static DEF_PARM(int, power_denial_minlen, 80, 0644, ++ "Minimal detected power-denial length (msec) (0 - disable power-denial)"); ++static DEF_PARM(uint, battery_threshold, 3, 0644, ++ "Minimum voltage that shows there is battery"); ++static DEF_PARM(uint, battery_debounce, 1000, 0644, ++ "Minimum interval (msec) for detection of battery off"); ++ ++enum cid_style { ++ CID_STYLE_BELL = 0, /* E.g: US (Bellcore) */ ++ CID_STYLE_ETSI_FSK = 1, /* E.g: UK (British Telecom) */ ++ CID_STYLE_ETSI_DTMF = 2, /* E.g: DK, Russia */ ++ CID_STYLE_PASSTHROUGH = 3, /* No change: Let asterisk */ ++ /* (>= 1.8) DSP handle this */ ++}; ++ ++/* Signaling is opposite (fxs signalling for fxo card) */ ++#if 1 ++#define FXO_DEFAULT_SIGCAP (DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS) ++#else ++#define FXO_DEFAULT_SIGCAP (DAHDI_SIG_SF) ++#endif ++ ++enum fxo_leds { ++ LED_GREEN, ++ LED_RED, ++}; ++ ++#define NUM_LEDS 2 ++#define DELAY_UNTIL_DIALTONE 3000 ++ ++/* ++ * Minimum duration for polarity reversal detection (in ticks) ++ * Should be longer than the time to detect a ring, so voltage ++ * fluctuation during ring won't trigger false detection. ++ */ ++#define POLREV_THRESHOLD 200 ++#define POWER_DENIAL_CURRENT 3 ++#define POWER_DENIAL_DELAY 2500 /* ticks */ ++ ++/* Shortcuts */ ++#define DAA_WRITE 1 ++#define DAA_READ 0 ++#define DAA_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL) \ ++ xpp_register_request((xbus), (xpd), (port), \ ++ (writing), (reg), 0, 0, (dL), 0, 0, 0, 0) ++ ++/*---------------- FXO Protocol Commands ----------------------------------*/ ++ ++static bool fxo_packet_is_valid(xpacket_t *pack); ++static void fxo_packet_dump(const char *msg, xpacket_t *pack); ++#ifdef CONFIG_PROC_FS ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_fxo_info_ops; ++#else ++static const struct file_operations proc_fxo_info_ops; ++#endif ++#ifdef WITH_METERING ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_xpd_metering_ops; ++#else ++static const struct file_operations proc_xpd_metering_ops; ++#endif ++#endif ++#endif ++static void dahdi_report_battery(xpd_t *xpd, lineno_t chan); ++static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg); ++ ++#define PROC_FXO_INFO_FNAME "fxo_info" ++#ifdef WITH_METERING ++#define PROC_METERING_FNAME "metering_read" ++#endif ++ ++#define REG_INTERRUPT_SRC 0x04 /* 4 - Interrupt Source */ ++#define REG_INTERRUPT_SRC_POLI BIT(0) /* Polarity Reversal Detect Interrupt*/ ++#define REG_INTERRUPT_SRC_RING BIT(7) /* Ring Detect Interrupt */ ++ ++#define REG_DAA_CONTROL1 0x05 /* 5 - DAA Control 1 */ ++#define REG_DAA_CONTROL1_OH BIT(0) /* Off-Hook. */ ++#define REG_DAA_CONTROL1_ONHM BIT(3) /* On-Hook Line Monitor */ ++ ++#define DAA_REG_METERING 0x11 /* 17 */ ++#define DAA_REG_CURRENT 0x1C /* 28 */ ++#define DAA_REG_VBAT 0x1D /* 29 */ ++ ++enum battery_state { ++ BATTERY_UNKNOWN = 0, ++ BATTERY_ON = 1, ++ BATTERY_OFF = -1 ++}; ++ ++enum polarity_state { ++ POL_UNKNOWN = 0, ++ POL_POSITIVE = 1, ++ POL_NEGATIVE = -1 ++}; ++ ++enum power_state { ++ POWER_UNKNOWN = 0, ++ POWER_ON = 1, ++ POWER_OFF = -1 ++}; ++ ++struct FXO_priv_data { ++#ifdef WITH_METERING ++ struct proc_dir_entry *meteringfile; ++#endif ++ struct proc_dir_entry *fxo_info; ++ uint poll_counter; ++ signed char battery_voltage[CHANNELS_PERXPD]; ++ signed char battery_current[CHANNELS_PERXPD]; ++ enum battery_state battery[CHANNELS_PERXPD]; ++ ushort nobattery_debounce[CHANNELS_PERXPD]; ++ enum polarity_state polarity[CHANNELS_PERXPD]; ++ ushort polarity_debounce[CHANNELS_PERXPD]; ++ int polarity_last_interval[CHANNELS_PERXPD]; ++#define POLARITY_LAST_INTERVAL_NONE (-1) ++#define POLARITY_LAST_INTERVAL_MAX 40 ++ enum power_state power[CHANNELS_PERXPD]; ++ ushort power_denial_delay[CHANNELS_PERXPD]; ++ ushort power_denial_length[CHANNELS_PERXPD]; ++ ushort power_denial_safezone[CHANNELS_PERXPD]; ++ xpp_line_t cidfound; /* 0 - OFF, 1 - ON */ ++ unsigned int cidtimer[CHANNELS_PERXPD]; ++ xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ ++ xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ ++ int led_counter[NUM_LEDS][CHANNELS_PERXPD]; ++ atomic_t ring_debounce[CHANNELS_PERXPD]; ++#ifdef WITH_METERING ++ uint metering_count[CHANNELS_PERXPD]; ++ xpp_line_t metering_tone_state; ++#endif ++}; ++ ++/* ++ * LED counter values: ++ * n>1 : BLINK every n'th tick ++ */ ++#define LED_COUNTER(priv, pos, color) ((priv)->led_counter[color][pos]) ++#define IS_BLINKING(priv, pos, color) (LED_COUNTER(priv, pos, color) > 0) ++#define MARK_BLINK(priv, pos, color, t) \ ++ ((priv)->led_counter[color][pos] = (t)) ++#define MARK_OFF(priv, pos, color) \ ++ do { \ ++ BIT_CLR((priv)->ledcontrol[color], (pos)); \ ++ MARK_BLINK((priv), (pos), (color), 0); \ ++ } while (0) ++#define MARK_ON(priv, pos, color) \ ++ do { \ ++ BIT_SET((priv)->ledcontrol[color], (pos)); \ ++ MARK_BLINK((priv), (pos), (color), 0); \ ++ } while (0) ++ ++#define LED_BLINK_RING (1000/8) /* in ticks */ ++ ++/*---------------- FXO: Static functions ----------------------------------*/ ++ ++static const char *power2str(enum power_state pw) ++{ ++ switch (pw) { ++ case POWER_UNKNOWN: ++ return "UNKNOWN"; ++ case POWER_OFF: ++ return "OFF"; ++ case POWER_ON: ++ return "ON"; ++ } ++ return NULL; ++} ++ ++static void power_change(xpd_t *xpd, int portno, enum power_state pw) ++{ ++ struct FXO_priv_data *priv; ++ ++ priv = xpd->priv; ++ LINE_DBG(SIGNAL, xpd, portno, "power: %s -> %s\n", ++ power2str(priv->power[portno]), power2str(pw)); ++ priv->power[portno] = pw; ++} ++ ++static void reset_battery_readings(xpd_t *xpd, lineno_t pos) ++{ ++ struct FXO_priv_data *priv = xpd->priv; ++ ++ priv->nobattery_debounce[pos] = 0; ++ priv->power_denial_delay[pos] = 0; ++ power_change(xpd, pos, POWER_UNKNOWN); ++} ++ ++static const int led_register_mask[] = { BIT(7), BIT(6), BIT(5) }; ++ ++/* ++ * LED control is done via DAA register 0x20 ++ */ ++static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on) ++{ ++ int ret = 0; ++ struct FXO_priv_data *priv; ++ xbus_t *xbus; ++ __u8 value; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ which = which % NUM_LEDS; ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, chan) ++ || IS_SET(PHONEDEV(xpd).digital_inputs, chan)) ++ goto out; ++ if (chan == PORT_BROADCAST) { ++ priv->ledstate[which] = (on) ? ~0 : 0; ++ } else { ++ if (on) ++ BIT_SET(priv->ledstate[which], chan); ++ else ++ BIT_CLR(priv->ledstate[which], chan); ++ } ++ value = 0; ++ value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]); ++ value |= (on) ? BIT(0) : 0; ++ value |= (on) ? BIT(1) : 0; ++ LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, ++ (on) ? "on" : "off"); ++ ret = DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x20, value); ++out: ++ return ret; ++} ++ ++static void handle_fxo_leds(xpd_t *xpd) ++{ ++ int i; ++ unsigned long flags; ++ const enum fxo_leds colors[] = { LED_GREEN, LED_RED }; ++ enum fxo_leds color; ++ unsigned int timer_count; ++ struct FXO_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ spin_lock_irqsave(&xpd->lock, flags); ++ priv = xpd->priv; ++ timer_count = xpd->timer_count; ++ for (color = 0; color < ARRAY_SIZE(colors); color++) { ++ for_each_line(xpd, i) { ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ || IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ continue; ++ /* Blinking? */ ++ if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { ++ int mod_value = LED_COUNTER(priv, i, color); ++ ++ if (!mod_value) ++ /* safety value */ ++ mod_value = DEFAULT_LED_PERIOD; ++ // led state is toggled ++ if ((timer_count % mod_value) == 0) { ++ LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", ++ (IS_SET ++ (priv->ledstate[color], ++ i)) ? "ON" : "OFF"); ++ if (!IS_SET(priv->ledstate[color], i)) ++ do_led(xpd, i, color, 1); ++ else ++ do_led(xpd, i, color, 0); ++ } ++ } else if (IS_SET(priv->ledcontrol[color], i) ++ && !IS_SET(priv->ledstate[color], i)) { ++ do_led(xpd, i, color, 1); ++ } else if (!IS_SET(priv->ledcontrol[color], i) ++ && IS_SET(priv->ledstate[color], i)) { ++ do_led(xpd, i, color, 0); ++ } ++ } ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++} ++ ++static void update_dahdi_ring(xpd_t *xpd, int pos, bool on) ++{ ++ BUG_ON(!xpd); ++ if (caller_id_style == CID_STYLE_BELL) ++ oht_pcm(xpd, pos, !on); ++ /* ++ * We should not spinlock before calling dahdi_hooksig() as ++ * it may call back into our xpp_hooksig() and cause ++ * a nested spinlock scenario ++ */ ++ notify_rxsig(xpd, pos, (on) ? DAHDI_RXSIG_RING : DAHDI_RXSIG_OFFHOOK); ++} ++ ++static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_dahdi) ++{ ++ struct FXO_priv_data *priv; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ atomic_set(&priv->ring_debounce[pos], 0); /* Stop debouncing */ ++ /* ++ * We don't want to check battery during ringing ++ * due to voltage fluctuations. ++ */ ++ reset_battery_readings(xpd, pos); ++ if (on && !PHONEDEV(xpd).ringing[pos]) { ++ LINE_DBG(SIGNAL, xpd, pos, "START\n"); ++ PHONEDEV(xpd).ringing[pos] = 1; ++ priv->cidtimer[pos] = xpd->timer_count; ++ MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK_RING); ++ if (update_dahdi) ++ update_dahdi_ring(xpd, pos, on); ++ } else if (!on && PHONEDEV(xpd).ringing[pos]) { ++ LINE_DBG(SIGNAL, xpd, pos, "STOP\n"); ++ PHONEDEV(xpd).ringing[pos] = 0; ++ priv->cidtimer[pos] = xpd->timer_count; ++ if (IS_BLINKING(priv, pos, LED_GREEN)) ++ MARK_BLINK(priv, pos, LED_GREEN, 0); ++ if (update_dahdi) ++ update_dahdi_ring(xpd, pos, on); ++ priv->polarity_last_interval[pos] = POLARITY_LAST_INTERVAL_NONE; ++ } ++} ++ ++static int do_sethook(xpd_t *xpd, int pos, bool to_offhook) ++{ ++ unsigned long flags; ++ xbus_t *xbus; ++ struct FXO_priv_data *priv; ++ int ret = 0; ++ __u8 value; ++ ++ BUG_ON(!xpd); ++ /* We can SETHOOK state only on PSTN */ ++ BUG_ON(PHONEDEV(xpd).direction == TO_PHONE); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (priv->battery[pos] != BATTERY_ON && to_offhook) { ++ LINE_NOTICE(xpd, pos, ++ "Cannot take offhook while battery is off!\n"); ++ return -EINVAL; ++ } ++ spin_lock_irqsave(&xpd->lock, flags); ++ mark_ring(xpd, pos, 0, 0); // No more rings ++ value = REG_DAA_CONTROL1_ONHM; /* Bit 3 is for CID */ ++ if (to_offhook) ++ value |= REG_DAA_CONTROL1_OH; ++ LINE_DBG(SIGNAL, xpd, pos, "SETHOOK: value=0x%02X %s\n", value, ++ (to_offhook) ? "OFFHOOK" : "ONHOOK"); ++ if (to_offhook) ++ MARK_ON(priv, pos, LED_GREEN); ++ else ++ MARK_OFF(priv, pos, LED_GREEN); ++ ret = ++ DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1, ++ value); ++ mark_offhook(xpd, pos, to_offhook); ++ switch (caller_id_style) { ++ case CID_STYLE_ETSI_DTMF: ++ case CID_STYLE_PASSTHROUGH: ++ break; ++ default: ++ oht_pcm(xpd, pos, 0); ++ break; ++ } ++#ifdef WITH_METERING ++ priv->metering_count[pos] = 0; ++ priv->metering_tone_state = 0L; ++ DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_METERING, 0x2D); ++#endif ++ /* unstable during hook changes */ ++ reset_battery_readings(xpd, pos); ++ if (to_offhook) { ++ priv->power_denial_safezone[pos] = power_denial_safezone; ++ } else { ++ priv->power_denial_length[pos] = 0; ++ priv->power_denial_safezone[pos] = 0; ++ } ++ priv->cidtimer[pos] = xpd->timer_count; ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return ret; ++} ++ ++/*---------------- FXO: Methods -------------------------------------------*/ ++ ++static void fxo_proc_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXO_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ XPD_DBG(PROC, xpd, "\n"); ++#ifdef CONFIG_PROC_FS ++#ifdef WITH_METERING ++ if (priv->meteringfile) { ++ XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); ++ remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); ++ priv->meteringfile = NULL; ++ } ++#endif ++ if (priv->fxo_info) { ++ XPD_DBG(PROC, xpd, "Removing xpd FXO_INFO file\n"); ++ remove_proc_entry(PROC_FXO_INFO_FNAME, xpd->proc_xpd_dir); ++ priv->fxo_info = NULL; ++ } ++#endif ++} ++ ++static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXO_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++#ifdef CONFIG_PROC_FS ++ XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n"); ++ priv->fxo_info = proc_create_data(PROC_FXO_INFO_FNAME, 0444, ++ xpd->proc_xpd_dir, ++ &proc_fxo_info_ops, xpd); ++ if (!priv->fxo_info) { ++ XPD_ERR(xpd, "Failed to create proc file '%s'\n", ++ PROC_FXO_INFO_FNAME); ++ fxo_proc_remove(xbus, xpd); ++ return -EINVAL; ++ } ++ SET_PROC_DIRENTRY_OWNER(priv->fxo_info); ++#ifdef WITH_METERING ++ XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); ++ priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0444, ++ xpd->proc_xpd_dir, ++ &proc_xpd_metering_ops, xpd); ++ if (!priv->meteringfile) { ++ XPD_ERR(xpd, "Failed to create proc file '%s'\n", ++ PROC_METERING_FNAME); ++ fxo_proc_remove(xbus, xpd); ++ return -EINVAL; ++ } ++ SET_PROC_DIRENTRY_OWNER(priv->meteringfile); ++#endif ++#endif ++ return 0; ++} ++ ++static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit, ++ const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ bool to_phone) ++{ ++ xpd_t *xpd = NULL; ++ int channels; ++ int subunit_ports; ++ ++ if (to_phone) { ++ XBUS_NOTICE(xbus, ++ "XPD=%d%d: try to instanciate FXO with " ++ "reverse direction\n", ++ unit, subunit); ++ return NULL; ++ } ++ subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip; ++ if (unit_descriptor->subtype == 2) ++ channels = min(2, subunit_ports); ++ else ++ channels = min(8, subunit_ports); ++ xpd = ++ xpd_alloc(xbus, unit, subunit, ++ sizeof(struct FXO_priv_data), proto_table, unit_descriptor, channels); ++ if (!xpd) ++ return NULL; ++ PHONEDEV(xpd).direction = TO_PSTN; ++ xpd->type_name = "FXO"; ++ if (fxo_proc_create(xbus, xpd) < 0) ++ goto err; ++ return xpd; ++err: ++ xpd_free(xpd); ++ return NULL; ++} ++ ++static int FXO_card_init(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXO_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ // Hanghup all lines ++ for_each_line(xpd, i) { ++ do_sethook(xpd, i, 0); ++ /* will be updated on next battery sample */ ++ priv->polarity[i] = POL_UNKNOWN; ++ priv->polarity_debounce[i] = 0; ++ /* will be updated on next battery sample */ ++ priv->battery[i] = BATTERY_UNKNOWN; ++ /* will be updated on next battery sample */ ++ priv->power[i] = POWER_UNKNOWN; ++ switch (caller_id_style) { ++ case CID_STYLE_ETSI_DTMF: ++ case CID_STYLE_PASSTHROUGH: ++ oht_pcm(xpd, i, 1); ++ break; ++ } ++ priv->polarity_last_interval[i] = POLARITY_LAST_INTERVAL_NONE; ++ } ++ XPD_DBG(GENERAL, xpd, "done\n"); ++ for_each_line(xpd, i) { ++ do_led(xpd, i, LED_GREEN, 0); ++ } ++ for_each_line(xpd, i) { ++ do_led(xpd, i, LED_GREEN, 1); ++ msleep(50); ++ } ++ for_each_line(xpd, i) { ++ do_led(xpd, i, LED_GREEN, 0); ++ msleep(50); ++ } ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ return 0; ++} ++ ++static int FXO_card_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ fxo_proc_remove(xbus, xpd); ++ return 0; ++} ++ ++static int FXO_card_dahdi_preregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ struct FXO_priv_data *priv; ++ int i; ++ unsigned int timer_count; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ timer_count = xpd->timer_count; ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF"); ++ PHONEDEV(xpd).span.spantype = SPANTYPE_ANALOG_FXO; ++ for_each_line(xpd, i) { ++ struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i); ++ ++ XPD_DBG(GENERAL, xpd, "setting FXO channel %d\n", i); ++ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%02d/%1d%1d/%d", ++ xbus->num, xpd->addr.unit, xpd->addr.subunit, i); ++ cur_chan->chanpos = i + 1; ++ cur_chan->pvt = xpd; ++ cur_chan->sigcap = FXO_DEFAULT_SIGCAP; ++ } ++ for_each_line(xpd, i) { ++ MARK_ON(priv, i, LED_GREEN); ++ msleep(4); ++ MARK_ON(priv, i, LED_RED); ++ } ++ for_each_line(xpd, i) { ++ priv->cidtimer[i] = timer_count; ++ } ++ return 0; ++} ++ ++static int FXO_card_dahdi_postregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ struct FXO_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF"); ++ for_each_line(xpd, i) { ++ MARK_OFF(priv, i, LED_GREEN); ++ msleep(2); ++ MARK_OFF(priv, i, LED_RED); ++ msleep(2); ++ } ++ return 0; ++} ++ ++static int FXO_span_assigned(xpd_t *xpd) ++{ ++ xbus_t *xbus; ++ struct FXO_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ for_each_line(xpd, i) ++ dahdi_report_battery(xpd, i); ++ return 0; ++} ++ ++static int FXO_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig) ++{ ++ struct FXO_priv_data *priv; ++ int ret = 0; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); ++ BUG_ON(PHONEDEV(xpd).direction != TO_PSTN); ++ /* XXX Enable hooksig for FXO XXX */ ++ switch (txsig) { ++ case DAHDI_TXSIG_START: ++ case DAHDI_TXSIG_OFFHOOK: ++ ret = do_sethook(xpd, pos, 1); ++ break; ++ case DAHDI_TXSIG_ONHOOK: ++ ret = do_sethook(xpd, pos, 0); ++ break; ++ default: ++ XPD_NOTICE(xpd, "Can't set tx state to %s (%d)\n", ++ txsig2str(txsig), txsig); ++ return -EINVAL; ++ } ++ return ret; ++} ++ ++static void dahdi_report_battery(xpd_t *xpd, lineno_t chan) ++{ ++ struct FXO_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ if (SPAN_REGISTERED(xpd)) { ++ switch (priv->battery[chan]) { ++ case BATTERY_UNKNOWN: ++ /* no-op */ ++ break; ++ case BATTERY_OFF: ++ LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_RED\n"); ++ dahdi_alarm_channel(XPD_CHAN(xpd, chan), ++ DAHDI_ALARM_RED); ++ break; ++ case BATTERY_ON: ++ LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_NONE\n"); ++ dahdi_alarm_channel(XPD_CHAN(xpd, chan), ++ DAHDI_ALARM_NONE); ++ break; ++ } ++ } ++} ++ ++static int FXO_card_open(xpd_t *xpd, lineno_t chan) ++{ ++ BUG_ON(!xpd); ++ return 0; ++} ++ ++static void poll_battery(xbus_t *xbus, xpd_t *xpd) ++{ ++ int i; ++ ++ for_each_line(xpd, i) { ++ DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_VBAT, 0); ++ } ++} ++ ++#ifdef WITH_METERING ++static void poll_metering(xbus_t *xbus, xpd_t *xpd) ++{ ++ int i; ++ ++ for_each_line(xpd, i) { ++ if (IS_OFFHOOK(xpd, i)) ++ DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, ++ DAA_REG_METERING, 0); ++ } ++} ++#endif ++ ++static void handle_fxo_ring(xpd_t *xpd) ++{ ++ struct FXO_priv_data *priv; ++ int i; ++ ++ priv = xpd->priv; ++ for_each_line(xpd, i) { ++ if (likely(use_polrev_firmware)) { ++ int *t = &priv->polarity_last_interval[i]; ++ if (*t != POLARITY_LAST_INTERVAL_NONE) { ++ (*t)++; ++ if (*t > POLARITY_LAST_INTERVAL_MAX) { ++ LINE_DBG(SIGNAL, xpd, i, ++ "polrev(GOOD): %d msec\n", *t); ++ *t = POLARITY_LAST_INTERVAL_NONE; ++ report_polarity_reversal(xpd, ++ i, "firmware"); ++ } ++ } ++ } ++ if (atomic_read(&priv->ring_debounce[i]) > 0) { ++ /* Maybe start ring */ ++ if (atomic_dec_and_test(&priv->ring_debounce[i])) ++ mark_ring(xpd, i, 1, 1); ++ } else if (atomic_read(&priv->ring_debounce[i]) < 0) { ++ /* Maybe stop ring */ ++ if (atomic_inc_and_test(&priv->ring_debounce[i])) ++ mark_ring(xpd, i, 0, 1); ++ } ++ } ++} ++ ++static void handle_fxo_power_denial(xpd_t *xpd) ++{ ++ struct FXO_priv_data *priv; ++ int i; ++ ++ if (!power_denial_safezone) ++ return; /* Ignore power denials */ ++ priv = xpd->priv; ++ for_each_line(xpd, i) { ++ if (PHONEDEV(xpd).ringing[i] || !IS_OFFHOOK(xpd, i)) { ++ priv->power_denial_delay[i] = 0; ++ continue; ++ } ++ if (priv->power_denial_safezone[i] > 0) { ++ if (--priv->power_denial_safezone[i] == 0) { ++ /* ++ * Poll current, prev answers are meaningless ++ */ ++ DAA_DIRECT_REQUEST(xpd->xbus, xpd, i, DAA_READ, ++ DAA_REG_CURRENT, 0); ++ } ++ continue; ++ } ++ if (priv->power_denial_length[i] > 0) { ++ priv->power_denial_length[i]--; ++ if (priv->power_denial_length[i] <= 0) { ++ /* ++ * But maybe the FXS started to ring (and ++ * the firmware haven't detected it yet). ++ * This would cause false power denials so ++ * we just flag it and schedule more ticks ++ * to wait. ++ */ ++ LINE_DBG(SIGNAL, xpd, i, ++ "Possible Power Denial Hangup\n"); ++ priv->power_denial_delay[i] = ++ POWER_DENIAL_DELAY; ++ } ++ continue; ++ } ++ if (priv->power_denial_delay[i] > 0) { ++ /* ++ * Ring detection by the firmware takes some time. ++ * Therefore we delay our decision until we are ++ * sure that no ring has started during this time. ++ */ ++ priv->power_denial_delay[i]--; ++ if (priv->power_denial_delay[i] <= 0) { ++ LINE_DBG(SIGNAL, xpd, i, ++ "Power Denial Hangup\n"); ++ priv->power_denial_delay[i] = 0; ++ /* ++ * Let Asterisk decide what to do ++ */ ++ notify_rxsig(xpd, i, DAHDI_RXSIG_ONHOOK); ++ } ++ } ++ } ++} ++ ++/* ++ * For caller-id CID_STYLE_ETSI_DTMF: ++ * - No indication is passed before the CID ++ * - We try to detect it and send "fake" polarity reversal. ++ * - The chan_dahdi.conf should have cidstart=polarity ++ * - Based on an idea in http://bugs.digium.com/view.php?id=9096 ++ */ ++static void check_etsi_dtmf(xpd_t *xpd) ++{ ++ struct FXO_priv_data *priv; ++ int portno; ++ unsigned int timer_count; ++ ++ if (!SPAN_REGISTERED(xpd)) ++ return; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ timer_count = xpd->timer_count; ++ for_each_line(xpd, portno) { ++ /* Skip offhook and ringing ports */ ++ if (IS_OFFHOOK(xpd, portno) || PHONEDEV(xpd).ringing[portno]) ++ continue; ++ if (IS_SET(priv->cidfound, portno)) { ++ if (timer_count > priv->cidtimer[portno] + 4000) { ++ /* reset flags if it's been a while */ ++ priv->cidtimer[portno] = timer_count; ++ BIT_CLR(priv->cidfound, portno); ++ LINE_DBG(SIGNAL, xpd, portno, ++ "Reset CID flag\n"); ++ } ++ continue; ++ } ++ if (timer_count > priv->cidtimer[portno] + 400) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, portno); ++ int sample; ++ int i; ++ ++ for (i = 0; i < DAHDI_CHUNKSIZE; i++) { ++ sample = DAHDI_XLAW(chan->readchunk[i], chan); ++ if (sample > 16000 || sample < -16000) { ++ priv->cidtimer[portno] = timer_count; ++ BIT_SET(priv->cidfound, portno); ++ LINE_DBG(SIGNAL, xpd, portno, ++ "Found DTMF CLIP (%d)\n", i); ++ report_polarity_reversal(xpd, portno, ++ "fake"); ++ break; ++ } ++ } ++ } ++ } ++} ++ ++static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXO_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (poll_battery_interval != 0 ++ && (priv->poll_counter % poll_battery_interval) == 0) ++ poll_battery(xbus, xpd); ++#ifdef WITH_METERING ++ if (poll_metering_interval != 0 ++ && (priv->poll_counter % poll_metering_interval) == 0) ++ poll_metering(xbus, xpd); ++#endif ++ handle_fxo_leds(xpd); ++ handle_fxo_ring(xpd); ++ handle_fxo_power_denial(xpd); ++ if (caller_id_style == CID_STYLE_ETSI_DTMF && likely(xpd->card_present)) ++ check_etsi_dtmf(xpd); ++ priv->poll_counter++; ++ return 0; ++} ++ ++#include ++/* ++ * The first register is the ACIM, the other are coefficient registers. ++ * We define the array size explicitly to track possible inconsistencies ++ * if the struct is modified. ++ */ ++static const char echotune_regs[sizeof(struct wctdm_echo_coefs)] = ++ { 30, 45, 46, 47, 48, 49, 50, 51, 52 }; ++ ++static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, ++ unsigned long arg) ++{ ++ int i, ret; ++ unsigned char echotune_data[ARRAY_SIZE(echotune_regs)]; ++ ++ BUG_ON(!xpd); ++ if (!XBUS_IS(xpd->xbus, READY)) ++ return -ENODEV; ++ switch (cmd) { ++ case WCTDM_SET_ECHOTUNE: ++ XPD_DBG(GENERAL, xpd, "-- Setting echo registers: \n"); ++ /* first off: check if this span is fxs. If not: -EINVALID */ ++ if (copy_from_user ++ (&echotune_data, (void __user *)arg, sizeof(echotune_data))) ++ return -EFAULT; ++ ++ for (i = 0; i < ARRAY_SIZE(echotune_regs); i++) { ++ XPD_DBG(REGS, xpd, "Reg=0x%02X, data=0x%02X\n", ++ echotune_regs[i], echotune_data[i]); ++ ret = ++ DAA_DIRECT_REQUEST(xpd->xbus, xpd, pos, DAA_WRITE, ++ echotune_regs[i], ++ echotune_data[i]); ++ if (ret < 0) { ++ LINE_NOTICE(xpd, pos, ++ "Couldn't write %0x02X to " ++ "register %0x02X\n", ++ echotune_data[i], echotune_regs[i]); ++ return ret; ++ } ++ msleep(1); ++ } ++ ++ XPD_DBG(GENERAL, xpd, "-- Set echo registers successfully\n"); ++ break; ++ case DAHDI_TONEDETECT: ++ /* ++ * Asterisk call all span types with this (FXS specific) ++ * call. Silently ignore it. ++ */ ++ LINE_DBG(GENERAL, xpd, pos, ++ "DAHDI_TONEDETECT (FXO: NOTIMPLEMENTED)\n"); ++ return -ENOTTY; ++ default: ++ report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++/*---------------- FXO: HOST COMMANDS -------------------------------------*/ ++ ++/*---------------- FXO: Astribank Reply Handlers --------------------------*/ ++ ++HANDLER_DEF(FXO, SIG_CHANGED) ++{ ++ xpp_line_t sig_status = ++ RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_status); ++ xpp_line_t sig_toggles = ++ RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles); ++ unsigned long flags; ++ int i; ++ struct FXO_priv_data *priv; ++ ++ if (!xpd) { ++ notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), cmd->name); ++ return -EPROTO; ++ } ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(SIGNAL, xpd, "(PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", ++ sig_toggles, sig_status); ++ spin_lock_irqsave(&xpd->lock, flags); ++ for_each_line(xpd, i) { ++ int debounce; ++ ++ if (IS_SET(sig_toggles, i)) { ++ if (priv->battery[i] == BATTERY_OFF) { ++ /* ++ * With poll_battery_interval==0 we cannot ++ * have BATTERY_OFF so we won't get here ++ */ ++ LINE_NOTICE(xpd, i, ++ "SIG_CHANGED while battery is off. " ++ "Ignored.\n"); ++ continue; ++ } ++ /* First report false ring alarms */ ++ debounce = atomic_read(&priv->ring_debounce[i]); ++ if (debounce) ++ LINE_NOTICE(xpd, i, ++ "Ignored a false short ring " ++ "(lasted only %dms)\n", ++ ring_debounce - debounce); ++ /* ++ * Now set a new ring alarm. ++ * It will be checked in handle_fxo_ring() ++ */ ++ debounce = ++ (IS_SET(sig_status, i)) ? ring_debounce : ++ -ring_debounce; ++ atomic_set(&priv->ring_debounce[i], debounce); ++ } ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg) ++{ ++ /* ++ * Inform dahdi/Asterisk: ++ * 1. Maybe used for hangup detection during offhook ++ * 2. In some countries used to report caller-id ++ * during onhook but before first ring. ++ */ ++ if (caller_id_style == CID_STYLE_ETSI_FSK) ++ /* will be cleared on ring/offhook */ ++ oht_pcm(xpd, portno, 1); ++ if (SPAN_REGISTERED(xpd)) { ++ LINE_DBG(SIGNAL, xpd, portno, ++ "%s DAHDI_EVENT_POLARITY (%s)\n", ++ (squelch_polrev) ? "Squelch" : "Send", ++ msg); ++ if (!squelch_polrev) ++ dahdi_qevent_lock(XPD_CHAN(xpd, portno), ++ DAHDI_EVENT_POLARITY); ++ } ++} ++ ++static void update_battery_voltage(xpd_t *xpd, __u8 data_low, ++ xportno_t portno) ++{ ++ struct FXO_priv_data *priv; ++ enum polarity_state pol; ++ int msec; ++ signed char volts = (signed char)data_low; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ priv->battery_voltage[portno] = volts; ++ if (PHONEDEV(xpd).ringing[portno]) ++ goto ignore_reading; /* ring voltage create false alarms */ ++ if (abs(volts) < battery_threshold) { ++ /* ++ * Check for battery voltage fluctuations ++ */ ++ if (priv->battery[portno] != BATTERY_OFF) { ++ int milliseconds; ++ ++ milliseconds = ++ priv->nobattery_debounce[portno]++ * ++ poll_battery_interval; ++ if (milliseconds > battery_debounce) { ++ LINE_DBG(SIGNAL, xpd, portno, ++ "BATTERY OFF voltage=%d\n", volts); ++ priv->battery[portno] = BATTERY_OFF; ++ dahdi_report_battery(xpd, portno); ++ /* What's the polarity ? */ ++ priv->polarity[portno] = POL_UNKNOWN; ++ priv->polarity_debounce[portno] = 0; ++ /* What's the current ? */ ++ power_change(xpd, portno, POWER_UNKNOWN); ++ /* ++ * Stop further processing for now ++ */ ++ goto ignore_reading; ++ } ++ ++ } ++ } else { ++ priv->nobattery_debounce[portno] = 0; ++ if (priv->battery[portno] != BATTERY_ON) { ++ LINE_DBG(SIGNAL, xpd, portno, "BATTERY ON voltage=%d\n", ++ volts); ++ priv->battery[portno] = BATTERY_ON; ++ dahdi_report_battery(xpd, portno); ++ } ++ } ++#if 0 ++ /* ++ * Mark FXO ports without battery! ++ */ ++ if (priv->battery[portno] != BATTERY_ON) ++ MARK_ON(priv, portno, LED_RED); ++ else ++ MARK_OFF(priv, portno, LED_RED); ++#endif ++ if (priv->battery[portno] != BATTERY_ON) { ++ /* What's the polarity ? */ ++ priv->polarity[portno] = POL_UNKNOWN; ++ return; ++ } ++ /* ++ * Handle reverse polarity ++ */ ++ if (volts == 0) ++ pol = POL_UNKNOWN; ++ else if (volts < 0) ++ pol = POL_NEGATIVE; ++ else ++ pol = POL_POSITIVE; ++ if (priv->polarity[portno] == pol) { ++ /* ++ * Same polarity, reset debounce counter ++ */ ++ priv->polarity_debounce[portno] = 0; ++ return; ++ } ++ /* ++ * Track polarity reversals and debounce spikes. ++ * Only reversals with long duration count. ++ */ ++ msec = priv->polarity_debounce[portno]++ * poll_battery_interval; ++ if (msec >= POLREV_THRESHOLD) { ++ priv->polarity_debounce[portno] = 0; ++ if (pol != POL_UNKNOWN && priv->polarity[portno] != POL_UNKNOWN) { ++ char *polname = NULL; ++ ++ if (pol == POL_POSITIVE) ++ polname = "Positive"; ++ else if (pol == POL_NEGATIVE) ++ polname = "Negative"; ++ else ++ BUG(); ++ LINE_DBG(SIGNAL, xpd, portno, ++ "Polarity changed to %s\n", polname); ++ if (!use_polrev_firmware) ++ report_polarity_reversal(xpd, portno, polname); ++ } ++ priv->polarity[portno] = pol; ++ } ++ return; ++ignore_reading: ++ /* ++ * Reset debounce counters to prevent false alarms ++ */ ++ /* unstable during hook changes */ ++ reset_battery_readings(xpd, portno); ++} ++ ++static void update_battery_current(xpd_t *xpd, __u8 data_low, ++ xportno_t portno) ++{ ++ struct FXO_priv_data *priv; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ priv->battery_current[portno] = data_low; ++ /* ++ * During ringing, current is not stable. ++ * During onhook there should not be current anyway. ++ */ ++ if (PHONEDEV(xpd).ringing[portno] || !IS_OFFHOOK(xpd, portno)) ++ goto ignore_it; ++ /* ++ * Power denial with no battery voltage is meaningless ++ */ ++ if (priv->battery[portno] != BATTERY_ON) ++ goto ignore_it; ++ /* Safe zone after offhook */ ++ if (priv->power_denial_safezone[portno] > 0) ++ goto ignore_it; ++ if (data_low < POWER_DENIAL_CURRENT) { ++ if (priv->power[portno] == POWER_ON) { ++ power_change(xpd, portno, POWER_OFF); ++ priv->power_denial_length[portno] = power_denial_minlen; ++ } ++ } else { ++ if (priv->power[portno] != POWER_ON) { ++ power_change(xpd, portno, POWER_ON); ++ priv->power_denial_length[portno] = 0; ++ /* We are now OFFHOOK */ ++ hookstate_changed(xpd, portno, 1); ++ } ++ } ++ return; ++ignore_it: ++ priv->power_denial_delay[portno] = 0; ++} ++ ++#ifdef WITH_METERING ++#define BTD_BIT BIT(0) ++ ++static void update_metering_state(xpd_t *xpd, __u8 data_low, lineno_t portno) ++{ ++ struct FXO_priv_data *priv; ++ bool metering_tone = data_low & BTD_BIT; ++ bool old_metering_tone; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ old_metering_tone = IS_SET(priv->metering_tone_state, portno); ++ LINE_DBG(SIGNAL, xpd, portno, "METERING: %s [dL=0x%X] (%d)\n", ++ (metering_tone) ? "ON" : "OFF", data_low, ++ priv->metering_count[portno]); ++ if (metering_tone && !old_metering_tone) { ++ /* Rising edge */ ++ priv->metering_count[portno]++; ++ BIT_SET(priv->metering_tone_state, portno); ++ } else if (!metering_tone && old_metering_tone) ++ BIT_CLR(priv->metering_tone_state, portno); ++ if (metering_tone) { ++ /* Clear the BTD bit */ ++ data_low &= ~BTD_BIT; ++ DAA_DIRECT_REQUEST(xpd->xbus, xpd, portno, DAA_WRITE, ++ DAA_REG_METERING, data_low); ++ } ++} ++#endif ++ ++static void got_chip_interrupt(xpd_t *xpd, __u8 data_low, ++ xportno_t portno) ++{ ++ struct FXO_priv_data *priv; ++ int t; ++ ++ if (!use_polrev_firmware) ++ return; ++ priv = xpd->priv; ++ LINE_DBG(SIGNAL, xpd, portno, "mask=0x%X\n", data_low); ++ if (!(data_low & REG_INTERRUPT_SRC_POLI)) ++ return; ++ t = priv->polarity_last_interval[portno]; ++ if (PHONEDEV(xpd).ringing[portno]) { ++ priv->polarity_last_interval[portno] = ++ POLARITY_LAST_INTERVAL_NONE; ++ LINE_DBG(SIGNAL, xpd, portno, ++ "polrev(false): %d msec (while ringing)\n", t); ++ } else if (data_low & REG_INTERRUPT_SRC_RING) { ++ priv->polarity_last_interval[portno] = ++ POLARITY_LAST_INTERVAL_NONE; ++ LINE_DBG(SIGNAL, xpd, portno, ++ "polrev(false): %d msec (with chip-interrupt ring)\n", ++ t); ++ } else if (t == POLARITY_LAST_INTERVAL_NONE) { ++ priv->polarity_last_interval[portno] = 0; ++ LINE_DBG(SIGNAL, xpd, portno, ++ "polrev(start)\n"); ++ } else if (t < POLARITY_LAST_INTERVAL_MAX) { ++ /* ++ * Start counting upward from -POLARITY_LAST_INTERVAL_MAX ++ * Until we reach POLARITY_LAST_INTERVAL_NONE. ++ * This way we filter bursts of false reports we get ++ * during ringing. ++ */ ++ priv->polarity_last_interval[portno] = ++ POLARITY_LAST_INTERVAL_NONE - ++ POLARITY_LAST_INTERVAL_MAX; ++ LINE_DBG(SIGNAL, xpd, portno, ++ "polrev(false): %d msec (interval shorter than %d)\n", ++ t, POLARITY_LAST_INTERVAL_MAX); ++ } ++} ++ ++static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) ++{ ++ struct FXO_priv_data *priv; ++ lineno_t portno; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ portno = info->h.portnum; ++ switch (REG_FIELD(info, regnum)) { ++ case REG_INTERRUPT_SRC: ++ got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno); ++ break; ++ case DAA_REG_VBAT: ++ update_battery_voltage(xpd, REG_FIELD(info, data_low), portno); ++ break; ++ case DAA_REG_CURRENT: ++ update_battery_current(xpd, REG_FIELD(info, data_low), portno); ++ break; ++#ifdef WITH_METERING ++ case DAA_REG_METERING: ++ update_metering_state(xpd, REG_FIELD(info, data_low), portno); ++ break; ++#endif ++ } ++ LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n", ++ ((info->h.bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum), ++ REG_FIELD(info, data_low), REG_FIELD(info, data_high)); ++ /* Update /proc info only if reply relate to the last slic read request */ ++ if (REG_FIELD(&xpd->requested_reply, regnum) == ++ REG_FIELD(info, regnum) ++ && REG_FIELD(&xpd->requested_reply, do_subreg) == ++ REG_FIELD(info, do_subreg) ++ && REG_FIELD(&xpd->requested_reply, subreg) == ++ REG_FIELD(info, subreg)) { ++ xpd->last_reply = *info; ++ } ++ return 0; ++} ++ ++static int FXO_card_state(xpd_t *xpd, bool on) ++{ ++ int ret = 0; ++ struct FXO_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ return ret; ++} ++ ++static const struct xops fxo_xops = { ++ .card_new = FXO_card_new, ++ .card_init = FXO_card_init, ++ .card_remove = FXO_card_remove, ++ .card_tick = FXO_card_tick, ++ .card_register_reply = FXO_card_register_reply, ++}; ++ ++static const struct phoneops fxo_phoneops = { ++ .card_dahdi_preregistration = FXO_card_dahdi_preregistration, ++ .card_dahdi_postregistration = FXO_card_dahdi_postregistration, ++ .card_hooksig = FXO_card_hooksig, ++ .card_pcm_recompute = generic_card_pcm_recompute, ++ .card_pcm_fromspan = generic_card_pcm_fromspan, ++ .card_pcm_tospan = generic_card_pcm_tospan, ++ .card_timing_priority = generic_timing_priority, ++ .echocancel_timeslot = generic_echocancel_timeslot, ++ .echocancel_setmask = generic_echocancel_setmask, ++ .card_ioctl = FXO_card_ioctl, ++ .card_open = FXO_card_open, ++ .card_state = FXO_card_state, ++ .span_assigned = FXO_span_assigned, ++}; ++ ++static xproto_table_t PROTO_TABLE(FXO) = { ++ .owner = THIS_MODULE, ++ .entries = { ++ /* Prototable Card Opcode */ ++ XENTRY( FXO, FXO, SIG_CHANGED ), ++ }, ++ .name = "FXO", /* protocol name */ ++ .ports_per_subunit = 8, ++ .type = XPD_TYPE_FXO, ++ .xops = &fxo_xops, ++ .phoneops = &fxo_phoneops, ++ .packet_is_valid = fxo_packet_is_valid, ++ .packet_dump = fxo_packet_dump, ++}; ++ ++static bool fxo_packet_is_valid(xpacket_t *pack) ++{ ++ const xproto_entry_t *xe; ++ ++ //DBG(GENERAL, "\n"); ++ xe = xproto_card_entry(&PROTO_TABLE(FXO), XPACKET_OP(pack)); ++ return xe != NULL; ++} ++ ++static void fxo_packet_dump(const char *msg, xpacket_t *pack) ++{ ++ DBG(GENERAL, "%s\n", msg); ++} ++ ++/*------------------------- DAA Handling --------------------------*/ ++ ++#ifdef CONFIG_PROC_FS ++static int proc_fxo_info_show(struct seq_file *sfile, void *not_used) ++{ ++ unsigned long flags; ++ xpd_t *xpd = sfile->private; ++ struct FXO_priv_data *priv; ++ int i; ++ ++ if (!xpd) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ seq_printf(sfile, "\t%-17s: ", "Channel"); ++ for_each_line(xpd, i) { ++ if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) { ++ seq_printf(sfile, "%4d ", i % 10); ++ } ++ } ++ seq_printf(sfile, "\nLeds:"); ++ seq_printf(sfile, "\n\t%-17s: ", "state"); ++ for_each_line(xpd, i) { ++ if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) { ++ seq_printf(sfile, " %d%d ", ++ IS_SET(priv->ledstate[LED_GREEN], i), ++ IS_SET(priv->ledstate[LED_RED], i)); ++ } ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "blinking"); ++ for_each_line(xpd, i) { ++ if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) { ++ seq_printf(sfile, " %d%d ", ++ IS_BLINKING(priv, i, LED_GREEN), ++ IS_BLINKING(priv, i, LED_RED)); ++ } ++ } ++ seq_printf(sfile, "\nBattery-Data:"); ++ seq_printf(sfile, "\n\t%-17s: ", "voltage"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d ", priv->battery_voltage[i]); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "current"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d ", priv->battery_current[i]); ++ } ++ seq_printf(sfile, "\nBattery:"); ++ seq_printf(sfile, "\n\t%-17s: ", "on"); ++ for_each_line(xpd, i) { ++ char *bat; ++ ++ if (priv->battery[i] == BATTERY_ON) ++ bat = "+"; ++ else if (priv->battery[i] == BATTERY_OFF) ++ bat = "-"; ++ else ++ bat = "."; ++ seq_printf(sfile, "%4s ", bat); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "debounce"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d ", priv->nobattery_debounce[i]); ++ } ++ seq_printf(sfile, "\nPolarity-Reverse:"); ++ seq_printf(sfile, "\n\t%-17s: ", "polarity"); ++ for_each_line(xpd, i) { ++ char *polname; ++ ++ if (priv->polarity[i] == POL_POSITIVE) ++ polname = "+"; ++ else if (priv->polarity[i] == POL_NEGATIVE) ++ polname = "-"; ++ else ++ polname = "."; ++ seq_printf(sfile, "%4s ", polname); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "debounce"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d ", priv->polarity_debounce[i]); ++ } ++ seq_printf(sfile, "\nPower-Denial:"); ++ seq_printf(sfile, "\n\t%-17s: ", "power"); ++ for_each_line(xpd, i) { ++ char *curr; ++ ++ if (priv->power[i] == POWER_ON) ++ curr = "+"; ++ else if (priv->power[i] == POWER_OFF) ++ curr = "-"; ++ else ++ curr = "."; ++ seq_printf(sfile, "%4s ", curr); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "safezone"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d ", priv->power_denial_safezone[i]); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "delay"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d ", priv->power_denial_delay[i]); ++ } ++#ifdef WITH_METERING ++ seq_printf(sfile, "\nMetering:"); ++ seq_printf(sfile, "\n\t%-17s: ", "count"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d ", priv->metering_count[i]); ++ } ++#endif ++ seq_printf(sfile, "\n"); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++static int proc_fxo_info_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_fxo_info_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_fxo_info_ops = { ++ .proc_open = proc_fxo_info_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations proc_fxo_info_ops = { ++ .owner = THIS_MODULE, ++ .open = proc_fxo_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++#ifdef WITH_METERING ++static int proc_xpd_metering_show(struct seq_file *sfile, void *not_used) ++{ ++ unsigned long flags; ++ xpd_t *xpd = sfile->private; ++ struct FXO_priv_data *priv; ++ int i; ++ ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ seq_printf(sfile, "# Chan\tMeter (since last read)\n"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d\t%d\n", i, priv->metering_count[i]); ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ /* Zero meters */ ++ for_each_line(xpd, i) ++ priv->metering_count[i] = 0; ++ return 0; ++} ++ ++static int proc_xpd_metering_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_xpd_metering_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_xpd_metering_ops = { ++ .proc_open = proc_xpd_metering_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations proc_xpd_metering_ops = { ++ .owner = THIS_MODULE, ++ .open = proc_xpd_metering_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++#endif ++#endif ++ ++static DEVICE_ATTR_READER(fxo_battery_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct FXO_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ int i; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ for_each_line(xpd, i) { ++ char bat; ++ ++ if (priv->battery[i] == BATTERY_ON) ++ bat = '+'; ++ else if (priv->battery[i] == BATTERY_OFF) ++ bat = '-'; ++ else ++ bat = '.'; ++ len += sprintf(buf + len, "%c ", bat); ++ } ++ len += sprintf(buf + len, "\n"); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR(fxo_battery, S_IRUGO, fxo_battery_show, NULL); ++ ++static int fxo_xpd_probe(struct device *dev) ++{ ++ xpd_t *xpd; ++ int ret; ++ ++ xpd = dev_to_xpd(dev); ++ /* Is it our device? */ ++ if (xpd->xpd_type != XPD_TYPE_FXO) { ++ XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev), ++ xpd->xpd_type); ++ return -EINVAL; ++ } ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ ret = device_create_file(dev, &dev_attr_fxo_battery); ++ if (ret) { ++ XPD_ERR(xpd, "%s: device_create_file(fxo_battery) failed: %d\n", ++ __func__, ret); ++ goto fail_fxo_battery; ++ } ++ return 0; ++fail_fxo_battery: ++ return ret; ++} ++ ++static int fxo_xpd_remove(struct device *dev) ++{ ++ xpd_t *xpd; ++ ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ device_remove_file(dev, &dev_attr_fxo_battery); ++ return 0; ++} ++ ++static struct xpd_driver fxo_driver = { ++ .xpd_type = XPD_TYPE_FXO, ++ .driver = { ++ .name = "fxo", ++ .owner = THIS_MODULE, ++ .probe = fxo_xpd_probe, ++ .remove = fxo_xpd_remove} ++}; ++ ++static int __init card_fxo_startup(void) ++{ ++ int ret; ++ ++ if (ring_debounce <= 0) { ++ ERR("ring_debounce=%d. Must be positive number of ticks\n", ++ ring_debounce); ++ return -EINVAL; ++ } ++ if ((ret = xpd_driver_register(&fxo_driver.driver)) < 0) ++ return ret; ++#ifdef WITH_METERING ++ INFO("FEATURE: WITH METERING Detection\n"); ++#else ++ INFO("FEATURE: NO METERING Detection\n"); ++#endif ++ xproto_register(&PROTO_TABLE(FXO)); ++ return 0; ++} ++ ++static void __exit card_fxo_cleanup(void) ++{ ++ xproto_unregister(&PROTO_TABLE(FXO)); ++ xpd_driver_unregister(&fxo_driver.driver); ++} ++ ++MODULE_DESCRIPTION("XPP FXO Card Driver"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_XPD(XPD_TYPE_FXO); ++ ++module_init(card_fxo_startup); ++module_exit(card_fxo_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_fxo.h linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxo.h +--- linux-source-4.19/drivers/dahdi/xpp/card_fxo.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxo.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,40 @@ ++#ifndef CARD_FXO_H ++#define CARD_FXO_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++ ++enum fxo_opcodes { ++ XPROTO_NAME(FXO, SIG_CHANGED) = 0x06, /**/ ++ XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */ ++ XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */ ++ XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */ ++}; ++ ++ ++DEF_RPACKET_DATA(FXO, SIG_CHANGED, ++ xpp_line_t sig_status; /* channels: lsb=1, msb=8 */ ++ xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */ ++ ); ++ ++#endif /* CARD_FXO_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_fxs.c linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxs.c +--- linux-source-4.19/drivers/dahdi/xpp/card_fxs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxs.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,2405 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++#include "xproto.h" ++#include "xpp_dahdi.h" ++#include "card_fxs.h" ++#include "dahdi_debug.h" ++#include "xbus-core.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++/* must be before dahdi_debug.h */ ++static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++static DEF_PARM_BOOL(reversepolarity, 0, 0644, "Reverse Line Polarity"); ++static DEF_PARM_BOOL(dtmf_detection, 1, 0644, "Do DTMF detection in hardware"); ++#ifdef POLL_DIGITAL_INPUTS ++static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs"); ++#endif ++static DEF_PARM(uint, poll_chan_linefeed, 30000, 0644, "Poll Channel Linefeed"); ++ ++static DEF_PARM_BOOL(vmwi_ioctl, 1, 0644, ++ "Asterisk support VMWI notification via ioctl"); ++static DEF_PARM_BOOL(ring_trapez, 0, 0664, "Use trapezoid ring type"); ++static DEF_PARM_BOOL(lower_ringing_noise, 0, 0664, ++ "Lower ringing noise (may loose CallerID)"); ++ ++/* Signaling is opposite (fxo signalling for fxs card) */ ++#if 1 ++#define FXS_DEFAULT_SIGCAP \ ++ (DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS) ++#else ++#define FXS_DEFAULT_SIGCAP \ ++ (DAHDI_SIG_SF | DAHDI_SIG_EM) ++#endif ++ ++#define VMWI_TYPE(priv, pos, type) \ ++ ((priv)->vmwisetting[pos].vmwi_type & DAHDI_VMWI_ ## type) ++#define VMWI_NEON(priv, pos) VMWI_TYPE(priv, pos, HVAC) ++ ++#define LINES_DIGI_OUT 2 ++#define LINES_DIGI_INP 4 ++ ++enum fxs_leds { ++ LED_GREEN, ++ LED_RED, ++ OUTPUT_RELAY, ++}; ++ ++#define NUM_LEDS 2 ++ ++/* Shortcuts */ ++#define SLIC_WRITE 1 ++#define SLIC_READ 0 ++#define SLIC_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL) \ ++ xpp_register_request((xbus), (xpd), (port), \ ++ (writing), (reg), 0, 0, (dL), 0, 0, 0, 0) ++#define SLIC_INDIRECT_REQUEST(xbus, xpd, port, writing, reg, dL, dH) \ ++ xpp_register_request((xbus), (xpd), (port), \ ++ (writing), 0x1E, 1, (reg), (dL), 1, (dH), 0, 0) ++#define EXP_REQUEST(xbus, xpd, writing, reg, dL, dH) \ ++ xpp_register_request((xbus), (xpd), 0, \ ++ (writing), (reg), 1, 0, (dL), 1, (dH), 0, 1) ++#define RAM_REQUEST(xbus, xpd, port, writing, addr, data) \ ++ xpp_ram_request((xbus), (xpd), (port), \ ++ (writing), (__u8)(addr), (__u8)((addr) >> 8), (__u8)(data), (__u8)((data) >> 8), (__u8)((data) >> 16), (__u8)((data) >> 24), 0) ++ ++#define VALID_PORT(port) \ ++ (((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST) ++ ++#define REG_TYPE1_DIGITAL_IOCTRL 0x06 /* LED and RELAY control */ ++ ++/* Values of SLIC linefeed control register (0x40) */ ++enum fxs_state { ++ FXS_LINE_OPEN = 0x00, /* Open */ ++ FXS_LINE_ACTIVE = 0x01, /* Forward active */ ++ FXS_LINE_OHTRANS = 0x02, /* Forward on-hook transmission */ ++ FXS_LINE_TIPOPEN = 0x03, /* TIP open */ ++ FXS_LINE_RING = 0x04, /* Ringing */ ++ FXS_LINE_REV_ACTIVE = 0x05, /* Reverse active */ ++ FXS_LINE_REV_OHTRANS = 0x06, /* Reverse on-hook transmission */ ++ FXS_LINE_RING_OPEN = 0x07 /* RING open */ ++}; ++ ++enum neon_state { ++ END_NEON = 0, ++ INIT_NEON = 1, ++}; ++ ++#define FXS_LINE_POL_ACTIVE \ ++ ((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE) ++#define FXS_LINE_POL_OHTRANS \ ++ ((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS) ++ ++/* FXS type 1 registers */ ++#define REG_TYPE1_RINGCON 0x22 /* 34 - Ringing Oscillator Control */ ++ ++/* ++ * DTMF detection ++ */ ++#define REG_TYPE1_DTMF_DECODE 0x18 /* 24 - DTMF Decode Status */ ++#define REG_TYPE1_BATTERY 0x42 /* 66 - Battery Feed Control */ ++#define REG_TYPE1_BATTERY_BATSL BIT(1) /* Battery Feed Select */ ++ ++/* 68 - Loop Closure/Ring Trip Detect Status */ ++#define REG_TYPE1_LOOPCLOSURE 0x44 ++#define REG_TYPE1_LOOPCLOSURE_ZERO 0xF8 /* Loop Closure zero bits. */ ++#define REG_TYPE1_LOOPCLOSURE_LCR BIT(0) /* Loop Closure Detect Indicator. */ ++ ++/* FXS type 6 registers */ ++#define REG_TYPE6_RINGCON 0x26 /* 38 - Ringing Oscillator Control */ ++ ++/* 34 - Loop Closure/Ring Trip Detect Status */ ++#define REG_TYPE6_LCRRTP 0x22 ++#define REG_TYPE6_LCRRTP_ZERO 0xF0 /* Loop Closure zero bits. */ ++#define REG_TYPE6_LCRRTP_LCR BIT(1) /* Loop Closure Detect Indicator. */ ++ ++#define REG_TYPE6_TONEN 0x3E /* 62 - Hardware DTMF detection */ ++#define REG_TYPE6_TONEN_DTMF_DIS BIT(2) /* DTMF Disable */ ++#define REG_TYPE6_LINEFEED 0x1E /* 30 - Linefeed */ ++#define REG_TYPE6_TONDTMF 0x3C /* 60 - DTMF Decode Status */ ++#define REG_TYPE6_EXP_GPIOA 0x12 /* I/O Expander GPIOA */ ++#define REG_TYPE6_EXP_GPIOB 0x13 /* I/O Expander GPIOB */ ++#define REG_TYPE6_ENHANCE 0x2F /* 47 - Enhance */ ++#define REG_TYPE6_USERSTAT 0x42 /* 66 - Userstat */ ++#define REG_TYPE6_DIAG1 0x47 /* 71 - Diag1 */ ++#define RAM_TYPE6_SLOPE_VLIM 634 ++#define SLOPE_VLIM_DFLT 0x1E655196L ++#define SLOPE_VLIM_MWI 0x8000000L ++#define RAM_TYPE6_VBATH_EXPECT 767 ++#define VBATH_EXPECT_DFLT 0x2B10A20L ++#define VBATH_EXPECT_MWI 0x6147AB2L ++ ++/*---------------- FXS Protocol Commands ----------------------------------*/ ++ ++static bool fxs_packet_is_valid(xpacket_t *pack); ++static void fxs_packet_dump(const char *msg, xpacket_t *pack); ++#ifdef CONFIG_PROC_FS ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_fxs_info_ops; ++#else ++static const struct file_operations proc_fxs_info_ops; ++#endif ++#ifdef WITH_METERING ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_xpd_metering_ops; ++#else ++static const struct file_operations proc_xpd_metering_ops; ++#endif ++#endif ++#endif ++static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos); ++ ++#define PROC_FXS_INFO_FNAME "fxs_info" ++#ifdef WITH_METERING ++#define PROC_METERING_FNAME "metering_gen" ++#endif ++ ++struct FXS_priv_data { ++#ifdef WITH_METERING ++ struct proc_dir_entry *meteringfile; ++#endif ++ struct proc_dir_entry *fxs_info; ++ xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ ++ xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ ++ xpp_line_t search_fsk_pattern; ++ xpp_line_t found_fsk_pattern; ++ xpp_line_t update_offhook_state; ++ xpp_line_t want_dtmf_events; /* what dahdi want */ ++ xpp_line_t want_dtmf_mute; /* what dahdi want */ ++ xpp_line_t prev_key_down; /* DTMF down sets the bit */ ++ xpp_line_t neon_blinking; ++ xpp_line_t neonstate; ++ xpp_line_t vbat_h; /* High voltage */ ++ ktime_t prev_key_time[CHANNELS_PERXPD]; ++ int led_counter[NUM_LEDS][CHANNELS_PERXPD]; ++ int overheat_reset_counter[CHANNELS_PERXPD]; ++ int ohttimer[CHANNELS_PERXPD]; ++#define OHT_TIMER 6000 /* How long after RING to retain OHT */ ++ /* IDLE changing hook state */ ++ enum fxs_state idletxhookstate[CHANNELS_PERXPD]; ++ enum fxs_state lasttxhook[CHANNELS_PERXPD]; ++ enum fxs_state polledhook[CHANNELS_PERXPD]; ++ struct dahdi_vmwi_info vmwisetting[CHANNELS_PERXPD]; ++}; ++ ++/* ++ * LED counter values: ++ * n>1 : BLINK every n'th tick ++ */ ++#define LED_COUNTER(priv, pos, color) ((priv)->led_counter[color][pos]) ++#define IS_BLINKING(priv, pos, color) (LED_COUNTER(priv, pos, color) > 0) ++#define MARK_BLINK(priv, pos, color, t) \ ++ ((priv)->led_counter[color][pos] = (t)) ++#define MARK_OFF(priv, pos, color) \ ++ do { \ ++ BIT_CLR((priv)->ledcontrol[color], (pos)); \ ++ MARK_BLINK((priv), (pos), (color), 0); \ ++ } while (0) ++#define MARK_ON(priv, pos, color) \ ++ do { \ ++ BIT_SET((priv)->ledcontrol[color], (pos)); \ ++ MARK_BLINK((priv), (pos), (color), 0); \ ++ } while (0) ++ ++#define LED_BLINK_RING (1000/8) /* in ticks */ ++ ++/*---------------- FXS: Static functions ----------------------------------*/ ++static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, ++ unsigned int msg_waiting); ++ ++static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on) ++{ ++ struct FXS_priv_data *priv; ++ unsigned long *p; ++ int was; ++ ++ BUG_ON(!xbus); ++ BUG_ON(!xpd); ++ if (XPD_HW(xpd).type == 6) { ++ LINE_DBG(SIGNAL, xpd, chan, "is ignored in Si32260\n"); ++ return 0; ++ } ++ priv = xpd->priv; ++ p = (unsigned long *)&priv->vbat_h; ++ if (on) ++ was = test_and_set_bit(chan, p) != 0; ++ else ++ was = test_and_clear_bit(chan, p) != 0; ++ if (was == on) { ++ LINE_DBG(SIGNAL, xpd, chan, ++ "%s (same, ignored)\n", (on) ? "up" : "down"); ++ return 0; ++ } ++ LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down"); ++ return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE1_BATTERY, ++ (on) ? (int)REG_TYPE1_BATTERY_BATSL : 0x00); ++} ++ ++static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, ++ enum fxs_state value) ++{ ++ struct FXS_priv_data *priv; ++ bool want_vbat_h; ++ ++ priv = xpd->priv; ++ /* ++ * Should we drop vbat_h only during actuall ring? ++ * - It would lower the noise caused to other channels by ++ * group ringing ++ * - But it may also stop CallerID from passing through the SLIC ++ */ ++ want_vbat_h = value == FXS_LINE_RING; ++ if (lower_ringing_noise || want_vbat_h) ++ do_chan_power(xbus, xpd, chan, want_vbat_h); ++ LINE_DBG(SIGNAL, xpd, chan, "value=0x%02X\n", value); ++ priv->lasttxhook[chan] = value; ++ if (XPD_HW(xpd).type == 6) { ++ int ret; ++ ++ /* Make sure NEON state is off for */ ++ if (value == FXS_LINE_POL_OHTRANS && IS_SET(priv->neon_blinking, chan)) ++ set_vm_led_mode(xpd->xbus, xpd, chan, 0); ++ ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE6_LINEFEED, value); ++ if (value == FXS_LINE_POL_ACTIVE && PHONEDEV(xpd).msg_waiting[chan]) ++ set_vm_led_mode(xpd->xbus, xpd, chan, PHONEDEV(xpd).msg_waiting[chan]); ++ return ret; ++ } else { ++ return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value); ++ } ++ return 0; ++} ++ ++static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on) ++{ ++ struct FXS_priv_data *priv; ++ ++ priv = xpd->priv; ++ BUG_ON(!xpd); ++ if (VMWI_NEON(priv, pos) && on) { ++ LINE_DBG(SIGNAL, xpd, pos, "START\n"); ++ BIT_SET(priv->search_fsk_pattern, pos); ++ } else { ++ LINE_DBG(SIGNAL, xpd, pos, "STOP\n"); ++ BIT_CLR(priv->search_fsk_pattern, pos); ++ } ++} ++ ++/* ++ * LED and RELAY control is done via SLIC register 0x06: ++ * 7 6 5 4 3 2 1 0 ++ * +-----+-----+-----+-----+-----+-----+-----+-----+ ++ * | M2 | M1 | M3 | C2 | O1 | O3 | C1 | C3 | ++ * +-----+-----+-----+-----+-----+-----+-----+-----+ ++ * ++ * Cn - Control bit (control one digital line) ++ * On - Output bit (program a digital line for output) ++ * Mn - Mask bit (only the matching output control bit is affected) ++ * ++ * C3 - OUTPUT RELAY (0 - OFF, 1 - ON) ++ * C1 - GREEN LED (0 - OFF, 1 - ON) ++ * O3 - Output RELAY (this line is output) ++ * O1 - Output GREEN (this line is output) ++ * C2 - RED LED (0 - OFF, 1 - ON) ++ * M3 - Mask RELAY. (1 - C3 effect the OUTPUT RELAY) ++ * M2 - Mask RED. (1 - C2 effect the RED LED) ++ * M1 - Mask GREEN. (1 - C1 effect the GREEN LED) ++ * ++ * The OUTPUT RELAY (actually a relay out) is connected to line 0 and 4 only. ++ */ ++ ++// GREEN RED OUTPUT RELAY ++static const int led_register_mask[] = { BIT(7), BIT(6), BIT(5) }; ++static const int led_register_vals[] = { BIT(4), BIT(1), BIT(0) }; ++ ++/* ++ * pos can be: ++ * - A line number ++ * - ALL_LINES. This is not valid anymore since 8-Jan-2007. ++ */ ++static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on) ++{ ++ int ret = 0; ++ struct FXS_priv_data *priv; ++ int value; ++ xbus_t *xbus; ++ ++ BUG_ON(!xpd); ++ BUG_ON(chan == ALL_LINES); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ which = which % NUM_LEDS; ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, chan) ++ || IS_SET(PHONEDEV(xpd).digital_inputs, chan)) ++ goto out; ++ if (chan == PORT_BROADCAST) { ++ priv->ledstate[which] = (on) ? ~0 : 0; ++ } else { ++ if (on) ++ BIT_SET(priv->ledstate[which], chan); ++ else ++ BIT_CLR(priv->ledstate[which], chan); ++ } ++ LINE_DBG(LEDS, xpd, chan, "LED: (type=%d) which=%d -- %s\n", XPD_HW(xpd).type, which, ++ (on) ? "on" : "off"); ++ if (XPD_HW(xpd).type == 6) { ++ int mask = 1 << chan; ++ value = (on) << chan; ++ XPD_DBG(LEDS, xpd, "LED(%d): 0x%0X (mask: 0x%0X)\n", chan, ++ value, mask); ++ if (which == LED_GREEN) { /* other leds ignored */ ++ ret = EXP_REQUEST(xbus, xpd, SLIC_WRITE, ++ REG_TYPE6_EXP_GPIOA, value, mask); ++ } ++ } else { ++ value = BIT(2) | BIT(3); ++ value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]); ++ if (on) ++ value |= led_register_vals[which]; ++ ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, ++ REG_TYPE1_DIGITAL_IOCTRL, value); ++ } ++ return 0; ++out: ++ return ret; ++} ++ ++static inline void set_mwi_led(xpd_t *xpd, int pos, int on) ++{ ++ struct FXS_priv_data *priv; ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ ++ if (XPD_HW(xpd).type != 6) ++ return; ++ if (on) { ++ if (! IS_SET(priv->neonstate, pos)) { ++ SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x00); ++ SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x04); ++ SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x0F); ++ BIT_SET(priv->neonstate, pos); ++ } ++ } else { ++ if (IS_SET(priv->neonstate, pos)) { ++ SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x00); ++ BIT_CLR(priv->neonstate, pos); ++ } ++ } ++} ++ ++static void blink_mwi(xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ unsigned int timer_count; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ timer_count = xpd->timer_count; ++ for_each_line(xpd, i) { ++ unsigned int msgs = PHONEDEV(xpd).msg_waiting[i]; ++ /* LED duty cycle: 300ms on, 700ms off */ ++ unsigned int in_range = (timer_count % 1000) >= 0 && (timer_count % 1000) <= 300; ++ ++ if (!IS_OFFHOOK(xpd, i) && msgs && in_range && ++ IS_SET(priv->neon_blinking,i) && priv->ohttimer[i] == 0) ++ set_mwi_led(xpd, i, 1); ++ else ++ set_mwi_led(xpd, i, 0); ++ } ++} ++ ++static void handle_fxs_leds(xpd_t *xpd) ++{ ++ int i; ++ const enum fxs_leds colors[] = { LED_GREEN, LED_RED }; ++ enum fxs_leds color; ++ unsigned int timer_count; ++ struct FXS_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ timer_count = xpd->timer_count; ++ for (color = 0; color < ARRAY_SIZE(colors); color++) { ++ for_each_line(xpd, i) { ++ if (IS_SET ++ (PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd). ++ digital_inputs, i)) ++ continue; ++ /* Blinking? */ ++ if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { ++ int mod_value = LED_COUNTER(priv, i, color); ++ ++ if (!mod_value) ++ /* safety value */ ++ mod_value = DEFAULT_LED_PERIOD; ++ /* led state is toggled */ ++ if ((timer_count % mod_value) == 0) { ++ LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", ++ (IS_SET ++ (priv->ledstate[color], ++ i)) ? "ON" : "OFF"); ++ if (!IS_SET(priv->ledstate[color], i)) ++ do_led(xpd, i, color, 1); ++ else ++ do_led(xpd, i, color, 0); ++ } ++ } else ++ if (IS_SET ++ (priv->ledcontrol[color] & ~priv-> ++ ledstate[color], i)) { ++ do_led(xpd, i, color, 1); ++ } else ++ if (IS_SET ++ (~priv->ledcontrol[color] & priv-> ++ ledstate[color], i)) { ++ do_led(xpd, i, color, 0); ++ } ++ ++ } ++ } ++} ++ ++static void restore_leds(xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ int i; ++ ++ priv = xpd->priv; ++ for_each_line(xpd, i) { ++ if (IS_OFFHOOK(xpd, i)) ++ MARK_ON(priv, i, LED_GREEN); ++ else ++ MARK_OFF(priv, i, LED_GREEN); ++ } ++} ++ ++#ifdef WITH_METERING ++static int metering_gen(xpd_t *xpd, lineno_t chan, bool on) ++{ ++ __u8 value = (on) ? 0x94 : 0x00; ++ ++ if (XPD_HW(xpd).type == 6) { ++ XBUS_NOTICE("Metering not supported with FXS type 6"); ++ return 0; ++ } ++ LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n", ++ (on) ? "ON" : "OFF"); ++ return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23, ++ value); ++} ++#endif ++ ++/*---------------- FXS: Methods -------------------------------------------*/ ++ ++static void fxs_proc_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++#ifdef CONFIG_PROC_FS ++#ifdef WITH_METERING ++ if (priv->meteringfile) { ++ XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); ++ remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); ++ priv->meteringfile = NULL; ++ } ++#endif ++ if (priv->fxs_info) { ++ XPD_DBG(PROC, xpd, "Removing xpd FXS_INFO file\n"); ++ remove_proc_entry(PROC_FXS_INFO_FNAME, xpd->proc_xpd_dir); ++ priv->fxs_info = NULL; ++ } ++#endif ++} ++ ++static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ ++#ifdef CONFIG_PROC_FS ++ XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n"); ++ priv->fxs_info = proc_create_data(PROC_FXS_INFO_FNAME, 0444, ++ xpd->proc_xpd_dir, ++ &proc_fxs_info_ops, xpd); ++ if (!priv->fxs_info) { ++ XPD_ERR(xpd, "Failed to create proc file '%s'\n", ++ PROC_FXS_INFO_FNAME); ++ fxs_proc_remove(xbus, xpd); ++ return -EINVAL; ++ } ++ SET_PROC_DIRENTRY_OWNER(priv->fxs_info); ++#ifdef WITH_METERING ++ XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); ++ priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0200, ++ xpd->proc_xpd_dir, ++ &proc_xpd_metering_ops, xpd); ++ if (!priv->meteringfile) { ++ XPD_ERR(xpd, "Failed to create proc file '%s'\n", ++ PROC_METERING_FNAME); ++ fxs_proc_remove(xbus, xpd); ++ return -EINVAL; ++ } ++#endif ++#endif ++ return 0; ++} ++ ++static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, ++ const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ bool to_phone) ++{ ++ xpd_t *xpd = NULL; ++ int channels; ++ int subunit_ports; ++ int regular_channels; ++ struct FXS_priv_data *priv; ++ int i; ++ int d_inputs = 0; ++ int d_outputs = 0; ++ ++ if (!to_phone) { ++ XBUS_NOTICE(xbus, ++ "XPD=%d%d: try to instanciate FXS with reverse direction\n", ++ unit, subunit); ++ return NULL; ++ } ++ subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip; ++ if (unit_descriptor->subtype == 2) ++ regular_channels = min(6, subunit_ports); ++ else ++ regular_channels = min(8, subunit_ports); ++ channels = regular_channels; ++ /* Calculate digital inputs/outputs */ ++ if (unit == 0 && unit_descriptor->subtype != 4 && unit_descriptor->numchips != 4) { ++ channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */ ++ d_inputs = LINES_DIGI_INP; ++ d_outputs = LINES_DIGI_OUT; ++ } ++ xpd = ++ xpd_alloc(xbus, unit, subunit, ++ sizeof(struct FXS_priv_data), proto_table, unit_descriptor, channels); ++ if (!xpd) ++ return NULL; ++ /* Initialize digital inputs/outputs */ ++ if (d_inputs) { ++ XBUS_DBG(GENERAL, xbus, "Initialize %d digital inputs\n", ++ d_inputs); ++ PHONEDEV(xpd).digital_inputs = ++ BITMASK(d_inputs) << (regular_channels + d_outputs); ++ } else ++ XBUS_DBG(GENERAL, xbus, "No digital inputs\n"); ++ if (d_outputs) { ++ XBUS_DBG(GENERAL, xbus, "Initialize %d digital outputs\n", ++ d_outputs); ++ PHONEDEV(xpd).digital_outputs = ++ BITMASK(d_outputs) << regular_channels; ++ } else ++ XBUS_DBG(GENERAL, xbus, "No digital outputs\n"); ++ PHONEDEV(xpd).direction = TO_PHONE; ++ xpd->type_name = "FXS"; ++ if (fxs_proc_create(xbus, xpd) < 0) ++ goto err; ++ priv = xpd->priv; ++ for_each_line(xpd, i) { ++ priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE; ++ } ++ return xpd; ++err: ++ xpd_free(xpd); ++ return NULL; ++} ++ ++static int FXS_card_init(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ int ret = 0; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ /* ++ * Setup ring timers ++ */ ++ /* Software controled ringing (for CID) */ ++ /* Ringing Oscilator Control */ ++ if (XPD_HW(xpd).type == 6) { ++ ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE, ++ REG_TYPE6_RINGCON, 0x00); ++ } else { ++ ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE, ++ REG_TYPE1_RINGCON, 0x00); ++ } ++ if (ret < 0) ++ goto err; ++ for_each_line(xpd, i) { ++ if (XPD_HW(xpd).type == 6) ++ /* An arbitrary value that is not FXS_LINE_OPEN */ ++ priv->polledhook[i] = FXS_LINE_ACTIVE; ++ linefeed_control(xbus, xpd, i, FXS_LINE_POL_ACTIVE); ++ } ++ XPD_DBG(GENERAL, xpd, "done\n"); ++ for_each_line(xpd, i) { ++ do_led(xpd, i, LED_GREEN, 0); ++ do_led(xpd, i, LED_RED, 0); ++ } ++ for_each_line(xpd, i) { ++ do_led(xpd, i, LED_GREEN, 1); ++ msleep(50); ++ } ++ for_each_line(xpd, i) { ++ do_led(xpd, i, LED_GREEN, 0); ++ msleep(50); ++ } ++ restore_leds(xpd); ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ /* ++ * We should query our offhook state long enough time after we ++ * set the linefeed_control() ++ * So we do this after the LEDs ++ */ ++ for_each_line(xpd, i) { ++ if (IS_SET ++ (PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd). ++ digital_inputs, i)) ++ continue; ++ if (XPD_HW(xpd).type == 6) { ++ SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE6_LCRRTP, ++ 0); ++ } else { ++ SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE1_LOOPCLOSURE, ++ 0); ++ } ++ } ++ return 0; ++err: ++ fxs_proc_remove(xbus, xpd); ++ XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); ++ return ret; ++} ++ ++static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ fxs_proc_remove(xbus, xpd); ++ return 0; ++} ++ ++static int FXS_card_dahdi_preregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ struct FXS_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ PHONEDEV(xpd).span.spantype = SPANTYPE_ANALOG_FXS; ++ for_each_line(xpd, i) { ++ struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i); ++ ++ XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i); ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, i)) { ++ snprintf(cur_chan->name, MAX_CHANNAME, ++ "XPP_OUT/%02d/%1d%1d/%d", xbus->num, ++ xpd->addr.unit, xpd->addr.subunit, i); ++ } else if (IS_SET(PHONEDEV(xpd).digital_inputs, i)) { ++ snprintf(cur_chan->name, MAX_CHANNAME, ++ "XPP_IN/%02d/%1d%1d/%d", xbus->num, ++ xpd->addr.unit, xpd->addr.subunit, i); ++ } else { ++ snprintf(cur_chan->name, MAX_CHANNAME, ++ "XPP_FXS/%02d/%1d%1d/%d", xbus->num, ++ xpd->addr.unit, xpd->addr.subunit, i); ++ } ++ cur_chan->chanpos = i + 1; ++ cur_chan->pvt = xpd; ++ cur_chan->sigcap = FXS_DEFAULT_SIGCAP; ++ if (!vmwi_ioctl) { ++ /* Old asterisk, assume default VMWI type */ ++ priv->vmwisetting[i].vmwi_type = DAHDI_VMWI_HVAC; ++ } ++ } ++ for_each_line(xpd, i) { ++ MARK_ON(priv, i, LED_GREEN); ++ msleep(4); ++ MARK_ON(priv, i, LED_RED); ++ } ++ return 0; ++} ++ ++static int FXS_card_dahdi_postregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ struct FXS_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ for_each_line(xpd, i) { ++ MARK_OFF(priv, i, LED_GREEN); ++ msleep(2); ++ MARK_OFF(priv, i, LED_RED); ++ msleep(2); ++ } ++ restore_leds(xpd); ++ return 0; ++} ++ ++/* ++ * Called with XPD spinlocked ++ */ ++static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit) ++{ ++ struct FXS_priv_data *priv; ++ ++ priv = xpd->priv; ++ LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE"); ++ if (muteit) ++ BIT_SET(PHONEDEV(xpd).mute_dtmf, pos); ++ else ++ BIT_CLR(PHONEDEV(xpd).mute_dtmf, pos); ++ /* already spinlocked */ ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, priv->search_fsk_pattern); ++} ++ ++struct ring_reg_param { ++ int is_indirect; ++ int regno; ++ uint8_t h_val; ++ uint8_t l_val; ++}; ++ ++enum ring_types { ++ RING_TYPE_NEON = 0, ++ RING_TYPE_TRAPEZ, ++ RING_TYPE_NORMAL, ++}; ++ ++struct byte_pair { ++ uint8_t h_val; ++ uint8_t l_val; ++}; ++ ++struct ring_reg_params { ++ const int is_indirect; ++ const int regno; ++ struct byte_pair values[1 + RING_TYPE_NORMAL - RING_TYPE_NEON]; ++}; ++ ++#define REG_ENTRY(di, reg, vh1, vl1, vh2, vl2, vh3, vl3) \ ++ { (di), (reg), .values = { \ ++ [RING_TYPE_NEON] = { .h_val = (vh1), .l_val = (vl1) }, \ ++ [RING_TYPE_TRAPEZ] = { .h_val = (vh2), .l_val = (vl2) }, \ ++ [RING_TYPE_NORMAL] = { .h_val = (vh3), .l_val = (vl3) }, \ ++ }, \ ++ } ++ ++static struct ring_reg_params ring_parameters[] = { ++ /* INDIR REG NEON TRAPEZ NORMAL */ ++ REG_ENTRY(1, 0x16, 0xE8, 0x03, 0xC8, 0x00, 0x00, 0x00), ++ REG_ENTRY(1, 0x15, 0xEF, 0x7B, 0xAB, 0x5E, 0x77, 0x01), ++ REG_ENTRY(1, 0x14, 0x9F, 0x00, 0x8C, 0x01, 0xFD, 0x7E), ++ ++ REG_ENTRY(0, 0x22, 0x00, 0x19, 0x00, 0x01, 0x00, 0x00), ++ ++ REG_ENTRY(0, 0x30, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00), ++ REG_ENTRY(0, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00), ++ REG_ENTRY(0, 0x32, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00), ++ REG_ENTRY(0, 0x33, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00), ++ ++ REG_ENTRY(1, 0x1D, 0x00, 0x46, 0x00, 0x36, 0x00, 0x36), ++}; ++ ++static void set_neon_state(xbus_t *xbus, xpd_t *xpd, int pos, ++ enum neon_state ns) ++{ ++ struct FXS_priv_data *priv; ++ ++ LINE_DBG(SIGNAL, xpd, pos, "set NEON -> %d\n", ns); ++ priv = xpd->priv; ++ if (ns == INIT_NEON) ++ BIT_SET(priv->neon_blinking, pos); ++ else ++ BIT_CLR(priv->neon_blinking, pos); ++ if (XPD_HW(xpd).type == 6) { ++ switch (ns) { ++ case INIT_NEON: ++ RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_MWI << 3); ++ //RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_MWI << 3); ++ break; ++ default: ++ LINE_DBG(REGS, xpd, pos, "0x%04X: R 0x\n", RAM_TYPE6_SLOPE_VLIM); ++ set_mwi_led(xpd, pos, 0); /* Cannot have NEON LED during OHT (type == 6) */ ++ SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x00); ++ SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x10); ++ RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_DFLT << 3); ++ RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_DFLT << 3); ++ break; ++ } ++ } ++} ++static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos, ++ enum ring_types rtype) ++{ ++ const struct ring_reg_params *p; ++ const struct byte_pair *v; ++ int ret = 0; ++ int i; ++ ++ if (XPD_HW(xpd).type == 6) ++ return 0; ++ if (rtype < RING_TYPE_NEON || rtype > RING_TYPE_NORMAL) ++ return -EINVAL; ++ for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) { ++ p = &ring_parameters[i]; ++ v = &(p->values[rtype]); ++ if (p->is_indirect) { ++ LINE_DBG(REGS, xpd, pos, ++ "[%d] 0x%02X: I 0x%02X 0x%02X\n", ++ i, p->regno, v->h_val, v->l_val); ++ ret = SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, ++ p->regno, v->h_val, v->l_val); ++ if (ret < 0) { ++ LINE_ERR(xpd, pos, ++ "Failed: 0x%02X: I 0x%02X, 0x%02X\n", ++ p->regno, v->h_val, v->l_val); ++ break; ++ } ++ } else { ++ LINE_DBG(REGS, xpd, pos, "[%d] 0x%02X: D 0x%02X\n", ++ i, p->regno, v->l_val); ++ ret = SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, ++ p->regno, v->l_val); ++ if (ret < 0) { ++ LINE_ERR(xpd, pos, ++ "Failed: 0x%02X: D 0x%02X\n", ++ p->regno, v->l_val); ++ break; ++ } ++ } ++ } ++ return ret; ++} ++ ++static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, ++ unsigned int msg_waiting) ++{ ++ int ret = 0; ++ struct FXS_priv_data *priv; ++ BUG_ON(!xbus); ++ BUG_ON(!xpd); ++ ++ priv = xpd->priv; ++ if (VMWI_NEON(priv, pos) && msg_waiting) { ++ /* A write to register 0x40 will now turn on/off the VM led */ ++ LINE_DBG(SIGNAL, xpd, pos, "NEON\n"); ++ set_neon_state(xbus, xpd, pos, INIT_NEON); ++ ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NEON); ++ } else if (ring_trapez) { ++ LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n"); ++ set_neon_state(xbus, xpd, pos, END_NEON); ++ ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_TRAPEZ); ++ } else { ++ /* A write to register 0x40 will now turn on/off the ringer */ ++ LINE_DBG(SIGNAL, xpd, pos, "RINGER\n"); ++ set_neon_state(xbus, xpd, pos, END_NEON); ++ ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NORMAL); ++ } ++ return (ret ? -EPROTO : 0); ++} ++ ++static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos) ++{ ++ struct FXS_priv_data *priv; ++ unsigned int msgs; ++ ++ BUG_ON(!xpd); ++ if (IS_SET ++ (PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, pos)) ++ return; ++ priv = xpd->priv; ++ msgs = PHONEDEV(xpd).msg_waiting[pos]; ++ LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF"); ++ set_vm_led_mode(xbus, xpd, pos, msgs); ++ if (XPD_HW(xpd).type == 1) { ++ do_chan_power(xbus, xpd, pos, msgs > 0); ++ linefeed_control(xbus, xpd, pos, ++ (msgs > 0) ? FXS_LINE_RING : priv->idletxhookstate[pos]); ++ } ++} ++ ++static int relay_out(xpd_t *xpd, int pos, bool on) ++{ ++ int ret = 0; ++ int value = 0; ++ int which = pos; ++ ++ BUG_ON(!xpd); ++ /* map logical position to output port number (0/1) */ ++ which -= (XPD_HW(xpd).subtype == 2) ? 6 : 8; ++ LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which, ++ (on) ? "on" : "off"); ++ if (XPD_HW(xpd).type == 6) { ++ int relay_values_type6[] = { 0x01, 0x40 }; ++ which = which % ARRAY_SIZE(relay_values_type6); ++ if (on) ++ value |= relay_values_type6[which]; ++ ret = EXP_REQUEST(xpd->xbus, xpd, SLIC_WRITE, ++ REG_TYPE6_EXP_GPIOB, value, relay_values_type6[which]); ++ } else { ++ int relay_channels_type1[] = { 0, 4 }; ++ which = which % ARRAY_SIZE(relay_channels_type1); ++ value = BIT(2) | BIT(3); ++ value |= ++ ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]); ++ if (on) ++ value |= led_register_vals[OUTPUT_RELAY]; ++ ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels_type1[which], ++ SLIC_WRITE, REG_TYPE1_DIGITAL_IOCTRL, value); ++ } ++ return ret; ++} ++ ++static int send_ring(xpd_t *xpd, lineno_t chan, bool on) ++{ ++ int ret = 0; ++ xbus_t *xbus; ++ struct FXS_priv_data *priv; ++ enum fxs_state value = (on) ? FXS_LINE_RING : FXS_LINE_POL_ACTIVE; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "on" : "off"); ++ priv = xpd->priv; ++ set_vm_led_mode(xbus, xpd, chan, 0); ++ do_chan_power(xbus, xpd, chan, on); /* Power up (for ring) */ ++ ret = linefeed_control(xbus, xpd, chan, value); ++ if (on) { ++ MARK_BLINK(priv, chan, LED_GREEN, LED_BLINK_RING); ++ } else { ++ if (IS_BLINKING(priv, chan, LED_GREEN)) ++ MARK_BLINK(priv, chan, LED_GREEN, 0); ++ } ++ return ret; ++} ++ ++static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig) ++{ ++ struct FXS_priv_data *priv; ++ int ret = 0; ++ struct dahdi_chan *chan = NULL; ++ enum fxs_state txhook; ++ unsigned long flags; ++ ++ LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); ++ priv = xpd->priv; ++ BUG_ON(PHONEDEV(xpd).direction != TO_PHONE); ++ if (IS_SET(PHONEDEV(xpd).digital_inputs, pos)) { ++ LINE_DBG(SIGNAL, xpd, pos, ++ "Ignoring signal sent to digital input line\n"); ++ return 0; ++ } ++ if (SPAN_REGISTERED(xpd)) ++ chan = XPD_CHAN(xpd, pos); ++ switch (txsig) { ++ case DAHDI_TXSIG_ONHOOK: ++ spin_lock_irqsave(&xpd->lock, flags); ++ PHONEDEV(xpd).ringing[pos] = 0; ++ oht_pcm(xpd, pos, 0); ++ vmwi_search(xpd, pos, 0); ++ BIT_CLR(priv->want_dtmf_events, pos); ++ BIT_CLR(priv->want_dtmf_mute, pos); ++ __do_mute_dtmf(xpd, pos, 0); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) { ++ LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output OFF\n", ++ txsig2str(txsig)); ++ ret = relay_out(xpd, pos, 0); ++ return ret; ++ } ++ if (priv->lasttxhook[pos] == FXS_LINE_OPEN) { ++ /* ++ * Restore state after KEWL hangup. ++ */ ++ LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n"); ++ linefeed_control(xpd->xbus, xpd, pos, ++ FXS_LINE_POL_ACTIVE); ++ if (IS_OFFHOOK(xpd, pos)) ++ MARK_ON(priv, pos, LED_GREEN); ++ } ++ ret = send_ring(xpd, pos, 0); // RING off ++ if (!IS_OFFHOOK(xpd, pos)) ++ start_stop_vm_led(xpd->xbus, xpd, pos); ++ txhook = priv->lasttxhook[pos]; ++ if (chan) { ++ switch (chan->sig) { ++ case DAHDI_SIG_EM: ++ case DAHDI_SIG_FXOKS: ++ case DAHDI_SIG_FXOLS: ++ txhook = priv->idletxhookstate[pos]; ++ break; ++ case DAHDI_SIG_FXOGS: ++ txhook = FXS_LINE_TIPOPEN; ++ break; ++ } ++ } ++ ret = linefeed_control(xpd->xbus, xpd, pos, txhook); ++ break; ++ case DAHDI_TXSIG_OFFHOOK: ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) { ++ LINE_NOTICE(xpd, pos, ++ "%s -> Is digital output. Ignored\n", ++ txsig2str(txsig)); ++ return -EINVAL; ++ } ++ txhook = priv->lasttxhook[pos]; ++ if (PHONEDEV(xpd).ringing[pos]) { ++ oht_pcm(xpd, pos, 1); ++ txhook = FXS_LINE_OHTRANS; ++ } ++ PHONEDEV(xpd).ringing[pos] = 0; ++ if (chan) { ++ switch (chan->sig) { ++ case DAHDI_SIG_EM: ++ txhook = FXS_LINE_POL_ACTIVE; ++ break; ++ default: ++ txhook = priv->idletxhookstate[pos]; ++ break; ++ } ++ } ++ ret = linefeed_control(xpd->xbus, xpd, pos, txhook); ++ break; ++ case DAHDI_TXSIG_START: ++ PHONEDEV(xpd).ringing[pos] = 1; ++ oht_pcm(xpd, pos, 0); ++ vmwi_search(xpd, pos, 0); ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) { ++ LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output ON\n", ++ txsig2str(txsig)); ++ ret = relay_out(xpd, pos, 1); ++ return ret; ++ } ++ ret = send_ring(xpd, pos, 1); // RING on ++ break; ++ case DAHDI_TXSIG_KEWL: ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) { ++ LINE_DBG(SIGNAL, xpd, pos, ++ "%s -> Is digital output. Ignored\n", ++ txsig2str(txsig)); ++ return -EINVAL; ++ } ++ linefeed_control(xpd->xbus, xpd, pos, FXS_LINE_OPEN); ++ MARK_OFF(priv, pos, LED_GREEN); ++ break; ++ default: ++ XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n", __func__, ++ txsig2str(txsig), txsig); ++ ret = -EINVAL; ++ } ++ return ret; ++} ++ ++static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg) ++{ ++ struct FXS_priv_data *priv; ++ struct dahdi_vmwi_info vmwisetting; ++ const int vmwi_flags = ++ DAHDI_VMWI_LREV | DAHDI_VMWI_HVDC | DAHDI_VMWI_HVAC; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (copy_from_user ++ (&vmwisetting, (__user void *)arg, sizeof(vmwisetting))) ++ return -EFAULT; ++ if ((vmwisetting.vmwi_type & ~vmwi_flags) != 0) { ++ LINE_NOTICE(xpd, pos, "Bad DAHDI_VMWI_CONFIG: 0x%X\n", ++ vmwisetting.vmwi_type); ++ return -EINVAL; ++ } ++ LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI_CONFIG: 0x%X\n", ++ vmwisetting.vmwi_type); ++ if (VMWI_TYPE(priv, pos, LREV)) { ++ LINE_NOTICE(xpd, pos, ++ "%s: VMWI(lrev) is not implemented yet. Ignored.\n", ++ __func__); ++ } ++ if (VMWI_TYPE(priv, pos, HVDC)) { ++ LINE_NOTICE(xpd, pos, ++ "%s: VMWI(hvdc) is not implemented yet. Ignored.\n", ++ __func__); ++ } ++ if (VMWI_TYPE(priv, pos, HVAC)) ++ ; /* VMWI_NEON */ ++ if (priv->vmwisetting[pos].vmwi_type == 0) ++ ; /* Disable VMWI */ ++ priv->vmwisetting[pos] = vmwisetting; ++ set_vm_led_mode(xpd->xbus, xpd, pos, PHONEDEV(xpd).msg_waiting[pos]); ++ return 0; ++} ++ ++static int hardware_dtmf_control(xpd_t *xpd, int pos, bool on) ++{ ++ int ret = 0; ++ ++ LINE_DBG(SIGNAL, xpd, pos, "%s: %s\n", __func__, (on) ? "on" : "off"); ++ if (XPD_HW(xpd).type == 6) { ++ int value = (on) ? 0xE0 : REG_TYPE6_TONEN_DTMF_DIS; ++ ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, ++ REG_TYPE6_TONEN, value); ++ } else { ++ ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, 0x17, on); ++ } ++ return ret; ++} ++ ++/* ++ * Private ioctl() ++ * We don't need it now, since we detect vmwi via FSK patterns ++ */ ++static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct FXS_priv_data *priv; ++ xbus_t *xbus; ++ int val; ++ unsigned long flags; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ if (!XBUS_IS(xbus, READY)) ++ return -ENODEV; ++ if (pos < 0 || pos >= PHONEDEV(xpd).channels) { ++ XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n", pos, ++ __func__, cmd); ++ return -EINVAL; ++ } ++ ++ switch (cmd) { ++ case DAHDI_ONHOOKTRANSFER: ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++ LINE_DBG(SIGNAL, xpd, pos, "DAHDI_ONHOOKTRANSFER (%d millis)\n", ++ val); ++ if (IS_SET ++ (PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd). ++ digital_outputs, pos)) ++ return 0; /* Nothing to do */ ++ oht_pcm(xpd, pos, 1); /* Get ready of VMWI FSK tones */ ++ if (priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE ++ || IS_SET(priv->neon_blinking, pos)) { ++ priv->ohttimer[pos] = val; ++ priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS; ++ vmwi_search(xpd, pos, 1); ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, ++ priv->search_fsk_pattern); ++ LINE_DBG(SIGNAL, xpd, pos, ++ "Start OHT_TIMER. wanted_pcm_mask=0x%X\n", ++ PHONEDEV(xpd).wanted_pcm_mask); ++ } ++ if (VMWI_NEON(priv, pos) && !IS_OFFHOOK(xpd, pos)) ++ start_stop_vm_led(xbus, xpd, pos); ++ return 0; ++ case DAHDI_TONEDETECT: ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++ LINE_DBG(SIGNAL, xpd, pos, ++ "DAHDI_TONEDETECT: %s %s (dtmf_detection=%s)\n", ++ (val & DAHDI_TONEDETECT_ON) ? "ON" : "OFF", ++ (val & DAHDI_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE", ++ (dtmf_detection ? "YES" : "NO")); ++ if (!dtmf_detection) { ++ spin_lock_irqsave(&xpd->lock, flags); ++ if (IS_SET(priv->want_dtmf_events, pos)) { ++ /* ++ * Detection mode changed: ++ * Disable DTMF interrupts ++ */ ++ } ++ hardware_dtmf_control(xpd, pos, 0); ++ BIT_CLR(priv->want_dtmf_events, pos); ++ BIT_CLR(priv->want_dtmf_mute, pos); ++ __do_mute_dtmf(xpd, pos, 0); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return -ENOTTY; ++ } ++ /* ++ * During natively bridged calls, Asterisk ++ * will request one of the sides to stop sending ++ * dtmf events. Check the requested state. ++ */ ++ spin_lock_irqsave(&xpd->lock, flags); ++ if (val & DAHDI_TONEDETECT_ON) { ++ if (!IS_SET(priv->want_dtmf_events, pos)) { ++ /* ++ * Detection mode changed: ++ * Enable DTMF interrupts ++ */ ++ LINE_DBG(SIGNAL, xpd, pos, ++ "DAHDI_TONEDETECT: " ++ "Enable Hardware DTMF\n"); ++ hardware_dtmf_control(xpd, pos, 1); ++ } ++ BIT_SET(priv->want_dtmf_events, pos); ++ } else { ++ if (IS_SET(priv->want_dtmf_events, pos)) { ++ /* ++ * Detection mode changed: ++ * Disable DTMF interrupts ++ */ ++ LINE_DBG(SIGNAL, xpd, pos, ++ "DAHDI_TONEDETECT: " ++ "Disable Hardware DTMF\n"); ++ hardware_dtmf_control(xpd, pos, 0); ++ } ++ BIT_CLR(priv->want_dtmf_events, pos); ++ } ++ if (val & DAHDI_TONEDETECT_MUTE) { ++ BIT_SET(priv->want_dtmf_mute, pos); ++ } else { ++ BIT_CLR(priv->want_dtmf_mute, pos); ++ __do_mute_dtmf(xpd, pos, 0); ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++ case DAHDI_SETPOLARITY: ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++ /* ++ * Asterisk may send us this if chan_dahdi config ++ * has "hanguponpolarityswitch=yes" to notify ++ * that the other side has hanged up. ++ * ++ * This has no effect on normal phone (but we may ++ * be connected to another FXO equipment). ++ * note that this chan_dahdi settings has different ++ * meaning for FXO, where it signals polarity ++ * reversal *detection* logic. ++ * ++ * It seems that sometimes we get this from ++ * asterisk in wrong state (e.g: while ringing). ++ * In these cases, silently ignore it. ++ */ ++ if (priv->lasttxhook[pos] == FXS_LINE_RING ++ || priv->lasttxhook[pos] == FXS_LINE_OPEN) { ++ LINE_DBG(SIGNAL, xpd, pos, ++ "DAHDI_SETPOLARITY: %s Cannot change " ++ "when lasttxhook=0x%X\n", ++ (val) ? "ON" : "OFF", priv->lasttxhook[pos]); ++ return -EINVAL; ++ } ++ LINE_DBG(SIGNAL, xpd, pos, "DAHDI_SETPOLARITY: %s\n", ++ (val) ? "ON" : "OFF"); ++ if ((val && !reversepolarity) || (!val && reversepolarity)) ++ priv->lasttxhook[pos] |= FXS_LINE_RING; ++ else ++ priv->lasttxhook[pos] &= ~FXS_LINE_RING; ++ linefeed_control(xbus, xpd, pos, priv->lasttxhook[pos]); ++ return 0; ++ case DAHDI_VMWI_CONFIG: ++ if (set_vmwi(xpd, pos, arg) < 0) ++ return -EINVAL; ++ return 0; ++ case DAHDI_VMWI: /* message-waiting led control */ ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++ if (!vmwi_ioctl) { ++ static bool notified; ++ ++ if (!notified) { ++ notified = true; ++ LINE_NOTICE(xpd, pos, ++ "Got DAHDI_VMWI notification " ++ "but vmwi_ioctl parameter is off. " ++ "Ignoring.\n"); ++ } ++ return 0; ++ } ++ /* Digital inputs/outputs don't have VM leds */ ++ if (IS_SET ++ (PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd). ++ digital_outputs, pos)) ++ return 0; ++ PHONEDEV(xpd).msg_waiting[pos] = val; ++ LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI: %s\n", ++ (val) ? "yes" : "no"); ++ return 0; ++ default: ++ report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); ++ } ++ return -ENOTTY; ++} ++ ++static int FXS_card_open(xpd_t *xpd, lineno_t chan) ++{ ++ struct FXS_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ if (IS_OFFHOOK(xpd, chan)) ++ LINE_NOTICE(xpd, chan, "Already offhook during open. OK.\n"); ++ else ++ LINE_DBG(SIGNAL, xpd, chan, "is onhook\n"); ++ /* ++ * Delegate updating dahdi to FXS_card_tick(): ++ * The problem is that dahdi_hooksig() is spinlocking the channel and ++ * we are called by dahdi with the spinlock already held on the ++ * same channel. ++ */ ++ BIT_SET(priv->update_offhook_state, chan); ++ return 0; ++} ++ ++static int FXS_card_close(xpd_t *xpd, lineno_t chan) ++{ ++ struct FXS_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ LINE_DBG(GENERAL, xpd, chan, "\n"); ++ priv = xpd->priv; ++ priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE; ++ return 0; ++} ++ ++#ifdef POLL_DIGITAL_INPUTS ++/* ++ * INPUT polling is done via SLIC register 0x06 (same as LEDS): ++ * 7 6 5 4 3 2 1 0 ++ * +-----+-----+-----+-----+-----+-----+-----+-----+ ++ * | I1 | I3 | | | I2 | I4 | | | ++ * +-----+-----+-----+-----+-----+-----+-----+-----+ ++ * ++ */ ++static int input_ports_type1[] = { ++ /* slic = input_port */ ++ [0] = -1, ++ [1] = -1, ++ [2] = 2, ++ [3] = 3, ++ [4] = -1, ++ [5] = -1, ++ [6] = 0, ++ [7] = 1, ++ }; ++ ++static void poll_inputs(xpd_t *xpd) ++{ ++ int i; ++ ++ BUG_ON(xpd->xbus_idx != 0); // Only unit #0 has digital inputs ++ if (XPD_HW(xpd).type == 6) { ++ EXP_REQUEST(xpd->xbus, xpd, SLIC_READ, ++ REG_TYPE6_EXP_GPIOB, 0, 0); ++ } else { ++ for (i = 0; i < ARRAY_SIZE(input_ports_type1); i++) { ++ int pos = input_ports_type1[i]; ++ if (pos >= 0) { ++ SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ, 0x06, 0); ++ } ++ } ++ } ++} ++#endif ++ ++static void poll_linefeed(xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ int i; ++ ++ if (XPD_HW(xpd).type != 6) ++ return; ++ if (xpd->xpd_state != XPD_STATE_READY) ++ return; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ BUG_ON(!xpd->xbus); ++ ++ XPD_DBG(GENERAL, xpd, "periodic poll"); ++ for_each_line(xpd, i) { ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ || IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ continue; ++ if (priv->polledhook[i] == FXS_LINE_OPEN && ++ priv->lasttxhook[i] != FXS_LINE_OPEN) { ++ LINE_NOTICE(xpd, i, "Overheat detected, resetting."); ++ priv->overheat_reset_counter[i]++; ++ linefeed_control(xpd->xbus, xpd, i, ++ priv->lasttxhook[i]); ++ } ++ SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ, ++ REG_TYPE6_LINEFEED, 0); ++ } ++} ++ ++static void handle_linefeed(xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ for_each_line(xpd, i) { ++ if (priv->lasttxhook[i] == FXS_LINE_RING ++ && !IS_SET(priv->neon_blinking, i)) { ++ /* RINGing, prepare for OHT */ ++ priv->ohttimer[i] = OHT_TIMER; ++ priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS; ++ } else { ++ if (priv->ohttimer[i]) { ++ priv->ohttimer[i]--; ++ if (!priv->ohttimer[i]) { ++ LINE_DBG(SIGNAL, xpd, i, ++ "ohttimer expired\n"); ++ priv->idletxhookstate[i] = ++ FXS_LINE_POL_ACTIVE; ++ oht_pcm(xpd, i, 0); ++ vmwi_search(xpd, i, 0); ++ if (priv->lasttxhook[i] == ++ FXS_LINE_POL_OHTRANS) { ++ /* Apply the change if appropriate */ ++ linefeed_control(xpd->xbus, xpd, ++ i, ++ FXS_LINE_POL_ACTIVE); ++ } ++ } ++ } ++ } ++ } ++} ++ ++/* ++ * Optimized memcmp() like function. Only test for equality (true/false). ++ * This optimization reduced the detect_vmwi() runtime by a factor of 3. ++ */ ++static inline bool mem_equal(const char a[], const char b[], size_t len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++) ++ if (a[i] != b[i]) ++ return 0; ++ return 1; ++} ++ ++/* ++ * Detect Voice Mail Waiting Indication ++ */ ++static void detect_vmwi(xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ xbus_t *xbus; ++ static const __u8 FSK_COMMON_PATTERN[] = ++ { 0xA8, 0x49, 0x22, 0x3B, 0x9F, 0xFF, 0x1F, 0xBB }; ++ static const __u8 FSK_ON_PATTERN[] = ++ { 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF }; ++ static const __u8 FSK_OFF_PATTERN[] = ++ { 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F }; ++ int i; ++ xpp_line_t ignore_mask; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ ignore_mask = ++ PHONEDEV(xpd).offhook_state | ++ ~(PHONEDEV(xpd).oht_pcm_pass) | ++ ~(priv->search_fsk_pattern) | ++ PHONEDEV(xpd).digital_inputs | ++ PHONEDEV(xpd).digital_outputs; ++ for_each_line(xpd, i) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ __u8 *writechunk = chan->writechunk; ++ ++ if (IS_SET(ignore_mask, i)) ++ continue; ++#if 0 ++ if (writechunk[0] != 0x7F && writechunk[0] != 0) { ++ int j; ++ ++ LINE_DBG(GENERAL, xpd, i, "MSG:"); ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) { ++ if (debug) ++ printk(" %02X", writechunk[j]); ++ } ++ if (debug) ++ printk("\n"); ++ } ++#endif ++ if (unlikely ++ (mem_equal ++ (writechunk, FSK_COMMON_PATTERN, DAHDI_CHUNKSIZE))) { ++ LINE_DBG(SIGNAL, xpd, i, ++ "Found common FSK pattern. " ++ "Start looking for ON/OFF patterns.\n"); ++ BIT_SET(priv->found_fsk_pattern, i); ++ } else if (unlikely(IS_SET(priv->found_fsk_pattern, i))) { ++ BIT_CLR(priv->found_fsk_pattern, i); ++ oht_pcm(xpd, i, 0); ++ if (unlikely ++ (mem_equal ++ (writechunk, FSK_ON_PATTERN, DAHDI_CHUNKSIZE))) { ++ LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n"); ++ PHONEDEV(xpd).msg_waiting[i] = 1; ++ start_stop_vm_led(xbus, xpd, i); ++ } else ++ if (unlikely ++ (mem_equal ++ (writechunk, FSK_OFF_PATTERN, ++ DAHDI_CHUNKSIZE))) { ++ LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n"); ++ PHONEDEV(xpd).msg_waiting[i] = 0; ++ start_stop_vm_led(xbus, xpd, i); ++ } else { ++ int j; ++ ++ LINE_NOTICE(xpd, i, "MSG WAITING Unexpected:"); ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) ++ printk(" %02X", writechunk[j]); ++ printk("\n"); ++ } ++ } ++ } ++} ++ ++static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct FXS_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++#ifdef POLL_DIGITAL_INPUTS ++ if (poll_digital_inputs && PHONEDEV(xpd).digital_inputs) { ++ if ((xpd->timer_count % poll_digital_inputs) == 0) ++ poll_inputs(xpd); ++ } ++#endif ++ if ((xpd->timer_count % poll_chan_linefeed) == 0) ++ poll_linefeed(xpd); ++ handle_fxs_leds(xpd); ++ handle_linefeed(xpd); ++ if (XPD_HW(xpd).type == 6) ++ blink_mwi(xpd); ++ /* ++ * Hack alert (FIXME): ++ * Asterisk did FXS_card_open() and we wanted to report ++ * offhook state. However, the channel is spinlocked by dahdi ++ * so we marked it in the priv->update_offhook_state mask and ++ * now we take care of notification to dahdi and Asterisk ++ */ ++ if (priv->update_offhook_state) { ++ enum dahdi_rxsig rxsig; ++ int i; ++ ++ for_each_line(xpd, i) { ++ if (!IS_SET(priv->update_offhook_state, i)) ++ continue; ++ rxsig = ++ IS_OFFHOOK(xpd, ++ i) ? DAHDI_RXSIG_OFFHOOK : ++ DAHDI_RXSIG_ONHOOK; ++ /* Notify after open() */ ++ notify_rxsig(xpd, i, rxsig); ++ BIT_CLR(priv->update_offhook_state, i); ++ } ++ } ++ if (SPAN_REGISTERED(xpd)) { ++ if (!vmwi_ioctl && priv->search_fsk_pattern) ++ detect_vmwi(xpd); /* Detect via FSK modulation */ ++ } ++ return 0; ++} ++ ++/*---------------- FXS: HOST COMMANDS -------------------------------------*/ ++ ++/*---------------- FXS: Astribank Reply Handlers --------------------------*/ ++ ++/* ++ * Should be called with spinlocked XPD ++ */ ++static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, ++ xpp_line_t change_mask) ++{ ++ xbus_t *xbus; ++ struct FXS_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ BUG_ON(PHONEDEV(xpd).direction != TO_PHONE); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ XPD_DBG(SIGNAL, xpd, "offhook=0x%X change_mask=0x%X\n", offhook, ++ change_mask); ++ for_each_line(xpd, i) { ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ || IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ continue; ++ if (IS_SET(change_mask, i)) { ++ PHONEDEV(xpd).ringing[i] = 0; /* No more ringing... */ ++#ifdef WITH_METERING ++ metering_gen(xpd, i, 0); /* Stop metering... */ ++#endif ++ MARK_BLINK(priv, i, LED_GREEN, 0); ++ /* ++ * Reset our previous DTMF memories... ++ */ ++ BIT_CLR(priv->prev_key_down, i); ++ priv->prev_key_time[i] = ktime_set(0L, 0UL); ++ if (IS_SET(offhook, i)) { ++ LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n"); ++ MARK_ON(priv, i, LED_GREEN); ++ hookstate_changed(xpd, i, 1); ++ } else { ++ LINE_DBG(SIGNAL, xpd, i, "ONHOOK\n"); ++ MARK_OFF(priv, i, LED_GREEN); ++ hookstate_changed(xpd, i, 0); ++ } ++ /* ++ * Must switch to low power. In high power, an ONHOOK ++ * won't be detected. ++ */ ++ do_chan_power(xbus, xpd, i, 0); ++ } ++ } ++} ++ ++HANDLER_DEF(FXS, SIG_CHANGED) ++{ ++ xpp_line_t sig_status = ++ RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_status); ++ xpp_line_t sig_toggles = ++ RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_toggles); ++ unsigned long flags; ++ ++ BUG_ON(!xpd); ++ BUG_ON(PHONEDEV(xpd).direction != TO_PHONE); ++ XPD_DBG(SIGNAL, xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", ++ sig_toggles, sig_status); ++#if 0 ++ Is this needed ? for_each_line(xpd, i) { ++ // Power down (prevent overheating!!!) ++ if (IS_SET(sig_toggles, i)) ++ do_chan_power(xpd->xbus, xpd, BIT(i), 0); ++ } ++#endif ++ spin_lock_irqsave(&xpd->lock, flags); ++ process_hookstate(xpd, sig_status, sig_toggles); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++#ifdef POLL_DIGITAL_INPUTS ++static inline void notify_digital_input(xpd_t *xpd, int input_port, int offhook) ++{ ++ int channo = PHONEDEV(xpd).channels - LINES_DIGI_INP + input_port; ++ ++ /* Stop ringing. No leds for digital inputs. */ ++ PHONEDEV(xpd).ringing[channo] = 0; ++ if (offhook && !IS_OFFHOOK(xpd, channo)) { ++ LINE_DBG(SIGNAL, xpd, channo, "OFFHOOK\n"); ++ hookstate_changed(xpd, channo, 1); ++ } else if (!offhook && IS_OFFHOOK(xpd, channo)) { ++ LINE_DBG(SIGNAL, xpd, channo, "ONHOOK\n"); ++ hookstate_changed(xpd, channo, 0); ++ } ++} ++ ++static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info) ++{ ++ bool offhook; ++ /* Sanity check */ ++ if (!PHONEDEV(xpd).digital_inputs) { ++ XPD_NOTICE(xpd, "%s called without digital inputs. Ignored\n", ++ __func__); ++ return; ++ } ++ if (XPD_HW(xpd).type == 6) { ++ static int input_values_type6[] = { 0x80, 0x20, 0x08, 0x02 }; /* I/O Expander values of input relays */ ++ int i; ++ ++ /* Map I/O Expander GPIO into line number */ ++ for (i = 0; i < ARRAY_SIZE(input_values_type6); i++) { ++ int chanmask = input_values_type6[i]; ++ ++ offhook = (REG_FIELD(info, data_low) & chanmask) == 0; ++ notify_digital_input(xpd, i, offhook); ++ } ++ } else { ++ int channo = info->h.portnum; ++ int input_port; ++ offhook = (REG_FIELD(info, data_low) & 0x1) == 0; ++ if (channo < 0 || channo >= ARRAY_SIZE(input_ports_type1)) { ++ XPD_ERR(xpd, "%s: got bad portnum=%d\n", __func__, channo); ++ return; ++ } ++ input_port = input_ports_type1[channo]; ++ if (input_port < 0) { ++ XPD_ERR(xpd, "%s: portnum=%d is not input port\n", __func__, channo); ++ return; ++ } ++ notify_digital_input(xpd, input_port, offhook); ++ } ++} ++#endif ++ ++static const char dtmf_digits[] = { ++ 'D', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#', ++ 'A', 'B', 'C' ++}; ++ ++/* ++ * This function is called with spinlocked XPD ++ */ ++static void process_dtmf(xpd_t *xpd, uint portnum, __u8 val) ++{ ++ __u8 digit; ++ bool key_down = val & 0x10; ++ bool want_mute; ++ bool want_event; ++ struct FXS_priv_data *priv; ++ ktime_t now; ++ s64 msec = 0; ++ struct timespec64 ts; ++ ++ if (!dtmf_detection) ++ return; ++ if (!SPAN_REGISTERED(xpd)) ++ return; ++ priv = xpd->priv; ++ val &= 0xF; ++ digit = dtmf_digits[val]; ++ want_mute = IS_SET(priv->want_dtmf_mute, portnum); ++ want_event = IS_SET(priv->want_dtmf_events, portnum); ++ if (!IS_SET(priv->prev_key_down, portnum) && !key_down) ++ LINE_NOTICE(xpd, portnum, "DTMF: duplicate UP (%c)\n", digit); ++ if (key_down) ++ BIT_SET(priv->prev_key_down, portnum); ++ else ++ BIT_CLR(priv->prev_key_down, portnum); ++ now = ktime_get(); ++ if (!dahdi_ktime_equal(priv->prev_key_time[portnum], ktime_set(0, 0))) ++ msec = ktime_ms_delta(now, priv->prev_key_time[portnum]); ++ priv->prev_key_time[portnum] = now; ++ ts = ktime_to_timespec64(now); ++ LINE_DBG(SIGNAL, xpd, portnum, ++ "[%lld.%06ld] DTMF digit %-4s '%c' (val=%d, want_mute=%s want_event=%s, delta=%lld msec)\n", ++ (s64)ts.tv_sec, ts.tv_nsec * NSEC_PER_USEC, ++ (key_down) ? "DOWN" : "UP", digit, val, ++ (want_mute) ? "yes" : "no", (want_event) ? "yes" : "no", msec); ++ /* ++ * FIXME: we currently don't use the want_dtmf_mute until ++ * we are sure about the logic in Asterisk native bridging. ++ * Meanwhile, simply mute it on button press. ++ */ ++ if (key_down && want_mute) ++ __do_mute_dtmf(xpd, portnum, 1); ++ else ++ __do_mute_dtmf(xpd, portnum, 0); ++ if (want_event) { ++ int event = ++ (key_down) ? DAHDI_EVENT_DTMFDOWN : DAHDI_EVENT_DTMFUP; ++ ++ dahdi_qevent_lock(XPD_CHAN(xpd, portnum), event | digit); ++ } ++} ++ ++static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) ++{ ++ unsigned long flags; ++ struct FXS_priv_data *priv; ++ __u8 regnum = 0; ++ bool indirect = 0; ++ ++ spin_lock_irqsave(&xpd->lock, flags); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (info->h.bytes == REG_CMD_SIZE(REG)) { ++ if ((XPD_HW(xpd).type == 1) && (REG_FIELD(info, regnum) == 0x1E)) ++ indirect = 1; ++ regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum); ++ XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n", ++ (indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low), ++ REG_FIELD(info, data_high)); ++ } ++ if (info->h.bytes == REG_CMD_SIZE(RAM)) { ++ uint addr; ++ unsigned long val; ++ XPD_DBG(REGS, xpd, "port=%d, addr_low=0x%X, addr_high=0x%X, data_0=0x%X data_1=0x%X data_2=0x%X data_3=0x%X\n", ++ info->h.portnum, ++ REG_FIELD_RAM(info, addr_low), ++ REG_FIELD_RAM(info, addr_high), ++ REG_FIELD_RAM(info, data_0), ++ REG_FIELD_RAM(info, data_1), ++ REG_FIELD_RAM(info, data_2), ++ REG_FIELD_RAM(info, data_3)); ++ addr = (REG_FIELD_RAM(info, addr_high) << 8) | REG_FIELD_RAM(info, addr_low); ++ val = (REG_FIELD_RAM(info, data_3) << 24) | ++ (REG_FIELD_RAM(info, data_2) << 16) | ++ (REG_FIELD_RAM(info, data_1) << 8) | ++ REG_FIELD_RAM(info, data_0); ++ } else if ((XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DTMF_DECODE) || ++ (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_TONDTMF)) { ++ __u8 val = REG_FIELD(info, data_low); ++ ++ process_dtmf(xpd, info->h.portnum, val); ++ } else if ((XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LINEFEED)) { ++ __u8 val = REG_FIELD(info, data_low); ++ ++ LINE_DBG(SIGNAL, xpd, info->h.portnum, ++ "REG_TYPE6_LINEFEED: dataL=0x%X \n", val); ++ priv->polledhook[info->h.portnum] = val; ++ } ++#ifdef POLL_DIGITAL_INPUTS ++ /* ++ * Process digital inputs polling results ++ */ ++ else if ( (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DIGITAL_IOCTRL) || ++ (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_EXP_GPIOB && ++ REG_FIELD(info, do_expander))) ++ process_digital_inputs(xpd, info); ++#endif ++ else if (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_LOOPCLOSURE) { /* OFFHOOK ? */ ++ __u8 val = REG_FIELD(info, data_low); ++ xpp_line_t mask = BIT(info->h.portnum); ++ xpp_line_t offhook; ++ ++ /* ++ * Validate reply. Non-existing/disabled ports ++ * will reply with 0xFF. Ignore these. ++ */ ++ if ((val & REG_TYPE1_LOOPCLOSURE_ZERO) == 0) { ++ offhook = (val & REG_TYPE1_LOOPCLOSURE_LCR) ? mask : 0; ++ LINE_DBG(SIGNAL, xpd, info->h.portnum, ++ "REG_TYPE1_LOOPCLOSURE: dataL=0x%X " ++ "(offhook=0x%X mask=0x%X)\n", ++ val, offhook, mask); ++ process_hookstate(xpd, offhook, mask); ++ } ++ } else if (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LCRRTP) { /* OFFHOOK ? */ ++ __u8 val = REG_FIELD(info, data_low); ++ xpp_line_t mask = BIT(info->h.portnum); ++ xpp_line_t offhook; ++ ++ /* ++ * Validate reply. Non-existing/disabled ports ++ * will reply with 0xFF. Ignore these. ++ */ ++ if ((val & REG_TYPE6_LCRRTP_ZERO) == 0) { ++ offhook = (val & REG_TYPE6_LCRRTP_LCR) ? mask : 0; ++ LINE_DBG(SIGNAL, xpd, info->h.portnum, ++ "REG_TYPE6_LCRRTP: dataL=0x%X " ++ "(offhook=0x%X mask=0x%X)\n", ++ val, offhook, mask); ++ process_hookstate(xpd, offhook, mask); ++ } ++ } else { ++#if 0 ++ XPD_NOTICE(xpd, ++ "Spurious register reply(ignored): " ++ "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n", ++ (indirect) ? "I" : "D", ++ regnum, REG_FIELD(info, data_low), ++ REG_FIELD(info, data_high)); ++#endif ++ } ++ /* ++ * Update /proc info only if reply relate to the last slic ++ * read request ++ */ ++ if (REG_FIELD(&xpd->requested_reply, regnum) == ++ REG_FIELD(info, regnum) ++ && REG_FIELD(&xpd->requested_reply, do_subreg) == ++ REG_FIELD(info, do_subreg) ++ && REG_FIELD(&xpd->requested_reply, subreg) == ++ REG_FIELD(info, subreg)) { ++ xpd->last_reply = *info; ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++static int FXS_card_state(xpd_t *xpd, bool on) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ return 0; ++} ++ ++static const struct xops fxs_xops = { ++ .card_new = FXS_card_new, ++ .card_init = FXS_card_init, ++ .card_remove = FXS_card_remove, ++ .card_tick = FXS_card_tick, ++ .card_register_reply = FXS_card_register_reply, ++}; ++ ++static const struct phoneops fxs_phoneops = { ++ .card_dahdi_preregistration = FXS_card_dahdi_preregistration, ++ .card_dahdi_postregistration = FXS_card_dahdi_postregistration, ++ .card_hooksig = FXS_card_hooksig, ++ .card_pcm_recompute = generic_card_pcm_recompute, ++ .card_pcm_fromspan = generic_card_pcm_fromspan, ++ .card_pcm_tospan = generic_card_pcm_tospan, ++ .card_timing_priority = generic_timing_priority, ++ .echocancel_timeslot = generic_echocancel_timeslot, ++ .echocancel_setmask = generic_echocancel_setmask, ++ .card_open = FXS_card_open, ++ .card_close = FXS_card_close, ++ .card_ioctl = FXS_card_ioctl, ++ .card_state = FXS_card_state, ++}; ++ ++static xproto_table_t PROTO_TABLE(FXS) = { ++ .owner = THIS_MODULE, ++ .entries = { ++ /* Prototable Card Opcode */ ++ XENTRY( FXS, FXS, SIG_CHANGED ), ++ }, ++ .name = "FXS", /* protocol name */ ++ .ports_per_subunit = 8, ++ .type = XPD_TYPE_FXS, ++ .xops = &fxs_xops, ++ .phoneops = &fxs_phoneops, ++ .packet_is_valid = fxs_packet_is_valid, ++ .packet_dump = fxs_packet_dump, ++}; ++ ++static bool fxs_packet_is_valid(xpacket_t *pack) ++{ ++ const xproto_entry_t *xe; ++ ++ // DBG(GENERAL, "\n"); ++ xe = xproto_card_entry(&PROTO_TABLE(FXS), XPACKET_OP(pack)); ++ return xe != NULL; ++} ++ ++static void fxs_packet_dump(const char *msg, xpacket_t *pack) ++{ ++ DBG(GENERAL, "%s\n", msg); ++} ++ ++/*------------------------- SLIC Handling --------------------------*/ ++ ++#ifdef CONFIG_PROC_FS ++static int proc_fxs_info_show(struct seq_file *sfile, void *not_used) ++{ ++ unsigned long flags; ++ xpd_t *xpd = sfile->private; ++ struct FXS_priv_data *priv; ++ int i; ++ int led; ++ ++ if (!xpd) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ seq_printf(sfile, "%-12s", "Channel:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", i); ++ } ++ seq_printf(sfile, "\n%-12s", ""); ++ for_each_line(xpd, i) { ++ char *chan_type; ++ ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, i)) ++ chan_type = "out"; ++ else if (IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ chan_type = "in"; ++ else ++ chan_type = ""; ++ seq_printf(sfile, "%4s", chan_type); ++ } ++ seq_printf(sfile, "\n%-12s", "idletxhook:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", priv->idletxhookstate[i]); ++ } ++ seq_printf(sfile, "\n%-12s", "lasttxhook:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", priv->lasttxhook[i]); ++ } ++ seq_printf(sfile, "\n%-12s", "ohttimer:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", priv->ohttimer[i]); ++ } ++ seq_printf(sfile, "\n%-12s", "neon_blink:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", ++ IS_SET(priv->neon_blinking, i)); ++ } ++ seq_printf(sfile, "\n%-12s", "search_fsk:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", ++ IS_SET(priv->search_fsk_pattern, i)); ++ } ++ seq_printf(sfile, "\n%-12s", "vbat_h:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", ++ test_bit(i, (unsigned long *)&priv->vbat_h)); ++ } ++ seq_printf(sfile, "\n"); ++ for (led = 0; led < NUM_LEDS; led++) { ++ seq_printf(sfile, "\nLED #%d\t%-12s: ", ++ led, "ledstate"); ++ for_each_line(xpd, i) { ++ if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ seq_printf(sfile, "%d ", ++ IS_SET(priv->ledstate[led], i)); ++ } ++ seq_printf(sfile, "\nLED #%d\t%-12s: ", ++ led, "ledcontrol"); ++ for_each_line(xpd, i) { ++ if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ seq_printf(sfile, "%d ", ++ IS_SET(priv->ledcontrol[led], i)); ++ } ++ seq_printf(sfile, "\nLED #%d\t%-12s: ", ++ led, "led_counter"); ++ for_each_line(xpd, i) { ++ if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) ++ && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ seq_printf(sfile, "%d ", ++ LED_COUNTER(priv, i, led)); ++ } ++ } ++ seq_printf(sfile, "\n%-12s", "overheats:"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%4d", priv->overheat_reset_counter[i]); ++ } ++ seq_printf(sfile, "\n"); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++static int proc_fxs_info_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, proc_fxs_info_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_fxs_info_ops = { ++ .proc_open = proc_fxs_info_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations proc_fxs_info_ops = { ++ .owner = THIS_MODULE, ++ .open = proc_fxs_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++ ++#ifdef WITH_METERING ++static ssize_t proc_xpd_metering_write(struct file *file, ++ const char __user *buffer, size_t count, loff_t *offset) ++{ ++ xpd_t *xpd = file->private_data; ++ char buf[MAX_PROC_WRITE]; ++ lineno_t chan; ++ int num; ++ int ret; ++ ++ if (!xpd) ++ return -ENODEV; ++ if (count >= MAX_PROC_WRITE - 1) { ++ XPD_ERR(xpd, "Metering string too long (%zu)\n", count); ++ return -EINVAL; ++ } ++ if (copy_from_user(&buf, buffer, count)) ++ return -EFAULT; ++ buf[count] = '\0'; ++ ret = sscanf(buf, "%d", &num); ++ if (ret != 1) { ++ XPD_ERR(xpd, "Metering value should be number. Got '%s'\n", ++ buf); ++ return -EINVAL; ++ } ++ chan = num; ++ if (chan != PORT_BROADCAST && chan > xpd->channels) { ++ XPD_ERR(xpd, "Metering tone: bad channel number %d\n", chan); ++ return -EINVAL; ++ } ++ if ((ret = metering_gen(xpd, chan, 1)) < 0) { ++ XPD_ERR(xpd, "Failed sending metering tone\n"); ++ return ret; ++ } ++ return count; ++} ++ ++static int proc_xpd_metering_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = PDE_DATA(inode); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_xpd_metering_ops = { ++ .proc_open = proc_xpd_metering_open, ++ .proc_write = proc_xpd_metering_write, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations proc_xpd_metering_ops = { ++ .owner = THIS_MODULE, ++ .open = proc_xpd_metering_open, ++ .write = proc_xpd_metering_write, ++ .release = single_release, ++}; ++#endif ++#endif ++#endif ++ ++static DEVICE_ATTR_READER(fxs_ring_registers_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct FXS_priv_data *priv; ++ unsigned long flags; ++ const struct ring_reg_params *p; ++ const struct byte_pair *v; ++ enum ring_types rtype; ++ int len = 0; ++ int i; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += sprintf(buf + len, "# Reg#: D/I\tNEON \tTRAPEZ \tNORMAL \n"); ++ for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) { ++ p = &ring_parameters[i]; ++ len += sprintf(buf + len, "[%d] 0x%02X: %c", ++ i, p->regno, (p->is_indirect) ? 'I' : 'D'); ++ for (rtype = RING_TYPE_NEON; rtype <= RING_TYPE_NORMAL; rtype++) { ++ v = &(p->values[rtype]); ++ if (p->is_indirect) ++ len += sprintf(buf + len, "\t0x%02X 0x%02X", ++ v->h_val, v->l_val); ++ else ++ len += sprintf(buf + len, "\t0x%02X ----", ++ v->l_val); ++ } ++ len += sprintf(buf + len, "\n"); ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR_WRITER(fxs_ring_registers_store, dev, buf, count) ++{ ++ xpd_t *xpd; ++ struct FXS_priv_data *priv; ++ unsigned long flags; ++ char rtype_name[MAX_PROC_WRITE]; ++ enum ring_types rtype; ++ struct ring_reg_params *params; ++ struct byte_pair *v; ++ int regno; ++ int h_val; ++ int l_val; ++ int ret; ++ int i; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ ret = sscanf(buf, "%10s %X %X %X\n", ++ rtype_name, ®no, &h_val, &l_val); ++ if (ret < 3 || ret > 4) { ++ XPD_ERR(xpd, "Bad input: '%s'\n", buf); ++ XPD_ERR(xpd, "# Correct input\n"); ++ XPD_ERR(xpd, "{NEON|TRAPEZ|NORMAL} []\n"); ++ goto invalid_input; ++ } ++ if (strcasecmp("NEON", rtype_name) == 0) ++ rtype = RING_TYPE_NEON; ++ else if (strcasecmp("TRAPEZ", rtype_name) == 0) ++ rtype = RING_TYPE_TRAPEZ; ++ else if (strcasecmp("NORMAL", rtype_name) == 0) ++ rtype = RING_TYPE_NORMAL; ++ else { ++ XPD_ERR(xpd, "Unknown ring type '%s' (NEON/TRAPEZ/NORMAL)\n", ++ rtype_name); ++ goto invalid_input; ++ } ++ params = NULL; ++ for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) { ++ if (ring_parameters[i].regno == regno) { ++ params = &ring_parameters[i]; ++ break; ++ } ++ } ++ if (!params) { ++ XPD_ERR(xpd, "Bad register 0x%X\n", regno); ++ goto invalid_input; ++ } ++ if (params->is_indirect) { ++ if (ret != 4) { ++ XPD_ERR(xpd, ++ "Missing low-byte (0x%X is indirect register)\n", ++ regno); ++ goto invalid_input; ++ } ++ XPD_DBG(SIGNAL, xpd, "%s Indirect 0x%X <=== 0x%X 0x%X\n", ++ rtype_name, regno, h_val, l_val); ++ } else { ++ if (ret != 3) { ++ XPD_ERR(xpd, ++ "Should give exactly one value (0x%X is direct register)\n", ++ regno); ++ goto invalid_input; ++ } ++ l_val = h_val; ++ h_val = 0; ++ XPD_DBG(SIGNAL, xpd, "%s Direct 0x%X <=== 0x%X\n", ++ rtype_name, regno, h_val); ++ } ++ spin_lock_irqsave(&xpd->lock, flags); ++ v = &(params->values[rtype]); ++ v->h_val = h_val; ++ v->l_val = l_val; ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return count; ++invalid_input: ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(fxs_ring_registers, S_IRUGO | S_IWUSR, ++ fxs_ring_registers_show, ++ fxs_ring_registers_store); ++ ++static int fxs_xpd_probe(struct device *dev) ++{ ++ xpd_t *xpd; ++ int ret; ++ ++ xpd = dev_to_xpd(dev); ++ /* Is it our device? */ ++ if (xpd->xpd_type != XPD_TYPE_FXS) { ++ XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev), ++ xpd->xpd_type); ++ return -EINVAL; ++ } ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ ret = device_create_file(dev, &dev_attr_fxs_ring_registers); ++ if (ret) { ++ XPD_ERR(xpd, "%s: device_create_file(fxs_ring_registers) failed: %d\n", ++ __func__, ret); ++ goto fail_fxs_ring_registers; ++ } ++ return 0; ++fail_fxs_ring_registers: ++ return ret; ++} ++ ++static int fxs_xpd_remove(struct device *dev) ++{ ++ xpd_t *xpd; ++ ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ device_remove_file(dev, &dev_attr_fxs_ring_registers); ++ return 0; ++} ++ ++static struct xpd_driver fxs_driver = { ++ .xpd_type = XPD_TYPE_FXS, ++ .driver = { ++ .name = "fxs", ++ .owner = THIS_MODULE, ++ .probe = fxs_xpd_probe, ++ .remove = fxs_xpd_remove} ++}; ++ ++static int __init card_fxs_startup(void) ++{ ++ int ret; ++ ++ if ((ret = xpd_driver_register(&fxs_driver.driver)) < 0) ++ return ret; ++ ++#ifdef POLL_DIGITAL_INPUTS ++ INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n", ++ poll_digital_inputs); ++#else ++ INFO("FEATURE: without DIGITAL INPUTS support\n"); ++#endif ++ INFO("FEATURE: DAHDI_VMWI (HVAC only)\n"); ++#ifdef WITH_METERING ++ INFO("FEATURE: WITH METERING Generation\n"); ++#else ++ INFO("FEATURE: NO METERING Generation\n"); ++#endif ++ xproto_register(&PROTO_TABLE(FXS)); ++ return 0; ++} ++ ++static void __exit card_fxs_cleanup(void) ++{ ++ xproto_unregister(&PROTO_TABLE(FXS)); ++ xpd_driver_unregister(&fxs_driver.driver); ++} ++ ++MODULE_DESCRIPTION("XPP FXS Card Driver"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_XPD(XPD_TYPE_FXS); ++ ++module_init(card_fxs_startup); ++module_exit(card_fxs_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_fxs.h linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxs.h +--- linux-source-4.19/drivers/dahdi/xpp/card_fxs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_fxs.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,39 @@ ++#ifndef CARD_FXS_H ++#define CARD_FXS_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++ ++enum fxs_opcodes { ++ XPROTO_NAME(FXS, SIG_CHANGED) = 0x06, ++ /**/ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */ ++ XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */ ++ XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */ ++}; ++ ++DEF_RPACKET_DATA(FXS, SIG_CHANGED, ++ xpp_line_t sig_status; /* channels: lsb=1, msb=8 */ ++ xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */ ++ ); ++ ++#endif /* CARD_FXS_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_global.c linux-source-4.19-dahdi/drivers/dahdi/xpp/card_global.c +--- linux-source-4.19/drivers/dahdi/xpp/card_global.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_global.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,907 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xdefs.h" ++#include "xpd.h" ++#include "xpp_dahdi.h" ++#include "xproto.h" ++#include "dahdi_debug.h" ++#include "xbus-core.h" ++#include "parport_debug.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++DEF_PARM(charp, initdir, "/usr/share/dahdi", 0644, ++ "The directory of card initialization scripts"); ++ ++#define CHIP_REGISTERS "chipregs" ++ ++extern int debug; ++ ++/*---------------- GLOBAL PROC handling -----------------------------------*/ ++ ++static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno, ++ bool eoftx) ++{ ++ xframe_t *xframe; ++ xpacket_t *pack; ++ reg_cmd_t *reg_cmd; ++ int ret; ++ ++ /* ++ * Zero length multibyte is legal and has special meaning for the ++ * firmware: ++ * eoftx==1: Start sending us D-channel packets. ++ * eoftx==0: Stop sending us D-channel packets. ++ */ ++ XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, unit); ++ reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); ++ reg_cmd->h.bytes = 0; ++ reg_cmd->h.is_multibyte = 1; ++ reg_cmd->h.portnum = portno; ++ reg_cmd->h.eoframe = eoftx; ++ PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx); ++ if (debug & DBG_REGS) ++ dump_xframe(__func__, xbus, xframe, debug); ++ ret = send_cmd_frame(xbus, xframe); ++ if (ret < 0) ++ PORT_ERR(xbus, unit, portno, "%s: failed sending xframe\n", ++ __func__); ++ return ret; ++} ++ ++static int parse_hexbyte(const char *buf) ++{ ++ char *endp; ++ unsigned val; ++ ++ val = simple_strtoul(buf, &endp, 16); ++ if (*endp != '\0' || val > 0xFF) ++ return -EBADR; ++ return (__u8)val; ++} ++ ++static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[]) ++{ ++ int argno; ++ char num_args; ++ int portno; ++ bool writing; ++ int op; /* [W]rite, [R]ead */ ++ int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */ ++ bool do_subreg = 0; ++ int regnum; ++ int subreg; ++ int data_low; ++ bool do_datah; ++ int data_high; ++ bool do_expander = 0; ++ int ret = -EBADR; ++ ++ num_args = 2; /* port + operation */ ++ if (argc < num_args) { ++ XPD_ERR(xpd, "Not enough arguments (%d)\n", argc); ++ XPD_ERR(xpd, ++ "Any Command is composed of at least %d words " ++ "(got only %d)\n", ++ num_args, argc); ++ goto out; ++ } ++ /* Process the arguments */ ++ argno = 0; ++ if (strcmp(argv[argno], "*") == 0) { ++ portno = PORT_BROADCAST; ++ //XPD_DBG(REGS, xpd, "Port broadcast\n"); ++ } else { ++ portno = parse_hexbyte(argv[argno]); ++ if (portno < 0 || portno >= 8) { ++ XPD_ERR(xpd, "Illegal port number '%s'\n", argv[argno]); ++ goto out; ++ } ++ //XPD_DBG(REGS, xpd, "Port is %d\n", portno); ++ } ++ argno++; ++ if (strlen(argv[argno]) != 2) { ++ XPD_ERR(xpd, "Wrong operation codes '%s'\n", argv[argno]); ++ goto out; ++ } ++ op = argv[argno][0]; ++ switch (op) { ++ case 'W': ++ writing = 1; ++ num_args++; /* data low */ ++ //XPD_DBG(REGS, xpd, "WRITING\n"); ++ break; ++ case 'R': ++ writing = 0; ++ //XPD_DBG(REGS, xpd, "READING\n"); ++ break; ++ default: ++ XPD_ERR(xpd, "Unknown operation type '%c'\n", op); ++ goto out; ++ } ++ addr_mode = argv[argno][1]; ++ switch (addr_mode) { ++ case 'I': ++ XPD_NOTICE(xpd, ++ "'I' is deprecated in register commands. " ++ "Use 'S' instead.\n"); ++ /* fall through */ ++ case 'S': ++ do_subreg = 1; ++ num_args += 2; /* register + subreg */ ++ //XPD_DBG(REGS, xpd, "SUBREG\n"); ++ break; ++ case 'D': ++ do_subreg = 0; ++ num_args++; /* register */ ++ //XPD_DBG(REGS, xpd, "DIRECT\n"); ++ break; ++ case 'X': ++ do_subreg = 0; ++ do_expander = 1; ++ num_args++; /* register */ ++ //XPD_DBG(REGS, xpd, "EXPANDER\n"); ++ break; ++ case 'M': ++ case 'm': ++ if (op != 'W') { ++ XPD_ERR(xpd, ++ "Can use Multibyte (%c) only with op 'W'\n", ++ addr_mode); ++ goto out; ++ } ++ num_args--; /* No data low */ ++ //XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode); ++ break; ++ case 'R': ++ switch (op) { ++ case 'W': ++ num_args += 5; /* add: addr_high, data_[0-3] */ ++ break; ++ case 'R': ++ num_args += 2; /* add: addr_low, addr_high */ ++ break; ++ } ++ break; ++ default: ++ XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode); ++ goto out; ++ } ++ if (argv[argno][2] != '\0') { ++ XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]); ++ goto out; ++ } ++ if (argc < num_args) { ++ XPD_ERR(xpd, ++ "Command \"%s\" is composed of at least %d words " ++ "(got only %d)\n", ++ argv[argno], num_args, argc); ++ goto out; ++ } ++ argno++; ++ if (addr_mode == 'M' || addr_mode == 'm') { ++ if (argno < argc) { ++ XPD_ERR(xpd, ++ "Magic-Multibyte(%c) with %d extra arguments\n", ++ addr_mode, argc - argno); ++ goto out; ++ } ++ ret = ++ send_magic_request(xpd->xbus, xpd->addr.unit, portno, ++ addr_mode == 'm'); ++ goto out; ++ } ++ if (addr_mode == 'R') { ++ __u8 input[6]; ++ int i; ++ ++ if (num_args - 2 > 6) { ++ XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2); ++ goto out; ++ } ++ for (i = 0; i < num_args - 2; i++, argno++) { ++ int hexbyte= parse_hexbyte(argv[argno]); ++ if (hexbyte < 0) { ++ XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]); ++ goto out; ++ } ++ input[i] = hexbyte; ++ } ++ ret = xpp_ram_request(xpd->xbus, xpd, portno, writing, ++ input[0], ++ input[1], ++ input[2], ++ input[3], ++ input[4], ++ input[5], ++ 1); ++ goto out; ++ } ++ /* Normal (non-Magic) register commands */ ++ do_datah = 0; ++ if (argno >= argc) { ++ XPD_ERR(xpd, "Missing register number\n"); ++ goto out; ++ } ++ regnum = parse_hexbyte(argv[argno]); ++ if (regnum < 0) { ++ XPD_ERR(xpd, "Illegal register number '%s'\n", argv[argno]); ++ goto out; ++ } ++ //XPD_DBG(REGS, xpd, "Register is %X\n", regnum); ++ argno++; ++ if (do_subreg) { ++ if (argno >= argc) { ++ XPD_ERR(xpd, "Missing subregister number\n"); ++ goto out; ++ } ++ subreg = parse_hexbyte(argv[argno]); ++ if (subreg < 0) { ++ XPD_ERR(xpd, "Illegal subregister number '%s'\n", ++ argv[argno]); ++ goto out; ++ } ++ //XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg); ++ argno++; ++ } else ++ subreg = 0; ++ if (writing) { ++ if (argno >= argc) { ++ XPD_ERR(xpd, "Missing data low number\n"); ++ goto out; ++ } ++ data_low = parse_hexbyte(argv[argno]); ++ if (data_low < 0) { ++ XPD_ERR(xpd, "Illegal data_low number '%s'\n", ++ argv[argno]); ++ goto out; ++ } ++ //XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low); ++ argno++; ++ } else ++ data_low = 0; ++ if (argno < argc) { ++ do_datah = 1; ++ if (!argv[argno]) { ++ XPD_ERR(xpd, "Missing data high number\n"); ++ goto out; ++ } ++ data_high = parse_hexbyte(argv[argno]); ++ if (data_high < 0) { ++ XPD_ERR(xpd, "Illegal data_high number '%s'\n", ++ argv[argno]); ++ goto out; ++ } ++ //XPD_DBG(REGS, xpd, "Data High is %X\n", data_high); ++ argno++; ++ } else ++ data_high = 0; ++ if (argno < argc) { ++ XPD_ERR(xpd, "Command contains an extra %d argument\n", ++ argc - argno); ++ goto out; ++ } ++#if 0 ++ XPD_DBG(REGS, xpd, ++ "portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d " ++ "dataL=%d do_datah=%d dataH=%d do_expander=%d\n", ++ portno, /* portno */ ++ writing, /* writing */ ++ regnum, do_subreg, /* use subreg */ ++ subreg, /* subreg */ ++ data_low, do_datah, /* use data_high */ ++ data_high, do_expander); ++#endif ++ ret = xpp_register_request(xpd->xbus, xpd, portno, ++ writing, regnum, do_subreg, subreg, ++ data_low, do_datah, data_high, 1, do_expander); ++out: ++ return ret; ++} ++ ++#define MAX_ARGS 10 ++ ++int parse_chip_command(xpd_t *xpd, char *cmdline) ++{ ++ xbus_t *xbus; ++ int ret = -EBADR; ++ __u8 buf[MAX_PROC_WRITE]; ++ char *str; ++ char *p; ++ char *argv[MAX_ARGS + 1]; ++ int argc; ++ int i; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ if (!XBUS_FLAGS(xbus, CONNECTED)) { ++ XBUS_DBG(GENERAL, xbus, "Dropped packet. Disconnected.\n"); ++ return -EBUSY; ++ } ++ strlcpy(buf, cmdline, MAX_PROC_WRITE); /* Save a copy */ ++ if (buf[0] == '#' || buf[0] == ';') ++ XPD_DBG(REGS, xpd, "Note: '%s'\n", buf); ++ if ((p = strchr(buf, '#')) != NULL) /* Truncate comments */ ++ *p = '\0'; ++ if ((p = strchr(buf, ';')) != NULL) /* Truncate comments */ ++ *p = '\0'; ++ /* Trim leading whitespace */ ++ for (p = buf; *p && (*p == ' ' || *p == '\t'); p++) ++ ; ++ str = p; ++ for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS;) { ++ if (*p != '\0') { ++ argv[i] = p; ++ // XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p); ++ i++; ++ } ++ } ++ argv[i] = NULL; ++ argc = i; ++ if (p) { ++ XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n", ++ i, p); ++ goto out; ++ } ++ if (argc) ++ ret = execute_chip_command(xpd, argc, argv); ++ else ++ ret = 0; /* empty command - no op */ ++out: ++ return ret; ++} ++ ++/*---------------- GLOBAL Protocol Commands -------------------------------*/ ++ ++static bool global_packet_is_valid(xpacket_t *pack); ++static void global_packet_dump(const char *msg, xpacket_t *pack); ++ ++/*---------------- GLOBAL: HOST COMMANDS ----------------------------------*/ ++ ++/* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST) ++{ ++ int ret = -ENODEV; ++ xframe_t *xframe; ++ xpacket_t *pack; ++ ++ if (!xbus) { ++ DBG(DEVICES, "NO XBUS\n"); ++ return -EINVAL; ++ } ++ if (xbus_check_unique(xbus)) ++ return -EBUSY; ++ XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, AB_REQUEST, 0); ++ RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, rev) = XPP_PROTOCOL_VERSION; ++ RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, reserved) = 0; ++ XBUS_DBG(DEVICES, xbus, "Protocol Version %d\n", XPP_PROTOCOL_VERSION); ++ if (xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST)) ++ ret = send_cmd_frame(xbus, xframe); ++ return ret; ++} ++ ++int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, ++ bool writing, __u8 regnum, bool do_subreg, __u8 subreg, ++ __u8 data_low, bool do_datah, __u8 data_high, ++ bool should_reply, bool do_expander) ++{ ++ int ret = 0; ++ xframe_t *xframe; ++ xpacket_t *pack; ++ reg_cmd_t *reg_cmd; ++ ++ if (!xbus) { ++ DBG(REGS, "NO XBUS\n"); ++ return -EINVAL; ++ } ++ XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, xpd->xbus_idx); ++ LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n", ++ (writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg, ++ data_low, data_high); ++ reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); ++ /* do not count the 'bytes' field */ ++ reg_cmd->h.bytes = REG_CMD_SIZE(REG); ++ reg_cmd->h.is_multibyte = 0; ++ if (portno == PORT_BROADCAST) { ++ reg_cmd->h.portnum = 0; ++ REG_FIELD(reg_cmd, all_ports_broadcast) = 1; ++ } else { ++ reg_cmd->h.portnum = portno; ++ REG_FIELD(reg_cmd, all_ports_broadcast) = 0; ++ } ++ reg_cmd->h.eoframe = 0; ++ REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */ ++ REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1; ++ REG_FIELD(reg_cmd, do_subreg) = do_subreg; ++ REG_FIELD(reg_cmd, regnum) = regnum; ++ REG_FIELD(reg_cmd, subreg) = subreg; ++ REG_FIELD(reg_cmd, do_datah) = do_datah; ++ REG_FIELD(reg_cmd, data_low) = data_low; ++ REG_FIELD(reg_cmd, data_high) = data_high; ++ REG_FIELD(reg_cmd, do_expander) = do_expander; ++ if (should_reply) ++ xpd->requested_reply = *reg_cmd; ++ if (debug & DBG_REGS) { ++ dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit, ++ reg_cmd->h.portnum, reg_cmd); ++ dump_packet("REG_REQ", pack, 1); ++ } ++ if (!xframe->usec_towait) { /* default processing time of SPI */ ++ if (subreg) ++ xframe->usec_towait = 2000; ++ else ++ xframe->usec_towait = 1000; ++ } ++ ret = send_cmd_frame(xbus, xframe); ++ return ret; ++} ++EXPORT_SYMBOL(xpp_register_request); ++ ++int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, ++ bool writing, ++ __u8 addr_low, ++ __u8 addr_high, ++ __u8 data_0, ++ __u8 data_1, ++ __u8 data_2, ++ __u8 data_3, ++ bool should_reply) ++{ ++ int ret = 0; ++ xframe_t *xframe; ++ xpacket_t *pack; ++ reg_cmd_t *reg_cmd; ++ ++ if (!xbus) { ++ DBG(REGS, "NO XBUS\n"); ++ return -EINVAL; ++ } ++ XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx); ++ LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n", ++ (writing) ? 'W' : 'R', ++ addr_low, addr_high, ++ data_0, data_1, data_2, data_3); ++ reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); ++ /* do not count the 'bytes' field */ ++ reg_cmd->h.bytes = REG_CMD_SIZE(RAM); ++ reg_cmd->h.is_multibyte = 0; ++ if (portno == PORT_BROADCAST) { ++ reg_cmd->h.portnum = 0; ++ REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1; ++ } else { ++ reg_cmd->h.portnum = portno; ++ REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0; ++ } ++ reg_cmd->h.eoframe = 0; ++ REG_FIELD_RAM(reg_cmd, reserved) = 0; /* force reserved bits to 0 */ ++ REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1; ++ REG_FIELD_RAM(reg_cmd, do_datah) = 1; ++ REG_FIELD_RAM(reg_cmd, do_subreg) = 1; ++ REG_FIELD_RAM(reg_cmd, addr_low) = addr_low; ++ REG_FIELD_RAM(reg_cmd, addr_high) = addr_high; ++ REG_FIELD_RAM(reg_cmd, data_0) = data_0; ++ REG_FIELD_RAM(reg_cmd, data_1) = data_1; ++ REG_FIELD_RAM(reg_cmd, data_2) = data_2; ++ REG_FIELD_RAM(reg_cmd, data_3) = data_3; ++ if (should_reply) ++ xpd->requested_reply = *reg_cmd; ++ if (debug & DBG_REGS) { ++ dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit, ++ reg_cmd->h.portnum, reg_cmd); ++ dump_packet("REG_RAM", pack, 1); ++ } ++ if (!xframe->usec_towait) { /* default processing time of SPI */ ++ xframe->usec_towait = 1000; ++ } ++ ret = send_cmd_frame(xbus, xframe); ++ return ret; ++} ++EXPORT_SYMBOL(xpp_ram_request); ++ ++/* ++ * The XPD parameter is totaly ignored by the driver and firmware as well. ++ */ ++/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift) ++{ ++ xframe_t *xframe; ++ xpacket_t *pack; ++ const char *mode_name; ++ ++ BUG_ON(!xbus); ++ if ((mode_name = sync_mode_name(mode)) == NULL) { ++ XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode); ++ return -EINVAL; ++ } ++ XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift); ++ XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, 0); ++ RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, sync_mode) = mode; ++ RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, drift) = drift; ++ send_cmd_frame(xbus, xframe); ++ return 0; ++} ++ ++/* ++ * Wrapper for different types of xbus reset ++ */ ++static int send_xbus_reset(xbus_t *xbus, uint8_t reset_mask) ++{ ++ xframe_t *xframe; ++ xpacket_t *pack; ++ ++ BUG_ON(!xbus); ++ XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, XBUS_RESET, 0); ++ RPACKET_FIELD(pack, GLOBAL, XBUS_RESET, mask) = reset_mask; ++ send_cmd_frame(xbus, xframe); ++ return 0; ++} ++ ++/* 0x23 */ HOSTCMD(GLOBAL, RESET_SPI) ++{ ++ XBUS_DBG(DEVICES, xbus, "Sending SPI reset\n"); ++ /* toggle reset line */ ++ send_xbus_reset(xbus, 0x04); ++ send_xbus_reset(xbus, 0x00); ++ return 0; ++} ++ ++ ++/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS) ++{ ++ //XBUS_DBG(SYNC, xbus, "\n"); ++ return send_xbus_reset(xbus, 0x10); ++} ++ ++/*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/ ++ ++HANDLER_DEF(GLOBAL, NULL_REPLY) ++{ ++ XBUS_DBG(GENERAL, xbus, "got len=%d\n", XPACKET_LEN(pack)); ++ return 0; ++} ++ ++HANDLER_DEF(GLOBAL, AB_DESCRIPTION) ++{ /* 0x08 */ ++ struct xbus_workqueue *worker; ++ __u8 rev; ++ struct unit_descriptor *units; ++ int count_units; ++ int i; ++ int ret = 0; ++ ++ if (!xbus) { ++ NOTICE("%s: xbus is gone!!!\n", __func__); ++ goto out; ++ } ++ rev = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, rev); ++ units = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, unit_descriptor); ++ count_units = XPACKET_LEN(pack) - ((__u8 *)units - (__u8 *)pack); ++ count_units /= sizeof(*units); ++ if (rev != XPP_PROTOCOL_VERSION) { ++ XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n", ++ rev, XPP_PROTOCOL_VERSION); ++ ret = -EPROTO; ++ goto proto_err; ++ } ++ if (count_units > NUM_UNITS) { ++ XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n", ++ count_units, NUM_UNITS); ++ ret = -EPROTO; ++ goto proto_err; ++ } ++ if (count_units <= 0) { ++ XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n", count_units); ++ ret = -EPROTO; ++ goto proto_err; ++ } ++ if (units[0].addr.unit != 0 || units[0].addr.subunit != 0) { ++ XBUS_NOTICE(xbus, "No first module. Astribank unusable.\n"); ++ ret = -EPROTO; ++ goto proto_err; ++ } ++ if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) { ++ ret = -EPROTO; ++ goto proto_err; ++ } ++ XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n", ++ count_units, rev); ++ if (xbus_check_unique(xbus)) ++ return -EBUSY; ++ xbus->revision = rev; ++ worker = &xbus->worker; ++ if (!worker->wq) { ++ XBUS_ERR(xbus, "missing worker thread\n"); ++ ret = -ENODEV; ++ goto out; ++ } ++ for (i = 0; i < count_units; i++) { ++ struct unit_descriptor *this_unit = &units[i]; ++ struct card_desc_struct *card_desc; ++ unsigned long flags; ++ ++ if ((card_desc = ++ KZALLOC(sizeof(struct card_desc_struct), ++ GFP_ATOMIC)) == NULL) { ++ XBUS_ERR(xbus, "Card description allocation failed.\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ card_desc->magic = CARD_DESC_MAGIC; ++ INIT_LIST_HEAD(&card_desc->card_list); ++ card_desc->unit_descriptor = *this_unit; ++ XBUS_INFO(xbus, ++ " CARD %d type=%d.%d ports=(%dx%d), " ++ "port-dir=0x%02X\n", ++ this_unit->addr.unit, this_unit->type, ++ this_unit->subtype, ++ this_unit->numchips, this_unit->ports_per_chip, ++ this_unit->port_dir); ++ spin_lock_irqsave(&worker->worker_lock, flags); ++ worker->num_units++; ++ XBUS_COUNTER(xbus, UNITS)++; ++ list_add_tail(&card_desc->card_list, &worker->card_list); ++ spin_unlock_irqrestore(&worker->worker_lock, flags); ++ } ++ CALL_PROTO(GLOBAL, RESET_SPI, xbus, NULL); ++ if (!xbus_process_worker(xbus)) { ++ ret = -ENODEV; ++ goto out; ++ } ++ goto out; ++proto_err: ++ xbus_setstate(xbus, XBUS_STATE_FAIL); ++ dump_packet("AB_DESCRIPTION", pack, DBG_ANY); ++out: ++ return ret; ++} ++ ++HANDLER_DEF(GLOBAL, REGISTER_REPLY) ++{ ++ reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd); ++ ++ if (!xpd) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) < 5) ++ notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), ""); ++ return -EPROTO; ++ } ++ if (debug & DBG_REGS) { ++ dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum, ++ reg); ++ dump_packet("REG_REPLY", pack, 1); ++ } ++ if (!XMETHOD(card_register_reply, xpd)) { ++ XPD_ERR(xpd, ++ "REGISTER_REPLY: missing card_register_reply()\n"); ++ return -EINVAL; ++ } ++ return CALL_XMETHOD(card_register_reply, xpd, reg); ++} ++ ++HANDLER_DEF(GLOBAL, SYNC_REPLY) ++{ ++ __u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode); ++ __u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift); ++ const char *mode_name; ++ ++ BUG_ON(!xbus); ++ if ((mode_name = sync_mode_name(mode)) == NULL) { ++ XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode); ++ return -EINVAL; ++ } ++ XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift); ++ //dump_packet("SYNC_REPLY", pack, debug & DBG_SYNC); ++ got_new_syncer(xbus, mode, drift); ++ return 0; ++} ++ ++#define TMP_NAME_LEN (XBUS_NAMELEN + XPD_NAMELEN + 5) ++ ++HANDLER_DEF(GLOBAL, ERROR_CODE) ++{ ++ char tmp_name[TMP_NAME_LEN]; ++ static long rate_limit; ++ __u8 category_code; ++ __u8 errorbits; ++ ++ BUG_ON(!xbus); ++ if ((rate_limit++ % 5003) > 200) ++ return 0; ++ category_code = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, category_code); ++ errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits); ++ if (!xpd) { ++ snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname, ++ XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); ++ } else { ++ snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, ++ xpd->xpdname); ++ } ++ NOTICE ++ ("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n", ++ tmp_name, cmd->name, category_code, errorbits, rate_limit); ++ dump_packet("FIRMWARE: ", pack, 1); ++ /* ++ * FIXME: Should implement an error recovery plan ++ */ ++ return 0; ++} ++ ++xproto_table_t PROTO_TABLE(GLOBAL) = { ++ .entries = { ++ /* Prototable Card Opcode */ ++ XENTRY( GLOBAL, GLOBAL, NULL_REPLY ), ++ XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ), ++ XENTRY( GLOBAL, GLOBAL, SYNC_REPLY ), ++ XENTRY( GLOBAL, GLOBAL, ERROR_CODE ), ++ XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ), ++ }, ++ .name = "GLOBAL", ++ .packet_is_valid = global_packet_is_valid, ++ .packet_dump = global_packet_dump, ++}; ++ ++static bool global_packet_is_valid(xpacket_t *pack) ++{ ++ const xproto_entry_t *xe; ++ ++ //DBG(GENERAL, "\n"); ++ xe = xproto_global_entry(XPACKET_OP(pack)); ++ return xe != NULL; ++} ++ ++static void global_packet_dump(const char *msg, xpacket_t *pack) ++{ ++ DBG(GENERAL, "%s\n", msg); ++} ++ ++#define MAX_PATH_STR 128 ++ ++#ifndef UMH_WAIT_PROC ++/* ++ * - UMH_WAIT_PROC was introduced as enum in 2.6.23 ++ * with a value of 1 ++ * - It was changed to a macro (and it's value was modified) in 3.3.0 ++ */ ++#define UMH_WAIT_PROC 1 ++#endif ++ ++int run_initialize_registers(xpd_t *xpd) ++{ ++ int ret; ++ xbus_t *xbus; ++ char busstr[MAX_ENV_STR]; ++ char busnumstr[MAX_ENV_STR]; ++ char modelstr[MAX_ENV_STR]; ++ char unitstr[MAX_ENV_STR]; ++ char subunitsstr[MAX_ENV_STR]; ++ char typestr[MAX_ENV_STR]; ++ char directionstr[MAX_ENV_STR]; ++ char revstr[MAX_ENV_STR]; ++ char connectorstr[MAX_ENV_STR]; ++ char xbuslabel[MAX_ENV_STR]; ++ char init_card[MAX_PATH_STR]; ++ __u8 direction_mask; ++ __u8 hw_type = XPD_HW(xpd).type; ++ int i; ++ char *argv[] = { ++ init_card, ++ NULL ++ }; ++ char *envp[] = { ++ busstr, ++ busnumstr, ++ modelstr, ++ unitstr, ++ subunitsstr, ++ typestr, ++ directionstr, ++ revstr, ++ connectorstr, ++ xbuslabel, ++ NULL ++ }; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ if (!initdir || !initdir[0]) { ++ XPD_NOTICE(xpd, "Missing initdir parameter\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ if (!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) { ++ ret = -EINVAL; ++ goto err; ++ } ++ direction_mask = 0; ++ for (i = 0; i < xpd->subunits; i++) { ++ xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i); ++ ++ if (!su) { ++ XPD_ERR(xpd, "Have %d subunits, but not subunit #%d\n", ++ xpd->subunits, i); ++ continue; ++ } ++ direction_mask |= ++ (PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0; ++ } ++ snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname); ++ snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num); ++ snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s", ++ xbus->transport.model_string); ++ snprintf(typestr, MAX_ENV_STR, "HW_TYPE=%d", hw_type); ++ snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit); ++ snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->xpd_type); ++ snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits); ++ snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d", ++ direction_mask); ++ snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision); ++ snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", ++ xbus->connector); ++ snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label); ++ if (snprintf ++ (init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, hw_type, ++ xbus->revision) > MAX_PATH_STR) { ++ XPD_NOTICE(xpd, ++ "Cannot initialize. pathname is longer " ++ "than %d characters.\n", ++ MAX_PATH_STR); ++ ret = -E2BIG; ++ goto err; ++ } ++ if (!XBUS_IS(xbus, RECVD_DESC)) { ++ XBUS_ERR(xbus, ++ "Skipped register initialization. In state %s.\n", ++ xbus_statename(XBUS_STATE(xbus))); ++ ret = -ENODEV; ++ goto err; ++ } ++ XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n", ++ init_card, xpd->xpd_type, xbus->revision); ++ ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC); ++ /* ++ * Carefully report results ++ */ ++ if (ret == 0) ++ XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card); ++ else if (ret < 0) { ++ XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card, ++ ret); ++ } else { ++ __u8 exitval = ((unsigned)ret >> 8) & 0xFF; ++ __u8 sigval = ret & 0xFF; ++ ++ if (!exitval) { ++ XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card, ++ sigval); ++ } else { ++ XPD_ERR(xpd, "'%s' aborted with exitval %d\n", ++ init_card, exitval); ++ } ++ ret = -EINVAL; ++ } ++err: ++ return ret; ++} ++EXPORT_SYMBOL(run_initialize_registers); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_global.h linux-source-4.19-dahdi/drivers/dahdi/xpp/card_global.h +--- linux-source-4.19/drivers/dahdi/xpp/card_global.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_global.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,94 @@ ++#ifndef CARD_GLOBAL_H ++#define CARD_GLOBAL_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xdefs.h" ++#include "xbus-pcm.h" ++ ++enum global_opcodes { ++ XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07, ++ XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08, ++ XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F, ++ XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10, ++ /**/ XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11, ++ XPROTO_NAME(GLOBAL, PCM_READ) = 0x12, ++ /**/ XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19, ++ XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A, ++ /**/ XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22, ++ XPROTO_NAME(GLOBAL, XBUS_RESET) = 0x23, ++ XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE, ++}; ++ ++struct unit_descriptor { ++ struct xpd_addr addr; ++ __u8 subtype:4; ++ __u8 type:4; ++ __u8 numchips; ++ __u8 ports_per_chip; ++ __u8 port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */ ++ __u8 reserved[2]; ++ struct xpd_addr ec_addr; ++}; ++ ++#define NUM_UNITS 6 ++ ++DEF_RPACKET_DATA(GLOBAL, NULL_REPLY); ++DEF_RPACKET_DATA(GLOBAL, AB_REQUEST, __u8 rev; __u8 reserved;); ++DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION, __u8 rev; __u8 reserved[3]; ++ struct unit_descriptor unit_descriptor[NUM_UNITS];); ++DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, reg_cmd_t reg_cmd;); ++DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];); ++DEF_RPACKET_DATA(GLOBAL, PCM_READ, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];); ++DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, __u8 sync_mode; __u8 drift;); ++DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, __u8 sync_mode; __u8 drift;); ++DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, reg_cmd_t regcmd;); ++DEF_RPACKET_DATA(GLOBAL, XBUS_RESET, __u8 mask;); ++DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits; ++ __u8 bad_packet[0];); ++ ++/* 0x07 */ DECLARE_CMD(GLOBAL, AB_REQUEST); ++/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift); ++/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SPI); ++/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS); ++ ++int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, ++ bool writing, __u8 regnum, bool do_subreg, __u8 subreg, ++ __u8 data_low, bool do_datah, __u8 data_high, ++ bool should_reply, bool do_expander); ++int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno, ++ bool eoftx, __u8 *buf, unsigned len); ++int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, ++ bool writing, ++ __u8 addr_low, ++ __u8 addr_high, ++ __u8 data_0, ++ __u8 data_1, ++ __u8 data_2, ++ __u8 data_3, ++ bool should_reply); ++extern xproto_table_t PROTO_TABLE(GLOBAL); ++int run_initialize_registers(xpd_t *xpd); ++int parse_chip_command(xpd_t *xpd, char *cmdline); ++extern charp initdir; ++ ++#endif /* CARD_GLOBAL_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_pri.c linux-source-4.19-dahdi/drivers/dahdi/xpp/card_pri.c +--- linux-source-4.19/drivers/dahdi/xpp/card_pri.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_pri.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,2770 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * Parts derived from Cologne demo driver for the chip. ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++#include "xproto.h" ++#include "xpp_dahdi.h" ++#include "card_pri.h" ++#include "dahdi_debug.h" ++#include "xbus-core.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++/* must be before dahdi_debug.h */ ++static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++static DEF_PARM(uint, poll_interval, 500, 0644, ++ "Poll channel state interval in milliseconds (0 - disable)"); ++ ++#define PRI_LINES_BITMASK BITMASK(31) ++#define PRI_SIGCAP ( \ ++ DAHDI_SIG_EM | \ ++ DAHDI_SIG_CLEAR | \ ++ DAHDI_SIG_FXSLS | \ ++ DAHDI_SIG_FXSGS | \ ++ DAHDI_SIG_FXSKS | \ ++ DAHDI_SIG_HARDHDLC | \ ++ DAHDI_SIG_MTP2 | \ ++ DAHDI_SIG_FXOLS | \ ++ DAHDI_SIG_FXOGS | \ ++ DAHDI_SIG_FXOKS | \ ++ DAHDI_SIG_CAS | \ ++ DAHDI_SIG_EM_E1 | \ ++ DAHDI_SIG_DACS_RBS \ ++ ) ++ ++static bool is_sigtype_dchan(int sigtype) ++{ ++ if ((sigtype & DAHDI_SIG_HDLCRAW) == DAHDI_SIG_HDLCRAW) ++ return 1; ++ if ((sigtype & DAHDI_SIG_HDLCFCS) == DAHDI_SIG_HDLCFCS) ++ return 1; ++ if ((sigtype & DAHDI_SIG_HARDHDLC) == DAHDI_SIG_HARDHDLC) ++ return 1; ++ return 0; ++} ++ ++#define MAX_SLAVES 4 /* we have MUX of 4 clocks */ ++ ++#define PRI_PORT(xpd) ((xpd)->addr.subunit) ++#define CHAN_PER_REGS(p) (((p)->is_esf) ? 2 : 4) ++ ++/*---------------- PRI Protocol Commands ----------------------------------*/ ++ ++static void dchan_state(xpd_t *xpd, bool up); ++static bool pri_packet_is_valid(xpacket_t *pack); ++static void pri_packet_dump(const char *msg, xpacket_t *pack); ++static int pri_startup(struct file *file, struct dahdi_span *span); ++static int pri_shutdown(struct dahdi_span *span); ++static int pri_rbsbits(struct dahdi_chan *chan, int bits); ++static int pri_lineconfig(xpd_t *xpd, int lineconfig); ++static void send_idlebits(xpd_t *xpd, bool saveold); ++static int apply_pri_protocol(xpd_t *xpd); ++ ++enum pri_protocol { ++ PRI_PROTO_0 = 0, ++ PRI_PROTO_E1 = 1, ++ PRI_PROTO_T1 = 2, ++ PRI_PROTO_J1 = 3 ++}; ++ ++static const char *protocol_names[] = { ++ [PRI_PROTO_0] = "??", /* unknown */ ++ [PRI_PROTO_E1] = "E1", ++ [PRI_PROTO_T1] = "T1", ++ [PRI_PROTO_J1] = "J1" ++}; ++ ++static enum spantypes pri_protocol2spantype(enum pri_protocol pri_protocol) ++{ ++ switch (pri_protocol) { ++ case PRI_PROTO_E1: return SPANTYPE_DIGITAL_E1; ++ case PRI_PROTO_T1: return SPANTYPE_DIGITAL_T1; ++ case PRI_PROTO_J1: return SPANTYPE_DIGITAL_J1; ++ default: ++ return SPANTYPE_INVALID; ++ } ++} ++ ++static const char *pri_protocol_name(enum pri_protocol pri_protocol) ++{ ++ return protocol_names[pri_protocol]; ++} ++ ++static int pri_num_channels(enum pri_protocol pri_protocol) ++{ ++ static int num_channels[] = { ++ [PRI_PROTO_0] = 0, ++ [PRI_PROTO_E1] = 31, ++ [PRI_PROTO_T1] = 24, ++ [PRI_PROTO_J1] = 0 ++ }; ++ return num_channels[pri_protocol]; ++} ++ ++static const char *type_name(enum pri_protocol pri_protocol) ++{ ++ static const char *names[4] = { ++ [PRI_PROTO_0] = "PRI-Unknown", ++ [PRI_PROTO_E1] = "E1", ++ [PRI_PROTO_T1] = "T1", ++ [PRI_PROTO_J1] = "J1" ++ }; ++ ++ return names[pri_protocol]; ++} ++ ++static int pri_linecompat(enum pri_protocol pri_protocol) ++{ ++ static const int linecompat[] = { ++ [PRI_PROTO_0] = 0, ++ [PRI_PROTO_E1] = ++ /* coding */ ++ DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4 | ++ /* framing */ ++ DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3, ++ [PRI_PROTO_T1] = ++ /* coding */ ++ DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF | ++ /* framing */ ++ DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS, ++ [PRI_PROTO_J1] = 0 ++ }; ++ ++ DBG(GENERAL, "pri_linecompat: pri_protocol=%d\n", pri_protocol); ++ return linecompat[pri_protocol]; ++} ++ ++#define PRI_DCHAN_IDX(priv) ((priv)->dchan_num - 1) ++ ++enum pri_led_state { ++ PRI_LED_OFF = 0x0, ++ PRI_LED_ON = 0x1, ++ /* ++ * We blink by software from driver, so that ++ * if the driver malfunction that blink would stop. ++ */ ++ // PRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ ++ // PRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ ++}; ++ ++enum pri_led_selectors { ++ BOTTOM_RED_LED = 0, ++ BOTTOM_GREEN_LED = 1, ++ TOP_RED_LED = 2, ++ TOP_GREEN_LED = 3, ++}; ++ ++#define NUM_LEDS 4 ++ ++struct pri_leds { ++ __u8 state:2; /* enum pri_led_state */ ++ __u8 led_sel:2; /* enum pri_led_selectors */ ++ __u8 reserved:4; ++}; ++ ++#define REG_CCB1_T 0x2F /* Clear Channel Register 1 */ ++ ++#define REG_FRS0 0x4C /* Framer Receive Status Register 0 */ ++#define REG_FRS0_T1_FSR BIT(0) /* T1 - Frame Search Restart Flag */ ++#define REG_FRS0_LMFA BIT(1) /* Loss of Multiframe Alignment */ ++#define REG_FRS0_E1_NMF BIT(2) /* E1 - No Multiframe Alignment Found */ ++#define REG_FRS0_RRA BIT(4) /* Receive Remote Alarm: T1-YELLOW-Alarm */ ++#define REG_FRS0_LFA BIT(5) /* Loss of Frame Alignment */ ++#define REG_FRS0_AIS BIT(6) /* Alarm Indication Signal: T1-BLUE-Alarm */ ++#define REG_FRS0_LOS BIT(7) /* Los Of Signal: T1-RED-Alarm */ ++ ++#define REG_FRS1 0x4D /* Framer Receive Status Register 1 */ ++ ++#define REG_LIM0 0x36 ++/* ++ * Master Mode, DCO-R circuitry is frequency synchronized ++ * to the clock supplied by SYNC ++ */ ++#define REG_LIM0_MAS BIT(0) ++/* ++ * Receive Termination Resistance Selection: ++ * integrated resistor to create 75 Ohm termination (100 || 300 = 75) ++ * 0 = 100 Ohm ++ * 1 = 75 Ohm ++ */ ++#define REG_LIM0_RTRS BIT(5) ++#define REG_LIM0_LL BIT(1) /* LL (Local Loopback) */ ++ ++#define REG_FMR0 0x1C ++#define REG_FMR0_E_RC0 BIT(4) /* Receive Code - LSB */ ++#define REG_FMR0_E_RC1 BIT(5) /* Receive Code - MSB */ ++#define REG_FMR0_E_XC0 BIT(6) /* Transmit Code - LSB */ ++#define REG_FMR0_E_XC1 BIT(7) /* Transmit Code - MSB */ ++ ++#define REG_FMR1 0x1D ++#define REG_FMR1_XAIS BIT(0) /* Transmit AIS toward transmit end */ ++#define REG_FMR1_SSD0 BIT(1) ++#define REG_FMR1_ECM BIT(2) ++#define REG_FMR1_T_CRC BIT(3) /* Enable CRC6 */ ++#define REG_FMR1_E_XFS BIT(3) /* Transmit Framing Select */ ++#define REG_FMR1_PMOD BIT(4) /* E1 = 0, T1/J1 = 1 */ ++#define REG_FMR1_EDL BIT(5) ++#define REG_FMR1_AFR BIT(6) ++ ++#define REG_FMR2 0x1E ++#define REG_FMR2_E_ALMF BIT(0) /* Automatic Loss of Multiframe */ ++#define REG_FMR2_T_EXZE BIT(0) /* Excessive Zeros Detection Enable */ ++#define REG_FMR2_E_AXRA BIT(1) /* Automatic Transmit Remote Alarm */ ++#define REG_FMR2_T_AXRA BIT(1) /* Automatic Transmit Remote Alarm */ ++#define REG_FMR2_E_PLB BIT(2) /* Payload Loop-Back */ ++#define REG_FMR2_E_RFS0 BIT(6) /* Receive Framing Select - LSB */ ++#define REG_FMR2_E_RFS1 BIT(7) /* Receive Framing Select - MSB */ ++/* Select Synchronization/Resynchronization Procedure */ ++#define REG_FMR2_T_SSP BIT(5) ++/* Multiple Candidates Synchronization Procedure */ ++#define REG_FMR2_T_MCSP BIT(6) ++/* Automatic Force Resynchronization */ ++#define REG_FMR2_T_AFRS BIT(7) ++ ++#define REG_FMR3 0x31 ++#define REG_FMR3_EXTIW BIT(0) /* Extended CRC4 to Non-CRC4 Interworking */ ++ ++#define REG_FMR4 0x20 ++#define REG_FMR4_FM0 BIT(0) ++#define REG_FMR4_FM1 BIT(1) ++#define REG_FMR4_AUTO BIT(2) ++#define REG_FMR4_SSC0 BIT(3) ++#define REG_FMR4_SSC1 BIT(4) ++#define REG_FMR4_XRA BIT(5) /* Transmit Remote Alarm (Yellow Alarm) */ ++#define REG_FMR4_TM BIT(6) ++#define REG_FMR4_AIS3 BIT(7) ++ ++#define REG_XSW_E 0x20 ++#define REG_XSW_E_XY4 BIT(0) ++#define REG_XSW_E_XY3 BIT(1) ++#define REG_XSW_E_XY2 BIT(2) ++#define REG_XSW_E_XY1 BIT(3) ++#define REG_XSW_E_XY0 BIT(4) ++#define REG_XSW_E_XRA BIT(5) /* Transmit Remote Alarm (Yellow Alarm) */ ++#define REG_XSW_E_XTM BIT(6) ++#define REG_XSW_E_XSIS BIT(7) ++ ++#define REG_XSP_E 0x21 ++#define REG_FMR5_T 0x21 ++/* Transmit Spare Bit For International Use (FAS Word) */ ++#define REG_XSP_E_XSIF BIT(2) ++#define REG_FMR5_T_XTM BIT(2) /* Transmit Transparent Mode */ ++/* Automatic Transmission of Submultiframe Status */ ++#define REG_XSP_E_AXS BIT(3) ++/* E-Bit Polarity, Si-bit position of every outgoing CRC multiframe */ ++#define REG_XSP_E_EBP BIT(4) ++#define REG_XSP_E_CASEN BIT(6) /* CAS: Channel Associated Signaling Enable */ ++#define REG_FMR5_T_EIBR BIT(6) /* CAS: Enable Internal Bit Robbing Access */ ++ ++#define REG_XC0_T 0x22 /* Transmit Control 0 */ ++#define REG_XC0_BRIF BIT(5) /* Bit Robbing Idle Function */ ++ ++#define REG_CMDR_E 0x02 /* Command Register */ ++#define REG_CMDR_RRES BIT(6) /* Receiver reset */ ++#define REG_CMDR_XRES BIT(4) /* Transmitter reset */ ++ ++#define REG_RC0 0x24 ++#define REG_RC0_SJR BIT(7) /* T1 = 0, J1 = 1 */ ++ ++#define REG_CMR1 0x44 ++#define REG_CMR1_DRSS (BIT(7) | BIT(6)) ++#define REG_CMR1_RS (BIT(5) | BIT(4)) ++#define REG_CMR1_STF BIT(2) ++ ++#define REG_RS1_E 0x70 /* Receive CAS Register 1 */ ++#define REG_RS2_E 0x71 /* Receive CAS Register 2 */ ++#define REG_RS3_E 0x72 /* Receive CAS Register 3 */ ++#define REG_RS4_E 0x73 /* Receive CAS Register 4 */ ++#define REG_RS5_E 0x74 /* Receive CAS Register 5 */ ++#define REG_RS6_E 0x75 /* Receive CAS Register 6 */ ++#define REG_RS7_E 0x76 /* Receive CAS Register 7 */ ++#define REG_RS8_E 0x77 /* Receive CAS Register 8 */ ++#define REG_RS9_E 0x78 /* Receive CAS Register 9 */ ++#define REG_RS10_E 0x79 /* Receive CAS Register 10 */ ++#define REG_RS11_E 0x7A /* Receive CAS Register 11 */ ++#define REG_RS12_E 0x7B /* Receive CAS Register 12 */ ++#define REG_RS13_E 0x7C /* Receive CAS Register 13 */ ++#define REG_RS14_E 0x7D /* Receive CAS Register 14 */ ++#define REG_RS15_E 0x7E /* Receive CAS Register 15 */ ++#define REG_RS16_E 0x7F /* Receive CAS Register 16 */ ++ ++#define REG_PC2 0x81 /* Port Configuration 2 */ ++#define REG_PC3 0x82 /* Port Configuration 3 */ ++#define REG_PC4 0x83 /* Port Configuration 4 */ ++ ++#define REG_XPM2 0x28 /* Transmit Pulse Mask 2 */ ++ ++#define VAL_PC_SYPR 0x00 /* Synchronous Pulse Receive (Input, low active) */ ++#define VAL_PC_GPI 0x90 /* General purpose input */ ++#define VAL_PC_GPOH 0x0A /* General Purpose Output, high level */ ++#define VAL_PC_GPOL 0x0B /* General Purpose Output, low level */ ++ ++#define NUM_CAS_RS_E (REG_RS16_E - REG_RS2_E + 1) ++/* and of those, the ones used in T1: */ ++#define NUM_CAS_RS_T (REG_RS12_E - REG_RS1_E + 1) ++ ++struct PRI_priv_data { ++ bool clock_source; ++ enum pri_protocol pri_protocol; ++ xpp_line_t rbslines; ++ int deflaw; ++ unsigned int dchan_num; ++ bool initialized; ++ bool dchan_is_open; ++ int is_cas; ++ ++ unsigned int chanconfig_dchan; ++#define NO_DCHAN (0) ++#define DCHAN(p) ((p)->chanconfig_dchan) ++#define VALID_DCHAN(p) (DCHAN(p) != NO_DCHAN) ++#define SET_DCHAN(p, d) do { DCHAN(p) = (d); } while (0); ++ ++ __u8 cas_rs_e[NUM_CAS_RS_E]; ++ __u8 cas_ts_e[NUM_CAS_RS_E]; ++ uint cas_replies; ++ bool is_esf; ++ bool local_loopback; ++ uint poll_noreplies; ++ uint layer1_replies; ++ __u8 reg_frs0; ++ __u8 reg_frs1; ++ bool layer1_up; ++ int alarms; ++ __u8 dchan_tx_sample; ++ __u8 dchan_rx_sample; ++ uint dchan_tx_counter; ++ uint dchan_rx_counter; ++ bool dchan_alive; ++ uint dchan_alive_ticks; ++ enum pri_led_state ledstate[NUM_LEDS]; ++}; ++ ++static xproto_table_t PROTO_TABLE(PRI); ++ ++DEF_RPACKET_DATA(PRI, SET_LED, /* Set one of the LED's */ ++ struct pri_leds pri_leds;); ++ ++static /* 0x33 */ DECLARE_CMD(PRI, SET_LED, enum pri_led_selectors led_sel, ++ enum pri_led_state to_led_state); ++ ++#define DO_LED(xpd, which, tostate) \ ++ CALL_PROTO(PRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate)) ++ ++/*---------------- PRI: Methods -------------------------------------------*/ ++ ++static int query_subunit(xpd_t *xpd, __u8 regnum) ++{ ++ XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X\n", xpd->addr.unit, ++ xpd->addr.subunit, regnum); ++ return xpp_register_request(xpd->xbus, xpd, PRI_PORT(xpd), /* portno */ ++ 0, /* writing */ ++ regnum, 0, /* do_subreg */ ++ 0, /* subreg */ ++ 0, /* data_L */ ++ 0, /* do_datah */ ++ 0, /* data_H */ ++ 0, /* should_reply */ ++ 0 /* do_expander */ ++ ); ++} ++ ++static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val) ++{ ++ XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n", xpd->addr.unit, ++ xpd->addr.subunit, regnum, val); ++ return xpp_register_request(xpd->xbus, xpd, ++ PRI_PORT(xpd), /* portno */ ++ 1, /* writing */ ++ regnum, 0, /* do_subreg */ ++ 0, /* subreg */ ++ val, /* data_L */ ++ 0, /* do_datah */ ++ 0, /* data_H */ ++ 0, /* should_reply */ ++ 0 /* do_expander */ ++ ); ++} ++ ++static int pri_write_reg(xpd_t *xpd, int regnum, __u8 val) ++{ ++ XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n", xpd->addr.unit, ++ xpd->addr.subunit, regnum, val); ++ return xpp_register_request(xpd->xbus, xpd, 0, /* portno=0 */ ++ 1, /* writing */ ++ regnum, 0, /* do_subreg */ ++ 0, /* subreg */ ++ val, /* data_L */ ++ 0, /* do_datah */ ++ 0, /* data_H */ ++ 0, /* should_reply */ ++ 0 /* do_expander */ ++ ); ++} ++ ++static int cas_regbase(xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ switch (priv->pri_protocol) { ++ case PRI_PROTO_E1: ++ return REG_RS2_E; ++ case PRI_PROTO_T1: ++ /* fall-through */ ++ case PRI_PROTO_J1: ++ return REG_RS1_E; ++ case PRI_PROTO_0: ++ /* fall-through */ ++ ; ++ } ++ BUG(); ++ return 0; ++} ++ ++static int cas_numregs(xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ switch (priv->pri_protocol) { ++ case PRI_PROTO_E1: ++ return NUM_CAS_RS_E; ++ case PRI_PROTO_T1: ++ /* fall-through */ ++ case PRI_PROTO_J1: ++ return NUM_CAS_RS_T; ++ case PRI_PROTO_0: ++ /* fall-through */ ++ ; ++ } ++ BUG(); ++ return 0; ++} ++ ++static int write_cas_reg(xpd_t *xpd, int rsnum, __u8 val) ++{ ++ struct PRI_priv_data *priv; ++ int regbase = cas_regbase(xpd); ++ int num_cas_rs = cas_numregs(xpd); ++ int regnum; ++ bool is_d4 = 0; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ if ((priv->pri_protocol == PRI_PROTO_T1) && !priv->is_esf) { ++ /* same data should be copied to RS7..12 in D4 only */ ++ is_d4 = 1; ++ } ++ if (rsnum < 0 || rsnum >= num_cas_rs) { ++ XPD_ERR(xpd, "RBS(TX): rsnum=%d\n", rsnum); ++ BUG(); ++ } ++ regnum = regbase + rsnum; ++ priv->cas_ts_e[rsnum] = val; ++ XPD_DBG(SIGNAL, xpd, "RBS(TX): reg=0x%X val=0x%02X\n", regnum, val); ++ write_subunit(xpd, regbase + rsnum, val); ++ if (is_d4) { ++ /* same data should be copied to RS7..12 in D4 only */ ++ regnum = REG_RS7_E + rsnum; ++ XPD_DBG(SIGNAL, xpd, "RBS(TX): reg=0x%X val=0x%02X\n", regnum, ++ val); ++ write_subunit(xpd, regnum, val); ++ } ++ return 0; ++} ++ ++static bool valid_pri_modes(const xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ if (priv->pri_protocol != PRI_PROTO_E1 ++ && priv->pri_protocol != PRI_PROTO_T1 ++ && priv->pri_protocol != PRI_PROTO_J1) ++ return 0; ++ return 1; ++} ++ ++static void PRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask) ++{ ++ struct PRI_priv_data *priv; ++ int i; ++ int line_count = 0; ++ unsigned long flags; ++ uint pcm_len; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ spin_lock_irqsave(&PHONEDEV(xpd).lock_recompute_pcm, flags); ++ //XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask); ++ /* Add/remove all the trivial cases */ ++ pcm_mask |= PHONEDEV(xpd).offhook_state; ++ if (priv->is_cas) ++ pcm_mask |= BITMASK(PHONEDEV(xpd).channels); ++ for_each_line(xpd, i) ++ if (IS_SET(pcm_mask, i)) ++ line_count++; ++ else ++ if (priv->is_cas) { ++ if (priv->pri_protocol == PRI_PROTO_E1) { ++ /* CAS: Don't send PCM to D-Channel */ ++ line_count--; ++ pcm_mask &= ~BIT(PRI_DCHAN_IDX(priv)); ++ } ++ } ++ /* ++ * FIXME: Workaround a bug in sync code of the Astribank. ++ * Send dummy PCM for sync. ++ */ ++ if (xpd->addr.unit == 0 && pcm_mask == 0) { ++ pcm_mask = BIT(0); ++ line_count = 1; ++ } ++ pcm_len = (line_count) ++ ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + ++ line_count * DAHDI_CHUNKSIZE : 0L; ++ update_wanted_pcm_mask(xpd, pcm_mask, pcm_len); ++ spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags); ++} ++ ++/* ++ * Set E1/T1/J1 ++ * May only be called on unregistered xpd's ++ * (the span and channel description are set according to this) ++ */ ++static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto) ++{ ++ struct PRI_priv_data *priv; ++ int deflaw; ++ unsigned int dchan_num; ++ int default_lineconfig = 0; ++ int ret; ++ struct phonedev *phonedev; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ phonedev = &PHONEDEV(xpd); ++ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &phonedev->span.flags)) { ++ XPD_NOTICE(xpd, "%s: %s already assigned as span %d\n", ++ __func__, phonedev->span.name, ++ phonedev->span.spanno); ++ return -EBUSY; ++ } ++ if (priv->pri_protocol != PRI_PROTO_0) { ++ if (priv->pri_protocol == set_proto) { ++ XPD_NOTICE(xpd, "Already in protocol %s. Ignored\n", ++ pri_protocol_name(set_proto)); ++ return 0; ++ } else { ++ XPD_INFO(xpd, "Switching from %s to %s\n", ++ pri_protocol_name(priv->pri_protocol), ++ pri_protocol_name(set_proto)); ++ } ++ } ++ switch (set_proto) { ++ case PRI_PROTO_E1: ++ deflaw = DAHDI_LAW_ALAW; ++ dchan_num = 16; ++ default_lineconfig = ++ DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_HDB3; ++ break; ++ case PRI_PROTO_T1: ++ deflaw = DAHDI_LAW_MULAW; ++ dchan_num = 24; ++ default_lineconfig = DAHDI_CONFIG_ESF | DAHDI_CONFIG_B8ZS; ++ break; ++ case PRI_PROTO_J1: ++ /* ++ * Check all assumptions ++ */ ++ deflaw = DAHDI_LAW_MULAW; ++ dchan_num = 24; ++ default_lineconfig = 0; /* FIXME: J1??? */ ++ XPD_NOTICE(xpd, "J1 is not supported yet\n"); ++ return -ENOSYS; ++ default: ++ XPD_ERR(xpd, "%s: Unknown pri protocol = %d\n", __func__, ++ set_proto); ++ return -EINVAL; ++ } ++ priv->pri_protocol = set_proto; ++ priv->is_cas = -1; ++ phonedev_alloc_channels(xpd, pri_num_channels(set_proto)); ++ phonedev->offhook_state = BITMASK(phonedev->channels); ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ priv->deflaw = deflaw; ++ priv->dchan_num = dchan_num; ++ priv->local_loopback = 0; ++ xpd->type_name = type_name(priv->pri_protocol); ++ XPD_DBG(GENERAL, xpd, "%s, channels=%d, dchan_num=%d, deflaw=%d\n", ++ pri_protocol_name(set_proto), phonedev->channels, ++ priv->dchan_num, priv->deflaw); ++ /* ++ * Must set default now, so layer1 polling (Register REG_FRS0) would ++ * give reliable results. ++ */ ++ ret = pri_lineconfig(xpd, default_lineconfig); ++ if (ret) { ++ XPD_NOTICE(xpd, "Failed setting PRI default line config\n"); ++ return ret; ++ } ++ return apply_pri_protocol(xpd); ++} ++ ++static void dahdi_update_syncsrc(xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ xpd_t *subxpd; ++ int best_spanno = 0; ++ int i; ++ ++ if (!SPAN_REGISTERED(xpd)) ++ return; ++ for (i = 0; i < MAX_SLAVES; i++) { ++ subxpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, i); ++ if (!subxpd) ++ continue; ++ priv = subxpd->priv; ++ if (priv->clock_source && priv->alarms == 0) { ++ if (best_spanno) ++ XPD_ERR(xpd, ++ "Duplicate XPD with clock_source=1\n"); ++ best_spanno = PHONEDEV(subxpd).span.spanno; ++ } ++ } ++ for (i = 0; i < MAX_SLAVES; i++) { ++ subxpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, i); ++ if (!subxpd) ++ continue; ++ if (PHONEDEV(subxpd).span.syncsrc == best_spanno) ++ XPD_DBG(SYNC, xpd, "Setting SyncSource to span %d\n", ++ best_spanno); ++ else ++ XPD_DBG(SYNC, xpd, "Slaving to span %d\n", best_spanno); ++ PHONEDEV(subxpd).span.syncsrc = best_spanno; ++ } ++} ++ ++/* ++ * Called from: ++ * - set_master_mode() -- ++ * As a result of dahdi_cfg ++ * - layer1_state() -- ++ * As a result of an alarm. ++ */ ++static void set_clocking(xpd_t *xpd) ++{ ++ xbus_t *xbus; ++ xpd_t *best_xpd = NULL; ++ int best_subunit = -1; /* invalid */ ++ unsigned int best_subunit_prio = INT_MAX; ++ int i; ++ ++ xbus = xpd->xbus; ++ /* Find subunit with best timing priority */ ++ for (i = 0; i < MAX_SLAVES; i++) { ++ struct PRI_priv_data *priv; ++ xpd_t *subxpd; ++ ++ subxpd = xpd_byaddr(xbus, xpd->addr.unit, i); ++ if (!subxpd) ++ continue; ++ priv = subxpd->priv; ++ if (priv->alarms != 0) ++ continue; ++ if (PHONEDEV(subxpd).timing_priority > 0 ++ && PHONEDEV(subxpd).timing_priority < best_subunit_prio) { ++ best_xpd = subxpd; ++ best_subunit = i; ++ best_subunit_prio = PHONEDEV(subxpd).timing_priority; ++ } ++ } ++ /* Now set it */ ++ if (best_xpd ++ && ((struct PRI_priv_data *)(best_xpd->priv))->clock_source == 0) { ++ __u8 reg_pc_init[] = { VAL_PC_SYPR, VAL_PC_GPI, VAL_PC_GPI }; ++ ++ for (i = 0; i < ARRAY_SIZE(reg_pc_init); i++) { ++ __u8 reg_pc = reg_pc_init[i]; ++ ++ reg_pc |= ++ (best_subunit & (1 << i)) ? VAL_PC_GPOH : ++ VAL_PC_GPOL; ++ XPD_DBG(SYNC, best_xpd, ++ "ClockSource Set: PC%d=0x%02X\n", 2 + i, ++ reg_pc); ++ pri_write_reg(xpd, REG_PC2 + i, reg_pc); ++ } ++ ((struct PRI_priv_data *)(best_xpd->priv))->clock_source = 1; ++ } ++ /* clear old clock sources */ ++ for (i = 0; i < MAX_SLAVES; i++) { ++ struct PRI_priv_data *priv; ++ xpd_t *subxpd; ++ ++ subxpd = xpd_byaddr(xbus, xpd->addr.unit, i); ++ if (subxpd && subxpd != best_xpd) { ++ XPD_DBG(SYNC, subxpd, "Clearing clock source\n"); ++ priv = subxpd->priv; ++ priv->clock_source = 0; ++ } ++ } ++ dahdi_update_syncsrc(xpd); ++} ++ ++static void set_reg_lim0(const char *msg, xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ bool is_master_mode; ++ bool localloop; ++ __u8 lim0 = 0; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ is_master_mode = PHONEDEV(xpd).timing_priority == 0; ++ localloop = priv->local_loopback; ++ lim0 |= (localloop) ? REG_LIM0_LL : 0; ++ if (is_master_mode) ++ lim0 |= REG_LIM0_MAS; ++ else ++ lim0 &= ~REG_LIM0_MAS; ++ XPD_DBG(SIGNAL, xpd, "%s(%s): %s, %s\n", __func__, msg, ++ (is_master_mode) ? "MASTER" : "SLAVE", ++ (localloop) ? "LOCALLOOP" : "NO_LOCALLOOP"); ++ write_subunit(xpd, REG_LIM0, lim0); ++} ++ ++/* ++ * Normally set by the timing parameter in /etc/dahdi/system.conf ++ * If this is called by dahdi_cfg, than it's too late to change ++ * dahdi sync priority (we are already registered) ++ * ++ * Also called from set_localloop() ++ */ ++static int set_master_mode(const char *msg, xpd_t *xpd) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(SIGNAL, xpd, "\n"); ++ set_reg_lim0(__func__, xpd); ++ set_clocking(xpd); ++ return 0; ++} ++ ++static int set_localloop(xpd_t *xpd, bool localloop) ++{ ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ if (SPAN_REGISTERED(xpd)) { ++ XPD_NOTICE(xpd, "Registered as span %d. Cannot do %s\n", ++ PHONEDEV(xpd).span.spanno, __func__); ++ return -EBUSY; ++ } ++ priv->local_loopback = localloop; ++ XPD_DBG(SIGNAL, xpd, "%s: %s\n", __func__, ++ (localloop) ? "LOCALLOOP" : "NO"); ++ set_master_mode(__func__, xpd); ++ return 0; ++} ++ ++#define VALID_CONFIG(bit, flg, str) [bit] = { .flags = flg, .name = str } ++ ++static const struct { ++ const char *name; ++ const int flags; ++} valid_spanconfigs[sizeof(unsigned int) * 8] = { ++ /* These apply to T1 */ ++ VALID_CONFIG(4, DAHDI_CONFIG_D4, "D4"), ++ VALID_CONFIG(5, DAHDI_CONFIG_ESF, "ESF"), ++ VALID_CONFIG(6, DAHDI_CONFIG_AMI, "AMI"), ++ VALID_CONFIG(7, DAHDI_CONFIG_B8ZS, "B8ZS"), ++ /* These apply to E1 */ ++ VALID_CONFIG(8, DAHDI_CONFIG_CCS, "CCS"), ++ VALID_CONFIG(9, DAHDI_CONFIG_HDB3, "HDB3"), ++ VALID_CONFIG(10, DAHDI_CONFIG_CRC4, "CRC4"), ++}; ++ ++/* ++ * Mark the lines as CLEAR or RBS signalling. ++ * With T1, we need to mark the CLEAR lines on the REG_CCB1_T registers ++ * Should be called only when we are registered to DAHDI ++ * The channo parameter: ++ * channo == 0: set lines for the whole span ++ * channo != 0: only set modified lines ++ */ ++static void set_rbslines(xpd_t *xpd, int channo) ++{ ++ struct PRI_priv_data *priv; ++ xpp_line_t new_rbslines = 0; ++ xpp_line_t modified_lines; ++ int i; ++ ++ priv = xpd->priv; ++ for_each_line(xpd, i) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ ++ if (chan->flags & DAHDI_FLAG_CLEAR) ++ BIT_CLR(new_rbslines, i); ++ else ++ BIT_SET(new_rbslines, i); ++ } ++ new_rbslines &= BITMASK(PHONEDEV(xpd).channels); ++ modified_lines = priv->rbslines ^ new_rbslines; ++ XPD_DBG(DEVICES, xpd, "RBSLINES-%d(%s): 0x%X\n", channo, ++ pri_protocol_name(priv->pri_protocol), new_rbslines); ++ if ((priv->pri_protocol == PRI_PROTO_T1) ++ || (priv->pri_protocol == PRI_PROTO_J1)) { ++ __u8 clear_lines = 0; /* Mark clear lines */ ++ bool reg_changed = 0; ++ ++ for_each_line(xpd, i) { ++ int bytenum = i / 8; ++ int bitnum = i % 8; ++ ++ if (!IS_SET(new_rbslines, i)) ++ BIT_SET(clear_lines, (7 - bitnum)); ++ if (IS_SET(modified_lines, i)) ++ reg_changed = 1; ++ if (bitnum == 7) { ++ if (channo == 0 || reg_changed) { ++ bytenum += REG_CCB1_T; ++ XPD_DBG(DEVICES, xpd, ++ "RBS(%s): modified=0x%X rbslines=0x%X reg=0x%X clear_lines=0x%X\n", ++ pri_protocol_name(priv->pri_protocol), ++ modified_lines, new_rbslines, ++ bytenum, clear_lines); ++ write_subunit(xpd, bytenum, clear_lines); ++ } ++ clear_lines = 0; ++ reg_changed = 0; ++ } ++ } ++ } ++ priv->rbslines = new_rbslines; ++} ++ ++static int set_mode_cas(xpd_t *xpd, bool want_cas) ++{ ++ struct PRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ XPD_INFO(xpd, "Setting TDM to %s\n", (want_cas) ? "CAS" : "PRI"); ++ if (want_cas) { ++ priv->is_cas = 1; ++ priv->dchan_alive = 0; ++ } else { ++ priv->is_cas = 0; ++ } ++ return 0; ++} ++ ++static int pri_lineconfig(xpd_t *xpd, int lineconfig) ++{ ++ struct PRI_priv_data *priv; ++ const char *framingstr = ""; ++ const char *codingstr = ""; ++ const char *crcstr = ""; ++#ifdef JAPANEZE_SUPPORT ++ __u8 rc0 = 0; /* FIXME: PCM offsets */ ++#endif ++ __u8 fmr0 = 0; ++ __u8 fmr1 = REG_FMR1_ECM; ++ __u8 fmr2 = 0; ++ __u8 fmr3 = 0; /* write only for CRC4 */ ++ __u8 fmr4 = 0; ++ __u8 cmdr = REG_CMDR_RRES | REG_CMDR_XRES; ++ __u8 xsp = 0; ++ unsigned int bad_bits; ++ bool force_cas = 0; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ /* ++ * validate ++ */ ++ bad_bits = lineconfig & pri_linecompat(priv->pri_protocol); ++ bad_bits = bad_bits ^ lineconfig; ++ for (i = 0; i < ARRAY_SIZE(valid_spanconfigs); i++) { ++ unsigned int flags = valid_spanconfigs[i].flags; ++ ++ if (bad_bits & BIT(i)) { ++ if (flags) { ++ XPD_ERR(xpd, ++ "Bad config item '%s' for %s. Ignore\n", ++ valid_spanconfigs[i].name, ++ pri_protocol_name(priv->pri_protocol)); ++ } else { ++ /* we got real garbage */ ++ XPD_ERR(xpd, ++ "Unknown config item 0x%lX for %s. " ++ "Ignore.\n", ++ BIT(i), ++ pri_protocol_name(priv->pri_protocol)); ++ } ++ } ++ if (flags && flags != BIT(i)) { ++ ERR("%s: BUG: i=%d flags=0x%X\n", __func__, i, flags); ++ // BUG(); ++ } ++ } ++ if (bad_bits) ++ goto bad_lineconfig; ++ if (priv->pri_protocol == PRI_PROTO_E1) { ++ fmr1 |= REG_FMR1_AFR; ++ fmr2 = REG_FMR2_E_AXRA | REG_FMR2_E_ALMF; /* 0x03 */ ++ fmr4 = 0x9F; /* E1.XSW: All spare bits = 1 */ ++ xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; ++ } else if (priv->pri_protocol == PRI_PROTO_T1) { ++ fmr1 |= REG_FMR1_PMOD | REG_FMR1_T_CRC; ++ fmr2 = REG_FMR2_T_SSP | REG_FMR2_T_AXRA; /* 0x22 */ ++ fmr4 = 0x0C; ++ xsp &= ~REG_FMR5_T_XTM; ++ force_cas = 1; /* T1 - Chip always in CAS mode */ ++ } else if (priv->pri_protocol == PRI_PROTO_J1) { ++ fmr1 |= REG_FMR1_PMOD; ++ fmr4 = 0x1C; ++ xsp &= ~REG_FMR5_T_XTM; ++ force_cas = 1; /* T1 - Chip always in CAS mode */ ++ XPD_ERR(xpd, "J1 unsupported yet\n"); ++ return -ENOSYS; ++ } ++ if (priv->local_loopback) ++ fmr2 |= REG_FMR2_E_PLB; ++ /* framing first */ ++ if (lineconfig & DAHDI_CONFIG_B8ZS) { ++ framingstr = "B8ZS"; ++ fmr0 = ++ REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | ++ REG_FMR0_E_RC0; ++ } else if (lineconfig & DAHDI_CONFIG_AMI) { ++ framingstr = "AMI"; ++ fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_RC1; ++ /* ++ * From Infineon Errata Sheet: PEF 22554, Version 3.1 ++ * Problem: Incorrect CAS Receiption when ++ * using AMI receive line code ++ * Workaround: For E1, ++ * "...The receive line coding HDB3 is ++ * recommended instead." ++ * For T1, ++ * "...in T1 mode it is recommended to ++ * configure the Rx side to B8ZS coding" ++ * For both cases this is the same bit in FMR0 ++ */ ++ if (priv->pri_protocol == PRI_PROTO_J1) ++ XPD_NOTICE(xpd, "J1 is not supported yet\n"); ++ else ++ fmr0 |= REG_FMR0_E_RC0; ++ } else if (lineconfig & DAHDI_CONFIG_HDB3) { ++ framingstr = "HDB3"; ++ fmr0 = ++ REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | ++ REG_FMR0_E_RC0; ++ } else { ++ XPD_NOTICE(xpd, ++ "Bad lineconfig. Not (B8ZS|AMI|HDB3). Ignored.\n"); ++ return -EINVAL; ++ } ++ /* then coding */ ++ priv->is_esf = 0; ++ if (lineconfig & DAHDI_CONFIG_ESF) { ++ codingstr = "ESF"; ++ fmr4 |= REG_FMR4_FM1; ++ fmr2 |= REG_FMR2_T_AXRA | REG_FMR2_T_MCSP | REG_FMR2_T_SSP; ++ priv->is_esf = 1; ++ } else if (lineconfig & DAHDI_CONFIG_D4) { ++ codingstr = "D4"; ++ } else if (lineconfig & DAHDI_CONFIG_CCS) { ++ codingstr = "CCS"; ++ /* In E1 we know right from the span statement. */ ++ set_mode_cas(xpd, 0); ++ } else { ++ /* In E1 we know right from the span statement. */ ++ codingstr = "CAS"; ++ force_cas = 1; ++ set_mode_cas(xpd, 1); ++ } ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ /* ++ * E1's can enable CRC checking ++ * CRC4 is legal only for E1, and it is checked by pri_linecompat() ++ * in the beginning of the function. ++ */ ++ if (lineconfig & DAHDI_CONFIG_CRC4) { ++ crcstr = "CRC4"; ++ fmr1 |= REG_FMR1_E_XFS; ++ fmr2 |= REG_FMR2_E_RFS1; ++ fmr3 |= REG_FMR3_EXTIW; ++ } ++ XPD_DBG(GENERAL, xpd, "[%s] lineconfig=%s/%s/%s %s (0x%X)\n", ++ (priv->clock_source) ? "MASTER" : "SLAVE", framingstr, ++ codingstr, crcstr, ++ (lineconfig & DAHDI_CONFIG_NOTOPEN) ? "YELLOW" : "", ++ lineconfig); ++ set_reg_lim0(__func__, xpd); ++ XPD_DBG(GENERAL, xpd, "%s: fmr1(0x%02X) = 0x%02X\n", __func__, REG_FMR1, ++ fmr1); ++ write_subunit(xpd, REG_FMR1, fmr1); ++ XPD_DBG(GENERAL, xpd, "%s: fmr2(0x%02X) = 0x%02X\n", __func__, REG_FMR2, ++ fmr2); ++ write_subunit(xpd, REG_FMR2, fmr2); ++ XPD_DBG(GENERAL, xpd, "%s: fmr0(0x%02X) = 0x%02X\n", __func__, REG_FMR0, ++ fmr0); ++ write_subunit(xpd, REG_FMR0, fmr0); ++ XPD_DBG(GENERAL, xpd, "%s: fmr4(0x%02X) = 0x%02X\n", __func__, REG_FMR4, ++ fmr4); ++ write_subunit(xpd, REG_FMR4, fmr4); ++ if (fmr3) { ++ XPD_DBG(GENERAL, xpd, "%s: fmr3(0x%02X) = 0x%02X\n", __func__, ++ REG_FMR3, fmr3); ++ write_subunit(xpd, REG_FMR3, fmr3); ++ } ++ XPD_DBG(GENERAL, xpd, "%s: cmdr(0x%02X) = 0x%02X\n", __func__, ++ REG_CMDR_E, cmdr); ++ write_subunit(xpd, REG_CMDR_E, cmdr); ++#ifdef JAPANEZE_SUPPORT ++ if (rc0) { ++ XPD_DBG(GENERAL, xpd, "%s: rc0(0x%02X) = 0x%02X\n", __func__, ++ REG_RC0, rc0); ++ write_subunit(xpd, REG_RC0, rc0); ++ } ++#endif ++ if (force_cas) { ++ if (priv->pri_protocol == PRI_PROTO_E1) { ++ int rs1 = 0x0B; ++ ++ /* ++ * Set correct X1-X3 bits in the E1 CAS MFAS ++ * They are unused in E1 and should be 1 ++ */ ++ XPD_DBG(GENERAL, xpd, "%s: rs1(0x%02X) = 0x%02X\n", ++ __func__, REG_RS1_E, rs1); ++ write_subunit(xpd, REG_RS1_E, rs1); ++ } ++ xsp |= REG_XSP_E_CASEN; /* Same as REG_FMR5_T_EIBR for T1 */ ++ } ++ XPD_DBG(GENERAL, xpd, "%s: xsp(0x%02X) = 0x%02X\n", __func__, REG_XSP_E, ++ xsp); ++ write_subunit(xpd, REG_XSP_E, xsp); ++ return 0; ++bad_lineconfig: ++ XPD_ERR(xpd, "Bad lineconfig. Abort\n"); ++ return -EINVAL; ++} ++ ++static int pri_set_spantype(struct dahdi_span *span, enum spantypes spantype) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ enum pri_protocol set_proto = PRI_PROTO_0; ++ int ret; ++ ++ XPD_INFO(xpd, "%s: %s\n", __func__, dahdi_spantype2str(spantype)); ++ switch (spantype) { ++ case SPANTYPE_DIGITAL_E1: ++ set_proto = PRI_PROTO_E1; ++ break; ++ case SPANTYPE_DIGITAL_T1: ++ set_proto = PRI_PROTO_T1; ++ break; ++ case SPANTYPE_DIGITAL_J1: ++ set_proto = PRI_PROTO_J1; ++ break; ++ default: ++ XPD_NOTICE(xpd, "%s: bad spantype '%s'\n", ++ __func__, dahdi_spantype2str(spantype)); ++ return -EINVAL; ++ } ++ ret = set_pri_proto(xpd, set_proto); ++ if (ret < 0) { ++ XPD_ERR(xpd, "%s: set_pri_proto failed\n", __func__); ++ return ret; ++ } ++ dahdi_init_span(span); ++ return 0; ++} ++ ++static int PRI_card_open(xpd_t *xpd, lineno_t pos) ++{ ++ struct PRI_priv_data *priv; ++ int d; ++ ++ /* ++ * DAHDI without AUDIO_NOTIFY. ++ * Need to offhook all channels when D-Chan is up ++ */ ++ priv = xpd->priv; ++ d = PRI_DCHAN_IDX(priv); ++ BUG_ON(!xpd); ++ if (pos == d) { ++#ifndef DAHDI_AUDIO_NOTIFY ++ int i; ++ ++ LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK the whole span\n"); ++ for_each_line(xpd, i) { ++ if (i != d) ++ BIT_SET(PHONEDEV(xpd).offhook_state, i); ++ } ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++#endif ++ priv->dchan_is_open = 1; ++ } ++ return 0; ++} ++ ++static int PRI_card_close(xpd_t *xpd, lineno_t pos) ++{ ++ struct PRI_priv_data *priv; ++ int d, i; ++ ++ priv = xpd->priv; ++ d = PRI_DCHAN_IDX(priv); ++ BUG_ON(!xpd); ++ if (pos == d) { ++ LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK the whole span\n"); ++ for_each_line(xpd, i) { ++ if (i != d) ++ BIT_CLR(PHONEDEV(xpd).offhook_state, i); ++ } ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++ dchan_state(xpd, 0); ++ priv->dchan_is_open = 0; ++ } else if (!priv->dchan_is_open) ++ mark_offhook(xpd, pos, 0); /* e.g: patgen/pattest */ ++ return 0; ++} ++ ++/* ++ * Called only for 'span' keyword in /etc/dahdi/system.conf ++ */ ++ ++static int pri_spanconfig(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ struct PRI_priv_data *priv; ++ int ret; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ if (lc->span != PHONEDEV(xpd).span.spanno) { ++ XPD_ERR(xpd, "I am span %d but got spanconfig for span %d\n", ++ PHONEDEV(xpd).span.spanno, lc->span); ++ return -EINVAL; ++ } ++ /* ++ * FIXME: lc->name is unused by dahdi_cfg and dahdi... ++ * We currently ignore it also. ++ */ ++ XPD_DBG(GENERAL, xpd, "[%s] lbo=%d lineconfig=0x%X sync=%d\n", ++ (priv->clock_source) ? "MASTER" : "SLAVE", lc->lbo, ++ lc->lineconfig, lc->sync); ++ ret = pri_lineconfig(xpd, lc->lineconfig); ++ if (!ret) { ++ span->lineconfig = lc->lineconfig; ++ PHONEDEV(xpd).timing_priority = lc->sync; ++ set_master_mode("spanconfig", xpd); ++ elect_syncer("PRI-master_mode"); ++ } ++ return ret; ++} ++ ++/* ++ * Set signalling type (if appropriate) ++ * Called from dahdi with spinlock held on chan. Must not call back ++ * dahdi functions. ++ */ ++static int pri_chanconfig(struct file *file, struct dahdi_chan *chan, ++ int sigtype) ++{ ++ struct phonedev *phonedev = ++ container_of(chan->span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, ++ sig2str(sigtype)); ++ /* ++ * Some bookkeeping to check if we have DChan defined or not ++ * FIXME: actually use this to prevent duplicate DChan definitions ++ * and prevent DChan definitions with CAS. ++ */ ++ if (is_sigtype_dchan(sigtype)) { ++ if (VALID_DCHAN(priv) && DCHAN(priv) != chan->channo) { ++ ERR("channel %d (%s) marked DChan but " ++ "also channel %d.\n", ++ chan->channo, chan->name, DCHAN(priv)); ++ return -EINVAL; ++ } ++ XPD_DBG(GENERAL, xpd, "channel %d (%s) marked as DChan\n", ++ chan->channo, chan->name); ++ SET_DCHAN(priv, chan->channo); ++ /* In T1, we don't know before-hand */ ++ if (priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 0) ++ set_mode_cas(xpd, 0); ++ } else { ++ if (chan->chanpos == 1) { ++ XPD_DBG(GENERAL, xpd, ++ "channel %d (%s) marked a not DChan\n", ++ chan->channo, chan->name); ++ SET_DCHAN(priv, NO_DCHAN); ++ } ++ /* In T1, we don't know before-hand */ ++ if (priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 1) ++ set_mode_cas(xpd, 1); ++ } ++ if (PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING) { ++ XPD_DBG(DEVICES, xpd, "Span is RUNNING. Updating rbslines.\n"); ++ set_rbslines(xpd, chan->channo); ++ } ++ // FIXME: sanity checks: ++ // - should be supported (within the sigcap) ++ // - should not replace fxs <->fxo ??? (covered by previous?) ++ return 0; ++} ++ ++static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, ++ const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ bool to_phone) ++{ ++ xpd_t *xpd = NULL; ++ struct PRI_priv_data *priv; ++ int channels = min(31, CHANNELS_PERXPD); /* worst case */ ++ ++ if ((unit_descriptor->ports_per_chip < 1) || ++ (unit_descriptor->ports_per_chip > 4)) { ++ XBUS_ERR(xbus, "Bad ports_per_chip=%d\n", ++ unit_descriptor->ports_per_chip); ++ return NULL; ++ } ++ if (unit_descriptor->numchips != 1) { ++ XBUS_ERR(xbus, "Bad numchips=%d\n", ++ unit_descriptor->numchips); ++ return NULL; ++ } ++ XBUS_DBG(GENERAL, xbus, "\n"); ++ xpd = ++ xpd_alloc(xbus, unit, subunit, ++ sizeof(struct PRI_priv_data), proto_table, unit_descriptor, channels); ++ if (!xpd) ++ return NULL; ++ priv = xpd->priv; ++ /* Default, changes in set_pri_proto() */ ++ priv->pri_protocol = PRI_PROTO_0; ++ /* Default, changes in set_pri_proto() */ ++ priv->deflaw = DAHDI_LAW_DEFAULT; ++ xpd->type_name = type_name(priv->pri_protocol); ++ xbus->sync_mode_default = SYNC_MODE_AB; ++ return xpd; ++} ++ ++static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ int ret = 0; ++ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ xpd->xpd_type = XPD_TYPE_PRI; ++ priv = xpd->priv; ++ if (priv->pri_protocol == PRI_PROTO_0) { ++ /* ++ * init_card_* script didn't set pri protocol ++ * Let's have a default E1 ++ */ ++ ret = set_pri_proto(xpd, PRI_PROTO_E1); ++ if (ret < 0) ++ goto err; ++ } ++ SET_DCHAN(priv, NO_DCHAN); ++ /* ++ * initialization script should have set correct ++ * operating modes. ++ */ ++ if (!valid_pri_modes(xpd)) { ++ XPD_NOTICE(xpd, "PRI protocol not set\n"); ++ goto err; ++ } ++ xpd->type_name = type_name(priv->pri_protocol); ++ PHONEDEV(xpd).direction = TO_PSTN; ++ XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name); ++ PHONEDEV(xpd).timing_priority = 1; /* High priority SLAVE */ ++ set_master_mode(__func__, xpd); ++ for (ret = 0; ret < NUM_LEDS; ret++) { ++ DO_LED(xpd, ret, PRI_LED_ON); ++ msleep(20); ++ DO_LED(xpd, ret, PRI_LED_OFF); ++ } ++ priv->initialized = 1; ++ priv->dchan_is_open = 0; ++ return 0; ++err: ++ XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); ++ return ret; ++} ++ ++static int PRI_card_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ return 0; ++} ++ ++#ifdef DAHDI_AUDIO_NOTIFY ++static int pri_audio_notify(struct dahdi_chan *chan, int on) ++{ ++ xpd_t *xpd = chan->pvt; ++ int pos = chan->chanpos - 1; ++ ++ BUG_ON(!xpd); ++ LINE_DBG(SIGNAL, xpd, pos, "PRI-AUDIO: %s\n", (on) ? "on" : "off"); ++ mark_offhook(xpd, pos, on); ++ return 0; ++} ++#endif ++ ++static const struct dahdi_span_ops PRI_span_ops = { ++ .owner = THIS_MODULE, ++ .set_spantype = pri_set_spantype, ++ .spanconfig = pri_spanconfig, ++ .chanconfig = pri_chanconfig, ++ .startup = pri_startup, ++ .shutdown = pri_shutdown, ++ .rbsbits = pri_rbsbits, ++ .open = xpp_open, ++ .close = xpp_close, ++ .ioctl = xpp_ioctl, ++ .maint = xpp_maint, ++ .echocan_create = xpp_echocan_create, ++ .echocan_name = xpp_echocan_name, ++ .assigned = xpp_span_assigned, ++#ifdef DAHDI_SYNC_TICK ++ .sync_tick = dahdi_sync_tick, ++#endif ++#ifdef CONFIG_DAHDI_WATCHDOG ++ .watchdog = xpp_watchdog, ++#endif ++ ++#ifdef DAHDI_AUDIO_NOTIFY ++ .audio_notify = pri_audio_notify, ++#endif ++}; ++ ++static int apply_pri_protocol(xpd_t *xpd) ++{ ++ xbus_t *xbus; ++ struct PRI_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ BUG_ON(!xbus); ++ XPD_DBG(GENERAL, xpd, "\n"); ++ PHONEDEV(xpd).span.spantype = pri_protocol2spantype(priv->pri_protocol); ++ PHONEDEV(xpd).span.linecompat = pri_linecompat(priv->pri_protocol); ++ PHONEDEV(xpd).span.deflaw = priv->deflaw; ++ PHONEDEV(xpd).span.alarms = DAHDI_ALARM_NONE; ++ for_each_line(xpd, i) { ++ struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i); ++ bool is_dchan = i == PRI_DCHAN_IDX(priv); ++ ++ XPD_DBG(GENERAL, xpd, "setting PRI channel %d (%s)\n", i, ++ (is_dchan) ? "DCHAN" : "CLEAR"); ++ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d", ++ xpd->type_name, xbus->num, xpd->addr.unit, ++ xpd->addr.subunit, i); ++ cur_chan->chanpos = i + 1; ++ cur_chan->pvt = xpd; ++ cur_chan->sigcap = PRI_SIGCAP; ++ if (is_dchan && !priv->is_cas) { /* D-CHAN */ ++ //FIXME: cur_chan->flags |= DAHDI_FLAG_PRIDCHAN; ++ cur_chan->flags &= ~DAHDI_FLAG_HDLC; ++ } ++ } ++ PHONEDEV(xpd).offhook_state = PHONEDEV(xpd).wanted_pcm_mask; ++ PHONEDEV(xpd).span.ops = &PRI_span_ops; ++ PHONEDEV(xpd).span.channels = PHONEDEV(xpd).channels; ++ xpd_set_spanname(xpd); ++ return 0; ++} ++ ++static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ priv = xpd->priv; ++ BUG_ON(!xbus); ++ XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n", ++ (on) ? "on" : "off", pri_protocol_name(priv->pri_protocol), ++ PHONEDEV(xpd).channels, priv->deflaw); ++ if (!on) { ++ /* Nothing to do yet */ ++ return 0; ++ } ++ return apply_pri_protocol(xpd); ++} ++ ++static int PRI_card_dahdi_postregistration(xpd_t *xpd, bool on) ++{ ++ xbus_t *xbus; ++ ++ BUG_ON(!xpd); ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ dahdi_update_syncsrc(xpd); ++ return (0); ++} ++ ++static void dchan_state(xpd_t *xpd, bool up) ++{ ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (priv->is_cas) ++ return; ++ if (priv->dchan_alive == up) ++ return; ++ if (!priv->layer1_up) /* No layer1, kill dchan */ ++ up = 0; ++ if (up) { ++ XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n"); ++ priv->dchan_alive = 1; ++ } else { ++ int d = PRI_DCHAN_IDX(priv); ++ ++ if (SPAN_REGISTERED(xpd) && d >= 0 ++ && d < PHONEDEV(xpd).channels) { ++ __u8 *pcm; ++ ++ pcm = (__u8 *)XPD_CHAN(xpd, d)->readchunk; ++ pcm[0] = 0x00; ++ pcm = (__u8 *)XPD_CHAN(xpd, d)->writechunk; ++ pcm[0] = 0x00; ++ } ++ XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n"); ++ priv->dchan_rx_counter = priv->dchan_tx_counter = 0; ++ priv->dchan_alive = 0; ++ priv->dchan_alive_ticks = 0; ++ priv->dchan_rx_sample = priv->dchan_tx_sample = 0x00; ++ } ++} ++ ++/* ++ * LED managment is done by the driver now: ++ * - Turn constant ON RED/GREEN led to indicate MASTER/SLAVE port ++ * - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel) ++ * - Constant blink (1/2 sec cycle) to indicate D-Channel alive. ++ */ ++static void handle_leds(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ unsigned int timer_count; ++ int which_led; ++ int other_led; ++ enum pri_led_state ledstate; ++ int mod; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (PHONEDEV(xpd).timing_priority == 0) { ++ which_led = TOP_RED_LED; ++ other_led = BOTTOM_GREEN_LED; ++ } else { ++ which_led = BOTTOM_GREEN_LED; ++ other_led = TOP_RED_LED; ++ } ++ ledstate = priv->ledstate[which_led]; ++ timer_count = xpd->timer_count; ++ if (xpd->blink_mode) { ++ if ((timer_count % DEFAULT_LED_PERIOD) == 0) { ++ // led state is toggled ++ if (ledstate == PRI_LED_OFF) { ++ DO_LED(xpd, which_led, PRI_LED_ON); ++ DO_LED(xpd, other_led, PRI_LED_ON); ++ } else { ++ DO_LED(xpd, which_led, PRI_LED_OFF); ++ DO_LED(xpd, other_led, PRI_LED_OFF); ++ } ++ } ++ return; ++ } ++ if (priv->ledstate[other_led] != PRI_LED_OFF) ++ DO_LED(xpd, other_led, PRI_LED_OFF); ++ if (priv->dchan_alive) { ++ mod = timer_count % 1000; ++ switch (mod) { ++ case 0: ++ DO_LED(xpd, which_led, PRI_LED_ON); ++ break; ++ case 500: ++ DO_LED(xpd, which_led, PRI_LED_OFF); ++ break; ++ } ++ } else if (priv->layer1_up) { ++ mod = timer_count % 1000; ++ switch (mod) { ++ case 0: ++ case 100: ++ DO_LED(xpd, which_led, PRI_LED_ON); ++ break; ++ case 50: ++ case 150: ++ DO_LED(xpd, which_led, PRI_LED_OFF); ++ break; ++ } ++ } else { ++ if (priv->ledstate[which_led] != PRI_LED_ON) ++ DO_LED(xpd, which_led, PRI_LED_ON); ++ } ++} ++ ++static int PRI_card_tick(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!priv->initialized || !xbus->self_ticking) ++ return 0; ++ /* ++ * Poll layer1 status (cascade subunits) ++ */ ++ if (poll_interval != 0 && ((xpd->timer_count % poll_interval) == 0)) { ++ priv->poll_noreplies++; ++ query_subunit(xpd, REG_FRS0); ++ //query_subunit(xpd, REG_FRS1); ++ } ++ if (priv->dchan_tx_counter >= 1 && priv->dchan_rx_counter > 1) { ++ dchan_state(xpd, 1); ++ priv->dchan_alive_ticks++; ++ } ++ handle_leds(xbus, xpd); ++ return 0; ++} ++ ++static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct dahdi_chan *chan; ++ ++ BUG_ON(!xpd); ++ if (!XBUS_IS(xpd->xbus, READY)) ++ return -ENODEV; ++ chan = XPD_CHAN(xpd, pos); ++ switch (cmd) { ++ /* ++ * Asterisk may send FXS type ioctl()'s to us: ++ * - Some are sent to everybody (DAHDI_TONEDETECT) ++ * - Some are sent because we may be in CAS mode ++ * (FXS signalling) ++ * Ignore them. ++ */ ++ case DAHDI_TONEDETECT: ++ LINE_DBG(SIGNAL, xpd, pos, "PRI: TONEDETECT (%s)\n", ++ (chan-> ++ flags & DAHDI_FLAG_AUDIO) ? "AUDIO" : "SILENCE"); ++ return -ENOTTY; ++ case DAHDI_ONHOOKTRANSFER: ++ LINE_DBG(SIGNAL, xpd, pos, "PRI: ONHOOKTRANSFER\n"); ++ return -ENOTTY; ++ case DAHDI_VMWI: ++ LINE_DBG(SIGNAL, xpd, pos, "PRI: VMWI\n"); ++ return -ENOTTY; ++ case DAHDI_VMWI_CONFIG: ++ LINE_DBG(SIGNAL, xpd, pos, "PRI: VMWI_CONFIG\n"); ++ return -ENOTTY; ++ case DAHDI_SETPOLARITY: ++ LINE_DBG(SIGNAL, xpd, pos, "PRI: SETPOLARITY\n"); ++ return -ENOTTY; ++ /* report on really bad ioctl()'s */ ++ default: ++ report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++/* ++ * Called only for 'span' keyword in /etc/dahdi/system.conf ++ */ ++static int pri_startup(struct file *file, struct dahdi_span *span) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!XBUS_IS(xpd->xbus, READY)) { ++ XPD_DBG(GENERAL, xpd, ++ "Startup called by dahdi. No Hardware. Ignored\n"); ++ return -ENODEV; ++ } ++ XPD_DBG(GENERAL, xpd, "STARTUP\n"); ++ // Turn on all channels ++ CALL_PHONE_METHOD(card_state, xpd, 1); ++ set_rbslines(xpd, 0); ++ write_subunit(xpd, REG_XPM2, 0x00); ++ return 0; ++} ++ ++/* ++ * Called only for 'span' keyword in /etc/dahdi/system.conf ++ */ ++static int pri_shutdown(struct dahdi_span *span) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!XBUS_IS(xpd->xbus, READY)) { ++ XPD_DBG(GENERAL, xpd, ++ "Shutdown called by dahdi. No Hardware. Ignored\n"); ++ return -ENODEV; ++ } ++ XPD_DBG(GENERAL, xpd, "SHUTDOWN\n"); ++ // Turn off all channels ++ CALL_PHONE_METHOD(card_state, xpd, 0); ++ return 0; ++} ++ ++static int encode_rbsbits_e1(xpd_t *xpd, int pos, int bits) ++{ ++ struct PRI_priv_data *priv; ++ __u8 val; ++ int rsnum; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ BUG_ON(priv->pri_protocol != PRI_PROTO_E1); ++ if (pos == 15) ++ return 0; /* Don't write dchan in CAS */ ++ if (pos < 0 || pos > 31) { ++ XPD_NOTICE(xpd, "%s: pos=%d out of range. Ignore\n", __func__, ++ pos); ++ return 0; ++ } ++ if (pos >= 16) { ++ /* Low nibble */ ++ rsnum = pos - 16; ++ val = (priv->cas_ts_e[rsnum] & 0xF0) | (bits & 0x0F); ++ } else { ++ /* High nibble */ ++ rsnum = pos; ++ val = (priv->cas_ts_e[rsnum] & 0x0F) | ((bits << 4) & 0xF0); ++ } ++ LINE_DBG(SIGNAL, xpd, pos, "RBS: TX: bits=0x%X\n", bits); ++ write_cas_reg(xpd, rsnum, val); ++ return 0; ++} ++ ++static int encode_rbsbits_t1(xpd_t *xpd, int pos, int bits) ++{ ++ struct PRI_priv_data *priv; ++ int rsnum; ++ int chan_per_reg; ++ int offset; ++ int width; ++ uint tx_bits = bits; ++ uint mask; ++ __u8 val; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ BUG_ON(priv->pri_protocol != PRI_PROTO_T1); ++ if (pos < 0 || pos >= PHONEDEV(xpd).channels) { ++ XPD_ERR(xpd, "%s: Bad pos=%d\n", __func__, pos); ++ return 0; ++ } ++ chan_per_reg = CHAN_PER_REGS(priv); ++ width = 8 / chan_per_reg; ++ rsnum = pos / chan_per_reg; ++ offset = pos % chan_per_reg; ++ mask = BITMASK(width) << (chan_per_reg - offset - 1) * width; ++ if (!priv->is_esf) ++ tx_bits >>= 2; ++ tx_bits &= BITMASK(width); ++ tx_bits <<= (chan_per_reg - offset - 1) * width; ++ val = priv->cas_ts_e[rsnum]; ++ val &= ~mask; ++ val |= tx_bits; ++ LINE_DBG(SIGNAL, xpd, pos, ++ "bits=0x%02X RS%02d(%s) offset=%d tx_bits=0x%02X\n", bits, ++ rsnum + 1, (priv->is_esf) ? "esf" : "d4", offset, tx_bits); ++ write_cas_reg(xpd, rsnum, val); ++ priv->dchan_tx_counter++; ++ return 0; ++} ++ ++static void send_idlebits(xpd_t *xpd, bool saveold) ++{ ++ struct PRI_priv_data *priv; ++ __u8 save_rs[NUM_CAS_RS_E]; ++ int i; ++ ++ if (!SPAN_REGISTERED(xpd)) ++ return; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(SIGNAL, xpd, "saveold=%d\n", saveold); ++ if (saveold) ++ memcpy(save_rs, priv->cas_ts_e, sizeof(save_rs)); ++ for_each_line(xpd, i) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ ++ pri_rbsbits(chan, chan->idlebits); ++ } ++ if (saveold) ++ memcpy(priv->cas_ts_e, save_rs, sizeof(save_rs)); ++} ++ ++static void send_oldbits(xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(SIGNAL, xpd, "\n"); ++ for (i = 0; i < cas_numregs(xpd); i++) ++ write_cas_reg(xpd, i, priv->cas_ts_e[i]); ++} ++ ++static int pri_rbsbits(struct dahdi_chan *chan, int bits) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ int pos; ++ ++ xpd = chan->pvt; ++ BUG_ON(!xpd); ++ pos = chan->chanpos - 1; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (!priv->is_cas) { ++ XPD_DBG(SIGNAL, xpd, "RBS: TX: not in CAS mode. Ignore.\n"); ++ return 0; ++ } ++ if (chan->sig == DAHDI_SIG_NONE) { ++ LINE_DBG(SIGNAL, xpd, pos, ++ "RBS: TX: sigtyp=%s. , bits=0x%X. Ignore.\n", ++ sig2str(chan->sig), bits); ++ return 0; ++ } ++ if (!priv->layer1_up) ++ XPD_DBG(SIGNAL, xpd, "RBS: TX: No layer1 yet. Keep going.\n"); ++ if (priv->pri_protocol == PRI_PROTO_E1) { ++ if (encode_rbsbits_e1(xpd, pos, bits) < 0) ++ return -EINVAL; ++ } else if (priv->pri_protocol == PRI_PROTO_T1) { ++ if (encode_rbsbits_t1(xpd, pos, bits) < 0) ++ return -EINVAL; ++ } else { ++ XPD_NOTICE(xpd, ++ "%s: protocol %s is not supported yet with CAS\n", ++ __func__, pri_protocol_name(priv->pri_protocol)); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++/*! Copy PCM chunks from the buffers of the xpd to a new packet ++ * \param xbus xbus of source xpd. ++ * \param xpd source xpd. ++ * \param lines a bitmask of the active channels that need to be copied. ++ * \param pack packet to be filled. ++ * ++ * On PRI this function is should also shift the lines mask one bit, as ++ * channel 0 on the wire is an internal chip control channel. We only ++ * send 31 channels to the device, but they should be called 1-31 rather ++ * than 0-30 . ++ */ ++static void PRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack) ++{ ++ struct PRI_priv_data *priv; ++ __u8 *pcm; ++ unsigned long flags; ++ int i; ++ xpp_line_t wanted_lines; ++ int physical_chan; ++ int physical_mask = 0; ++ ++ BUG_ON(!xpd); ++ BUG_ON(!pack); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); ++ spin_lock_irqsave(&xpd->lock, flags); ++ wanted_lines = PHONEDEV(xpd).wanted_pcm_mask; ++ physical_chan = 0; ++ for_each_line(xpd, i) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ ++ if (priv->pri_protocol == PRI_PROTO_E1) { ++ /* In E1 - Only 0'th channel is unused */ ++ if (i == 0) ++ physical_chan++; ++ } else if (priv->pri_protocol == PRI_PROTO_T1) { ++ /* In T1 - Every 4'th channel is unused */ ++ if ((i % 3) == 0) ++ physical_chan++; ++ } ++ if (IS_SET(wanted_lines, i)) { ++ physical_mask |= BIT(physical_chan); ++ if (SPAN_REGISTERED(xpd)) { ++#ifdef DEBUG_PCMTX ++ int channo = XPD_CHAN(xpd, i)->channo; ++ ++ if (pcmtx >= 0 && pcmtx_chan == channo) ++ memset((u_char *)pcm, pcmtx, ++ DAHDI_CHUNKSIZE); ++ else ++#endif ++ memcpy((u_char *)pcm, chan->writechunk, ++ DAHDI_CHUNKSIZE); ++ if (i == PRI_DCHAN_IDX(priv)) { ++ if (priv->dchan_tx_sample != ++ chan->writechunk[0]) { ++ priv->dchan_tx_sample = ++ chan->writechunk[0]; ++ priv->dchan_tx_counter++; ++ } else if (chan->writechunk[0] == 0xFF) ++ dchan_state(xpd, 0); ++ else ++ /* Clobber for next tick */ ++ chan->writechunk[0] = 0xFF; ++ } ++ } else ++ memset((u_char *)pcm, DAHDI_XLAW(0, chan), ++ DAHDI_CHUNKSIZE); ++ pcm += DAHDI_CHUNKSIZE; ++ } ++ physical_chan++; ++ } ++ RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = physical_mask; ++ XPD_COUNTER(xpd, PCM_WRITE)++; ++ spin_unlock_irqrestore(&xpd->lock, flags); ++} ++ ++/*! Copy PCM chunks from the packet we received to the xpd struct. ++ * \param xbus xbus of target xpd. ++ * \param xpd target xpd. ++ * \param pack Source packet. ++ * ++ * On PRI this function is should also shift the lines back mask one bit, as ++ * channel 0 on the wire is an internal chip control channel. ++ * ++ * \see PRI_card_pcm_fromspan ++ */ ++static void PRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack) ++{ ++ struct PRI_priv_data *priv; ++ __u8 *pcm; ++ xpp_line_t physical_mask; ++ unsigned long flags; ++ int i; ++ int logical_chan; ++ ++ if (!SPAN_REGISTERED(xpd)) ++ return; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); ++ physical_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines); ++ spin_lock_irqsave(&xpd->lock, flags); ++ logical_chan = 0; ++ for (i = 0; i < CHANNELS_PERXPD; i++) { ++ volatile u_char *r; ++ ++ if (priv->pri_protocol == PRI_PROTO_E1) { ++ /* In E1 - Only 0'th channel is unused */ ++ if (i == 0) ++ continue; ++ } else if (priv->pri_protocol == PRI_PROTO_T1) { ++ /* In T1 - Every 4'th channel is unused */ ++ if ((i % 4) == 0) ++ continue; ++ } ++ if (logical_chan == PRI_DCHAN_IDX(priv) && !priv->is_cas) { ++ if (priv->dchan_rx_sample != pcm[0]) { ++ if (debug & DBG_PCM) { ++ XPD_INFO(xpd, ++ "RX-D-Chan: prev=0x%X now=0x%X\n", ++ priv->dchan_rx_sample, pcm[0]); ++ dump_packet("RX-D-Chan", pack, 1); ++ } ++ priv->dchan_rx_sample = pcm[0]; ++ priv->dchan_rx_counter++; ++ } else if (pcm[0] == 0xFF) ++ dchan_state(xpd, 0); ++ } ++ if (IS_SET(physical_mask, i)) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, logical_chan); ++ r = chan->readchunk; ++ // memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG ++ memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE); ++ pcm += DAHDI_CHUNKSIZE; ++ } ++ logical_chan++; ++ } ++ XPD_COUNTER(xpd, PCM_READ)++; ++ spin_unlock_irqrestore(&xpd->lock, flags); ++} ++ ++static int PRI_timing_priority(xpd_t *xpd) ++{ ++ struct PRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (priv->layer1_up) ++ return PHONEDEV(xpd).timing_priority; ++ XPD_DBG(SYNC, xpd, "No timing priority (no layer1)\n"); ++ return -ENOENT; ++} ++ ++static int PRI_echocancel_timeslot(xpd_t *xpd, int pos) ++{ ++ /* ++ * Skip ts=0 (used for PRI sync) ++ */ ++ return (1 + pos) * 4 + xpd->addr.subunit; ++} ++ ++static int PRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask) ++{ ++ struct PRI_priv_data *priv; ++ int i; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask); ++ if (!ECHOOPS(xpd->xbus)) { ++ XPD_DBG(GENERAL, xpd, ++ "No echo canceller in XBUS: Doing nothing.\n"); ++ return -EINVAL; ++ } ++ for (i = 0; i < PHONEDEV(xpd).channels; i++) { ++ int on = BIT(i) & ec_mask; ++ ++ if (i == PRI_DCHAN_IDX(priv)) ++ on = 0; ++ CALL_EC_METHOD(ec_set, xpd->xbus, xpd, i, on); ++ } ++ CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus); ++ return 0; ++} ++ ++/*---------------- PRI: HOST COMMANDS -------------------------------------*/ ++ ++static /* 0x33 */ HOSTCMD(PRI, SET_LED, enum pri_led_selectors led_sel, ++ enum pri_led_state to_led_state) ++{ ++ int ret = 0; ++ xframe_t *xframe; ++ xpacket_t *pack; ++ struct pri_leds *pri_leds; ++ struct PRI_priv_data *priv; ++ ++ BUG_ON(!xbus); ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ XPD_DBG(LEDS, xpd, "led_sel=%d to_state=%d\n", led_sel, to_led_state); ++ XFRAME_NEW_CMD(xframe, pack, xbus, PRI, SET_LED, xpd->xbus_idx); ++ pri_leds = &RPACKET_FIELD(pack, PRI, SET_LED, pri_leds); ++ pri_leds->state = to_led_state; ++ pri_leds->led_sel = led_sel; ++ pri_leds->reserved = 0; ++ XPACKET_LEN(pack) = RPACKET_SIZE(PRI, SET_LED); ++ ret = send_cmd_frame(xbus, xframe); ++ priv->ledstate[led_sel] = to_led_state; ++ return ret; ++} ++ ++/*---------------- PRI: Astribank Reply Handlers --------------------------*/ ++static void layer1_state(xpd_t *xpd, __u8 data_low) ++{ ++ struct PRI_priv_data *priv; ++ int alarms = DAHDI_ALARM_NONE; ++ int layer1_up_prev; ++ ++ BUG_ON(!xpd); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ priv->poll_noreplies = 0; ++ if (data_low & REG_FRS0_LOS) ++ alarms |= DAHDI_ALARM_RED; ++ if (data_low & REG_FRS0_AIS) ++ alarms |= DAHDI_ALARM_BLUE; ++ if (data_low & REG_FRS0_RRA) ++ alarms |= DAHDI_ALARM_YELLOW; ++ layer1_up_prev = priv->layer1_up; ++ priv->layer1_up = alarms == DAHDI_ALARM_NONE; ++#if 0 ++ /* ++ * Some bad bits (e.g: LMFA and NMF have no alarm "colors" ++ * associated. However, layer1 is still not working if they are set. ++ * FIXME: These behave differently in E1/T1, so ignore them for while. ++ */ ++ if (data_low & (REG_FRS0_LMFA | REG_FRS0_E1_NMF)) ++ priv->layer1_up = 0; ++#endif ++ priv->alarms = alarms; ++ if (!priv->layer1_up) { ++ dchan_state(xpd, 0); ++ } else if (priv->is_cas && !layer1_up_prev) { ++ int regbase = cas_regbase(xpd); ++ int i; ++ ++ XPD_DBG(SIGNAL, xpd, ++ "Returning From Alarm Refreshing Rx register data \n"); ++ for (i = 0; i < cas_numregs(xpd); i++) ++ query_subunit(xpd, regbase + i); ++ } ++ ++ if (SPAN_REGISTERED(xpd) && PHONEDEV(xpd).span.alarms != alarms) { ++ char str1[MAX_PROC_WRITE]; ++ char str2[MAX_PROC_WRITE]; ++ ++ alarm2str(PHONEDEV(xpd).span.alarms, str1, sizeof(str1)); ++ alarm2str(alarms, str2, sizeof(str2)); ++ XPD_NOTICE(xpd, "Alarms: 0x%X (%s) => 0x%X (%s)\n", ++ PHONEDEV(xpd).span.alarms, str1, alarms, str2); ++ if (priv->is_cas) { ++ if (alarms == DAHDI_ALARM_NONE) ++ send_oldbits(xpd); ++ else if (PHONEDEV(xpd).span.alarms == DAHDI_ALARM_NONE) ++ send_idlebits(xpd, 1); ++ } ++ PHONEDEV(xpd).span.alarms = alarms; ++ elect_syncer("LAYER1"); ++ dahdi_alarm_notify(&PHONEDEV(xpd).span); ++ set_clocking(xpd); ++ } ++ priv->reg_frs0 = data_low; ++ priv->layer1_replies++; ++ XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", xpd->addr.subunit, ++ data_low); ++} ++ ++static int decode_cas_e1(xpd_t *xpd, __u8 regnum, __u8 data_low) ++{ ++ struct PRI_priv_data *priv; ++ uint pos = regnum - REG_RS2_E; ++ int rsnum = pos + 2; ++ int chan1 = pos; ++ int chan2 = pos + 16; ++ int val1 = (data_low >> 4) & 0xF; ++ int val2 = data_low & 0xF; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv->is_cas); ++ BUG_ON(priv->pri_protocol != PRI_PROTO_E1); ++ XPD_DBG(SIGNAL, xpd, "RBS: RX: data_low=0x%02X\n", data_low); ++ if (pos >= NUM_CAS_RS_E) { ++ XPD_ERR(xpd, "%s: got bad pos=%d [0-%d]\n", __func__, pos, ++ NUM_CAS_RS_E); ++ return -EINVAL; ++ } ++ if (chan1 < 0 || chan1 > PHONEDEV(xpd).channels) { ++ XPD_NOTICE(xpd, "%s: %s CAS: Bad chan1 number (%d)\n", __func__, ++ pri_protocol_name(priv->pri_protocol), chan1); ++ return -EINVAL; ++ } ++ if (chan2 < 0 || chan2 > PHONEDEV(xpd).channels) { ++ XPD_NOTICE(xpd, "%s: %s CAS: Bad chan2 number (%d)\n", __func__, ++ pri_protocol_name(priv->pri_protocol), chan2); ++ return -EINVAL; ++ } ++ XPD_DBG(SIGNAL, xpd, ++ "RBS: RX: RS%02d (channel %2d, channel %2d): 0x%02X -> 0x%02X\n", ++ rsnum, chan1 + 1, chan2 + 1, priv->cas_rs_e[pos], data_low); ++ if (SPAN_REGISTERED(xpd)) { ++ dahdi_rbsbits(XPD_CHAN(xpd, chan1), val1); ++ dahdi_rbsbits(XPD_CHAN(xpd, chan2), val2); ++ } ++ priv->dchan_rx_counter++; ++ priv->cas_rs_e[pos] = data_low; ++ return 0; ++} ++ ++static int decode_cas_t1(xpd_t *xpd, __u8 regnum, __u8 data_low) ++{ ++ struct PRI_priv_data *priv; ++ uint rsnum; ++ uint chan_per_reg; ++ uint width; ++ int i; ++ ++ priv = xpd->priv; ++ BUG_ON(!priv->is_cas); ++ BUG_ON(priv->pri_protocol != PRI_PROTO_T1); ++ rsnum = regnum - REG_RS1_E; ++ if (rsnum >= 12) { ++ XPD_ERR(xpd, "Bad rsnum=%d\n", rsnum); ++ return 0; ++ } ++ if (!priv->is_esf) ++ rsnum = rsnum % 6; /* 2 identical banks of 6 registers */ ++ chan_per_reg = CHAN_PER_REGS(priv); ++ width = 8 / chan_per_reg; ++ XPD_DBG(SIGNAL, xpd, "RBS: RX(%s,%d): RS%02d data_low=0x%02X\n", ++ (priv->is_esf) ? "esf" : "d4", chan_per_reg, rsnum + 1, ++ data_low); ++ for (i = 0; i < chan_per_reg; i++) { ++ uint rxsig = (data_low >> (i * width)) & BITMASK(width); ++ int pos; ++ struct dahdi_chan *chan; ++ ++ if (!priv->is_esf) ++ rxsig <<= 2; ++ pos = rsnum * chan_per_reg + chan_per_reg - i - 1; ++ if (pos < 0 || pos >= PHONEDEV(xpd).channels) { ++ XPD_ERR(xpd, "%s: Bad pos=%d\n", __func__, pos); ++ continue; ++ } ++ chan = XPD_CHAN(xpd, pos); ++ if (!chan) { ++ XPD_ERR(xpd, "%s: Null channel in pos=%d\n", __func__, ++ pos); ++ continue; ++ } ++ if (chan->rxsig != rxsig) { ++ LINE_DBG(SIGNAL, xpd, pos, "i=%d rxsig=0x%02X\n", i, ++ rxsig); ++ dahdi_rbsbits(chan, rxsig); ++ } ++ } ++ priv->cas_rs_e[rsnum] = data_low; ++ return 0; ++} ++ ++static void process_cas_dchan(xpd_t *xpd, __u8 regnum, __u8 data_low) ++{ ++ struct PRI_priv_data *priv; ++ ++ priv = xpd->priv; ++ if (!priv->is_cas) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 10003) == 0) ++ XPD_NOTICE(xpd, "RBS: RX: not in CAS mode. Ignore.\n"); ++ return; ++ } ++ if (!priv->layer1_up) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 10003) == 0) ++ XPD_DBG(SIGNAL, xpd, "RBS: RX: No layer1.\n"); ++ } ++ if (!SPAN_REGISTERED(xpd)) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 10003) == 0) ++ XPD_DBG(SIGNAL, xpd, ++ "RBS: RX: Span not registered. Ignore.\n"); ++ return; ++ } ++ if (priv->pri_protocol == PRI_PROTO_E1) { ++ if (regnum == REG_RS1_E) ++ return; /* Time slot 0: Ignored for E1 */ ++ if (regnum < REG_RS2_E) { ++ /* Should not happen, but harmless. Ignore */ ++ if (regnum == REG_RS1_E) ++ return; ++ ++ XPD_NOTICE(xpd, ++ "%s: received register 0x%X in protocol %s. " ++ "Ignore.\n", ++ __func__, regnum, ++ pri_protocol_name(priv->pri_protocol)); ++ return; ++ } ++ if (decode_cas_e1(xpd, regnum, data_low) < 0) ++ return; ++ } else if (priv->pri_protocol == PRI_PROTO_T1) { ++ if (regnum > REG_RS12_E) { ++ XPD_NOTICE(xpd, ++ "%s: received register 0x%X in protocol %s. " ++ "Ignore.\n", ++ __func__, regnum, ++ pri_protocol_name(priv->pri_protocol)); ++ return; ++ } ++ if (decode_cas_t1(xpd, regnum, data_low) < 0) ++ return; ++ } else { ++ XPD_NOTICE(xpd, ++ "%s: protocol %s is not supported yet with CAS\n", ++ __func__, pri_protocol_name(priv->pri_protocol)); ++ } ++ priv->cas_replies++; ++} ++ ++static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) ++{ ++ unsigned long flags; ++ struct PRI_priv_data *priv; ++ struct xpd_addr addr; ++ xpd_t *orig_xpd; ++ __u8 regnum; ++ __u8 data_low; ++ ++ /* Map UNIT + PORTNUM to XPD */ ++ orig_xpd = xpd; ++ addr.unit = orig_xpd->addr.unit; ++ addr.subunit = info->h.portnum; ++ regnum = REG_FIELD(info, regnum); ++ data_low = REG_FIELD(info, data_low); ++ xpd = xpd_byaddr(xbus, addr.unit, addr.subunit); ++ if (!xpd) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) < 5) ++ notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname); ++ return -EPROTO; ++ } ++ spin_lock_irqsave(&xpd->lock, flags); ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ if (info->h.is_multibyte) { ++ XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n", ++ info->h.bytes, info->h.eoframe); ++ goto end; ++ } ++ if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg)) ++ layer1_state(xpd, data_low); ++ else if (regnum == REG_FRS1 && !REG_FIELD(info, do_subreg)) ++ priv->reg_frs1 = data_low; ++ if (priv->is_cas && !REG_FIELD(info, do_subreg)) { ++ if (regnum >= REG_RS1_E && regnum <= REG_RS16_E) ++ process_cas_dchan(xpd, regnum, data_low); ++ } ++ /* ++ * Update /proc info only if reply relate to the ++ * last slic read request ++ */ ++ if (REG_FIELD(&xpd->requested_reply, regnum) == ++ REG_FIELD(info, regnum) ++ && REG_FIELD(&xpd->requested_reply, do_subreg) == ++ REG_FIELD(info, do_subreg) ++ && REG_FIELD(&xpd->requested_reply, subreg) == ++ REG_FIELD(info, subreg)) { ++ xpd->last_reply = *info; ++ } ++ ++end: ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return 0; ++} ++ ++static int PRI_card_state(xpd_t *xpd, bool on) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); ++ return 0; ++} ++ ++static const struct xops pri_xops = { ++ .card_new = PRI_card_new, ++ .card_init = PRI_card_init, ++ .card_remove = PRI_card_remove, ++ .card_tick = PRI_card_tick, ++ .card_register_reply = PRI_card_register_reply, ++}; ++ ++static const struct phoneops pri_phoneops = { ++ .card_dahdi_preregistration = PRI_card_dahdi_preregistration, ++ .card_dahdi_postregistration = PRI_card_dahdi_postregistration, ++ .card_pcm_recompute = PRI_card_pcm_recompute, ++ .card_pcm_fromspan = PRI_card_pcm_fromspan, ++ .card_pcm_tospan = PRI_card_pcm_tospan, ++ .echocancel_timeslot = PRI_echocancel_timeslot, ++ .echocancel_setmask = PRI_echocancel_setmask, ++ .card_timing_priority = PRI_timing_priority, ++ .card_ioctl = PRI_card_ioctl, ++ .card_open = PRI_card_open, ++ .card_close = PRI_card_close, ++ .card_state = PRI_card_state, ++}; ++ ++static xproto_table_t PROTO_TABLE(PRI) = { ++ .owner = THIS_MODULE, ++ .entries = { ++ /* Table Card Opcode */ ++ }, ++ .name = "PRI", /* protocol name */ ++ .ports_per_subunit = 1, ++ .type = XPD_TYPE_PRI, ++ .xops = &pri_xops, ++ .phoneops = &pri_phoneops, ++ .packet_is_valid = pri_packet_is_valid, ++ .packet_dump = pri_packet_dump, ++}; ++ ++static bool pri_packet_is_valid(xpacket_t *pack) ++{ ++ const xproto_entry_t *xe = NULL; ++ // DBG(GENERAL, "\n"); ++ xe = xproto_card_entry(&PROTO_TABLE(PRI), XPACKET_OP(pack)); ++ return xe != NULL; ++} ++ ++static void pri_packet_dump(const char *msg, xpacket_t *pack) ++{ ++ DBG(GENERAL, "%s\n", msg); ++} ++ ++/*------------------------- REGISTER Handling --------------------------*/ ++ ++/*------------------------- sysfs stuff --------------------------------*/ ++static DEVICE_ATTR_READER(pri_protocol_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += sprintf(buf, "%s\n", pri_protocol_name(priv->pri_protocol)); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR_WRITER(pri_protocol_store, dev, buf, count) ++{ ++ xpd_t *xpd; ++ enum pri_protocol new_protocol = PRI_PROTO_0; ++ int i; ++ int ret; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(GENERAL, xpd, "%s\n", buf); ++ if (!xpd) ++ return -ENODEV; ++ i = strcspn(buf, " \r\n"); ++ if (i != 2) { ++ XPD_NOTICE(xpd, ++ "Protocol name '%s' has %d characters (should be 2). " ++ "Ignored.\n", ++ buf, i); ++ return -EINVAL; ++ } ++ if (strncasecmp(buf, "E1", 2) == 0) ++ new_protocol = PRI_PROTO_E1; ++ else if (strncasecmp(buf, "T1", 2) == 0) ++ new_protocol = PRI_PROTO_T1; ++ else if (strncasecmp(buf, "J1", 2) == 0) ++ new_protocol = PRI_PROTO_J1; ++ else { ++ XPD_NOTICE(xpd, ++ "Unknown PRI protocol '%s' (should be E1|T1|J1). " ++ "Ignored.\n", ++ buf); ++ return -EINVAL; ++ } ++ ret = set_pri_proto(xpd, new_protocol); ++ return (ret < 0) ? ret : count; ++} ++ ++static DEVICE_ATTR(pri_protocol, S_IRUGO | S_IWUSR, pri_protocol_show, ++ pri_protocol_store); ++ ++static DEVICE_ATTR_READER(pri_localloop_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += sprintf(buf, "%c\n", (priv->local_loopback) ? 'Y' : 'N'); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR_WRITER(pri_localloop_store, dev, buf, count) ++{ ++ xpd_t *xpd; ++ bool ll = 0; ++ int i; ++ int ret; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(GENERAL, xpd, "%s\n", buf); ++ if (!xpd) ++ return -ENODEV; ++ if ((i = strcspn(buf, " \r\n")) != 1) { ++ XPD_NOTICE(xpd, ++ "Value '%s' has %d characters (should be 1). Ignored\n", ++ buf, i); ++ return -EINVAL; ++ } ++ if (strchr("1Yy", buf[0]) != NULL) ++ ll = 1; ++ else if (strchr("0Nn", buf[0]) != NULL) ++ ll = 0; ++ else { ++ XPD_NOTICE(xpd, ++ "Unknown value '%s' (should be [1Yy]|[0Nn]). Ignored\n", ++ buf); ++ return -EINVAL; ++ } ++ ret = set_localloop(xpd, ll); ++ return (ret < 0) ? ret : count; ++} ++ ++static DEVICE_ATTR(pri_localloop, S_IRUGO | S_IWUSR, pri_localloop_show, ++ pri_localloop_store); ++ ++static DEVICE_ATTR_READER(pri_layer1_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ if (priv->poll_noreplies > 1) ++ len += sprintf(buf + len, "Unknown[%d]", priv->poll_noreplies); ++ else ++ len += ++ sprintf(buf + len, "%-10s", ++ ((priv->layer1_up) ? "UP" : "DOWN")); ++ len += sprintf(buf + len, "%d\n", priv->layer1_replies); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR(pri_layer1, S_IRUGO, pri_layer1_show, NULL); ++ ++static DEVICE_ATTR_READER(pri_alarms_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ static const struct { ++ __u8 bits; ++ const char *name; ++ } alarm_types[] = { ++ { ++ REG_FRS0_LOS, "RED"}, { ++ REG_FRS0_AIS, "BLUE"}, { ++ REG_FRS0_RRA, "YELLOW"},}; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ if (priv->poll_noreplies > 1) ++ len += sprintf(buf + len, "Unknown[%d]", priv->poll_noreplies); ++ else { ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(alarm_types); i++) { ++ if (priv->reg_frs0 & alarm_types[i].bits) ++ len += ++ sprintf(buf + len, "%s ", ++ alarm_types[i].name); ++ } ++ } ++ len += sprintf(buf + len, "\n"); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR(pri_alarms, S_IRUGO, pri_alarms_show, NULL); ++ ++static DEVICE_ATTR_READER(pri_cas_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ if (priv->is_cas) { ++ int i; ++ ++ len += ++ sprintf(buf + len, "CAS: replies=%d\n", priv->cas_replies); ++ len += sprintf(buf + len, " CAS-TS: "); ++ for (i = 0; i < NUM_CAS_RS_E; i++) ++ len += sprintf(buf + len, " %02X", priv->cas_ts_e[i]); ++ len += sprintf(buf + len, "\n"); ++ len += sprintf(buf + len, " CAS-RS: "); ++ for (i = 0; i < NUM_CAS_RS_E; i++) ++ len += sprintf(buf + len, " %02X", priv->cas_rs_e[i]); ++ len += sprintf(buf + len, "\n"); ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR(pri_cas, S_IRUGO, pri_cas_show, NULL); ++ ++static DEVICE_ATTR_READER(pri_dchan_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += ++ sprintf(buf + len, ++ "D-Channel: TX=[%5d] (0x%02X) RX=[%5d] (0x%02X) ", ++ priv->dchan_tx_counter, priv->dchan_tx_sample, ++ priv->dchan_rx_counter, priv->dchan_rx_sample); ++ if (priv->dchan_alive) { ++ len += ++ sprintf(buf + len, "(alive %d K-ticks)\n", ++ priv->dchan_alive_ticks / 1000); ++ } else { ++ len += sprintf(buf + len, "(dead)\n"); ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR(pri_dchan, S_IRUGO, pri_dchan_show, NULL); ++ ++static DEVICE_ATTR_READER(pri_clocking_show, dev, buf) ++{ ++ xpd_t *xpd; ++ struct PRI_priv_data *priv; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ priv = xpd->priv; ++ BUG_ON(!priv); ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += ++ sprintf(buf + len, "%s\n", ++ (priv->clock_source) ? "MASTER" : "SLAVE"); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR(pri_clocking, S_IRUGO, pri_clocking_show, NULL); ++ ++static int pri_xpd_probe(struct device *dev) ++{ ++ xpd_t *xpd; ++ int ret = 0; ++ ++ xpd = dev_to_xpd(dev); ++ /* Is it our device? */ ++ if (xpd->xpd_type != XPD_TYPE_PRI) { ++ XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev), ++ xpd->xpd_type); ++ return -EINVAL; ++ } ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ ret = device_create_file(dev, &dev_attr_pri_protocol); ++ if (ret) { ++ XPD_ERR(xpd, ++ "%s: device_create_file(pri_protocol) failed: %d\n", ++ __func__, ret); ++ goto fail_pri_protocol; ++ } ++ ret = device_create_file(dev, &dev_attr_pri_localloop); ++ if (ret) { ++ XPD_ERR(xpd, ++ "%s: device_create_file(pri_localloop) failed: %d\n", ++ __func__, ret); ++ goto fail_pri_localloop; ++ } ++ ret = device_create_file(dev, &dev_attr_pri_layer1); ++ if (ret) { ++ XPD_ERR(xpd, "%s: device_create_file(pri_layer1) failed: %d\n", ++ __func__, ret); ++ goto fail_pri_layer1; ++ } ++ ret = device_create_file(dev, &dev_attr_pri_alarms); ++ if (ret) { ++ XPD_ERR(xpd, "%s: device_create_file(pri_alarms) failed: %d\n", ++ __func__, ret); ++ goto fail_pri_alarms; ++ } ++ ret = device_create_file(dev, &dev_attr_pri_cas); ++ if (ret) { ++ XPD_ERR(xpd, "%s: device_create_file(pri_cas) failed: %d\n", ++ __func__, ret); ++ goto fail_pri_cas; ++ } ++ ret = device_create_file(dev, &dev_attr_pri_dchan); ++ if (ret) { ++ XPD_ERR(xpd, "%s: device_create_file(pri_dchan) failed: %d\n", ++ __func__, ret); ++ goto fail_pri_dchan; ++ } ++ ret = device_create_file(dev, &dev_attr_pri_clocking); ++ if (ret) { ++ XPD_ERR(xpd, ++ "%s: device_create_file(pri_clocking) failed: %d\n", ++ __func__, ret); ++ goto fail_pri_clocking; ++ } ++ return 0; ++fail_pri_clocking: ++ device_remove_file(dev, &dev_attr_pri_dchan); ++fail_pri_dchan: ++ device_remove_file(dev, &dev_attr_pri_cas); ++fail_pri_cas: ++ device_remove_file(dev, &dev_attr_pri_alarms); ++fail_pri_alarms: ++ device_remove_file(dev, &dev_attr_pri_layer1); ++fail_pri_layer1: ++ device_remove_file(dev, &dev_attr_pri_localloop); ++fail_pri_localloop: ++ device_remove_file(dev, &dev_attr_pri_protocol); ++fail_pri_protocol: ++ return ret; ++} ++ ++static int pri_xpd_remove(struct device *dev) ++{ ++ xpd_t *xpd; ++ ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ device_remove_file(dev, &dev_attr_pri_clocking); ++ device_remove_file(dev, &dev_attr_pri_dchan); ++ device_remove_file(dev, &dev_attr_pri_cas); ++ device_remove_file(dev, &dev_attr_pri_alarms); ++ device_remove_file(dev, &dev_attr_pri_layer1); ++ device_remove_file(dev, &dev_attr_pri_localloop); ++ device_remove_file(dev, &dev_attr_pri_protocol); ++ return 0; ++} ++ ++static struct xpd_driver pri_driver = { ++ .xpd_type = XPD_TYPE_PRI, ++ .driver = { ++ .name = "pri", ++ .owner = THIS_MODULE, ++ .probe = pri_xpd_probe, ++ .remove = pri_xpd_remove} ++}; ++ ++static int __init card_pri_startup(void) ++{ ++ int ret; ++ ++ if ((ret = xpd_driver_register(&pri_driver.driver)) < 0) ++ return ret; ++#ifdef DAHDI_AUDIO_NOTIFY ++ INFO("FEATURE: WITH DAHDI_AUDIO_NOTIFY\n"); ++#else ++ INFO("FEATURE: WITHOUT DAHDI_AUDIO_NOTIFY\n"); ++#endif ++ xproto_register(&PROTO_TABLE(PRI)); ++ return 0; ++} ++ ++static void __exit card_pri_cleanup(void) ++{ ++ DBG(GENERAL, "\n"); ++ xproto_unregister(&PROTO_TABLE(PRI)); ++ xpd_driver_unregister(&pri_driver.driver); ++} ++ ++MODULE_DESCRIPTION("XPP PRI Card Driver"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_XPD(XPD_TYPE_PRI); ++ ++module_init(card_pri_startup); ++module_exit(card_pri_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/card_pri.h linux-source-4.19-dahdi/drivers/dahdi/xpp/card_pri.h +--- linux-source-4.19/drivers/dahdi/xpp/card_pri.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/card_pri.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,31 @@ ++#ifndef CARD_PRI_H ++#define CARD_PRI_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++ ++enum pri_opcodes { ++ XPROTO_NAME(PRI, SET_LED) = 0x33, ++}; ++ ++#endif /* CARD_PRI_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/dahdi_debug.c linux-source-4.19-dahdi/drivers/dahdi/xpp/dahdi_debug.c +--- linux-source-4.19/drivers/dahdi/xpp/dahdi_debug.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/dahdi_debug.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,77 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "dahdi_debug.h" ++#include "xdefs.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++#define P_(x) [ x ] = { .value = x, .name = #x, } ++static struct { ++ int value; ++ char *name; ++} poll_names[] = { ++ P_(POLLIN), P_(POLLPRI), P_(POLLOUT), P_(POLLERR), P_(POLLHUP), ++ P_(POLLNVAL), P_(POLLRDNORM), P_(POLLRDBAND), P_(POLLWRNORM), ++ P_(POLLWRBAND), P_(POLLMSG), P_(POLLREMOVE) ++}; ++ ++#undef P_ ++ ++void dump_poll(int debug, const char *msg, int poll) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(poll_names); i++) { ++ if (poll & poll_names[i].value) ++ DBG(GENERAL, "%s: %s\n", msg, poll_names[i].name); ++ } ++} ++EXPORT_SYMBOL(dump_poll); ++ ++void alarm2str(int alarm, char *buf, int buflen) ++{ ++ char *p = buf; ++ int left = buflen; ++ int i; ++ int n; ++ ++ if (!alarm) { ++ snprintf(buf, buflen, "NONE"); ++ return; ++ } ++ memset(buf, 0, buflen); ++ for (i = 0; i < 8; i++) { ++ if (left && (alarm & BIT(i))) { ++ n = snprintf(p, left, "%s,", alarmbit2str(i)); ++ p += n; ++ left -= n; ++ } ++ } ++ if (p > buf) /* kill last comma */ ++ *(p - 1) = '\0'; ++} ++EXPORT_SYMBOL(alarm2str); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/dahdi_debug.h linux-source-4.19-dahdi/drivers/dahdi/xpp/dahdi_debug.h +--- linux-source-4.19/drivers/dahdi/xpp/dahdi_debug.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/dahdi_debug.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,282 @@ ++#ifndef DAHDI_DEBUG_H ++#define DAHDI_DEBUG_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 /* for dahdi_* defs */ ++ ++/* Debugging Macros */ ++ ++#define PRINTK(level, category, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: " fmt, \ ++ #level, category, THIS_MODULE->name, ## __VA_ARGS__) ++ ++#define XBUS_PRINTK(level, category, xbus, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \ ++ category, THIS_MODULE->name, (xbus)->busname, ## __VA_ARGS__) ++ ++#define XPD_PRINTK(level, category, xpd, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \ ++ category, THIS_MODULE->name, \ ++ (xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__) ++ ++#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \ ++ category, THIS_MODULE->name, \ ++ (xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__) ++ ++#define PORT_PRINTK(level, category, xbus, unit, port, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: %s UNIT=%d PORT=%d: " fmt, #level, \ ++ category, THIS_MODULE->name, \ ++ (xbus)->busname, (unit), (port), ## __VA_ARGS__) ++ ++#define DBG(bits, fmt, ...) \ ++ ((void)((debug & (DBG_ ## bits)) && \ ++ PRINTK(DEBUG, "-" #bits, "%s: " fmt, \ ++ __func__, ## __VA_ARGS__))) ++#define INFO(fmt, ...) PRINTK(INFO, "", fmt, ## __VA_ARGS__) ++#define NOTICE(fmt, ...) PRINTK(NOTICE, "", fmt, ## __VA_ARGS__) ++#define WARNING(fmt, ...) PRINTK(WARNING, "", fmt, ## __VA_ARGS__) ++#define ERR(fmt, ...) PRINTK(ERR, "", fmt, ## __VA_ARGS__) ++ ++#define XBUS_DBG(bits, xbus, fmt, ...) \ ++ ((void)((debug & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, \ ++ xbus, "%s: " fmt, __func__, ## __VA_ARGS__))) ++#define XBUS_INFO(xbus, fmt, ...) \ ++ XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__) ++#define XBUS_NOTICE(xbus, fmt, ...) \ ++ XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__) ++#define XBUS_ERR(xbus, fmt, ...) \ ++ XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__) ++ ++#define XPD_DBG(bits, xpd, fmt, ...) \ ++ ((void)((debug & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, \ ++ xpd, "%s: " fmt, __func__, ## __VA_ARGS__))) ++#define XPD_INFO(xpd, fmt, ...) \ ++ XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__) ++#define XPD_NOTICE(xpd, fmt, ...) \ ++ XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__) ++#define XPD_WARNING(xpd, fmt, ...) \ ++ XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__) ++#define XPD_ERR(xpd, fmt, ...) \ ++ XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__) ++ ++#define LINE_DBG(bits, xpd, pos, fmt, ...) \ ++ ((void)((debug & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, \ ++ xpd, pos, "%s: " fmt, __func__, ## __VA_ARGS__))) ++#define LINE_NOTICE(xpd, pos, fmt, ...) \ ++ LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__) ++#define LINE_ERR(xpd, pos, fmt, ...) \ ++ LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__) ++ ++#define PORT_DBG(bits, xbus, unit, port, fmt, ...) \ ++ ((void)((debug & (DBG_ ## bits)) && \ ++ PORT_PRINTK(DEBUG, "-" #bits, \ ++ xbus, unit, port, "%s: " fmt, __func__, ## __VA_ARGS__))) ++#define PORT_NOTICE(xbus, unit, port, fmt, ...) \ ++ PORT_PRINTK(NOTICE, "", xbus, unit, port, fmt, ## __VA_ARGS__) ++#define PORT_ERR(xbus, unit, port, fmt, ...) \ ++ PORT_PRINTK(ERR, "", xbus, unit, port, fmt, ## __VA_ARGS__) ++ ++/* ++ * Bits for debug ++ */ ++#define DBG_GENERAL BIT(0) ++#define DBG_PCM BIT(1) ++#define DBG_LEDS BIT(2) ++#define DBG_SYNC BIT(3) ++#define DBG_SIGNAL BIT(4) ++#define DBG_PROC BIT(5) ++#define DBG_REGS BIT(6) ++#define DBG_DEVICES BIT(7) /* instantiation/destruction etc. */ ++#define DBG_COMMANDS BIT(8) /* All commands */ ++#define DBG_ANY (~0) ++ ++void dump_poll(int debug, const char *msg, int poll); ++ ++static inline char *rxsig2str(enum dahdi_rxsig sig) ++{ ++ switch (sig) { ++ case DAHDI_RXSIG_ONHOOK: ++ return "ONHOOK"; ++ case DAHDI_RXSIG_OFFHOOK: ++ return "OFFHOOK"; ++ case DAHDI_RXSIG_START: ++ return "START"; ++ case DAHDI_RXSIG_RING: ++ return "RING"; ++ case DAHDI_RXSIG_INITIAL: ++ return "INITIAL"; ++ } ++ return "Unknown rxsig"; ++} ++ ++static inline char *txsig2str(enum dahdi_txsig sig) ++{ ++ switch (sig) { ++ case DAHDI_TXSIG_ONHOOK: ++ return "TXSIG_ONHOOK"; ++ case DAHDI_TXSIG_OFFHOOK: ++ return "TXSIG_OFFHOOK"; ++ case DAHDI_TXSIG_START: ++ return "TXSIG_START"; ++ case DAHDI_TXSIG_KEWL: ++ return "TXSIG_KEWL"; /* Drop battery if possible */ ++ case DAHDI_TXSIG_TOTAL: ++ break; ++ } ++ return "Unknown txsig"; ++} ++ ++static inline char *event2str(int event) ++{ ++ switch (event) { ++ case DAHDI_EVENT_NONE: ++ return "NONE"; ++ case DAHDI_EVENT_ONHOOK: ++ return "ONHOOK"; ++ case DAHDI_EVENT_RINGOFFHOOK: ++ return "RINGOFFHOOK"; ++ case DAHDI_EVENT_WINKFLASH: ++ return "WINKFLASH"; ++ case DAHDI_EVENT_ALARM: ++ return "ALARM"; ++ case DAHDI_EVENT_NOALARM: ++ return "NOALARM"; ++ case DAHDI_EVENT_ABORT: ++ return "ABORT"; ++ case DAHDI_EVENT_OVERRUN: ++ return "OVERRUN"; ++ case DAHDI_EVENT_BADFCS: ++ return "BADFCS"; ++ case DAHDI_EVENT_DIALCOMPLETE: ++ return "DIALCOMPLETE"; ++ case DAHDI_EVENT_RINGERON: ++ return "RINGERON"; ++ case DAHDI_EVENT_RINGEROFF: ++ return "RINGEROFF"; ++ case DAHDI_EVENT_HOOKCOMPLETE: ++ return "HOOKCOMPLETE"; ++ case DAHDI_EVENT_BITSCHANGED: ++ return "BITSCHANGED"; ++ case DAHDI_EVENT_PULSE_START: ++ return "PULSE_START"; ++ case DAHDI_EVENT_TIMER_EXPIRED: ++ return "TIMER_EXPIRED"; ++ case DAHDI_EVENT_TIMER_PING: ++ return "TIMER_PING"; ++ case DAHDI_EVENT_POLARITY: ++ return "POLARITY"; ++ } ++ return "Unknown event"; ++} ++ ++static inline char *hookstate2str(int hookstate) ++{ ++ switch (hookstate) { ++ case DAHDI_ONHOOK: ++ return "DAHDI_ONHOOK"; ++ case DAHDI_START: ++ return "DAHDI_START"; ++ case DAHDI_OFFHOOK: ++ return "DAHDI_OFFHOOK"; ++ case DAHDI_WINK: ++ return "DAHDI_WINK"; ++ case DAHDI_FLASH: ++ return "DAHDI_FLASH"; ++ case DAHDI_RING: ++ return "DAHDI_RING"; ++ case DAHDI_RINGOFF: ++ return "DAHDI_RINGOFF"; ++ } ++ return "Unknown hookstate"; ++} ++ ++/* From dahdi-base.c */ ++static inline char *sig2str(int sig) ++{ ++ switch (sig) { ++ case DAHDI_SIG_FXSLS: ++ return "FXSLS"; ++ case DAHDI_SIG_FXSKS: ++ return "FXSKS"; ++ case DAHDI_SIG_FXSGS: ++ return "FXSGS"; ++ case DAHDI_SIG_FXOLS: ++ return "FXOLS"; ++ case DAHDI_SIG_FXOKS: ++ return "FXOKS"; ++ case DAHDI_SIG_FXOGS: ++ return "FXOGS"; ++ case DAHDI_SIG_EM: ++ return "E&M"; ++ case DAHDI_SIG_EM_E1: ++ return "E&M-E1"; ++ case DAHDI_SIG_CLEAR: ++ return "Clear"; ++ case DAHDI_SIG_HDLCRAW: ++ return "HDLCRAW"; ++ case DAHDI_SIG_HDLCFCS: ++ return "HDLCFCS"; ++ case DAHDI_SIG_HDLCNET: ++ return "HDLCNET"; ++ case DAHDI_SIG_SLAVE: ++ return "Slave"; ++ case DAHDI_SIG_CAS: ++ return "CAS"; ++ case DAHDI_SIG_DACS: ++ return "DACS"; ++ case DAHDI_SIG_DACS_RBS: ++ return "DACS+RBS"; ++ case DAHDI_SIG_SF: ++ return "SF (ToneOnly)"; ++ case DAHDI_SIG_NONE: ++ break; ++ } ++ return "Unconfigured"; ++} ++ ++static inline char *alarmbit2str(int alarmbit) ++{ ++ /* from dahdi/kernel.h */ ++ switch (1 << alarmbit) { ++ case DAHDI_ALARM_NONE: ++ return "NONE"; ++ case DAHDI_ALARM_RECOVER: ++ return "RECOVER"; ++ case DAHDI_ALARM_LOOPBACK: ++ return "LOOPBACK"; ++ case DAHDI_ALARM_YELLOW: ++ return "YELLOW"; ++ case DAHDI_ALARM_RED: ++ return "RED"; ++ case DAHDI_ALARM_BLUE: ++ return "BLUE"; ++ case DAHDI_ALARM_NOTOPEN: ++ return "NOTOPEN"; ++ } ++ return "UNKNOWN"; ++} ++ ++void alarm2str(int alarm, char *buf, int buflen); ++ ++#endif /* DAHDI_DEBUG_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1141.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1141.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1141.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1141.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,656 @@ ++# ++# $Id: FPGA_1141.hex 7107 2009-05-18 12:35:20Z dima $ ++# ++:020000040000FA ++:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF4000A8270A006AD6FF4000A8270A006AD6FF4000A8270A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B511115511115511115511143 ++:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200001AA1111AA111001AA11100001AA1111AA11100001AA1111AA1111AA113 ++:80010000110000002552222552222F21F112122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F1121200002F21F112122F21F112121AA100 ++:80018000110025522225522200000000002552220000000025522225522200000000002552220000FFF9F99F9F7F78F8878700000000000000000000000000000000000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000000004F44D4 ++:80020000F444444F44F44444000000004F44F444444F44F44444004F44F4444400004F44F444444F44F444440000004F44F444446F64F446466F64F44646000000004F48F884846F69F996962F21F11212000000CAACCC2F2DFDD2D22F21F112124F48F884842F21F11212004F4CFCC4C46F6DFDD6D62F21F1121200006F6DFDD6D66F6DF0 ++:80028000FDD6D66F6DFDD6D6000000008AA8882F29F992922F21F112120000004F4CFCC4C46F6DFDD6D62F21F112128AA8882F21F11212004F4CFCC4C46F6DFDD6D62F21F1121200006F6DFDD6D6CFC5F55C5CBFBEFEEBEB006F6DFDD6D66F6DFDD6D6000000008F8CFCC8C8AFACFCCACA255222000000CFC4F44C4CCFC4F44C4C008F8C66 ++:80030000FCC8C825522200CFC4F44C4CCFC4F44C4C000000CFC4F44C4CCFC4F44C4CCFC4F44C4C00000000CFCCFCCCCCCFCCFCCCCC000000008F84F44848AFA4F44A4A255222CFCCFCCCCC0000CFC4F44C4CEFE4F44E4E2552220000EFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F84F44848AFA4A9 ++:80038000F44A4A255222CFC8F88C8C0000CFC4F44C4CEFE4F44E4E2552220000EFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCACA255222CFC8F88C8C0000CFCCFCCCCCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFCBFBBCBC3AA33379 ++:800400000000008F8CFCC8C8AFADFDDADA2F21F11212CFC8F88C8C3AA33300CFCCFCCCCCEFEDFDDEDE2F21F112120000AFA9F99A9AFFFEFEEFEF00EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA888BAABBB3AA333000000CFCCFCCCCCEFEEFEEEEE2F22F222228AA8883AA33300CFCCFCCCCCEFEEFEEEEE2F22F222220000EFEEFEFD ++:80048000EEEEEFEEFEEEEEEFEEFEEEEE000000004AA4441F14F44141155111000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F559591F11F11111000000CFCCFCCCCCFFFEFEEFEF3F32F223238F84F448481F11AF ++:80050000F1111100CFCCFCCCCCFFFEFEEFEF3F32F223230000FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4C35533300CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220092 ++:8005800000008F8CFCC8C8BFBFFFFBFB3F33F333334554442AA22200CFCCFCCCCCFFFFFFFFFF3F33F33333008F81F118189F9EFEE9E90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AA222000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFF8D ++:80060000FFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4C2AA22200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F886862552220000008F8CFCC8C8BFBFFFFBFB3F33F333334F48F884842552221B ++:80068000008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000004F48F884846F68F88686255222000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F8868625522200009B ++:8007000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F33333EAAEEE7F75F55757000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F44F444447F75F557573F31F11313000000CFC8F88C8CDFDBFBBDBD1F13F331314F44F444443F31F1131300CFC8F88C8CDFDBFBBDBD1F13F33105 ++:80078000310000DFDBFBBDBDDFDBFBBDBDDFDBFBBDBD000000004F44F444445F54F445451551110000008F8CFCC8C88F8FFFF8F83AA3334F44F444441F11F11111008F8CFCC8C88F8EFEE8E82AA22200008F8EFEE8E88F8EFEE8E88F8EFEE8E8000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCDFDEFEEDED1F12F221F8 ++:80080000214F44F444441F13F3313100CFCCFCCCCCDFDEFEEDED1F12F221210000DFDEFEEDEDDFDEFEEDEDDFDEFEEDED000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCCFCFFFFCFC3AA3334F44F444441F13F3313100CFCCFCCCCCCFCFFFFCFC3AA3330000CFCFFFFCFCCFCFFFFCFCCFCFFFFCFC0000000000000000AF ++:8008800000000000000000000000EFEAFAAEAE3F39F99393000048180000000000000000000000000000000000000000000000000000002F8D020000000000000000000000000000001400000000000000000000000000007EBD000000000000000000000000000000000000000000000000000000000000FFE40F008084010000000000CE ++:8009000000000000000000140000000000000000000000000000DFBE060000000000000000000000000000000000000000000000000000000000F04FFE8002004001008004148002800414800200008002800400002148000000480000108204000021AFEB050000000000000000000000000000000000000000000000000000000000F08F ++:800980004FFE000000000000000000000000000000000000000000000000000000000000FFE40F48180028000000002100000021001400100240010000400128000014882800008088020000CFE40B008084010000200100000000000000120000400100000000000014000000000050358084410128004840818102214860118002211AEF ++:800A000001148002211A041400B01281041480028004148828108204808802214800CF550648180028000000002100000021001400100240010000400128000014882800008088020000CFE40B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000018001800000000280079 ++:800A8000008088020000000000F0C59D000020020000001002000024000000100200000000110000000000000088220000D0B60F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000800130 ++:800B0000000000000022000000000000000000F0DF2F00008002000000000000002100000000000000000000000020020000000000F0FBF600000000000000000000000000400200000000000000000000000082280000D0E4010000000000000000000000000000000000000000000000000000000000F04FFE000000000000400200008F ++:800B800000000000000018000000110000002008000000000000CFDE03000000002100000000000000000000000024000000000000820000000000005F580C000080014800001200400100000080420200000000000000000000000000280020F23B1C0000000042000000000000000080020000002400000000000000000000220080F27D ++:800C0000157E000000184002002001001400000000400200000000000000000082000000000000DF350D80010000001200002011011848000082000000001880010000000000000000000028E09104000000000000000000000000000000000000000000200200000000000000CFE5030000001200000000000000000000000000000000A5 ++:800C80000014000021000000000000BF640D0000000000280000000000111211280080022200002800000000481400008002000048F0BA9700000000002002000000000012000000200200800200001400422400000000008004EFAA0D000000180000000000000011108102002800000000000000001400008002000000DF3F0900220099 ++:800D00008001002200000011002811000000002002220060122002002220020000000000007F2908220080012880020000000000000028800228800200000040011C02000014100110010014008FAC0A280000A012800222000000008002002820020022000000001400002002000000001001F0ECD30080021800000000000011004001DD ++:800D80000000200220022200902180022601280040011400110000008F5C0800280020012800281400288041010000481800280020222224020021001001000042602200002002EF4D0C18001200000012000000000000200180020090114001000000222002002200000000001FAF0F000000000000000000400100000000100100000053 ++:800E00002828800200200200008082022280F2E52C800128000000800100800200140000480022284001381081022032220028140028004220128282022822286FCC0B0020018001220028140000121400000000000000224200000022002800000000000000EE6C00200112280020820200002002144001C0211C01000020021122112243 ++:800E80001120021480128102100100000000BF150A1822002001220020020000001001110028002228003021002880020000140014140022202202004AF22FCD00002812200200000040410114002820020026410111000028000000000000002220020048009F1106281820010000000000280020010080011400200200280000002228AD ++:800F000000100100200228002800BF540700228A0200002002000022142002001840210222001818000000000000001302000000688084D4AA0BA01218202201800200000000281128110011000019022822C021C02128222822001322422102281400000080027FCA0512001800120022000000000000281122000080018002144001143D ++:800F80000000000000288002260128001FE10500002022218202000020322128143021281B12112042211211611212004001144001102142211201142200002022C441222F45082280060022000022800214100100108202804A01004001008014010040010080020000001002AB5B800212221A22818102800200D0116212142222132226 ++:80100000B2218182022217121420022822000028000013E21222A2224001222A2202138222E61224F6A6D6001A828282A1121200220000001982021CC12114141713267121118112A12213A1213210F121211B221F12021D212A02221C12114171211191210028282848601468BF12033AA1122AA11180A222222A8222A22200200213525C ++:8010800011119021281081C321A02215C12118C0212E21400117120028150140110140810220022268006F2C040000000000000000000012000000008001180000000020020000002800400100F025E6A0221A021AA1A23AA22228222A22220200141F12A222111F13F331311D211F1173313121B021322117121CD21182A1111A13D111BF ++:80110000021D21F021212AA2222E21281551111C0215D11102202282A2444A8424F49425A0115AA6223AA6811A81812282022AA22280021D21151161122E223B223AF32321F0A19113D2115A11141AF311111AE111A32215A1441D21681F120240D111C221C0211F121201222280A2226E422B4430422F1C011AA2711A03A0222828222AC5 ++:80118000022A8202F021211D212AB221F221211F1252131F11D311012A38212217122E211F1363113A032A7221E112D41192211F12A2222AE21282D21152111428155111282022A222B042046AF6EE37A0211AA7217AA3113AA3312880022A8202221B221D211F12B221A2133A33223E121F12A2221F133821AE21171226A1131E111A115C ++:80120000A1221F12A2621F12A2261F12A2222AE212F221212A02141D21002A222222B22102212E226AF68FD62002002A01220020020010018002280000801201002220022220022200002002000000004220046FAA03001828200100280000200200008022020022200200000000002220020000002880024A0228226BA880B411021B2143 ++:80128000421B212394212B1419B24299212B94112B94222F1439212F1429D312A9421CE922C4811F2264112E4296F1214296C1429AC2421B292CB49142B29122B49132621B28271419B24298212F1418B14228B2422AB2422892822A84E82274390C481B61481B21421B212394212B1419B24299212BB419B24229F2429113B2423931298F ++:80130000B93394821F2285F921C21AE82264191F2224C9539E212CA5293CA4693CA42946B1913242822714282F1488F242A1F04281B04228B2422892822B4229E822F44BD800824800000000002800000000218001880000400100800400000000000000000025019F2406A012001AA2348002222002000000128021912100400100001871 ++:8013800019010000402122020000000080062280F4499BA01282200100880000001812001140810200221128800220220280229211100111200800110080040040012FC60B28D28081810222200228220012000015A2211832201A81022200281411A0242814001414280020020020044A42224201E74180810220A24180080000800100C3 ++:80140000141200100100110000A012120020011180028200100100000000481F370F2001A0122002000000003011000010012004422084010010410121200200804601002880020000CF26011220010020010000002002100100000000000012200222281922822122022800000000002822F02BD7001212800220010000000014000000D8 ++:801480000048800420011200802242012820020011002002220020022F120818002001280000000020220114004001000080040020421141828222810220A242000000002002F0A8F780210400002601000000180040020021A01280840200808282022082840140420200261112022820024280F215E2004222320022000000B01102483C ++:801500002814006012218041312200149011100128800400102104112002228004000042879300008002000000180000200100180000000000000000220000000000A024000020023F5E0B18002222204201008001182024820121200120022B4200148081120122802282014082144201112428284220024880B45903002212008002003A ++:80158000004021014001001C0200148002000028220020040014000010024222000028229FEB0B1200000022188082818101111C0118208212114101A02124121228000000001A028022022200280000424880061F8F062880022C2221022428002C041800281C829411118082A22413011341716291421C0414E0111242924114100100AE ++:80160000146018004282800222006F8B0538180022200100000000400114406124001448144001002622962130211922021110110110211481022800482024721E0300A041004800000020E4148204480021C011182122102284046248002100110022000022282A0400420000F0A281001222200100003200001820020040016222004A99 ++:8016800001002214001820024828000000002A2402282002001F33040018180028A0420000000020022A042848008004122210022902201101002AA4244813240600000028800270910900004200290228422381A44124282602602420120200A02129D222042306004002800400808202822842888024240C202AF2B9D400820000202198 ++:80170000010012202131310014468124241241E11441410118180013944111112092311B3448C0419041139441110080022240017F8A0B42281A84A218281220028002280040C141221082024A81851AA224221440B142022912A252004810410186018002424868008014C2411F110C38823842C682210322222A832121A4413F1492219D ++:80178000225E41141E232944F12111114E211F1244E11234414E43424A227421916113322320B221346111221312D111324117141382A246422A84A8642A6214F0DEC9A0439A22A2313A82022B211602421A22A41120A1432D21112A2456114E426848A0241AF5423226B123A3122AB423A664212C81932119A634384E6113A4441CA2462D ++:80180000A0484A240422286A2682E412AE428FBE0D802101188027A2342810C25280A1121C11A1221394432AB221026E231B521AF1232213F11252122D624012623227111661122714164121C2211CA284C0A1C0212A0C8A26040080F259D5002220022302211002232211A241211002290242204402184280020020220430220048800426 ++:80188000488004800A8880084A084AF2B874A04D3220A3452F23F112122F21B1527522F252522F22B142D422F142622F34F7131126F243433B241D42281D413F2352223F2697413F23F213125E6237312B112CA6421F12C6233F31F312211D61425E111F117341014E218A6814AE81C6F141A18AA8CC88AAAC88AA28A48842DB8AA0541A6F ++:8019000024A1414AF412122B333AA3752F22B25285A1762F24B552A6751F2151233F26B64354311B2217221D112E411F3838313F33F833123F21F153423F17C5621CE412C2232F35F732311D612AE213E113E31262121D211B8815E1186A181CAC62426AAACC6AE222B222E2189A221FCC0D5AA663383AE225A6332B112AE32587B252A7BC ++:80198000325E624A95121F13F1311323F241411F26B623B462F421411F1657111F269E513F25F413522F23F733135E712C62262F12F442612F31F712332CB261E613E215F741214AB461B2C16C14CEE1C6E114A8222AA22A6A28A6422BEE486A745C03EAA7233AA3277E723AF2122229E32587F272722B325E724AF572523F17F731311FB8 ++:801A000022B263F661623B663B461B461F16F621433F26BE71F5F3623F27F773723F23F732712CF641422F16F662632F33F732331F36B261E615E415E714E616B461B6E1EE14E41CEC1CE414ACEE6AA66E4AA88E6AB4E2EE36A6647E54800100002A0100008004190480020010A12480029012422901213022A01240010000220000482820 ++:801A800080022880029F6B020018800120210220011200380000220000A012422180A12480428202001A06282240010020021C04482002F0564780B511021B2146B211724292612F2491212F24B911F2429213F142922AF442931B432F3429D312B921C4912E421CF8224216F1225296F1214296C1429AE222B491C2421B2926B29122B48C ++:801B00009132421B28271419B24298212B84112B84222BA4222B842229A842882E42FE4220B211A4421321B211041986B111A6921B414ABA1182A9421CB93184B911A4A433A2942B121CB921AC841F2221D921A4293CE419C242D2349AC6431B29429A52128A56121B68218AD612A2482F1428BA4228BA4228BA4238A22B8486F2EB1A00A1 ++:801B800082000000210000280000000021009081000040210100482800000000000000000025014FBA068A221121012818000000002200000000100122D02202422262200600422800222240411103808282240200142FA3082028081118286021282603000013011681A8141800260200230411210028800214211414390648800A408166 ++:801C0000260400624214423F510628D214001AA221004001220020011C8148820112262208D022841202E01482822404802412912228620026421121A4428084E2220414F0473B0020284101002C8162220000221400A014000011200240914228002228101112011904001B281400222002004880D4F2090000000022C01100008012411C ++:801C8000011800110000004A020000280000902100804203340000484222002FAC0620810222282218802282118121210100296112142800E01442012C4122012122223012101311012C2204000028808882220248D0C80680012022021828228041818121011414104101002042012CA1241210828282820100112681924220121142232D ++:801D00000220820600F03CB7008002002800C0310000200224183220120160140040020000104212110100000000008800622242F0769EA012C081280010021262008280041B21160133021082B42111A2242502120000230400480028000022244821828054222004E02B0E200142122828400100001A22030029020021802101204401C1 ++:801D80001130213022B011048004110011002280062006214242FBB814008800202182022012020021000020010014000080110200000010110288000000238402200290A7141A82118102203222132281622280286127B0218121C22120015021138102421C012C011D220060110048280088002448A02823A42423024A2284F422150040 ++:801E000000808182010042000000400321002024022C04210000C04228004200112501100140024200482100F03AA3141C61121426611210022901280000C011204201144840C121001CC4121E61241002111001354242726142114142426224110040622400007FDF0D428002009033281022D122052991222113D2230429011440829125 ++:801E800041250222241216011A041032122848112084044200484222820082422984FA5B56000020020000100114141200122022820200E01582052200002200804481020048140022222110020000FF98081110011128108214820110824481140226410129C1232C011240424102001429F411221111112912111281143182101301005B ++:801F0000100200F08B350000001260223880138101001114142024E11481E2148244011442338561241613011A028022021C04141081042032222A34424820823422EFDA0D2A840200282A811181021A1201202282043214130480611228000048800414140000000000A04810022128004828482F174E8141813221100248422442422994 ++:801F800084141222843262211800104282B442322218400220A441212C4102422124428280140321C80040A2848088F83A262002002480032400104101180020212462220000A0123100520018001440810400110011100229840242C021F0B16F008004C042104121410280C6413438484082022119A552A092112002400112218004489A ++:802000000028004840818204420000822114DFB50516116112111C122223225522421827143562112F21F131312D6213942213A1125260222D533A042F24B412F341112041A2442F25721103142419D422F22121211D8146631425C34127242A046026B0820C2E8386E2250B1B66221902172248B052D1228382F241221F21A144158282DF ++:8020800024C2632CC14119C6711F11D211962115F372611F12E222E4238481351315D311042721312B422F124231424242483928344322212D2223143242004E412AFEB3BB14181C022E21E023D222D331F22141122F23611148142B441712237441313217132B361413F222422324A23415A2111591222F21744282A411182A53112CF16A ++:8021000041214632412CD4118414C142112CD811E4242AE62A84C24242EA84025F3607000082420020022200000000124220044221802104422094121002002248008880888408A8488848280020F4A3C414141C4241D111E62135126E711AB142D522B141B453F542422B64F071132F2656322F147412E313A1112F2352122E111AC562FC ++:80218000273166F2331323A1112427312914532319F441621D221F22F22123421714CE828E82AEC215F281822F2AB8A298A22F22FAA2A32AA2AA2A0A4FCA4751114E611CC2611CA6715AE711F333112B542F26F541513F17F743432F2456213F27F5634227123F34B562F312311B352D122734AE812F11D5227E1233313F27F113115AE1BA ++:8022000011F1111329A4773F1181744163261F32E232E614E418E83C58311D222F28F8C1E12B2425B222FE22A2AEE36E622BA86A9A229FB74DE113C24126E112E218E22761212F35B552B762F612321F26F753713F24F443416E623F35F542432F34F462612F13F462411E511F36F522422F34FC21223F32F432424E723F31F552532B51E9 ++:802280005E5227353F26F313521512D121D221F241423F36021F18C8422D421F34F6C18219F422422B46CAE22EE62CA8C82BEE2AAE46AFD848E113E6127621E116C2217AE327F732333F17A7662F27F761723F357743F263431F26B773F761632F36F673732B577E711F37F761633F36F662E31F37F3F3733F37F673723F27F552512B55FC ++:802300003B553F35F563722F235731421F34F662621F36E636E614E414E43CFCC1C31F24E424F4E1C12F2EFA62422F2EF6E262CEC28ABCC2EE26AE669F9B0A222002224826A2410024408144224182C42212108112810242001828290121422A010000220082A048204802000000005F7A0A180000D02201200190124081849341002812D5 ++:80238000001081921128000018400118208204008A04400142800A290A808422E81101481B21B01122B411324219F2421119B24299212B9413B14239212F1429F3429113D312A9421CE922C4812E4216E12264191F2265192CA4292CB491C2521B29341B296E111B2927141B28271419F2428119B24218F14281222BA4222B842229A842FE ++:80240000882E42AFB70A1CA4611CA42146B1113242282F1291412A99412BB41B214A39212B94322D811B432B8423E214B922E114A9821E812E42D6B123214DE31D021B29589AC6418AE236A129348A6614282F3498212C8AE614289A22AA54228A84B2A2344222EFFF08208804000000008002000000100200880000400100800400000039 ++:802480000000000000002501BF2B0F0018004082012621431182010019021A1203802492215012111100521021043120942100401112410100282880042004DFFA4F21210A1C22A14160223200821824B0113A9140024AA32C001904142818181424802942611218181440012A08142A0C0000482924021C4221F82E2E1412E23021003075 ++:8025000022281C2253212212219E211414C0222E13A82091418A12816211140029442122641620810400881502133621008082040019621429F8136F008001181A0412290120880100982224124248808412013180410112981114D01201141942012240210800002223A4420000875640814221014001221381012C21081388924114A049 ++:802580001411001001181C02282120822202211002141124001902000080022800E0F8032A012A81C211381AA21616824C2101111622C411182239C121282211482002B0230120A68130411413118133422C031CA28215224C013482A682C4424A822422025FFD0E1923E21122012A812121B28181212171824132411B21421C0219042887 ++:8026000020442182712162112221A081284032118012221261222A1891A1003482882082042822F063D900002216011CA24216221401001888901130131AC2211001000028002A24024E211450211842160311408214010026826424286800F088270080240822112880013012821C8381888104111041021931812211E02184A41282183A ++:802680002A042100AA8182122222042B422442428002221C24A842285FA142A1421211428021032E4100112601202204C0220018212218920048111021140160122A04800442210022002224482220982200AFA30B00201801482400202208002110012200004200602100002812804803460290214200002028024032214820F43E3680D5 ++:80270000264101112A2125D212820128928216A112486014282712C011902246311110612416212483342112B0813221E0228D2432436242204402A222292222928268C0622F140F000000260142001125010029280100000000228021140288122A0421100222602200100242488004A024824A026FFA01181400194202258181682A88DB ++:802780001B818002184001481448140010B212C48111824282809222121116C2422621C68122241400B042024A028082840CAF5C4911016011202422041242101202103241222238A02122C816814481A2122B3824108381288102000000800842C0829082F02282A08221C8CF1F0E208282022621811581B212A242002042819112128059 ++:8028000001601428271414111242282AA18142100118C061400248C0E210010000290400287FD60700002045021001112400002888C041E01224A8122083A8420023A148211B282100220030415021006024A08420140200003FE30A1440011221001812C81AA8820021284042011904228602008E128813482229243881142824184022E9 ++:80288000B84118621411482100422002428222F0818D201101202221121122480216810220041280021842182E828810010028001A0223011992212228800225128102222082A4280042212FAD0C22002248C041800233810218238112D212144102001110011240018840028041011052120000200A260186221802820082CFC50242A2F6 ++:80290000141C012722800122113C04400219532240311122158211334219A28421292484051246813122142383064834C041144814144002001C04281C22F2CAE220022A041211168132211400A021002042A212801122A81280290230122342012C91419042111418002C02210029324320022A082142212CE45D091C31812226A1311384 ++:802980005612190182181CE52981C132226A8122782231121B11E023A42A111A5222829E831D812E8246A2898AF83121382C2241A3423F1662281B88272227342A180123C2224229E226F8222121E032C442BF644301A691211963143CB671E215B621F321A33F11B8A1782301C0223F11F243521F21A2211C21F231218EA11CD432F442FC ++:802A0000411F13F4313139B5C2A5518A091B448E521117121CB14123043127121F14041B4C2D831D4217348229EA289822CEC288CAEE18A28E4C011B6328141226B212C1122127111AE12EF64222882311124262122D1119B161C6414A15F34182AAB321A1882F2484E221B282B232D632E533918227332B111F2222F31323E01666242864 ++:802A80001125237642016A4CA246006822422837B3200400482A816422122008122400482041024A22212428044A82A12488422A299482421800482248800448A04880048A048A04820028EF2E4631111324F231311EC227213D61D022F133333F3BE7326612122F21732353132F21F31211123B53B021F492A23F28B882F113122D823E9A ++:802B0000C2AEA22F13A3191A6A249E813E322B223F21F233722F21F3131221CE812E822F124252223B4A342CF26222AE222F263222372223AAE66AEC26F473F7B021B24116F131711E122B213D1135F113123F33FBB3713E73AAEA21F11212173235F113732F11F113113F21F1131119F183931F2CD813F873323F31F19293AEA22F3F739A ++:802B8000B3A3B186F352111F3BF152511F12F231623F31F1337227128E833F3AF8226115D332D431523215F322222E222F2AB222B222E426B4E2AEEA2B4EAFAA4BB151D41124E211F1F17327213F15F631333F22B113A1FF1F38ACB923F112123D232B752F23F333112CB113B562B631E52CFD83C22BE21B531F13E713FCF1D21B93DE6354 ++:802C00002F29FE52529E937AA6511F23F233332B341F15E124F4C2816EE22F12E22454223BEC46A3446E222BEC6E222BEE2F32B2E2BCE2AEEE6E423F47011B761F1256117E311F37F753623F37F763633F23B123FBF1F15EF31EB22F21F112123F32F272722F277723F313133B513F17F721721F3CFCC1423F16B671F57171BEF11F3EFC21 ++:802C8000F3D32F3FB792FFC3422F3DFDF3511E511F12F271332B773F37F742432F3CF8E3E32F16F643432F3CFCC3C327341F14E42EBAC2BEE2BAE2BEE2AECE2BEEEEE2EAFE2945A0126012C011400126236132400124122081022812002821283190830010021820022D1240022C08240040022C0200202804DF150F800240B21102122496 ++:802D0000822081081813421281021800822821901216F1228212888A8221C1821A121211922122282C8802000080220222A042006BC7C0511B21B01122B611B242B111B242B181B242B911B24219B14229F24291B22F1439212D911B431CF9A1421CF8214216E12264192E529E212EC29AE222BD91C2C31B293CB19122B69132421B282778 ++:802D80001419F2628119F24283112F1428B24228F242822229A842882E42BFE6091CB51186B4112294412B161B614A912129B911B6423B114A28F242913AF4421113A29433A3B43F22A1941F2228E522E81DC212566132D6A112DA42A3693CB59122B29194128A5612682F12A8682DA3681CA84A29A84A2D82AA84B8229482AAF4442A004E ++:802E0000824800000000000000000010020000000014000048000000000000000022002501AF77096011004642C11224C021821282483412241302281A82024810014811002522818802001442581224A04828002480042904A0828820F4992214428AA22130114A012811422028611129883211B0430913081E811082C21119216226199B ++:802E80008E8232225621828128115312282501004A1821681435820AE02802281428BFC84B8134E11A021A34531221902182183A3811138832111C2225F2811220A941B0819211139421483B84282D12141C82A214D021C1412B1428251102224A38211013D2222804288228142B24CFD8062001400180521248200848252241022D818040 ++:802F000022424102001820821282A282520088001118008A040082421C840220982282003FA207008002119041800412002412218A8402252101000029042924941212244288100224480046A24824822140012002822008488F16021128001E2166E21124021A082118190111281811CAA1421C0682481B241C0613C121202886013013F5 ++:802F800016E22211210139A42822144621948148C862C82B4842222228885F790C14280016C16218130448248041414221222DA248221B14808824C442422C61124818429042821D121229521242240023044A2824488128C282484A888202885F260D008082123141288009122001182140C1121C84020026C121102144222823012400B9 ++:803000001224189041CA221A111342818484A44288008822486FC44481021142487612011442118044A121188001B02291826A810828A222112008241082842409424E31822850224880828408484A02800842F0AC3980042846A121A0122054128223A48121282CAA48101102002D622C88B182212188240219012CA3181E420040022481 ++:80308000C20025220A00A2002502240027E30000280000001200400100004A080020044002214882884002142A098828000000244810120222800468FF2602480019A2526E1219014227148200141381A1840021230E122CC28242292173818234A22038822D221A246118A8B041830282242C4402482B482096429022210028EE6B20027C ++:803100002601002240013C81E42409201A22410118824AA24820820200802401122C0829212124988228272400800800292802808824C4425EC8200111481130221221482290C21214822918A22148208888B441C2422C2224C85218C8602411C01140818808A08414C22086C48142424E824A9A424222005FB40548006024400242200452 ++:8031800080A4832004428888C0128800130400201202182343024AA8121C344200408184881882A882008221882C28F2FA470011120039849121182E41B08322011C0413B132542148130519B42188661A16829841904100209C522114122011411162241186113241428A046200888A2422F84271001248108121A64119828109C021A0DB ++:8032000084008A3281281BA4248008E82C230182A01800208824240C8A21681800481428222902002004007F1A042004000000001C812C240E00800158001121140000402228081E8380081F28841442020024241480820200002E418FEC4F218492414800212084A814421819892181014200808181011280088230521200218A441103C2 ++:803280000042008068184800A024480000BF780B14112A04004691216022114091222411A2131A028822210022881132332292828012220C68602420622C2260242280020029C882828004F01BB610012A014819450113C1111C884502C0121C86E8314881C6114200110046011C01C6221501488A815122C081105112201803802218021A ++:803300002221228282AF4B0C808194212002422200881C825822130613042A31133083682D124829B891562219B4228444014288C0424081C1121C044225422194222E8230421002829042F02CF27041314111421CE43134415E12684823E13814B181F481E24E131E421CF4824258184A84A4C8483CB442641829DD3284A74258521D8252 ++:803380008A3552888830823B212F2C5C222F24944127242B8C4E418AAC24CE2227262282A022A611F2E29580C4211E3111B042E211E2127261F151111B882B872E414E91B011FC82813BAE3E113714DE411F11C9832F3772C1A2A62E133363151B16CE81424E822933C2223C911116A24C1BC1CEC2111F18068692811D613B884E23C82B31 ++:8034000042E028F86242C8CA2CC4A2BFDB08181A2182764192112F2294411AA1A26E5119E12D39122F1731A21B36181BA4BAB823AA2A1B1DE01212B311E2247FA10237238E8223E928C4512F25B881F882221F1CF523934E131C41A184157142E11846423223238AA8E82B6488230C88AAF44EED002260122082040012A041241A842209AA ++:80348000C0228220012180218488028081024A8281921268808688026800002400822008006FFD41A1775AA11119A6667AE726F673333F15E524D522D33372B321D422FB23811F15FC63E11F1EFEF1D13F39FD21611F1FB662AEC62F1EF721611F12FAF1F11F1DFDE1416E422D222B231F1BFFD1733F3EF323231B6A5AF6F1313E711F1E44 ++:80350000F2C1431F36F662623F3CF8C3C14AB441A6CE2F2EFC62E22BAA2AAACCEAAEEA2F2EFEF66B141B771AA5311D216AE627F762623F33F76371CEF22BA81DA11F153D122F2C7F63F1F1533F1FFF41E13F1FFCB3933F16FEB1F12BF71F12FE62E11F33F371611F1BFFD1D11F18FC61C32F29FA92811F1DF1D1F12F2ADF337881F2D161F6 ++:803580001F1BEF15F541C11F36F663222F26F2C3C33F1C2EA444EEC22F2CFCE2222BA8AAE228BCE2AEC82F2EDEE549A1453AA7111B221B446AE226F271635E714E322F2BFB23333F1DF6C1122D922F26BF53FCE221FAEF2FFB12D129BDF1FE61733F36F663E11F32E627E716B7F1AF5FEE432F283B121F1DED23FD937337393F19A9871FEF ++:803600001DA7DDCAF4E1623F34F442432F22FEC2E11F14E414B462FAE2E2EEE22BA2AEA24ABC62AEEA6EE26EB8141B453AE313F221211F14F471721E721F37F751714E732F2FFAA2B33F3DFD92122BDE2BB62F2FBFF2EF2FF7F2F22BFF2BD4FEF21F1EFFE1E12B661F31E325B462A7FFFEF22F1EFC92B23F23F641D1EAF991333F3BF29321 ++:80368000932F2BFCD1F11F1BAE8C2F2CF463632D432F2EAECC1F34E434FCE2E22F2CFCE2E22B2EAAAA4C2BEEAEE2EEE25F46080018004001228A6422400124004800004A328142111022949242189092800125011440038044220848148AC4224828002024F8DC228011810142F04212198291414A01981B49A048189A84A2484A218AA939 ++:8037000042422242184A82219582422413C4928218A094922324084825A148809482AA6424C0A248888A8462389F7C0B2AB411021B21421B212394612F24B111B242B911B242B911B442A94B2F1429F24291A22D913AC4912E421CE82264152E5296E1226C192CA4292CB5D1C2421B292CB191A2141B6923B481B642B881B24298612B84DE ++:80378000112B84222B84A22B84A229A842882E422FD906581B61A041421B212119B242B111A2841B212BA413813A112F2438212B94119833032B521CE9224CF121D2921D421AC2438E212CB591C2421B681819A6141B2123A4282714193242282F141AB14228A284222304299242A82D421F8C0C00000000000080020000001002000000D7 ++:8038000000140000000000000080020000008221F0EC2C208101122C456214406239121381A118241A040048824A02480023C41118802284840162A012286A0122109241880042468204482822282800271E1440412102360113611490812C28188108296114822446812108291482018886A38129AA219083A0811C8818B2423A422AA8A5 ++:803880002C29021C32811988C8222424C22D428240014F254E216114004238141C2174821281A882988280818468241D42588227212C248821A1811421132E2481A8244AA9212E821A94E2482A682C4E21106112203462212CA4A427222C8802F063460012141AC2121123041413813911291141A2412111008822800424421180A8292143 ++:803900001A421201C0812002230223028828881B48884002808402002F2F030022280010110220D81228081002208801200A00200100C2880000502210821482120242100200240082A0486FC30D320000621442206618481230C142C0A2884682243C1160284219042CC24148C23200820029882AB481122268142004008A04C260248055 ++:8039800006F0DFA5800328006200212A348124180046022A28A88429A54818828248484062140048008200272888421442881904424800C2800823042A0C887F140C00800240914100809C81884E810010020011221012013220A4482A2908000026022F28022122210024002004240080F4DF7B0012192104222094412008AA010060113D ++:803A00008602116014214021884182041121481111481902800114100200142820440224C04200AF840400202604408228052123A28400800220890A2D4212B082412208213B248A21084820892424288824220214298C0288299882288018828CF22EDE0000114002188280041041A1944AA8841A24022002288004002E510000004002CB ++:803A80000020840828800C210082800400CF3504001214482C02241C84A1483012481118C89AA24828138988448242B1428131824829B4422288149141804A22240980260213826418D022285822A2A048424222CF7E0A20418102001A044824803881A04890412C0120C22148000010E21142228108001C01008819442208908248004200 ++:803B000082002180088F150B192408100114D032022400902248004848888008820020889481808C0400828A048682028622C88250128028A8840082888A0482572914002811002AA4140023241112011338838621C88114A0410080041100408298818800708202108102680011110024002100F0DEEC00A20048130222188038414A093A ++:803B80004A184202118A0228240031422984C4220042240080082B81002C2A02228008002880064800F042AF404101C20030412C84288309A8121252244002408136228825813222003C4422082098423302114A08002140020020240800A8F04543A0424601200228A28014021442202C140122139A81282A8448028882C0210011148810 ++:803C000088348800343488292C1441416122A88022849482482414EF320F00481100400180082C0C88004AA84100A04800001902882008420000400228284800802808000082002348F212F78081A2212230231129A12122164321012F118482A1212231122A11621814002400C8402111C211202302A01440018018021C086028800290C7 ++:803C800042425F4F092008000020C44114280000220020821881081021252428849C820000400186218808202848C2822424A2822A38422C0442F061B4200A58426642622424200882348E2134164282D423682120B112428141A1812388D3228682410100141B420024110026022280022024040010026F310D13641E2AB2410623F223F7 ++:803D0000222F22A4632D2237181734C642A1292F21B892A1C2172A371B281C32118A284811E128A8282B6C4280B4829C82130811141214337DA21181022C58232B881D8380A4842B24F08242E014CC426FA5043E618A02146AC2211CA4214E111BC41A94A21CA4843F14B481A164273C4E41288E818AE136A3422F328858322B46312CB8E7 ++:803D800021EE182D6421111A788182F883A22C7881A262112F2C5A222F288AC281112322B2E228AACA42424282826FB34101111A013C1421F441112522C8B29AB1117983C2926A54211991922CBC23A1838AFC412150215AC4317A2C728261242F2838411480E83BA2422398821CC8A222CAA84613284821B88288C24224AEC2888A64223F ++:803E0000F094C42001200288400126012200800228000000130800200112211220511212200120022602260224C022800220022242DFA60D9AF371311F1182C6A26E622B661F25E221F3D332CEC22F25BDE2EC29B9C38EAB943B953F15F9B1B11F3AAB333AD82178837283F311431F16FC31D32AF6A1933B5C1A41F313932B91DE911DA3C9 ++:803E80001F3BFB9191313B39EEE23F12A8662B8A1F16B623C8813F1828F262E22F22B862E624F462E22AA2482AFE4565A0221F13F62111222EA21F36B661F651522F23F173521B883B992F2AFA12922BACDAABDD3F12FA73B11F1BFBA3933F1BF3F1F13F2FFFA3A33D931F35F461611F39A96E1F3AFF83D11AE921F983833F18E819FDB187 ++:803F0000B31F3AFE81812F29B9A2F2E1E33F1C9C2229F8C16129FA83813DA123F2C2822F26B842EC2CFC22E22B22EAA284EF5C0C6AA6731F11E212E226F621233F36F653735E323F3FFB92922F2BBBC2AE113F1DED1AE91FF973313F15FD33F11BBA3F13ABB31F2EFF83833D821F35F46143173A1F3BF3A3A32F19A8889AF181833F18F8E1 ++:803F800081C11F3BFBA1A1823B882B771F3AFAA3816E622BCE1F329AA317383F1868222F2ABAA2A8662F26B2C29C82AAAEC44F7307FAA7231F12E112E226F621A31F36F653732F27F5F3F11F1FFFF1F1CED22F25B5F2ED1FFDF2D13F3EF6F3F13F1BFFA3B13F13FB31F31BF2171817311F15E426E62EF6F1733F3EFED2C39AA9481F38F875 ++:8040000093932F39F9A3A31F3EEA29F992922F26F6A3A33F3EFC22222BCE1F3ADA22F88383373A27222F2EBEE2ACEE2F2EBE82B822AA8C4EC26D9C80011440012622018200348A44A14110018A84321142822831004A120288800129092A011C091C012C08002008408204824A2208F0C7C5001982012419220434482C2808C082132884BF ++:80408000842818228308005211821B12122C248428988282A0281C2118A228219082822501200882230421806238BF210B481B21B011A2841B212394212F1491212B9419B24219B14229F24291222F1429D212A9421CE92AC4812E4216E12264192E4296C1429AD222B491C2421B29241B29421B2923B681724292212F2498212B84112BFF ++:8041000084222B84222B842229A842882E428F6603481B61221B61421B612384F262111B212B841B412BA413B142082D91322F142A93822B421CF922521CE1226C112EC286A15286D132A5293CA4292CB491C6421B29421B2923A648272619E62698614A8AB24228B2422A92A22A94822B424AF82242FB4100824800000082008002000079 ++:8041800000002818000000400100800400000000001100000080029FD80C407211840119013042AB4924860324100182C282882048511200112598122D120021804541011985818468241846022B8418428002278890824880B25F4622A42800152252328F130820248398111B482842284130245280642C4A4282428116A141001814A854 ++:80420000242A084E8A4B122CC324868AA86830422738A6220841200414428BB520642C4381011313B12218B242083F23A88214C021488A2224686848881B412D818A062D21A129071B4110829151421129B241A181288A8334922B4825222AA484239222708408C62204429F580D21281440032117814216280420F1428100C0848022016B ++:80428000201402404162112100001B2820088CB446016342088A6624122521880821100220F269930000282440628180123211002C01A04A14A21412302114C021201104001810161102002C9141658204821C885422220027240000F01BB524130425711118475214241129C9122A1891992581919527314D421CA44814138AC8262849CB ++:80430000C111111F2118D924C812A68221085C011D164E3186210240D122042591454249224184544A1088F46C42C0411072311A01350414A8B082021A582120612F481C04130122224064111492002129122208186061221419024280185123599462222448244100E0434A0240014502248D12242C81911111158A817185425134A81C31 ++:804380000C1B821C5814293231205141A5C184128A2111464305141B142C6924412114272482420044126448811088B44203442592216602113508490123012694118088082130862D2449A4848C8861242249028C1149822431585883C3114F8401481222419918684522604A21122304226042E054081153021D480022A304181388C2D7 ++:80440000842E84436912402104D08209002F143182A0414093112B58181582C8480022CC21222414D8424502662108802428048904F0CCAD000041004424940034800425341244C7198901901885140213011928C1842A1424080040426216121427110011100A2588440421211048F45C294075262162324022427A1C4122C12129E84428 ++:8044800061482F728859418E41244118CB414DC82512C112282ED1F0188583B192B482C4131A84011847228F1324B241915145E889444B72480121486486228402C34274EB0B845012C410513C4820C1810013880100AD14168878A40890882C64144084012B42441880088B1211AB14444A01230225014A0188478A211A2404218C041834 ++:80450000DF69440240624425424242224189081601242424648E17248AC144412522082351261219511221C24488480031254145044001844954221018140C50C24120F2F6C314A4459261302111C01141882128882118288828C08120822BC22244481302262418418241C68224144004822301C2605521824841215042480040D8C8067B ++:80458000C484A014131102230145484202442221142901250421281314A11446020016C24441241280847224E241A418108C54A44384342454442100491408004CF179C760121419548183944442704814A2141924443146481800368144814488C4210045A14144241E41482C041542140830821431804884888208880044434448081FE7 ++:8046000068048250422514181144541200C08200128830864728444144882004106124001243881845013B149048004C58610024898444444E0849144A4844F9A1B3341E48414042140C80D12119C18443C111C081003881821816921898214C18512244471983290841802121022127118012020041001014120200448FC70D00000019E4 ++:804680000220226211142C1201114712001488822826012641A43400242412319A14120148416413188281C4811180018880010048182E7710548310112451121480D124AA8121002A991260122222008A84C4A44C81682220220C144011140418481601422111304211222124203422104424F83A9F6091C044180080542948124C024C35 ++:80470000C71145019880B114A41E2944824182AA434C2442684154821A44081A6444F0821110E4588202448012070000002528F27795B015748137245D154115C4211E147B11142E121E12711CD511E117F211811694314CE241F154548AB882EA22189674183F2332438AE2C1D144E471B8121C51411E124F42C4135021174149768C6235 ++:8047800014142145E57414124C38424141C485359867D7D012124E7612F21A4245D16354118D436D425BE813EC317411C242822C9124345B8A6394824F41F658412B4CEE427275D75465614F51F146C22B986951642739259325939542DF2CD9462838812D7586B4512828B886426C48C5867442528A818CF4243A1FEF41C3168435B14819 ++:8048000074217D5A022D42C49F893B122F12AA986534367D9223F8A2136F4BF8121B8EE1AE216E1226DA11E25152722A2EB424D72B68185622BCC1E144AC4125D5327254F412459E11E5F362871129C44A5F64764B8251242C18D264F128444C141444F427A7800228188A22842284324412426044001260812811308100901180010000CD ++:804880001800302890989018909890989098804808000048F09D6AF081473FF67221712AF8486C3F7FB763F66626AD589FBBFED3D12F2BB9B2DD6454116F6CBDA2FB26A27F13F31E3A2F3BF365A5DFDCFC7A6A2AF224367F33D624FA14124F62F6EFC79F8898425C748FF4C4467F55E121F11B5B8FA571D616729A7F9AF84181CF19FD9168 ++:80490000898FC9D846B899F9C4CC41416B554F42F24C44C5E444F4C44A2F95087F72F6226F97F26F62D4EEFAB3377F647446F71A5BBFB3FED3E53F27BEB2DE33F553736D973F3BFB36866F63F31EBE2BFA6F4EFC6CCC8FA6F721236F6AFA32626F367677F36666FF3F7D9E5F6664FFE9F583437FF1751EFE1717E7E5EFF9D18CF99786F77D ++:80498000E1DFF5FB9AD51E488F85D6EEF89B926FEC1C5E466F45F12424C5F64E4444EFCBF1376BF031777D473D27F5FE32147F6133437F61B52EF3D7813F7BF9F2C22F28FA52123F11F1E7F72BBA6F62FBBFB97F33BAB7FFF274CFCBFF61734AF225A76F23D725F317764F72F6BFB78FFDDD66D466F4878E4F65F514561F63F317179FE50A ++:804A0000F5DADE29F183159FECF4DF1F3F54DC39D18AF2DE58CBC465FC8E8CC5BE52F56464CFC4144AF8A43AAF21067F79F527279D2F7774F7D2FFF5F767257F71F532332F2DF9F3F13F3BFA82A23F24F173516F7BFBB3B17F71F9BFBD6F63FBB6F44F4EFDFC5C1F36F621A36F62FA36564F36F777736F76F7BFB78FEDFCC6462F65F4D779 ++:804A8000DE3F3DFD1F173761FFF1F155466F699996FFE8F943465F7CF253D19F3CFD43416F4DF54CC665FE8E8A65F656146E24E5F44E44CFE4F4AC3E1F6C092230244001430226011492140011204804460400282014218481822804420014C01140022C08244082440624400283048504DF290714150480D1C102284D1217881828241131 ++:804B00004C218338248D14924A32848B1480A8424CB2240143621149684921909612A34274481281497828C14446420855088400804404E012F4BAA3D022F4112485F211248B141F41364A1D64EB141F41B64A9961AB9459F44A944B43AF1439342F147924D812FBA4481CF9244A1CF8264A16F1245A96E1A26559ACE449C24A1F49C25226 ++:804B80001F497228F2912483F49124EB941F48B24AF18124AB941B28AB9453B84A39A4AB9443B24A792498924F8284F9244A3FF70229F4116429D441D22AF111648D121F41961C1F41D66AD84196BA1B41AD963AF4488753E32458851C7337D812F1255A987F824CF126DA86F12258875D6D539E254D4A8E28BCF59164C3F29164E39421FA ++:804C0000EB141B28E3E448724AE548F24A215B28A744AAF44A1436F84A944598B26F829492AE5A4FFD038482480000000000000000001002000042440014008480040000004004000000001002BB270040624228C1211216424C8201F143413412842E81131321845124868504393211214C919241256848290423121A0611B4488522C470 ++:804C8000111A74880546C444C44126084902F0841240349116480120788322C482D029C4811602105124128522480183022CC2148914124C9128298194136419011E848C4464864C065904481120440223932244428CC129A6F857AF008E1116EA428412D422D821A9142788411321C21B44641C41EA11F81122881C8431364CA82C29D12E ++:804D0000299611C134937B1246781B42E63481D2E2410C1F84D2589242853644122E45D98824D4249424302C2C742844E883F8A7B51004100184004054228CD4321884011084424801404A01442110624100488684042028440448904190411800412116D842022081027FD90541004041881111082081110111002B841B48400880020036 ++:804D80001411000028402462812D12CC0284E081623411008004842812882244F06D981001118144194184C211A36119311121141668317011C8121B2D11866C142542E2843111C9F11A6480236421E0112218414181F12241115016C012101B41180248824933442E882CD2B40F1110111814C9142621118889C11211113011244E982CFB ++:804E0000811DC18C4825021A641112974600C0122818441116C912641115088321341225521880048128B03408002FD645110400111200952211114301D0814102144E811C42081128100A95941280830430218228501289A342007942410140411802428A014E24C38AF2392460842127545C0250218C1812119B8B162543C1214420C1CE ++:804E800022602484B044D2B21181645450211E414D489024B3018764C01434608121624AE114E2482482849124688A2404CCA81281CF11059C611242104214084551481840B4244492148D12001848259821432491841810582200114E847088021B142C1108124149532411C12921031584381C4C01104284F49E9314008C0118B0142449 ++:804F0000A82400100200C0898641042800350841253412844D884100140028130242C1296218800240051148801298841008EF744BC14126511847221270414E8A52C183C18A16B114440149D192E818614248684074665249595122165D2A47184344CC8445C11121168863414663C136BE1512A42519B252D81481C4148E444E248A45E3 ++:804F800028D8483838816F92068E1290161140840147145032110024531308201142D818825418249044421098124248282908473211A14002886825C14800002816C82448444084E4D40E124054482428108284240112C01338284246021048180118412634248C04281018040046C221298202141C44011928810226820A002092184F98 ++:80500000CC0E4035110044205528286262420000001C44010085110216010000C02230482400201499482812884100888C48888B88022988FA5BB32028211151211185541411330410C441150211359414000048608213D1184103102161140024811111254378620260142512811122542230422B24482A247442F25B8FA0242811001037 ++:80508000021810C141112024B5422144010081164912240241002042440822444A12084038212D82493821902218290300882908005F8906121601830234901140081122115021800240420140181111824201A100199221311651242289521210822482982230218602122110228488F829D114100449140442100841161482020012115B ++:80510000110025314231422564441110012384134838B828002001481611028082040000002181FFE40641224400882400C032282412001B212446A2612004200484222D1812186082211821008031110020820C82288042C828221C220A814AF2B17240348800144400335128301211212932441082411852141008C36222812485532884 ++:805180006021260211245B1228844009A49889322284141D12121812240040011DFFE084028914C18410982C10214884A161121C021D142061157042024A11E18108840018853158C028C04219814188010049410128814882A0186024304AF0536C20A1291484823D82817D458D1327822A98324B133D411CF1374219F123143D523D48F2 ++:805200001845512819117822D465F116665D2C16513829C1228361223F22723158C35A36239FB2924285D1AAA4381C6A382B88129931B28B882B382B68282C82C68B2AF822B8144F44F4841C83D15C426452250C17819581E7175412523B414671120147113641914114AFA4D491D4B1E283C2188373410A26B3387121548814684713260B ++:80528000923821979327861D2113B2EAB422082562134EA22D283622F2628129088F1CE6ACF4B835A03217125D141354354146E28193424A741712D12184C122382E624F1524A41437248146486124C95518971234A112848CF4427A5B217088C2323565B1121824422F35FC151619722995114E22582C51881E9286A24E429038FEB5006A ++:805300002A410800844724602460246024A024400624123011100221282901390121422D1150121004224822200200140092A041004A02422D65144C322117411F92F221227F72924A2AB322A7662BFD1F16B662A5542F21F746561F14F771712B118F83F242434F45F158193F84B448C441CF95F731BB9F96E48545F9291A87838FB594A5 ++:80538000291E121F8FEB41F11775173135FB6A52BFB6F42B29AF8EF31E381F14FEA98D118F84B4A2F62A2AAFA8F882823592424AC2682F2EE2D94BE146F23561125F52F621243F32924A1F22F36B718F26F6F2B43B763B363B552F25F557573F15F172712B158FA2B242F456155E111FA5F44B429FBDFD53533E9A1F36E6B454B28FB2F186 ++:80540000784ACF67F627241F21B19BFD21323F33F3393B3F91733B7323F169698FA7F39E1B2F1CFE8AAA3D12BFA4F57262AFAAF28AAA2F2CFD43622F24B442A6648FA5F58DD2141F53F2217497C19B22155277FFD4F42379BD192B442F4FFB61632B341F35F513136F74F572511F36F75755AF86F75A59E7C495E9A4F54A422CFC5F5F1FBE ++:80548000B3F21B39A43FB17138FB7A788FA7F4313B2CF291F38FC3F13F3D16F2232ABF22F32A2B2F16F25A98AFE3F3A3A3BFB85A33AF85F522D2AFA3F312982F2CFC42422B442B66EEE86ED2EF9F49F111755F53711CFC6D2D155777BFB4F4236BBD5BBFB4F4B2B23F27F713323F35F513537F74F553132F37F75353AFA7F75A59D7D415BF ++:80550000E1A4F54A429FB5FC53539E3B6F33F3131B3FB17138FA7A7AEFE3F337373F32F2B3B3BFF2F33F3E9FA3F3133BBF33F223233F16F2783BAFF1F9A3A3BFA8F81313BF95F57252AFA3FB1ABA2BFC2F2496E22B268F8AFE683A7FFE0B47128001450245810420022041220112444842000000182818201228020022A012006012860839 ++:8055800040022008008242824282BF9B088200442410280115088001001C021440014211425302400440088C05221200181321062334114228004A012826A81480220226F8A6EFE022F411248D131F4132481F49324E1D2CAB141F41B64A9961AF149945AB944B42AF14BB24F4429547822D914F82D418F9244A8D814FA27418F1244A8FA9 ++:8056000019E2A26459ACE44DD2A4F491242CF4912485F29124A3F6912CA3F6816CAF26D141B24A9921AB9451AB9443BA4A39342B944F82B442F924484AFB244A7FD7012CE441D638E5C17248F1118467244CF24A131F49744AC664AF349B44AF14A942AF74A943AF747934D81AF83748AD854F22D518F926C28F11FA275283F8235286D5A0 ++:80568000B2E55952A61F88D2B2F51164ED819E2C27361FC90217C8AF2451418F64E9C8F2483155F84A93478B8F2439A4244782986D4829F9245A1FE902000000000000000000000021C01480080000140084210010022002604400000000002501DF7F02580013B142D118D12241B1389441008C111229820412463442424841130263644B ++:80570000641231132434222426022641381323E212B128A1422113888C12280122842428244C8102F0A43E10319118008644A8612422A1BF2205852231942C215112A31BB88C0281241D249031544908221602142C828108820080E381362248981562888426A142894428846455482F9A021442121D124245791AE21422E71254242E197F ++:805780002A51281931241A145222874284CB241062128E31445E24671115447161E2210299021784842981B221913842128F2493A4228F4A413182281528744218D842A5244F1431521F4802581301802109128502A148A502819220C1119A34428242450865221401292804400227221A82189182002823328142482011488822820200A0 ++:80580000008FEE08105114503400409241001C28411114984110C131820080140840022094144001008583022042A814004002989608C0244818F0BB13B02461212220034F128182948860AC895429F0C318308622492C440119F42142842B42130480982A41229016182D132428188A837546B12241A3121423584388854296A823558214 ++:8058800000F0B357C0143C91217035021D14224287143088254901871D816B842259344114001CC448278248400221484B12D043011651222428284226912A1C2543022129E88128998823342C4200DFCE05221004002200230848C88C5132441001883288C04128214811008283120400122170288121C9124384410211825440522C2872 ++:805900002C0120015F5F0D2361243012104C2281B164C8921E211628020044C142112365513412884521044212C3B1811502A9D422160822148082021371840813062911C224C12212274245F828142F98068011E814820218C0243184C18266C11883C24220830125081284882B4224444041216221301818461221044840274194432012 ++:8059800002224518C211210010F2741A20041110322244814218400224450118400212803244CA4209442821438212044A023021432221F112889C3142460E6088904885A441164841084240F21CA4142B4116522811212D2418A1682D518F289128841197412648028F2182311158267544A18485D11246822264134D284F2148024A9127 ++:805A000032AD2211681671C2588145D22825F142818246C1482E14A7412FC2C11C2528614244C4CF9E0600141A2242182491148E243011298914024A114484048418248902444944144284A124184A1202144C8201181A7262414441180824844200228014A8124F21092054411C0411840035420800001414121819CC21E02462941E239A ++:805A8000B0116224884511041001004601A7148CA2411AE41872122A1251421181442014022124641E3110042180624425843115408408841289488418212281D84111C284C015C01584D22214008212138A2108828220244412280100455284261A088426F8AB8C242011124801241C04480081218982221104240024102404C2214424C3 ++:805B00000042221842001140C1428044024112AC115422281016081622F146CD2041112911324240140A4229B4421231421C140A2121C041290248142820E432044D482651A11247AC2845622243F418224B428C1298824146A1141D4246A442CB344088140484E0E24C61482011A118411884111186C1288840181214718448E282012011 ++:805B80004411324340044188103811284421A862413012621601883721882128230121848002C4BFE203148184444460521741C02800812001122064188212CC288101641198C0316281415082860118B082840441802201601812002A04224844284F120F100418000047812120088301964C6888A0211186345244824CA4814C61224AA1 ++:805C0000A9841228B02428041A1A8119C1882410C44180044884001800C1009FC1412231132440D11213D882064C145A822828882182811721882041012502242C044426022518418A72280210A21221258421A31213084521410480C2222604004FD30284811A042781B0120221844014D2222622125222400130428003C84061328051D6 ++:805C8000142C04458AD1245448590251842810634280420A622902481210023F2F4C7215F68812BF210117423D2226CC2B4D184E421D48ACC8C88D51AB428F34F9188C5CD823F823131798A84C89D268AA7447461B25477E874F2B3C4F2D0485789282F213188E212F127492714175CA71482A615D3E633F24DB81D521B112D442C11A29A5 ++:805D000082F622648D182230224F8506211654848751872143F41B226B41A5D741D22828542225C28A455826244E18A08247154FA6F414422D414562114119D4276653218962748F42F362422634321D2419769AE222064C034A0143F54484DF847944783424A216855246455824CD324F4A4B81D19144D121D512E15194149F443111A5F0 ++:805D80005942AB288B22841AB3A29211978847119ABA52B18171113142535C133D522F38B512C1815DC28F4263C21954114F49E828D664E8A9F164862E785D8C2F43FD62483F225FC3A651322711348F22B2424656EA46A82229741848FC55A5006110024220044120242804449260894048648A442648648244880010344888D01408C932 ++:805E000008494918042A88840888004844400181006F674DE121E1C1F1181DDFC1A1579FB5B518F549529B628F24B4AA5A28AE4C1F31F58181CB55837888B251F58A88BFADFD6C68FE61EFA3F6EBC3DF36F73B7BCDCB2F13F7A1253F5ABCC14CFA6A61DF51A1662F87FB212A2FB1ED81F148E38F85F3D8F22BBB5F4ABBA4E11DFDD2545F76 ++:805E800074F44979EF44F414147AF54A48CF65F564464FC1F13838E7A3AF2A4B63215FE554F9FFF1F16517BFB5F54A56FF74F76A7C7F74F4EFE7AF24D4AAF61B533F3D5DDFB5517CDFD5D5BAF873717F447449F93E3EBF3AFC8CC68FB5F56DEF2F31E533F7B2F72F54F72C2EEFF656F52F66FE66663FE2F2171F9FC1F3472FBF47F7FEFC4B ++:805F00006F6FFDE7F72F7AFB93933BFF3F39F85B7BEFE7F736362F27F74A48EFE5F76644EFC1F13C3C4FA2F18F1CC0162F41F5181F7F61F17113AFA5F51A12BFB4F523775F74F4EAEEAF24FC8AA88F25F192926BE6EB889E92BFA5FDA3A33F18BD16FC9CC95F3AFDC5EB5DC37D134F34F4B7F13F3BF7B3B72F59FB6C6EAFA6F6F5FF3F7ED5 ++:805F8000F697F73F6AF29DB71FD9F3CDE79FFEF2766E2B635F7BFF33172F19BB52F7C5D68F84F57E5E6F61F13214AFC4F67D5E4FC654C68F82D28CF15933145771FF61F41B1FFFF1F13517FFF5D5BBF54F7FBFF6F74F4FAFEAFA8A8AAFA8F85A122F2DFDA6A4EFC9E9B9F9D3D1BFBAFABBF95F4AFEA5E7DFFAFDC7EF7DC67F77F7E7677F33 ++:8060000079FDB2F23F7BFFC2F44FE6F66F665F7FFFF3F77F7BFFB3B6FF7AFA9BBD7FFCFCE3AFEFE7F236345F7EFFF3733F39BBC3F6D7D7AFBFFD3E3A6F61F33236AD6CAFE7F76A4CC5FC2C2CC7A28FEB0C1C01490118F0241100400124001588420820041001000049011008422E1100A0124840488204004844124C0281C02400F0947FB6 ++:80608000200841152842044041182218082901989244844E2116B84828285482839412969146CAA21242418028392813815881981A342619622612008D961A4494442902004445F8CAB8C0421F4152381F4132481F41324A1D24AB141D24AB9419B64A9945AB944B43AF1439352F147924D812F925481CFB244A1CFA244A1E214FA2F498B3 ++:80610000212E4A8759ACF4D824ACF491242CF4912485F2912487241F49B24AF1812CAB161D2CAB941D68AF345985AB9443B24AF924482F64792498924F8284F9244AAFC5064D4A1B61AD431F417242F21124A7241FC1B26EB181722AD6C1969A4B68AD132AF44A8553E234F834482D113D485CD9A2C5851DCA16C54A87591FA27498D516A2 ++:80618000F4982526FA912C6D4A9E64E5F39124E7241F48326E1D2CAB9617C12D941D2C2F34DB85F24A9143929226F842864F82B44A984629FA344A7F1802848004000000400428200100001003008800004001000024004001820000000000002711D066418292111052218CC1744381B119748861A888C0128A44C8442545C841D2848702 ++:8062000028100B2342118282C1882C014A2902E01418217225C281112322112101228642022C2401004F6806248A825141814D21404118224141E83804512D14A2D0222112A84A418641A2246C341487142714872246024C22C2848C811AD2228404428E6470A2F18248248C18048A5684433848454861C23BC4242C3261183D44843FC14C ++:8062800022971581AD51C12C2818B1125214814C4257283CA214CE281E8C27289368224F2452248563128B21A7281C11A85ACE2484A82F2814814663141938261B1227923082282C2852C2422D52411467837F110E200140014180011C5981818A44A2482D148A142221648800142442601148422044C2240018408114C224884C4622A807 ++:8063000084128141A04830848184006E580019421261224022410281404248022901242240281441144241021008C082422240010026C14400A041884110440428008480F47DBA2451C0148961111362418722894158212A0814705148148B1D9144130CC14846C34651165142248586E44462216011213C7214AB34B01142364C9342187D ++:806380004AC8C44289861A9E1827C3902884DFAC0921224311C13119022782164A48210A250927214911829C2248468844CD44112954721542441A38422E442311C211213CD22C21136146304C8D211A441894444674442878220483411888B4270B154441C218246041160240180200990415881141C481002448518001400482422210F9 ++:80640000011442221651240084231828082828841638262042C894508420854144544849042160A18D26419041812311840121450849B52408441210A8244D184303858244181108424508839411418361124A61862B428C811464812110FCB58AC018488D2141250228144430111CC42519C11841A02481241042C1448CC981201117120D ++:80648000041944028D242C653141482112205926441B2421430221400421F082184D48F0593200172164002480216184008882141823410110842C1201501400421440020000A860482524B22104402818428401103448432402F01DFA8071115249616444A1174416964816018718796891193412318011825484198418551447214123DC ++:80650000148CD428C5324034128D11591898842F4144EC39462CC1238919E561E481147214D82454484C258944E8A20B43082A211102432201001F811422014311A843850444821C12744824026011402142140422502228460280024825C1482400224A02801468828514F4523C10A44840C1180041102201640014511044140224444219 ++:8065800000428248118088C2410025B11422828484A41441211123512426044412008400128FE3062622411818028112841782841184161812421824711201123961244051228224242C2264248002009041281110220C44480030122001523034F0378F14825308CC0599011400004001612140031CE41401D0146C4410425148484128C3 ++:806600004481448C081904822595210048504111481004A02421893224F07F8B00241221122D46002110924812301889942410021A481802001CC81380022825E22413C442149D420011200418C024808201301400241240D8710D544110024425518610422101404123391225410600250212424800430800245026261644234612C44373 ++:806680004842E02112044C048008404442B11145420241164204008001448220021410144123541240114181183822145012C67241441141484304281641448142041902201404908C22008F840A008C8402184424288D218410C8198C08704821211104C011184488001428484800808194185AC213123012442138C84254180016C41405 ++:80670000008C14F4652B00824150688C6881001062A100400C4400480014446044104215428108824501608E81302882442A311412441A345110C8224604228181F0662E1484122B41418814904A841A349444126812404A28081214236144C0428811818B1448CCC32541282F84014B42D04241C4443814804215C822202581041A2221AC ++:80678000711242F86A92242443D82651B26749CD98852E115A996183C1161E5130461D974B143D852B114338411A1152444584F481431D82A7541B64412C62284E454E1450186247121B425CA21A77445F2882E62332311622443244430349724CD882712C51282F7B012227198741448D12277140022E728961141658298722955D8E6409 ++:806800004D1215F342438B1115E33534425E43463542702438A21F22A7422B677F8812B513F82728FD1DAB151A3A641F31C4514A85C1114968543D14B018C1444F4429A491C07A69F1D7D71455C45684CB3584139413ED4DAC32121F81C818A948F811982422A52951441B111C0455F481411135A281A5D821477542FCC2844564222D434C ++:806880008547E629D6417642B71BF442241227416316F1485479F414614B55441823E12381B23C624184AFBB4981022841824E11A0146014200446014604440011204804102101831124112441014184145024484582C4828008244004808482544848817FCC4A71A4F464168F21E163F25444DD85ED4CCF61F45A489F36B3C6EC24B4C2E0 ++:806900007D43F1CAC22F84B4B4BB52F587836D144E53CAACDC4F25F442414F64F514154EC22F84F5687ABED787832F4BEB6BFF99E22C7542FC111C8F6A5E891764AF81F1C1F623F4B5376B3B6AF5C89C5D126B114B118F85F124222BCC4F45E58DB954A2214F64F495EB2467626FA6D528F13E3CCFE4FD4E4AED4CEF41F47A68AB366F4846 ++:8069800059A8AF8CFF4218AF28FA22275F1D4DF6878375F744443F1CA9DC4F75F442415F75FD56543F35FD49538FB6F7B4B797B16F68EA68FA96EC1F34D564F4193AEFF9FD19285F53F338585F4EFF11141F5AE349F171518F899B155F41F114148F85F134326F4959444FCCF87E344E68CFC5F5FD6E144D244F61F53C3287E1C7E1FF54F2 ++:806A0000DC6EF14A12AFA6F323732F49F81812AF2CDA3BF48A8A65F9B7B36F25F586826D146F55F552411F14D524F143476DC64D415E53A5E9E7F6B3E58FD2F3A2A4EEE63FAFDE62D573F41E1EFFEAFB2B3C1764AFD5F3C1F62F15F535F72F41F1A1A19F95F715176B114B15CF85F124222BCC4F45E589FF1638CB75CD161FE64CF38727A4 ++:806A80006F61F53C32E7C1CFE454FFFD1FEFE4F16A3ABFB2F793958F25F5DA9A3D4BBFBBF86667FF3DFD17177F3858777F54E415F541515577437717F717512F3C54B8DF77F6B7E5CFF2F326269EB67F7FFE475775F7173FFF7FFB1F2E7F77F35E7F7F6CFF53573F76BF12F1B1B18FA1F117177F557144F44C1C4F22F386844F45F584FCCE ++:806B0000C7C245FC4C5E5F3E0321008449410884221260812416088444114413011321044231441142000020440126011C01A041141A041A4421010000D04802005D1250141241502412344424841400400134004084045180044850818084A2C21002E1706202468342820468244854202401008042E9C4043CF41124E5F31124A7141F2F ++:806B800041F24A111F41F24A111D24AF149921AF1419F54A9143F24A9543F24295578AAD914F82C4914FAAC4855FA264116FA27598F122DA96D5A2E549D2A6F591243CF591248D821FC97248F39124AF24F88164EF24D141F64A9219F24A9251AF243924AB9443F242964782A9FB244889F9244A8746E082E441362A1A12FA8124A9C124FB ++:806C0000A11F48D26AA12889B385D22A31B4AD35478A2774578AA9B126D412E9AA45F125CAF0264A85D1A6DC58D236EC58D2A6C4284DCB1D648D821E6CCF14D8C1B246D8C1B66E89F44A151D248B345D28A9B934E444688A4C7BB4B848FA36484E944F22F582AC40288824080000000028004410010021800100000000220000000000405E ++:806C800004840082000000F01ED35024002611C44129522880548248122D4260442588E1424134124E1126210425021414130529A8121A2248025411C658624E214CC2414B4A212A081C644448C2841A04814C8292A8DF560F1B1213F8271245E82261892C28F12184A18E221648088E1616C822CC5438125922F88844114A127428B5465E ++:806D0000D1821A12A8524E824C043F4681382227C82E1419CC1217818722C068463A484C682884284B4281844A22581C413F260411372C1F21424174D821482A18F284287028029246161878144154121B85137C52018622D241C4881E4110E32368428948A58426631885C484761141F844828982FA224C4F14C8C4428AC4285284A44113 ++:806D800043624BCF58074B1210C42C2E127022227124C14825E2818481546216C8224B418D22124C038D24A0246185D522C12121812A2D84052F220561C46E921954221E2C668322C448002484284914084A221A48F894D7C0110016084400200100134802258204D012080088000040411248028890820050220010125122100228220078 ++:806E00004008245F1D0940815152842551C14460188142586B4100143088430141404818642642801288882A48A2216140628425C1488881214840381400460212A48C1404812F9401148061811056410092816021124042314281413318048410249442204201A25022182586482254124829181822140127410028292201818140F8768C ++:806E80007E80D18144524184118441104184A4245B48240080280121803188882200108858828284A242008450820010022508230248008423544240F2A7FA100340418682361442244002A33148212B522800144304114180C1121E442821A012488011A21810748202630100218BC124824E18282CA12822828308F06F1D40240284009B ++:806F000000908881311041A42100848918048004100480648281842D94182748C02180049834484A921124401168422486084A012210F82BF21440210110094214141188400250242441160480024004000028000000122302A024502881460821402205502A460822F09F63504322121548C2212216041C58822D81D081D12C2483362265 ++:806F800041960C42221C144424812121362A848D221E841812218E111261248217412344CA13248351328368645AD2222838482DC8A82885F2186D0011004184424846414801250221D04201A1401504004044624400221248908620026622C812688016C8484A08608360812C22038400EF8E0B8042215138401141010080443214250275 ++:80700000400800006502000021402215220884A182204102000000884002004A083FAF02111120421498222902A139542250241D884A624C465E84484904422A088180012982E2248384021810A281242021B222C8482180741202842F24C11281224820025F8102111C160151501227125022110050234AB1441818844414024082188299 ++:807080004102222420220500100820811808002140A881408A0221A8F06E9450888B444AA412A484224041784456446B224B622E88265422495482812C147242A2391AB19CA88800289073482485DA88B148BC4264AD2482122CC2224612046AE222234262241602C042212D421AF167410028000000841421211124000000800448000019 ++:80710000100820082100001002282100800100000000003F8B0A84842AC441400311244044E44182822208000024901A18184A88080014111484848C8494420000004C18C4242CA328000084822C042D184FC4098508484002113052A018450439020020514888812180818408211032421480420A480024004082412498228008200110BE ++:807180001882F45AB6004800400422114014A12818880000002180018800004091222184A0422800008011420428000000401202186B96100400005012581114008004000000304481000080010000240000108201129088100200008200F029AD1038582004241110026141471262220000282C24442221A329200800111111A1853248C5 ++:807200004A283C2200002C11143C24222200008424212C24F1A71E40C8484C84840220018A0164443C9221100281841062242118988C88084022C2211428848429840450221242004444282818008110588224219F390812000040020040918800122008001004000048000022301218002440088068280080042100284842007F23020041 ++:8072800000240000F081128308000000C0888400000040022482000000004002008221420020080000489FC10C12122644C122143592118C049A591BBF1908C282001287428E484249040046084860214288D022622121A2214012122284A881E02828148201203128844220E4630A41220050241426E315D11151338830111110028484FF ++:8073000010084A040000002D22D0220260230010022E12212C911288602142004048A8C8898414F84DBB000000211052222C084062342118800880C848103C286200218512022B2A20021062282C0285021E1220183A1A2028188208008480F434D8F022222B21182B11122B11C0132592821E111F11B189E998F848888F18F448484215A9 ++:807380001981548985F844484E444F4294244F4222E24202286514A4226F22F21222182B191AB89229C8122592821E111F11B188E998F848888B488F8424E48404488558884E4859016F22D224A2123A21311200259282BCF1131119ED89F818888F18B4C82464141501C485C8688F44D44CB444B26422624200444584F322222DA22AA14E ++:80740000131AB8922828582229C81B3B1119ED89F818888B488B4C4242008485C868F777000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FF49 ++:80748000E40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000000000002D ++:8075000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000AD ++:80758000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000002D ++:807600000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000AC ++:8076800000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000002C ++:80770000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000AB ++:807780000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000002B ++:8078000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000AA ++:80788000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000002A ++:807900000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000A9 ++:8079800000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000029 ++:807A0000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000A8 ++:807A80000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000028 ++:807B000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000A7 ++:807B8000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0027 ++:807C00000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FA4 ++:807C8000FE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000000000000065 ++:807D0000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000000000A5 ++:807D80000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000025 ++:807E000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000A4 ++:807E8000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000024 ++:807F00000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000A3 ++:807F800000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000023 ++:80800000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000A2 ++:808080000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000022 ++:8081000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000A1 ++:80818000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000021 ++:808200000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000A0 ++:8082800000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000020 ++:80830000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000009F ++:808380000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F001F ++:8084000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE406111001C9444484313062122854484C844A0218962218A4208452808189012DA ++:8084800018288322D428A824628C4208C88C8444C8C22222302820440200282816286188CF780D488C467948711814C82CA384E644D21423291BD824C2224C526A4CA182522B188E189622B412D826A2188DA283B848A985838844084A31128E48250A8B382E422842A0129860228962222AD52223B91238828B482721AFE50DA012208438 ++:8085000044248491224433813288E04802241AD2848188088908002642628120822664A426084E3218884200248821200100212C2283A1822319C818F021746014118411188304230420A21843410C42264428024A3288301C8A247112042840080020024062A8A01C83842204B08803488C024224402228F48812DF920B80045084409856 ++:8085800028446800224062422100108201008220811822A4188282421048480842222200280000001082012018F2D1CB0084118111C0244442400400004014A2212C01182C082180088389494808200480048481208402220022240022808201F05ED8000000001200000000000000000000000000000000000000000080040000004F4DF4 ++:8086000004C02185011C0484C0417048E1845818450160814C628144409184E4411C34128C21E2110658508221481008008581C242224A088A8181352846128896188AA2142A44F2E853241D24121244893169460160C2822014E83114CC442C0122104408A4604423D2260D1E88268A8884A912885118C56122442C44DC2888A2411124B1 ++:8086800044272160231A982218608862CFAE026591318C11B419C4218C0442C48AC4C89115AC146189C13416982410358C8556843C8491185E821B251AE882C18283B4122886588112812C5294704284AA2CA0182C817428022CA22880AA148B862CF433A1200214008C44011428850142404168441002000010624427224C02812C0400F8 ++:80870000181004450180562884211A44016C21612416E8246183180022AFEA0918004422704802271684234408502840022147818511810A44211C1246D5864124022C890250124414D0184128022D81111C48384200C01412420048EFAB4B2102383858259C341C33186D1181259118AD111AB41868525C2AC4C122C915788904890412F3 ++:8087800050213692143283C61213321128BC2A431E7411A2841C81C21218209842E028A2822441468466827F940628008011624131135223104358125829511421481E4428CB14104122C4224082D1269224128D822CC2211D12D034C211442521011225612100210028274190420085F2C76A20012AE141A224C483C63256D88431488438 ++:808800001216186888222E87D08158181189DA84184448311451158C2181A23412002661882884C341AB4A11A8111B81844E824220288A4134442A84F669C9E0821122041012C2114C410449416892812146C421005B28440082881281132161111213011C129A522263012882111218448400896346898181024318E644029F770C541900 ++:80888000E1C60126C411114C4288841294812811260244184125381211B02281784A6122002230650081224222222082418C948263022210224204382A344212326F9A0D42002821418311180219E1320421120012118418C0184C18041004004002A012445018441682C1282601100143011810420884004C3CBBF0452216D1488192268E ++:80890000162771347B183444121F22552815180148166111847F892251816CE84842C2584118181E21182850212AF12214286791281E22B8B02C21250860411628D128028922B388822422FE6F32800122400285010026011C088D122225342410044118004061A214006045212800801204F011281450221D2800244B421843016044415F ++:808980004E14415FD904C0243885648284322210822104A081280035C882828A44B88194214816A1482AC14187414822684100290242204201000000000000424E88B0190B430100308485341881862882819184221E4425243484424A418128624C00184200410017821724804462222848E038B4A181042C24984480056884224418483D ++:808A00004FB10180048341628323582818246484446022884C4145028411110010021124100A21008129B112241104100116018341040020018C84922883F2C7EC60B1121996221982C42510E184428916CA112589448181A11254188D143024802832223E8814241614848188024382EA8114E841921412C034001684820270248201213B ++:808A8000F08EB90028C0340000120010B2480811200888008822114548D81403286301218443913132100160412282200322002212E08241C824281682724F09C01281004098228412230324C098281C28428104441021082188244184C011220000001A922182005041A021004412884032582904CF180923024C012D14163412186C32D2 ++:808B000024C01419584170140827448308A288484C08144D824841209614284AA1244241224D2825058AD4128494414C94C25849C44258482CC44429061026F41B3D00C421428421112121181123D281C11821A3889192D02281034100111825CB11166422934182416122801142146811441210A81244004410044143911424F07FFE50F8 ++:808B800082C041D012810248458114484C82460129429112261428D1120189014D814002805A1488701408C88118154404C1499221441138180038854632489026447B9A10C4629B21A57C21CC1887912E22D57BF8DA53321ADD139F1194185EA85423DD83D822A2164F14D198A1248D21473437416F94F824218F66D3A9A5166F23E287BD ++:808C0000F231212AF418223AD927F382464B22CAD1117248A43B1F14A21152184F44B122B17491147A1132687E1C4B252B42FFC60D1AF3161C2A21F21A23AF2192232B112D244CE4A1E186B6127886DA32583C5D225D848F39B194748A3881197C2471615481E02892127145341744298D7495228242B82133191F8132E64D9246911C1B76 ++:808C8000A62675C4044A02622D8883D44685D628B44CF2E47624312225F514721847464F62D188A4112933282C41E844F9B1282F4AB512E93245A4965BA11A7894B481B884084D1B1B531725922B238D8E18444D1C4E31255422874643E1C4F124454CF1914115A44321AC25A141414812CD664FE2E2A112E4CA013FC10411508118152865 ++:808D0000143144114A18A1842004463481464448C448441D48448C44944110218824B82424182408828182002908690829082D8410022504008140F42EFD2425E2F362B17FF1F54B684F55F64F4DD7D4BF85E5BE72CF9973BFDEFC4189FF4CB8A6FE55411F44F1653DABCAAB8E9F14D881B94EB4CC78415A17CFC5E42DE833F64CC99FC66F ++:808D8000FEB4B48F8CB4D8FCC4C6BEACC7E81FB9FA91835F97F4C3C67F77F74F497F72FADBDB3F3CFDC3C42F64FC52C26F6454464F26F6C6C66F6755E24F4254446B413F6548F313111FC353B8BFB7761BFA1D3CAF86F66929BFC1B5A3F7F6546E238BF93F19F4DFF5FFFEFB15552D46EF46F77CBECE9AB78D9F45FDFE788BAC5FA4F91D7D ++:808E00001BCFC7FCE497AEC1AF93F93FAB6F4BFADA481F87F74444FEE6EF69D11BF4446ADF19FA43414F56F649C97F77FEDBDD1F16B771F752D62D847AF754544F67F5F6D66FE37346F476544F85F3245A4EA83435D144F42D2C7FC3F21A294F61F25636FF41F618598F81FC182C3BBCBD6B5D55FF58F1F7817F33FC81569F1EBB82FC92DC ++:808E8000D83B989BDC4F12F1A4C9C9B854F53C2E2F17F295C75D1D4F78E36EF628A81F85F654469E64CF42FA1D251F31F261797F48F944E59FF6FEE565BFC6FF31311F24E64CF4D2444F44F474766B764FACFD664E6FC2F6AEDC8F8AF96C7ECDE7243AF33C34DFE1F35E2FE7F3CF67774BFF3A67AFF2F26ABABF55F39AF3AFA171D7F5FFFE ++:808F0000957F3BFCB7853F6DF8F3F9EF6FFBAEF4FD145FE8B96CF784E9D721FFB5F5BE2E6F7DF93767FFF7F79E2F6B7FAF83FB55744F6BFB92666F63FB773F2FADFF99B13F37F7C665DFFEFEF565BFB4FFD3F11F24E649F1D2522B664F67B776F5E4CA6FE6D6CCF4ACCC8F8FFB6C4C7BF69014B02201226022160816682212608924164863 ++:808F800024492689220111281181182849819216302220022120024B12122A082240210140042081028B24B0CD01800212211608004440181801130200008214000011001484284921541412221604444212B01124044A11240418484E12414A311440C159C0421F4152281F41B248F1116CA3D441B64AD141B64A9961AB9459B44AB925D7 ++:80900000F44A954B422F54F925482F14F925484E914FA2E414F8254A56F1254A871D2E4AD6F5244ADE244D4A1F49C2421F4952281F4932481F49364A1FC8B24AF18124AB941B28AB945788AF443924AB9443B242792498924F8284F9244A3F570C2D421E6C2CC4248F24E1C136484CF66A124CF4489468AF649B458B945B42AF24B125F4A1 ++:8090800048111B42AF44B927B44AE922F548155BC2527F8234D827A2D675247BD855A41FC8C25A1F4886F5912C27141FC9764AD1C1F24E111F88F24A941FC8B24AFB8528AF443924ABB4A2AF44332429F9A648182E588FB10A004800800100008002000000100A1880080000000080040000000000000000002170BD0B30224C11D4140115 ++:8091000028284078120116415C1811899111612A018B425815141219F2114A13512156012658241901169112132181611116C121221899081099348522148826B83404441FDD0412248140F824582F81149811228214481282434C13E43811E918148492288A0419044189012E12002C12240241112E848488163847252844988C0044125E ++:809180008A021881169948AFDC0212238441C4181696382213413A14201634884551811CF1861183718162865883318286324113C511953211139222648D22C02123D11425C1A413918117A259D286918983328415B8144288E5828842A216121E4C5FCD0280120E45C168428480C281111C6181148AC4124124132214843225421508A4E3 ++:80920000441842188130114112001412811218488004840064004898451808DE318004144C124808281815188284088D81419841A141892AA82400488314022400811816041100850121112148003C28D812014449044311420824DB9790115C911433614123C19715782894423413511837814D4298211B86906A4645518484272410F506 ++:8092800021441516C161233414CB241CF24221122FA221E221B24888D182B411721578AA611A831485B841D182B11262885084684B2426746107581C413122160A8219B2186214244885134182083C024508888100421C14140526914212C9F5112640A2122932188688419112FC840A8B84200116B84222185442207424C2AC401164416A ++:80930000594194181D142558248542C1118816F848856CA1814C1C98628F544A614681231452681C06259142504828E014621181D0216224248C3421188591A1153285333851253414811281896642F0A8D6D0181421A124F02892485025848532241B12848241602CC142831282A1349081EB34100185450910352F21174449E2459281D0 ++:80938000412481402E94122D41C31214828712921A2982C128FEEC2484002735446042A5968840711423124604001122114616D124C124882052840066C144A5048924B142020070110422224501862482C242412004AB8428243D7120120200821222A21C08800810312221124418C024141044C14430422100A01200121800002045819B ++:80940000420810024018082014F4E84A143912022D3344366241267429C689141A92120064222C84C124898264414E252D24519B2448452954878346127814D241D622E141C2144AC181502420742811331214442622B42244127812A8862A15FCC94CA04811180084664218028512C18345C8841124828585C411411C0240624143022193 ++:8094800000461494210014284302411311A8218056284B48851204439128484008229FF20D0000851401244224111522418615840120621240414124014E9A8011F3481243D21291211828992102404208261404000029840200442C44F43BF4903128686811001128A6488C418104166244296218488E181460248C012114908484284813 ++:8095000000492A0480198888A884C61103002501A0144242298C0428AE993081512C829111848440584A00B4508184154A0400812C8181341848211C44384800108441841155821682E4141228658527211688142825C1428381018322015F130C00491481841614B21112018014018048A2418622028243E81891444141A0C14502148C3B ++:8095800004C8C042806812814423018228C2601444C100800440FA3AF3244428000090148381010080084883214112984220544821002002810080820220448EA112111001400100A125924486A221496111EC06260891948302501880781802103818212146A228490244230650A180180420C868968154A58486814402112D8242281836 ++:80960000261102004A8123A482401802CF1904242071721224581200144651814B85005C4444111181E81238131431421C415121464121438344014591441CC21114A22058122084282114246248888012A424416F9E0E20CD45A0812A0183C2411A165228503814008D6410981181494C084441612914022441A44100D022042931484F01 ++:809680001114012384614449242112088CA28121188146F2AA37508215841418021588410250428429C2421D48911C013308822143E82801C8484411424E84144CC8489C44824C1429625120711244C244181A022345021642A821422D2426F838EB241B22133814A7844D1132113555918A754851381219A4418B45E7AC2F1441E332241F ++:80970000F885811F1AE91C5811471547149F3851369B153CA4764F82D2A8B141B45591211D985D4487282F317289F8258A2D515F4A734138212F8155214E495887A2EB82882BC88889D31C24F121721434475F1F12C222BF8894A825DD28A1338F83DA6111F1428985F24B8B6542F124463B98E0237A28686415FC82C4AD5EC0444E444FB0 ++:80978000127446388827441F1D584C8A722464292F14F213194C21F5D2251B89482F49B142E24CB8145121221AE124F7126A66B862E18284528A3F29012D142885F631511E244611E881F248427553822781DD52258D51D11F41F419283AF485A8BD19481AD42455ACF012466B84112B88914FA1C8426964122EC789545226A28497826DB3 ++:80980000F358467A52C3431E52A0441847654B44128B144F21E1287654E447F12466FFFE0C80012961C82A48048028810814004002248002100211122192419241924192452129222802419084C081400144800228120028FFC94DF222227F42F2311E3F23F532244F6757E62FA29242CE4263B842F4D8C49724BBBD4AE514F5CC841CF430 ++:809880008DCD1F3DED42BA91F9CA8B1F3CFC41476F44B555F891D14F44F564F51FE7FED6D48FFCF54F955F6FFEF6BE4F7AF335E4AAFBC5548FCAFAEE244F4DFDC6466B4C1F17F2A3854F44E535F57476CFC5F464746E58DFE4FCEACA8F86E786F62C6C7FD60F55F6A764DFA2F23F736B458FF353BA7FE3D23BF4DB4AAD841F24F4FAE8A711 ++:80990000148F8DFF49581F14F5DDCD2AF6ADCD1FBFFF838C1B99CFACFDC4CA1F94FD41514BC54BC95F7DFCBE36AD976F6DFCD84F7FDDF145777F79FEB525BE32BF13F24CC48FC6F6CE846F4CFCC7476F4CF573313F1AFA54545E724F67F77C7CCFC2F7F8DAEFEDFCEAEAAF86E783F67C7C6F934ED377F21774E43F22F32F297E76A5F82DD5 ++:809980003C9F95F762E225FCC3C88F84F6494ABB99CD1CEFE4F5CDDD4F5FFFEDCDBF1FFFABAC1B998FF8F9C943CFE47C55B74571D5F1D4C26F36F6E65F6F4FF25ECE77D45F74F1B3671F21B831F228387FDFF7BEAFEFCEFFC4D41F225E731F39B852D754E535F52666EFC5F41C7C7E58EFEABFB2F96A388F86F72C5E8F364BD177F2973546 ++:809A0000CF91F17F33AFCFF6B93BF5FF333ABF17F77BFBAFA1F1CBCAAF84F64B43BF8BD9CAF14E5CDFDDFDF4F4DFCEFCFB71BFCABA91F9CDCFEF28F85D4F7F75F4C7524F24FC4753FFB2F7DE4EEFE4FC4FDE7F54F5D5E77DA71D933F33F3BBA94FC7FF5E5EFFEDFDD6D63F27FF43553F1DB952F754547E526F67F77A78ED7C8F8FFDFFFE74 ++:809A80002BFBAF86F73C58CFE6F5724A302440012D110016683284241E48244011011349042811421100423901710042181004230225012E138C6432483412800412649E482C820410089FFC062501228489C1280010011181205484A542E8240A8D81418845B24808446045305822851462442A0118442CC12860496041420012A041253F ++:809B000084048C34484118227F12012CF5112485F21124AB161FC1364A1D24EB141D24AB9419B24A3915AF5439B4AF3439242F347934D812F934481CF9244A1CF8264A87114FA27498F1264A96D5A4E449F2244A1F49D224F4912487221FC932681F49324E1F48B24EF1812CAB941F88F24A9255B84A7924F84A9443B2427B2498924F825C ++:809B800084F9244AEF4A01ACD541925E19B2647111F86C1219921E1F41F24A841D24A9BB84F24A1543D21AB124F4489143C29567828DB16B421CF924CA87114F827498C1429E212D4B9AE2B2E489D2A2B49166221FC9326C1749A3B481B242D181F262941D28AF64DB84F2489484ABB4222BB447892D346D484ADBA6F5479C0023880400AA ++:809C00000000000000000000001800000040010080040060110080040000000040013FDE062219332A004E2860C114141821E041A44184601114121942014450243A3412269146B0241834245D22882240C4144314A42188122B142F290256121C944242805448800AEF6E410182186B12A5711392182D21478184811C21113B81453241F0 ++:809C8000457818143812CB121282902911112B41B026C112181229714403849146EB1178434A22844441414AAC41121648825148385018417FEE07A01A842D66842B148135440C495112226D4119148C54184511781262D31244E0C88164216E124C14F48124274164CD11C6344281118B144F14C84C2C031847152D832668444E18442F8D ++:809D0000812404464C0A2E8916F6CA982012B1222141D18192121E281C51818112181688092531148921C12100827021E211124341A22118A01228258102C445235132A08448211A4262812524019012C03400E06E09008280080088000000000000000000000000000000000000000010010011400170E7052C5482118D141249661422F9 ++:809D8000424D6C2B1314154298828149A5261AF8811325A481284F8844641415E292A215990423088D5846E4221A12E5410189E212288452C423A25887318C1882B244A4138827284C03728E48FFF60270221A11C8144B282625D48432182B124814812D88161294522E82825CD188A82513C841406681388B441531825887814E24882770 ++:809E0000221971182C92245C28146481212AD73868882190141AA48A2425E48188B388F4E7310020088008800800000000000000000000000000000000000000001100100114009772001A621212403C28200230811400114601421183240115824A4244428431484918988490141942618189618188100285210882A58144A648441042CF ++:809E8000082CF4BE79F0221245419828843C4331118591898F24422A0433052A0122811E2145E14412C448549B348F1284D429A2A112472A87241413081A1872C1225C879B85BCD1859C823B123D1A1249D84861814D2A5AF842384B484A2984B28A022126C52184818F22211251181CA824993842C011B0210148911F81044C54218C5CD7 ++:809F000024422681C4228CAE18478243581286041E811213196A181F8439122778130816813985834472443244A3156289482CF48C3EE02221412803451189811258281041821421042280721421422412E1D2C14A411D181244822784C0111C424298482C5D48109948813B29A502A14CD184B128A881224C2C042249052842158401146A ++:809F8000843490312226086289A112901130581245222111D4810842111A0214188584128844C89818AC0B16D11264242841292822048442242C82410224EFD70594460123021816824246185422282908101482312244241116418888413884701482948110B31984B4A24124144204C1308811442A64818116149414002C02481A0C009C ++:80A000004022030000100110542C0000140042481004851228082800260410810284212C4244210116042170386282003014228FA907134211B42221C31189D12212846222BC428218942C443112A9421124914142851114788522D22488A412811159048CF3811C6AB12A012CC14567248F186211824365842183C1328C912218C01468C0 ++:80A08000AF340B001410021041721108004889211122011AC414400185041248818C2101824582A21290820082E51231280010021884444D484C02212240F2BB3F24804382A14284C061481C0411808404000015581216A26143A4414501A042002248221117821442411008141691421022042C82A124A028C2389034CEBB005084228571 ++:80A100008305218D131210D22801322B428E58181227293038130C6042181E4C4C01581782C01823A112214C516218122F22312848230222818C22048608830112828148AF6809480011002800008014010028200800444A48083041C0211004450160114A8118714144348A848110612884814800446044003F844902800110818444A14A ++:80A1800042C4005048121C823148836248114008271120414408232444048C04A6C8298C21A82819C812441A12A114842E128012282808B08203CF620AC20091000020881188428814280482001A142802811088111889140810810450842501212041985824188110C842004A110227344FB50322100810289428A4406854BC0883324146 ++:80A2000014848042014823C82C90681028220410511418214110110815181221882818844124E1412804A04121824E214004287034B1111214A34143219422181A522120C8421827218C0A4024481414041C011814AC03212C012D32C01284480029418101C82C04208861888221446FAF02302328460840081048141811895981104811A0 ++:80A280002913D818A184262192491088942810C8C418884448804CC8811A2434484260641603A9219418120000F0217FE082014828842012080044001150482AC44C005042848C9141B823661427181634881E4121C048801405E634444C8809F0A8541588020082281828D02221F8CABA80338116B8227419C6212CD48134485A744C86A2 ++:80A30000F23988F03123293318878456618926A831C4A6A8884F83F56139668CD181E682F128894781A975118121C41D4E41CD98ADC16F26D162C4DA27228BC4AE814E12456A8247258F84F51C18AB849A29E441E819A118EF8D0A2B46B028529826F118588744A372117A224178498154828D988F94B44128D2E2BD2898AF9187352F44A1 ++:80A38000D18892288D4443D1D934429D6248811D2625F421C1256E28897213D4C15111BE8927118F9155821F81D1D8B411F95A522123A18C18441EFA4A712842F6EA2424642A1394318C16A1224E211CC59C1825C8139D514B4411AE4D1A17D823E318D192B48195EC4F7674413514A935548F136855526AF454884F22612536B115F23761 ++:80A4000016C29E228FC83E4DC2511AF348621B81A984D888228AA62928828A066BE48F3E0116041644417422414461C12988D4120825111412149244814130116028502181153288248A028B28148A028658145024844582440260882482243608260826082648B44E4CF152427F51B11CD19DF4795BDFF7F55D177F45D122F48C969AF981 ++:80A480003832AF2D7944B6D8FD99973FF1F12E2C5F3DFCC7F76FD9F954585E549E8A3F9CAC1C2D113F32F2D353AE426F69FD238AFA7192F9F8E22F26FC771457213F3A8ABCF1FFDC4ABFEDFCCB83B7316B898B558FCDF1CDD52CF3263621CFE19BBA8B66AE828F82B268F6EAE2DF1543F114467F54342CDF13F54D4FDFF7F559191E324ECE ++:80A5000042CF45F59E9ABFB7F7FF9A5F55F1F7FEBFFBFB3B3FEFC2F3D5D33F3FFDB291EB554E448FAAFFE3CB2F98F85219BFB7FE935B8F8BF7B4B59FB3A95FAFAFF7F2FE2F26FDB7DEBFA9F92FEBBF98F5F8F48FADFEDBEABFBC58BBEF48B879F3E83CDFDDFD587A6F62F32228CFE19BAA8B668F8EFCCAD88BDD8F67FFD7F5344F64D5134A ++:80A58000D648F22928DFD7B36AF27B733B77FFC7B76AF7989EBF1ABA5BF75B59DF6DF98B817F88F86C6A3F7EFE83B33F99F976788FC7E68CF7C1EBABC695FB21238F85B572FF5CDC9E3B8F85F572EA2FA1F9C2626F61F79A8EBFB9F917C7EFCFFFF8BA9FBFFEFBFBBFB3F6F3AD8B778FADF3DF9D2F21D166B178F35C5E2F82A9568F89B339 ++:80A600009265886E528F4E4CE124F527651E3C9F177349F96E2CFFD7E723F37C7CABFF8FC5F5E9EB9F85F75F5D9BDF9F3BFBB5B1CFA7F3F3F73FBBFBB53DDF87F76175CFAEFEE3C9DF96FE111BDFBFE785F57AF84F63FB9A3B5AF55ADA3F33FBC263FF71F33B3BBFF7FB9B5D8F4FFFD4FABFF5FEFBF9BFB2F6DB8D9F1FFBDDBBFFFDF8BA93 ++:80A6800092EF62F35A18CFE5F932987AA5FD8F8CED8BFB6452AD7100008480641248800484004008C02282281181F048240040044A024220044041188244E281C4820016482241420800202428046FFF0F230A228485011C5181894108111815088498163848102821148418B5489211831411088160412D41109621181F8814C628E081B8 ++:80A70000344219028C246481181E4820011260184FD7076D521F41D22CF11124EF14F11124E7141F41F24E111D2CAF149921AF1419F54A9543F24AB543F24A954F82D452F9B5485CF9A44A1CF8254A87115FA27498E1A264594FA2F498242E4A1F49E232F49124C5F2912C87341F49724EF2812CEF24D141F64A9219F24A9255F84A924371 ++:80A78000BB4A7B24B84A7B24D84AFB24488DB44FA2F49B98D0A49561ED1219B24E3111EB1428471617898F42798194B89AD45839218DB5A28D141F83F442952F88C4245FAAC5814FA2BC18D8A4B498F224DA96F524DB87492EDB96FC24CA17498F22E989B26CB891B26AF181282F12D181F26A1519F24AB45D28AF5421B14A5284AF449326 ++:80A8000044AD342994B82D525B16000000000000448002000014002100000000008001000000000000280040080000F0C1BB80413122814E124111212664821CD6121468844598121119CC141A28518113048411114AA184C2002C0812233211E3A22853C38320C85851A72218709C4142A8248C082C08128981F46ACC9042821021120916 ++:80A8800036215112842608150419B242913A83922114488494824A62222639248117654E2881434431442041914845C84811211061148D52F046894B14254AD44285614243D41412F47A3B80258412A94194112B1228A14B2433068594242D21124E3116A8211721148D411638888A022B524B4A8C34111784244285634446426C18585CF9 ++:80A900009848824E18414D21162141BDCA62452346B84481592256544843F13879101211022642041149912185411898418112273486C82413088C041190411C528180684423328841122213A11228C7128421112111A582744822494758284318024C02384857CEC04300100422501244308188841480224124182821642A28156211104A ++:80A980002812C8C8800826021C41C8138420119241211942210884882A34482281124448A73314281C512194245C728699214E149CB9424282419112CA7148712284511843113134451135248C92443B414719714418876419E7189524248E278A84D49662444F98044A291852229B142D723A741862232C24942428F04DB9800411A17002 ++:80AA0000215248112D148D9622192859281182842A116498452881C122443C62812416E9214239C4308C25F181624C42D143329383148CD584C84180022413311812668AA742484B1280D4AA08269113404146641A28131481042114121AD42146240118114E241D84261164124624D44118148881A42518806188482562124139042B5817 ++:80AA80001318338246D822862E5128100A4342F2EE2D0030441850212822116490248481505216180224516C4421127431A4485021422AC5294200803431141222881C8424CC61184EA414E042285424100821128E425FF30440B14102CC1214C8184484114D8118229028A0241A02812C1284B4220DB22018089021C41742224F82242885 ++:80AB0000229412282554822484438232C2842542082A812592A22A24F27AD2C014184082811101161882411A61194A01288901808881111808A02400458804004E82128041441D28A22120E9140800808A1184021A0444FF6943311416410447815D1226983816481C31213D181C88712AD42882A612308F3811469AAC4D213A8432818CD0 ++:80AB800074244888463821AA64421A82634427D281483E48489B5A1C29C4819084278E4D1243E182015A0243FA82A360886012122302145034901286081628148161810090444C212204800421522A04414424121C188121E122D84112221882C6824885220280828422A83458EFDE061422702218810240011C14086012442001C0126835 ++:80AC0000001C8A0648114219A14A00C06240D4412854282440021D521286D442C1240029490200008F3D051E2E4111602283218202902240028008264808407C21621260813E88C048220083414C240910180C10E814C184818481103828B04882028222844CF1C22BF0841820D2411441414824213211113548341A22278184429281003B ++:80AC8000810022281098248180088084011D241F4221444138112CA881161221214838448398184200A9D4DD04211018C81883181118191A3828004100206182111008842194811200234AA8421822128B4280186882A7241922221228A22190144B1630424138588C21F2B2C3009181284508008962228008882008408402001244002A8A ++:80AD0000A842190811414849622800004120028200101811E8248121312889218421F4855D00414100201204882A11914490188119A1814A032AD1862148811181341484400814132181614140041A2214042288804804008421008024F2B7516012C0414488136181112114504200142481448400602222118998110000404104004CC43A ++:80AD80004824240025522813D12184014400286682048140F44BCF00822214008022E288118892191D144418201281B128082181812248839431890889048348011100844018C11814844884148449C12840480149C241847FA2032508481230841C0110024C28820822808842087012488441012901397411081C81018490485E21130230 ++:80AE000020243218424C028D22130144004A318A5022247E61C0148748446B2215664215594499B212826418C93111281A528249B84436188FA1B24451A13782C521945126A8118798156882E0851CA1182544F81845DF4AD21411DA52D21A348CAB812F84B618781D5C58818D1C8F49E18EE216E18828C419EB34AA015B2373FA2121975D ++:80AE80005187181D998B131372227921F828182E881549D4CD614A1CA1288D198C9A118992B8C982F288188F12B298D28996C3CF22B18818D84DB11461261311FC44889C74226424AC44F832881F98B411D8C2D31211D784E825C26A2934128B1147825643F2685B242501856884363818288962218F28F81321BD2266F2848216D128388B ++:80AF0000188F8321A3122A58C222167181FA212156B84665164A62111B641E1C8AC2241A8AE5419221F0182A8C36491F23D311E324931886021E381E344B4223D628D1C8B4228497482E4C8FF54C01148001615012C08180082D819082C0848008444054214002152218212822382420024712302460124003260274402608C02382810073 ++:80AF8000B71D144741845D245F53F719B87D27E5DE46D288A2BBCFA9F38B899FB9F9C8DB8F89E12BFA9B11BAF991918B57CEEACEC845FC22222F24F4EA6A2F25F4656D3F1FB9CAE8ADBDA3FA24AC4F9AFB71F1EAFE652D4F82A273CF24F45A748B665F5656319F18FAADA19F1A6B623D122D36EF2AF9E2DCCE42D6F8683A2E324F42E2857B ++:80B000007512E87403326E48CFC2F22D6D1F19D33352776D248F12B2BAFB9EBD9FB8F83B9F8FACFDB8B88FABFA9B994F4AF91D9D8F87E484F4C2E84FC1F338384F54F4E86B27225F5EFAB331AFAEFAF2789F9AF8A48CAEA8DF9DADCF5FD3F52828CF89F9E8C2AF25B762F645459F92F2A9A1DF735B198FC1D341D1A1512AAF85A11CDE580E ++:80B080001F85B538F32E241E182F83F17C36141F41D251F62D2C1F13F31933CD25AF92F21417AF33F3A9B3BF61F3AB819F91FBD7D5DFA1F1BAB89F13F38C9C1F13BBB8A9BB6FCA7824FCA494AE888FA2FA7858FFD7E7AFB7C8ECADF5E2E14FC2F2E8EC1F93EA2AFA27653E3C1B338D2AAF21F36A6AFFF2F21313BF19F9FBFDBF36F31A3293 ++:80B10000B53B1E8B227E7AAF2CBCD2FC6A2A2BBBEFC6A6624E7ACF9B4CF13525DF52F62D25DF57D3B9F21D2DAF82F21D3EBFB3F3A1B3BFD9F3A1A3FF81F3D7D5DFFBF1BAB89F9BF3A4945FD27338B8B8F9ACACCFC3F3AC9C5F7AF82AAA8F87F4EF6D3E7A8FACFC5A598F9CDEC4EA8CFCB1BD8EA2FF51F318189F5BFBACA2AF61734AF86E9C ++:80B180002FBFB3F3AABBBF7CFD6B63EB11FD1BBF91B19CF9D8DEAF2AF9D2D2AFA6B6DAFD6C6C8F23F76C7A8FBA042A01228414844D11842284001400001008811289022811901189028B24208401006184410000160800164865814C82842201128902EF3F0C41110000902124118128815120022688218A01444021024842C021488064AF ++:80B20000412001118032421123123142122100902812888E48213A245424B745C0421F41522A1F41326A1F41324A1D24AB141D24AF249961AF2419F54A9243F24A9543F2429157822D915F82C4955FA2C4814FA264115FA264195FA26559ACE549D2A4F491242CF49124C5F29124CF16F89124AF14F18124EF14D141F64A9119B24A19F5DB ++:80B280004A9543F24A9443F24294478A2D944F8284F9244A9F450C8CE441169A21AF26311187241E248B141E24AD941B61ABB44B61AB944783AF44299292478329F9A1482D91AE5889B926F818816B4286F4225886F4225B87492E4317C92E4B9E448F2261412AF9812C2F1661C9C1286E1415F8483549B24839A4AB14224E9486C8B46B1E ++:80B3000042984F82F573F64028080000000000288400000010021880080000004008000000000000000080045012F0D8AD244C03C4D084B421F142128514B811926A318881982E498482C8121388738C314186744158857CC2814C0342A0126042412091A1112291421D6A8227811844A0251892285048524C7144F27BC98064182C1221A6 ++:80B38000186848A01282008151C1493115818902904C806292294202160884228420021378915818C48E2419219214441842481C2841B122681412184A826812F089F72449217C2C12914C16394281388A316C251158149E2C478214608A1819C814137862D1A5BA2941F82681AB181614B841428892284CE2542888614A26B511D218C2A5 ++:80B40000141B246B81A9255641181E22281C05E0E2A494541E421F840C2A14018088F2841244811912028884B011D448618842002E4885048044051422008001008D11155818820042C4001882C041988238120038417FAD090000800200008400A901210040010028410000001280020000001002902100000018410000EF5907C0341000 ++:80B48000C24812902118118002114200204428914C4184A024318021160100112C91113012C0114608429092A018641880210284402861244F5C4601282400181001142002301A240048841631444484904400126814200128181800601146082124821CA281641880810285048081F442C8004C01C04822802201400814480000008100AA ++:80B500002828310000004041424182010080041200000020011008F034622002288184842200848018486214002200221860880000209422242800000000101838128820648182502480A448304428F0F3F400000000CC0118A014100200200848460414C11421102941024828002228202162482021120140018200000010F8ACF30024F3 ++:80B580000028000010080040018120440800000024000012001001811C2182048820012140041E884112800222EB34204222429828849014401828089042000042896245908841142150212C05244238001001811C21628483B1322888416281884918B48A3144CA01498682F2AF3F00000020420812A041850214116082882004101108F9 ++:80B600000081801282020028228081928400400142110000000040F87681000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE004800000000448002000000100218800800001400848004000000400428000000002180F106 ++:80B68000F3B5000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000081 ++:80B7000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000000000000006B ++:80B78000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000840000000000000000000000000084140000000000000000F0653B400410880144C02410918A11890980482802281691440059 ++:80B800000012008041082C241184028883442104120000128100008081043F940D0012008124842483858204201148A418411C08821992812A048526147481C44800441004100820112852821152008031848309604240085FA40A418011884118548244C021A918E1888111088C218288E21168148222001A048289844118847412448419 ++:80B88000428868841448248301008061818009208201F0881B0000000060221E48800400C084824411004C1221048514421405000000000018842240A14100004C480840048304CD2F000000165818008C021942021C1141244801701408000070481464112941842598429A0212004911110A181558120012008522028281246F1F0623D3 ++:80B9000046E382117124120417A12646844238129C456288D0527594A812162D361986912185F448221415A22126282A3428285B28141D1686E19211D21214A8242E121C0A989D1646C58C4371948AC112C832436886FFF50B289022401412D121912421C028254241130188850441265C181119422802C3F412248521324480826812473E ++:80B9800011211D2220419822228E218412B441921664A8A438A0388485F25C223042118C11217214184808268C128161851883487654C1913299A11418881064A4141460231A088C27786324099661812453149148182941318343611445084C8101290C4CA8421FC10C160852008504400882492271344838141091114911850325A281E6 ++:80BA000030A56E12892111C241A32908188CB228218112684430211215C8216411129064200149B9421804EF480C842944189118282824406842002200C51204288A465A4112C02A828008101805260184C241588260224084C11A4C06009812480021C0482FA30540448403008C8222F418418125188101802212180200414489110820C4 ++:80BA80000148848004111312181288050010088924461824A242802221F26E27805142C11923614228859228B089638225486D8144641CC2112E14282800214CD28341B218881142BA1C2C488121E2926951812146E424C121430116724842C11868C84C2187A6818818487D48008001818480028C240418122011188442F8428516480505 ++:80BB00004C48C8242E580012484088820480A21686188802D018D1810220048D340040A442442678A90631941991211D123C11142482D3819881241502221C089C084301804144D8186212408814B8820287182417239081A291812222A113128818C31824502A10962242284CF21C9E802295684C914A9068804408814A4188114C28020E ++:80BB800000104842682248842C02A681041904202813128662144248284301004880242124C348848582F4F7510040420228C0230012100884001218284143D181B128188198482424262204442002A01890489022114D214123042941021E2422222800289658A28FC207A4281C0480047018941529C448882840281104842E818C02D0E5 ++:80BC00008401124F1854810028400800832213144444941A149992619C0480941820018C115442E0C746318226141488110885440212228A0223C4811001912148190260861110C441861409264881081130388400008308834214480844888302207218F1E64A608148122332282283232263828342129838812882414A82681426184242 ++:80BC8000E62402128C2294241E284B489488496112828C44044C84842388819118921B21182684810224224A3142F0F2F48002B0114402441284110024008012084481111200142880424A82B12405C80021260210C14C844421008111008F242124850121F0DA6180044D48804202126068282084246314157428130484183028885C01B4 ++:80BD000030141041648800F0442113688C1114C11621918140018C988112848818002120F8BE15408881C44C20018C4494428244413840D4828268184052416F2422C41180384425414538224621A624660A4821200386D814A412604245E1210684003044448C331226F4D838E011E64E4491452E1B2CA261544781288F1BA62827458957 ++:80BD8000548A4D64A71A448F190823A8418F84A18217522AD382774CE942524A23FA3A284BEF94FADC21D262B38B73828A7E38F14C44CB384D129E1E1648E22AF1814A2B5147872CE18C7132F244148383511823791B43012D21DFA3F122322B212D11C7824982F7855C2528B4884CA13511C49D2866C488CF9134252E212CC4C89DC814A6 ++:80BE0000683F31F4244A1F54B6C504AA54418AB4C1C8832EC4879317E48C12F1F14557129BF287949FD1B814D1188821B318A21436EAA4B248E4A8F74C288F334F32221E184487D589347825F4385A8762A733988569A22FA1018F92B811FAA41131CD2117628D3D1741ED38E552149377A156841D218FA14854CA8B249C22621236C83129 ++:80BE800065942415E1F7D4888252521B32488551818D268D484722C8682D143E2C436362FFAA4D011C01254168243044601484204842880220C124114413411401182821100300002B12804878240141706442282661246044400264D0480285F4D31614214F41F1282A1E712F25A755CF85A5154FE3D756BC32F96862A76A1AA175CF264C ++:80BF0000521F8F62DA46E8AEFEA2A21B765B541F12F6ADA94F4CF441414F63BB11F162466F6EFA1B58FA6D94CF43D311F61434AB195D85D5F13135DF12F28985DF1DED62BBC5FD6169DED45F74B8C8FE44548F82F264E6FAFE6C6E4F41F6E4ECCF4CEC85FCE26A14284F53F73829CFD1A3318FA1F34868CF87F31C76ADD7EF44FD2822AFCB ++:80BF800048D228B148F5CC82FF1AF839B77F53EBA4F4464ABF95B545F581D3FFF6F66FCD9F14F41C14DFD7F54C6E6FE1F71371FAFF6868DFDBFB81A17F57F619815D859F14F671799F12F6A9A18F14F721A3DF58FA21298F8EFE4D978B884FC2F36878CF62ABCDCFE6D1C4F5EEFC4F4AE942FBEEA2341B335F41F52D3C9F53F3193829726B ++:80C0000048BC18F5243E7F76F2BB948F26FE8AA827848B55CF66F2A2A92E26AF4AFAECEEAF8AFA6354DFC6F52D7F6BAA5FC6FC51514F43F735318FE6F6A6E6AF93F578584E485FDBFB21614F6BFF98185FC9F9F9581F17F769611F1EFEB9993FB6FEB39DAEA9DADBEFBC9AF92C34CFC3F266EE2BFFAFE6F65E646FC6F654746EF287251424 ++:80C080001B315F53F33D3F9F52F35B788F85F77A388F43F7183EBFF7F3DBD48F22BA8E3848AB55C764BF9AF82827BF5AFAECEE7F9EFE6B7D5FD6F7ADEF6F46F6654D9F15F55C5E5F17F54E4D7FF9FDFA99FED48F8CFEB5BD1D235F5BFF199A5FC8FAED681FC7F76D69FEBCCF82F373FFBFDBFBF1F98F8DDB7FBD9AF96C7CCFC7F72EBE2BAB ++:80C10000FFAFE7F75E7C8F86B768F764EA5F1E0C1880415822A0128441204248C248C0482884890283246144118304004E24318902812024022B1260128C242211242962812009122089024A228122F89987F0A2111331241678280141122217882B9282001843081288C02113921882282322C41850244249A12C2628E8122401846999B8 ++:80C1800021C30480322292188421846C42081A544AF048241CF4D811D032F41124AD131F41724AF3116CE7341D64AF14D141F64A911F89F64A9351AF147934F84AB143F3429157832DB15F83C4955FA2C4814FA264116FA2E519F2234A96D5A2E449D2A2F491242E421F49D22AF19124CF26F8912CE7341F48F26E121D64AF26F91168AF09 ++:80C20000249945AF24B924F44A964B422F247924D84AF924488DB44FA2F45E88C04A19D228F51124421E2CA724288B141D24AF64E989F248B449B24A7935F84AB153D31AE889D442F332484CF8225A4CF925CA5CF8255A8F19E28265412DC99E242D5B1FC9E2A2D541D438FD91246A68C98B141D248F12D9C1F422951F81D4589A61AD9196 ++:80C280002A94984B422B9422A9B98284F32452DF4908004880048400200100000000420000800200810000004800000000000000000000E0730B134131182184008B4283718204848CC158202842142102118189C221002A215DA414842042B4119221148A81AC1237424A68A2862101801488182421A6416082D024F418D420240836B64E ++:80C30000445281A74124548392812AC1811149246114832C5A4914895841C665C8434606203834484A123821424901A571222888041249E288B4624158C21F684592182A38882E84621ACC21F094C6141304812D648316183C68BD1467824521628B1CC544882E4146A428841532889457878E2CA280A381645C33492881C3B2416343F088 ++:80C3800089528E682CBB2184C41A45F114C822267A44F88C5121AD14928E48982CB66828A2411F550F18111812611129012088688114842001864831251041244891444421428C0820241201113400102428A228241A0400822082B224041210F4D3FA0010443822A014112712288521080090884120F142118281411007804228948400B0 ++:80C4000044004119523615581450221914924100148021089012844A0BBF4B4B932114185C9218136242AB422C7441283A23182D4342B94731211F43E8446A8A8591941932426893845228281E8226E22CE1458AEC4AE118810A2E882A316A1EC18F5C012A8CF11AC186839C686DA88724478242224914C888AEE224004455982A196244B5 ++:80C48000422C52188DA18A021430419928E212A9C24E3183584826044344018428C0A42B4148A0121321022E8C367A4114711243A1864A61911D82424A528488E3828432447885F28921302114182212E0223129392446428131422D42890345417414328811921427241C9248282225682D80B886634C492898841D22154231285A78C478 ++:80C50000C84210B182048641B822C9484082416888822FCF4A01182304800145F2284141895824A04221612A09A22AA484244D4826C4641233489448480085022484292194A9400880A8219628C226209142881088251102F0C9BD6041448B24904E40041242106488220041144410D66821C25288428A248428C12414208622443C484032 ++:80C5800028588214481051846883092240044449B842C268C47F110948406442D0254298282422128C0288481448835281180000401C8412161AA1212D441829246222001A420422814B84484286685481C06883A542228400C2CF7603422C912C6449B41152C2CC62B3433218872289682448142E5489D281E82235C48D1483C222496EF3 ++:80C600008439C444A59448471216724CA24123C662361478813838454A888234749C9D288378CA45B82264868394482A45886282427F3C034D184480124804304248880082244188114C0200469444104424229C12200222100221282008118928084842121880381428414C8924F4841A3F390C001800260400214A2882042988C8282C0E ++:80C68000828C88688188250A648197228581028C05450864428289C8241D448A1494414E848884848C642280E2480489A4250028BF5B0FA464481E2400211E24C0862412004443248158242658848843918414222443280A98288E451001498A55222488A021004212484CA2844301814C0445B82288D184FC1BFD008C0180315218409179 ++:80C700002190411083A484C6010011414282844215A284002048084B4800814284608211159281202AC2824125B248A8822841414280F86DDEC0494A9262844480024227881C42044D48B0110241559244218A14C861200818C048478280C243224984C14444422800818342081082220A818822888C01122D9420B8440241001014040094 ++:80C7800082206842236884008E28460444111346C125A63844C830228280C882103CC80099081012084682C4222024A4611844488D41DF9C011212486242002B24624582080034603230320000842444C140E28148E684A2484614612411890C4D214810140813028841008342449888228828F02598604440043024250420C14282192426 ++:80C8000078421418447448B121781104490143422A8214442201004389021818004C04212A01008C21080016149448288429F1A6A1805182262225A34113C5428006400410018C8208428C827821A2A4144062148A42081288482846022D41825CC9242840292288048008222220A8412B1A288F7D0A45084D415034153824358802C06CC2 ++:80C88000212DE412F018464226D84914022782C01C801848C4142E421C481A0886E84291448A028912188818C2C84C5284A88504C820884112384A21BF490D4D442F2A7526A6314742424F4621217224B441C8A8197C8C7684B4E8F185644F4EF42A385F62FEA4112A98AC235ACC4DAD37128BC24FC872E4B8C8C668813071CA82BC84799E ++:80C9000081F42A2A156CC48F8BD298CC892A9C2846F844C4CD4223F2C8C84FC4B844F3684816787CF8181B2BAC4FF8011A912C184366157B222F21F246284AF48A21283E4123D412B842DD41F61292AD285F1C78CAF14B88878C4CF5482E3B841552248E2633E441FA248A3F2CA883FDCC4C3824735EA25E281B8C7A845251219B384E28CD ++:80C980001A881EEA446848B088E48AF814844995B24A56485F930D172456CC218D442CE1E145F121443D262CFD82422344A644116D818796246C4448F4144496D815E832A246857857F928838D521E148B124F8C26FC86416CEC61731894CE4D444F18BA2C1C54216B42B3688A85E4A8B1A2E221BA22A2224C84F3E8A68AA4823E58BB8DB3 ++:80CA00001011121108C1D028018B12118D1211890100000044005048211A0210121802000041100629011880011880011850480012F01E49144F43F75415A7F17F41F5543F7FD7F74E4FCF66F77C3EEFCFF7FCF89F16F7F9DBEFC5FD47818FE5F916144F4AFAB57B5D8B7FF5F9D4684FCBFB848C474C5F5EF63737FFD7FD7D9D8F85A47B6B ++:80CA80008F84F5B23886F991911D637FF5F3961A3F5B57AE8F23FB69619F3B78DBF96129DF95AD898FC5E824F85AFA2F23F23AE88B823AF9ECA88FCAFCACAC8BDA8FA3FE5445145F57F7165DCFF3F22F3C4FF5F7776FEFF5F56D377E325F5EF6E9EDAF2EEF6FFF57D7EFC4FEB595DFFDF1ECAE5FFBD3D5F8579F6FCDF6F4F4EFCFFDC486D8 ++:80CB0000FF76FF2727FFF4F4F7872F8CE58BFB6B782BFF9F98F8D9591F3AF637FF2FA9F9BBB1BFB6FE7CB29F96F6B1A3B79D9F9FFB7775BAFAB8CC1E12AF8FEF23F27AE82AF298F88F86E38AFF6EEC8F8FFD587A7FF80C5F13F734765F63F13F3C4F37F36F77EF75F7546A6F44F54547BF54E487E62CFFC6C67F55F16C8E6F47FDA6C67F37 ++:80CB80007FFBE6E77F57F74E644F43F384926F6CF467E735F36747FF97FD5848AF89F58AAB2F29A72A1F9BEB24F68775AFA9F1B3318FC4F6DBB99FBEF6ABB9979C1F97F348CCCAADA45E92AD8A2F2AFB2A488BF78F86FAF8A88F8BFBFEDC8F8AF928F8FE11144F66F73C34DFE3F337344F77F77F77EF77F7772F6F44F7FEFEAF2AFEF2EAEF ++:80CC00007F38FFCFCFEFCFFDB594DFDFFDAEE67F7FFFEFED7FDDFDCEECCFEFFFECFEEFDEFE5D4F75F6775D5FEFFCC27A9E9EAFBCFCDA9A9F82F2B1BDCEE6FF7BFB9E9ABF5BFB49C9BFDDF9E96B2F5A7BC9F9E1A1BF5DADFCCF2C7E46F2BA982F2AFBEAE8CF83F3E8E8CF8FFAB8BCCFC7FFB8988FA4E659030023021880014712928044A2B5 ++:80CC80004120014002288228801241141118B648029084400149415814844F1248484308004864008CD44882440442F08A45B0A401417024121184024C12829282504243A2148485944414848D241144218932262825224882C2488222440081682008133848288502232408102811A8412894DE68D022F41124A5F21124C3F41124A3D466 ++:80CD000041B26AD141F24A9119F24A9151AF14B924F44A9153F2429147822D914F82E454F9244A1CF8244A56F5264A9E212ECA87594D4A9E24ACF4D1242D421F49522C1F49B24CF89124A3F48164EB161D64AB9419B24A3985AB9443F24A9443BA4A7924D842F93448984FAAF4896B40DB41D238F4112CC7141FC1364A1FC13668CCF64AEE ++:80CD8000941E2C8BA44F88D22A79A5F84A9253BB4272B4F842816F83C4854FAAF148114F82CC856D1A4E212ED887581CE558E2A27581DCA2E149F228C115F448921F49D22AF19124EB121B21AF44B991F24AB453B14A6181AF443934AB144398924F8A94824FA2E45107004880022004000000000000008001880000400100800400000078 ++:80CE000000800200000010026FDB0224162481A2141C1212018811244881890423C4494824874883C4A42281481082E8110A40882308120046088F22089012101A41032181288B848A2182914848CF860A118AC22C230185248283C22A8A3218821433B94111912419CA11131441D118B4812212B148934584298CA4682C4CA1251436641D ++:80CE800018708885C1154E284F1228246489211E48284E2230244E2486C4243681F2D1DF4032344D382A8565D2213828A86718812B4A948B4934118D451988F1834299B424B81936812211A97881F48823C8A0429E218718721436E41884447118C2118CD2169344A11788148997222E4A80B884674A1624B112F612694001240020120169 ++:80CF00008422120025A14142224A12514840018982042A2584014883C8420012008186AC8244428280C412100220F2482400228B24F059C8501440414441844108120042100840088242002A04601448834422095026400200C02810A11412881A32480092800432B0142484F47A3370429224848D322626D1823435A9E712081B8429D120 ++:80CF8000C1045883A21A2A84648288194274230E2B128741281A2C628EA218A0241484AD84982B4190284481818A84D122A5844C321612EB4283082048F4E3612480125148112C81C51429A2212028914481428CA22848428304F02442454122D24821E424A1288C225A620000258C51824048448808422D42C8492881C12C12A014824890 ++:80D00000EFA406535442841E224D22448499B2189481C0434294800183212228826812C02AB0118434288218C82001664241282888071C222511A81E1688011A52424229648A102414B4B50A4870410481422C36182240B2688146C84800224B212243E464A21443688843A52922816041288902816022419C88C2C87200472448D04826F8 ++:80D0800024A824882288201102F0C24840482407182902222428131A042200A6086021178A84901A42848227841381942210A1216021E024024211802408A69844A8E084918122422991189022482CF634AB002880014444008001898824F12241420000002428008084C24842000090181812101882C418800124101324012846889118C9 ++:80D10000F066C380C42422128C9142422B2124281DA28B418C248494228C8682A1214EA14D6842448B248744188366844AB2288144880180C2228D914A82AC422924048B48802CF4429AE8286622991883A512842CF49FB740084D11004C3224842280C124888489914188C024504A8061A88880126211244624822242C812901E805181DE ++:80D180008901881E4C23A2418100C084122002A014221FCA0F214002008480544A000021215082B01228886828848044028E2A268242C84A008028A814824C820144A98A084608182A01604144441084E2CB0A480048444842628741248F240A816084156245284978451284861181081A282211442426112861A8812008928220880180FB ++:80D200004881088880A814880048EED840B844021604AB2100608E44C4100A48833842128118816028894442C848704148480248C2482484608520A428CB146369849A0281844624A4824238C03444F0C8572021A14262894486522800122CA2410027425024660846088002848810029A3431222222141A223228009C2A04C01181181206 ++:80D2800014812200A012A018183FF14F22180838430120A112128A018981011220E148214222812124188884034A89A284A01480D1C2041A984288102C0440C2418082210541424400B09708801145110981400C13820180C18C898128A448492AB842083022888E48E20030480082A28820D882848421085042801C8808200140C41282E4 ++:80D30000DF2C06848005484241212450228682A448820014C0124039280019841111486C28842A8828A24200228081011247842004200420244404A888F07D5FE081442101402454486043428304818304230484C1846228226882838401824800848002248514089018008DC4814C488839282A8808822A880418EFA601848016242151C1 ++:80D38000242C839241812624B882139288822A11021A84114AD82241822828A521E1237112A1834A6981702A011C11182A54182061458CC131144290448222188A51224B421F48044A31A8126AF6441845D6A8D6EA42AA64588D221AB888C858376C29646626B684E843A9EA1A588A5018848C312AB4297818A224AB9AAA8A7288A8886850 ++:80D400001245B812A882C73487C11365848B481C21AF82C24BE89AE944664BA08949F211C62429041D341819B42A344412CB22C74197CD8CD9A27152FA48824D288FADF812A99AFC69144632588C44F2C268EE48AB44AF1AACD5A37628EA86F798584AA2552AC5122F82E248C8C92B959B4487458E544B828EC829B4117959C8985A850FB1 ++:80D480004D444B1849ABF3242BC47F810E125B5122774187415A41A4522F41F5239A2F22BA22B448841192984C81F14E181E4AEF88C4198B3A1BE22C58221AA1258E284F49FFC474271823E281041F2DF862A485F3381A8B1C83EA88C3581E882B1CC9B13879428C58198D2C224242327084D444A1138F1706404178240118200214001222 ++:80D50000144025C1211A44011C025C0285814101144100101211120111241122114512410200281648045C024C024CF25D77A0541F95F11C1C8F81F545454F44F45C525E421AD413F67852AF2FEF63F1C3433F14F74144DFECFC46427F1CFDE1683F2ECAB81D31DFEDFE87A6EE6235F133AB3F3AF3F6764D262CE68DEF3C7413F3E2E26FD1 ++:80D58000727A8AF3A7C7BB441F3DFCE3615F56F6455835F587918E92BF1FFDC1D19F1CAC898F8C7CC8AC9DCAEE49B9C4ED4FBFD4FEC3C7A0551E58CFC1F13C3C4F64F546466F65F56C64E3B38CFA6E648B77AF6EFE5BC33F3DFF4BCEFFE5FD67737F15F1E5FCBF68F92B291F9DF4D5FE7F6CFA69FBBF15F56A6A2FAEF6E76FDFFAFD297BA6 ++:80D60000EEE8EEF2BFBAF7E3436FFED238F817D59B448F8DED8C74D5BDD9B4C8FCCCCC9F9CBCC8FEC9C19F9DEF8EF8C8C88F8CAC9DEE94AAB9C2ADFE2BDFCD5DB012F111513AF234345F75F55656EF27F3787A8FA5F16F3F6E3E2BFF8F85E7ACD48AF15E51CF69F97F63EF2FFFFCE72F4FFF4B518AE13CFFEAE89F96FE12182F87B22AF73D ++:80D68000FFFD5FFBFAD2CB2BBDAF8EE681F3E1F36F6AF623AA7FEBF95A598721AF8EFFEDE4CED92B442F44F9C8D2BF95F781991F94A4985AF1D4944B9DEAB834BBE2AFFE4F4AF9C4BF242B559F11F115355F51F3195F6F65F55E1CEF46F73E1A5F7BFBFBBD8F26F6DEFA5ECA8FAFFD4CC3EF65FD6C76FFFDFDFCEF2FCDFDEA789F9FFF4859 ++:80D700007B2F2EFA7A683F95F54369ABFFEFEFBFF6FF787BAF8FFFEAF81F9FE72FF62CE697A8FFCDF8584BAF2DFDEBF9DF4FF7DC59AFC4FD4BDFBF3DBDDAFDD8D19F9FBDF8A9BD4F4DF9D4944F1EAAB14BFEFE764F4AFB938180012A01248C8401411200248C04122416586892892229048B2420141298128982119892A012908284218C0B ++:80D780000416088A0484800484284820812288027FE20E82116041850122165C2819A682842C299188411422344814E01442C8814846D182C121118694424A32221110011B21B011B422181158414A21511AE014012009411843A134F02B3DF024521F41722CF21124A3F61124AB161D24AB141D24AB941B21AB9451AB9443FB4AB543F338 ++:80D8000042B14F82D412F924481CFB244A8DA14FA264114FA265194FA26459ACE449C24A1F49C2C21F49D22AF19124C3F69124A3F68164EB161D24AB9619B24A19B54A3924AF443B242BB44F82D442FB24484CFB244A5FFA096F22A561472212C3B611B26A51418B144CF24A941F41B2489A25AB9413FB48245399B217822D947588DB85CD ++:80D88000C5B45FA2ACA15FA225F1248A96C14B9E258CE4C1D234A868ED131AF26881967428E148F26A914CF26895118F449B25AB94322F445B842DB447822BB46F8284FB244A1FE6464108000000000000000012000028008800004001220048000000844001000000005012F0A83400228D241848444E29814A02AA212381E14114981AA4 ++:80D900004444844A924153C22C22438221D48242484446181864289082491882428AF6284643E2812421C41400842A8181828E8234443E77004339111426281182511885028562848514A91443046212822848428246C84822884C92438B24A0A120C4819302681632318A21314828292411C8488B121800006011F031EB004E145D28163F ++:80D98000C14843C1491049B284E282B12AC51C5C81C4484064812C28D6143454A24D28586AE882382C59744944B888128CF84281A942946226C229AAA14163F4443818728D14896482202181C2A2281E411E44EF1A048082012230221628468801008364812D14414A024A1281628280144802246022800148C0818220C11248C3C2282416 ++:80DA0000480020911822004200F082872002A02118841884202112014002508585020010011190134E211909200482004100304212A981B622013430488008004A034A88F428562035142D288551482AC1E462226F8448A1C113B48A3184981D58AA216F1AC6C44152884A6244484C0468248648F288141AB28312821AB1852694A1224B5F ++:80DA80002C1819982A2B84863381460247152B4A8A21882262821FA70B5800190232C28B2430421C22283412822B81178587113A4C31C414808842C14216A5428E71248480A8A1372A00110013AC21CA81B381C12211908948881991421818226889F266A3803214278216C81C844B2120E2C108191561884400435A288A02425211424C41 ++:80DB0000044811008248E901002E84F024C1482902E982742242287C8231421032442A28280E88485F560E418146A4121AA2248C122412284142A8421741AB28128C844824C284471547190086382620342412115222001813A3211800122484C5E3881288D422911C424218B0828102AFDA0818C32204448901B0138482B228012A28048F ++:80DB800088221C2135C228502A1811C248830818D021042481444A0200481213761448B22484B282052042A418488121160CDFE6060016184418042881420000400400288504A042468441016218200428208601808422DA82120218001100428C0122298802484FF706442216AC12CCB13444D824B2112426C32220BC4531848822884EAB ++:80DC0000242D848845F121824230414CA484521880A424244843011C2385A24816A21416042D22B083042D12788F44A1182489A818C9025FF10A1844402442280283424864C181406282188CC411128B2443A2144D48441181239228C0245890122826082A01221226C2282641981A1D4889688142504820A443208281F4DA4F00168482A8 ++:80DC800084614425021226021602242820011661220011672830141024140430868021521A88434291942C11A441420011A01848A01244602A4C2121F43B5B241A04894144014418448141212E148B2100454202584B812F12018082742802008A04400548122C2101194401D0427242824304714118C2884A012821F08E7C00289038847B ++:80DD000040AA12800844844228100224004AA8123081252231421C289A22444823048488168478112452411C08460130581B18112443CC1242860283718422F2953F00424904121250684441844A028492430222100C0048182288B41AC2481654811411C46026819481428118A1841D1416851224844118A4211A220221413E7E2049A8CD ++:80DD80001212140042220022401162182381021C0280243242284840210100001122802402004004400882413A080088208CE4BC4492241C111814842201901413D222018AE181E8449181983888391D410188C0A468443044A2924446A421403291C0A2F64231A12CC15210324441000090488410F4B391C048100122216042A415088403 ++:80DE00002400218D221C8468410030812234192191481490484D212001141BC24188411004271220741152211622449224822C22614420F8EFDA8042149422854294128128C89200210022112180B464E84874441191449084926A1841044A882434144428661461426E825812142A248C858403A04100704483F2729E408882142892183F ++:80DE8000812418388942941828348E3180792112089032C05282496C31009A3212271440518125A242A01816088C21820854800200201241881202B50B2F42B284E261D248E2D23314A0312B124F41D1480A8943B298FA922189F2138337224F1328B921F451C18695634E144F23F112475F84F464812E112F2821D814C448481E143B81B1 ++:80DF0000181A3B31AA11F18222AAC4121D41F012D18ED42B44A6A8114C9281AAA242CE81881F380E421B435B124F8151292D526F8171245A44AD8A1D18A116D489F8221117424C2188D148C2C42D814CF261828642F342659B162D818B298ADECCB6148478157461D3B1FA841E597AA5FCC4A147C46FB8E282516A37157AD3C27F45443112 ++:80DF800024982B288AA91189781AD454F446248F6F4EA2518D1485A84212CC5228A7448B211B6A26E22753A22B15244F24F932836AE311DAA2F542114B2D2A91466E816B6A8149A81B486745142F647A41A4141AB222A422A75F46C15C3F31E241BD51F455314C1472594132571E164B414F62A4472E622D584D3816A242BFF20B0040218D ++:80E00000284428442804426044200442008200280080C218D08408001400100889088B8248888008140050425012122011F81F2C246F41F2652DC761EF11F56C656F6751486F46F664649FD4FAB9298F86F668487557FE4F76FE7E492F22FB6B89CFC2B6F4FBE5F15F56C9C26F6CFCE674DF53F433E9DFF5F5EB293F1BFC4B4C4F43F7C4A4 ++:80E0800041DF55C5434DA6DD8DCFE8F6CFACDF6EFF777D5FF8DE13F18D3FBF94FD1B599FABFDCFCF7F79FB8684EEF22F26BC42EC2DFDCAC84FCFFFDCDCCFC6B62F0D6F47F7357DD7F1EFD3F16C676F67F34A5EEF62F26466FFF6FB5EFEAFA3F26A5E5F7DFD4E6F6F62FBFFFB3F27F7FBABFFF2F676727F1EFFA5B5EEF36F6CFC64F4EF470F ++:80E10000D7D5F445472B663F17F66E6F6F67F7C644DFC1E122F2D47E4B394F69F34E6CDF76F7575D4D5EBFB1F38767BFD4FC5B59BFBFFFCFCF7F19F9A4A66F4EAFC46AEE2EFE8A88EFCEFFCCD8EFCFFF4CFA246F47F73171C7616F51F13C77EFE3751EFC243CEFE2F627E7BFFBF22838AF24F64B51AFB9F926B7EFF6F763E33F36FA3C6C37 ++:80E180006F4DFCE7E15F53FBA4B66F6AFC66E4DF36F6656F7F5DFD65E39FBBFF44576F4FFFC4445D4C484F6B76B7F7B735DF45F1E5CF7F56F69DF75F72D1DDFA5B5DBF9FFF497B7F6CFD86966D44CFCAFE38589ED62BCF8F8FFF7E7C4F4FFF6474DFB942F27674DF5373157717F53DE5AFA3F71C1ECF66F73E7EFF72FF3ABE7AD7A6F38360 ++:80E200009B8FBBF976F6DFFBFB33333F3FFBBDFD6F4DFDE7E15F4BFBA5A56F6EFC7666CF47F7757FEFDFFFE4E29FBFFFE4F66F4FFFC4445FD1E131F1BF75DFF8F29F2D9F5DFEF5FF7F1FFFADF7FFDBFF16B5BF95F5FBF9BFB5F656544F49F92426EFEAFF3A68BEF63B578F8BFB7C7C4F4FFB24341F110F4901228445022C214122212241CE ++:80E28000022413412241022813291441140121460400100618D012092E11004845012601144005289A84024A228122B85F0829E441521412C38216C844F08164A38214AA49904474AA94225F89A424412819C48429448465492A44D4248D822C04824130441AD2148894949A346A824A11B142311428484E841088E444022EFFC0421F41CF ++:80E3000052281F4132481F41326A1D2CAB141D24AB9419B24A19B54A3924AF1439242F1479A4D812F924481CF9244A1CF8244A87114FA27498F1245A8759ACEC49C24A1F49C2421F4952281FC932481FC9B24AF8812CAB941D6CAB9419B24A19F54A9343F24A9243F24296478229F93448984FA2F4B6CBC0421F41D628E441724AF111246C ++:80E380002356C1AB141D24AF44D941B24A0B2F5479A4F8421157822B94478A2D916F82C4914FA2C5914FA2FC18815D488B295F827598C4CB8E24BCE5C9F2244B9A74287111FC48821FC9F268821FC8B22859C1AF64D941A2B45F88F24A1243FA429226F84296478A29F1B648A9F8245A2EAF008248000000001604280000000021800800E1 ++:80E4000000000040080000208404008002000000442541F15A5B4004229189418816081343183818482016F928111119129574803824482062281220814214452102222219228302220048130421644D588A43E88284628482BFA7071CA238C42828268221A2348F2418A112D0684868282860C2248182121C140223022D48895882212513 ++:80E48000A814238BD1128893114924018B14478585A124660989A181E6CA412A1858628218B641F468933025E28D248D218963A24AC2284A7151581C8362818F6488E226581836598134158285A18125249C2228A9D882512A135182426B3816F1C2292826E14294219048421C922413A6421B142CA1C225F524581EA8446E881AE2917E70 ++:80E5000092C4E5001200001820A2282112008180024C225248430A1984020042880028491101802101122AA121C9412844088488844622484218020017AB10025041411A269261C048100113581840A64214A22822800400841604284908A024410050248C94841741211A048A028460888084B2141408006F824C912116218232284148C6 ++:80E58000C56244222F9EE186088C6548871D8A42388446B811948811263449BF4422A621931498488991C818141CE1114836289CC8214A32C2CE1B881E81481F85C8D34B814AB116F888124F811832D68B2442C9F6256B00190144285A82E4841224A6864E28C04859B84191A42F84D214B848E811260A60142792281883052886EC8804D2 ++:80E600001B429011442895362986A48183AD9482A84815E848810846D842D8243458260844BF8847922120922145482452614284B93181B01118688800800284144916684442835214848C240112D041814842888864261D4431211C21F48811CA119258698969832931844842ACF6596640F812242022810181180049014F821808412222 ++:80E68000E04241484214083200205581B0211C08C2A0241C08828923A121401884382812A0832E14228842290AF02187205428C425845641498482028245082A614429A861484400C22671223264478182760428001D1412115082428148854402896444824F858AC611816392428502188C914A432574C407282001642400C014906100C7 ++:80E70000902C2185240800848A0410146881842AA82560480022188002100881181425C842480088822008007FBF0D2A14144AC4145C21342818002E49909447848D24218996841E24804469A24B424912E4C462816E181CAA6149BE8411C18222229C8804A4E084438CF15128A34CC1482762EA1138821283658418F07ADA40A2214D12E5 ++:80E78000286602612062418812404822E84413041028C8248A0484800110081284C04880012286AC121608488928081E48290130B4288288A24684F47269002826541850188584021C14890842814B2426114484B44432488444418185849268421028088200204408482C2804001E444E18620018818189882404EF7641C24C108A522817 ++:80E800004C029344021059284442304C002648082C82A142414001802402802412561844481184428742221C811208188D9421808118840824F7CF2042054425A441224664828914810280033822424C94444D818502418800192402424021041908822008901485112291228724004246628416C644162844F472AD4014C21481001400CC ++:80E880002228424111000022402252142290621484400829481804230486010063082244428314A4180089024120019A22F4E4F57082114409141410040084144881C04442114C420142601600422002200413088601402228A4482488002420248801400481812978D201608228282284442890A112441886882402848100A19024899831 ++:80E9000048461108814246C491830888C1411668484602C08812284008494148888149C8885042481F9D06501221111244100A0025110845022480440241002021023084400128400E2180049120841623082400418800128298F01FF5800240942C48848041488804411220B1840284809245423021003044CC5184C44541848441D8413F ++:80E98000187C18144404CB480058418504104C84C1424B1444444542C158C042242002302810C42480038E1C84608288C041008C016A184211024091C2814548D224142898410040A1214C0AA840242484022850A284DF2A014F24738CF43A228561214D3C1D24001D48411F14145C18482F48B46834CC30C48D226F945C51289C2E0215CB ++:80EA0000088F8EA6441742483D8C8F24C84410BC88ACC82486C88283FF44122A64288B742CA871859A582C8868491E18524B8C241E2834C0224415962A8F16042F16E2A2511899031847458B164B235953428F9654481049D24234488FC4966889141842728868816819642E2D872457C185ACC14E44001F52D21101E088314247484784FE ++:80EA80008C914C41CEA2828F22D146F8E9A4F02344371255F8242857C211C5D8CC94286A4AF9AA28158A7C144868C12AC2242E686F54E442F24C684B1247621B81175629F24161457418B444F4888447188614349D37D8304437DCF1CE444D6CAF88BC12B2687B14BC5E544C1A28B254E4C1D3A8D14CD48CEDC1E484F4DFF6141245215197 ++:80EB00001270420123042F14082F140829082D84D04208290888118B842440A224248245A22445829284281C08004D838449084D838488C08680A8424C284224422442F449C2346F43F2353D8B315F12B252F76A66AD42EF24B41AF5CBE22F21F56BE32F4FFDC2D2EF65F53EB66F4EEF6AF22F87AD8C1FBCFCACE82E493E2EBF3EDABAF32C ++:80EB8000434B8F86FAE3E9AFE6F67A389FCAFCB298AFDCFC212327223FB351BB3F99FDC8CC9F35F1434548CFC6F6EDAFF7988F88FAD8DC8FACFCCE788BFE8F8995284BB8CFC3F23CDCFEE8CF8FFE7C2E2F1745F274644FC6F4282C4FC3B768F26F67AFC4F464648B55BF34F4FEFC8BE68F8DFB4656EF4DBF3CFBE8FA2F6AF22FAFED8C5FBB ++:80EC000098F86C294F7AF82434DF9CFAC8EB3D2B8F86F2A3E9AFAEFEFABAA796AF8FFDEAEABF92E22AF8735BBFB8F89BDD8F8CFC59511F1CAC44CFCEFEEDED1F5DADFD8FC7FFC8C88F8CFDE8F88F8BBB18A631CFC2B26CBCC2FCD8C8CF4FFF9D9D346F46F725658F62F227276FE7F3787C3F53F364648FA1B141F43A3D1F1EF6D87ACFC5BB ++:80EC8000F55E1C4F4DF39C3EAF82FA2D29CFE8728FF92A281F92F6E4FCDF96F62DABDF94F42A498FBEFCC8CC8FE7F38AE59E9E8FCEFE81CF2F24F293F3B5FB9B998FCCFCD9DFBFD4E449FD7C7CDF7FFB33359AF958F8CF29FC5E488B988F83F78CC84F8A79B4FCDCF46BDDCF8DFD6C5EC712347F76F72D619FF3F3773FDFF2F27D7DBFF1DB ++:80ED0000F56E6C8F21F5C9C1AFB3F7E3619FBDF1D4D4EFE7B1D6F1FC786EE2FF92F28C6EF7989F9AFA6D6DCFCEFE6D6BFFB6FE6D69AF92F4684BCFE4F4FEBCCD64CFE5FDCCCE7FDAEE28FE98F7BFB8F85B99CFECFCDEDEFFDCFCD4948FEFFFEE8FBF9BF3B8B8CFA5F7DEDEEFCDF5ACBC8F89711CFCBC9CC7CBCF4DFFC4C4CFCFF76C562F5B ++:80ED8000BF026130222042088400400812E081848244044A020028114400A02400208408490800884849880448200140840440241828F8F36E201A312440D141224234288285B181123884B0A4048A044B48005C388428498422621C48C08882485024112068241508849021298182811482842108869898A09486FB9893D036F511248D5D ++:80EE0000131FC1F248131F41724AD341F24A131D24AF349921AF3419F54A9353F24A9743F2429747822D915F82C4914FA2C4816FA264116FA2E419F2224AD6F5224A9E242FA2F491242F22FC91248D831F497248F29124AF34F8812CEF24D941F24A9319F24A9251AF243924AF24BB34F442B24F82D442FB2448B84FA2F4D888D0A4859650 ++:80EE800058CCB248F111248B141F41B248E141F248941E248BA45D288B9443F2489526E8543B241CB927B448BB24C1914BC21E81419E212A641D2E59822E5117812EC21D442CF99124AB14284E911F81B242F811248F44D981B2429B214A1994B21A94B24D482BB42D48B84D587F4203848004000000000000000000218001000000000011 ++:80EF0000000000000000280000000000AF1B04225126042741146A912810A4C28485614412914417428819840214410080932428811820622C1416611822190914C016418DD18C3851C1128C8C2222FC42884E28489044FF9A0152828184688D3441636182149092708A51284AB2880291A213A4484D682299B24C92214482213391222A31 ++:80EF800094C2141A0432D02256188D1298E214D02231881B1482492104C1249241C609EF7C015A7241CC24812F44C12416F42A14815443C298267A4114D892424C518126D12124F429441A5281CE2C112A31842215323128AAF4488139E114312124194D29014F2A5414DB1898ADD14E141AA281286088AD828E7A49348841F73800100890 ++:80F000002217816220024E824061881848A84382A84828821084022841282532182014024880896222503892186024845081884D4842224684042084F49ADB1044840122285081220082421289010018828D858A845881444014050088126041001C38112C28810100817042230148200284428483A442AF5F0E281681D21C82018B28401B ++:80F08000F121881AC2318819081A2AC2C543268544842404624883352881702214880C88264108218D2317C81AEAA9243212C21AA884AB4889289A9CE018B1988204C47F3E0240A5121D242222818428890A1A0A1C19A8A1224E844B12C886358448461884C24491224032A4204C84485118D022B811B28321919824002458238884CAB88F ++:80F1000010018C944828CD3D9024121088018A4211418113A18480014081843148488811800449451808901820012882130181C18A82942283A1843B1C8283948840048CB9C803904C47DEE08431244922420420A2218B141054812E84414A0262848922DA4862412CE882012481000011818448214A084E2283A4484148008244CB86204A ++:80F1800021048828100289FC6FDE50C16015008C01140021412042088C08494494182494285A98488C0420048C92812822402804202832381681241451622220149A48008511A228288FF20B22000080C248142048A818241200411E8118A0840044280043138E01484002902130186081602A8138588460998081C8484A71228182043FB8 ++:80F20000B4074E25221C8202842899B611C24288841C08CC018338441B818B2112E65C14A82DA8424881414784188982080000706822AC2849B2113C42282490449368258B4120A4248982A2484E884B9C8041941410240100160890184318A2422072481494A890186044261818A2212100422688D222042E818041B848618122844AB1F7 ++:80F28000915428868801E088948812218022F23169002800418041941CC011228C011880032B948A860888240018411220112181088622C18160188311882808002484162264A410080000BF3E0800002011044021844881282442814114018C726801101488C241414A224818140881C1121602104122481841B88154822460AC241042E0 ++:80F30000CC164E14FFAC0448004160422128604221854244020082002A01184B282004002084018304806212100888228988031880044280224188820470D408142508409442002121839283504281109226848D8421498C84D424682240022E4240824422A1219582942142202424044A6144186044004242220040B845040020C228801A ++:80F3800041E281021220011A2AA8A1128890821249082A084200168203294302808188068302842284008C0480028416E88204803422D302286848004028011A08174520058F15421861155E2852842B212601114D11284C62188048981111828091181CB8111448141805008902301820042D4842A0849F19490210148408410091850118 ++:80F40000144C420C60424C1251484284488442E0449148008D44C0885041C048801564142180B44981D8220127A28C7842022123084568484123048243182885820380E28842C4488014F48144256118407424392211C02134602113A2C21412003021224001104129B61844311140010000468121C249F05EC7F0422AD0140414001E44B3 ++:80F48000A041681E24481A8234180020011821111826840844190160144A0184112C95488420088002444982224408000010026FF60E2324185444412F2112682165B81BD298F2B2E2F0164483F211433B826B21BE815FA4352C2AD2917221D12242D416D144F323295F1298221C94222C19235AA999C1491F2D58418817D42EA8174A1F9B ++:80F500001161141E1215D12A445822F05A1839C84881CF157466E4474E82F4E824811AF488214B12124B12384B522AD19981C112CCF184B88D111F68E944F128A11EFB1ABD4CA9242E811B221A445244DE5236E1E928B11D44C8A136A1211B1185A8151F9814EA2CF458788CB4117968E8880489843548488F24B42261461C88F1C765F03C ++:80F5800021222154282624D444C14483E3B8B85524745529BC543C681A62124D489674827448AC4B4C7C84F84443813AA454284A85F14858C688711194324FB8B868C2518D2883A4828130485042A72447872F267848F8826A242E28D0844496C86F52031122110042200488C081800800281110010015C8241508848E2415684C60481CC2 ++:80F6000061481486446148250121D0120829082C088880082C088B8400FF5248E32454D68F92F215548F94AC228D484F21F55E14DFDBFFE9D91F9BFBD1D14B918F85F77D77BF93EB12FA4888CFB3B516F121214E58AF86F6292895FA6268DFB6F47BC9DFABBAD6FCC9CA6F4FFFDCC36B991B994F45F9BDBA7BEA8F28F8A4A69BCCDF7C74AB ++:80F680008AF29C569F8DF511132FAF7D8BFBCF6FAF26F6DAD2AF2DF5C24A4E4B2BFF4F4ADA84F4366EEBD6343D236F56F628291F41F148CB2F25D6CAE461F55E1CDFCBFF79BFBFBFFB73B32F25F94E7CDFF6FD3BBB6F23D3CEF9785AAFAFF75F7DCF4CECAF7F22F282922F83F35DCB7F1BF8B4A263F99CDF6FCFF7DCDA6B194F69F99FFEF1 ++:80F70000FFABBBB7F7D9C24FEEF6C8CA7F74F44A4A4F6CF7D85C1F39F8DABEF7F8BFBCF4EAEAAF8DFDD25227A82FAABEF2FFE6E44D4C6FE2F34FAB243F36F62666BF82F2151485FF6266A5FE5616AFE4F1BBFFBFF7FFFBFB2F35FF9692AFA5FD3F3FBFB3DB77F85BDAEFFED692F1EBE91D59DFF6F7E7C73F32FA6E677FB77562F6E3A7BFAA ++:80F78000BCF4D6D72FABF3DADE27B87F78F81252BF7BFAAB21CF4DFDBAB19F3C5C5F9D41EF51FD595FBF99F9517B3D83EFE4F4AAEAAF25F55AD22F25F5E2EAAF87F766644F48FC24749F9D4DF362626F62F62F2C1F41F14C4F6F63721AFE5216AFC5F199FD9FB7F7EBFB3F35F3D696EFE7F95F9EBFB3FB37B37F74FDFE7F6FDAF3FBF99F32 ++:80F800001DFDE1FBAFBEFE33A3BF33F3F74BEFE3F8B287B5FBD2D26FE3F39ADE3F31F19393FF73FBBBBFBF95F1DDC5BF9BF3C9C9DFF4F44B49FFD7FF595BBF95F5DD997D87AFA4F46A68AFADFD5A9AAF21F12B2A2BFF4F46F684C64F6AFEB5D1001006410010440800405481204104301144824400114218800100182002008044C14860B8 ++:80F880008114481484A04100285048F0F6C3A042006022C012448592218726194482E42428C822A24623D158AA48A82AC4816722142E5244C02125120811259221701138481181828119A2149018502240428841384284A048FFD40A2E421F4152281F4132481F41366A1D64AB141D64AB9419F24A9155B84A3924AF1439242F147B24D825 ++:80F9000012F924488D914FA2D418F8244A8F51F2244A87192E4A8F59C24A9E24ACF491242CF5912485F3912487141F49326A1F48B24AF18124AB941B28AF243995AB9443BA4A39A42F247BA4B84AF9B448984FA2D4C40D6D5A1F41F428421FC192181FC1362A1FC1961A1F41F64A941E242F147B15B84A29F34AB55782AF143B252D916F26 ++:80F9800082D412F9255A1CD9A1E8517A246A195D4A9E254FB2E459D2A4F5912C4D139E64CD119E24E7161F48F266111F88B246F18128AF54F18124AF24B395D2483194AB2443D82273B43848678938ACF565B62028880400000000008004000010020088000000008480040000004004000000004001CF4A0E1C42E21182D24A7212488153 ++:80FA000044CA1822228622E82528C2A2AC318416668A28282850128440B28882862461422810011041682283F144122608A885120829120824002084F4F428C0148E3450841264442F22F911242C82883818872144E451442E524A08441614F442A887426B128B24699A148931322D4A1698121E4425628327832F41823214302811288B1A ++:80FA80001400898488A2148116B81462831615F8572CD041B284B211F22442434112D42272148891A4A88B8327A1522D2243CA1C23CE942682A212322F2468D8E9332863B81AA25213F1124A2E1CA9B314744233282D3217438CA21216C8148591248C6B82A1422B28800125C8122A611483F192A180211142782862C1149A64328C1202CD ++:80FB000020C8844548036C81948A41444189220248284918B82204000018840045028726288004100889821428C124844C81F4EBE810840200C442100A4622C19240010018008480044904480090421004211200812800000088008008421002006FA90B400110C8112426810388248C2404288F2114C4422880060089022840484808830E ++:80FB80009424411042A242124A41CA483092905246C8C816324C2622080080F4A3320000001608221A0220911829442142081E42006800E082040000004508441821102823441848220812848C2471460829080000D50AC113220481544612110A4F2448220E004A51422002A480844104684048984A8064C221200423061830426041B073 ++:80FC000062882408882242101202427FC30B49420400228C44A2214415288461118C083846628218008440180800841800002810084422E022012008160841A9A421128242818844F0B2A5200124400841F1001A0448821AB44A0181428744200488004084C12226883112846CC21280624A90122441264442880D184292844A0218581870 ++:80FC8000684E883BCD24001122122D1412008130182100410018242E1844414042048B21440060C43200180028814840D84804008118224100410040B2590141441042E8423114104284B54891128E11839914188D423A44F4221844C182400C8D344941F8221812C48B124D221829119884442AC1424D22268834828812B044618936A8B6 ++:80FD000021824E14898441A484DFCA082B124081C212704852C12A415818200446C2482810E88104480081210020022452002220826222842011441CA841811648A24244480018824A42FA8FE5001008A100100A1400C01500304212440080120225825222000040022502C1281800840000201102000000BF8C0C281220A1215012A1242D ++:80FD80002470124112045022400280120C6082695248404402213012211260211014A212421A1802812014420422444508222257932022012481240081502119014400002D4210444208222668228012060080512218C012C024121A028100818004002240142282F225BA50888B444E48523240430A25524445F424222AE252414202204A ++:80FE000041922225A6111A31926145180225121102A558888F24E42424440C2120E428514445B424A222262211064054282125A211FF990B0000000024000040010000004008000000D062021002240000280000002100000000F0658F40E882A42448400400241646C5242829020000C02290121898828800401141C32C842E486248211A ++:80FE800044000044444C838202001881400229F18EC64008480021C02210014C81A1220000188124842180018800400414008C522248000080011244800300004062842183D4A30980041440022001448082010000002180118808241008250140488404000000400428000000002180F1AB61108401000025022412101802000000840017 ++:80FF00002002000000240000400200001800000044002004427F5A0B818B4442460150220010143424222218401408A45022121A22292808101211111138188B54424221001200414163222242020040026522B1840B8484484822402801404254424A820200000024258481918888004054142601A484299442220040820144C4684A02D7 ++:80FF80000000404812F226C32001440021001223010030411002100840040040024112200222004400400812008140020010C82800009FB10F00000000001008240000000000000000412D22002400000000000000200100400810F47A86301400112461A1003C2111222115810100840041000000857214448442421216221202000018A6 ++:020000040001F9 ++:8000000012000018212001844A04C14F9B0920410440022722002971185128242304214018088902418322022421002C72269422222622512250224181201102104A12021004225088414AF4737500222214284082F112122124100214004112404808810084004424210069226122442428002A810118811252420040588800008F890951 ++:800080002F22F212222CB11221B112013C512229E811F111119B98867948F888418F8424F4414911489558884F84E444F424444B244F4222E24202286554442E242F22F21222182B111AB892092C592229E811F111118B988E898F84B888F44848424E4880548885F84448DF1D036F22D226E222A113122301502229C81B3F1191D19E88CF ++:8001000087818D418B4442141581445C888CF64844C5B444B2242222024054444CF326226D222AA1131A389282502229C81B3B1119ED897818B888B448240400C485C8688F850F48420000008024040000000000000000000000000000000000000000000000F093598024040042424200000000000000000000000020240442484AA44444 ++:8001800042002024040000000000005F380448424842200442000000000000000000004800482004A0440000A044002004000020882808007FCA0548A044000000424200000000000000000042004A04800400004A04002004000088820000B0260E48420000008024040000000000000000000000000000000000000000000000F0935968 ++:8002000080240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935900002004000048000000000000000080A4444800004200008084248404000000000000F06CB580240400000048420000000000000000000000000010 ++:8002800000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F99054842000000800400000000000000000000000000202424040000000000000000E0290B4842000000802404000044 ++:80030000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F093598024040000004800000000000000000000000000004242420000000000000000009EB27E ++:8003800080240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008004000000000000000000000000002024240457 ++:800400000000000000000000E0290B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240400000048000000000000004D ++:80048000000000000000004242420000000000000000009EB280240400000048420000000000000000000000000000000000000000000000003F99054842000000800400000000000000000000000000202424040000000000000000E0290B4842484220044242420000000000000000004800482004A0440000A044000000000082888243 ++:8005000000F0E56280044A04000020240400000000000000002004A04400480000A044000000000088820000F073DE80240400000048420000000000000000000000000000000000000000000000003F99054842000000800400000000000000000000000000202424040000000000000000E0290B004280240400004200000000000000E2 ++:80058000004848480020A44442424200424848482004000000888280082F210A8004484800004AA4440000000000000000000000484AA4444A0400208484840400000080A8888200B0F40748420000008024040000000000000000000000000000000000000000000000F09359802404000000484200000000000000000000000000000050 ++:800600000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F093598024040000004800000000000000000000000000004242420000000000000000009EB280240400000048420000000000000000000000000000000000000000000000003F990520240448488024240442000094 ++:8006800000000000000048484800424242A0444A840442000042000000008200F0756D0048004842008024240400000000000000800480042004420000484AA4444248000000008A0800F077C80000802404004A040000000000000000000000484248422004808484040000000088820000CB12802404000000484200000000000000002A ++:80070000000000000000000000000000000000003F99054842000000800400000000000000000000000000202424040000000000000000E0290B48424842200400420000000000000000004800482004A0440000A04400200400002088280800FFCB0A48A044000000422004000000000000000042004A04800400004A04002004000088A8 ++:80078000820000B0690A48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990500004A0400004800000000000000008084040042424220040048484A044A04000000A0888A8808F01DCC808404A044000080040000F8 ++:8008000000000000000048000042424248000048484A0442000000008A2808005FB30248420000008024040000000000000000000000000000000000000000000000F0935980242404200400420000000000000000002004200400A044484800202404000000002008007B3D00422084240442004A0400000000000000000000A04400424C ++:800880000000A04448004200008028088200B05C0D48A044000042200400000000000000000042004A04800400004A04000000008028080000EFE50E48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420012 ++:8009000000008024040000000000000000000000000000000000000000000000F093590000480000004200000000000000008084840400422004002084044820040000008A088888F072FE80240400000048420000000000000000000000000000000000000000000000003F99054842000000802404000000000000000000000000000020 ++:80098000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F99054842000000800400000000000000000000000000202424040000000000000000E0290B48420000008024040000000000000000000000000000000000000000000000F093598024040000004842000000003E ++:800A000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359800400420000000000000000000000000000202424A444484800200400000000000000CFBC0D48420000008024040000000000000000000000000000000000000000000000F09374 ++:800A80005980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F093598024040000004800000000000000000000000000004242420000000000000000009EB2802404000000484200000000000000000000000000000048 ++:800B00000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F99050000000000424200000000000000004848480020040000A044480000000000200800F0F9698024040000004842000023 ++:800B8000000000000000000000000000000000000000000000003F99054842000000800400000000000000000000000000202424040000000000000000E0290B20842404420042420000000000000000000000A04400420000A044002004000088822008008F610848A044000000200400000000000000002004A04400480000A04400001C ++:800C000042000080280800004FB50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484200004220840400000000000000000000000000202424040020040000000000004F6207800448480000200400000062 ++:800C80000000000000000048484A044A0400A04448800442000000200800D0CE0848420000008024040000000000000000000000000000000000000000000000F093598024040000004800000000000000000000000000004242420000000000000000009EB28024842404422024044200000000000000008004800442004A0400004A04F2 ++:800D0000004200000082888200F0859C80044A040000200400000000000000000042004A04800400004A040000000080280800004F530448420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905480000000048000039 ++:800D80000000000000000020242404002004000020240442000000000082827F8705A044800400002004000000000000000000008084040000208484042004000080080000AF710B4242200442008004000000000000000080A4444820040000000020042004000000200800F749800448420000000000000000000000000000802404008B ++:800E0000000048420000000020880800F0C61500802484040080240400000000000000000000A04400200400484280240400008028088200826FEE0C0042424842424242424A240400000000000000004242424A0400000020840442424200008028080000BE368024044220242424A444424200000000000000000000000000002004206E ++:800E80002424040000000000F0E91D208404A044420000000000000000000000484A84044200000000802484A44442000000008200B09A04800420040000484200000000000000000000A044424A24240400484AA4444AA44400000080A88800004F3B020080040000004200000000000000002024044A8484840400004248424842000050 ++:800F00000080280800F031618024040000004800000000000000000000000000004242420000000000000000009EB20042480000000000000000000000008004800400800400004842800400000080080088FD9A80248424840480040000000000000000000000802404484200004842000000008028880800F07E4A2084840400000048F6 ++:800F80004200000000000000000000424800A04442A044000000000000000000CF6B0748420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F99054800000000480000000000000000002024240400000000004220240437 ++:801000000000000000F0D43C002084040000420000000000000000004800480042A04400004248808424040000008800003EA380240400000048420000000000000000000000000000000000000000000000003F990548000042008024240400000000000000004242420000004200420000420000000000006FB204200442200400484287 ++:8010800000000000000000000000004A04200400004200200400008882200800FD9D80044A04000020240400000000000000002004A04400480000A044000000000088820000F073DE80240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000072 ++:8011000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F99054842000000800400000000000000000000000000202424040000000000000000E0290B42004248420048800400000000000000004848480020240448004800424248000000002008004F9B07484820842404002B ++:8011800080040000000000000000480000202404000080A444420000000082208808885D3E00424842484200200400000000000000000000004A8404420000A04448000000008882888200F02A2780044A044200000000000000000000000042004A04800400004A04000000008028080000AFC60C484200000080240400000000000000F4 ++:8012000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F99054800004200800400000000000000000042424200000000002024044200000000008282EF430820044800000042000000000000000000000048424842000042488004420000008820080025 ++:80128000AF2A0348420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905A044000000802404000000000000000048000000800400000000000000000000F0B58C8024040000004800000000000000000000000000007C ++:801300004242420000000000000000009EB2800400000080040000000000000000000000422004000020044200000000008200F06424808404004200802404000000000000000048000042202404000042004200000000A0880088DFA80C48004842000048000000000000000000000048420000008004424800000000888A0800F02BE136 ++:8013800000000000004A044200000000000000002004A04442484880240400208404420000000000009F130B211641C8494D4860824B42493414412218606428648C4602240047818094122911881198180000128C81C41A1054844841200A0044C026811E2246420829F4272F3021812D11C0134D484725812C6226221287424588423403 ++:80140000224721CB212AB12A31188D122446A612442412E13210D848628223322821A449744894686AD124A2522D24F0281443C826872243B2123434298483E184C116DFD20F252101841810342C222B12211008490460C584205282402804441012442801418082811158422D442200668202188824451892524422272481839444CF8AD3 ++:801480000828301AC045218C111204202311080040421208844445A2521602160A28002826186282212001411226861124584841000081420012217DCF00408144188C240480022241109224282741200118240020011840180800004246084826040028280022412424001280F1CC770085011180240242494404442032242502281A0263 ++:801500001290124002008112008400100810486884424400004C0228262423210340F2641E00800100000000000000800200400400000000000000000000000000000000D0E408422041042C21421298218C922848504A200A411068C120422802228484450885C64812000000816082284008008081042608122845F2A54E80621140416B ++:80158000591216521414872460116014121427418D6412484901324148444951A4702224112C64214C16046181301421811889E129642130C4564424C2264445228284052F7C0C42141214501222543126D18272388144D14A11B126189414901887411014182431242518480C85D22881030084602181842628E124491822841124A342BC ++:80160000400A1AA45245F222AD202201448521D12201818C04004800182E488044043822422244843026124568444846140461004400188C021230844604105442438202007FF20D24801101848D12112B1611189018842411464238484110344847824C42121801292101001222100222114100802898180082A88481844AA14A8122BFBC ++:80168000E343A1212250281A7222436482C127822AD482042118188C024130399024400841448149C24228EB12491102124187325961423483E34822A141230416389C128D449684AC482658844B4AB07F05302212105283C31112541A42A314180A2711265882008480C22441504A118592342C446281472180420285B2240114814B8241 ++:8017000060240016081A1864C98A24E88324C428F05275A01200913828211D2A6E18283880011220048744441B1244CC143828004100182843021280119421141D24641A021298C28901C9098B86106884F02884496C22EF4B0F45684484189018122D1112812243014F12012A086200400881E0410842208188C1248243248401224D42C7 ++:801780001604181243311280284648584826061822232422F48EBF40A1142220544181200282412082141C18044829329440021A5834288B4146986226148141018C0211A028812480C4441A1262424428828001100A843FAD05682302490200845024112290821812204124025058430481400244114224842200C48001444122804208D8 ++:80180000811880A484842488185684F8E62A30214B122280D49461811812411C880227114A919C814E24803222874885440E504123D482F51844196E42418B181F420422450849358484643846A242831262C41634284998C48C412268815684F8F95ED02404811E24002415284238221230842002124448204181044508224002582821C5 ++:8018800080A441481942A22141126041181288100883241222818284C2584FA602201268232601904814488148144414482A54828904406C44288002830800C1288441211038444426028032883088410082A028452216B8880686F8F68670214A68121038188521028221B02421181C04281114668842911142C0416014114820011324F0 ++:80190000148484021111502880484162448BC141801108980027229FFB03D084213244184014441804800421328140982C8C1201841151D041084B12110000144248428484810036042881002883041283011210F42FA4004002C0240080024C02000044001400C012814908488CC84A444141428828480044008A01818006281212418305 ++:801980000400250857632012D125417A21D4411461245D38133221100151450881451189080014418042082601442041044160422504C11E2840548144144181288C18344A0060364FF20A48000081004880544180C23870280400694104818122218122845028848C042227142481845012181094184C121844088C5C14004C48C44421C3 ++:801A00003F810A298192481400681C0249042A0C1180842C22128464822E41A042F028C140014400108184080042812B84608E70C284C4481E43C21224824129648821827FC105181840345C272281610027412184442954221654142D2423421481622281112616D1224182012434285C4282442202A0210080949140810220040010F8CB ++:801A80005C62400A6964818014044481403422289038000014508280C3188C08841E24268848814844C8248C5441F048214148885840042886341C10880112186919B4AD460319137845D444B261B54862C48971C5A8141B261A5244262475660C26952C6FC4041B428B221C64425F5424D811F428381E41C14C11E811F24226574E85281B ++:801B00002222568B8B2CAAE845B884B141D84838485F82B912EB816C41499918A08545F12A88DF8D081287817F8162A2BFA4D144527359B241C2243582F8214482FF24913C893324355A812A7121D51852A11F84D2B5B228529B32376197A4E443D2B23841171A68253444E5DC82127412D4A8F22848E092A6444483796C3C28C5F84A4841 ++:801B80006996C2812C058766E032372626B71A61138558842A54D62E424D2848A55121942E4C2CDCC9926C26D519DA8C62441887228941E862784838842E2488844CD444944440D24984D27D4481A5114B3885388A4D3B59E45424A8148A6A6146B89CF18438CCF88466AF810742144081448144818488C481C08148880000484448800482 ++:801C0000488024882488240800400146014A08230421822501219A14A24824102808AF424AF363221E32FFE3F33E6FAF83F22E22BF82F22227EFC1D17DBC92FD8282AF9AD834B89AFD9A86AF85F523233B667F34F493D11F96F6612956DB9BF4617FB73646F3A3FBDFBDFFDF95C6D262F844C73F37F7C1E27FFC586425D264D686F44C4F5E ++:801C80006BAE4F61FFA4F6BEF81F2175E3F3C5861F1CFE646E2F2FF6465C8F85F584C64F45A554DE5416B2164DF121226E6AAFE3F33A7E2F43F36662EF82F22266AF81F12DA73F59F92222A5C882EFC9F9B6B6AF85F723273F46F667633F7BFF62611F96F2225B3D436F767E6BD339FC135B9FB7F7DF9F7F78D4EAF84CCFFFFFFF61273F0C ++:801D0000F85CECED4E47E46FF2F64E4C4F26F246364F6BFFFCB6BF21F54323CFACF8C4CA6FE2F262626B5CCF85F58CCC5AF556544F45F572529FD746F363431F31F71D3C7D37BF86F26F27BF467643F77F3EFFFEF672F43724BD2B77383BD52F67B2D6FF6F477F127226F7D3912F92F4286D1D1BB794FCDCBE44F362334F31F79F758D8329 ++:801D80002F647488FA737A1F2CFAA7C7855A334D26E7E477646BEA4F41BB62EBE3FF33F11F1C7A47F49193EFC2FAB4A44F65FDDAD86FECFCCEC42BD48FCDDD64F96715343F36F439739F31F14F173FD6F2476FFF56F66367BFF7F7EB6F3F17FFE3E3B57B87F75FDDEFE7F7DEF8FF76F62F297FF2F2F3B52F96F2286F17B2B7B66FF6F22E60 ++:801E00004B87B8AFB5E13FFBBF7FED8F2F64748DFEF7FE1F66F2AB87C57E47F72C2EFFE6D2CEF4B4F2EF42FBFAB88FCFFBB9FBBF98784FF99D99CFEAFA96844F2DFD9E9A6FECBC9AF99494CFEDFDECFE5F2703002A0121844342080000406481441144114C0200891241048149110810240400502400200222841400844C8204400481F0F1 ++:801E80001B9F70A2131154814991212394216168259341341146028F2402248481518111109228350213026110022732444014C22C45419814848B8280F88448989A344845B8480829C1484C681AEF5F0E4D421F4152281F4132681F41B24AD141B24AD141B24AF91128AB9459B44A3924AF1439242F147924D812F924485CF9244A1CF84E ++:801F0000244A16F1244A9E252E4A96F5244A9E24ACF591244D421F497228F2912483F49124A7141F48B24AD141B24A9921AB9451AF443934AB944B422F44FB2448A9FB24484AFB244AAFA3014D421A56281E24836641AB141E24A3F411242F46E8C192B24F81B24A3824AF1439242DB14F8BF442116F82F442B54FA2E514F924CA56D1A4BB ++:801F8000E45DE2A2645D2E5B8B2C2E531FC9C25A1AE2226CC983E449366A1D44AB141D64AF44B911B64A8AF24A9143938A22297B84983869A4B44F82F154C6000000000000002800000000210080090000004008000000006041000000000021F08589002A0143118C02002800A5811498424B4241826100D084522444400229C24428505C ++:8020000022414140098902816CC2141682B412024308288126286888608218F0324A202178220848002A01C0182A0185846442A4281B4281C02815088022732A048B848C28CC248126218112524810041481C348018824468421C1144A031AC644479A845FA40A184A628244C9048002D08461222243C44A43322C4C7281124C9228141A3E ++:8020800042222873240A8B244934416C42782AC5144281412608845C321EC9984629E1429884292432188D14E2884E124B244369818FC209201122012820012820511884806424A0240010588444430221908283A882000028254108440020418102402401221884288489027FE80C228061812128230460888120245812112D2340421830 ++:80210000282884048450812820D4862405A0921A02CC028C14841496412B92B042084C084C88D448220145C824481DFB2446241206181436F214481D62142F18167282423C448B48C117848382884731A887128F2884C26AD024746854C2D02898A45C5341256642242614041AA8822E18A085248299F148322C648120B444015608AFEB01 ++:8021800044828632128901306221623378E211229488428714A1312229C85886E182C4298C042E4A142A34282D4C488B4186042823014512344C44C24C3258284A488238118B144E84AB1441424C0142F03EA240044124181382D14845411848C282454285782461848184228028847822088445C24450C28229B21592956C322483220297 ++:80220000209182199292182B84908C28219028124245F81824421FB8051504153824102191124911123154604280316466824446684420018372440A00262454218100762C1238186182253481412114892201008023C11821C048ABF800424420048451224123D824022A8825C2188008D0821164212420082B82D012684137466022265F ++:80228000420814460481141218160C29324481A12F8112082222A9741448D2F60C2449016041002C0280121858128125824804228028044E880060444C1298281084240860228008508222221800420041860800008FF90A4427418441561421D1168241A2288C52822D81842393D84E268AC4228482442410C2483046244D8987454512E4 ++:80230000C44224268452284E1441861854812232188443C14A703208862822121868A42F660194D0148402102871264244A14110A414D0420210044F8124048B84264814A228438262224A4288A2821A04195228822411296941A111214840084588239118484C81F192C6004501121642029B12C028491C42148442912814144581C8416F ++:80238000609486E21204294413B88812489248221B4122C9E2226884441314A13481378450483048AC9148842B143052895424441FB406002480C41489C442224810A1C211200286A248815084241068892847822A04256424810024885014200810C2246041314C3481828218200800847F9308842382924150921844122D81E028022051 ++:802400005814822902A8002018022410A22414136828881C09150221882C82081028518118152201F0182441224024C142EF5902006022812200816410028C2204100150822288E02241110224001044124411082400914185051120864204180045088282128F2F0E86C22210B248A121400842A024444486240884001584228441212490 ++:8024800022224C410829080030219480028C21E24308D041011948A8144183211184C4141CFD1D75401808115021108112082018210493D22438A8222A588127384E248A1108428382641A81418D244951E21DA4002E44C442282B84144094484423211186B242322448442954429E987022084828224800292122022400A18222134409F0 ++:802500008825588100848114444C1404C021004998849188601812A08158E08104430800881884001E6B0042211800584042A29682212318A428218122884D224A088602222124D0280882C0A289084022948112498A01D0484408124820082216182401F05671F022488168642842812846088444482825024221704412082D4880011C94 ++:802580000870212434461449048C44C24983624214814186250954D0186AC210044788C0823042F0F489242976A412C2228F21A3442B551E226E288F92D2687762D32412E8247429F1228287184E811D612678C9E1B83C632728BF261962C42D42B76243E2C444E46494211F44A128CF18F2A2832B64B6F449499D221F88E642E115785194 ++:8026000018F885167843A8D445F218743E124F44E844E83C15FC17521426324A26721145B82111F82D488B114D82218829581723C8248AF224283F88C28429423848CDCA1CC82926D12266848CD81B768613F6A828EF1249D251485E85A61C2858446D11DF88528485C3488F95744E548865781838624C8A518445F44214C73B009C82B2D1 ++:8026800062B162F41E23841425B242A48E8AE24C64484DA42B8887943D822A74ACFA8C872EE460198382C42A83F2A1214F14E6CC98888F28988696C641A72233D248D61DD825BA24E819E147E8219859185F55031F99E82169492E344D88C7881E428B41121AFC533D00228414E01201141A24028302850128110028118111101118912803 ++:8027000090280000180000400124400100244002240082428242DFF24AE22454828D2AFFF1F6CA483F14F462223F16924821EFA9E924748AFA8D894EC2BF88B882F8E7C5BDCBFF8CF4C1C11F8CFC8181D5F6C343BFA4F443411F36F6C3C3AF94FCC5457F6CFC4E4CCFD4FEC5E77F745457CF78F886A2EFCCF4DCDC8FDCF4C1E7BF9CFCC8D0 ++:80278000EC8F14F441411F84F5C5C63D912CF892884FA4B4C2BD44F5A422CFCCFD84944F49F8736DE024E424D6A8F21F7F2B1D1F35F66A2A3F16D288C46AAFA1D122D266F28783EF84FC23A1AF88FACDCF3F28BCE6FCE4E22BCCCEC8CFE6F74242AFACEC24F461433F38B822FE44647F7CFC4C4ECFC4F6E4ED4F64E42CFCACAE7FBAFECF40 ++:80280000CDCFCDFDC9CDCEF6FFD6FFE8FCDF5C85D188F7DCD62B914D16AD1CCFA6F4C6CCCFC4A4BBEFC8FD84D54F45F54472246F64D44684F21725FFD5F4474577747F73F24F4DEFC4F29296A5FA42625F58F8C1C3FFCEFE8FAD7F5EFCCBCBFFEEF4A3A17FCE7E8DDDED5113BF245C135F76F6E6E6BFB6FEC727EF3C5CCE4FE6F6A7AF7F78 ++:802880007CFDA7E5DFF8F8AEAAEFCCFC9D9DCEC33F79FBDBD19F5BEB55F551419FB4F7CFCF3FB8F842C2AFADFC7E6A2F8EFFACB84BFFEFC4F41C5CCFCCBD9A4EF246664D662CF27735FFD5F75D6FF7757F73F24F4DCFECFE92B2AD2A6F24F48F8FFFDCFCE7E5FF58FAEDC73F3CFC6F4F7F5AFAE76DDFDCF46D2F35F36BC315F36D4FCFEAED ++:80290000F82BAF7F7CFECECFC5EEA6F6A3A76F6CFDA1E3DFFAFAEFADEFDCFEB5B19FBCFC83A6FFD7FFA9AD9F5DF551519FB4F5DFDFFFB9F956D6AFEDFD7E7A6FCFFF2C2CBAFF8CC8CFD9FD4C5C6F2A0200002B12842A4108822440220882288420B848024A02420080121718221404630214501684411E48200984149A4441482481A24149 ++:802980004212462478390F2302230246111112F12A128088823884148225220A842504890AA827825083822608492858821AA282908E282B82822E8282418C220418451802AD125048224482004D35E032F41124A5F3112487361F41F24A111F41F26A131D24AF169921AF1419F54A9143F24AB343F242914782ADB14F82C4914FA2D418BB ++:802A0000F8244A87116FA2F498212E4A9E25ACE449D2A2F491242CF59124A5F2912487241F49724AF28124EF24D141F24A9219F24A9251AF243924AF2439242F647924F84A944F8AA4944FA2F4CC89F024411F41543C1E2CC36641C9E141B22EF111246E951D442DB14992921B42ADB55B424C7925F84AB13F82C4B55D5A8F54BB25FC582B ++:802A8000814D428F55E222E85D42E95DC24ACE2C2E591F49D428F4912487241F48F66A118E448F349161AF749921AB3459B248B124B448A1424E122E48AB3463BA48F12452E7E360888200000000400400000000100200880000221400004880080000400400000000400135051602204188014C22410484002C8402804843312480D48132 ++:802B0000021A52221004244928928224412112A0822B82148C912428E0840800184189124804281CF2656210E43A3181007D2289120240088C84084091229024801408C022153828436C8291C4228944158648082445190180781822124105458288A2188021C619F08B4B2071E342810163912A498241144868C62084428122C82215B283 ++:802B8000441238521568281D1289328484919592242C547841672C84006D88290216C824452862D644103482B088024D12421C23F3C88710248108811942020000204802240051000028228942223424102468828200200119C2811120E8220188110018438241082281F036B28001418011116A8125010020180221822148818481001513 ++:802C000002114A0290444222002829C12800214888488014224104A04120812209F0C16C244180119A2418499142458214324285621482EF115884250885C5441C8852182E4C216C86127C345228248469A1424C42616AF012A4815953225D2A26C811128884C2460C8D2245B84C123C48A2F0559B24440081431261E14A4125542210980B ++:802C800041886F1158E2247044816418409964344D42148D242A0125D42A644200E0614AA2288411423D244608188881466484608421568C42880ABF750512901421181821A424004830822181608840484CC828400A28284841258804184A32241D22902849012F4211728882C21148211288412053842285A458009BCCC018420026C486 ++:802D0000242004441224F0221243054082C42880085844E02884B22204888534828002108408828021981400806441444100A2482304827F75041962841C220921442128844322846842200422830829912228382C02430A43582800152459828A244608420051D0280268288281248486024094228902EF41012542046308108AD212044A ++:802D8000212A011440B1240812908C41448908812181809144488C1182042504122825E448220280321800200281164C44184884B68E41923161199216286912AA241C0229E322817816B1141481CA2283C82283C124444E88264238462863284134488C9812682C942485842934828E2447128091228C01484781442185426442453868A3 ++:802E0000CC22F6EA9300001004450223440C4800214844A014844C28882242042825A824A4C24562412C0888800422442081C82C800682205248828921280420F88A8530222110629218839122846022400480982400224840A2128902190288C2114A9282422A8CD2180436084F3408108C084885021800108848C48422F0EEA82001502C ++:802E8000240040022140164804221004842048049847886143E2810416082C031824286880880112122210084240044308C982A14224F0DB758021021280064C046614220410028242C84624382828100AAC25548485C4848711002D44128684544900C4E890448CB2688828048008818A244888C844AB79201404281014020088298201D6 ++:802F00004B8264400220011A0820028421220080410118AC239C28280000100245180412288A012048B228F845422400411118105842004410040024A0418046944821400200006022400189421504800245018011321200884C04006042F0815240040035C41400002244902C308270A462484038882339848A341914822CC888F4430224 ++:802F8000A0829C1A012D8119984D184C8808802281028A1524018C012604812FCF0A2240022800814004001002430A84C721805142844C1232244100420042D0821412C222162402128C43040088820082A2E0820888419FD10B86260A5841260284122420628242124A02428D244082628428212820042761104624114A512443014791B7 ++:8030000081128D6122839228298828084B84124A82A2241A224484F239BE60844448C0120050828140149228412594122348A2248321912288181D44AC48CA14002C4101448C098D411042420888424024C226181844808101812182CF4F0E4D442F480273D155F13422A12354A210A622E311A41843F222926F6CB446A862488B9BC7C1AE ++:803080002E8267229F8258A3A7248B884D3A5D52A76329C3128AA613AD238F81F1A9AB8F41E1F21EE88A15E88C24C248AC11B214A88C4F486948E088AE114F42B8842AF4AA19A0244348E622F4122846044392184508466282C465B2820E2AF8886E85FC3212842EC229F288C81E2145E5C8F6461CA7488D854943A241AF74F181815DC8AB ++:803100002E2767444F983A4529B151E849A2228CB2A21BE2449112432181BF2823E34AD888646225FCBDB3242F232102182682C11A850E66E62A1242D4286442644F4802184B14878C49A23C4F8881D264B4281764214A4868142E8423B425C8622E1471183189E1C1C2245F825944853248AAB88C0C4C0543E689F848148CA22CB0ACFADA ++:80318000728A0022400162200442200642A02482200848288A84A2482800881248124812885220812821044E82124A084602462229044212140082286FA345E245644245D446F442C62F47D5CE518A4F65F5464C21222F24D426B452F146244F45AD626F85FF4C4CEFC4F46CE84BCC8BA4CFECFC4B6B1F94F4444CC76DCD5C4FC5F5524A55 ++:8032000043F14455FE3267615F75D2FDF197577FF5F4574D5FF4F546462FC9F664E48F84FE52F88F89FDC8484F48F4C4C44EC44F4EFEA4C44FC6FEE4C4CFC8F88C8C4BABBF4548B272F5644C243F31F442426F43F34E5CAF24F4565665FC46462B66AF24D6A6F456146F6EFA96D64F6EFAD6F8CFC4F44646EF82A4CCCFE7F7868E2FA6BED3 ++:8032800042F44E4EEF6DF88CDEED1EBD3B4F63F35646AFAAFB87975F77F73D27FF7AFFEFBF7F577755FFC3C32FCEFE64E4CFC4EA8CFEF8FEAF8CA45D4F4DAC9C4F4EFEFCFC5FCFFEE4F46F4AFAAC8C6BBB8F41055E562F42564475F5E3452F43F11E1CEFC4F45C54A57822A4572F81774CB212F186644F4DAFEA6BF54F44F442486F82BE47 ++:80330000E49EB84F48FA49EF1FD1F3545C4F6CF194C4DD1DAD3B4B664F43F2A47C4F6CDF31761DF98735BFBCF97B6BEFC4F1C4C4CFCAF3E464CE262F2DEF29FBD6546F48F8C4D44F4DA87F4F4AEECEEF4FFEEAECCFCAF8A8B8FB1AE027F32E64457657B433F27674EFC151EEEF41F14A482F62B232F31A58C7A46F41F1A6E22F2BFFE4A6B7 ++:803380006F89FF6C6C2F85F5A688EAFDECBE6F6AFA262E2F57F75A5EEF6CF998CA3FF4F4122B4F67F626367FEEFEF7E71B63DF72F3EFA5AFBBFA7377E7C11F1EFEA8EC4F4EF6882C2F8EFE9EFAEFCDFD96D44F4DFD9494FAFFFCFCFEFCFEF4CFCE7EACFEA8B83FB6031810062C0140484208400200444002852441048D2421421008816349 ++:80340000022230261006148426011400860884204804201828D84822F8791F10C22424206241401C0626028141209822439A223E4800A88608225425684821548410D2418208C18A12C2244196981C2880121284311420C2943648844404EF87014F22F5112487221F41326C1FC1726AD241B26AF18124AF269921AB9453F84A9643FA4AAD ++:80348000B343FA4295478A2D914F8AC4B14FAAC4A14FA2F418216FA2E41DF222DADE25ACED4DD2A2FD91242CFD91248D921FC9B248F99124AB941F49B24AD941B24A9921AB9453B14A3924AB9443B34A792498924F8AA4944FA2E4BD052E5A1B6187221E2487121F81342A1F41B628F18144AF42B11194B81B69A9B994D418A34B4E314732 ++:803500008A2D916F88C4B14FA8E514DB84E811BA24E514E2A2ED54C2D9CE25ACFD412C2CE948C6D31D248B941F48B248F99124AB841F48F24A141F41B248BA15B2483824AB9443B34238242B94678A4AD1A4F5457800820000000040040000000010021800000040014008480000000044000000000025017F2B0711002301001D28218456 ++:8035800080024180120228AC8248080026048008608421B0864224021285A21281301A228C018241812018062240B41438246F8F0621272810C44418484448644890429042804482140442201422140221C902800200231118860448414845A248228CD58188A4288C14811444E48244015D7F1071C20216C44418489042446924F222447E ++:8036000044292482042A042D8283042314A23C2130828742D08194227028447452189844891482148415F48448222E58159448288C5C41482224C48E1143F158E910022400001D2C400800001002214782000010040000002482804222011A1208A128290188860882240041442A4424F2232E0044104141041082420242A0844800210087 ++:8036800000008C042508240040022A2511020041100C180000004014044308F087A124100224003C1408524082210124842D18A48344088C02244008812B2441260C18494404442502258272122221082184291884381219688181418041F61AA724100611214124003800181288400A3048002240021042C822C028209144225042101246 ++:8037000042C4128D14002180480429014D18102408242F550F000014304185024824244280241492182518420881008C44480829141404246045181002242221208801850220081908C1108411F45EB514202402920028110000002044220212C2840080046044002160844002002168A9031860248C220189912400209122A021FFE10D71 ++:803780002523440420024444248824284904221221826082292282890418E14018220140F28442460824844100001084020080515836443842411AF47D44001884698118022148212800608421211024010089144208100484401404003028000000A02188004D22888114200800FFD744512112263E141822604244218A029044302229C6 ++:803800005422430A1628044E8829041A140C83041044044944028D2284C0620018404228014CA28284844116A824A042EF6E0521004002246014100221304880012081229A28008410425424812C0120D42208484042041E2800A0618800165842124432884004330300A01400000080018012420200200442244224464802006400C02233 ++:80388000242AC44849824484044880A418488A9148C14C08308400DF5B0D420028200400422004402804460227A45240028304008181618002004200224084029602302A858608292888E44804227022F4F45D4002240023012100002B2142904210022100002440022400602110042448410000604200820028000000006F9C451161A13B ++:803900004842C04214241142144840021002200100244002242004240028244444004800250480060049844142E222049082F03861602440021400480000000000002100810000440000004400400845084024410225C2228845188828088812F0E6EB0020014022010084182301148400808401A1218484000081280041408412C424846F ++:803980000000290283882858242224442400472AF02B2A1022810484008181A50284112481106884000029040080849444274420460642002824442129012124981847814CA1219823AC145941042143F8C25B20282821022341092501144001140000002100004008008C821104004C12129422106461002942021022022420294225F892 ++:803A0000C1B414254981061C4888914A00400468401802211800A12418248845221404245400650A480084242C054822960468444034268041149422F0699D24242F28419212972829542225129842118B513B2148A42C14B84A449242460200A12518123A422F64944290222126141452422A420C4461444768219AD882F18A5A49F94215 ++:803A800092967CC282C142418AFA8421A8DFA64151138389A16614165A118135114861241C0125012410D2283112D0281422044088141464821E446440742434244924F2242C65C216412A24F2422289C28486F42424695A8449D4524134243C49F4F744A0441132004AB118E1840442A100469229A78421242085214468A4A44642F244DD ++:803B000042C51248CC224F221114D422C4422C5242CD62A394483AD42235122CA7128EC243F12242928F22F528842F6CB8D49A924426748672FE0A801101114A11211421142114210442844210880448801488041008A04280040022602620044A2821668142124A02204121A824009F5F4873437111612125F382499F35F55A48A7943D57 ++:803B8000433F34F44A4A2F11F111533D42BFB454AAAD48AF84744AF8485A2B1542E0247442E2A451226F64F44E4EEFC4F44C4A6D266F67F75252616F6464646D266F62F24A4ECFE2D244F41E5E6F45F544962BC4EAFEC8C8CFE5F956446F4EFEB4822F27F756146F65F556544F477F84D424F812A33437141FB154223D422794B5F14B41CD ++:803C00001724A78415F347473B557E362D43AFA4F4424A2354A8AD48AF81F1521223B448E4257542F2CA9225E224FC4C4EEFC454ECFFF4F416146F7151CE6F64F4424E65D226F44A4ECFE4D664F41E4E6F45F544966D848AFAC8FE6F6551664F68F8C4C62F2BF3D6D66F6CF446546F4F7584D466F174D9343F14A4511F11C1223D889F2183 ++:803C8000715BD98A542235724BFF52522B31172437B4AFA414528A23E425B51215A2442CD122D4AAF84242E5FE464E67E4EFE4D476F222226F21F1464825D662D466F22624CFE2F26C6665F65E1E6F65F184562F6AB3A2FADA32CBD96F68F936B6CF6BF97A746F64F4D7D66F41B136F3A4A44F68F97A8C343F34F41A1235E1245283AF15D1 ++:803D0000B51AC442B5E934D4627412F2173146D3AA54A8A5F8484A29B412B1121512E824D522F41A8A2F24748AFA464E6FE454EEEFF4F662627F61F1464C65D66AD466B266F2486EED2E65725EFE56144F28F582362F2CBEDEF996D46F69F9F6F6EF6FFDBEBE6F6CFCC2466F48F9B4944F6A7884E4CE060000218400248460812440420847 ++:803D80000000000021100200619014100621100424004022480200244006004482BF570924A0124022410200240010082150228400400A245024D08454482428415024602244612840044480120844439282414E844188A24445F2ACD5C0521F41D228F111248F24F11124AF24D141B24AD141B24A9921AB9451AB9443F24A9343F24A93F3 ++:803E000047822F14F924484E914FA2E414F8244A56F1244A87192E4A96E5A2E449E2A2F491242E421F497228F2912483F69164A3F68164AB161D64AB9619B64AD985B44AB924B44ABB24B442792498B24F8284FB244AEFAD01ACD541D628D141B248F111248B141D2C8B141D24AF44D941B24A1BB54A39242F147924F8489143E3147826AD ++:803E8000E814F9241A8F14F924828F1578247298E1A2645D2E4BDE252E4A1FCDE2A2F491648F22F49124221FC924F2914CAB121F41F428841F4194A85F8116AA432DA44F81B442723498326781A84FA2F59FAB40288804000000400428000000002180018800004041040048000000004400000000002521F4D79E00411002104221612483 ++:803F00000000240022400800000081502844001044020000D0240200308800000028820043B1460AA01800200820040000000000000000402201184044020010020000000041200230820040015FC902604C10028221144246120422000022404802301220080060411100C124408204004100416082412002808842021412AF6A0D2001C5 ++:803F800000008001000024000000000000A412A4004424000000002821008008000021800810B4250780020000001002004200000084408802000000000044C024880080018002008400002001F0EA340040220120041004000000008400410000001044082441420000410040A241184024088844120010041B7600282412000010140214 ++:804000000042000000814184280000400440428444044C8248040030422A014188801804001844F01EB6000000200400000000004008000000000081000000000080011800008100180000F051DD000000000020010000000080480400002800100200004308000000000000000000F0C68C00440090124200840024000026020042000097 ++:804080004008100460440000240048008200000000408404002FDE0741128114001012022100002400410000000000000080040000000042000000000000003F6A0140041410225422403812400240022C420480180400402802400242480040068004200C000000008004002D71102411082001000000000000004800000000440041004F ++:80410000008200000000000000100400B09F020000800181000014000000000000000000A0220000000088100818000000000020018FEB0A000012000000000000400220010000000000000000000000000000000000003F580C000000000000000000000000000000000000000000000000000000810000EF4C010000120000000000003C ++:80418000002100000000000000000000000000000000008100004F88060000000000000000000020010000000000000000000000000000000000001F1806000000000000000041000000000000000010020000000000000000000000F077FA004001000040040000000024001004000000000020010000000000000020010000FF410900E6 ++:804200001008400800000000000000000000000000000000000000000000000000B018060000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000820000000081000000000000000000AFF108000000000000000000000000002400120000000000000000000000000000F2 ++:80428000F03B9E000000000000000000000000000000000000000000000000000000280000F0E43E001001008400000000100400001004000000820021000000000000000000180000F0465C000084000040040000000010020000100218000000180040080000000000800200003D66000000000000000000000000000000000000000028 ++:8043000000000000000000000000FFE40F00140000005400004840040021004400100218808802218001884008000028840000800200002F6B030014000048405588281082044480022100448002214818808802214818448828842148408481421882041E148002211A01445C0300000000004840010000000000000000000080020000ED ++:8043800088000000804208000000F0FBB6004001000040050080044448002100440010021880880221800188400840088042080000280000F0F83E000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE001002000000480040 ++:80440000800221000028000000280048000000484004281082044400108204440010F2F46C000000000000000000000000000000000000000000000000000000000000FFE40F000000000000140000000000000000008002000000800800000028840000000027E8000000000000000000000000000000000000000000000000000000006C ++:774480000000FFE40F000000000000000000000000000000002800000000000000000000000000FFD70400000000000014000000000000000000000000000088000000804208000000F0B2BDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1151.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1151.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1151.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1151.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,695 @@ ++# ++# $Id: FPGA_1151.hex 7107 2009-05-18 12:35:20Z dima $ ++# ++:020000040000FA ++:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF4000C8C10A006AD6FF4000C8C10A006AD6FF4000C8C10A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B511115511115511115511115 ++:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200001AA1111AA111001AA11100001AA1111AA11100001AA1111AA1111AA113 ++:80010000110000002552222552222F21F112122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F112121AA111002F21F112122F21F11212EF ++:800180001AA11100255222255222000000000025522200000000255222255222000000000025522200001F1BFBB1B1755777000000000000000000000000001AA1111AA11100000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000066 ++:8002000000004F44F444444F44F444440000004AA4444554444F41F114141AA1114F44F4444400004F44F444444F44F444440000004F44F444446F64F446466F64F44646000000004F48F884846F69F996962F21F112120000004AA4442F25F552522F21F112124F48F884846F61F116164554444AA4446F65F556566F61F116164F41F107 ++:8002800014144554446F65F556566F65F556566F65F55656000000008AA8882F29F992922F21F1121200008AA8884F44F444446F65F556562F21F112128AA8882F21F11212004F4CFCC4C46F6DFDD6D62F21F112122F21F11212006F6DFDD6D6EFE7F77E7ECFC3F33C3C006F6DFDD6D66F6DFDD6D6000000008F8CFCC8C8AFACFCCACA25CA ++:80030000522200004AA444455444455444008F8CFCC8C8255222004F44F444444F44F444440000004F44F444444F44F444444F44F4444400000000CFCCFCCCCCCFCCFCCCCC0000004AA4448F88F88888AFA8F88A8A255222CFCCFCCCCCC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00C5 ++:80038000000000CFC8F88C8CCFC8F88C8C0000008AA8888F84F44848AFA4F44A4A255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88C8C0000008AA8888F84F44848AFA4F44A4A255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE522 ++:800400005EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFCBFBBCBC3AA33300008AA8888F84F44848AFA5F55A5A2F21F11212CFC8F88C8CCFC3F33C3CC55CCCCAACCCEFEDFDDEDEEFE1F11E1ECFC1F11C1CC55CCC9F99F9999995599900EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA8889AA9993C ++:800480001AA11100008AA888CFC4F44C4CEFE6F66E6E2F22F222228AA8883AA33300CFCCFCCCCCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE000000004AA4441F14F4414115511100004AA444CFC8F88C8CFFFBFBBFBF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F3333315511100FFFFFFFFFFFFFF54 ++:80050000FFFFFFFFFFFFFFFF000000008F84F448489F95F559591F11F1111100004AA444CFC8F88C8CFFFAFAAFAF3F32F223238F84F448489F91F119198558884F4CFCC4C4FFFEFEEFEFBFB2F22B2B955999855888FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F35533300004AA4448F88F88888BFBBFBBBBBE9 ++:800580003F33F33333CFC4F44C4CF55FFFC55CCCCAACCCFFFFFFFFFFFFF3F33F3FD55DDDC55CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220000008F8CFCC8C8BFBFFFFBFB3F33F333334554444F42F224244554448F8CFCC8C8FFFFFFFFFF7F73F337374F42F224244F47F77474DFDCFCCDCD00455444E1 ++:80060000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AA22200004AA444CFC8F88C8CFFFBFBBFBF3F33F333334AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333332AA22200FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA22200004AA4448F88F88888BFBBFBBBBB3F33F33333CFC4DE ++:80068000F44C4CCFC2F22C2CC55CCCCAACCCFFFFFFFFFFFFF3F33F3FCFC2F22C2CC55CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F8868625522200008AA8888F84F44848BFB7F77B7B3F33F333334F48F88484255222008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB00000055 ++:80070000004F48F884846F68F8868625522200008AA888CFC4F44C4CFFF7F77F7F3F33F333334F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F8868625522200008AA888CFC4F44C4CFFF7F77F7F3F33F333334F48F884846556664554448F8CFCC8C8F3 ++:80078000FFFFFFFFFF7F73F337374F44F444444F47F7747400655666455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F44F444447F75F557573F31F11313000000CFC8F88C8CCFCBFBBCBC3AA3334F44F444443F31F1131300CFC8F88C8CCFCBFBBCBC3AA3330000CFCBFBBCBCCFCBFBBCBCCFCBFBBCBC000000004F44F444445F58 ++:8008000054F445451551110000008F8CFCC8C88F8FFFF8F83AA3334F44F444441F15F551514AA4448F88F888888F8EFEE8E86AA6664AA4444AA4448F8EFEE8E88F8EFEE8E88F8EFEE8E8000000004F44F444444F47F774743AA333000000CFCCFCCCCCDFDEFEEDED1F12F221214F44F444441F17F771714AA444CFC8F88C8CCFCEFEECEC93 ++:800880006AA6664AA4444AA444CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444444F47F774743AA3330000008F8CFCC8C89F9FFFF9F91F13F331314F44F444441F17F771714AA4448F88F888888F8FFFF8F87AA7774AA4444AA4448F8FFFF8F88F8FFFF8F88F8FFFF8F80000000000000000000000000000000000008F8FFFF820 ++:80090000F88F8DFDD8D8000080010000000000000000000000000000000000000000000000000000D0510F480000000000000000000000000000400100000000000000000000000000708F0D0000000000000000000000000000000000000000000000000000000000F04FFE80040018000000000000000000000000400100000000000056 ++:800980000000000000000070C1060000000000000000000000000000000000000000000000000000000000F04FFE800200400100800414800280041480020000800280040000214840010080041400108204000021BF26050000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000066 ++:800A0000000000000000000000000000000000000000FFE40F481800280000000021000000210014001002400100000080020000882800008088020000EFE40F0080840100002001000000000000402101000014000000140000001400000000007028034818148002800414182810820416012810A21140012810A2414001002B1148400F ++:800A800001280048408188022148008828108204F05C65808401800200000010020000100240010021001400000000280000808802000088280000F04EFE000000000000000000000000000000000000000000000000000000000000FFE40F00002800000000000000100200008001000000000000000000000000280000F06A4D0000001F ++:800B0000000000400200000000000010028001000000200200008822000020080000D0950D000000000000000000000000008001800100000000000000000000000000F0A149000000000000000000000000000000000000000000000088000000000000F0B3810000000000000000000000000000000000000000000000000000000000B2 ++:800B800000FFE40F0000220000000000000000000000000000000000000000000000000000009F7509000000000000240000000000000000000000000000000000000000000000CFEA09000000000000000000000000000000000000000000000000000088000000BE3F0000000000000000000010020000240000000000002200000028D9 ++:800C0000000000220000F086FF0000000010020000000000000000000000280022000000000000000000820000EF420D00000000400200000024000080020000000028000000000000000000000000F088FA00000000001002000000000000000000008002000000000000000000800800F049550000000010020000004002000028000019 ++:800C800000002200280000000000000000000000F059DF0000000000120000801101120000000014180000008001000080088800000000002002BF2708000000000000000000000000000000280000000000002200000000000000F0A2D900002014020000001800000048180000000000000000001200280000420000000000EFE90A122C ++:800D0000200228201202C0210000200228800200002021062001384821208281110200482004004A080020242804AF6B0F00006880120220020000000048120000002800122021040018901200002004004200008008F04C5C80012240020000140012002880022800000018420000221002228001002248008004820000422004CFF407CD ++:800D8000002260120000000000001200280000A0240000200400000000000040022400000020042FC60C190214002001002800002012221222042A04001082022C820100000000244820442204000000290400F0CA6F0000C02180010000000010820242A02400000000210000000000004800000000800400F0384B6012C0210000002022 ++:800E0000020000281824200200002A1422022218480000000024480024421002210024002004CF1E05002A01800116C12180211202122A01480022002007A01400204402002004420014214800424A080080080020F828FC000013018044026028002E810024122800248001000018180000122004000048800220022004200421004FFE2F ++:800E8000030000002002001C04000080C82200200280840200220038108201802202000000000022000048FF98020018130112801102882603132881428284022302004800582081A1421082C312800100221442480042C80042208A0400C26F7F0900220020942126012C8104001220812802002228202402000000000042280021200272 ++:800F00000000000000006E1F000026012240022100000000602280A24260221821003012004002806222004200244200000000800410F2C5F20000804241011822000024002382024A82042200100268002448000000002004000000000000001F9F43211201001011011129110111212602100200122480824102001042224102240000C0 ++:800F800010020000211002212582044248AF76092002100128221392128002211820012A11A2421822C032003AC4426022120024122428160210120223041002100221002004F071CA400111824001212110011190131012020080044042C242004002002400280080840400240000000000F0D6EA00110000903110811101194302800178 ++:801000000080010032004A2201422112004840020021102204001002210000245F3A020040010000200200802103002128800200001002000042200400000021002100000000F0354320021100C022B01182922190211081028001002448004800000000000040022904804402002110020040016F4409118086120120011022022902126F ++:801080002224240048212418222A28C242801262142C0440C24200214200213042242800005022201442F131A314001450112681022F330227122234C01123D32252222612024AA46126022D22226A042F24C41224242C0421D022825222E024044612C2422B44002440022421A0441C44F28A3A501110F12121107121E32312D122B111B7 ++:801100000213522237212C230223012B622A012952222229612125A2222A22B142245422167242022502219042482421405222100221400240012F270C2A7221210222003D11181F1282D111021D11001A8183C32242286A81A422185E2229A24430122110A21100226A012421461222244412022124212421B042043042EF640B20022261 ++:801180002002222002220080022880024A02288002280000200400000048000000000000004220F4578910511115011B221F12A2221F33F331333F13F321211F1252311F31F111313E222AB232B332A3222AA6332AA6672F221292427AB722B622A2221AB14204242B11272429C2622125522227242B442B44422512022C52222552222121 ++:8012000021004AE424F41DB314F0414115C1411F12B221E222F233331F33F323211F12F221211F3252311F31F122222E222B223E322F22F222222B666AB662E722B282D922B462BE22F622622F22521327242F14441292422B222D2221244E422552222F24A4442CE42252222D22255222255222254212A2442B447FA204111C04281372F9 ++:8012800021A1223E333E322B331B331B222C42E211E12282B222B232C32229B632A3736AE72292822B555AF522622F22E221E31111022F21B112914229C22221251232424AB4422454222942522200101202214AE424F46A4B1413A242E014722131211D232F23E223F332123AA1222C52221E122F22E22292221AB322B262B652E727A761 ++:80130000642E222B832F25B5D2B522F622622B331E1127243B441E122B11212B222C1242A2444A44F242424AC4422821230200242502294442F22DC40000000000000000008002004200200400000000000000000000000000002004FF680B260180220226012A01220000800324A0242220022200284828214200008002004842004824A8 ++:80138000000000200400EBF2A0421B21221B2166B111726292212B1619B26299212B94112F2429F242B3222F142BF242B12AC4B12E421CEA22E411F22242DE212E429E212CA42D2D421B292CB49162221B294E121B2923B481764292612F2498612B84112B84222B84222F2428B242A8424AE822F4C38DA0421AE412246116137162026E2F ++:8014000013126E91F042B31AE234094EB3124EB1F042B123D1128BC5B129EC119A52DE212D429E211CE51D92421B2929B591B62234812F24B19142B2814692614E8219A6A419F24282224E82224E82224A38222B8426F21A5D00824800000000000000000010020088200400140000800100000000000000005012E05F04A220C221002108 ++:8014800024222C880200000028802282C2220020042428120028002642220820044880240400800888428840D2C40C1813880113621428121260111E81118603122AA82180021A044822283838588A81054AE1248205200112212A01130829022442A0482240622422421C24F8E5C21428138C6212603460211A02233381221918028238F8 ++:80150000802282223252288AA2125A8225B1429111182C8601421A12921221284886418222A44242A084228860242A24C84129F8428380011860122002204821410120810228001A0426020000882820044A020080081800480024000040220848006F730D0080020000120024004022C11200A02400210000A012005A02282901181200E3 ++:80158000240000820020023042A024F02AEDA0429031901126D1232142322142328025082A81848294421A02200242122063242442520040C2124082210448220021800480820400F038F380041B21281C41321128D0128104A0148200292192424820042880042063243602581A0226C212160200400200308220042022944280043FBB78 ++:801600000122000019420280021A0221003248182420830224001800004820040080C112124280240200008002008002CBD98024A22488282424221C2401212361221A84012324410200200320F1224228000023012252800200426220862A082240A228002420F6A6A110014280010030422800A60100A0822240826128123012422025FC ++:801680000BA0242015222482042C440282230828486028C8688012622840F28FCD009011A8208244822222840400904218001288208484022811808484022A0424800121284A220A00001002000020081F4D021C041923826322482446A34228238441031823842108128818C6022C22E122653238A248286823C54222200320046A682271 ++:801700008848A084B02238822AA428222180682467470028000024282212421022A814408284231202004A02004248520080820129016602268216A248808208004210022008228F66081081916190224A521280042001426021408201280023240100A012E021042A04230242002442424828212004424280A8244200F0414A3011482238 ++:8017800020021450122511E2141102180000222A012304A04242482212244828240000288006003042284A4842020024208208F0F27C0000200121800448001431124A42A24210022C012001284224422C022A0448120080A14126022A2808212024048221002008BB361400800420120229823222424A02422122121880042A24422242A0 ++:8018000002482001C0420016024200212C020000404202460200008F1202100111101322342342214A122281022B144E1252231422042840022C0224242CC442242820C2222820122206282A98A288422880448228362288001FA90A11000000001200242821211002224228482418C04240020020011602482C84240400422004284002B1 ++:8018800042000021F0CB7A0000400140014001621C0200008002004821000022000028100222204202244800100200002042022FF40DA0280082A014124A2262244023355123015220248481012004802424042268242A240124221262809482A08442200486822804001C4C7298030048281128800214400128224800001890221A841386 ++:80190000C2821A4422022214008094420000800200222902004800101242F16FB980F181412228883942D12282D632C44235A342212B11A04129F112522B261A2761242CA2421A22822664225846A24223D322762262242B2148221827224642A2A4CE422D2226622426024A88D82224346282C6019F564E11210817162226E222052693C4 ++:8019800031192263211E516E612361261E226021208623054A612423C662B022A2432B244262283A022C32423A82B222062F22042A848814A244242D42B022044001CF670E142818481731B042725131436223A4642714172415E22495124A24863562681AA4422F24D22294422C11B242652429C2122C065A9412242386A6445A042B663E ++:801A0000822BA2CAA84CA044242924AC8C282CA2822C48F2D33FA02120011214800118A01248A0412003122880024A0200522001122001200280642220028004000048002448A042707C051B2B17152AB3310716B261F531225AF461235A75512327B442E722A245422B676E323AA3622AE323B622A2722B733A92322E722B312CB412A522 ++:801A80005529E625B762A2112B622C32425A3742A0A42BE829B8E26C242B6446A2884E82CA2C6424C8AAFE62628A4FA1231F11A4321B331F217112F261723F27F651623F35E725F553431E6217113F24F122326AB762F742522F27E727B362A6322F26B762A6EA2F23B372FE42722B722B373F15B542F462612F25F742622B531A51222FD3 ++:801B000024B632A1756E422F26B6C2EA2CFAE2A22BEC4E422B444E42CABC82B8C2BC4224B482ACEA6E628F1401181F12F611211F13E31163216E511F22E314E427A7441F24B54133423F15E522E227E624B472E626A7332B426AA6722E222ABE32A67629E22396221E532B444AB442E625A7711AB122A2645AA3752B64A0AC2BEC2B8C2BA1 ++:801B8000EC2B442B442F24B4C2FCC2822F2CBC6286B4A2AA8C4AF2D82E141F18F121211F11B221D2217212E236F763721F34F643631F35F563721F247553F153122F25A5552B772F25F552727AB362E422E224F66262C827212B7E2F24B632B672F342412B643B772F25F742621E122B332F22B242A6335E722F26F662622F2CBAC2BAE2E9 ++:801C0000BAC2BC42B442F442422BCC2B882F2CAC462AA4AACAE824F29F596012400114004001800440012800800200000028000000002A010024402248028004408204484A0242F0ADE700121428182818684A81A212484A012B1480819432484A238182A4242322051AA242522A2481A425242818001A268422A428228A040048008800A1 ++:801C8000822822AF2E0E481B21B01162241B21272419F6621219F262921B212B941B412F24A9432F1429F342B3322F14AB424EB12E424EA12E4256F12242DE212F22641D2D529AF222521B292F22B49142B29132621B6923B681326219B66298612B84112B84222B842AB4422892822A84E822F4779880B411061B6146B211623419E224D9 ++:801D000081E236094EA1112DA2224E81F042A3C0B1212DB12CC5A12AED1118E219B22264192D418E212B421B292F22B491041B6927221B2923B6813262112B82112F249A214E822220F242822229B82294822E42CFFD04200800400100000000000000210080080000140000200100000000000000005012144FE9028A021021818214212B ++:801D800002A082481427142221BA84A4432081A28228222880012F248301008001A0141260244A2808005021304242822248002CF8DFCD301186012A0115A221231272A28151232008821A42A2218852481242238424A44321142094427682A6282982BB1232229072302166A242A2C22CA8842828242821A8881C06CFC44D11611C40013D ++:801E00002CA2612912F282212CB181A2421423C42212CE222AA525124A2131D221AA043221342A3511296425688A3242222303181A8234820028222C285822482C8438224E828814826F7D012A01A02118111021020021821482281220280428224A024A82240190422002A02198B06201230466A1682326A88460142228800228A0247024 ++:801E80002B07220080012712122211200800003224824A010000C012120022802C84080024681811888A028200002448004A0200BFA70514141982E12402182118922DA1182118141AA48229A82C80A28162C042426868A02166A2184A280362A02136A28316A2822C862224224401C062002004224222AE4B0011190228213912A2218627 ++:801F00006218180011122AB882E22C026A210180044822182862001A222408121A2222A4121C86AA2C200C00480080842202B0FB0A130220210512126011282C08182004122008886800298462258001292B2C0C4A0222248E121E228810022210018012324200428084F2396E301100229011681814182826012E8318212112882582243F ++:801F80000829A821208892421A82A84119212A227622A2858084A448A0482C4421848228842422042C042800DF3B0200460100121C3222232428A41422142028341162122C8281A441308240034230218024014A622210622224800280820490828004882B842A84F22A261400005224000019010048A89022221888800423288421240AEB ++:802000002C21820C1800802922026200A220080000222800006F88021400A0412C212522128208121D822C6122882AC51162928218822BC24823C1621B8229222D278BA8433E4220AB832221242229E422E4120882C84242A2802214828E6422AD84800114281021321125A1412E11192604462148022C2A314222424800004218102224E6 ++:80208000028012022384A68648880048000021484222888002BF8E0420810132190114381E8220012400C012208102402284012829028222DA0221688200208522048601008242822248218A220442689F9708191101004200108108182B8422138238428813820C2D821341028048A24148820024001A4202146018142082180221002261 ++:8021000048002829023FF148010026012821501220E11895821488100228182B614200C2240020725262254280448201A842272C4A582270422224240470C2022328E228044800DECF400100101211022811002118182221122908800118488848262211414182C42214A049002214224222222880028084040000E0D106002890112C2439 ++:80218000E23481B21244021382D423810448C042202889084810022821482321044A221882948220018A8208826028002880142224883482DFDE0B001C21250200C08100800B20A1818222200421301288A200A22A089602808206002024C4212C4441A2242822400280228602AF2E018081040018000000802208142901408144821181E7 ++:802200000C11111111222002808408824219180114284681028004800200F0534680041428138422866314422F1C11B24128314123A52C286242881848428860242C84250418821C01C0128829829412108292422C082C1A811AC28280384288C0812C280910811601390123849122B04198121982A8822188908218882188182C880810FF ++:80228000612140228A4482C4414886611227183082106224A0244210820810821882F459B9144819913142622F11A624214A332113A88142922B9F1322A449EA9822381AA444482C44A1448EC24AD221F762111F1A68231E5380A218B8488216A1418AA4242288212A9CC32A089062622842C84E8124DDF6D0112161111D211D334E121773 ++:80230000225642F342F22F15D831D133F141D115E124FB22122E8127211D52A24A0818D02211A22614271713A8752BB423A6242F2494A2B6E222F242431F2871C2F2218327282CFA4262AA7242022F2444D2222A44722232226AC261421FEF0F40212223312123D111373396C1122B4CBA58222CB292A4A82F2481A38F2BC586E129F9830B ++:80238000822B8CDA44127232021EC225A2488AF8224213622525A18C882BE61F1238421F12FCC34113F241C211C682B2E2A8468E8229ACCCC88226A2E8DF5B0B420022482A810448221A049A0448148A4481C421821482148214C0210018428842221110B122082A082A0820282248210882288A04824A22A824BFAB0A1AA1111B311AF701 ++:8024000011831E722F21E336D331D231FC839227141F1A91C31F39BA33B591B122FEA1931F21F79152581F1131511F2CA41C1F34F443A15E126E633F19BCA1F612922F13F22123682F3DF312313F28F462633F1AF273733B2E1F36F6A2226AB6A2A24623EC2436822829E824B4A2A2224A88E42AE2470A1F11E115F531313AF531931E324B ++:802480003E321F32F31113AEA39E92211F39FB82821F38F823921F23F9A3A31F3BFB31121F2BF8C3511F19BD43F5C3823F14FC41433F127472F273631F3BBBE1BAF2BD33F6232335E139F682B113EA36FAF2311F37FFE3611F36BA62E226F262221F34F64242242B222E222F22E22232422E622984F42262CF714E8185B411E1117151E33A ++:8025000027E721F773731F35F3F1E31F2CFD52D21F1CB3D2FDC1832F17A71D3F1FEE2EE935BF92D513AD914E91CE421F14E824B442F251531F16F691C1BEF12BB32B4E2E221D619E723F21F381A26E633F19F971533F3EFC61633F18FA61E12BAA4AFEC3C14EC22B882BA82BAAEEE22BAA2BAA2B8E8AE42CFA4C26144AC5511F13A3171FA3 ++:8025800037E526F671731F37F75153FEE3DED229FCD1D32F2DFDD1D32F1EEF2FFFF2E21F3FEF37AFAB2B5C1F39ED14FCC2822B443F34B422F673633F37F6B3F32F1EBEF2BEA2F423232B449E223F28FBA3A22F36FAD3911F37FDE3C11F34FAC3A1CEA22F2EFAC1C33F3CEC2CBC62EE2EFAA222EEE22BA6EABEC2EC28EC2CFE2929008001EF ++:80260000002E110082200812000020088242820000421180082A2104002082C411481440814481040048000000EFF2031C0122200218C0111A028001883288823832A04180044880A42511282925A9420082188A22A428A028622084022004A042428082A424F0313580B51162121B21621B212B1419B262B111F242911B292F2419B1424D ++:8026800039A12F3439212F1439B12F14BBB1C4911F2AE414F8234256F121429E212F22E41DC252DAE222BC91D232B491E232B991E216B891B662B881B24298612F2698612F2418B14228F24282222BA42AB442A8424AEA22F4E52680A1612681C613112CB1114222C183283C0B3C2BC212222C09982382B92285B8222D91C29227229E213F ++:802700002E41922712922B42482D121A66261361261126126122114E22114E22E024024E228012B242C242BF2A0A208804000000000000000000210000000040810100000000000000000080045012F02B53002691112083012081022DA24212483A04821A52222AA48618002242808191421A0424124622E81801728004620011428A84D3 ++:80278000088882688A840428F052D4145292281C022926B1827222611123433181111939831AAC2423288248A128A86A38412331212B82E22E82222B871A8C321112283622E82461122B4A8224484A08002036420021228621F652C614A02D14142C832131A2123C0386A386141B1C3892A6A21A2482C68139322A243A12222B214AF3224F ++:80280000821996228E121217245AE81162218A2681B642AA2C20A4842A84880822232402001C18F2FE148015A1122880067022012E12281412241B48424824224A228222889841421182884218D24828188088828154120010120148004A2828A448232482A2429FE30D1480912126038044B281542282468204004821112811421B428090 ++:8028800004A028002C2104123C280120826414B0428822A46800250288482100A0248AF478CE14281A820A122E511E621833262163261813B9827543A21A29A92127255A28A3288682169362314223E42284A2A1888229C2A1282CC283228E1262244A4802468368182C6C24A82C842CA42820F2D3511081238262312AA5432B144E2133A6 ++:802900002C31422B142B182562143823343213A48428601A6833C442E028824422A11282921C7AB2017022A3248E512982ACA4B082642440A184826A9842214882482AFCAD261422A01811221440021229A28260141A4C82A81824122B121C218E1402291221042AC4228A04240022288200422502422211822D82244602800C2228F0C4DF ++:802980004D8002424002D0218406282270627112C112C8D022448288621429B4122222A8412602C214424A128181222522642582101102424A2208804402428824E2C8CD3E0020C42142181A027042814901224222284AA12822132104252101E2102104481942220120361121290830422224228A22241482088888C02280F259A11448B7 ++:802A00001800302121380080A481828008211248802821880420021A3211288288284821888022022128C2002121C042A02C002100B0E40920011446C231294222D612A492119286C151282996422F2C81B413A82413552100687813A22596018AC2E22A2191228232212B1E21E012B462082CA2482B84244223EC2802C68288A22C2CFA65 ++:802A8000ADF2A042002800181B61008046821422892881220282A0484A22020021422A24041148A0121162C08210022448004200488800004817BC1021018014822264244233055820A428888AA116200140C221302288721A3212188AB2110822822480724142420242E0120400A0848200222904821EC8A04120010011318003290129C9 ++:802B00001181513242201282280224004002804402244021211812022024B8410220088200B02298C200F02342001304C012422C44C21211241D62A0142B818A2401259142222880422212219423428A849852293A8229A8121C1221848202224221208C2468242028080040F223CE0028481C021121288004001128184822888088D4122C ++:802B800088041A042A08001200008004221001108148022400002188002988782E041E2180222244B14102311C01122714881023019AA41890418A1201302362182438202904241601421CA842208444111151216022882448004800F0936400111111110042682419112191223B818098532822290429E424A252E02458212022081021F2 ++:802C0000882296521012434202291832C221882110021002C800FFC30A421218000012000040210420421181A8820000002C24042C0216028088AC28002100288800280088222220022870940C20182114010080A2426819824832211B2440A2185A021D42121C34810014408228042888248E2111C8B04182022142233A2129042084946C ++:802C8000228028C2A127229F3A05282868182014B211220300800248211421134443114281A1422C1C01A04248260100C042481100482200800CC2230420C8222018028D7DE01324991113A3441562122C712152121117217AF512831AAD1515E137A5AA1C041CA24446B14286B241B462D432C252AAE128EC25C7822C48C2811B882CB8A7 ++:802D0000616612244AB422B4432AE41E54128A3CA248235C22282AB862A8482E21F0661114428AE61242418194422B662B5556F212412B7425318137181F22B4D2B881F213527AB23236C1A23F227421B22144F381231B134A32121A1292212388F2A1321E2339D23258223F14D2224242D121CC221F2C44C2822C88ACCE2512A228628E95 ++:802D800081F0152190311F12218176117242F141221711281B726E122651214A61262F18CA722146F18392CE932ADC11AA2114272D2B22884A34224ABE42A18A2F1985B2A228B522E11C24B84126024AE22874A291832A384242230CA08A8E224829082F2AF874162024022A0124000000402141A2412400110042A0240000001820028884 ++:802E000030224003222082040000482840024A2288F22D1D90511F1743C1411ED1423B244E221D512CF413322B223F2694831B211F37EA1EB822E3119982DE934AEE18F81221141F3851114E823B211A0313B822EE37E6287882725332211F28AC4C37143B4627242B463F2414728231A329A42C2123A44C8ABAA2FAA28248282F28F83737 ++:802E800051A0621F13E511F32121171437143F34F253133D313B763F24F773733F31F243D2DAFCF1B32B9F2E723F13FBC2D32F1CBBE3BEE1A85433F461C33F32F662611F13A2319AEB19F1F2F22F38A4888E821F31F411122F18E81CFC21421F14B44234423F24F4C2833F3CFC43432F24BC42AEC82F2C98428AA8AA2BA22BC48A88F8EA60 ++:802F0000FB14121F1124F331114E424A7443F242421F11F321233B331B663F24B643BC51F533A3EEA13B364ED12BC43F1DBD42EE18CC533CF423E33446F312112B11248E532DC22F25F4A2A22F28FA1242281F2AAA4C37142F14F662222F24F6E3E23F2CDC13F241612BC42B8C212B8CEA22B2A2BAE2BEA22EE22AF2C6C9141F137731F182 ++:802F800011211F13F3D1533F1454333D433F15B763F723723F22F643423F34ED1DFDA3B32F2EFB43423DF13F18FDC3911F1EFEE1814E4337343F36F422632F36F632132B51DEC2BE622F2FFFB3722F2AFA828296E223F3A3A33F1E7C62F363612B662B261F26FE43832F3CBEC3B842FC62C229FC42822B22AEA2AEA22BA26AAEAA2EA27FFC ++:80300000CE07002A0180448104488004123081281280041100281142808221840100885012400180048A242208482008820000001F31044819021124482612C1121B21B0117242B281542219C4B21B4928B0422B0A1984D222E4144262142E42E02288820D23021C2938621121108274420125838488744202252288828468284FAD092AE9 ++:80308000B41122B21162241B21271419F242131B212B9419F2429213F9429313FB4293AAF44291B22D91AAE414EB22E414E822E415E22264192E4296C1C29AC2D21B292CB491C2921B292F24B8917242B381324219B64298612B84112B84222F24A8422F2428BA42AA4A88AE426F55052AB111A44219E224B111661419F242131B214A99F3 ++:80310000212DB21AE63429D332A8422F14291392422D312E121CC9821E212E8296E12264193CA42C3C35912CB411C6121B4127241B692724132812918219B2421AB1422AF24282482F2428AAA42B4829E828C4F3008210010000000082000000000000000000002200000000000080022400000014F0683A0000222C812184041C88BF82AB ++:8031800042827412217251B281A5A1681384E21124042229818181E21807D836B231A48413011CE81388A81613864621048230C2288200882822428AD48F4C11A1292814423C62231CF242322C478131C21442352222028288188A92212511C3612139B68214E221C422488219C182869122467241022C0882A22D811100462224F84282F1 ++:803200008028641222294741218FC2215227324AE132A4253BA488162266141D5290132B83184AE2382491113E4211A6B241C11214CAB2629141E6A2611BE11B41172586B28122D43288E3148814A184212E8180C42282244A082CA8424E216AF84BC400000012260220F162138AC2821032214A9241A88220A2A411108312A2252186C1D8 ++:80328000121224802848012E91484228232228328100298824244822880200CFAC0E2200002818124213A912484A2808224E81E024329188130A11001A122181A421290918800C0026830419140221E01428888844022928A2242220F281286014223819B12121D112F241222821101232422F14B191D42232A121421B434AA12882239CBA ++:8033000061484E122AEC11182214B2C292C22D21382D238AA184143B9288E6226E1A2308212428282266422208E8F08E53E0142202C0212C8162152B24390842105212198788B842C2414A6314883C88A4241A2281E41128A218602B481984712281C9222C94111C14D2226612908123488204212A14B2A204A2F0EA2400A02113818132EE ++:80338000112220E12241A284C8588237261942A2811CA88328801821C4438A833412272424482CA8822810B28114A18288CA8268288242808822C2228822208224F2BBBC800242408202130260184611228604428008422480224931812820244883081382024234B02181A842214E82208A22080010422244028E624F430A0013041B4267 ++:80340000344821222B142082683A17211A222881A1241B8224328AA44142AA84A442299131142AA4284A8128A2253A88062C0480120168212C2404422820682648F08688800132260180824101582004C08212141944029A120128D0220100A024184225A2412482008828142E81206234904182240082208208F041CB1422C021112E43A5 ++:803480001C92621126914216E112A484172C56E321226D111C0533AC2816212814D112A142A0411C09BA24D412A638A0291B182384CBE23C86AA283332A127241C6828460242230823AE4A484AF8E59F8001182800241A02124A0821008200882A842281A242A8484A12A22421282E42A08212298412822212014081044880240400280065 ++:8035000000224F2A0411140042122B21501226A24280258824B86108190412421031228082046011800121A82D2120C342288E222888602C860214424828A02C232228642842FF1F050019021602B041022314210219C1912D2110819812210080641280088280D4229241248004800221D012421182022124002312024800F083411420E7 ++:8035800021E21102144A23044200001413091A46621113641115C2114E824825C18133890400112200A211182714304324221414130429A824002210222224F29C69A04100480000421118150224222440028A8228B22288C211A085211031822114401102291422223141820000882811908200210021F0DF1C00901140E11A64143466D7 ++:8036000011A121481C810468382818482C8198113081882E111AA21482A0480090210013824C820682826018904200308248C2202C42F185B9C04118481224122002122412249E231042236818004821A8601388308118481C6212182800002112002824224829840A2A3822228082841282F4F375001304002400101201000010810239BD ++:803680000221A0128048020012271421002280012212101101285021100200200280F8B538140060124840012822306111428A21A5489260144A681326023052481901488A91A24800402202182081022A1821C421601600888008884228EF7C0E0058800200C012422C61262842244022868A022308290188482212290496A1412150121D ++:8037000048290411111110A2A480882A8828488228E42208298AE8134D914152181E1119418233211CF4323319E612B531D413AD492A44611A2E423B488E22F021222B12CEA11AA2542413A111233C935E42371125B12118A1222CC6421F22D2226122141F28B2A1E418048E811D23CAA828AAF2E242A2A2A2AE41CA74CF0956C1113E21C5 ++:803780001322E41413E124F623224A742211C2119235F192911B2C2B918AC2313E811F11C78114213F1CF131216E118E11C6B111ED22AE2A4AA12225F222218212125E111F1266142E22271229E222F2E14315A2442D622F2208282C848624C4A25F3A091011A1242E4233F172411442115AF15122272446E226F941222BD21F24F24391E6 ++:803800007E823B546AA8181DA21F22A44225B2919CE22C4C2294122C4482C24225F22311EA13A28539BA8188E834B841988223B48228022D82882BA44E824A8A3A222F960D421C01000000141220011210010000002110229412800818C22018220882000080044022088224800228001767B04134413AF311515AF631212F25F663233736 ++:803880003427142B541F2435633F1CB5C1FEF2F13F3FFC12911F1DFFE2E1DE323AA3112F3BE82EEE3EF722622BA29EA23F34748133411AE43EFEA1A33718421F18A8C91F1436822BE51952211F28F882822B842BCE15B1438214A2A82F2EFCE2C22F2888AC882F22FADF46141F15E111E512F331315E623F17F672223F36B263E217B653E0 ++:80390000F441411B752F14B4D1BD73F7F3F33F3DFCD2D32F2EF9E3C12F17E71AEB22F3A3E32F14FE21616AF2C1732B5CDE52CE432D42FEB2AAEA28E2285E119AF9C1E13F1FB751FEC36123F881812F28FEC3813F3CFEC1431F3CBCC2F48282AE82AEC2EEC22ABCA2AECA6AFE43DDB04194412AF211211F15F771722F36F663211714371409 ++:803980002F24F543323F25F7C3533F2DFDF1D1FEC33F2DFFD3F12F1EFED1713F17F53111AEB31F1EEE26FE23633F32F7D3E32F24F482C22F15BD92DE22E422AA823F12061F19EA2DFDE2612F15ACCE8AFAA1A23F3CB843B8C3FE41C13F14E822BE22A8AA2F26FEE2C22BA82BCCAAEE26F6BAABF051111F11F121311F11A2751F27F772320E ++:803A00003F16B261F253713F25F743633F25B542B4D3F973F13F2FFFD3C33BDD2F2EFDF3917AF721312E223F1EFE62623F32F662632F3DF7D3513F1DF5D2522F29ED21F121A31F32F823238AF831332F24F4F3713BE51F1E7681D131F8E2E23F1CF8C2C23F3CF4C3C1CE422F28F8A2A22F2AEE2EACEEEAAECA6AF67F6D0020022248222050 ++:803A80000224402241022CB281C42212108102280011428800A0821002002D126032E03208144081048002004200F01A2200C0111321129112197622B21124062F14318142921412281984AA4928A2463123B022255922422ED280052A082B82A0821AF442818288E02488C2828214482D8222A82A9482A242A6F3A9F480B511C2111B21D8 ++:803B0000421B212394612F14B111F642911B212F1439912B9413F24291222F1429DA12AB421CE92AC4812F2264152F2264192F226D192CAC2D2CB591C2421B2925B29122B491B242B181324219F242821B682F2438812B84AAF44282222F24A84229AA42A8AE42FF2B0A181B611C95214AB1113242682F1491612F14A8212F14BB11B2424E ++:803B800029B24229F242918229B322C4B12A85A8D2522EC286F12142D6C143CA42B391C2431B693CB49162148A32421B282394212F24B881E624BA8112A24A2724D022AA42A82B4229EA28F4345420040000000000240000006200000000000000000000000000000000000000F07ECA001902281416011923C44128293F81230C2B298A4A ++:803C000084392133B91292418A23E2140212339382E01204122AA52918218A928225816C18482C82820646827842024AE222A4422912228C84F2BEB714521228198181941221293332429012308113D42231618A011B84221C9481881D62190213A361241AFC8222881C847231022E11821992122E81881C4432212111142C028288484874 ++:803C8000221C22E4330A126A01322061211D324A9113488A32B3881D824EA24AA9252C6A381F2106562191C1A6D123E121B28122641435E221A8489A866114282F1192812E411B811C8EE214C2621C3262272819042986F28262422D424AA842283D6280142112C111191402226826A241244830112413C81112881B42A8138A82841221A8 ++:803D0000A11228D8282A1161221A928282218221C0820000112422A048200222C042FF590D22281C91212601260127221214121848809412223C0B888032211480B22141011421001301C011822522581200482E81824E8382004A08284800422CE4990319941122181AA4142721121813BC12C223141F2861241B2926E11C21E4339C2129 ++:803D80001B1E1B488AE424E812E42481B43268392A25A3586E12A83B382B38297A22E11A45A112888E22222148C0424A8888E2282494224AA2488A22F815FA4061111A12C1114E12112129C2422E11137212C181E01815C2A16E8316412188AE823C9C21567221B28161214E231AA24912211388A2A129F2A2539012A028241322A848297F ++:803E0000A84882228E428006C28A44F25F3CA02428141A82062A812171920118C052482992315212CAB222B84143C14120848285C2811200623E832E129231860186912188244A822814C142004A086821628082FCE5420060162011C11214008A6124A01242001B162C0C1B284A0280AC428AA421198A8266114A386213240452112200A7 ++:803E80002344C3A2E84E81684848220088224824A024FF19462106523219422204324828C0912231196221200148881384682160380024C0212028912122CA22011148208204A028883042282002222180F861988081011100E02462141021024621C1824810210220012814324224421C212403221A08C0222420DA2122082428242008C2 ++:803F000029280488828848D0314D210713C13119428114B162018A8216C253467121E22184F51142288E21A81A84E82268121B5229052724584AE2288394311B9222121E2228A04A422F1832222F282462284A68282C860AA2A0828280FE887A2028210218D022814681C411C091802108138208424814208404228E21221C8221A4824240 ++:803F800048A0821124112419028A24B2812404420048202A0442F035BE202211A14214211148A0211982A281182C8B582162130432181C430278488001C831C082481A022CC891233123400140A24A62800200280000217F7C04000042124200C818881100801881612400004824E022086013480011822129011308800211140060244264 ++:80400000222800801882F4D52A601C0020613611281B52141B841611410112212430611C08A811001602242490A2239E1112192408005012888681B24108888022B842682882218A2402284F6F066016489211001460242024D22202800180081302C041211C081422486011A068211B2100220020026014258188280621C0828084089691 ++:80408000071A621212803422408121A112141A88088681521218202102100290812B141A222A6121822D31001A38221C212151129023008800290242214280C882CE211F83074280222432111A34323082820090822218582D22A0861A0C1A8211B1210960141424280078904148882222820028888004A04828820042006F8809001C04BD ++:80410000008004224282001421000000002882C8282800408106881311C21224004280984200A04880024A02888004FF1202118220024240622411304221190813A1821A22542142118A11712192612CB2416126132181261C41022932218042A143481522880A4888008044C2E20020F87338148A81A14113012093121342022824281162 ++:8041800070420126234201250118248840012192141A2248818C948100312C8202C021142C0224240020042304AFC10A12A215A13446E316A651682D411F242A69161812281E132F32B241E134A6242F12A3635031137442B313D622E211751221E93884F481732A71A2C2122B8A11132132134E4124271222481D81882324A22422EAA28D ++:8042000084884AE634A428D7DBF061411F19A5211391213B1117362E114E221AD11193F13F19B283381119A89D2521D121B851DC11F811A1C0431B422E13193D622E421F26BE62EB260A4E6315F1A1811F31D1126B281F31A2163B283982EA28AAAEC2C22CBC42D8229C8229B88234428288C89FAD023828182AA4412430531B132F1AF457 ++:8042800062C2822C48F38283231AE123B623F122418218AA21B322A23842A6D12192312D11122B193AB893A8F52B25602D2F121BC2212A681A13F84341158306AAC262A24E622426A248888227265F8C49012A01148200A041A048200800130113018012011142110090114218E01228C481C08140011460328A04008A0400008200F0C859 ++:8043000088E01C22043AA7113F13DA33D233E434513323A4222F22F813912BB91CF8D2E22D522F34B4D2BD11A5FF1BB92225F2A2723E517AFC11522F37D733F491422BC94E431F3AB421663C39A2E2112AE1257543F181823F12D821F443E33B46242B242B88CAA846CEC22F26D222A4888A1CF2EAE6E015B311A7322E211A7913F1536328 ++:804380002B451CF351D33BF91AF792B23F19F993912F1AFBC2F33F24F412532BDF1F3DFD72719E913F13D332F263E27E517E411F27F571732F3BEB38B4D2E62CF5E1636EA11F38F483233F3AA2281F23F353511F1EEC18F821A1CE433F32FAC3E1CE422BCC2AE22EA88ECAFCE2622F28BCC284BC42E44B4FF151613AA4231F13F331313F62 ++:8044000013DB33F223734E13272A23AC2A2F21FB93819AE838F8D3E22D532F36F6D2D11BC82BDF1BA92E121F34E422FC31717E721D731F25F713539E432BC95AF6A3D23F12F681E33DA32F223A211F12E125B5C3F881A33F22D833DE31FA41614EC22B842BCC2F2CFC42622F2CFE62A229BC82A8C8AE824FC8099E313A83F121211F23F3BF ++:8044800072333F35F733314E712BF72BCD1B5D2F29F993832F39F8B2B33F3DFF71732F37F5F2F13F1CFCF3D11F39F921312D233F26F673512F17F771731F15B7F3EB2CF6D2622F2DE73AFE21A3AE233F29F2A3A31F1AF933123F17E51EFC81A12F12FAE3E31F32FAC1C1CE422BCC2B222F2EAEEAEEE22F2EB682BCC2C4C2EAFCBDB300400D ++:804500000124E012012603262241224932810028802201801282128212A2242110225412400123022E11481460320040022C82C422480020F8E44B80A1212212422834484A21C1818A04C011C032482F1421794231B1884081C4215816816419A0252A082E9292B0818201252208284E82E014084A2828248888A48482421417D6A0421B22 ++:8045800021181B214AB11132421B212B141B682B941B682B94112B9413F3429113F34291222D911B421CFB21424E811F2264112E4296F12142D6C1D29AE222BDD1C2C31B293CB891E214B8917242B1817262B181F242811B682F2438812B84AAB44228BA4228BA42A84A4AEA22F49443A0421924B21164141B212394212394212B94282F57 ++:80460000149B212B94222B84222F1428D212994229E322E514E822A9212EC296E12224CC43283C34512CB491C6421B21421B292394212314918219B6421291222A344222232432422B424AF822424FC8062008000000000000000000100200280000000000000011000000000000280021F0D11B70717414C3311152154822A4148B42288A ++:80468000141948A8494A212197911BC2A2282A411215311125D184C2442F11082982D8218A98223C130116A14286011C021829A81C8222828290428029A442A7C414204A2441F43242DA021F6268183375228291926413BAC392812D44701AB181F4488168827024887253B2210849BC48A9412B14411749E02831A1D0222892E32B412BC9 ++:80470000482E8111311D42C6D84226E248622A4786688E2988FF9B473145439D22144CF421182332425B2183B82331233B828C38C423A1433EC21E414A58211B428E181AD25268188D3533120713D821A44298B641641DF012818A0223B281E212D81293423C31A127158A84AC68A8822F24C246AAB188B422F498EDA01219D21421C112A7 ++:80478000484A09C6926142C01212181B4A2D81114C3821A92BE814820400B058F227C2124938982C24D422C8242E11501213E12408238484A8282048638225044C2298284828829FA30E2280C1284128230600299921B09144A24A29011C11213491422487141924542210A32469240440022D9112002C0141821419E41488948216280455 ++:80480000252218028148CFB643B112B4119224244E228411B7214E21AF144A22DC235D2813CC1886F75881E6AA52B32BB4A1A1828682F22A111CD31C1C14632384D82F16988614228AD272B631B483F4C1182F14B83A14D2220183092EC2A23A041A94284AA168A8EF6A0B2B2432322822812289B14192211A5812181934C1224F11A81833 ++:804880004A7312A1C1424ACA821724622E481E22855512222C91481AA4282C083B122839C4428E41279C8641082511C198882A24A416A0582922346846F2D18B204111446A6428335432F0428821E632C1AB8125E2A5486294178862AD211B181C21C288113D1211C845C24349062C3841251421A88147221C2361214C94F225E121A4848B ++:8049000048218D922A484202811888A81FCF098F260185C423768202212B2412B01444A212186CC48A17428581DA1448C4182F44E84122B684045D588F41942154452AB8416154219F44D2E1AB42C24341B19842B48892482812C09449C29643D2482866246E1849F8ACFD50122E1946111A08C0297048A2416538828742467422A8411257 ++:804980001602C0D22631281E88849E2125022282168992242608A09440E81122482694A280E14CC284508288A0182306232158282FE904449022434144D5489144C35142134881612C800146B284745482C6284604211546B83804301C482B4840A281491302129028421116221133184812207122188861888342048D3C3033271126CA8C ++:804A00003C6145618167864F817456EA28A41429F942984CE12364A417239E4B4F29C6616E984797AC7A887441F2114A4A531C2AB4896225416398611F4481C38C4F12B818E41E31A4143FA17CA4A23816381840C2842AF12882C3D248A8C28B4243D72CF89FFA9044286511F1681228411123021C51811074425284984944044C1804498E ++:804A8000847224C824A4524D181654848B2C22122D82442F126181230289C14422128592414AB8948461816C38142CA94381128908DE520013014424114934185839C2221889C8421111808494188348486148844218A82C082141214528C1422C441418344985351285349224892361118B2480342825064CB484849C82EFC141A1242264 ++:804B00002952384400408481881C42B55488792483382420813B146E11412CC8224C04960C2921882574112831181212A01848502484E0224444A594884AC88812901844F0E95B003018224678281298418116F41442811D448124842185A218402224D42838815049259A184A31888C142411840118284E188AF282141A2412418119CAF2 ++:804B8000586B81C012478C60822C014C21F6FE824042042721C0442826822214CB351818B0A494C44B12A0124AA2182C088C712488021C922113436481821B2850183487181443819421588AA29420082048084E149082A240F82BD270820140EC7508151215D2422838814225A2127088612849942881418A0147288100424C88F112429C ++:804C00001098442460E282A3DC160984509289118218C288682F8823E38A84958489E182C8913F86078CD332F1294422836242CC341849511889821288DA486C21684D21223C84B121145D4122221AD4144302432C4811E122C8892490446082814541A41430281981A816874142241285E481C4444A61C4DF1F4391444042011400006051 ++:804C800044214344110148130815042268231411A24819085081482382412401800211211441E21C044414104404880000EFE10B182AC4111228AC44A24281A840B81138881028812111865481228148704408528D61B1888F21E816582AC814111E211B8225221438422638218A14668C104822014A482802E03842529490441001222023 ++:804D00009648271544472219034B42501860144C022784C01347151C7818932880064D414041488406210090114221441D481912024100001082F2B7891466E51C511F9D21AFC5F447276485B522F218691F49F4B87BB7822FB8B421991429FC148445223244CD815F24F84124815BA2CD223CFAB2121F18E138D84A78C8B48866194C35F1 ++:804D8000131D3F178D3F94F1848AD41A7442FCB18217888CD42843E2DCBD98C4426FACEA24A1A881CE18AE198D6A7F1B0D4F21B513E2C273228812F86B281F81D588F5C7869C98834DD18B818F45E438FEA532AE322B69C37412F4C1683E318B88233C4A1FC3F492548F84D22AF8316C1B1825B822E166FFC1828D11228F52E32AF42B25AD ++:804E00002B9517D249F1425D8F32FF2AB22F8CF41A55324F84782AA84365944C888DC44B45437376469223472216F2141657322E4849F4622247652AF16A3242D6F645146718B7C787549F94E456F911798F9AB732F1884C4FB2F525CFFCF54211D7861DC14FC7B64AF1544A4F21FD558BD127116C341E2D82CBA11AF58D42AB141F31960B ++:804E80002C2335D11F51F8C588F9A2124F4DD948F1B8C85E1A4FCDB536C2842B8C4F2A0E421800400200241A04488044F28148A0480042132804422094811004002A2194161084A482502448A04826A248804406006400824CB2C4099E4227A2E7D15F42F4953E6F62BA6CF64765DF53D144B8AFFA78B2BEDC4F2898B34F56F3FD1DD5DD5F ++:804F000047F92D2CBFB2736CBD85E177D244F8AC561D154DEE5F48F7717A17383FAD24F99CAF6F78F8928256E832F2B1D59B391F34785B5AE88FA6761BFB49E21F24F47B856B8CAF89FA6C384E188AA8DD2B992F29C9488F8B36246F474CF241662F6D761CF41D345F695346CF62F22F6FBFD2F1D3C93F7BF9F8B2DAFF8282AB985F77F354 ++:804F8000D6B55F59F7F755DFD2D49FF16FCD5FD8F588DA3F14F82CCF6FC2D4F4F61596AFE3F997DF2FB1F49A98CFE8FA9F7FDED24D569FF2F3BBBFBF99FA719BB7F99FF5F43A2BBFB7F28FEF3FBEFC4B25BB88BF98FC6C38CFA7F798D48F8FFB96946F29F522788F8BFF7C5AEF57084F61F62677CF53F23515DFF5B32EDA1DF64676FF54EF ++:80500000F185963F4AFBE1B2BFB9FF5B823B911F44FBFD5DD733FFC5795DFC1B59F7D55F9BFF6C7FCFE2FA6CCE5F77F1584A7FD8F7717F7F7AF2CA4B9E864FE8FAE6CB3F29F813419F32F2B597BF1DF7C1A7B7B4D5FE696ABFBAF24BE73F24F75BB93F1CB9DAF17C3E2FA5E928E92CF5D6CE6B996F82FEA868CFCAF92DCC346F6CF79677F8 ++:80508000CF33F21D35CFE1535FDF72F62E36BFF6F1D3C73F3FFFF3B3BF9D7DCAF2DAD27F77FBFFFCDF7BFFDFDDDD4D7F91F56CED5FCBFF89CBBFB6FA6E4FFFF3F51A4BFFD9FDF9DFFFFBFD1A4AAFA9F9CEAE7FBAF7C5D67F71F13F3FFFFBFBDBE91FDFFBDF4FFF74F47A63BF7FF2CBEF3FBEFFDFD9BFA8FDDBD9CFE6F37E7E8F28FDE8BA68 ++:805100006FEDB91695D28F8BFF6C7ECF2C0E43026170220100148A64129200208192418D22482811288012821242148102100600004140811444482308481400002024684470EA0E2041C12C4E1215081E68611E2823E481324247882F1441D872284933154E21128B8453AA845183C1428F59D221B4888245A4D2174D25226132924E119B ++:805180009A02E032A1684AB1110216E84408B84B4229C948296883603A7F1F052CF511248D121F417268F21164A3D441F24A121F41B24A9961AB9459F44A925B4AAF14B9A4F442914F8AF442915F8AE414F9A44A4E814FA264157FA264192EDAD6C5CA9E242E4A1F4DC2D21F49F22A121F49B268F9916CAB861F48B24AF18164AF26F9813D ++:8052000068AB9459B44AB9B4B44AF924482F247B24B842FBA4484AF9A44A7F6C0EA41D648D421F417228B211344C1D24AF24F111248D8419D64A9B65AD924B42183E482D814F82F44A1123B242F9241A8F14B12468156FA228E9A26515BCF498243C74D1DC82B191D6225581181FC936421F88921A1F48D462F181688D3459B442EB8B349E ++:80528000424F82F4429236A894678A4AF18252FF9A03200800820000400400000000008008000000004008000000004004000000000070D602801137242954224D224F23341885110A82479884221538882C1494241AD418611E848756A364228F1832438D6142CCCBCA2847112D2434CC7152233237221C44C363F048829E4C48C0864059 ++:80530000A2214AB1248411B8FB0E5931812E982541C8198904A6B142AA4193C4184829F81683F2182B12AC89442158A48E219031C925219812B22532248E516A486189A88952948CE884E88398A41E881B1219018629CC7846A4D2C844811CA2C27F9801441B1C16382127A493D14AA612ADB2CE294B148D412E1899D828C8B39CDB282976 ++:80538000F386124F22847111F8518E81AE411F81D484D6827242E191F4D12249F182422E411E434F943281AF68B2317426F3211C8964954D21C39D339B1EAD148324CC1844DE225A68254688A1C3EF430D1C01673A4400244C4401A1809844214142204408198428C2A1458A8261192C88028B284782924B829018128184888AA2828227D5 ++:8054000012008AC481E0648A042244438242F82FEC00194203266281141E684228852171488324B421941886C891304882204A14D118C24890825022520041601210B41146C12841482D111B4814482901982218224CA24142F0CF7A3438242624D1414564432574A1F288125AF843228819B88651A21C64368CF6A2431B1213964113F480 ++:805480008A43466244142F92F824421DA846E888B2643862397A22D32438A82F1866282AC4C2197C228888D12AF48118E088D626A4842D6421218836B88874944D226312450245921819316A4EA283D932A5411582E8247821921183F23243A6D118B4A1641413D894C8434214852152122CE48C63642CC2871312B38212A2142148428347 ++:8055000082A814841C088A14E22822342241981289F864B3140039229171444C32141122893821278C17244C914889641C8C28B41202A0422314D2C1D228E422684CAC1A088A822402434AC8E51CBA41E288D22768241C31812714AF248131284DD2484C032382C46848BFD40591414E24E044A24256469211C081495482226711C2822602 ++:80558000D187682826C58641821648B884048B124247221422D08404444E3191421183554826C1881283B41812EA8894C42B211A042D2449E1228491286FFC0B281638482518583822C126CC4A841941E416088C0244C0148344125181168424C84C4C0C27141C8434181E282D8622422686E18402212D122AA16825E148460440CC2248B1 ++:80560000A048AC08F0A482108222C124122180821422011082C4178B4281A042C048484E26CA124481120220711462641411209882B0840110042128808CB11282280842841248C6D4C60333B214D26853841E642D2A2C52A48753837482C952811C9846877E8B8247221C887F6268841C7468644E87441364446F8D22F424412325D3223F ++:80568000F4144131441B286D2823B54D83459C1123B9A2459848848B58472E8D845EA24826A41C83A6418746AF840D8200288119B44481622480114182C41112421558484154434874811208442608240046D48481D2248882318120582830268C4292612CB98444228103244885240982FFF70C4D411912B461016D1160923532511AF687 ++:8057000081182114448242C0819146B482424422048114853486909262258132411012088312B2A2011A74222851C281862C18F28212890885A418812CF4A796B0120228814381120190842142E8121A022559141628311B8CA11214C08450A2AA4179A84418C8281849029011211489422818018308201138844624A4183A14A282F02332 ++:80578000DB602940015442222001828C041013E842184822820287588159A8246012436412271190941C74C19421134802491428324946088233025D18258364C248414C810883024B5B40040000231524840AA8A0214D484716601362168108242604A41C6944141870844241022C512C8984C21823081022189148824A02440032904235 ++:805800004416045FB94402C022201506816B24B08982D12148128899184800A55118560124846F2492842692881814284128241CE14122044C6251C086A0422848882A11088981A1822A81A114883FFA0B141269448A5281544814460C008C2431244622B886846845882847381F823115181041324981BC840A8C8812411201892861144E ++:805880001220491184A4A124A6022CC4888220D4E50568800160284212240025A2418004210042A012C0184A29840840642246C28156421294444841421A0841842A040019C2844482448954424400215F4C4D012F687418614287183281491748C24121855185144639816B14226B4A8843243C22AC62121CB44832823A14043018852591 ++:80590000150868160B1E4113CA139D842C91418E182CDC2122A13470244208466C1C8CF2559640982148172190482614614399021742B042021249C2A84501281121C84901498A0820081C21C88286081D142541147182245442308B44311A024825088242201292847F8F4612F1C12115F421796F28F3E448BB62174427723F11A8619DD4 ++:80598000B139C751518E584E232E8C9F1FE224F149681F1966279DCA45FA18CF1F22F7AF226CD91EF62A14869C48EE4BCB981F18D444FA131E2F84B148E469F2F3178DAE2FD4FC42A223E4A3328219F42381E4AFC498C24D1845B252E643E8BD01EF5C42E1227692F62811857618751954141E71CB75CB466E832B4B85734EF858418F425C ++:805A0000F2AC4CAF1C53424BCA2B8B49F18128275A37586254DCF4872117815D6B29B8929B9219E645781982C22427213D8989EA18D529F1911C8DB31F18F5419DDE9B4D12EBDA8E124B1B1AF6629C4D982D181CECA23CBCF05615226F212231412D3356742C1AE1E8328B46AA8C17212D3C5F3598935B414DC2BF11D254F12A884DD54B93 ++:805A8000218BE679325E4AB828E46AA9899D5247A69F417222F72632279445F121435D1D8352841337841C74A1B84A18584CDE2C524B228764AF6EA849874A4B48CB2243FC1C4A004B1284618C048C54248C54241E48241648C448641648A44844E044226144824411004A0280081C082E1110044D9148432231249A049A049A84A249280B ++:805B00009285229128928D247F7B4F7141F2412B39F23B6113F12A643F24B257B151F71D955FADF921911F4EFD5B53AFA5D36EF8FAD88F46D2ABFC1A992F33B118E9197B2EFD22A847F81FB2F478FA4FA27228F89299DFCCF5267C6FD1F18C371D123F955129BF61341B3F7BB21BF28A16A5D862D18ADAAA752AD667F912F26F64FD2E2C3B ++:805B80006F64F966444F46F516D64AA58867258FC44CF115531FB7F735211F12F231213E366D667FD1F355227F5BFBD5B73F1EFAD3F53F35F55A5E6F6AFBEBDF6F5EF5EF5C8F81E949B9ABFAB1B5CFCBF3A92DDFE2F8614F9F97E792F1A83A2F9DFDCCDFEFEBFF1C9E7FF2FA21A33B239751BF7454EA3FE3DBDBFAAB2FBFFCFCC346FD8EA1 ++:805C00003D83BFF85AA7FF91FF4E6EEFEAFA5616EF6DB9A4FA5E546F47BF38F774F61F7A4CF371573F71F71B2FBF53F37D7D8F43F7581E7F65F15B5CDF58F9CB9F1F38FDC9B9DF35745ED87DFCDFD9C7467DC94F87F93551EF14FD84F14F56F724A8DD8D6F15F57C7C5F3E7629F992BA4FFFFFA67EEFE9F3872D1F36F611718559ECAF26B8 ++:805C8000F6B727AF97F6CF16BF21F12F37BFFDFDCB9ABF25F747951EDA6FE4FDB6B66F66FFF6DC6FC6F516DC2F86E58BFB649A4B58347F73F53F77DFF3F22F37BFF7F77A76EFE7F77F3FFFF5F3EFF5BFFCFBFBFBFFBDFD5F47FFC5F5BCFFEFFFFDEECD7FDEFC75BD5FDFFEECCDCFDEFDEDFD5FDAFA2D6F7F67F77D7D4F1EF4E96FFFFDFFEB ++:805D0000F8FA2FAEFF7CBE2F1EFEE1E23E37FFD1F16F2FFFF6F6B6BFFFDFFFEF77EF6DF9EF77AFEDFD43DBEFADFDD75DCFEFFD6A7EEFEFFF7A7EEFEFFDBEBCEFCDFD7CFCCFCBFF6CFE8F7A0D0000472240A241248A04001A44110112811B41200180020044188008290149012184180040A3482240016400008A24240882EF7206A6022668 ++:805D800081C211601215B4242161128A74428314F884482D225F8884721198A2139388532A34261671238292814C124284E9485212118052321B28248A522A1124C082112909AD8643C812413812442CF49F65E022F4112487221F4132481F49724ED241F64E121F41F64A9219B64A19F54A924F8AF44A954F8AF442954F8AF442914F8B90 ++:805E0000E414FBA44A5CF8254A16F5244A9E212E4A9E25ACE449C2CA1F49C2C31F49D238F8912483F4912CAF36F88164AB941F48B26AB981B24AF99548AB9443BA4A39B42F24793498924F8BA4944FA2F4F96DF0244A1D644B121FC136421D2C611D6869F111682D941D6C4ADA85D24AE98254582E48AD954B42AD146B415CEBA2D558E870 ++:805E8000A27C18D424F8982126F28825348741349E2CA41D6485B29116F8812827241781A33491257491F84A245789297394183A94AF24733498986F8BB44AE1A2F17F4900000000480000000000000000000000000040084800820000400400184210080014F0D8C11041120140084D228D414D18282648F145182C944C2F140829180C2E ++:805F0000518E414B284A5818817024B112424B5A242C014C0419C824B4116B423B412311E82A818D6418882D528F226D224602820064FF6207521B1A18772226BC41D222931988237A92819848213D182812278247152D628189227341D8C122B242D12CE284C88880024E282ED12CB82161A31CE942A452818CE8461851181D2A1D184482 ++:805F80002588024B818A63422885D41824E4450D1B144A51321D2226942929F22219837832B685322893F2411C484336D28D225B854FA442CA251B214BC35C68388C91286D882E1884155824183B94483F84E1B1C8151D44184A92836912D994BA437932D925D82828B7BA94342F24294212541856B21404902118448148184427148688CC ++:80600000216824D03A4148032400844A58818B24262814E4149282142722E08284928428228A72289261E11E484A09188C22040024822841A8844241D7B220820212184826624187221A028E4825023C480813D25232918B2416280414218F11D28134181928C898828810148108348200430481400214482D8286A82448888444F0AD3E1C ++:80608000142416E581C223473212E3652445619896C13189F1C11A4CF48552CF12948AACB42834811CD881E25274C26C1448222E4428716386B216F41281422A79227182F9264885F728824F21CC93BC21988113B88811722448E425022E186120CD24BF6803221D341658211E2529F14234D016B22BA118F8A991C279F88558271686E9DC ++:8061000082F46811A6C9182698418E491CA4211C446C3AB0722832D21144502386B244129982274413042908248728C0642C682C628CC1840041FF3345410222322044EA4144281811091D1846028566224531824213C8412646069394284A034718852458248A21E418231A59A18694281E824729994138811C28414118E6820162218491 ++:806180004B85288F1C0FCB416014241226280542850240648250421AB441028C44048A52421220287628831272243122401841240E492184428129531A572228458399844C01288B82C922C8284AF8E151100A4E2441839444259441631232415B24281AC44C222460E1288496185822569848864C321448866411488CD1A1073817844159 ++:806200008119488412C14424424C120223C4482243E441042C8155483F7E051C1232121942111248C8114A21C11810028123483C814122009CCC24241932182031216041000016042A14B688418812A8288C888468841288C60A80CC2880F23F49241E45212F5132244A712622C14B5CF712424E1189031841E3A2948D411D84C484818C87 ++:8062800078813E6885722CE1A4C11D1AD643E842F1126484464321D19413C4644F148841611A4E3AA6714A2314B58A95D48B84837C62B428B48884CB2889EA970D220011A5C148C30440081944C24883042532248D122AC4249228484448208212820280A121C02488D02801CB828C824114A828248224C0142230944C42A81449F47FAA37 ++:80630000800416911811B0245124204422958A1091884918922835022114293144394754821C041A8638424008144912014445A82444482C018601008F4218422832888021F1BD7D242601442522062146281424082C01430423044248CD412048C28844264891885414818225044C11124288E2882482014549082484630230C44C911812 ++:8063800041C0C824B7BE24A012850489423149C0288491C89088418116C8812D288C742408220011141D823A44CC4823084C048052488191250246E481941813E891121813240190841218C9C348F0CAD9402894412411184152136111481922041B82400114004F9408CC4241A8864480A482482C42A812C44122881039642144282121E0 ++:8064000018B088952258830844E1C024F0DBCA14A2902818522818D048D44242420221008B4246446382112A011084413824C1C084001502211118820092184087C88189611118D08225C18A80A48480EC9F014410224264142302124AA8141C4328843122411261140025C8822622D8414802822147A24E898230A112824684281C412C61 ++:806480000A184081AA2428446722122222412C015F7F031160214481848121008342E814B1140219440240241444545842A0811200402182928112A848144C46068A42822E8202102A8882044D88201242F43D1840F4112A3041415211374327322008D021446A14188D2118A021C011882E81C302421A882681843181382908881AA28105 ++:806500003671C10A29894189392218909AC0189082588C4884F89DFFC04A446880412404411663124CC8811A221434234843E42148C24927421118484AC8882645486B42548B524126384C8911522D0091873682288584E8482218840840820A2948F81EED144D221FC856B13D2EAB418F44E522D421F5695A13B442AB412F9C18B9237124 ++:806580008DD998F443886E2627398F14D41B7885D834E25A7482B82D92428F1862241CF248822F44B862A5126F4278B5F914B487C417581DA82FDBA6132F41F942981F2BF111113F2871846A214B1129A54DA9014F48816123F0FE84D01344322E481F1241D247E28412E2517D89F2E8B287214BD48F7C7442B251F3245139D184D46241F5 ++:80660000C8118E1C35521146F194892FC574A5F858D6CCA2695968481B39308A17198724AF559488EB448FB87224D188BA22A88339F8CA242B224F42D882F98484CBA25ACCC48F48D884B8F54562463AE141A3114FC4F211218F957116F41425E9E2925413193512412A74A646D29C34695F82F264542E24B9B84CFA7C741E4C97625B92BA ++:806680008D44178A7B4A26FA882F1FA1022F4462A2A84F827B847245F2812C4B469F6956128F8852981E114F82ED88F8D82AC74216FA921EAF82F2AC284F84E528F5D1E60065016712302460127024220140A7414C0A4C0A8DA4800A448012E2440228411004619014B026880440024302244004648648028524280487445FDC0F4AE49729 ++:806700007318FA36528F816321A7834F11E541F38999CF89B961763BEC58F958784EA19F39FDC8C95E59ADDDAFBBED8CAC9B2F71F8818B2FECF412132F11F9FCD8CECBFF3DFFC9489AE93AB32CF211176FE8F9AB81DFAB355A9F89BBC9B491FDC8D5DFD1B41FB991F8B99CE49F11BB18F8585889B422FA2CB44B448B889AF59A86AD77D07C ++:8067800014A671A7A11E13CD181F35F51A1E4F61F45E5CEFE4F58E8C15F37A2CAFA4F18AEA4E8B9F79F95B1B3FF9FB4A9ABFBDED15F51919CFF8F9878F2FB2FE2A2BEFD5F5DDDC8FB4F49BD3AFDCFC9AF88FAAFB23A91E362F6EFBBB199FAB75DAF9FBB9BFDDFDD1F6DE11DFD1F11E9D1F31F898AC2F81F81B81AB838F45BC9EF13EBEEFDA ++:80680000A3FB56C2EF8BBF94F98292BB76241F64F4116797E17FF3F351773F77F77B419F17F7193CFFEEFFF3F42B42AF85F6C7D7FFA5F1F632EFADF16C2C3E396FCAF7FE58BF86B631F1ACBE6F2EFE6FEE8FB1F7347DCFBFFDF3F7FFFDFFDC594F2DFFAABE4FE3F111357F5BFFA286FFDBE925FC9BBAEF2CFCDBD2AFFCFDDFCC9F71F19A09 ++:8068800092AF897B8FFFDEDA6F21F9DE58CF25FC36B8CDBE6B7C2BCC9E5CCFECFD9967245D677F71F33B2F7FF3F31F7EFFE3F77B36FF77F31F7DFFFAFFFBFFBFB2F45FF97D17FFBBF9F63DDFDFF3FCBE7FD5F7ED3FFF9FF5FEF91F1BF9AC8F7F7AFC2F6FCFF6F6747DDFFFF9FBFFFF7FFFDEDE6F6DFFAABE7F71F816347F5BFFBE1EFFDF3B ++:80690000F3D8499FFFFFDEFCFFEDFFCE1FEFFDFA9BBDBFB3FB9F99FFD1F95ED86F63FBDEDEEFADFC3EB8EFC3FBFEFCEFCAFEB4FECFECEC830E22004082D41481048A44A241A0482482A04820091318084211441901392824229492800900341004248A0440210800400689024C028F3C0C8E414002181648428841E412788108201441122F ++:806980002154812119447484521822124186C442C6018122924B128A123281418A7228A14841193228C08200844AEA8804478A008882AF46032CF4112485F21124A3F41124A3D441B24ED141B24A9921AB9453B84AB9A4F44A9143F24A9147822D914F8AC4914FA2C4854FA2E411F2244A96E5A26459ACEC49C24A1F49D224F4912485F226 ++:806A00009124AB841F49324A1F48B26ED141B24AB981B24A19B54AB9A4B44A7924B84A79A4D842F9A448984FAAF46818D08685F62E431E28E7161B21A3C4246F16D1C1F24A841D24ABB484AD253E482F546B83AF5429D24AFB3648386D5A5CD8847C18F1248A8F55F2245A87114D5B9AD2B4F491284D4B1F48561C9E4889F1912CAF24F1E2 ++:806A80001124C71417C1AF64F991248BA41781ADB7B2874447818B84478B25F4B6488B942F2AF5266F400800000024000000000000301228180020040014000048120000000000004004005012F0269A9011441742D081A12127848951184181A123A41C8F11044D198931513383D11401855281414D49262B4822A1782283312410D15298 ++:806B000028088111295512918B12904188122988C1448744CB9441281243180E46E42A4142A4421118144522823D212C48624882296442E110052826818422117221021420C8221BC14D221E84841564611416DC18FA14A2602C148A911313483228296828200CCF186282BFA9075B146E124D214119C5338364111441CB9427326A88B96D ++:806B800089C582DB4149F112482B215D121C018723918AC24183E2121862111B1C8226BA8C4574D2C3845144218D14A3674A94CF2806EE1313C9812938222748874C497D84028E194F81F84BEB00442430288041582C2840488254420026481501412811424187413502242082829121224485218851811413D832011811001890184824F8 ++:806C00008442224C22F2F3CB1004811224C4C064211A92821120C8125018101AA484828501502710128838182C188844044002C024A11022018489C948888C14022100263848F08478704231214D228D2216F44122161FD91CD585784182AE4835028C6C63C3E8586292F382B244E8B258C1228F51922165C1526E8443A51663B86228EC2C ++:806C800022E1425818B52465582B1424CB42941B814671122284C128833A2C16D284B644C914A6F411C18004C3922812EB4289912CBD548C9841808838128881414426F98269A8871811252C9232219486D248E72C4138422742C2224C1251141227C82B14D04A0219F188412D48428B148487228302B01C08F0FFF9501626012D1244141C ++:806D000075924160732CB881662411904A47132788BB82444430448C1A515295942125A41482413A94848A0416C282812538641410A2418591881218290829221884F14A244A62C549FA3247502A26E4541255621522A418C04493F114681D2A144D482582B4459382CC712491489427482844134922022348934822284F128C1409128820 ++:806D80002EC64531124724C03389028C51221E283261231662284289F2ADD49018248384012A81412834385014188B4221818E1425488A041236541A4B8184872812C37148148532118A64241244D231C302001992A898811E248611A2C2003241446E128D142CF49AEB902418122856480C733C2100248818145420685222AB8100488068 ++:806E00003222495621A04212A2A34101C024268A64428C01C200004C0518C8848A24E181524822F078FC1066618D241363E117C12991462E412E48128C64812734594466416F88D3A1E8C364418C7111FC498488C9D2A29214479227C42D452CE123E88CC1431D9444812D232E4426F434C825B5916682928B12A3D1149C1A2B16ABC18B36 ++:806E8000212B684393124B1ECCD628E47A0BAE12281C41344228421781604185B111D21268818552814A98412D24D01A8A84024C0216E12224018A22324822282A044F124998188200218E44211120018228C016488D248418222F63076022D021028D6145C82414424518222838188308E12183024484C1C022224C4404C024A4861924A7 ++:806F000044029928086341298208922260412084A1418081281178BB4CE211721801418911440170825112937812419484242068144C6412188084825114864242C4214A084182A21001A3022440A22400C024858212582247224941481444F6E76A2048741802415042482628810889048044250890628392151091444CC42149246448A1 ++:806F800026280928B081064A021C82C4641825E184619212212445C21442A024260280F42545702168244C820183058127114EA412A50415324585B51828A4811412524002A083841C41826458341F240144C0146044299118241FC422048890B822602849289298E084097041049046C0484E2850180030426019882A68484281302C81A2 ++:807000002881234414048D82811098488188418845C182841B8416184519CA888180881448088489088C8884E814F831F2508480942424244642714412AC1A4A48C24484C02B402744152841C6482D49899844D026440423082114002C080025842402291108888AA1844331440070124C78534C2311D1A1642113C18112180014142138F8 ++:8070800080216141A981015934221982021A2841810221469164002468202114A212122416011C4114C42289014014442412F4CCF410248802002044341820062C04422382728448C15814419420588100818E48400411809888418561C48501109C812E4211A021C110184868218181989F89038C041A44C18222F01A2683813228444635 ++:80710000EE91B241A121884AC162160210031D5C2982DC12C158C013E01402822D5C214C4441460140C41124852594B82048A486214A48843322288FB24CF1312613CC162B248F24A28427E1AD34F5F968DEAE189578D3E2E47142A4426BA45E86BD786B15A3D18D541C17C44FF23422A3F1C2717F41E144D429C42AC22D86413DD21D8571 ++:807180001E82CE838B4116791CC9291F84F3A188142B921E21988F417326E884D9C4E8C4884AF4A4984F9353448D152469E4B8942947732F48917E53F4544A5E262B28AF11BAC28CB1877CA9F91C819F93318E7CD88154855C638385B34AC2141FD4711C7E4853829EAC2F58CCAE9B6D2F4A684A22867428F4C384AF62D141756B44B44A60 ++:8072000092C993999B27CD2E888F48E168B48A85D488C59AAB4188EAF84544C0114F4271329819178117B285312118471117643CD2D86C114BD1CE1E86E28235D48F72E21627D761B12414F1C4694B6219C84847226714C39658451131448E42ED21157824BB4154224D12EF23E451F4121A9C26145C242C3A1E76F23E22474DC36344850D ++:80728000F4184A5F370B4221208224824481048A04822480A248200800800200002888126B8212881A92861A9286284168004522482248220880224822282488F2123F148E1447C48F82F237558F8BF218D98F81F13E3FAF21D173F49B3BBFA2F6EA4C5D154F2DFB1E36BF91F96D3F575A5FD2F311334FC4511165FE27671F9AF641614F70 ++:8073000083AA771FD37183F5315A9E122E2377792AB1F151183F3AF67213271235E542F239131F1AD788F1A3211D1F2F29B11AF3A4A64F41F1A4766F62F164EA8FA2F2DC587AF5BA247D58145F42F36535FFF2F33737CFC35B7FA5FA3672AFA1D177D97B9BA9AF96DA11F941F3FF75FF3FBDDFF2FB25C5DFD1F7153D77D41F13F33F1EFF4B ++:8073800072F22FDD5F15F47D2AAF27F77B19779C4FB7E98BE9A1F1BF2F5F1AF1B1DAEF13F3BA33E79E9F13F1191BDF32F27D53BF36D5CFA1229FF5576AAF41F3AE26CFCDDD4ED66EF44C4E8FE1F1684C7E5C8FC2F3CBBD346E567F73E423F23537DFD5F54C4D9FA6F67F7FBF27F74B439FFCF63B7BAB6CDF54F5D4D2FF5AF3C1D1DF36E6BB ++:807400008FF5777D3F13D7CEF511194FA4F523637DEF5FB4E7A1A4443E7E3F79F9286F4FE9E1ABFB838F2F65FE9754BF7BFB8787AFF1FF1E55BFD7F64A46B7D27F7AFA7ABC3FBEFB83B94F49F99C984F62F22E2CCF4FFFF4946F8DFCDEC8EBDDFAFDEC728FCD4CF3F7767F73F73E3EDFF3F37C7C5F76FA696A7FF3F67B7BAFBFFBDAF3BF37 ++:807480009DFFCAA19B95BFA7FD6FFDDFD7FFBDFD8F8BF97D7DEFD7F76C699FB3F36D7BFF36F25F4FCFA5F55C4AAF24F47A7CFFDDFD6CEE4FEADAE4F4A32F7F7DF68F84F5F5BE37EFFCF65E57AFD3F21F17FFF7F7EFEFBFFFFB7BBAFFBDFD1E86EF8BF9BE3AEFEFFF7AF6EF4FFDDE48EF8DFD7ECC4FCFFDECEEDED9601240011C01471212BD ++:8075000024122623412149034411A04120410481E044921187446901004100400114483C01141200404802284844800244F0FB1A10A42143628125A221001817C8809288535832138811D41A19754801814142172281245021830C81C882141188842C4818C4482AC148811648014445884918C2488584344845F1D4DBD024F41124C72245 ++:807580001F4932681F41324A1D24AB141F48B24AB981F24A925B48AF44B9A4F44A9543FA429147822D954F82C4914FA2C4814FA264114FA264192E4A96C5DA9E242EDA1F49E222FD91248F22F991248F16F99124A3F68164AF14D141B24A9921AB9451AB9443B24A3924AF24F924482B944F8294984FA2F4E879D084F51164E7221F41365F ++:80760000441789A7241D2CAF14D141F248941D2CABB4514CDB84F4421545F8429145C8956F8284D98681F924CA16F124CA96C14A86F52459C0591D2C4D1819961C19B64CB191324A1F48F64E12288F625941AF22B915B2483924AB9443F14AA24F81B448FA1648A9DBA4F5524C148482480000000010020000000022800100000000400896 ++:807680001400000088400428000000002902CF180341222A312485C2282128260419080018284E211E242AD181E442F83441828322088422471318D2888302924229D892E288821434684122911C028AD48131881A84312629D382B61A8482C848EFC9052C61587542384317484F8268C1314F3824F31288E048F4884453097088341487BB ++:8077000014841644744894444CD6A421D4847828E1C225351C482A51414909A3C34959F14398424C34C81629A1482D14A449E288F548844341E488F1482541CF1C0330E61861A714458A22D24152416F38812812A4841C9A21121246C8874795188332844B18835448499118D81D8C2A24B1482834C61648B248019CB5C5815448DB841157 ++:80778000EA41B288A3412582A3C227442D5E36A8C256F8477A90141167128C42B281328C161CA2482216088AD44831144243D2483A158B24224C183448484CE222E11492848D212A35184528A112116F12E88822D2C17424422892412216081F894444C8344F88D44A6183205848415F5B0122442100008C12820200102898A21022122ABE ++:80780000C11484852102478240BA18C2481604825041894808848004B04A21014881844008008C042CB4CA03241302205121301118B0822144C8412988C61112834294218B428E28490447241A4202104112D82AC6118A8448C291400411934404888329914250842823D184A294224441EF51064015021214211311029848104188D4129F ++:8078800028312A41258942C844944D4228C502E091024CD12862184847188D82930881404151244A2138981682141864A27024A8C181442CF4F4B260224A0200008C22815242C0282C24A8821A022082B248E1433818A082122210189248252AC418884220014420C448408C2122440881200180064CF11E9D102281024924B224649420A7 ++:80790000918A0011A082402118284478648862844018240AB048014C219582182601224E88681832601829C688184D4A1860228180A224009FEC0A2012C22A8C018118451808002D924145895482401421246114640022901810A24850421241129014298211026682C2181220C824804474584498880067948002530128478180A22580D2 ++:8079800002100823A4828092328B1A0020026281644A7228041882800241252A64118284831408005460888342280288E04126F8BEC524C0121D242447872E1C266414C9243182002F3118F4822D4211A6A2125E8948C9A542660642442E84AB414D2A48CA6141438533144D112588F51A21561288C52A86A3168E184571C846C428895401 ++:807A00004A874422C6A841F0AFB3208282C1280083E481A2128483024008482C4A084588428812110889628220028C012C0829082230268AA48212838224420812608B2082229188224C22D81701A02100000041122A0188004064824248288428000000104808400400A0164422003028009088008A240480044D48F30C2C022245628206 ++:807A80003018228489280C00852482A818169C244882B048922887428C92340068888428001028011A02894238184284400884831408169C244C88045F9C0C305200230284008458800A004186688448608828409884264804C028402842080020B72401830281480084880089280430844245F8E151D088B268A4464181202152848AF16D ++:807B0000248445B42482722488222863414CE22204B018A7319EA88AA8210042178800C548B848E484A41400281028D14C52C44B222A3228848384048741472248A051DE1C000020322400180000008200120000812002280020840A4C028002008400100800000040880440F86BEF406C82484800000016444424820200108878420A29B2 ++:807B8000A512588888804244114101C18C84840400800144444C82C2288881840050A290129F430884424A04000042204CA48128880000288128250818800822200254104888A2440044000042448C8823080018004821F028678082840200000044A022000040081002388488288400400140084800008002E0410838008400008221A0F9 ++:807C000014D71A0012000000008800124200008100400822422840080000000000818041088400000000828180F49FDF90188306620000803814414B2220820144844042422221210982680051191211483848C2420000E0883114414B822222810000242424121FD50A2648E84284044088010085C4A4A02200000090222584919888889D ++:807C80001024021426015088498424020000814444284E280000001012F2A3A300000022001818008148002008608C684142001008281890842022010000000082888483041840143828844841F0495F0000000022002008000000008446080022001024020020018200804108000000608800004244FEAF00222A820222008028088908CA ++:807D0000001054888D288DC88F82924CC128422082424844240822432102822841811890988F81088B8942830C1028518842484924F492E790241244001088A3118088282824840188122088048C16C82842282AA42220D4440A490260420040280220C888848100C088008E884608485FFC083228002249028084A151811212828200005D ++:807D80002064824220A2228508444B232822280012820000B0184188052041F88818844184221008C1FF230B2F227212C2122B11122B11C0122582E831F111118B988E898F84F888418F8424549111489558884B644E444D4449F22424224C02284554442E242F22B21282B192A1812B99822C5122881E1B1F11A1988E898F84B888E48449 ++:807E000024E48404488558884F84E4FC046F2252262E321A213112002592829CB11191D19E888F81F888418B4C42465911405C88488FC4D444B444B2642202004445C4346F22D224AA123AA1812B8982822592821CB11191D19E888F81B888A44C424280445C888CD6530400000000000000000000000000000000000000000000000000C9 ++:807E800000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000024 ++:807F0000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000A3 ++:807F80000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000023 ++:8080000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000A2 ++:80808000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000022 ++:808100000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000A1 ++:8081800000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000021 ++:80820000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000A0 ++:808280000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000020 ++:8083000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000009F ++:80838000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000001F ++:808400000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F009E ++:8084800000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE42D ++:808500000F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000000000000080 ++:80858000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000001D ++:808600000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000009C ++:8086800000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000001C ++:80870000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000009B ++:808780000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000001B ++:8088000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000009A ++:80888000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000001A ++:808900000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000099 ++:8089800000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000019 ++:808A0000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000098 ++:808A80000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000018 ++:808B000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000097 ++:808B8000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000017 ++:808C00000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000096 ++:808C800000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE16 ++:808D0000000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F0E2 ++:808D80004FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000005 ++:808E000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000000094 ++:808E8000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F425082400849E583040022448280C224448321212C296489204284811888A1820042008440C8482082B414042240A4244024D14802CA0242129F6F0B212E4830482D4446CC284166B424B414028E28C14B424460834CA268364F ++:808F000018282934841A88237818E448B148B81C84BC487828A4425A2291C8431DF428548D442E84A22E1430A430844C2262C2121A6E81928A21F88FA60024002584448801284C2262484C08442243110842001E4844A8368468C820B124280C80820610C84418482210044B28414004128D148888808CF153293042831228048041084404 ++:808F8000184018A84200841A223688848A848808001244488904C0248021818849584820AC181A0200C820128882E6822408D0910720048146186C422E4444008002000044121818002001008280018E4881424008418002E042042200410041200100D0BA0A000000482086040040844284028822881800001890188C0800420030484801 ++:8090000080C42C41000080224224022081218158A90021002200000000002400000000000000182800000000001400000000000000005F2B4502430221441843132411022400464854841D94120041C14912984440048D418341A881286044288C220882118C02202402481AE4812206221812305445F86573B011143211A042818CC428B9 ++:809080008916E81836322C84212842628282364C8883014840C2714A082E824A92282D18921E21414C8151424C4348D448D382228A880510941463698444432802F01EB770128342014C06C964422E4884AE4390421283145448592B99388422899124484644228568841E8821921A82F921542634289225A48310149C28CA822284243524 ++:809100003C4F22114488218192144598128044C4120016A812842C01A02124802842420841301444100830254211282E48895282009014004485C1282E12008218002024A924414C0842F0B5B2502417414D136026001221503819C412842113B14832818890884820A224240081159828184245082482181E2C4018C86C8D12D018A1217B ++:809180002412811218800118490422BF4F0C1921223228778187522E1127C25CF2251829E2A231411846D6A482F1142A17836F11F22154D3F12148455983288B522F14F311444B214863F62894272243F8224443938C25715266175921B124F418412352821AD44864314CA428AB5885A6346D28124C11D4270B24141C410225216341410D ++:8092000014288B61465228495428A083A44B12CC98148C5241278222241C54818D1483746264846D282378422288D91691142D198C91683A34482512481208211EA28B584425024024F2975ED014E141C2242D289F42C52C11A992238D34A55123162141F221145E2895C6B1113E41469941266814F04238324B14198282E149024426C42F ++:809280003445C82A424A52414C413C131E292A8135541D18490590186A61C34C8541F41A415021464921411451484D18188425912728891D240823558441C1C3052941C6841F446181954214521C1AA212236114581AF2142124CD21666251160922224C825184448424818D44AD4416C234812FB10F89C244AC028931289021444422C55A ++:8093000082134408418C820120AA122D1481A822C01484115891848C84912485924852804102381189C434002A9132C01220418AA484CF6C421344229129284440722138128901A4904211814502893332400810188836225048224288302221008018084BA4608950228D441288452226A8212842002F1248513644182E194B2145187C55 ++:809380002CF12D12122713A97212CA9E448285C4721664A2369C8C16485424819B148B52D31358C2CB256A618A2725384933285C62214DA11E4817218F1429C3B128244D484D186CC31829F41A828B52AD1483B414E488F432EE2012712A038119021221C48111803448112445183814A043281038244C420261141088013C042C61814217 ++:80940000842642342410C848292101824C2202414A228102560316822201101262119C51848721854118682219332413023141689024358484F488428C34421C15081A14815242493231628321047048425182460441B0628181A114284A42042F234AC224D0428412E848118C422298214420080083291248514843022244324C1104D0A9 ++:809480004204241602C0120023942A21112B1A00203C28403288C912820448F0335D149044595248282128212811408811C1181232241682A212806484229D22ACA4182AD12B6222301284222924425424816218215668142C01214213210242424A8211E245A224DF670B9011890480A6184721C022C062242835C442850114882180014D ++:8095000041C0842242884841008028C12800846022403448269418800A8B82C0A2101204848F2E0D00844290181189124841243214112A41741158415049902319518130121351818418841842A4901422141424C02187225C12E8129428465118301A488100188941722872DE4B22A1341E42504B100815146A812584C22A401814180C60 ++:809580006D884C5182611C6182C046C0641240E44621A1244124C4465141414CC1424711181C81211114646116143414C400F0EB4D40011001114444122480581228C0812014031C0420F142184888001007160A59144102402482840400C08244A082210028008144EFA603155241C0641487221185024400942181848042A882584648CA ++:8096000008A4402862114781C0188420461113C838A12481B02C0181102A91188C01245224101408BFDB0D8490418542448491434478C01480460100441884193142198451414C180111814AD812B42608CC012D411024C11587116022284C419328251152844A02108CB522016F8F4A7214B11674147C284A5A825FE1F133188D1CB2180C ++:809680008F317232D228D4813359C711971565F533814F14A44450F98D49160D4E6827A5974456B716F45216467422B413C2144F62F33C234D42C426763AFA6226EB4835711B88955E435128EF84F62818CF6385558E584D4CC5D8BB4311A3263CB24596288D16A9D27CB213D258761CBB42D88471815918AC31212E2884821B93DF4262E2 ++:80970000F5495461BB6427E1DF41E852F124238F82646489A4811E138E532F2242C918B336132F11F641241AC52E2E2A382F556889AE1F69E1283112CA7216A2254E2489E122F24E9FE022D151911B4475B57542815434753A222658192167234DA1CC7384F21922CD2AA5EE9191785AB2263224CF14E73A91482F8995138D9884EFA2B746 ++:8097800041766414155B43C48F26F74D1818D5F971118B552652A913942B3EA836B4C414A2264C7116E82722F473CB0022200266026662816A28A18616E82428E1445A816C3A116C32912811283128398112A3286182418261D0120121C01340033C081C28410588C08416482231486044FF2749E131F1331B3F31B123F24E4CDFF3F21BDB ++:80980000499F92F7495CBF16FACDD3AF2EFCCAD89F15F9CFCD8F8EFCB9915ABE11A82A3D5A4D6145D43A5424AB6412CF72B286F8E8A86B891FE9B418F918D32F62B582EC82D365F135131E14CFC2F275642E252B14C6F3AC2A2F26F7B99C2F69F11B9AAE82AF48A9B2EB91CD146F63D344544CA5FEFF81141F31F1335B3F315173EFD4F4D5 ++:809880005D5DBF61D5CFF55B549F34F88F9F1722BB74DF75F98B889D1C9F94F419AD9F31581B1D1D6B644F41F5197B3D2B6FD47E14FC5CC44FA1E521F598821FBCF458DAAFB1FF9AAA6F25F4625A4D36DFD3F55D5DEFE7F65E66CFC2F34A14FFD8F1B337AF26F6D2F6AF2DD522FB3A32AFA5B562FD6AF2CD54EB326D4487C48FA7F16ADAF6 ++:80990000341F21F3236755F72724E5FC6D7FFF91F16D3BBF84F1BF67BFE1FB3A29AFB5F39951FF41792EF93F15CFBFF7B71DCFDBFA1791EFD3F3751D8F767527F72DA51F17F56C7F77518FE772D6EEF1FC1A14CFADF5361C2B891F33F71F1EDF72F27957DFF2F33D3C1F72F34F1C1F34F8696E3F3EFF5B387F6DF11F982723AF45F3EC3C47 ++:809980006F8DF1443E6FC7F72E4CCFC2D4ECF59159341F31F32B27DF63F22727EFF6F63F31BFE3F26F3CFFC6F3BD6FBFE1FBFBEBBFB5F19D5FBF91F9EFFDFFD7F7BD3F7FFBF1BFAFFFDFFF6C7D5FD2F5297FBFF6F66E6B6FB3F4BE6F7FF7F7E8EECFFFF344DFEF41F1ED7A7FEFFE5242BF33F7193EFF56F27F15FFF7F27F66DFF6F74B5650 ++:809A0000FFF1FF5B79BF3FFF5F5AFF79F13F9BAF2BFB5A7A6F4BF1F67A4FE1F77E78CFC2F66C7CCFE4F5D66F80011C0165032C01001484144022018424007048048170480490124218422034243024846D11482484248C4442084824846C82C4224844D04802CF450E412829C12CA128144CD238F1112422D022518118178221122D21163E ++:809A8000E8146A8340C225241A3224811B4281211227A2C0114C9212100C692121721124022C41483214850418C0141A042E43EDD7E022F4112487221F417268F21124A7261F41F26A111FC1B26AB911F24A925781AF443925AF347B35F842B357832DB14F82C4B15FA2C4A16FA2E411F2265A9E212FA2E459D2A2E449C24A1F49D222F4C1 ++:809B00009124AD121F49724AF29124AF24F18124AF24D141F24A911B21AB9453B84A39A4AB9443FB4A9247832B944F82A4944FA2F496B1D0A2F41124AD421F417248F2114C87341D4C46D3C1F44A851D642F24DA81F448945D482F74D985F448875352587B4229F925588F14B827087F8224D9867498D136E419D286F491282D488E642D9B ++:809B8000411FC9724AE248722AE348F448131F48F268959E44AF142AF14A3543B2426183A764439388678229E9A2F1C4920080040000006041004002000000009081000000204208480000A028004480022488000081008D2A00150414B361122A615216120131404112F88212848721C4830484AC582C2C3419A410521A232251221B4225 ++:809C00009031843B8181451898498B52B042C1382492AD44C4830C2B414880914884EFDC0480C23A1A5224D083244178249838321628981E49722821061B212B928D741E2449022841781C51484C21B484A29412472620014D822C911450123181901820E92186E382048C7212C44416C1824F8C059021323C14D92232311322312F4F814E ++:809C80007232F1281414A911BC99324A1229F2A24A584D188F2952A4CA32128B2425417C133A214D123078684A61A182106281872417A424C3E582618225F288142694A2832261842D12168461299F2A074054281A9214118364418100008264222122815781184782284100858521114284A4282C1D5124190213918C161C16A1121100C9 ++:809D00001892421E488B144823244284344884DF710B430283A2218034281904124A018F242148A44181430113A32436681443A284002B4244350A0000802242C412118D121D2822121001100828412884301440F8D85600472244A5E56364114A0193F1AC4123E212088D16128E221D741B244F88924C619028857324932CE3711814B1F2 ++:809D800024D13492982D6843F21481264595142213F21422114D926C7189B442BA8AC2187CC8412ED6CC582A83C4A4E24A98184CF85292800281C581351318148D111F8A81E11842588429A1584F15E2530458218B121362224EA322811A42C23E222C1108821113024C4291341CC196444D994A028098484D82248032AC224B948141CF8A ++:809E0000680E414D224992324982B448220449346260258A4124528260CA87524E249048551844DE24D184444551618688C62417412614C434E0215221A41D2836022378A338185431722E8CC12D48800C1886F81561506849141188828A352412874812438376515C841C38441B42811289528246C485C0B8406A8246440225024CB44465 ++:809E800081460468D08264114CE144120A284C182866414AA182842F886144C0845F750F811A54482551844D12901A4CE42104618F214A0285A482C42504293142284245C29418414E82E011021F44929817A1245816180885E141429422C023424C2201244018B844B24462A183A224BDDE24134782A1124A7182814243091C028088A582 ++:809F0000141608122624846191288C04258A42014AE84182C82422282092122129210884129088882480814A944418004A01EF69081F646361C391394B431D26184F32714861483F2221D128C8416D484B848474C9A1212AC41816A9A4C5628227812D28AB42429E214C21DAC2F815626822365882222781EBB42C81C232265982826C4915 ++:809F800088811AE88CE2E231D816BC38E442FCF27930824003852261268449E18104284A7194887111E844EB820441A981E4441225140441861126742262442A014D1212411223140115941C4C048A04002AD442B1144484C42448008B3F00120011414CA11614CC84042728E01471911488C148132652819886688451D02843F81422823A ++:80A000008938142682E81128533285341812248183487448C28893C8888D82904884284C46A4124C83F245FCA01225450187221142C02211801321184268251D424184846129044C688242008430144A8898442410281124143981108A011800811849C2C230424048F481BE3081402EC54412223028288C0110444411442C51724948C19D ++:80A0800048471550211825B124511416C812508258134C140159344C5184498411150812193122802883A4811260883F864B22051A4424012558412B14105242588810F8822211130818224012141214440226048CA22187222800850228212D2410021C02EC024CC8848425166882C4C4F01324002741152A0180C1140026E82841410187 ++:80A100008A95885889E822188928E284180812508283038918143C12430484299178214E284A82CC49C22184C01C846668448391881E8480C811AFCA47D184045058141481481C344C111C024CC341C0114004A2163494008C84B414C24120F944224220081A8484041823410264288682A224282C041880012002DF9D0C502168100A46B4 ++:80A180005592004068288422440021424240120443518200480022408491244B41220010150116E81461152992421812212B84282180057F92095183484432448A1481228132412904128514C244856421168C91381D281342211115532411752842C85434441112176814471218508418144A026341E14229A882C18240084CF8FB7B245F ++:80A2000084B01294481AC81410184801CCE8C6A1242B1A10021B2488414A18068A0189688812A024C01180C22AC044C02280A24913012244881B2426044D2258C0142628123228BFF80C7D4317182D1AC5F24B9749751914C161481784C88E848D449B66DD82EF247454A4891D2A4F1915E1E8716C28FC11674D4A8D841E514CF2A6942AD3 ++:80A2800021D744F1B498474D5A427954F4284C85746291E87D541187C4AF1671AA384443F51414AFE496544FC7B42271D214F838A145F25E6E60439E1415F1131849C4824E61EFF267A4D7E23CF4392A2F1794126D94849E99AC51174BC64CD844D41CCA1165D58461542F33117236E114F21C2665F6382225D4332342B68AF21732672133 ++:80A300001F4132418F2458443BE21B2824B7699332A2822F2F5A28CB218B8232CCE4C1B24F43A21465FA1C244E44367811D58421B539E114B218B282D129F1958216E35D6142BD418FE4779AF52A28AF9BAB471F48DCA818B81AD185722CDEA97518E888DC88CFC81F24A6C27D14FB111D1A46B161D7A871B66D98AF85E131C1C81F15C9D7 ++:80A38000582FF8F348A84B9385BC82EBECDC84C33C49B1A878EB4B81128252128C9686482110824401148E4844130248301110011142114211425142490845014501471250145024702403248A44A54864400444484448441F1746D144F721345FE2F3247CCE369FE1E346F645463F26F67152DF27738ABAE1FC4C184F28F12E3BAFA673EE ++:80A4000068FCD4F2AFB4FCC27ACFD6F4FC5CCFC7D6645CFE67216D8E6F42722AE8C44CF8A4ACAEAB2F6EFE72741E3CBFA2F21216AF8FFD7C4CCFC7F4E4568FC7F72A248F89FDF8BA8FCB59888F81F32832CF88F128286BC6EB57AF8BF764444F4CFDEA6C5F3143F244666FEA57E8ED5CCE239FE1F36C6E7F67F313421F27F5511E25FADA4B ++:80A48000FECF84F1C453E7E8AF8C7428F8D8FACFA6F68E3EEFC6FDCC78DFE6F78EC8CFE8F9524A7FE7FE7E7EFFC1E187FC991B2FCDFD8CCBEFA7FE52614B65AFE3F2125EAF9FF87A4CEFD7F4AC5C8F8FF7687CCFD8FDA8E88FA9FB5C5BCFC1F1586CCFA8FB2C2A6BCECF27F8BACE6F47F4B4B4AFCBEB554CF131545D776D1E5D1DBFC6F117 ++:80A50000EA4DCFB6F64B484F46F762412F66F2D35B3BF5D7949F2CF54ECBDFDDF9E894CF6CFA5ECD3F1DFF6E4D5FDAFCEC7C5DC32DCB7F31D4EEF53F33AFA6F5FBFDBCF4BE3E2F89F3E3EE3F4EF62165D5FA3B3DAFADFD7F4EFF44F4E656AFC5FD5357AFCFFDBA92AF85FB5E96BF91F926B2EF8CF5CA646F84FC747CFE386F43F6949C4FB6 ++:80A58000EAF3B848345F76F48727DFF27347FD6F19FFD7F46D65DF77F71E553F167443FA435BFF94FDDD8D9FFDFD1F9F9F9FFFA8988FBDFF7F6BFFD9FB7FDDDF9DFFED6F7FD8FC15CFBFB5F4FD7FFFF7F76F7FFFDFFC9C5FAFCDF69D4E7FF7FF93755F51F71D1FBFF3F3F7C59FF5F56F57BF28F5DEDAFFF4F5EBFFBFAFFFDA98FFB4FD4F3E ++:80A60000DFEFE6FFEEF8EFCAF6EEDAEFE7F8F29CAFC3F6D8DECFEAFB2F1E0080014901148C4401141224122400134124C82440040044C024008800909410022E12842A0100221214122008824C02811281F02CF1C0421544028304184CB228C1446602884D48B014D42A8844A24120C9248CC4842412A4286F22012E129694849042C0120B ++:80A6800044214C14341149A841811A94884318129438502A4B4810942841BFE90C2D421F41522A1F41724EF2116CA7261D64AF26D141B66A9961AB9459B44AB924F44A954B422F14F934482DB14F82C4B54FA2C4816FA2E411F2244A9E214FA264594D4A9E244DCA1F49D224F49124C5F29124CB141F49324E1F48B24ED141B24AB981B270 ++:80A700004A3985AF443924AF4439242F44F9A4482D944F82C4944FAAF42FEBD012F41164611E28E5F3116C85D241F4481217418D94CCF44AB141AF143925AF6439A4AD1159B44A18D742D98594887DC2121D4A87495F2234D845F358214D8296D8B4A44945E381F24C919A7246F381284F24C1288F74F981248B34822F7463828D943AD476 ++:80A7800042E981D442F822482D948CF51A270082000000000000000012001003000000004501400800000000160180020000005012F0884280B524110143F428510089E111AC18114E184994C8CB41C6CC588B853082C92248C424460219E111041E2C4F8411D42828146421889889C1658334811893911A8CA148504848888624684C8223 ++:80A80000628514F8D23B4022E822088C41D648E141C8443048A3841811C1222AC124448B124A01492176422832188766844129642816B81222A32413F2112414A6C2122AC824A7464C224842488498144F8211EA42C1284386E11508FFDA0146E24E41014D584F9651864C31181B944F24C141F25489BC6CB11EDC84A4811688C52C412FB2 ++:80A8800041D2842458824D728C45267715D882E18AB14882A2257B921389386623C8A3CCD1689284842BC24185E441542886A8298E6C6C8C6599129FE50218602A00808138449088848148148022734824928280C942282A245181145048C8442522914411008B121331684462139118128180084C1B440428224644F84D5C002008880054 ++:80A9000080080000000000000000000000000000000000000000110010011400775E6024291241B42491281442444598323A4401AD8816921429E42A0854181AD2856C5C5028844AE21114318280D148E626189211444311E8522A14C4282382E4380921844925AD822D124412288CE897431222D1855148806A124608CD242B121AF48812 ++:80A980008150A25A9414212E8282548D881A33815CA41445C22883837441B986914816A42429682213C11441896A1A4250C4213A478378C29C2C5843C3842F2A011EA883A4487FCD060082008800880000000000000000000000000000000000000000100100114001702907268212C228242883421482521A118800434802004C01200A52 ++:80AA000041800529815284B02485420280322828006E828C94181188123014460420814128046F8E4621D414E192512444124C35295E2C89A9B42618B818D4187138E1828121F6281222CB1243D228A42C872638898252482381B114126241421C8152212C11D582F82493414D1230324215621D42A6D842948CECE24438449266FC3EE81B ++:80AA8000807622A3218D228073647824D184E288D21A9728899858119DA42E18298124912236644281B044B222212262412116EC6261441604190128278225348A8E1422831428A3848028C48A4882C99182844AA8429FE4480143511844442112812325211801901818002826684184203EE284C05850821A0220832214221281C12130E6 ++:80AB0000216B4827412D121190113B144CB144125448224965441245F8A9D8209112C0646C820345018483C822302881896248209834214F24084A2838148222144418301CD014B14822E24423028022364258486C2183814414342480364A4606124F6303A95224442C04814B34A120447112C84C211A02C018841001182524A641824288 ++:80AB800018238446813418288F4841A6841698144C0160884414224B4224A0422B494678140828214B24243F91060015880144A0215C12821201002D1484282014084019048B12304238241628022424189084228C4A94141923A2290041188022B18284018180F432EC242218914D12441E2C42FB215D22D018F2221A8C14223134869849 ++:80AC00002886B81412BA4488C148498694182A24957422842E4483F12411274843A21A4F82C824CB21444D62871C2E441B7822238111E242B482F32842D6A8242784478442248F57092C4114866222B02401C048881504848542482401481400538818844242112295128301E02225112681212822A11212202114A4146044434124810218 ++:80AC80004C82F47AAA702104B048120281400925144121410149A12121002848542014B42428014341044110849414284110242189C2422824490112901241844C0428416F810784424301914002A038882141D0829881811388A88228901910018148412224224448A0210021004AC2242883184204833862E11881202102001FD70C17B4 ++:80AD0000228C411154124B2114C19018128041C11250428118A0344824724120044A22044C2504C9014301167444A2614448442984813444422C21014B42C0241246A421486E5524C0268D429128890412291141EB4234832911D184031C1159281584282A2838241A8841820882328749E0419C229E4CC0884482882B84C4400594430219 ++:80AD80004384B14481116C8248242F3E0D86160542105128E081C22228830220398422242219020060224321A2680022280044508460244210428424614284180010C222A4412C3124441CF156890000102802341420612884002489A12824188200001004200240041290124028C2280000166341268222012484288502831482F6E5CE97 ++:80AE00000080441184111244621800C08121400286C18884113991218629C2814185051611088424003C1444011127211410B2210859111208000020018FB206204288224218011062C800830818A225082C21210142414A8181211214248403A08484808459424A081244429046C0444448411E4821846044F0CF7C1421D0230400188B64 ++:80AE800041288C942187588682062240E4221111611A274A86A412112A180311221A5818290915088C6C812D2884842958241822C48002301420020021411F1C41A1224B58944FB6762ABC1C52B857211CE233E183D929C2868E522B113D3429E888E1894AA8115E814E24CAF685237E441A32148C3145182B414F43518E4F21B1149D1643 ++:80AF00001B817E1A4F48C9281F4CBC22B85425D824C5284A7418E126951C4E144B214F45D4CCC11C83C2412E421FEE0B75B7211211887221981325B429F1896849F24281932911312CCFC3F11DA11F22E1235A94F028832E842E844941F481A44D24E04362CE289A492C7838FC8C1A449F84F62214A14F285122AF63A122AD912B124F686D ++:80AF8000A1212163F162142CA221A3E1444444D4E34A02A5D62E1153114A018D5827A129788B678A25D193E898E829C822272225F18B113BE21B2A1B195D118419F22C512B562E43AA5214499B484604668744944E2722C3742462451F4A7844385313566437846564C12C5488AF8211F244224D284B3743B58D05C01100442F1441641454 ++:80B0000020044200402308413084428442A442A442A4C2A4C224C230C12213081B482419342819B42888D4288894884885A24824482C0200706F41E221E1B2F12D3AB5FC4C644F71F313484D442F85F743927F84B753FFF1923DCAAFA8FA2A2BAF9951FF272AE7EACFE8B1A5FA99C59F39F8A383BFFEF53A139F365C36F7F2EFF2E845FEB2 ++:80B080009AACA7884F71F9F2C15F7AF8AA2AFF53FAEBE9FFF9E14FFDAB89BFDEE44AF1E7492E289FDB7984F4C169AFE8B888F918184F85D764E225A3464B576B449F154AF11513EFD2F52D3AB5FC4A487E733FA1D44EF54A7BBF34DBC2F9929B2F6FDBB2EC385B52C7B2FFF2D2BAF1AA1A2F2EF7EFC99F5BFCAF31DF98F869EFEF31F12DC2 ++:80B10000A5CF9CFECDEFEFF9F161C1AF8FFECE4F6FD9F174555F7BFCAB2FAFEB528EFFF3FB3111CFEAF9BE9CFFDAF1BA26BEB89F99FBCE5AFF1DF592868E9A4F45F574784FC1F3543EEFC6A6776F65F44E1D343E362D47FF22F22A2FAD2B2F14F7151E3794BF24F22AC2AFE1B8ABFAC1A23FA9F592927F2AF38B9EBFBBFBBE9FA7AB8F8CC1 ++:80B18000FDE7F11FD9FDE5F49FDEFC45C716F967458F9CFCE5C74F17F5FA494FEEF65CD84FE5F547426F69F51F9FEFE1F16E7CEFE8F2C9CD9AF8D8C2CD9E3F54F7ABA3BF35F71D9F1F14FC4642CB55E7E12F87F7564EA744AB664B554F24F5F717F03532FF72F22F2BBFF2F24F4F3F12F3151FBF95F15B33BF32FF33BB3FBEFEC7A23D4BCB ++:80B20000BFB2F9BF3EFFE3F9ABA3EFF8F9BA9A4F5EFFEFD91FFBF5E5E51F7CFC6F6F4F97F6F7754E63FFF6F67451EFDCF654FEDFE5FD56545F6CFC1787ED8EEFE1F1C7FFFFF6FE4E4E6F6CFDD7DD7F54FD7272BF37F7D3D97F34FD57D3EFE5F4565E6F65F5527A6FE57446FC6E6C4F45D564F552434001186032008422960886486389142F ++:80B28000C02440120113081348044C82C12421282901002F12011C4158128414C081121412002001001200003FC804432A210281C012122115382210082416D83268812C6283A0414A024A122214024924742432481842801202298116B41116926123064A21B142311490444A638281484E2414EF58072D421F41D22CF11124C3F611243B ++:80B30000EB141D24AB141D24AB9419B24A19F54A9243F24A9143F2429147822F14FB24484EB14FA2E414F8244A56F1244ADE212E5AD6C55ADE24ACF4D1242E421F4952281F4932481F49366A1F48B66AD141B64A9961AB9459F44A944B42AB944B422B944F82B442FB3448984FA2F4B747D082C464A7121781A386724A9121AF14D141B2BB ++:80B380004AD141B24A9B25AF2439258B1453F2421447822D356F82C4B54FA2C1815FA22C7125AA291FA264484D4B9E254D4A9E284D431B49C5B291522C1B284117486911D162C9242DB1F0429743C21643F34296842F44F936482F44E8A2F1558940084800000000440020040014000000880000501200A400000022404861410000004020 ++:80B40000021022F421243426468211427824C1141189712128321990444D82162C3898202121C128422A148204721AD24242B42431241E24281218284C01181222242A84186141128D2421C32234284CC22449C24CDF1E05188E34848D246183D18262A3806881A880088A0228CB126E82B0446241431264862149522A46840529B448011E ++:80B480001244414582F64438174626B418C48C9661229A245822122CA4C1414684A4851689F88FD1F012244E3823D1A24248FC16282E128C51181E288D9126644441892B9818CCE12469216E14847266622A60422F26A1162A15D142253518324B144911C4541E2C808307471E821F429C841227C2488F433444CC62644B124371C4FAF5D3 ++:80B50000384042144814B4110215088A022820C88241208A2202C03441448C240481454214847224C82400803222484F16411468C82981921212211225220848288A9428F03326D022010040E422812482A4120012408822012628443848224221812528C118282C054302988223022228C382B22281A49482C048884189290843C2148466 ++:80B5800042F087AA1468641F81D242F212682E192113014392C89B145227A48BC19E224E8A26B4EA5124A628277B4846C8461E6448626622554849218496264361C84F21984C2F8528F5448884CD8126E2B364842D848721C84CB618E44186A4481A34B44E28FEA51400135162181C3112271420E482A1144A1188A1184E824CF28268269F ++:80B6000084942852AC7648C246AC0262561862854448288A622828244E228CF214688584822CD5180B4C0849A8348B8449A64290484C064F710D2B3461A982B248C22C22122826A448912458278C8C322A1818842DA8588C1A04B0443148182878442361424827414CD148B8845148CA01E82D1815AC82272446D882C49823D448282111DC ++:80B68000C4D4129889E62A044481818C8442821716742298634B14212E4112818C3122C0444941824151429602128122818124882995584442412C312C87624962415018462491844820082023188284F8C7DDA024AB1219C264568442641372528843A212928744A842422830222C04282E488B49684602414B2856E5820522892A31411C ++:80B70000208401807C440844241812248C6584002D582F412432484BFE90124034128481000000003042611417810022604400918120252412A2210080881208000088830848F01228B024E18102902818F0BB74244B42211D2867815E2826E243B416C27483878E3212305CAB421246912846941222121D44C984B42A6421846A91A44D6E ++:80B78000628CA1922B16921886912489B12C0123E241481CC848241852A3D282C16C2A2191D88C028AF43355A0181A1284124408112450121A041B4920784A26C211C0244860222884148C044183C4184A12022A44046024302C4442481C2888B38406124A28112812B214A43484BF9906200324C0282283518243812111021002121221C3 ++:80B800001846280228002C051218202212A8422C31282692284148C05416B1480181908984184B1880228411041B6A2400411034441324143182390230813110A8288191801378B25441448904407228724886044A424814644112188C488D184E511242395A242A01218121414C9418487F634C221964816D3A642C41A44244002A014431 ++:80B88000146C02446042484424814181433438125244B014542820022221428100812200244140022011C814812285F4DB7840010081C284411C21240430424452320088C41A38131B84602611004DA8240048448648B884148888220886848888088242C92884084C28A28261221EF68082C32242838232220000100881290220022283FD ++:80B900008402002262260820042840048425F24412224C04D02984829624F08428204A4284822104F02F45400880011212188C91122C03002304421818381880842282C4828818ACE44374141804003E441A240646044C6285229285641445024223150220084227415F5F0EC4844800815062D0C112822841012C484809842928521260B6 ++:80B9800084241C09273440296222D0221431821C84C121188711131432141111304114328004400821F0A45400828C91286A014228484200444220A4212820B848028A04C292008C94244840384A4C2B048849684888A08480288408004E8422808808888E43626FBB0C1E28C06160188681110250282634422982311144400420D8423163 ++:80BA00004119614288112811C0A21488D0C24888240442180042C16CD418A824580046444434224C3222F08271A021437A28D284F38238EF846A852B46B08A2212724264442F247111962844324CB272F458442E352B621362642621C27B1E1E4E212F243468A34422D2CC62824B252A123C5157544CD8C99F4D4A7228B184E4C2D98482D3 ++:80BA8000B2841C98886F41B228FA1421C9F26A940083A93132C7121D123CE5C163951F25C5431A98183718916A36623E1185B48119A4BA8F25A8945CAA221721CA3518DB248F227534D862E282EECA24A81C5F29E82AD442EC48A2C88E68A7AD125EAA9F18FC444A2D8586E12BEC2534526522E28268418F72A4449F7446F22314384579B8 ++:80BB00004A62443AF4222445D26B5144AB312E32242C541429E9C1B188C21287828DB884197489F54448CB58EB449F213262AA7416DC489A54246B257F642ED14AD24AF1D5182B578D1C9054471E2F1801393841FF24F448142B92441E844F48A2144B4C4A7832F4758A504118158CC148144081C48180A8418849C48147813C1A443384F3 ++:80BB8000200986088C0118822008A0821129189192116B82908240022482240082249E482C62886089F017F314284FD1F11429DB7187518FD6E286F4247EAFA1F5B6372F2DF54858AEC4FFF9F18363A7D33F7C7D9FFF9711CF53F1DC5D5F93FC28142F817828F949198CF4615B2F1AF9194BEFF3F9389EBE16EF45FF25271F59F723AD4F05 ++:80BC000043F31F7D1F77F23232FFD9F43436B75C1F3BFA55911F3272A1F55111BF34783CFEA6144F25F858428F4EE446765838F88721DF264EF315354F57F71C1BFFA3773AF928232FA4F2323BAF91F1B82B6F6DF7C8E8AEA6FFE9F18726AFDBF9F3F76F6BB396F1383185F93F798F45F157395F12F685C72F82F6212B2F3DF9D3F7AFF728 ++:80BC8000FD3BFB6F6BF73EF76FE2E243F7377D9FF1F33A2E2F47FD1551CFC5E523734BF5ECF6BEB41F36F661611F7DF1C9EBCFE2F3566447458F25F46C44CFC6F47E2C83F77E72DE42247D25489D2EBD2C5E4FBFF7B373F42774BFA5F57FBF3F63F1BAB85E72AFA5F94747BF8FF956514B818FC3FB339ABF8DFF3FD99F5BFD65DD5F5AF8F4 ++:80BD000065A5DF71F57B532FB3F1B3DBAF36F4DA5B27AAAFA4FCE6CE9E36BEF69FBBF3BEBE8FCCF3B8BC5FF9F5EFA59F9EF2B7BF3F55F923A2BF98FA5113BF84F82CEE2F28FA44822FE8F8A284AF85BD66FAC48C4F42F31ECC141AF224641D1E9F66F27C4F7FF7F757747F53F75F5DDFD7FE33168F83F2D4F2FFF5FD6343BFA7F4EEF95FB3 ++:80BD800013FB38BC3FABFB8FACDF9BFE89D75F9EFDEDC95F76FE3B73BF33F2CA9BFFF7F67E5FEFF9F5A66EBDCA6F6CFCF1F79F7BFBB8BAAFEAFBD3D77F59FDD4DEFF5EFAE9A1FF6FFFFAF83F3EFECBE91F3DF1EBC9CFEAFCE2C24F4CF8828E6F4AB8F2FDECA84FECF864563F9C052901002502240040020014130180222124A12411282072 ++:80BE0000142294124A02424322440145014D114081248224C248348C448544840412286044F069D8001A3228B04C81F26A11444D111D482981220423042942D81811814A883884424004286528712602A4A08286B4286148218A8661C918CCF2229280088908B8412D9243E14408B8F08986F024421F41F22C121FC1B268F1112CA3F61100 ++:80BE800024AB141F41B24A9921AB9451AF643934AF547B34F842B547832F54F934488DB54FA2D418F8244A87154FA2E41DE2A26559ACE44DE2A2F491242CF4912485F29124EB161F49364A1F48B24AF18164AB9419B24AB985B44A3924AB944B43AB944782ABB44F83B448F9244ABFFB0347221B61CF22B111B26CE141326E4C326C442D6E ++:80BF0000141D642B3419F24A16225C93412F447321C8943F82C4B44FA2C5855DCA1E245F82A4211F227418C4435CE2A2F491248CF49164811F49326613396A86F446118E248F54D141B248BA85324843B24839248938248BB46B428B844F22F5FA722028880121400800402408000000000000A800004001400800000000000000000020B3 ++:80BF80005812F0A1B31449232221913426382316A1212782298249C248128972CA34241D2426E2442237481042D1492254482AB91C322400492124322226A4581E4888B028A84AE0A51828483C184F85383883BC141464458928D848022098818180A914818001832204A934149018818D813088222843C2222093628C9442524CA22428F5 ++:80C0000020282848C82414121344B44182828581752204411230C2281449F6495C80229C818438A6A84114388322C238661428D48493C28C43C8A82724F289622326641828302C4A7B68D4414584664148CE2A82A88AB56C918112C28E644B248E5236A8814634244C11CC984E144D426A41E127F817229014281812411227121648221118 ++:80C08000224882941A5048415C12C1248442002652582E5242A412222880022042140800871240C12842D02861818B8432429082418918F45DD40010088002280021000041000000444828004160821200218001401408000000290100000018490470A14A8191149024501400193424837928C1989058808402892281264128C82416C11B ++:80C10000482D114825041EA4800BC0882B28E0114898211822988C02482B4826828982742806818885F4A1AE80811118041D242062146C42689281004142226082182A0480982412CD421961A60012218200244C021C1148212102222148213082284247822961C440FCFCA3141004280000001A0892C05800000030144628021400901413 ++:80C18000C0A4A0121260888884882002A0818412A0482812000020082FCA058001101408000000000028100840284808001002281212128828008001802282228104004C0120018220F88B4D800200800117811E28814A28018908128C224548248224120414431268810080A22880023843E88102124901C08100A0484822188844478157 ++:80C200001842F094A60030143012200130921400251204004120A582004304000022000000008022420884004008290140080000AF510E20311424128321C1111E28A3A9484062884418222A154C88856A82C0441422C0180028228A21818A824314A82132498182220A4884C2233434004112184288CF9C0D22001004400840210110022C ++:80C28000810041284830848140440821282021020020A812008440482101001220918812852408B0CB0E0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F8004000000400428000000002180018800004001400848000006 ++:80C3000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000B8 ++:80C3800000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000DF ++:80C40000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000002800002282002008000000000000F08DC60000901410314800284608C1 ++:80C4800081144004445084003024102401002800004120C21400810028983048102892488418441880F8138F24431144145821844C9312132241A318206541B1B0824188051C618410182A04410021842B21E0410231811912C892582C2804210018124C084120028D24F0222A30144410D82411C834830490211E486085473184441844DE ++:80C5000012C4160100842041041042880343011426F82411002B148848301260841289B18482140C4C22312C82C7F41002414001341226214122080011248281480083048D2421460400200221204214024088494802228200004008120000EFBF092210029021C120C2284E11001218128886082242223021000000901400008001001CBB ++:80C58000016A282112C182008009D08414084A9244CD3A90131116454298181931388F4124012E184A41280418124781860189854488E2248224D1487A188204848F418214A112441AD2418F67C21818A3866584425829A434478423A21232221018F838CBC031142501A01216698143011B41838101000041809448428581221402C4202E ++:80C6000014042242112A013034221608488091418A0400478923A221628120048FF30B21C01424849141222E488B212022C4184A21A1818E188CC1A1A01220022242128A62A180417818040049A1211B4852174218B22F82A52481B04291424A830460C1229028467C190B578230388C9658199148D08481018426584825142A087012B807 ++:80C680008CC192149C436482230525B8143428AF1182B148D14192884A312841811424421A3254828C819298481A38142018EC84C1844C622C5F7705100A1C44840212141C14082A8131184014814804872243A114200C2922412841410490184384014269084932422490414961424014786802002112F0495880341410063024842844C7 ++:80C7000029931100001A448A010000881088042502484638242381542211AA21618244004028020090C2411E2C2CA1822A1408A73A146627C13A99F21448184181DC9245A3C2181812C72181C215D8221964489853A142444E22422B428C21743A22528443733421DC42B1194254285D88642CA2432483E812044981D424E8C964C4A64881 ++:80C78000AE694CDE4883F88F45004440041932681218124C5141814518024C016081896182508188848341026D18C05852AC041810A2294A81024C041E4460C11886081220D24221110880F4CCB224301444189014009018281903800218001189011351490089018D42481907420022448240C828C05880424208404808244481412B1239 ++:80C8000044F024F5604690124664223018602188484C4CB249C898848A84EC4225C8819828C84D699021106388219288C288848118A829086A880AC2414C0C833844291824488831488118F07DB350422400904880448827490800828160888181848308C18C1488341888814DC88B141189051A52814428841427848364898428818608D5 ++:80C8800084A018842CC2148068829F810B00001400001181F08118684884284302482C8601002140280800002242250A23014C09441948248411840125428812048008889F890A824440260112844081220284221880018400485200402824058C112485922186449818182883041092241001200223826222260822146FCF0B0016044056 ++:80C900006482C02181921892140000221C03C021447880228912842644A128002138002128802204830210247424082001224921F286BCB0412181A241441214290280B442C8449AF2188242463A48422C2888088800192C521225220888A0181280E4623484884188302414C8001488210020888104AF7702001410162812688128450833 ++:80C9800081188088A1129C2181E284228492816812481A821251212A2102481A820285810128C29028400881122200A01280081F3804161888148821044822481115042819E4112448288824052F88118241815C1240840114186081D0429482120020128844042823840421212508831822F86F282459E5886141443D1243B1284288F25B ++:80CA0000B839F28B1983B141A5A22784828B638BE293D28126F331A87B4317C66226E824E4837A647423E8A52181E283B841632215382C4489386883B881B6A8D6ACA2364185187D487222C412A5042F46A9AA2E81AAFA2B133032411CA155448F4421B14252281B44C9E112C6181CF8D818921E582F44614C1E898A88ED187188541819D2 ++:80CA8000B448369993F41AC21C91C1CE9C2A84024CE323B182B892F282181DE46EA862293961C8818A59422D482C92A243B228D18462814B5181AEC26044169626453A348CD48191481F83019CBE43F8C58287891C94D98B8686E891A15CAB17A7888B444AD8241EF8111127822D5382DA768884B6D1A9583E42E789E9EA65D398B934026D ++:80CB00006B418C7844CC44878815084E4ABA588CA2A41E2A83911A86047F72489221241912982123143162126712167822A1412501254158129022A024806228288082C12488442281108118811191121D442951412919919211291984198419C48249149844F0D468247F17742717FB2A22BF967473DBAAF43A5AF7546F72F646522F2797 ++:80CB8000BCA2DCB2F5CAFAB7ACAF9F76C8FED3CFBF94F4811997941F96F147CF3FF6DCA27428D9AAFAD29B7FFCD877F7AB68CFE8F88A491F1252642FA1DAB9F813F7FFC1F18882FFFD775FB558F58C46F7BC9F11F3BA94C7E8FFFC725AF69E9E6768E7488FE3F3D4944F47FB9C1CEFCDF4B9C6346F66F4375FBF22F23B772F87757BF35B62 ++:80CC0000199F91D54CF63E6FEFC4A5E79F58DF32F4CAF89F8EFFC85BAFEFF7DBCFBF95F489BBB7959F94F55D5DDFD4FCC8CA8F91F54ACAAFB9F1DF5FBD1FAF9FEE29BD82F519115F75F65BCBAFA3F89BEDBFA3F38F8FAF8DF579EBBFB5FFDF3FEFE7F9E989BF9BFB9D1BEFE5FBFECEEFE9F99612EFC3FB3C3ECF6DBB56F1FCFCCFAFFFFE2D ++:80CC80002A246F45F614572F137312FA5A2A1F91D79BB278F359331F18F6D3F49F97E425D691F5CB588F9CF5F87A3FDEF4F8DC9FAEF7EB58AF8AF6F9D9DFCEFF6DCD9FA6FE2149BFA7F7FBDBEFCEFE99BFEFDCF4F4A62BED1F98FA35376F69DFAEF9BEBFEFF1F1BA3AAF8DF74951DFF7F67AFAAFC4F48BA99FB1FB1E98DFF4F4CA9AEFE165 ++:80CD0000F81692EFC1F1BABA6F41B4B6F3D4544B986F224AF25775E77127312FE7D3B3F61874AFA2F27B398F23F7B969BFE9FF7BE9DF3DFD51413FAFFDEAF98F8CF5F97FAFCDF9F9FBBF9EFFFAE89F9FFFEDFCDFF6FE6BEA9F93F7FB78BFBBF3EE6C9FBBFBDAC8CFEBFFAA78BEB84F65F6BEE6FFB3F8FEBFAF93F3BC3CDFFFF76AF8CFC564 ++:80CD8000F468E89FD6F67A788FA8D29BF86C4EAFE6759CFE22A2CFC2F2BA9EEFC1B5B2FBB4A4EAFFD1418001188001000014121412148C049A84220920044211102194924229012A282402430221A08248224822000000400289228922F82AB2708401141514246112848F1201188C0684001C59814E14222082014E241302198582811253 ++:80CE00002405C0531245012F32014E1340012734400346032C022816088440F18199C0421F41522C1F417248F21124A7241F41F26A121FC1F26A931F81F24A9355F84A9343FB4A93478A2F747924D812F934484E914FA2C4816FA264116FA264192EDA96C54A9E24ACF5D1242CF4912485F29124CB141F49B24EF98164EB141D24AB941957 ++:80CE8000B24A19B54AB924B44A7924F842924782A9FB2448984FA2F425A9C0421F41562C1F817248F2112C87241741C726166C7616D43852848F3431348F3461824E1751987B412F14915518696C116D42141DD216E5327498D522F5512C45B21146F211244B141D2469F111646B141F41F242941F41B242BB1592924B43AB9447832F2459 ++:80CF0000792498B86B42A9F924527F860B004800000000000000000010020080020040014008000018000044000000120000F0E93B200144144528D42863828321041A0242182C44F8449813A141C4422A114804857452318852163C622212284AA121C97121D484110684471149248243D181D82844744252244227288D242245082F571A ++:80CF800006262169836D222CA62144121D46818D3125381116584927189E4425B18842846391481D442611A21226E8419227A88E14CCD142C61537422D8622ACB981E282912813A1862D11A724A44249058C4428991C18488CCC418CFCADEA3011528F2251412D6E70147832985C83343C232303C35112CB41A9E5912864828711222715CF ++:80D000006C22686193E442B824843BE74D184B215D121966CE22CF12F99228C903111F447213762432382635951032482D84EC85782A968843E481F8CADB20024128A0612240031484141E48148A9482538832144C81A41445480189A2128391138584819242284D1212E90145038362819848830423C44883D4841422112221A4428148E9 ++:80D080007BD570246141141E28D0419218150C1F88044061818B84842411463221819220084100811582322400E012694114281C082C1141A228608885A14842122C029812882608F0F15F00282722111C36421722721A3634AC2EE78825041B848E688BA4897144A221511678287128D422047B212A8163812361884E84189021382D1142 ++:80D100001AB28291218743AE4C81193A22291832912F84E244C8B82AE488A424428E48A4CFA50F11472317221661122594199B24284EB48322561884C088222F14C24814288A018CC824442133223121C01486388490211952212691212399212D1CCF2A443821231219324146382418C018C84283048FDC4F6142008922B441C22243215A ++:80D1800055814A3812D8584E8819E4843888182F44D28241C51819423842901483C2121E2A228024A118168423A118206112808A788882A8481A38322CBC28A887C222838248782244B34D9214D042A6612A81D2142451289032922E418921D182F222184B48214164282E1683688843A2215C58844883C262121D1226410827834F819299 ++:80D2000015244665124CC84113224889642112524DD88742782321049E6B108832211E4284112314382D27468504B02A08830234C02AC082C0184C641816424438422D19160382288A64C6A141602816082072325882A1984C2228122822141A223388EF620C24144019045022481CA1214648C8144425842CD481C1148A4218C18122280E ++:80D280008C042B12188821890121121213CB81902882B01898488248001260A8A20082488442EF670B2D2525C52149D38465334A42B55EF223141A921A8391CD81E3E182E822B495D48291A28CC8218F42E8C8962856B812E251DA86B188353A8932923D22582286589647821F4A711A92449B812CF698428CD4827891984492A48BA4AE44 ++:80D300005C8D64841AA424C8379780A4212415382240C248148C14CA642C28C114222724178181434214041502114C5224812C44412205122E8116F422519A824188182162C826D54102281890B212002BB49018A48F1C032821222047B211322213F42282100281248B2118008628810448A58484934B288F28C4242C34282A04921291D9 ++:80D38000456A16224226E894282224212468142782C6C21810042880F4774B00701612010081891238448AD224012B4820083260249088444200200484A302812848A0381A1258438322880184824419828808100800C5022F2E0D1384018185426181943281708144834418714812247822F624889100411C02100212002456082100000F ++:80D400001502118614644820311812121A684100121644F461EF0010A121A0212C825422112C117842084CC18A20024820824148121832821A68421429231122782188AA2125021A04118280889418109144844182121A1834A222AF67088222384A82C222111301601A182381091A9412222B42152221A182290800182348814144048A16 ++:80D480000110C114D018C114C438842416889381872382188440040046F151142002A412810070428803260480132232518748A6082A081CC1982422112A01141CC881321012022224908818008822812508C082002225022904BF18032506290443711198442230444880088A0488444004B0180400C828803B681068242088CC84814984 ++:80D5000042842218D442022008884548242408C48088D8A30E250111119048009041178200702208601C16B841E1889219228424104818482C88A8218150128F2142B841C8188952411A9228848481248100C14B28450288438221FA7F5960841248814821808401635141800266E1449212008018C2831887129818241642444801C02866 ++:80D58000D024044188904241294C42046800000044822B24444F6C08212B19258263C43D717AD21AF42A3A3B728727AD311566842B912D226E9267162F81712A233F28AC98818554A2A19B1AA9F11C847F7894222FAA6121828E132F83F298242FC251AA2F1372A5EB8AFA24382782868A52282BD887A8AF44CB1A4F44398C4931144F42C5 ++:80D60000D3548FFE1F38E034C622197253884258F11F24E214744892438E822351228386A8288AB464B881D882C9912A67B12B841F12A23114AAE82833288E848381E6A1B9238AD121F91D2247528E141E242961694F4816A8943E8C911711414331121644F48288828371C2F4268E241742F03C1187128F23753892122E181286DD543B14 ++:80D68000218C8DF9846A9F97F5124C1F41B388F2546CC9F2D3288379C854A483E4227452AA2527961E3897874C7268B82224A48C67928A84774D98488F51D4199C884C7C9A8845A9D286F888C4878A2C284206E243F267F5504122C440044C041644E1880496084114841448141A448544A14814581C82448105489014110018B042012326 ++:80D7000004213042922744304210421862814284F09F37345F57F7242FBD254F43F66C665D77173255F534163F14F2E642EAFC48C6CF6CFC8CCCD794BFCFFDAFCD3F18FAA5FD1F3CF86DB55FCAF9534937141F16B239F259CB17B4872417BA6FCDAFCC45F6CE473F3DFCD18B179815F1DEC73F23F389EA3FF8FE4597AD422FAEFE4252AF3E ++:80D78000267547F6CD6EEF66FE2422EF24F464688FA5F5F8F8CF86FC84888F88F87E2B141F35F551491F51F23C748FA6F71278D751DF56F44C663F34F6D7549F95D52812E889FBED999FDEFDEDCFAF39FF8BFB2F9EFAEFAD5F57FDD559C7149F1CFA79739FB5EFBDF978A26F2EFCFFFFEFEFDFEEF287AF3F39FAF1F21FD2F32D658F3DFC7E ++:80D80000EBE6AFA8FE86F7AFBEFB2A6C6F62BA92F16A7E6FE4F89FBE6F62FAFAF26D126F86F75C5E4BFF6BC64F89FDDCDE9F244DF271732F32D73FF21B258F26F62A73FFD6F249281F23F11715AFDFFFA1A19F95FFD8D88F8CFC4D69EEE43F19F792B15FFCF592D1BF13EB8DFD859D6D4D9F92BA787619D312F43D1F7F7EF496B72F29FBA4 ++:80D880005A5A2FADFDF3E33F185D9D5F11F39C877FD5F789AB3FDCFA559F6D6C2FEABA82F95A323B519F29F11E9CCFE1B1DEF5FCF2CECE2F4ABA16B9FCEB86FB165F347F75F73971DF33F27B35CFE4F71A7BBF17F27D549FA5F74767BFDDFDB9B98F85FD5858CF4FF9E5C11F4EFCA557EF4EFDCDFF6FCBFF39399BB3DF9CF584C89DA99B4F ++:80D90000239F3FB7B2FF9C8EFFFBFBDEFF6FE9FB42482F3DFDF3E33BFB9FD3F27D358F3FFE9BBF8FA9FBF6B7FEBBAFCAFE68EEAF8DF5DCBA3DCA9FABF946C68F2DFD8E9ACF6EFFD4DEEF8BBB24FABCF44FCEFFC2F680012140022061122022410180041289028922088210120881490943122802290923423824901410046088404821483A ++:80D98000044400924E24826F820D23082A117142C268141B21A1112148AD1392241698B822253414290189131408282D122062182D1A8021712222612217411816D81831811886081220581810084E8243018068124E94D024F41124C5F21124CB141F41B66EF11124EF24D141F24A911B61AB945788AF4439A4AF547924F84A914783AFED ++:80DA000014F924484E914FA2E414F8264A5E214FA2651D1FA2645DACE54DC24A1F49C2521F4952281F49B248F1916CAB141FC8F64A911F48B64AB911B64AF98548AB944B4AAB944B42AB944783A9F9A44889F9244A4FA9094D4A1B41C5C228CF1491616B161781E7241B21AD151FC196A21F89F44A94A2AD954782AF147134784A7126F8CA ++:80DA800042954F82E114D9A6E814D2A4E11D72216A44BCE15DD2A4F9C12CACF191648D424CC2911D6CAB92CCF42A911D44AF46F11164ABA41F89764AB4B4B44AB234B44A3AB4A9B3B6948A4F22E5360C0000008002824004000000240000000000000032004818000000604180024800840000F04B83002C525815721148C85511466219FF ++:80DB00001582A24818A7218CA3284F8132B8178141832183A24285C222850190142D925A921243C31412223B128CC2231742152CB382D51A51126051818B81E582911612A92C81C8A21F1805293487A012468651822E1A4D1987228AB311588115A8484E8216AA84632472BA0146DC21581C237244C812AE4D4322C224454894411125545C ++:80DB800092E41576C884A1C1911422AAD1813C8A8642A4124962A2444446F42C1149F4B5DA346044941C3115A14236A2412DB11CB321782855214A71E28AD268A2861F82E17823B158621B46638A478225238C823397256C418F4431152D1489F2124345C1A52F41D2589828395DA61312D943C1A88D12ACF114228418AF6894544F82E9B3 ++:80DC00004BF4C966C042191286324A12ED1115581C842D82124A68818928D128A9498D14104A4844D2484222C4188D254144225A1292210025C12C87228C44A1411C012E11924A68882443C824C036410000DF15090018198281521A2800181528045C116424260817888140312100004411420024001604442E111120888186012011188D ++:80DC8000B44228A214008281F0C77B241564324124C95482901343F1468888121689A948257A11C4118E6848D6E41411287442BA2854161C51A24B214582A2122A4136451D821B182542A88533D14BE51834183436311121111A48E22124A212162CA1288D44BF120F212221284618522A2A5124438881E184818849E224F128112819A8DB ++:80DD000094109121482B42411445D2412134222043827494B11318323BCE121663851CCC48C011190191444E822C2324432C9988C49FEF0751114C117112C4281114184628184921D114548615048B4889446C15842C44484A81118A42043824414501400411605818321991229012A08121481A02182022745A0F912005801342623285DF ++:80DD8000421806A4A09442460184D024418168811B28255882172A804441B81838213322426D1284D02842D284126E112241260123A112819223B2543A824A8178EC476342839428E05112C62494524A2152348480514840D42C1104A4628127218211165248F0922346470610984424407288331426A8492A44D8A1A414CB8428104212BF ++:80DE000084012B2481F01C190051C0114881812A41184181813152112447A98522084160C14242441800464C28830D23815122128C818121A81411120081400C89042842400842DFA843D34112E18192111D64444C827112193B28D082E1A481E1486144257298120C4D184CC582AC64122D1823F1812646CCA976D4A4618929333369620D ++:80DE8000B132D0187196CA38AE518B21112489D11C0829F112288572B4A221728B421688DC760C4004C0121E28A11D28621A543213C12228148C949A5D484440048D218C044114A481245225220C1184904615D828212882542E4CD448D18126845448200480C4848242F07CF50011241123143C42001338429266761402818304705491CE ++:80DF00001252481011028A21D11AC8242CC84219094A49A181418860828A011821A0C180098088140C23A181222FE40862C9814124E21104848C044098188E6822418A1112480810A81C8287441250184248221008261AD84102841FE82101888052222400212F81480820240AF05E3280014112812011130240022136490286222114513B ++:80DF8000421B4141418074884228322283A841304984801403284145618113B4844141CC51840029022A0400F0E3860000402114C844C01416C84C8002821C92448A24684886A8288502D0943A44441C68111214C62281682586288408C822338628328820182202B03208218C08A46F48068259446281A1854204256248162841284164EC ++:80E0000041D028512116812441244412045824482184121811298184411384A2528AC18818421224400120012284608223F2F4EE404C8884644112811014480228112542012505004601241414502218121140C14240085D4290688652814519821213631114850229015082B200606380041A0646021964128490428823140881690C447E ++:80E080005092002D81828C918114624124508289424841880424428002004882A05818818908244438C8F0D94B108551484141441C11261408004441119981E1414804445115141461445414890131002C2454124014665141A014C65118848D41420028381EE24210088D924F1C081608190418148054241311D1428481D281B1824194BD ++:80E10000C82C26B88433812B1880C3421E821024822151182051811682344826021C181A011AE86814E429128185841402283012F01D1290141F1901CF44D144117E1AF1416AB0863112AB4DAD1257415F8171173882AF14718CB596FC1711F7414B1543DC47D24264238AF1211D3F5269122FA318F218881F15F441D123F4A48A15B6A47F ++:80E18000E883E8889D113987E32382BC46B4C25C2A2B114E2812EAE724B646232283F22FE514267148FC1C172483F1511F1825558287B185CB924CE688E172D278F1118F4F418CF941138EEC8E9187529D958E831711C4E3711CA2444394194AA134A56A2B9D591148AC52717735CF6168991F31B4C371C35BB81D111D1824A3E98275121F ++:80E2000052C22AE881C94236F8ABD3E04514847212F16348481FE414F44C461D844A456887AD42A18AB86C65A82F255648A0441F28CC42704CFA45511F749C428FA9F21332828F81F48243182116F212156794A7446B3C8F42E29AB248A88C8D8589F1919416E21D8886F18AA2888342B88AE2887988F2942C8042814281028C42011C086A ++:80E28000884888483021608A608270210817823021008A02CA028A028A42A128001440226132842601244002248224484448F08C2F141F16E4977118FE212117965F17F51C146F4656918FD4F4C4C2ABDC2FABF5149D4FC5FDEAFAFF98F9C2E2ABFD8BFFFAFD3CACDF5BFF3AE34B8AAF96F734375ED2AF26FF84867F6E7968FA3A88AFACAE ++:80E30000BDFAAF573F13F898A26FE8F28F8DDFFFFEF1E45F7AFAF9AB3714AE922F2BFDCBCA3F3D7D5BA9DF8F8CFAE8688F8EFD3C7E4F6CF8DC8CCFC9B972EE1141F165414F17F5383ECF8262465F37711FF5262635EF7DFDC2C6AF85F53AF4FFF1B957FEEEEEEF3BFACEF6FF3CBBAEFFBE9CEF89F99C959F1EBFA4F848CAAFF1F43CFEEF98 ++:80E38000E97133FAF392AFBFF8A2582FA3F6F8F82F2EFDE3528D262DACFFD4F4ECEE4F4EFEA5AF9FACBC83A8DDBF25F5FBFE1F34F55B28FAFCD2AAAF8EFEE8DAEFC7F7CE8CEFCDF9ECEC8F86DF6D42F111355F51F5393C3F51F14B69DF75F5327A5D4D9F94F4C5D51F61DD8AE521F394154FC9F18193FF3EFFCAC62FCEF8B4D48F8DFFD735 ++:80E40000C55FD9FDA4D78F98FA47C5DFF1F15C5EEF26F76A623F2AF582E3A5F86A6A2F8DA1FD3F11743973A3FB8F8FDF3DFDED6CFF7AF3DB9BBFBFF21BBFAFA9FFCBEBB7BDB79D8FA6F448288FAFF7CA582B77AF88FCBAA88F86FE2838CF684EF111355F51F5191EFFF3F24B6DDFF5F5377E5D4FFFF4F447573F29F1D2DAEB11FFF971B7DC ++:80E48000F2AEBFEF3DF1DE967FBFF5E6D26F55FFDCD94FDBFBE5C7FFF8FA4646BFF3F6BC7EEFB5F5FBCA3F23FD126229F482CA3F87EF24F71352DF6BF8278FFFD4F4DDF5DFCFFDBFBFBFAFFF2BAABFA7FF73FBFFB5FFCBCBB7878F87F55A3AAFAEF6EA7A4F67F58ECC8F8BFB88888F84F6A6B1901490145016844048C1482412C048241659 ++:80E500004864886412463481004411812187441881180042002B1210C44822001648A241141E48A04128848582041220F8A717A04811608134841C0124118901A5321144112978117842021C18A414118845221542512328244AE282311127221150416712826D1386C893481C29411211283142369882800228247FB7063CF4112485F375 ++:80E58000112487141F41324A1D2CAF14D141F24A911B21AF24B915F44A9453F24A9543FA4A914783AD915F83F448955FA2F448855FA264154FA265595FA2E559C25ADE242D4A1F49C2521F49523A1FC9324C1F49724AF39164AF34F18164AF14B911F24A9351AF343924AF243BA42F247924D842F92448984FA2F472FBE032E4417628F3C4 ++:80E60000112487121F41722ED281F24C1128AD951F41F24A825B61AD9453D24A3BA5AB3443D31ABA37D44ABA21D158FB23821E242E1A9E255D5AD6E5B2655927A217C82E529E442732967C4CF19124A5F391248F326148AF5649F44A2359F24A1343FA4AB243FA489243FA4A842B42AF44F12452FFBD0900000011000010020000000000E6 ++:80E6800000000000004008480000000044200800000040015F840112248941944C91251744D12904484200212E141781A5328483012A11648246944279E182013126E2819AD41B121426E1412841B14572447151CA71601184841E44196441224129B38AA1A18841443F3D0A7D42174810219312167869B228D142E181648181E3588445EE ++:80E70000582B4213783132E14E3946486248211382D416A82589E644092849B4446A61BC32814D228123928286D81C7D88E2113451250982A72498C04281701821D85648A24146D582118464B185B4257418C2446F8124A4424D88E4412D2D871437882749272B8D21221664AA43D8217414E2C128722239F1A3B244BA4451144786E3A98D ++:80E78000411952824E251FA8A1424781D3C9191782AD45199484A1442C8374B222781CB114F8F11150340011CF22013C41782271110816582800842C2101137248A1418B1424442C8492411C822514248991212A3C11263381411D642582D418B9814482A4141220E124221962898100F0ECAD00804144419418CC324680318118121440BC ++:80E80000B21144341142A03400301884142322813C48882002414021484128E68194181A140225924427448C542A0086C824F077D3B0471154842167821993A523512198813819D4227894D281311481265A284C9131D1144632495934544AC1122A381E1E2447812E421B182B218E11248F28F12816ACF144821C5842131C32112118819A ++:80E880001E282983F448822EC8788381F2BBCC901130186199621197288B211429C8181B82522D82594949B24841523842E0C14401904858468292228A8524C92282121D84B08AF1822412239C42A3C4C1421911221162838B21A123B828B8686981F04FE7304641415042266443644C840112111224124911312C184C6113190242AD4149 ++:80E900001D14C113216129C48D344528F4211222121061A194C41B821664A1122124C04E46344242872442C02422AFD445D14802002880415148701247217211C2182470129428814124265548121948824624C5988561844382B488015296E18182217A41984224491488D122019244006488290446F88F1D106944D02831442512041274 ++:80E98000654184210245C1298448542F42E11854241A044B212388C11483482C621149013183827148514A2430584164C9B28142038A0628262852842A01A741CC021F780400261A45110C272114803228000012141824288C412804855414A0412220241242542226C6242846D4240A211D18128C118208002B14252C08260800DF9D07B6 ++:80EA00005444ACD258716653286C81D15A511239322A6031518513C8414C322A29921C57814841251D84E7483164AA91484FA122C2478AD262322DB3E8C3B484A24985C64B8D14ABA4156228C821A6F224488742863C14266844C4422FD605220000441001441813019018222C31148D1143E154084A52842860116183C41881184245022F ++:80EA80001812181E242412A722199414287C4188A12120C112002229688128A47FEE0621942548429224241284194131111413410148008628D241854551C189A4248F380421006881214140C41245088CC245ACC14212C01880121284612226C214C01C26F84D3D304100424922011100001800400123512412842186220800144FA104AD ++:80EB0000862841043A440C2002232411E218127912422418120443285184508410F414E310B142D1210112004012041200184118440026011114412C71210C0016E1240A4615449211122190194911084C0100288D4170260A22002248B06E4501106251358814298181921A2C34284D1881582588C6412A0110160CA624011A0420C188DC ++:80EB800090118C088D45341144004220342122111624062A110200A1582F220696220141106441112884144011E41261481033121902B98101902190C918A513091848421111814145184289C1235081181425C12218212485028C8101421FAD43024268182825811262C1133112151214131212C294344842708242C21A412C8501182414 ++:80EC000015621418241624954211605150224C181402800128182841386502691178FF4511042415088400804242848102918B14104C024C3C4888880000008444A80080021820081028938200D08408008308848288BFF80330258581421918DF481232820024001641B112041281501C83C44384B56621C08183211638824A1141542102 ++:80EC8000A01825C812D4228C2264B2182311410841491144081443B2560756081E648418288094214D48844C08E8410094484794168152221684C1418840818484C1A11618C548211ABC48013047B04DC9112246149128A3058912081830242582F8A617343CF4911247128C518D1F425322D062713EF41A189A51828B412E1C9B15AD1A8F ++:80ED00004DDC6D412F4CB113D1185895D1175829DCC97552E221F44D429324A14C8B8437147CD564F118937449F91818CA55B947C41F2AE6B1D1124498117E31ED22A5F822244FC2E2E25AAC455414C5F4CF2C7041D4C296183D421E1145F8192D1B3194AC47714242931214457751F1132246D825C242428F457582D5A8F81D2C67111F24 ++:80ED80008854132B91279189FC1A8C4F4907E21785553411974135762ED542F422A3CD184AE22248718252234E184B224951228118188D894E38FFCC052B1146F1132ACF51F22222A314D4D2B43872811151115B3157583391824846B111F138498F12F2355C2CE8A13C4666E326D2188941C9121FAEA33235F814565351128CD282752207 ++:80EE00005A1417A14B119B592751BB421F81F3133616D98CE442C81496AA116B1127418F82E241F5A2C2BF1B0B100420384420044B84B048088B84C084114C18D1481841140111811110614811850440A128148E28418A42A1281480081C081C088884889088908890281F3241F164646F41F128261F71F2644B7F77F75F5FFF66D37EF4F6 ++:80EE8000884BBF8DDD11F828DCCF98F487918F84F44858CFCEFEEAE9C8CFF2E986F698986FC9F886C54F64F756658D828F99F1D451CF18ADC4CFEDE9AA724B36737E9C4F81E92B7EA8F4A78EAFCCFE5BBCAF2DF47A8EEF89FD999A2FEBE881F9CECEEFABFBB6BA2B91CFA9F9AEAA2F8AEAC3F3F8F4FE681FCA46F361735E128D261F75F2E0 ++:80EF000035237F43F35F5BFF44F11E5DDFD9F4CFCE3BC41F73BD97F4DFE89E82AFBCF9297BBF9BFF71C3FFD2F9E6ECCFDDF9C8D87FF8FC436D7FD4F4D1C39FBCF5D652EF11FDD849CFEDF8D8885FCEFBF4827FC3EDA3FAB2A2A67E3FF74B6F3FDDFB5FDFAFE7FB9CDC9FB1F3332D7FC1F8DAEAEF8757A26F63FABEBA4F62F2323C6F43F3BC ++:80EF8000ECE4CF2FFF33A3146F47F716448B22FFD1F3292EFF72724FFF2F7E65F765A73F59F1D94B3D315F44F88313EFECBC5AF11D5CBFBD7DEFFEBF1DAF82F38888CFF8F98ECDDF64FE1F659FB1F118199FF5FD83D3EFF6FCF8FACFEAFAD3CF3F3DFE1252AFCBF38C164DBCB5F37A49BFD7F9CA4BFFFFF31AD69FB1D1BAF29818EF65FD94 ++:80F000003E1AEFA3B19AF1189AAFE2D382F1A6A8814FEEFF68A8147F73F71352AD327F71F339B7FF47F75F1BFD5C6F51F155A52F7D759BFB1733FFD5F9FB594761BF35F5CDDFBF95F1F547FFDBF1ECFD8FDDF9C9CFFFF8F44F677F51F799439FB4F54ACE3F11FDFC6E8FAFFED8CA7F73F35266BF51719CFEBF37CF617B17FFFFCFBFFFF939 ++:80F080005BDBFFEFF31AF6BFB9FB1F19F7D9AFA7FCFEDCA5FEAE266F63F9AEBE6D184FCAFA48444FEEFF947B501210022180210184144021011200281281828111812094118118811842989014008001346032400140081244126C024C22E144021F76091C011C6181454148816212442C21014011C1141A54784885B5144481C484488D50 ++:80F100002530181904482884443C1481415818442B14161CE2C17428F211482512C1128C942810628140B84823F8A298C0521F417228F21124C3F61164A3F41164EF34D141B64AF91168AB945F81B44AF92548AF743925AF547925D852F925485CF9254A8F14F8254A16F5254AD6F1235A875DACE549C25A1F49C2C31F49D238F9912CAFBF ++:80F1800024F89124AF14F98164AF14F98164AB941B68AF343985AF34B9A4F44A92478AAB94478AA9F9A44889F9244A1FEB0C2E5A1B61C5B211522C1B21C5E281F22C131B284CF191282D2617892576A5F84A16578A8F5431A12D353D482DB45F82F548947BC216F5274846F127DA83D536ED19D2A2E5C9D2B2E449D61CF5912CA7241F4875 ++:80F20000D21AF18164AF14D141D64AD141F64A33D078B124F4481247828B1443921A6F82941A4D5ADF260B8482480000000012C028000000002120048C08100800410040040020020044440000000040011B5324143118430313A21215542260112111C4301513512843515229C14C4944641C4D621CB1117442961923012E16442A61621E ++:80F28000199221C0981CEBB42843F19468211AC4128B144CC4128C890AAB82AB214B42624DC83FAB0B1282174214212D1411C03C4D192D48966B818681B148189254843AD481048C83D284128B021CC18495624589E481623414128A51211D2285C434C934861426D281688419082B84288F219424160489519422CFBE479211178C16E1F8 ++:80F300001241C2253211AF6192154FA1C4112E189504871813D12C311C2B148C314C4935122ECDAE4C1C21751132151159E544C3388D7173B26361181522B826F9D8224E3C5487594D229961878961648227898352264F88E1A132744D618F49F41BAE40024342142241410484256188252188B114148204537242018932245023281562A7 ++:80F3800044AC381821816100A012F02811155814908268218A44B281041A84A2492822218481228F8D022144002E11842CE141542410AA411C013448298154388C440581827024681421812CA42441282A0822302484298122C248629A4421812808400230B44C68884664887F7B4631241CD2125163644651416012CE381C63288496117F ++:80F400007C994474127522C4931AB2598A92416D4A11CB1259F51461A71381AB38C1641F2174843111165812D427D51E477082563866786B421BF81B444F883424872847882D482B24428992248FA642021011D463914816345226B482D21223243181957654417254C22C4A3813848186425C828D2246F5116C2E4B405C48883D521342B1 ++:80F48000D12842CA1129839442629CF548212B14294892588544C68825A4D2684E8883B224B85A4E6142174223112342414114C1588198A5810186D8421141711338247E812846217424E15124418261862B292849024C28911411C457841F42512886348221178285D18248A54828C088659A843044846D9320F112410013448A11146136 ++:80F50000512741144A81CC212D94496112751852122CC241A44B2966F81221891413E2124491882FA8D32821045322B82691188554E2186270D298444E128A426A88248933282936C246045F250CB964448D348505251161211E2829149528901468904200C143C81A4D1818848845028F42088126891134218D1449041F41429A85881C5E ++:80F580006612419C16C1882585D3426624784C9414106282429FD2430140C1122684022302200A27888581012A78488481E4820122204424240284A0414904006081810080411288C8221870442808813042202101AD74341725548D211D1437422C82D126912927751EA187122F88F145181CB412B886964D4721CD428E188C6311814BC2 ++:80F60000428F44D212952817482194328E1E16B221B144011E2CCD1149921D24DB522827429F2472F8A1941D44EF28652CC22F249334678729227854086E4F001249416824154881820100428218411822A5015C028F44429288C0242D428942A8248C24F42488104244A128AD1282C9082D118CC484502A1270241848384820A4412848AB ++:80F680002FA30A512221239221342A14F14823103942A1881D14921A02B028D4480582A6382270225841404411B1822421011CE18852494224839242222521942A2A58121E84A398868A048449B444A248F0C4CD00100818004210B12221422401C110281212E24281018E498200882426244C1848014E844C04815381B48103891152417F ++:80F70000428B81008013A28288824B1247A49B97807211024981228262412923829C812C486188112164874450411419120229B424D52882C12881414412602280082A2162416483CC241B8110D32444041E22446A08428082F2AA7A24442504118484842240084253D18418C7188B4826E81811841A4828847124488984021A2CE1116249 ++:80F780002422800228001912283148818574188212382448206144218800FFF847611880621100D01C146249451101181668228146018611284931211DE4C11416C8422811A30A00191132252121542C24D22432B124188C48D228B88801308669280A81281F41078400A40046221281C4621A82110482442F2221B622C411107288044892 ++:80F80000205812432981042238441C88C179459348A1463211001338448248A0144220024C1292423F7704206241221421002C453112448200200214800400002C18C41C100224248691C24B2184A08412800880220418C064441800412084F199C32073174808241D2210082A09881125224894C154844518C22130412123B116B4A231E7 ++:80F8800084B14B48222742AF1208590140D4A4184851C1174846348338514D4112C0822624724822836489F0DD1B2484E061444C08811220844818922140C114424B1819E928F248842789C0142288488CA21C81121E81602484811AA48413010042888B43868681226221286045400221C18F3945D15172A3FC122E9FD3D218732983D25D ++:80F9000022A2242F22F383813D3B8AD81B39148FCAA9336B226F11F9CD486B174F19F12918C1CF66B224F167184F66DC1262484D831E1C6F49E12762342921B388D858924D122FE4F41B87F6F6D6CD9D42A7944DB25FC1F1128AAF43F182B44B42EAF144E22F48B584C8966E2C5FDE4B7226D214931C6961A2214678417933F959448CA21C ++:80F98000C62FF161499FC85911CFDCFC48118B623E27449544F3818B3BC889C2673D284F29F11F58BFC8A582242139D161F281DC47C15E4A5E2CB97121B1A4D411D629E31FB2316AD12DC1184E224F2754421A5C824BA46E44878F484D8E806121401281B22AF43C542CE518F8745282514552124721211D4E17EC29F889EB2EE89AA8667D ++:80FA0000142FE43C188B198FC2EC22AA25CE638BA68D99BAF294416D211F2233A58E9347F68B214E286D98222D988E12BB4CC6F2CC244F8808DE326D24874A268282761CF2141F140040010000850181008002100111281144001128002181002220021820022440032440022C0200282004F01B6C241B1166F2242C4FE3F21B2AAD2ADFF1 ++:80FA800054F24D155F44B5C1FCD3DA2FAEFA8282BD88BF88FB1C999F94F4E8A84F65F576162F25F1EC7C1F98F1FAE9DF9A5E6CDFF6F67E666F37F6A6245F41F3A4766FE2E631FDF2C19EC67FFBFBBAAEAFAAFA62EE3F77F76724FF55F17F7DBF97FA9AB8AF1CFFCB99FF18F8858DAFC6FC52466F69F8CA4A2F4FA54A4F42FEACACACF28790 ++:80FB00001F246F61F16666E5FC3D6C1F21D2AAF24F2DDFF4F21F7FBF88FEC4F82FA4F42E2C7D86EFD8DB95FBC9CBBBDF5F95F53FDF2F91F3D6DC8F99F1C9F99FBAFEECD6FFF7F57E6E4FFCFEE66E7F8CFE846F6FE1B712FFF8EB4D476FEDFD1B9FFFCAFA485CFF71F153715F51F1765D5FCFFD5ADC9F9FFFDBBFFF1DFDDDDDCFC5FD529425 ++:80FB80006F6DF8DE4A2F6F3DA26F4AFE8CCC8FA5D7BB44F133333F32F4222C4F4352B9BFB2F26F27BF37F17F7C9F9EFED3D7BF2FF382A2BFA8F88B888FB1F95B59DFEEFAD79FFFF7F56211FFDEF78919DF9EFFADE9DFF2FA6B6FEFE7F676674F7AF21737AFB8F5A6EE2F29FCD3C94F69FCB7F59EA66F69FB72EE3F73F367277F77FA7FFFD6 ++:80FC0000BFFFF7BBBFBFBAFBC3B9BF98F88E8EEFE6FC52566F68FADE4AAFCFA7482F4AFCFCDC8FA2F337BC144F61F13367EFC3F37D259D2BBD2BFFD4F219337F75F5A3E32F6DF77B73EFA1D327F8AE9DDFB2FBEBFBFFAEFCB7F9FFB7FD22B1CFDEFEB8B9DF9CFE2DEBDFF7FC7F5FEFE7F2F4E74FFEF6DFFDCFE8F596EE2F2BFEF3EB5F71FD ++:80FC8000F5BEF41FF9F997B4DFE7F73F373F15F795A77FD7FDF1FEBF8FF7697B7FB5F9CFDFEFCDF57CDE2F45F9F6A6E7ADEFEFBDE2EC4AFCBCDC8FA6F79A19B02201002A415824482220220192248460884CA24942922018084E24B04882014B12800198B026082AC8484B121618E48804482041844404A0484A221108CFAF028651412D42 ++:80FD000011154C1251321E2C341B4942112D8243D83A2849F411482F2471244841C821244A424285615863624829042FA2189144199212116522714422081B212722928724C08332884B4A2D12164824E8444AF155FFE032F4112485F2112487141F41326A1D24AF14D1C1F24A911D68AB9455F84A9143FA4A915B422F347925D812F92574 ++:80FD8000484EB54FA2E414FA274A1E214FA2E519E2A2EC5DD2A2FCD8242E4A1F49E222F591248D131F4932681FC9F24E121F48F64A121D2CAF349921AF249945AF2439A4AF24BBA4F4429247822BB44F8284F9244A5FFD0E2E4B1F41F428411E24A7141E24A71615F44611CCD252D981B642DB85F24A9153B24AB325F4429357822D917DC6 ++:80FE0000482DB51981FB278A1E215D528F11B221E44152328F59622217C92E521F49C6131FC8B268E1C9D236E148F248131D2C4E974CD2389B252F3439A48D3243FA421245B8427B2698924F82F5A26AC0280000000000440000100200000080081008880020024800000000000000000000D02A43821405671112A982712211717834C242 ++:80FE800086088213E1457241E431E2221838238B1448E424C722167C62C4156D4845B118488A921226062AA881237314487A11542A56885A288D92967581C2888A36A412497882981C4CE8C4F2C36514249284107311028D14181C8811413A15864688D1862CA5144E9C471832225C226412872189A828F2224B214AF841A2121B3884714B ++:80FF000015E22A94148B28C84712A3C561488127C14936122480032A6411F0A4E93042464D582416D13823713229F1C11A8A4469C24F11B881614615F658272A754268AA8D1422C37126F2C428BF41E282DDC37942EC51B891C21E4AB21898363BA589E8213C312F417E12E2616AA41F24311C9F24B23854621B18AF22A887491A824AFA84 ++:80FF80005824442CF234954022413211240044144C822148026416A8148288122F54B181A41422140061A0824A4288C2821B240026524140185C8188CCA286807891584849048031142908984D48FFD109242800890181112C113142400218222C092C23D2181284228848A22520C14AA04228480044C02C8B824823042212203148004845 ++:020000040001F9 ++:800000002884A9014C0900BE4A902118321426C51116F32842448B843C9381818F18642C5314E434CA4413081CD218513C1D4A4655A59C542F544FA2C1824483A2422B2126531421348368927F2984DC94026612619177816F8891C2214CA6848C944443626CFF7D49111122038C9211118121ADC22C06908B241C1234C100893221194396 ++:800080006C186D418D721C54A47C8493422126C822221552258485A14889D252B422180868A7141512948A2181008309224C74EA0D221A0214471160813B424C416111131888A48546C4922CB224F5228111418413784248521485C21184C1A249822484C12460422E828127141A28D4410312C01887114B416A58228F43A4844994444449 ++:8001000088BF6B451211C2141604C142004AC1142129921C802248511A266A84A489416D869C94538D8489F21268C97528C1648428D144428748854405211189B28A31294391982361429A1414180829A248823FE8084AC2418111812D22122711350295A414284E8343C4184344084418472813E22122184482BA8501242C54218865912C ++:80018000482A618538F0882281628C82A14229B18604201168282C8252422D1CC9F21C223F4A0418361641922418414AE2830448111002342243E2483242004848445084482944742241648841128260522523850116828118012451442441833714496882003035141F22E53231184721226D22441C722219C24B5603DF212444EA42CCF6 ++:800200002D8F4218BA4851481B424E2DEB828D4559944AAF78E342F4324884CB422748137341247218D1D2B812F4AD12E024F221188D226638122F217C1134121823FCC832F0822C274283A128C3F27B141042541411C116E824A1414AA1411840224834310025B12414229818204432184322C418546F2224484A84684143A221C15028FE ++:800280001220C9911D2860884443D24811D448038143724824F8D5DF800414484911814202508411438421084603A88E4925847488318824283302112695414684E144B184144111C14400811382D858322814908411C14443A24141282841F08F52302444504111414121498418230942E440A4245430888F12084081447614480489181B ++:800300001202818E420029A2245C125224008244CB84188688221402184210CA84FF7A03C01111128CC4128CD2814218C1C160880024890121481B2400244A484868244A193842A024222366124A489881800C80E2A1B4118414A2481B1448121A34828CA4218412257A344D52243014408692444A311438126C82D121C214E04882E141D5 ++:80038000B62631181C21614A0016049042128186469C11122E141E44183260418252108402131106A1884122459284A308EF540C12116081143223245281228E2810E5441183E881684448190282842227C82601D494430D4369828C1802852198A81B482F283288814724118392224501608142214A2203842E84883F1C0F848064148BE1 ++:800400001240032239081B4A23C18888254AC2831588182464224128A162214062828410413542641C12420820381128211283018B4820420245080032EFED091112482890491824002CC41C2C08841941110890822810410100690810022002000051263112008284241518B224988C84894832188044F29D5930C2C22548A82825489840 ++:800480004D2A5128389048942AD1848134298959C22E118418212245B1122444882261284B48200112637A15281872146311144120B142482C212161422240AC292643E45208B4A0418044641118422D1424C4248A8294C180011848182B82918D14488D811418AB81471A32B428822FA182EA81442231188A62E287422111D415820246E0 ++:8005000082124818024129017F384D51115B181253E15DD464F312431F2625B423B182C413F094825618B182D1315B284B1259A81A8F88E82AD283D28E864358A8C3DD2A1B867846E81EB812DA217433B21FB8F14466839F22B362D68452CA4E21AFFC74887C917128D424DAC8B29A6E432F8431822E8783F151E12427672358429CF12DBD ++:80058000222794C425F8322C8CF231848F82B2887449B884582C5DCAC7846F95F688C2AF15D29166232D8C832AF62D42AD441F11C1EC17879AF8CA2A8E226CB321C494CD248E69ADA24F1A5A4E47491F11C811821991817F21F14C881E828F85542447A2C97214F434889CE642D8AF074964159D118B648C3139DB368F51D22DE579F8483D ++:800600003B3B8D7FE5D912D56BF392D987572B431F4AF9532DAE5C8B8519531D4DC7157352FD45136F48FC23128E458FE6F124549F42F117484E13EF1BE298E942817153F881B32D89CD16B7661F137E3A9A144E8129F544782F42B16229E484B128D248B29C7186C225800228410000000000000040044210088110088141801108424001 ++:80068000480100000014001A040012800448F026C6241F6775335E4CDFD3F325AF2FC67749F43D3FAF45F71D3DCB11BFBCF6C24CFFFCFCC69A6F4CFCFFE94FCFFFF6D82FB8F99A9F8F9B6D19AFA2F8218B7FD6F6341B5FE4FC9783DFBCD423F483EE9AFD92DD8F11FA96F63FADF18F185F72FFC8D2FFFBFA8A8CFD8FAFBDFD93BBEF31F18A ++:800700003B2BABDD6F41F95C844F29F95E5ACFEAB86AF4262667E44F47F2B43C6FCEB61C4EF277567F67D5CDF13D3D9FB6FD5358FF67F63C7EEF44F53D2CBFEDFDEAF2AFADFF8ECEEFCCFB6D7CDD5DCFCEFF7636EF3FF3BE99BF9DFD9199EFBBFBC5CFFFFCFD155DDDCF7FBDFCCFDF1FA5ECBDFE585A2FDFFD31BF5F4DFFB372FFC9D16CCE ++:80078000BBC8FDFFFDEF48D85EF8D8CBBFBDFF5F7BBFA7F7FFF46FC5F5DEF4CF69F9DEDCCFCFFFFCF4EF66F7761C6FC7F8FCDCCFEDFDBB7D347F75F71747AF13F21918D7E1AFD1F1592FDFF1F35A7CCFC1F33836BFB1F3C262FFF5F5CE8A7F6CFCFFE9EFCFFFF5FA2FBBFBFAFDBF9BFD9999CFBAF92F8FDFD67E2DF9514BBFB9F1ED4BDF8E ++:8008000073F58AFBAF89FE96EC5F95FF95F67F63F73F3EFFFBBBE8FDBDAFFFC8F82FA7EFADFD93BBBFFFFD7B619FBDFF16968B944FEFFD6A5ACFE3F35E5C6FE3F31E78EFC3F3D85CCFCAFB1A67347F75F71756FFC3F31C1CDFE7F55F5FFF57F63D7FEFC7F73D3FBFB7FFEBFBBFBDFD5F5FFFF7F97F7EFFD5FDFCFC7FF7F3FEBFFFDFFDF836 ++:80088000D19E9BCFBAFBE5EFFFD5FE4D4DDFFDF4D7DBFFFEFDD5DFCEFAAFA5F6F7EC5F77FFD7F47F5BF33F3EFF71FBF9F1FFD7FF8FADFFF2FADADABFBEFEE9EFBFB7F7DFFB7FE5F5FED4CFEFFFFEDEEF6DFDDEDCEFE7F73E7CCFC3FB9C9CCFECFD7D6280012501498164228434860848341A44A349241F88542811811181820081291118FF ++:8009000001291998969086E01248F82293842A69812E819226022041016C22992812208122F87CAC001281153428A01420022662888921988A5012A084824C82C4A145D21882C4214D4896B12204488A82B481828412423442C09186642415981A484E11414A088B9441462242748408F04699C0421F41522C1F4132481F41324A1D64AB85 ++:80098000141D64AF149921AB9451AB9443F24A9143FA42914F82F442954F82D418F9244A8F14F8244A87114FA274D8F1224AD6C54A8F4DC2DA1F4DC2C21F4952281FC9724CF19164A3F48124AB941D64AB941B28AF14B995F44A924B42AB944B432B944F8294924F8A84F9244ACFE1044FB2F4116487221B2183F41124E5F11124E11E2430 ++:800A0000AF549821ABB459F24A9443F24AB543D9526A832F147836D818F8245A8F14F924CA8F51F82448871D6FA274D845F3C825ACFD412CACF981648D521FC9724CB191764AF28124A9D941F64A94282D335F8156224F8294984B4329F824482B946F82B44AF1245AAD7420288804000000008002480040020000000000000000000000ED ++:800A8000004004A8000000002501CF14014443931822604148E5514B17482C82981884888A012CC185236881C460421F8288324344296A82C651A2841AA29244511351184119F41388893C42514049018B186821184B84904A7840F2E6B12419348163C21D349F2294242AE821BA288569B3172C1F21CC449427B1C934281FC1D612641582 ++:800B00009D4493544263D468B1285125C28F41A294282724346AB18253264CFB2A13838234133CB8C8D129E823D828EC3C8144D828249E282936848285B548F2D6E69046471D2AC151703A24D66B72117C28B5A4F12281378718613C31114D1251E97C1BE2D441E185F22C818A623122273883AC68939D2A4AF29A2243E4543814B9311E2B ++:800B8000911DC88F112C98158D83F02B444E128C2CC64822C3D22286A834142FA5F27675408112CE2C14191426E822A84960812CF881484A688885C248893A314270485425D0267448D484C124228751219012112E121A52128E242683D6220127348E48F091282C3881188425A2494A088744828504FF510F2411650200218001180048E5 ++:800C00008180024A0240488104008450845A42282422A4521002403448901A1902001118482180014008F083DC003810143C14848D2300219082748242A9684244D04385942424172287244870C202414428811A0A79115812B051884181448E448A94848CC48889259446004302B0DA03240025044911428A012941021C84082F8892245D ++:800C80004C0629C44828242CC248008861684148A04A2C72111402709401701218082004484256484204302C001F8604D0214704C11098210041A08264844200004D112145A141149042852214C814858192288C8105461A01424E18114247122744858232858C9188214858002180F1A1621021814164446D2222146011244082918E47E6 ++:800D0000182200188462400114428912011144224422114C7228174C9442882524E1826188252838884B84252801008418C9015F970E212CC22681901844459828800E121C48122821A4484412C42A0C8441214229C6448C24014A01418041124822611483021A844C3843A118C22CA54810840881BBA70041110000322422111800004589 ++:800D80004842084382015024B0284184012721402802E20000830222424A4821820100C5024480914822F0E9A350122E16244443C43869B22481B212C22212121AD88668C838422F88847138E482A148405C262E1864196144A56141812A24D241C424CB12E512282499241A66872CBC2834989552842D18812D52C8C0188C9C2CF068FEB1 ++:800E000000F02411842444508181114E814012411251480041904428111021E482A4242015829214A082400145C22825924181828D1182248AA484E044094440248141F897F300001240880100001890128001100422424880048C044904A0212444210000800160884A18210424484A280941428008CFFC082424404508840087210021F3 ++:800E800018818901102831440080044228234588964210824202841242428B42182004828848890418466444428418228CF4DEB30021000081008400321240880100460442808424C44242CCC422400240028384014212008304148A048129A4844A492434480046F8AC3950888F24A4444E1581841800186554644B222C32381800814C5B ++:800F000041D22252221AA51192902818807441F1211111A7E285B848842484042E481220D844DC44B824A2622A0418414844242721272A1AF179D20020020000120080010021000042488420840440080000200200002200001818828200400800705809848C848404440000644444222800802102251892124A8129880840441141518457 ++:800F800084844248000052E04441C424282820840448502290129F920B4508480000009012452482030000C1002180018820A424001C02400C480000000016848C2224042004904821F04DB100480040021002441228000000801482A214800800001444C0288084021004006048800200001280180289F54CC200000040084A010000420C ++:80100000000000004481001002124800000000008001802428048004800200F07DDF30188324240440022119311441C3A22422000040C242241212D2C28200411511111138188B14200400001014B42424220620088124A54222F16FF7404888844442021001404414A22200100884842121181888C8304440444101848C044A240200807C ++:8010800029414484828201491428049042219FE10F20010028200300810080010089820480040000007024022800440040881111210C81004800008100F04C7C002241000000000000000000904480048100800200210000000000E0840800008004004144EFB605411200C02290225280012001180030284885080042C042C06426042EB4 ++:801100002200126042004180819491485ABC4824010049A4418486288414F8CDB42081624200218118104102812004008444203444C39448C04800421248412012240280028100A09DA088A04C0040A84600009F890E000010144292132C2131181223042400128C6284486848424842201418444444922420010000221B1100811248A00D ++:801180005C4AA484428150884143F4F87AF0222227212CB11221B112012C512239F812111F11B18979817948F888418F8424F4414915C1419558884F84E644544449F22424224C02284554642E242F22F212222CB112A1812B99C0922592832F31F111119BD81F98D88898488F8424C44880548885F84448AF6C016F2252262E321A2121F5 ++:8012000001142592822D1B1F3191D19E8887818D418B444246511148155C888CF44844C5B444B6242202002554444CF326226D222E123AA181232948512221BCF1111119E989F818888B488B4C420048C485C868FF760A00000000000000000000000000000014110000004011010000000000000000F0136714110011111100000000007B ++:801280000000000011000040110100101101000000000000400240022552223F54014001100111000000000000000010110100401101151101100100000000100210025022242100CFDE01100100100100000000000000404111010040011541010000111100000040024002002100F0FDDA000000000000000000000000000000401101F3 ++:8013000000000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F71064011011400000000000000000000000000400110010040010000002512120240020000CF710700000000B7 ++:80138000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F01367100100000000000000000000000000001411000000400100000000000087 ++:80140000000024241FEA0F00000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F01367100100000000000000000000000000001411E7 ++:801480000000004001000000000000000024241FEA0F00000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F01367100100000000004B ++:8015000000000000000000000014110000004001000000000000000024241FEA0F00000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000020 ++:8015800000F013671001000000000000000000000000000014110000004001000000000000000024241FEA0F00000000000000000000000000000014110000004011010000000000000000F013671001000000000000000000000000000014110000004001000000000000000024241FEA0F4001100100000000000000000011110000146A ++:801600001150111100111111000000002100210025421202F0C1A8001100000000000000000000404111010040011541010000111100000040024002002100F0816B00000000000000000000000000000040110100000014110000000000000000003F710611000000000000000000000000000040110100000014000000000000000040DB ++:8016800042F2A1FE00154141511110010000000000000000000014001001000000100100001012120224242552222424F032E40015414141010000000000000000004011010040014001005011150100000000002552222552222100CFC20700000000000000000000000000000014110000004011010000000000000000F0136700000082 ++:8017000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F013671001000000000000000000000000000014110000004001000000000000000024241FEA0F00000000000000000000000000000014110000004011010000000D ++:801780000000000000F0136714100114001100000000000000001001000010110140011411111001000010121202242424405222219FF20D405111151141010000000000000000001001004041110100001411110000002100212410420200CF550840414111010000000000000000004011010000140000001501000000000050220025B4 ++:801800000224F0525D00000000000000000000000000000040110100000014110000000000000000003F71061100000000000000000000000000004011010000001400000000000000004042F2A1FE0014001110010000000000000000111100001411501111000011000000002100210025421202F0814A00110000110000000000000052 ++:8018800000141411000014501114000010011100000024002400100200DFEA0C00000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F710640511114501100000000000000000011501114000014001100001400000010E1 ++:801900001202404252224002F01D480014154101110000000000000000001110010014141400110000140000001002002424250221009F140C00000000000000000000000000000014110000004011010000000000000000F0136714001111110000000000000000000000004011110100001001000000400240024002242121BFFC0D4096 ++:8019800041411101110000000000000000501111000010011111001100150100000000002140420200DF9D0D100100000000000000000000141411000014501114001001110000000024002400100200DE3300000000000000000000000000000040110100000014110000000000000000003F7106000000000000000000000000000000BB ++:801A000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F7106501100141001000000000000000000111414000040010000110000001012120224104202009F520C00000000000000000000000000000014110000004011010000000000000000F01367BB ++:801A800000000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F013671001000000000000000000000000000014110000004001000000000000000024241FEA0F00000000000000000000000000000014110000004011018A ++:801B00000000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F013671400110000000000000000000000000040010010010000000000000040420224242121C79F000000000000000000000002 ++:801B80000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F71061100000000000000000000000000004011010000001400000000000000004042F2A1FE20 ++:801C000000000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F710650110000000000000000000000001100004001000000111154 ++:801C800000000021212140020000F0AA6300000000000000000000000000000040110100000014110000000000000000003F71061100000000000000000000000000004011010000001400000000000000004042F2A1FE00140011100100000000000000001511010000115011110010110100000000001002242400F0CD48001100001108 ++:801D000000000000000000001414110000145011140000001100000040024002002100E0C50100000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F7106110000110000000000000000000000001411000011104101008D ++:801D8000000000000000002424CF420250114041011100000000000000001400110000141440010000110000000000502221401202F034BF00000000000000000000000000000040110100000014110000000000000000003F71061100000000000000000000000000004011010000001400000000000000004042F2A1FE0014001110013E ++:801E0000000000000000000011110000141150111100111110010000002100210025421202F081160011000000000000000000004041110100400115410100001100000000240024001002001EA200000000000000000000000000000040110100000014110000000000000000003F71060000000000000000000000000000001411000079 ++:801E8000004011010000000000000000F013670010110110010000000000000000000011111400000000140000000024242400002400D0BD0750111400100100000000000000004001000015014001000011000000000010120200006F99080011100111000000000000000000000010110110010040010000005022212124002400002D52 ++:801F00005C00141100000000000000000000001100001400141100000000000000005022100200F084680000141411000000000000000000151101001100141511010040110100000000002140022400DEB90015011511111101000000000000004041110100001001111011111151111100000024242424000000F011B6001110111111B5 ++:801F800001000000000000000000000014110011101111511111110000000000000000F066490014111415511111000000000000000000000010410100110000000000002512124202400200F0B3950014151141511100000000000000000011141100001414111001004011010000000050222421254202704903501111401101000000DB ++:8020000000000000001440110100000014000000110000002424401212022100F072221001000000000000000000000000000014110000004001000000000000000024241FEA0F40110140010000000000000000000000141001140000000000000021002100211002F057BC00001400000000000000000040511111000014111415110140 ++:8020800040010000000000000010522200F0BEEC501100000000000000000000000000001041011400000014110000000040120200242502EFC70F00000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F71060011001101 ++:802100001100000000000000000000004001000000400100000040424202000000F0B954001501404111010000000000000000000000001140010010010000001002104202212421005FCB0800000000000000000000000000000014110000004011010000000000000000F0136700110011100100000000000000000000001400000000D7 ++:8021800014111100000024242400000024F0BDBA000010011100000000000000005011110000100111110000141100000000001002242400F023DE001100000000000000000000404111010040011541010000111100000040024002002100F0816B00000000000000000000000000000040110100000014110000000000000000003F7175 ++:802200000600000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000040110100000014110000000000000000003F71061100000000000000000000000000004011010000001400000000000000004042F2A1FE4001111511410100000000000000000000001001001100E4 ++:80228000400114000000101212022424240021B0490C40511115110100000000000000000010011440414101100100001400000010020024242400002D870014141411000000000000000000501111000010011511010010010000000000101252222400F0C5E600110000000000000000000040411101004001154101110000000000000F ++:8023000024002400100200DE8900000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F01367001011110111000000000000000000001011410100000040010000004042420200000070670C50110014100100000000000077 ++:80238000000040010000110014000010010000000000250224250200BB6600000000000000000000000000000040110100000014110000000000000000003F710600000000000000000000000000000014110000004011010000000000000000F0136700000000000000000000000000000000150100000014110000001002000000210057 ++:802400005F420A1100000000000000000000000000004011010000001400000000000000004042F2A1FE000011000000000000000000001100004001100100001400000000000040420200F0C172000010110100000000000000001001140014141410010000141100000010020040424202004FDC06001140010000000000000000401193 ++:80248000411101001440011411004001000000000000100200F0C35C001001141001000000000000004011010000000000005011100100004002400221100225029F7A071484148084E4220141224122404402C02C122481128120A41200100A41502846611452148C144298448C140400852488428C021282200925F8BEE930424E118479 ++:802500008734C5413C4C8F42F442224D411A028D24C0254392262725874223E72542C8121E4A10F222122CF114281256B84861C41F42D44812521889417154794264822624E6419E348AE31A41C4844A12947449A2121A1A38981EC27F9608B0180481318124800444284902142841A3410C269A1880042A0123412241180457829504162F ++:80258000012413442C0641424321381C82A289C42442202102842CF4DF5B24140048008B12482516A51240488442148224C2521A048941280428B02601004784242C8204130116384200289828321308800212160410484278FD034200114C3444002262000044002218220070124202000052004242118450184410A42442220022400480 ++:8026000010040020A1189FED0240511810084CC42C000000108252242400000024124018088905002044280410584810040041100422288AA2819888D04C09004001000000000000000010080000000000000020040000000000000000001F9B44E221424212180431448581291428D44864444912922AA0428126041061124416D6186109 ++:802680008440C64C2448522CC22C30441F249148A0144B248181881121830242432122B348229844DF8C0549143511499168134198222D262081C21812109884448C43A41400226230320080A148169244288A1221B823C12884444C82084E1230412DC8CCE144415842848E58002628F212846063159611259C2424812722452AA11481F2 ++:80270000D0844574243882C38221941844204261324441A3C148C0464D182724681A86D22CB211324446784844A481465428811F24889418488163341C4A8293288843E6BB0A290420314813414164128280B248014240068932244222004A021A824101128842418018918230281311822284A21400178825743408009608488902EFCBD7 ++:802780000F2A11019016848302432458128442C0849022C0120022874448422220022B42D22A1C088A122281018184A11A968A8A14281122A8948C0410881478245848F03688141984D3722192211C65453D1816931DA41B1227399111578146DC5AD448A2384781168552144427844F8294128D454C618223A1C232524A4923628A3B528C ++:8028000043A4C35D884B522D388E316E8846E88401182E488326C31843A4942846F8BEB32082120559D381B444521815728C41011041C5156342CD2212841AE28234416CC4488924C241416821622A81840C28832804A28B854C2BAC187A088C2CA841424628335848C34C08DB17305116D122C1228091182961451825F81B225E81258831 ++:8028800048C848297418A4824C5141444120C2242341AE5283A9D283089A9212193112283F8261C4A3D541724A3238871284A384A114848C221208C1384CC24A9FA208808402128464428CD28471124D31222718D44128289022A245C214122512419218A2895184852104B0881122163844141825164162A41C225842288B284D288266F6 ++:802900002802290886FABA1F10B84342021C3414400140068392142941CA924D181C4112642822916249B181734402A041671116321468C5014E18598122314226A14889240984B042B212044E18884823784228044FFC081818141C820281CC3353002E188004114246021211501830844289044541A682103688242244742881C948180E ++:80298000C82212228C018C2401888011064428222FF84B819132222D211B254341D824C3592416712118E21114566966D268652138734AD4C15281C666541FA1C64C73981C2B838D124E1285A424164544DE41E3C2F41188278543322127A48B9432A48D442C31D8CC88E9AAF524428245A8248B82BFD2021041014058241D4822165C2890 ++:802A0000128532848D118029420120884182028081028744614498F02282E0124108442415B842286162158C08232482C24800A04800CFCF0744161261828501550A11B0118812088C18B824311488A42A24816426896C2481442110785482441122C11290142241704228210529B21434421A1222413858829A041225F8CC624008811251 ++:802A80001224906881161848C8848131821422252B06C814005441144339862420E9483488868812242281C4848824004400000000002988F453830040154C82C1414D4825312827148D8218859421472287288230148AB11402C140C8488352142148002212C081CC210842857264084AF81882464422C1420021288C6822902828674964 ++:802B0000002200604226064E1242400411182B814346A12588408101842216C441E024AA2984141D884AF244824598411142A62215E1842232464C51848C0222898C16A212E0844142F227259024911212541D321628B122A4181221822901543964C34E1490244CE4216448009012211800891408222460221E81814CC884410000468290 ++:802B8000213D221C6181C0880085F1242B8001408441040024884C0524841028441992585052224D828C3421413E8140D822C1938018B213821607922A94318A14080000308828428448221222CFD1072581120A29020081A024104A2401180083248838282002214848472210440123022048C8624121301836244228014440044440046D ++:802C00008604CF7A43822141441102481CC32211283218182082B848082E84302A86242432242A61832289249429222344822464189883282202004D184400842A612152A02116B418A424484D1C141444582884804184A186C44490234938110082164204A72289D84211E2240889049A029422484D28C3E88264842420016B28812AF498 ++:802C80002844238412348866042504805842124F944653461D26442E262F51323646F82568563272E081B998514227811FD8BB9AF544872E4B4F457882E85CF314812D4226B44DF4481245F119134F4FA2C8764EB8E49222672C2F2B7A82D23149B2128EF1454927855AED48D288325489B116E183B8242EB11C71B8F814888B154F597992 ++:802D000018B8C80B1B31C0181A51811D226D7627458D58ACF21C282CD26278151A0817928B43512D4849A5C19D6662E552826D219D5A4F46D222DCAA13D128D62BEC84C1F4114F43628BFA7B2CB664FE2814CF2266A2CF85A1124C25048A33586E582742A82E1423E8A6E224F643B340B138711F518D89C11497118D123F12B289FDE3D128 ++:802D8000A346D818F1A19567234F44FA82388B9D8F2AE3677A24E886F18CACCEA82E263E4C2F47B2824C28971E2B9D94AEC222CFD4D199D84C9649C227E92BA88E948D242E422B44259A428D6623F4821E2D224E4818CAE4820423F2F5C224400326014581440114004004281228800283044280128192114440044624021C0140981448E5 ++:802E000045820482268244124412044110141824F476A824446F43F33F24A1A7911AF15D4E6F62568B2B2ADF8CA5988F4A5951BD184F423148CF4EFAD1D36B9B9E925F18F499996F89A8C81F3654AD9F92F48948EEEE6FEBFF95C8EF81D3DAF8A8C44F6EF6E4A48F8AFAB9F36F4CFA94A4CFCEFAAB8DCF8DFB8E8CEB8C29A21325544867F1 ++:802E800042CF8CF56A3E2F44F5A4A44BABAEC47EE4E7C6CF8A4C5264CFC5F53E3E8D48AF81F13436AF67F72A72AF84F1F86AAFCEF7A8AAAFA1F31B1D9D394F6A38635F5CF8CD8D4F67F13A1C7F16FEB9F9CF8FBFACFEE9DB5FA3F439C9DFD7E5E6F6F6FC4FBDFC9AFC8FECFEE8C64F4EFEBCFEEFF8FABFBF7F5DFCACACCFCCFA698DDEB812 ++:802F0000AF8EFBFAB483F4587CCF85F158744F46FF4CDAEFA6F76274CFCAFBB4F2CF8AFF78FCEFE7F2C81750425F73F73D2C3F42F33F2D5F71F137245F53B359F78BB19F68F9AA82AF895BD5FF39F927219D7B7F7AFBA7BFEF8ABBD4FFAB79DFDEFCEC7A2F4AF465E78F91F37D7FDF9CFEF4FA2F62E6F8FCC2EAEFAEFCF6CA6F6DBE24FE71 ++:802F8000B8B89FBBFBCF8D52CFC7F78FCFFF9CFC3E6C2F47D622B242F64242EB446F27FCFAFE2FA6F67E684F8FFEF8ACAF8FFC3CA8CF86F35A79F02624DF73F73D3EDFD6F33B395F73F37B7EBF92F67B3ABFBFF7CBD88FAEDDAA51FFFF3BF9A7A1DFD6FEDD1D5FDFFF7C7ACF87FF6DFDCFCBFDEC7ACFEAFC7FEFCFF7F7EF6FFF9FFFD4FA73 ++:803000006F86E7ECFD8AE8CFAEFEF6C84F6FFEBAB2FFEBFBBFBBFFDEF6F8786F87F7C7CB3F9DFDE2F8ABFFAF24F45E58A7A4EB572F66FF6AFE2FA6F77E78DECC7EE4AF8FFE3CAA8FC6F3622580014140026081248A0400824048A64864484624E1442208208411180229384823026302006988A4821E481CA841221A041A048A84228122CC ++:8030800089229128F0613E30A4A012163824A0164481288981929216584232AD813214B688B121042E4246244214E34DA2824218CA1222C482114989722403C148C3A428880048808483048C94A88A2444F372E7C0421F41F228121F41324C1FC1B24ED141B64AD141B24AB981B24A19F54A9443F34AB143F242B147822F14FB24484E91DA ++:803100004FA2E414F8244A1E215FA2E419E2A2655D2D4ADE242E4A1F49E222F491248D131F49324C1F49324E1F48F64A121F48B66A9921AB945D48AB9443B24A39242B944782A9F9A4484AF9244AA7A7D0A2C464AF22E5413246CCB24EC164AB144CD24AF98164AB3428AF443934AF141AF442B14782AF147BA6E814F1241A8F14F925C2B6 ++:803180001AFA244A8E214F8275D85536DE244FA2D5C1E222FD81448D521F48B248F18128AB141B688D121F48B662D9C1A2B45D684E9447824E9447824E944782AD946B4A4E144FA2959D400820010000840000000000000000008200004440080000000000000000000021D0510C100212C48481A12B4180048C0121A5B41232142A1504D2 ++:80320000430C8D2280664143826226184112290127211E228001499238284C2DB218C222838191448CA21200414C25B2886242FFBA0E22A2C153A2241429C1158445D2815282504A8C8441C222112CA243184782B0A4542C22212951141B8225084449922188C3B3240812C09215784213011B84154212348826E28964A840781441F8EE85 ++:8032800053002F8452481F418242628167112F8154244D6B812244A485A2219033D02282CD24328AE2A89214A0212E45191A8731142836F142BAB084012289E222E8496414478126E292C81349342E2E982CE28458284C648283D186F26241200200C35481400800D028413842434132344243A2144181A44694442867224022410821445D ++:8033000021B02C81021684215138282712A014000080318418C0A4F02FB64042941228301114C011122CA1418B141114122526714A1331484051844211445180A82845429442133124280045226114194242A814C082100285A4424C0828008CF4188A2428169129352A18A616AC8152A11C8248C31825E68422C268128E6AAAE114EA88FE ++:8033800022E428A224B326A2614C1422C2582E14483B142D151F4A1192322E4849C184685A62A28A91415688E424A2528B818B424F88745428F2245828AF4C4E0225D229D1290243C141A0218114233148891162822283C2528C88EB18541849E42264124649A561C62448A641274456C221C0A540A625434121B6128616129158486247FE ++:80340000814E1847828694442828F0772E807211240288311A62A1111C3132C217211145B14251622C551866314A28A881882CC42428408222122C43D124F521141225A221814691A410C81892C60221B042828ACC488903C9C568BFCA4512C81452450812814F2281012D24182C2848C821822722D08402EC81A51840E6217428D421C812 ++:803480002860942C922849921820463828814301A981551E4E388F21C4117A08C2204864422160888FB4018F41024A92221A02188144448D1422281C51144156088301842C64D28B148CE4125884404894C214E029843488444364439012821628C68C8A07902C902222424442B0521804DF9649015048193148130614282A4401400886E7 ++:803500000841002A810219322425086041423669614911044A32122C08501448288200308248C182C4288B12288C048149F42788144C43C4128D218936718CB12D21A3241901828155C8845AC82281C922A1341932612C46744242D8857144F81188C37522624A2AA4252D14A6363822ED118A7428B248E864C8981E282149E4C8B522C89B ++:80358000C82296A824C4C830445F89052112C3624118001046342A1A423291702158284118902845F848148658481782874143227822A2246041AC4584084014084921A112166856488F24791108C024484C12A424128564883F7B4A311100524160A44810D222B281B428413A28822D285A12221828C11810C818182C044E1821164228A2 ++:803600001CB22401818392481284446014C816A881800942006C024210F457D500254102C0214426C425160422144145521441111147114951144358144388628485210484C21028811456414C14C34415A281C0241548266421502218C582A281267824081AF471F22042688114C9113812242A45612240042A881201450230E810820433 ++:80368000228243016894243088A012188A0400D082A54880114434488289E882C1188880899922AD320043934241E04144B641418C92184229489154909449846184690841263824489014A0211F410888144890882C440200008081088224490142C246688B0030DE24861104412400282013A88290411CE112981884218CC82823020095 ++:8037000026068415084508A14901222A0410C12810C81287118180041088044E2200302887145F3D03162202002002AC61184285642418D02215B124C1392A21C4182B1442D082E884082311042F8194148443311286C26441834216B8848124521220C2344E8844004004904241CFB40F1031212668161912119141A4881819813AC88472 ++:8037800030818A042301212284908429642C9C840148004958428944282C841102A0182598822121002129280100F0B2733466044C429128B062911821484484A100120041481B429041122A281404002841421880040028914058284388041842128889C824102221C1DAF0FE2D40082FB1442881541844402C6151884F21127144880C1F ++:80380000226188412952842511823A8485F221843304142394428C7811828482981218248041E24844820A482522048334C26D8823025F59041E518F18F32121D14F457144F113495B3594CF23F46618178614566D2185341A4B37CC7843A6321F416B311D4C8423E82452454F14F114141E34CD8346B259A941AE12DD844D25A7E42DA38E ++:803880008F4444FB828223E518F141432F217884D2226D2129F1C8C2A7A48A686DA8C1E6E344F5A254502371AB112D4189B22BF5281427C2BD143D2489C892FF889A17CBCC4BB15F1CD919F47232CDC84F1C7C44B8CCF53C22CDA1667A24D8887418B84BFE4FCA1E5887418CE4E4A9214E12A5887CE938148341DCA8B42D16C2582B52436B ++:80390000B142FC84C6124D542F84D284C61A4E9C8CD922E2844CB324626245CA3C17822CF244223CF474629CE921F29A615AC1823FD2F3E34BCCC28655A11BA7E183C224E06A947C8D54DE822F2864B22621D4825C62214F44BCB222B12482D4819312CB11182F45F8989883A88586F488188125A8223E42A939FA9AB21856847FAC09122C ++:8039800020011A1404140048144800C04880141801118131004411000000421450124081440200004008488014280A22F0AA74242F61F1263F3FF1D177F192123F34F37F1D5FD5D14FF285A7DD633F38FAC9D5DFB8F88F844F5BF9FF394BAB4F27F7E7677F6EFC5D4D5F45F73F475F48F86C4E67223D4B37292F2A3CA2D7E82769E7F9AF0F ++:803A000029F9A6D64FF9597F9F38FCED8D6F73F24B4B6F6DFD76765F7CF8D29A2F21F942924E426F4CF88282EFECF886AC6744AFA8F9CE9CCFC7FBF4FCEFCFDE374BE171F357773FF3F1377FFFB1F15731DFE3F1674F7FD1F1B1BF3F78F9B3A3BF3BDBFFF1879D7FDAFCE7A54BBBBAFBAFAF7FEFFEDFDD5F4DFF7D455F8CFCFCFEEFC1F131 ++:803A80005D5FBFA9F1FEFE6FE9718EFF9A16EFE8F4965E6B5B4F79FF1F1FAE27CFDEF63E3FBFB4F5CEC6EFE6F6C7D7EFFDE921F972B62F2DFCCE8E2F29F9DE9E6F6FF976162F24F24EACEFCFF8ECEDCFEEFDAC9E245F71F12767FFF1515F8FE1F14B5FFFD7F75B5DFD2D5FF8FE186E3F3DF7DBFBFD1FFFFCFDE6CFFFFABCB6FF7C7A7F6FF6 ++:803B0000FFAFD9FFC3F7717DDFE2F58F85CFE6FC2E4A7D4E7F79F5A8CAAF8BF18C4D967C9CFED2184F4FF5B5D76F516118879EFF77F31A1BAFA8F86A7ADFF7FFD3DFAF21F142B26F6DF45ECEEFE9F1DEDE6FEAFEE2C2EFE8FEDEFCEFCFED8BFFECD89E4B344F71D357F3371F7FD6F35DDFFFF5F77F3FFFF67217FDB5FF2F2DFDB3B3BFADDB ++:803B80005FFF7FFCFDF7DFFFFFFCFEF88FBFFDFFBE7FDFFFFFFC5FDFFF6D5EFFDEFC7CEEEFC7F75D5E3FBDF5F6FE67B9EFCCF49A5CCFE8F4D6566F4FF5B5B7EFF1F1AB2BBF9EF67F77AFB1B18AF86A6A7F7EFFDBDFAF21F956B26F65FC5ECE6F69F9DEDE6F6EFCEACAEFE7F7FEFC4FCDFDF8F9CFACFC9D5820022342683284221E48229A5C ++:803C000064328A4462893492289289227948048B24F0482430483048698992128161422A09002D82001658241A442109124496081A448634489242F055B94051414054244053418144A5128111541811850454222141180049E444126244188714214604904280C128621E280023D481224498128A941248212E4823648A29018911F4142E ++:803C800041E022F511248D121F41F24C111F41B24AD141F26A131D24AB9619F24A9151AB9453F24A914782AF547924D812F9A4488D914FAAE414F8244A16F1245A96E5A2E459D2A2EC49C2CA1F4DE222F491248F22F89124A3F49124A7241F48B26AD941B24AB911B24A9945AB944782AB944F82B44AF9A44829FB2448B84FA2F44398C0C5 ++:803D00001A1F41D428F11124ED111F41B24AC124AF2451418D9444A99B45A9392529F92448AD9557822D917F82D418F125524E114FA248F1215A96C54816D5B6E451D2A4F5D12C47A21B41C73213794CF19124E7141D24CB161748AF44F11124A993652F447924D84AF92448AD144B482DB46D484CFB845A7F6D0382820000000000800260 ++:803D800000000000800188000000000010010000004400840000004001AFBF091813C214400829912112222288580025048118A5C211430428302529A14231AB121E8427C8824582C841122538848B1422273211890C2B212A8801242800108221E48148F531281411921082A42191608455828C1268518A84935845924443062222811164 ++:803E000048901C81C02142224213022541A212281283148401C60883143248488B141A22E32281284A81F4A53100D243018C84D21891211843B22684BA287111847E329448C158255221629028F08154188B842116E86279812C4A342846A314846B21482A5138118B4924CBA4A887276024284A81E322612224881CE961F4BDC9C0111940 ++:803E80004202201102831481084200800125F42448184128406122B0245118234281042C3481101122B828012346048001008148810012982A1408FA0F258102001224440046012400005129321110C421002454406182851404488E242180215824C4414C440218E0141914082F4428420400007744005427421632242D238715123022A6 ++:803F0000B02201165581165681218012B41894844435F24824B02A250180026D38258103274227319942C11350848B282D8A2480280C842448224782CA4118C83C24112261164294131C1406284828404151249424B0114284C52164344F220458188352842604AC6718230110D341524B54234492A82F2108128846086508432492240060 ++:803F800084EFDA0D108502222662811810423112244C418801352402504886044058342618010010362422244B121E82818041140C8470C24184084A281202845A1808873B14381E282784290226414102315494A92324450427B89042356868465881801236484400148901312826280420A2432218205814818C82411854421262B042D9 ++:804000000A86F8F545002528248101891292982642062810018142124508A41812288148441443612285A54283890116BA4832224A12844812C83C431288168434423048148184214902BFF248028041411402A028C0281230884124128002418002000081428C2941042A3411441112A18410E158240424188800A9088E49202201F0130F ++:804080005F90122D12842D11167422C12124812691282D1829C188594446D221A812A51251841A5618228C924285143544AAD1C2C14C922934114489E221C268419A44B385C5548A12811504A1A3584A8E484628A2122888378920828281025028E0220125111188840189C148904485241808004448811881A021841B21221A5232008C6D ++:80410000228212C82840186A884A814484842112A84844A4C77F00002D41100200250A1400181951321129118311088424A418A41613283128222216C22618441024410422268282020022224400248481846F27042618093028112901006024508220044A41384823644189014A21121821042110524840082095282982E28116280810E4 ++:804180003284230116225822200412417F2F0F472143911E414143911455121C4508994131228021814244054002444C0240044190252982012811502212858202002011741804222200161414F2C5FF248C041C24812414081884C04440084C8402141448221002120020010080448C026842004218523242C10046C228006223026022BC ++:804200002BC880924A241125811102904324006904690145813112186110440224602128122302602140420428322922422E0200201122015082482112186F2B038444484C044424444044410610021210924428302218184902001022511800A01280524140040010028C2242120444404808F02AC90018688C8141284228026082121034 ++:80428000440142854448888204C4800581A02481212304428100818440220142882608428881848C2408A0488CF88882708235811605250544113504142119125141211504541845014C0244302421002C72141108200122140089015024602210522A1004C12481D02254249F59044E18904281581D484884124844154C842401228002A5 ++:804300002848250218800814160440118A44488A8421242404462265214604891224048128422810A2282FEB41F3162437996F41E134D44641F2162425D1461152849C44994A613B441D321F2445D1135474201158268B214763B1151A84F421142722812449D428D142A262572628321E28A7862B182C51228352C81A51224F81C12243F9 ++:80438000823A6885BC1891ACAF2E026E134728B449F111495F154458841CD28C4421F422124562714565514571275CC86E2849F22866636144441810E223816281811D6423E242C128A01185342AE921C2221634322A58A28E12C72618A552488744842D28184EC227C98F3604488F449121B7C166D2C8A1149566A1177415D22B7211741A ++:8044000041A9121E1222128F21F354121B518F4304403826A9065E11A5F43212ED228467825A351223332417148CE621E544F248421E146E624AA2644150428F44EE426288ACF242422C141264223FFD01288012A828812887242883843248200442224622022044088C048C041D48448CC424484C024E24400444C044184C04482A088895 ++:8044800049843824882AC48148884881BE88145F74F73626C5FE2C25CF66F4775DEFC5F52C25DF73F7266BEF84F42B219F51D5F6F4575367626F11F66476D7B6FFF6D4FFF72C3CCB56657E46726EFE3E362FB47442F27E2ECF83F265666F66F62627EF237246F6361265B414F16D2D4F2676367454F62E1C4F48B626AC882F68F816964FB1 ++:8045000048FC94B6CFCADACAFAA6EC8F8AFAAAE2CF45F5D4942DCE2FA448F165477F22F4272E4FF3F26F4EFF57F5767C4FF2F25F1DED453FE4F463699F95D17CF477757F567667D175F31D7DFFC3F327156F42B32CF3545EC7E4CFEEF85C724ECB8FA5F17C2EEFC7F474772F64F626264FE1F214164FE355445F51F56D2FCFE777166C6151 ++:80458000AD1867482D84222D26EFA1F98C8C4F23F324246F42FAAEAEA7828F86F25E144F49FDC4FE5F3A047F77F427476FF2F2151D4F65F75F576FE3F3474F7F71714FF7622C3F94F41B3377F47F35F146566F53D167F24F2BFFF6D5DFF76E7C4FC6D764D1AED4EEF8565E25D3BBF42E2E7E62CFF3D262F266662FA1F676462F2357461AD8 ++:80460000F16D6D8F86F644444E16A7A5CFCCF442E623D4A8F29E126F64FC5612EFC2728AFC66EC9F86B26AF2DE94CD448FE8F99B1A247F74567765F73937FF29F7575F2741DF76F63F3777F43F22563ABF91714DF737577F73F117357F75F53F5F3FE2F367554F46F7243C4F64D566D466F8161E2F3CF413536F637336F27E6C25FA6E6EAD ++:804680006F25F47646EF2353465F15F36D6FCFA7F5545C4E52AFA7F4CA682F24FDC2E2E5FA9A12EFC5BDD2FF3E3CEF48F26EEEAFAEFC2A688B998B15CFEADC5907490141D0140141004001240012441311284104440040048001290100180020C2482A4168222002404842088400004430421012810123042C01404402144110441151428D ++:8047000084461104412002400100102224028042012384041A2404212004004284A11028E8FC0C2E421F417228F2112CA3F6112CA7361FC1B26AD1C1B26AF91128AB945781AB9453F24AB343F242B15782ADB14F83D418F9244A8D814FA27418F1255A87192E4A87592E4A9E242E4A1F49E222F491248D121F49F248111F49724AF29124BF ++:80478000AB141D24AB9619B24A19F54A9443F24AB643F242B44782ABB44F82B448F9244A5EFDE092F41164A7221FC1326A1E2CA7261FC17268D1C1F26A941FC1B24AFA1528AF143825AF343B244EB15782ADB167818DA14FA2D518F924CA8D815FA23598ACF498252E4B87592E4217C926FA81648D128E248F14F19124A11F4992141D28F2 ++:80480000AF425141AF24B315524A43F14A24414C5384AB344F83344A4F22D5CE038482480000000000282002210000001880080000004008480000000000000000005012F0F82A000011C012891253820032002426423868291108002C821204002041180A41241810815114002100118100001042080085F2757E402248B82211681200A2 ++:80488000402112014509411C0180528114280028228001651294142418009016A0121598242247222002442144324C036C2261421661448BA214608C842D3160128C5212251811942122550829D212B148228142032210B284830218244311D186014941E284015921E152110822472241132242144224C126D068024416714AF4437F40A1 ++:804900000200811221002022010041811042181801222800000065082400400200144C120200810080220180210270320B2228611140481241824241D8120100002901211608008440684100241245420400442A01C024A0212001004002810012D084F424CEA01431122392412C61118C9124842A810150838184224B4284114A82042981 ++:804980000662482662410028811C24147518D4324192241A741222044221846971C40216C811902E4334287E8450D380C4234311914181128D1128A18011415281818092142414892704234688042C110424002D414811121123332646829242384800293144004028028C83714874B9082E1200290212350244222E118423010084B042E2 ++:804A000042080000203248268401A0218514044485C61400184901002311182418C21A1601E149042EC4F06514301D18118800182121268411942281002122896181C012002C05842226010028004449C4122021811524012142124448002A01243042224287D680423A4833226133801191122873A2212004002C8264134632284AC218A2 ++:804A80008912E221046122408432128301222AA44200122290842128C816C28241002E4894258841F2BF2B002022281242081A020085010084271400610044220040042C41841502111602804802004A3111848481402848E4884164514100DF2A0B51902829A2211D12842C2132241A9223250840021C44984A324A014183628225A86144 ++:804B00007912A41241491282711451242828A28094141252861348C844122998822886F828444331481246325AA0121225114182C212C01312001C41280485228223515290282A2414020021102265224028C112A0141229012290124C846188428444438101A14128F06CFA100100402D21124422121102400444C0141816044440041647 ++:804B8000042512941443A41449811104410080044582051A4894C2448844881684480446F4543C002332222B14181221125052204102200187211220840200A01224121A0426020066040022001244482222A182812181825880852404CFE404400114001800408842180810082800201112820622000000402821210180411402000000E8 ++:804C00001800002140F28AF6B012028C032D18281001000015022400C0224C0200448100241220C1121281120020B1143442124820022A442801290261180052F025BC00001422001014220240010000001200000028414022C444000000206424414074420800002C7118020018213D9A14101111081E2100115400000010080010024295 ++:804C800081204204200440628400442410022C6441004A120210428844182214024F9E04154202128181112601891111418541022422182424904240889154122004002800800200220062808A816524892D0100C602005FA90B828210B2811204001022420C1140082222001200002400480021481008C0124212212424812542042100DE ++:804D0000230127144C013C022D8440088D4181212494404948431681424848044400282514921222291882022140012548081A0441414024011A64452035144844800228122504CF1F4B02336A838D5AA9E822531312105A112C528685022140022242126C4152848F22B214A322704222342448648F249114808181818422542449142421 ++:804D8000E2CCD528E18854288E181E12821B419A9D425C64245F1142F1112186C22333E1927318091712D5C114253A3181118541427832488432242A82042152F012122A81014825A234842A04405424182CE56115F242362F23B1180AD227212944022F2454824C021C12D2EB012414B1141255B418814256B52A4251711C01165C48859D ++:804E0000A433167612C214122584448C44D426E24114E621B144B1121424D584A121413267642315E444058B642F24B432D242E444E14479327488F414384C714262455E12448FE707120022008422842A0118805184291194224129B21484924490449044806441E045021E24E041021E24A02180021A02009088418938348843C38143E1 ++:804E800022342442CFCB41F21212313F237122F32B398FB2F13A389F93F225399FE3F33B399D391F73E111F1131BED1EE9C1362F61F136345E1256E442F244462B44CFC6F414167E626F4766216D144F24F334322F27F66E3449F364383AF224344D744F47F222322F26F244444F66B674B3E26E21276CAFCDF17C7C6F2BFBBE2EC7EA6FE4 ++:804F000061F686A26E642E142F23F24C74142E233FB717DA32F42B218D1AAF83F339295F92F3272BB5DD99F3393F143D29CD1C4D1A2D3E2F61F336344F657142E446F64456E5FCA8985E524F67BD62D764F116145F35F234224D57EFE5B116B27487F114544F65F63674272127244F44F57474CFC6B662F6BA8EA7E82F6FF5D6D4EFA8F8E5 ++:804F8000B2328FAAD1ECB6C6FE62646E544F65F548F7242F22F223623F21D333F22B2BF7E23F11F139299D1935FB23253F11D2315355F57D147818B632B334C1126D542B224B662C51EEAF82E825E523F326364F6455222F77E421F644562F84E44784D644013E444F45D2227146F676766F44F472362F2EFA1A288FA5B856B1D45D62AF95 ++:80500000A3F85A6A6F2D7C22B422B444E724F51E94143E33BF33F72A223F36F22B2B755F138F93D299F11B1B3F12F21221DD3B5F51712F7F1668C13E3A6B334F6293522B224B224F64F44A4AAF83F814164F6FF732222F25D466F162572CF271626FE4F56254784F43A2146E566F41F772226F64F476726F61F56A2E2F26F496A22D826FDA ++:8050800025F55E58AFEBFB3292EFE5F7CDCA2F46A4424B344F64F11DE400005024842A01144002140000122001002014022142002142002100000048A041241648020000004220046FA50C2450281222111810041428810010082003122800800212200112200180210116040044216880041A04901880818401BF52042D531F41D238F126 ++:80510000112C83F61124A3D641B24AD141B26A9921AF245985AF243924AF747924F8429747832DB54F83C4B54FA2E454F8244A1E254FA2645D4FA265594FA2E44DF2245A1F49F224521F49F22C121F49F268121F49B26AF18164AB161F41B24AB991B64AF98548AF64F9B448AF447BB4F842B4478B2F44FB34484EB44FA2F4BB76F0225A5D ++:805180004CE42275117C68F1112423F6112C2B1617C12F46F9112C2F24FB11284E9747838F7459844EB747814EA567814EA54FA2F148954FA2EC54DAA4E15CF2245AD671246B1C4FA271C1F8241A1B48CF2235818B121F48F42C121F49346A1741AD841F4996221F8956429E484E2696D862E289F4422416F842A48CF51AE800824800003D ++:80520000000026040000000010020088000040110884002008000040042800008110022501EBBA20080083012508811904284042088422121084024E2220022A04680041840000002C0100608C001042821424410200707605609800100110020000000000000040020020018014021200001004200100001880020014705103200848891E ++:80528000512184001C042226040081220041002315A22820062210018D4200560800182100E0810C26044082152442024031121B4A0011000000A10000100A0018002220022400802401440000000040040000100200180000F0AC45000000000028001001000000008002400200000000800200821800000000800100001FE30F18001092 ++:80530000280200142002100270288221022880048424680050820049014C011280012A01800400182021028100006F390A00008428003021800200008992120022002881246221000060416041A0212001B800420080011828400800F0FC7580010000000000400300002800800400000025080000000000180000000020010000DE7800B7 ++:80538000000000608100001800002848000000400222000000004002000000000000000000AF3E0D0000121842400410080010C411001222004444002200124812200122404401208201008004800120012822AF870480010084000000000012800128100442000042C1000000008301002004830100218022880100F04617000000184260 ++:80540000400C002001001C2101321004484400214A02800480012860811100800489010021A01282200180F227E600120018840018008400004C0128482002400400285048188001000045020022120000420000120028F0C8BD00000019011008000000000000000000000028800800002800001200008400180000F017460000000000E9 ++:8054800000000000000010040000000000000000000000000000000000D0BA0C000000000020080000000000000000000000000000002200000000000000F04FC8000000000000820000000000440000000000000000000000000000000000001FD108000000000000000000000000000000000000000000200200000000000000CFE5031A ++:80550000000000000000000000000000000080018200000000000000000000000000F09B160000000000440000000000004004002100000000180040080000000000800100005F25010000000000000000000000000000000000000000000000000000000000F04FFE00008100000000000000002100000000000010020000000000000087 ++:8055800000000000F02517000000100800000000000000000000000000000000000000000000800200008DB5000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000041000000000000000000000000000000000000000000C71A000000400800000000000021004400240018004002000064 ++:8056000000000000000000280000F0C86F000084000040040000400400000000000080080080010084000000000000180000F078C4000000000000000000000000000000000000000000000000000000000000FFE40F00000000400500800444001002400400218001882810021880088400008042080000280000B01401001400004840CE ++:805680005588281082044480022100448002214818808802214818448828842148408481421882041E148002211A01445C03000040010080041400000000000000000000002800008008000000288400000000BF7405000000004005008004440010024004002180018828908280018840084008804208000028000070220200000000006A ++:80570000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0021001400004800800221000028000000280048000000484004281082044400108204440010F2448D00000000000000000000000000000000000000000000000000000007 ++:80578000000000FFE40F000000000000140000000000000000008002000000800800000028840000000027E8000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000002800000000000000000000000000FFD704000000000000140000000000000000000000000000884E ++:3B580000000000804208000000F0B2BDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73 ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1161.201.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1161.201.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1161.201.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1161.201.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,20590 @@ ++# ++# $Id: FPGA_1161.201.hex 11553 2017-06-07 14:32:38Z dima $ ++# ++:020000040000FA ++:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:100010005599AA660C8500E004008C85C0018C828D ++:10002000BC008C8691778C43200008C90C8700F3B4 ++:100030000C83008104000400040004000400040098 ++:100040000400040004000400040004000400040090 ++:10005000040004000400CC813C138C8110812C84AA ++:1000600000004C8000F88C87FFFFCC8400A0CC827D ++:100070000020CC8080004C8600004C8100004C8524 ++:1000800000004C8300004C870000CC85D847CC434F ++:1000900000000000040004000C44000000000C8577 ++:1000A00000800A06000080610000000000000000DF ++:1000B0000000000000000000000000000000000040 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000000000000000000000000000020 ++:1000E0000000000000000000000040900000409070 ++:1000F0000000000000000000000000000000000000 ++:1001000000000000000000000000000000000000EF ++:1001100000000000000000000000000000000000DF ++:1001200000000000000000000000000000000000CF ++:1001300000000000000000000000000000000000BF ++:1001400000000000000000000000000000000000AF ++:10015000000000000000000000000000000000009F ++:10016000000000000000000000000000004000004F ++:10017000004000000000000000000000000000003F ++:10018000000000000000000000000000000000006F ++:10019000000000000000000000000000000000005F ++:1001A000000000000000000000000000000000004F ++:1001B000000000000000000000000000000000003F ++:1001C000000000000000000000000000000000002F ++:1001D000000000000000000000000000000000001F ++:1001E00000000000000000000000000000000020EF ++:1001F00000000020000000000000000000000000DF ++:1002000000000000000000000000000000000000EE ++:1002100000000000000000000000000000000000DE ++:1002200000000000000000000000000000000000CE ++:100230000000000000002500000000000000000099 ++:1002400000000000000000000000000000000000AE ++:10025000000000000000000000000000000000009E ++:10026000200000000000000004000000000000006A ++:10027000000000000000000000000000000000007E ++:100280000000000000D0800000000000000000001E ++:10029000000000000000000000000000000000005E ++:1002A000000000000000000000000000000000004E ++:1002B0000000050000000000000000000000000039 ++:1002C000000000000000000000000000000004002A ++:1002D000000004000000000000000000000000001A ++:1002E000000000000000000000000000000004000A ++:1002F00000000000040000000000000000000000FA ++:1003000000000000000000000000000000000000ED ++:1003100000000000000000000000000000000000DD ++:1003200000000000000000000000000000000000CD ++:1003300000000000000000000000000000000000BD ++:1003400000000000000000000000000000000000AD ++:10035000000000000000000000000000000000009D ++:10036000000000000000000000000000000000008D ++:10037000000000000000000000000000000000007D ++:10038000000000000000000000000000000000006D ++:10039000000000000000000000000000000000005D ++:1003A000000000000000000000000000000000004D ++:1003B0000000000000E48EEC0C8500400400040006 ++:1003C000040004000400040004000400CC26000023 ++:1003D0000000000000000C44008000A0CC260000BB ++:1003E0000000000000000C4400800060CC260000EB ++:1003F0000000000000000C4400800008CC26000033 ++:100400000000000000000C4400800088CC260000A2 ++:100410000000000000000C44008000C8CC26000052 ++:100420000000000000000C44008000A8CC26000062 ++:100430000000000000000C4400800098CC26000062 ++:100440000000000000000C4400800058CC26000092 ++:100450000000000000000C44002000A8CC26000092 ++:100460000000000000000C4400200068CC260000C2 ++:100470000000000000000C4400E00030CC2600002A ++:100480000000000000000C4400E000B0CC2600009A ++:100490000000000000000C4400E00070CC260000CA ++:1004A0000000000000000C4400E000F0CC2600003A ++:1004B0000000000000000C4400E00008CC26000012 ++:1004C0000000000000000C4400E00088CC26000082 ++:1004D0000000000000000C4400E00048CC260000B2 ++:1004E0000000000000000C4400E000C8CC26000022 ++:1004F0000000000000000C4400E00028CC260000B2 ++:100500000000000000000C4400E000A8CC26000021 ++:100510000000000000000C4400E00068CC26000051 ++:100520000000000000000C4400E000E8CC260000C1 ++:100530000000000000000C44001000E8CC26000081 ++:100540000000000000000C4400700040CC260000B9 ++:100550000000000000000C4400700030CC260000B9 ++:100560000000000000000C44007000B0CC26000029 ++:100570000000000000000C4400700070CC26000059 ++:100580000000000000000C44007000F0CC260000C9 ++:100590000000000000000C4400700008CC260000A1 ++:1005A0000000000000000C4400700088CC26000011 ++:1005B0000000000000000C4400700048CC26000041 ++:1005C0000000000000000C44007000C8CC260000B1 ++:1005D0000000000000000C4400700028CC26000041 ++:1005E0000000000000000C44007000A8CC260000B1 ++:1005F0000000000000000C4400700068CC260000E1 ++:100600000000000000000C44007000E8CC26000050 ++:100610000000000000000C4400700018CC26000010 ++:100620000000000000000C4400F000E8CC260000B0 ++:100630000000000000000C4400880040CC260000B0 ++:100640000000000000000C4400880060CC26000080 ++:100650000000000000000C44008800E0CC260000F0 ++:100660000000000000000C4400880010CC260000B0 ++:100670000000000000000C44008800D0CC260000E0 ++:100680000000000000000C4400880030CC26000070 ++:100690000000000000000C44008800B0CC260000E0 ++:1006A0000000000000000C4400880008CC26000078 ++:1006B0000000000000000C4400880088CC260000E8 ++:1006C0000000000000000C4400880048CC26000018 ++:1006D0000000000000000C44008800C8CC26000088 ++:1006E0000000000000000C4400880028CC26000018 ++:1006F0000000000000000C44008800A8CC26000088 ++:100700000000000000000C4400880018CC26000007 ++:100710000000000000000C4400880098CC26000077 ++:100720000000000000000C4400880058CC260000A7 ++:100730000000000000000C44008000400C85008098 ++:100740000A060000802000000000000000000000F9 ++:100750000000000000000000000000000088000011 ++:100760000000000000000000000000000000000089 ++:100770000000000000000000000000000000000079 ++:100780000000000000000000000000000000000069 ++:100790000000000000000000000000000000000059 ++:1007A0000000000000000400000000000000020043 ++:1007B0000000000000000000000000000000000039 ++:1007C0000000000000000000000000000000000029 ++:1007D00000000000000000100000000000000040C9 ++:1007E00000000000000000400000000000000000C9 ++:1007F00000000000000000100000000000000000E9 ++:1008000000000000000000000000000000000000E8 ++:1008100000000000000000000010000000000000C8 ++:1008200000000000000000000000000000000000C8 ++:100830000100000000000000002000000000000097 ++:1008400000000000000000000000000000000000A8 ++:100850000000000000000000000000000000000098 ++:100860000000000000000000000000000000000088 ++:10087000000000000000000009000000000000006F ++:100880000000000000000000000000000000000068 ++:100890000000000000000000000000000000000058 ++:1008A0000000000000000000000000000000000048 ++:1008B0000000000000000000000000000000000038 ++:1008C000000000000000000000000000FFFFFFFF2C ++:1008D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28 ++:1008E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 ++:1008F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 ++:10090000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 ++:10091000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 ++:10092000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 ++:10093000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 ++:10094000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00ECC9 ++:10095000DE880C44008000E00A06000040510000E0 ++:100960000000000000000000000000000000000087 ++:100970000000000000000000000000000000000077 ++:100980000000000000000000000000000000000067 ++:100990000000000000000000000000000000000057 ++:1009A0000000000000000000000000000000000047 ++:1009B0000000000000000000000000000000000037 ++:1009C00000000000000000000000840000000000A3 ++:1009D0000000000000000000000000000000000017 ++:1009E0000000000000000000000000000000000007 ++:1009F00000000000000000000000000000000000F7 ++:100A000000000000000000000000000000000000E6 ++:100A100000000000000000000000000000000000D6 ++:100A200000000000000000000000000000000000C6 ++:100A300000000000000000000500000000000000B1 ++:100A40000000000000000000050000000000008819 ++:100A50000000000000000000000000000000000096 ++:100A60000000000000000000000000000000000086 ++:100A70000000000000000000000000000000000076 ++:100A80000000000000000000000000000000000066 ++:100A90000000000000000000000000000000000056 ++:100AA000000000000000000000000000000900003D ++:100AB0000000000000000000000000000000000036 ++:100AC000820000000000000000090000000000009B ++:100AD0000000000000000000000000000000000016 ++:100AE0000000000000000000000000000000000006 ++:100AF00000000000000000000000000000000000F6 ++:100B000000000000000000000000000000000000E5 ++:100B100000000000000000000000000000000000D5 ++:100B200000000000000000000000000000000000C5 ++:100B300000000000090000000000000000000000AC ++:100B40000000000010000000100000000000000085 ++:100B50000000000000000000000000000000000095 ++:100B60000000000000000000000000000000000085 ++:100B70000000000000000000000000000000000075 ++:100B80000000000000000000000000000000000065 ++:100B90000000000000000000000000000000000055 ++:100BA0000000000000000000000000000000000045 ++:100BB0000000000000000000000000000000000035 ++:100BC00000000000000090000020880000000000ED ++:100BD0000000000000000000000000000000000015 ++:100BE0000000000000000000000000000000000005 ++:100BF00000000000000000000000000000000000F5 ++:100C000000000000000000000000000000000000E4 ++:100C100000000000000000000000000000000000D4 ++:100C200000000000000000000000000000000000C4 ++:100C300000000000000000000000000000000000B4 ++:100C400000000000000000000000000000000000A4 ++:100C50000000000020000000000000000000000074 ++:100C60000000000000000000000000000000000084 ++:100C70000000000000000000000000000000000074 ++:100C80000000000000000000000000000000000064 ++:100C90000000000000000000000000000000000054 ++:100CA0000000000000000000000000000000000044 ++:100CB0000000000000000000000000000000000034 ++:100CC0000000000000000000000000000000000024 ++:100CD0000000000000000100000000000000000013 ++:100CE0000000000000000000000000000000000004 ++:100CF00000000000000000000000000000000000F4 ++:100D000000000000000000000000000000000000E3 ++:100D100000000000000000000000000000000000D3 ++:100D200000000000000000000000000000000000C3 ++:100D300000000000000000000000000000000000B3 ++:100D400000000000000000000000000000000000A3 ++:100D50000000000000A001000000000000C0000032 ++:100D60000000000000000000000000000000000083 ++:100D70000000000000000000000000000000000073 ++:100D80000000000000000000000000000000000063 ++:100D90000000000000000000000000000000000053 ++:100DA0000000000000000000000000000000000043 ++:100DB0000000000000000000000000000000000033 ++:100DC0000000000000000000000000000000000023 ++:100DD000000000000000000008000000000000808B ++:100DE0000000000000000000000000000000000003 ++:100DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:100E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:100E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:100E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:100E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:100E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:100E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:100E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:100E7000FFFF0094DA5A0C44008000480A06000084 ++:100E80000041000000000000000000000000000021 ++:100E90000000000000000000000000000000000052 ++:100EA0000000000000000000000000000000000042 ++:100EB0000000000000000000000000000000000032 ++:100EC00000000040000000000000000000000000E2 ++:100ED0000000000000000000000000000000000012 ++:100EE0000000000000000000000000000000000002 ++:100EF00000000000000000000000000000000000F2 ++:100F000000000000FFFFFFFFFFFFFFFFFFFFFFFFED ++:100F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 ++:100F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 ++:100F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 ++:100F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 ++:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 ++:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 ++:100F8000FFFFFFFFFFFF009C16A90C440080002814 ++:100F90000A06000000410000000000000000000000 ++:100FA0000000000000000000000000000000000041 ++:100FB0000000000000000000000000000000000031 ++:100FC0000000000000000000000000000000000021 ++:100FD0000000000000000000000000000000000011 ++:100FE0000000000000000000000000000000000001 ++:100FF00000000000000000000000000000000000F1 ++:101000000000000000000060000000000000000080 ++:101010000000000000000000FFFFFFFFFFFFFFFFD8 ++:10102000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10103000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10104000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 ++:10105000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 ++:10106000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 ++:10107000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 ++:10108000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 ++:10109000FFFFFFFFFFFFFFFFFFFF007844650C44E9 ++:1010A000008000680A0600008020000000000000A8 ++:1010B0000000000000000000000000000000000030 ++:1010C0000000000000000000000000000000000020 ++:1010D0000000000000000000000000000000000010 ++:1010E0000000000000000000000000000000000000 ++:1010F00000000000000000000000000000000000F0 ++:1011000000000000000000000000000000000000DF ++:10111000000000000000000000800000000000004F ++:1011200000000000000000000000000000000000BF ++:1011300000000000000000000000000000000000AF ++:10114000000000000000000000000000000000009F ++:10115000000000000000000000000000000000008F ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:10118000000000000000000000000000000000005F ++:10119000000000000002000000000000000000004D ++:1011A0000000000000000000000000008C000000B3 ++:1011B000000000000000000000000000000000002F ++:1011C000000000000000000000000000000000001F ++:1011D000000000000000000000000000000000000F ++:1011E00000000000000000000000000000000000FF ++:1011F00000000000000000000000000000000000EF ++:1012000000000000000000000000000000000000DE ++:1012100000000000000000000000000008200000A6 ++:1012200000000000000000000000000000000000BE ++:10123000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE ++:10124000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE ++:10125000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10126000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10127000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10128000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10129000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:1012A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:1012B000FFFF0050F1CA0C44008000D80A0600006D ++:1012C000A86B00000000000000000000000000000B ++:1012D000000000000000000000000000000000000E ++:1012E00000000000000000000000000000000000FE ++:1012F00000000000000000000000000000000000EE ++:1013000000000000000000000000000000000000DD ++:1013100000000000000000000000000000000000CD ++:10132000000000000000000000000100000000209C ++:1013300000000100000000000000000000000000AC ++:10134000000000000000000000000000000000009D ++:10135000000000000000000000000000000000008D ++:10136000000000000000000000000000000000007D ++:10137000000000000000000000000000000000006D ++:10138000000000000000000000000000000000005D ++:10139000000000000000000000000000000000004D ++:1013A00000000000000000400000000000000040BD ++:1013B000000000000000000000000000000000002D ++:1013C000000000000000000000000000000000001D ++:1013D000000000000000000000000000000000000D ++:1013E00000000000000000000000000000000000FD ++:1013F00000000000000000000000000000000000ED ++:1014000000000000000000000000000000000000DC ++:1014100000000000000000000000000000000000CC ++:1014200000000000000000000000001008000000A4 ++:1014300000000001090000000000000000000000A2 ++:10144000000000000000000000000000000000009C ++:101450000000000000000200000000000000030087 ++:10146000000000000000000000000000000000007C ++:101470000000000000000400000003000000040061 ++:10148000000000000000000000000000020000005A ++:10149000000000000000000000000000000000004C ++:1014A000000000000000000000000000000000003C ++:1014B000000000000000000000000000000000002C ++:1014C000000000000000000000000000000000001C ++:1014D000000000000000000000000000000000000C ++:1014E00000000000000000000000000000000000FC ++:1014F00000000000000000000000000000000000EC ++:10150000000000000000000000000080000000005B ++:1015100000000000000000000000000000000000CB ++:1015200000000000000000000000000000000000BB ++:1015300000000000000000000000000000000000AB ++:10154000000000000000000000000000000000009B ++:1015500000000400000000000000008900040000FA ++:101560000001002000000000030120010000000035 ++:10157000000000000000000000000020000000004B ++:1015800000002000000000000010800000C00000EB ++:10159000000000000000000000000000000000004B ++:1015A00008000000000004000020002000200000CF ++:1015B000000000000001000000000000000000002A ++:1015C00021000000001000000000000000000000EA ++:1015D0000000002101000020000000000004028043 ++:1015E0000000000400800000000002040120000050 ++:1015F0000000000002000000000000000080000069 ++:1016000000000000010000000000008020000080B9 ++:1016100000000000000000100000000000000000BA ++:101620000000010000000000010000800080008038 ++:10163000000000000000002000000000000000008A ++:10164000000000000000008000000000000000001A ++:1016500000900000009000000000009000000000DA ++:101660000002000000C000A0000000000000000018 ++:101670000000000000000010000400200000000036 ++:10168000000000000000000000000000000000005A ++:10169000000000000000000000000000000000004A ++:1016A000000000000010000000000000000000002A ++:1016B0000002100800000000000000000000000010 ++:1016C000000000000000000000000000000000001A ++:1016D000000000000000000000000000000000000A ++:1016E000000000800000000000000000000000007A ++:1016F00000000000000000000000000000000000EA ++:1017000000000000000000000000000000000000D9 ++:1017100000000000000000000000000000000000C9 ++:101720000000000000000080000000000000000039 ++:1017300000000080018000000000000000000000A8 ++:101740000000000000000000000000000000000099 ++:1017500000000000008500010001000400000000FE ++:101760000300410000000000000000040000000031 ++:101770000000000000000000000000000000000069 ++:101780000000000000C00000000000A08000000079 ++:101790000001800100000000400000000000000087 ++:1017A000000000000000000005002100000003010F ++:1017B0000000000000000000000000000000000029 ++:1017C0000000000000000000000000000000000019 ++:1017D000000000000000A00400040004008200419A ++:1017E0000000000010000000000000000880000061 ++:1017F00000000000000000008200840000000000E3 ++:1018000000000000000000000000000000000400D4 ++:10181000000000202002000000000900000000007D ++:101820000000000000001000000000000000100098 ++:1018300000040000000000000000000000000000A4 ++:101840000000000000000000000000000000000098 ++:10185000000000000000000000000000000004A0E4 ++:101860000000000000000000000040000000000434 ++:101870000000000420000000000000000000000044 ++:1018800000000000009000010400000009000000BA ++:101890000000000000000020000000000000000028 ++:1018A0000000000000000000000008840810040090 ++:1018B000040000A00000000200000000100000A0D2 ++:1018C0002020000000000000000000000088000050 ++:1018D0000000000000000000000000000000000008 ++:1018E00001000000000000000000000001000000F6 ++:1018F00000000000000001000000000000000000E7 ++:1019000000000000000000000004000000000000D3 ++:101910000000000000000000008000000000000047 ++:1019200000000000880000000000000001000180AD ++:101930000100010000000000008000000000000025 ++:101940008400008000000000820000000000000011 ++:101950000000000000000000000000000000000087 ++:101960000000000000000000000000200000000156 ++:101970000000800000840084080080040000000053 ++:10198000000000C000000000000000000000000097 ++:101990000000000080008001800000A00000000026 ++:1019A0000000000000A000002100000000A00000D6 ++:1019B0001010000000A000024000090000C0000854 ++:1019C0001000000200008000000100C18000000043 ++:1019D0000000000000000000000000000000000007 ++:1019E0000000000000000000000000000080000077 ++:1019F000000200000400000000000000048000005D ++:101A000000000800000000000000000000000000CE ++:101A1000000000000000040040400800000000003A ++:101A200000000000000000000000000000000000B6 ++:101A300000000080000000000080010000000000A5 ++:101A400000910000008000000400842000200400B9 ++:101A50000000000000000000000000000000000086 ++:101A60008003210900000000800008000000000041 ++:101A700091100009000409080000000000000000A7 ++:101A80000000000000000000000000000000000056 ++:101A9000000004000000000080830991004141899A ++:101AA00000000000000000000000808304000080AF ++:101AB00000808083A08000800000000320000000E0 ++:101AC00000400000020000000000000000800080D4 ++:101AD0000080000000000000000000000000000086 ++:101AE0000000C001010182000000C000010082006E ++:101AF0000000910100000000010100000000000052 ++:101B000000000000000000000000000000000000D5 ++:101B100000000000000000000000908385840009A0 ++:101B20000111000000000000000000008883009008 ++:101B3000889000088883919088900000000101003F ++:101B40000000000100000000000000000000101074 ++:101B50000408000800000000000000000000000071 ++:101B6000000000000000010000C0010100000000B2 ++:101B700000000101000001C001010101008200001C ++:101B80000000010000000000000000000000000054 ++:101B90000000000001000100018201019101828822 ++:101BA0008910C18200000000000000000000000158 ++:101BB0000184000001894001918404008301001028 ++:101BC00000C000080100000000000000000000014B ++:101BD000A00008000808000000000000000000004D ++:101BE0000000000000040000410000000309400064 ++:101BF0000900090009210000418004020309048052 ++:101C000009001100090000000000000000000000B1 ++:101C10000000000000110200410021800303911127 ++:101C20000080899140880000000000000000000052 ++:101C300000114100000003110011C10000008311D8 ++:101C4000008000000080030000000000000200008F ++:101C500000400000800080800900000000000000BB ++:101C6000090000000000000000000000000900035F ++:101C70000000000000000080094100050009400349 ++:101C800000020041090400090000000000000000FB ++:101C900000000000000080000000000000000000C4 ++:101CA00002828091899191830080000000000000F1 ++:101CB0000000020000099100800302008009110069 ++:101CC0008083000009400000800300000000020043 ++:101CD0000080008000000080008000000000000004 ++:101CE00000000000000000000000000000000001F3 ++:101CF0000201000000000000008800010001000156 ++:101D000041010001000101009001000000000000FD ++:101D100000000000000000002000000000000000A3 ++:101D200000000189901091A08991008000000000BE ++:101D30000000000001000001A10090010190C0031B ++:101D400005049083880000010000080100000000E5 ++:101D5000010000880010A0A0820800080000000018 ++:101D60000000000000000000000000000188018267 ++:101D700000000001000000A10082000101A0018517 ++:101D800001830101000000A000000000000000002D ++:101D90000000000000000000000000000000000043 ++:101DA00000000000C18911018201918800800000BB ++:101DB0000000000000008300900008000000830085 ++:101DC0009004C000C088010000000001000001086C ++:101DD00001020000000010100800100000100000B8 ++:101DE0000000000000000000000000000000038070 ++:101DF000048000000003000000C000820041098050 ++:101E00002191094111210000008200020000000020 ++:101E100000000000000000000000000000000000C2 ++:101E200000000000000802898441110291800080B6 ++:101E300000000040000000008300800080000000DF ++:101E400083008000800000000300000000100000FC ++:101E500003802080000002000010800080000080CD ++:101E60000000000000000000000000000000000072 ++:101E700000880013D000828800410042C200008226 ++:101E8000000000132000000000000013C2008100C9 ++:101E900000000000000000000000000BC100000076 ++:101EA000000000004820004200000083C1000084C0 ++:101EB00000000000000000000000000000420000E0 ++:101EC000000000000042000000000000004210007E ++:101ED0000000000000224800000000000013000085 ++:101EE00000000000000000000000000000000000F2 ++:101EF0000000FF000000FF000000000000000000E4 ++:101F0000000000FB0004C102414100000000FF0C82 ++:101F1000FF30000000000000000000000000000092 ++:101F20000000000000000000000091089900C0308F ++:101F3000C3FF00000000000000000000FFFF0000E1 ++:101F40000F0F0000FFFF00000F0F0000FFFF000059 ++:101F50000F0F0000E7E78100000000000000000014 ++:101F60000000000000000000000000000000000071 ++:101F700000000000FF000000FF0000000000000063 ++:101F80000000000000FF0000C3004242000000000B ++:101F9000FF0CFF3000000000000000000000000007 ++:101FA00000000000000000000000000099009900FF ++:101FB000C030FFFF00000000000000000000000033 ++:101FC00000000F0F0000000000000F0F00000000D5 ++:101FD00000000F0F0000E7E7810000000000000094 ++:101FE00000000000000000000000000000000000F1 ++:101FF00000000000000000000000000000000000E1 ++:1020000000000000000000000000000000000000D0 ++:1020100000000000000000000000000000000000C0 ++:10202000000000000000000000000001044000006B ++:1020300000000000000000000000000000000000A0 ++:102040000000000000000000000000000000000090 ++:102050000000000000000000000000000000000080 ++:102060000000000000000000000000000000000070 ++:102070000000000000000000000000FFFFFF0F0F45 ++:10208000000000008181CFFF0000002099000F00B8 ++:102090000000000099003FFF000000000000000069 ++:1020A000000000000000000000000000000003002D ++:1020B0005600CC00FFFFFFBD000000000000666678 ++:1020C00066660000FFFF0000F0F00000FFFF000068 ++:1020D000F0F000003C3CFFFF0000000000000000AA ++:1020E00000000000000000000000000000000000F0 ++:1020F00000000000000000000000000000FFFFFFE3 ++:102100000F0F000000008181FFFF00000000990018 ++:10211000F000000000009900FFFF00000000000038 ++:1021200000000000000000000000000000000000AF ++:1021300003006600F000FFFFFFFF0000000000004A ++:1021400066666666000000000000F0F00000000017 ++:102150000000F0F000003C3CFFFFFFFF000000002B ++:10216000000000000000000000000000000000006F ++:10217000000000000000000000000000C0C7C07D9B ++:1021800030B04103008600640090000000860260C9 ++:1021900000B200100086006000B0000000000000E7 ++:1021A000000000000086006108B00005000000008B ++:1021B0000000000000840440008900850000000049 ++:1021C00000000000084002C1018000B44940024103 ++:1021D000018000044940A2C7016108B4414008865B ++:1021E0000071009000000086008000800000000068 ++:1021F0000080010000000000000009000000000055 ++:1022000000000000000000000000FFFF00000000D0 ++:1022100000000000000000000000000000000000BE ++:1022200000000000000000000000000000000000AE ++:102230000000000000000010000000F000F00000AE ++:10224000000000000000000000000000000000008E ++:102250000202030000000000000000000000000077 ++:1022600000000000FFFF0000000000000000000070 ++:10227000000000200000000000000020000001001D ++:10228000000000000000000000000000FFFF000050 ++:10229000000000000000000000000000000000003E ++:1022A000000000000000000000000000000000002E ++:1022B00000000000000000000000000000F030C03E ++:1022C000000000000000000000000A0A0F000000EB ++:1022D0000000020203000F003C00000000000000AC ++:1022E000000000000000FFFF0000000000A00C0044 ++:1022F000000000000000000002000040000000009C ++:1023000002000000000000000000000000000000CB ++:1023100000000000000000000000000000000000BD ++:1023200000000000000000000000000000000000AD ++:1023300000000000000000000000CB080B0B00F0C4 ++:1023400040B00000000000000000000000C000C31A ++:1023500000000000000000003000500000000000FD ++:10236000000000000000000000000000000000006D ++:10237000000000004000000000000000000000001D ++:10238000000000000000000000000000000000004D ++:10239000000000000000000000000000000000003D ++:1023A000000000000000000000000000000000002D ++:1023B000000000000000000000000000CB083C000E ++:1023C00000F000F00000000000000000000000C06D ++:1023D00000000000000000F000AA300050000000E3 ++:1023E00000000000000000000000000000000200EB ++:1023F00002000500000000000000000000000000D6 ++:1024000000000000000008000000000000000200C2 ++:102410000200000003000000400000002100000056 ++:102420000000000011000000040000000000000097 ++:10243000000000000000000000000000000002009A ++:102440000000000004000000000000000000000088 ++:10245000000000000000000000000000000021005B ++:10246000000000000000210000000000000000004B ++:10247000000000000000000000000000000000005C ++:102480000000000000000010010000000000000932 ++:10249000000000000000000000000100000000003B ++:1024A000000000000000000000000100000000002B ++:1024B000000000000000000000000000000000001C ++:1024C000000000000000000000C00000000000004C ++:1024D00000000000000000000000000000000000FC ++:1024E00000000000000000000000000000000000EC ++:1024F00000000000000000000000000000000000DC ++:1025000000000000000000000080000100018005C4 ++:102510000009000000010004800400010001000027 ++:102520002101000000010001000000000001000086 ++:102530000000000000000000040000000000000097 ++:10254000002000000000000000000040000000002B ++:10255000000000000000000000000000000000007B ++:10256000002000000000000000000000000000004B ++:10257000000000000000000000000000000000005B ++:102580000000000000000000000000000204002025 ++:1025900008C000200000000400800280002000022B ++:1025A00000000004020000040004002000000004F9 ++:1025B00000000000000000000021010000000000F9 ++:1025C000000000800000000000000000008000000B ++:1025D00000000000000000000000000000000000FB ++:1025E000000000800000000000000000000000006B ++:1025F00000000000000000000000000000000000DB ++:102600000000000000000000000000000000008248 ++:1026100005400040000000880040004000C000006D ++:1026200000000000004003000004009000020000D1 ++:102630000000000000000000000000840000000016 ++:102640000000000000000000000000A000040000E6 ++:10265000000000000000000000000000000000007A ++:1026600000000040004000000000000000000000EA ++:10267000000000000000000000000000000000005A ++:10268000000000000000000000000000000000004A ++:1026900000000090000000050000000040802000C5 ++:1026A00082000000C00000800000008000000000E8 ++:1026B00000000000000000000000C000000000005A ++:1026C0000000000000000003000000000000008483 ++:1026D0000000000010050041000000000000C000E4 ++:1026E00000000000000000000000000000000000EA ++:1026F0000000000000008400000000000000000056 ++:102700000000000000000000820000000000000047 ++:1027100000000000410010019041100108840040B9 ++:10272000100000008000008802000000100000007F ++:1027300000018000009000200000000010100084C4 ++:1027400000840800000000820004000000900800DF ++:102750000005000000000000000000000000000074 ++:1027600000000000000000008000000010000300D6 ++:102770000300000000040000002000000000000032 ++:102780000000000000000000000000000000000049 ++:102790000000000000000000002008840808082154 ++:1027A00000800000A0004000000002000000840043 ++:1027B00082000204400000000880C0001000108069 ++:1027C00000000000A00010000000108000000000C9 ++:1027D0000000008200000000000000000000000077 ++:1027E00000000000000000000000400000000000A9 ++:1027F00000000000100000800000008000000000C9 ++:1028000000000000000000000000000000000000C8 ++:10281000000000000000004000A1000041841020E2 ++:102820001040000021A0000021000002080000204C ++:1028300000000004092040000000000440000000E7 ++:10284000000000000500000000000000000000C0C3 ++:102850000000000000000000000000000000000474 ++:1028600000000002000000002000400004002100E1 ++:102870008002800080020200C000000040000220B0 ++:1028800041210001030100210000000000000000C0 ++:1028900000000000000000000080000400000005AF ++:1028A00011001000001000004000000000000400B3 ++:1028B000C080000000850080010000000080010051 ++:1028C00000000000000000210000000000030000E4 ++:1028D000002100000021002100000009000000008C ++:1028E000008000000000C0000000010301000100A2 ++:1028F00000002080200020A000000900000001004E ++:1029000000800082C002C00200820000820000003D ++:102910001000000000000000100088C0411080007E ++:102920000040004041A0000000000000884000007E ++:1029300000C0000000000090000110000001200015 ++:1029400040030000000000840000000000000000C0 ++:102950000020000000000000009000000040000087 ++:10296000008400400000020000000000000005009C ++:1029700040000000002000000500000000114000A1 ++:1029800005204000000000200020000000000000A2 ++:1029900000000000000000000000000009000080AE ++:1029A0000800108884000000C00000000000408083 ++:1029B000000000000000C000000000201000002007 ++:1029C000010001A0840000008440100000001000FD ++:1029D000000000A10000C000000000000000000096 ++:1029E00000000000000000000000000000000000E7 ++:1029F00000000100000000800000000000000090C6 ++:102A000091000080010000000080008000000000B4 ++:102A1000000000000000000000000000000003892A ++:102A20002089042105900505090240110341008019 ++:102A30000580088000000000000000000011110364 ++:102A400000090002031100008000200000000000C7 ++:102A50000000000000000000000000000000000076 ++:102A60000000000000000000000000000000000066 ++:102A70008000000089090000000300004009008078 ++:102A80000003801000000000008300000903030021 ++:102A90000000000000000000000000000000000036 ++:102AA000098289A100090110010101000000010152 ++:102AB0000088890801C000C000000000000000007C ++:102AC0008901000100010100000040000100000038 ++:102AD000000000008800000000000000000000006E ++:102AE00000000000000000000000000000000000E6 ++:102AF0000000900084009101000000C1A0C0A1C1AD ++:102B000000080001080100000000000502C0A0024A ++:102B100000000000000000000000000000000000B5 ++:102B20000000400000C0898383098300C00008843E ++:102B300083000040000000000102001000000000BF ++:102B40000000000000000082000000000000000003 ++:102B50000000000000000000000100000000010073 ++:102B60000001000000000000000000000000000064 ++:102B7000000000000100A0A0880105000801A001DC ++:102B8000C0000182080009008800830004000200E0 ++:102B90000200C10000000000000000000000000072 ++:102BA0000000000009000080210389050500820063 ++:102BB00000408910000804000500030000800000A8 ++:102BC0000000000000000000000000000000000005 ++:102BD00000000000000000000000001005000500DB ++:102BE00021000509000002000000000000000000B4 ++:102BF00000000000000010000000800903008008B1 ++:102C000000030000038080008800800083008005AE ++:102C100000000000030000000000000000000900A8 ++:102C20000000000000000309020911098080000073 ++:102C30000002400941C10080008002800080000045 ++:102C4000000900008000030021000009910300003A ++:102C50000000000000800000000000000080000074 ++:102C60000000000000000000000000000000000064 ++:102C700000000000000000000000000008218003A8 ++:102C8000000000800240808300000080101000835C ++:102C90000080000080000003000000000000000031 ++:102CA0000000000000000000019001108589C08232 ++:102CB00010020084000301110008A01001080008A0 ++:102CC000000000000000820001000100000111016D ++:102CD000000000C000C0008200000000000000886A ++:102CE00000000000000000000000000000000000E4 ++:102CF00000000000000000000000000000A000092B ++:102D0000880590C0A090010188090400001000010E ++:102D10000089000402A00802000100000000000079 ++:102D20000000000000000000000083918885400042 ++:102D300010080091019100000090021004000401AD ++:102D4000040000000000000000010000000000007E ++:102D50000000000000000000000000000000000073 ++:102D60000000000000010000000000000000000062 ++:102D70000000000000000000000000000101011040 ++:102D800000000090C189A10008010090010101002C ++:102D90000000008803000208C000A0C0000000007E ++:102DA00000000000000000000000000089A11103E5 ++:102DB0009010000008822010001100000000001098 ++:102DC00000100000000000100000001000000000D3 ++:102DD00000000000000000000000000000000000F3 ++:102DE00000000000000000030003000000000000DD ++:102DF00000000000000000000000000000000302CE ++:102E0000088004000980034009008021008003112C ++:102E1000080000000080030000858500008000009D ++:102E200000000000000000000000000000000000A2 ++:102E30000010480082410000001010000041000016 ++:102E40000022020000000000000BD0000041000042 ++:102E500000830200424800000083000000000000E0 ++:102E60000010C100000000000000C100420000008E ++:102E700000000000D0000000000000000000000082 ++:102E800000000013C20000000000001310004260A8 ++:102E900000000022020000000000001300000000FB ++:102EA0000000000000000000000000000000000022 ++:102EB000000AFF5F00FF00FF550055FF00AF50FF05 ++:102EC000000000000000000000000000F0F0F0F042 ++:102ED00000000000000000000000000000000000F2 ++:102EE00000000000000000000000000000000000E2 ++:102EF00000000000000000000000000000000000D2 ++:102F000000000080BFBF000000FF000000FF0000C5 ++:102F100000FF000000FF000000FF00000F0F000096 ++:102F2000FFFF0000000000000000000000000000A3 ++:102F300000000000FFFF08DF08DF550055FF00FF1D ++:102F400000FF000000000000000000000000F0F0A2 ++:102F5000F0F000000000AAAA55AA0000000000003E ++:102F60000000000000000000000000000000000061 ++:102F70000000000000000000000000000000000051 ++:102F80000000000000003F3F000000FF000000FFC5 ++:102F9000000000FF000000FF000000FF00000F0F16 ++:102FA0000000000000000000000000000000000021 ++:102FB00000000000FF00FF00FFFF00413A3C3C3CE6 ++:102FC000FFFF00000000000000F000AAC3C3C3C35D ++:102FD000555555550000000000000000000000009D ++:102FE00000000000000000000000000000000000E1 ++:102FF00015F05500000000000000C3C3C3C300006B ++:10300000000000000000F0F0F0F03C3C0000F0F0A8 ++:103010000000FFFF0000FF000000F0F00000F0F0F3 ++:1030200000005555FFFF00000000000000000000F8 ++:10303000000000000000FF003F30FFBE00003A3CEF ++:103040003C3CFBFB0808000000000FFF55FFC3C31A ++:10305000C3C355555555DF209A9A00000000000063 ++:103060000000000000000000000000000000000060 ++:10307000000015005500000000000000C3C3C3C3DA ++:103080000000000000000000F0F0F0F03C3C000008 ++:10309000F0F0000000000000FF000000F0F0000071 ++:1030A000F0F000005555FFFF000000000000000098 ++:1030B00000000000000000000086006008B0000072 ++:1030C0000006006008B000000086004108B0001053 ++:1030D0000086006108B000000086046100B20000B4 ++:1030E0000086006100900000008600E10890000565 ++:1030F00000000200000000000000000000000800C6 ++:1031000000000000000000000000118601F00084B3 ++:103110004940A2C75180A8844940A2470160008469 ++:10312000494002C7018000844140000000000000C7 ++:1031300000000000000000000000FCFCFFF05C55F7 ++:10314000F0FF000000000F170F0FBAAAEAAA82B220 ++:10315000AAAA00000000000000000000000000001B ++:103160000000000000000000A00000000000FFFFC1 ++:10317000000000000000000000000000000000004F ++:10318000000000000000000000000000000000003F ++:103190000A00000000000000020200000000000021 ++:1031A0000000000000000008000000000000000017 ++:1031B000000000000000008001000000C0C000F01E ++:1031C0003C35000F000000000F170F0F8AAA2AAA33 ++:1031D00000300000000000000000000000000000BF ++:1031E00000000000000000000F00A0000000000030 ++:1031F000FFFF0000000000000000000000000000D1 ++:1032000000000000000000000000000000000000BE ++:1032100000000000000000000A00000000000000A4 ++:103220000000FFFF0F0F000000080800080000006A ++:103230000000000000000000002000000000F03C42 ++:10324000F0F03C55555500000000FCFC505FF7FFC6 ++:10325000200000000000000000000000000000004E ++:10326000000000000000000000000000000000005E ++:10327000000000000000000000000000000000004E ++:10328000000000000000000000000000000000003E ++:10329000000000000000000000020000000000002C ++:1032A00000000000C08070B000000000000020009E ++:1032B000000000000000000000000000000002000C ++:1032C000F03C3C3C3C553C3C000000000C0C505F8A ++:1032D000F7FF2000000000000000000000000000D8 ++:1032E00000000000000000000000000000000000DE ++:1032F00000000000000000000000000000000000CE ++:1033000000000000000000000000000000000000BD ++:1033100000000000000005000000000200000100A5 ++:10332000010000000000004070B005000000000037 ++:10333000200000000000000000004000000000002D ++:10334000000004000000000009200400000011003B ++:103350001100040000008300110000880400000038 ++:10336000000000000000000000000000000000005D ++:103370000000040000000000000000000000000049 ++:10338000000000000000000000000000000000003D ++:10339000000000000000000000000000000000002D ++:1033A000000000000000000000000000000000001D ++:1033B000000000000000000000000000000000000D ++:1033C0000000000020000000000088000000000055 ++:1033D0000400000000000000080090000000000051 ++:1033E00000000000000000000000000000000000DD ++:1033F00000000000000008000000000000000000C5 ++:10340000000000000080000000000000000000003C ++:1034100000000000000000000000000000000000AC ++:10342000000000000000000000000000000000009C ++:10343000000000000000000000000000000000008C ++:1034400000000000000000000000000080000000FC ++:103450000000008880000000000000000010000054 ++:103460000000000000C0000000000000000000009C ++:1034700000100000000000000000000000400000FC ++:103480000001000400040000000000000000000033 ++:10349000020000000000000000000000000000002A ++:1034A000000000000000000000000000000000001C ++:1034B000000000000000000000000000000000000C ++:1034C0000000000000000000004100410020100842 ++:1034D0000021001000411010000000000000004119 ++:1034E00000000000000000000000000000000000DC ++:1034F000000000900010001000000000000000A17B ++:1035000000000010008000800000000000000000AB ++:103510000000000000080008000800000000000093 ++:10352000000000000000000000000000000000009B ++:103530000008000000000000000000000000000083 ++:103540000000000000000000000000820000008871 ++:1035500000880000000000000020090000000000BA ++:103560000082004000000000000000000000000099 ++:103570000000000000000200000000000000000049 ++:10358000000000000000000000000000000000003B ++:10359000000000100000000000000000000000001B ++:1035A000000000000000000000000000000000001B ++:1035B00000000000000021000000000000000000EA ++:1035C00000000000000000000000000000030003F5 ++:1035D000002084211000A0100810101008200020E6 ++:1035E00000000010000000000002000000000000C9 ++:1035F00000000000100000000000000000000000BB ++:1036000000000000000000000000000000000000BA ++:10361000000000000000000000000000C0000000EA ++:103620000000000000008400000900090000000004 ++:10363000000000000000000000000000000000008A ++:10364000000000000000000000000000000020005A ++:1036500010000090038405009000900002004100DB ++:1036600005A04000A18200000300A100410041002C ++:1036700041000300410005000000200000000000A0 ++:103680000000000100000000000000010800000030 ++:10369000000000000000000000000000000020000A ++:1036A000000000000000000000000000000000001A ++:1036B000000000880000000000000000000005007D ++:1036C00000000000000000000000000000000000FA ++:1036D0000208A00082000800000008000441080061 ++:1036E0000041A000010002000000000004000000F2 ++:1036F000C0000000C00000000000820000000000C8 ++:103700000041000000100020000000000020000028 ++:1037100000000000000000000000000000000000A9 ++:103720000000000000000000000000000000000099 ++:103730000000000000000000000000000000000089 ++:103740000000000000000000000000000000000079 ++:10375000000010001090000005880040058841001E ++:103760004100118803882188000009001000000032 ++:1037700021080000110040001000000005001000AA ++:1037800010001100030010000000000010000000F5 ++:103790000008000000000000000000000000000021 ++:1037A0000000000000000000000000000000000019 ++:1037B0000000000000000000000000000000000009 ++:1037C00000000000000000000000000000000000F9 ++:1037D00000000000902100000020022002200000D4 ++:1037E000004100200221C000101110000220000042 ++:1037F00000000004002100000100000000000000A3 ++:1038000000000000000000000000000000000000B8 ++:1038100000000080000088000000000000000000A0 ++:103820000000000000000000000000210000000077 ++:103830000000902090000200000000200200000024 ++:10384000A0000000000000000000000000000000D8 ++:1038500000000000C0001004090080010340108433 ++:1038600010002000084102000000000041A0008874 ++:1038700090108000C14110040500838803011040AE ++:10388000000080048001020041004101100400009A ++:103890000000000000000000000000000000000028 ++:1038A0000000000000000000100000000000000008 ++:1038B00000000000004000000000000000000200C6 ++:1038C00000000000000000000000000000000000F8 ++:1038D0000000000000000000040900004010040087 ++:1038E0008200880001001002004100008400842052 ++:1038F0000000080020212008000900000821080815 ++:103900000000880004881002040900000002000082 ++:10391000000000000000A000000000000000000007 ++:10392000080000000000000000000000000000008F ++:103930000000000000000000C00000110000A00016 ++:103940000000000000000000000000000000000077 ++:103950000000000000000000000080008500001151 ++:1039600083C180000380000283C1830003000083C1 ++:1039700003414000830000C1030080008300808970 ++:1039800083C18000030000828382830000000083E3 ++:1039900003204000830000C103000000000000007D ++:1039A0000000000000000000000000000000000017 ++:1039B0000000000000000000000000000000000007 ++:1039C00000000000000000000000000000000000F7 ++:1039D00000000000000000000000000082828282DF ++:1039E00088828340828201C0048905C005A0A1822B ++:1039F00000830501038283C004C101000882838221 ++:103A0000A0C083C182820102024105C005A00282DA ++:103A100000830300038283C004C101000000000092 ++:103A20000000000000000000000000000000000096 ++:103A30000000000000000000000000000000000086 ++:103A40000000000000000000000000000000000076 ++:103A500000000000000000000000000000008200E4 ++:103A600008820083C082828211820082C190088312 ++:103A700083820083C10083A085820083014082008D ++:103A8000848200830883828205820082C140088389 ++:103A900083820083100083A08582008301400000A0 ++:103AA0000000000000000000000000000000000016 ++:103AB0000000000000000000000000000000000006 ++:103AC00000000000000000000000000000000000F6 ++:103AD00000000000000000000000000000000000E6 ++:103AE00000008080008388800080848000808309BB ++:103AF000828304C10083C100028502C1008341802A ++:103B0000000000800083C1C00080048000808380AA ++:103B1000828304C100839100028502C10083418039 ++:103B20000000000000000000000000000000000095 ++:103B30000000000000000000000000000000000085 ++:103B40000000000000000000000000000000000075 ++:103B50000000000000000000000000000000000065 ++:103B600000000002000083A182C10000080083C0A1 ++:103B700040C1004100008302000000200080C0A17D ++:103B80008000000200008302408800000000838261 ++:103B90000908004100008302000000200000C0026C ++:103BA0000000000000000000000000000000000015 ++:103BB0000000000000000000000000000000000005 ++:103BC00000000000000000000000000000000000F5 ++:103BD00000000000000000000000000000000000E5 ++:103BE000000000000001008283A183040000018224 ++:103BF000830901C10082008283830400008300C026 ++:103C000083A18200000100848383010400000082FC ++:103C10008309A0080082008283830200008300845D ++:103C2000838300000000000000000000000000008E ++:103C30000000000000000000000000000000000084 ++:103C40000000000000000000000000000000000074 ++:103C50000000000000000000000000000000000064 ++:103C60000000000000008309000889C10883830860 ++:103C700000838282A0888383010101830000C00346 ++:103C800001030100A0C18383004005C0088383A015 ++:103C90000101A0839003838301010183000010824E ++:103CA00001030101A0C100000000000000000000AD ++:103CB0000000000000000000000000000000000004 ++:103CC00000000000000000000000000000000000F4 ++:103CD00000000000000000000000000000000000E4 ++:103CE0000000000000000000028309802182009093 ++:103CF000020011831184000402C04103028300000A ++:103D0000C1104104210400C00283418002C180A08F ++:103D10000200400384A000C002C0410302830000EF ++:103D2000C1890420022000C0000000000000000043 ++:103D30000000000000000000000000000000000083 ++:103D40000000000000000000000000000000000073 ++:103D50000000000000000000000000000000000063 ++:103D60000000000000000000000000000000000053 ++:103D700012422148000B020012428148000B02004F ++:103D8000124200000000000012420000000000008B ++:103D900012422148000B010012428148000B020030 ++:103DA000124200000000000012420000000000006B ++:103DB0000000000000000000000000000000000003 ++:103DC00000000000000000000000000000000000F3 ++:103DD00000000000000000000000000000000000E3 ++:103DE000000000000000000000000000FFFFFFFFD7 ++:103DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3 ++:103E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:103E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:103E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:103E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:103E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 ++:103E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 ++:103E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00E878 ++:103E700064CC0C44002000E80A060000C832AEDE24 ++:103E80000000000000000000000000000000000032 ++:103E90000000000000000000000000007B75AEDEA6 ++:103EA0000000000000000000000000000000000012 ++:103EB0000000000000000000000000007B75000012 ++:103EC00000000000000000000000000000000000F2 ++:103ED00000000000000000000000000000000000E2 ++:103EE00000000000000000000000000000000000D2 ++:103EF00000000000000000000000000000000000C2 ++:103F00000678C000000000000000008C07000000E0 ++:103F100000000000300000000000000000031E60F0 ++:103F20000678C000000000000000008C07000000C0 ++:103F300000000000300000000000000000031E60D0 ++:103F40000000000000000000000000000000000071 ++:103F50000000000000000000000000000000000061 ++:103F60000000000000000000000000000000000051 ++:103F70000000000000000000000000000000000041 ++:103F80000000000080100090882000004000000029 ++:103F900000000000000091000301000000C00200CA ++:103FA00020C1840004000420040000000000800000 ++:103FB0000090000000000000000000000000000071 ++:103FC00004000000000000000000000000000000ED ++:103FD00000000000000000000000000000000010D1 ++:103FE00000000000000000000000000000000000D1 ++:103FF00000000000000000000000000000000000C1 ++:10400000000000000000080000000980100001000E ++:104010000000000000000000400000080000000058 ++:1040200000000002210001000180010008000000E2 ++:10403000040000000000000000000000000000007C ++:104040000000000000C000000000000000000000B0 ++:104050000000000000000000000000000000000060 ++:1040600000800000000000000000000000000000D0 ++:104070000000000000000000000000000000000040 ++:10408000000000000000000000000000002000A070 ++:104090000020000180010004400100000001000038 ++:1040A000000000000000000400010082000800047D ++:1040B00000000400000000200000000400040000D4 ++:1040C000000020000000004000000004100000007C ++:1040D00020000000000000000000000000000000C0 ++:1040E0000000000000000000000000000000400090 ++:1040F00000000000000000000000000000000000C0 ++:10410000000000000000020000000021002100204B ++:10411000A00000A100200220000001020000000415 ++:1041200000000000000000000080002000000000EF ++:1041300000000000010000000080000000800080FE ++:10414000000000000100000000800000008004006A ++:10415000000001000000000000000000000000005E ++:10416000000000000000000000000000000000004F ++:10417000000000000000000000000000000000003F ++:1041800000000000000000000100000100012121EA ++:10419000110240012001000120000001404003A164 ++:1041A00000A00020002011000020000100000040BD ++:1041B00000090008009000000083000000000000DB ++:1041C000800100000000000000000000000000006E ++:1041D00000000000000000000000000000200000BF ++:1041E000001000000000000080002100000000001E ++:1041F000000021000000000000000000000000009E ++:10420000000000000000000000000000000884081A ++:1042100084888280C02010048408102100020100DC ++:10422000C0088200008000800000C0850020C0001F ++:104230000080C0A00080000000000002000000001C ++:104240001000040800000000000000000000000052 ++:1042500000000000000000000000000000000080DE ++:1042600000000080000000000000080000000000C6 ++:1042700082000000000000000000000000000000BC ++:1042800000000000000000000000000000000540E9 ++:104290000000050111001190410004001000100001 ++:1042A000050020004000110400000001A1200000D2 ++:1042B0000088000000000201000000000000000172 ++:1042C00080012000200005000000100000200000F8 ++:1042D0008804C000C100410041002100000000002E ++:1042E00000018021800100010000000080004000EA ++:1042F00000000000000005000000000000000000B9 ++:1043000000000000000000000000000000000000AD ++:1043100000008810000404000000100000000305E5 ++:1043200001000000000001400091000000204089D1 ++:10433000000000000000000000020000002000005B ++:10434000000420040100050000000000000000003F ++:1043500000000980090004000000000000000000C7 ++:1043600000000004048208040004000000000200B1 ++:10437000000000000000000000000000000000003D ++:10438000000000000000000000000000000000002D ++:1043900000008002C100801100040382800110052A ++:1043A0002000800580000200100900000020218804 ++:1043B000218820C0000003000088000000000000E9 ++:1043C000000800000000040021010000400100007E ++:1043D000000000001000080010001000050440005C ++:1043E00000000420000000880010211000000000E0 ++:1043F000111021000000000000000000000000007B ++:1044000000000000000000000000000000000000AC ++:104410000000000004800400048290A10004400811 ++:1044200084881021108240001100A1A000000080AB ++:1044300000000000C100C000C0001000000010001B ++:10444000840084800000000001001008C0110108F1 ++:1044500000000000000000000100000000000080DB ++:1044600001000000018000000000008000800000CA ++:10447000A00090800000000000000000000000008C ++:10448000000000000000000000000000000000002C ++:10449000000000000000000400041090009000A044 ++:1044A000100400000902110402040200C1020020ED ++:1044B0000900092002200440030041004140008817 ++:1044C00000200082000420000040008204880000D8 ++:1044D000000000908000000040001000002000015B ++:1044E000200221014000C000802180218020802105 ++:1044F0000000000180019001800000900001800117 ++:1045000000000000000000000000000000000000AB ++:104510000000000000000000000000800000040017 ++:10452000000005040011008000000080042110A19B ++:10453000008000000080A080A18000008200008038 ++:1045400000000000000000800100000000000000EA ++:10455000000004000000042000001141004100851B ++:10456000002083A184400100094120A020842080F4 ++:1045700008840000000420100804042090000410A7 ++:104580002010000000000000C0000000000000003B ++:1045900000000000000000000000C183040302804E ++:1045A00002404021084184089102C102040900052B ++:1045B00000080388418404020405038040008280CF ++:1045C00041802000050011000200000000000000F2 ++:1045D00000000000000000000300000000030000D5 ++:1045E00088000000400010201100000080831104AA ++:1045F0004000410083820409092111918080050057 ++:10460000800000000000000000000000000000002A ++:10461000000000000000000000000000918305047D ++:10462000000809A000011100820040009101010072 ++:1046300000000001910904C1000400119008C1C0EC ++:10464000418401080000000000000000000000009C ++:104650000000000000000000000001000000000158 ++:10466000880011000000C1008501000090009083C7 ++:10467000850205C0011089830091008301C18882F1 ++:104680000184C004000000000000000000000000E1 ++:104690000000000000000000000000000000089082 ++:1046A00004A1089000830188000000880001080030 ++:1046B00005A01010410140A0C1C010411000080227 ++:1046C000A104C1020800A1000190890010000002AD ++:1046D00000010020000100000000000000000000B8 ++:1046E000C000820190888300C00010911000C08536 ++:1046F000C1018301C090831101018900A0089101CB ++:104700000001000000000090000000000000000018 ++:104710000100000000040002000000000000000092 ++:104720008009008280C000C1210008091000020930 ++:104730008200C080800503410400A00284050404B7 ++:10474000898040001084040041002000C141822182 ++:104750000080000300800003000000000000000053 ++:10476000000000000003800083000000800880003B ++:104770008083092020210080830208098402898027 ++:1047800089090009000000000090000000000000FE ++:104790000000020000000000000000000000000017 ++:1047A000000010888308A180888308C1031141821A ++:1047B0008321210800030409100302020891051057 ++:1047C000051000890240A1110020000200412104CF ++:1047D0008084000003000400800000020004030243 ++:1047E0000003008080400080000089838840000032 ++:1047F0000880808082040080030289830202808412 ++:104800009189A180000000008000000000000000ED ++:104810000000000000000000000000000000000098 ++:1048200000000000850882C1110890830005018402 ++:104830000008C101010000000000A10189408810AA ++:10484000A11009050008C1C104A090090004008559 ++:1048500000C082880400000001000400C0010001C3 ++:104860000101A0010080089000C0000891838389A5 ++:104870000090010808C090A010C0C11091830101F0 ++:1048800088C0A1058982000000009000000000009F ++:104890000000000000000000000000000000000018 ++:1048A000000000000000830509028208C082004069 ++:1048B0000090001000000111010901000108010130 ++:1048C0000004000000A0010501000001000201A099 ++:1048D0000001000001880000008800000000008244 ++:1048E0000000000500000080019101080000001098 ++:1048F00083098411850188088391C182A000A004E6 ++:1049000082058801828988A082000400900000004E ++:104910000000000000000000000000000000000097 ++:1049200000000000000000008303A1004000808020 ++:1049300000800040009100411008044010114180A7 ++:10494000050302110910110009C010211002058091 ++:1049500040000403040410800000008000000000F8 ++:104960000080000000100000008003880400004068 ++:104970000080838802C0C010008083A004800902E8 ++:1049800002008002800900A1808080000000800079 ++:104990000000000000000000000000000000000017 ++:1049A000000000000000000000000000000B2000DC ++:1049B000816000000022480011410000000B44000B ++:1049C000000000000042020081000041000BD00006 ++:1049D00000002100000BC100425000000083D00005 ++:1049E0008148000000830200124200000000000B1A ++:1049F000C2000A000000000BD00041480000000B7C ++:104A0000D00082880000001002001100060082130E ++:104A10000200000000000000000000000000000094 ++:104A20000000000000000000000000000F0F0F66F3 ++:104A30002D2D3C3C000000007E42CFCFFF66990048 ++:104A40003C0F2D2DFF6C0F6CF0F00000F0F0C0005B ++:104A5000C000C00000F030060000000F00000000A1 ++:104A60000000000000000000000000000000FF0047 ++:104A700000003C3C0000F0F0FF005A5A5A5AC33C78 ++:104A80000F0F00FF3C3C00000000F000F0000000B1 ++:104A90000000000000000000000000000000000016 ++:104AA000000000000000000000000000000066663A ++:104AB0000F662D2D0F0F000000007E420C0C1E1EF5 ++:104AC0001E1E3C0F2D2DF06C006CF0F80008F0F06D ++:104AD00050003232020200003006003C6600000046 ++:104AE00000000000000000000000000000000000C6 ++:104AF000FF0000003C3C00000F0FFF005A5A5A5ABA ++:104B0000C33C0F0FFF003C3C00000000D020D02031 ++:104B10000000000000000000000000000000000095 ++:104B20000000000000000000000000000000000085 ++:104B30000000000000000000000000000000000075 ++:104B40000000000000000000000000000000000065 ++:104B50000000000000000000000000000000000055 ++:104B600000000000000000000000000000218000A4 ++:104B70000000000000000000000000000000000035 ++:104B80000000000000000000000000000000000025 ++:104B90000000000000000000000000000000000015 ++:104BA0000000000000000000000000000000000005 ++:104BB00000003C3C663C00000000BDBD90F6424257 ++:104BC0007E7E30303F3FFCFC7E7EF6F6303F18188C ++:104BD00018180000000004C40303000000000C0CBF ++:104BE0000000000000000000000000000000FFFFC7 ++:104BF000FFFF0000000066660000FFFFFF00FF00EF ++:104C000099999999FFFF66993C3C0F0F40BF0000AE ++:104C10002000DF0000000000000000000000000095 ++:104C20000000000000000000000000000000000084 ++:104C3000000000006666663C00000000242490F638 ++:104C400030F330F3606F606F0C0C18180606303FBD ++:104C5000781818180000000004C4000000000000CC ++:104C60006060000F00000000000000000000000075 ++:104C7000000000000000000066660000000000FF69 ++:104C800000FF66666666000066993C3CF0F000FF37 ++:104C900000000000FF000000000000000000000015 ++:104CA0000000000000000000000000000000000004 ++:104CB00000000000000005805A01A00900050086E0 ++:104CC000026100B000800186026100B900A5A086E3 ++:104CD0000C6100B00000008E006500B0000000868E ++:104CE000026101880005A0865060A8B0000500861A ++:104CF000006108B008400000A24751F00804494094 ++:104D00001286016108B40840120021904004004856 ++:104D1000008400000090000000A000C001B0000569 ++:104D2000000000000000000000000000090000007A ++:104D30000000001000000000010040000000020020 ++:104D400000000000FF7FFF7F000000000000000067 ++:104D5000000000003A303030000000000000C0C009 ++:104D6000000000003CFFFDFF00000000000000000C ++:104D70000000000000000000000000000000000033 ++:104D800000003CFFF3C0BF0E2F0800000000280009 ++:104D90000800030CD7FFAA00A0A0FF5F005F00007F ++:104DA00000000000000000000000000000200000E3 ++:104DB00001000000000000000000000000000001F1 ++:104DC0000000000000000040004000000000000063 ++:104DD00000000000000030303030000000000131E1 ++:104DE0000131000000003CFFFDFF0000000000005A ++:104DF00000000000000000000000000000000000B3 ++:104E000014000500003CF3C03F0C0F0000A0002878 ++:104E100000000800030CD7FFAA00A0A0FFFF00A01D ++:104E20000000000000000000000000000040000042 ++:104E30000000020000000000000000000000000070 ++:104E40000100010000000000000000000000000060 ++:104E50000000AAAA0003AAAA3C003C00C0C0C0D41B ++:104E60000000C3000000000014D700FF0000000095 ++:104E70000000000000000000000000000000000032 ++:104E8000000000000000000000000F4F00010202BF ++:104E900002000A00280042424380FFFAFFFF000F91 ++:104EA0000000000000000000000000000000000002 ++:104EB00000000000000000000000000000022000D0 ++:104EC00000080000000000000000000000000000DA ++:104ED00000000100ABAA0000AAAA3C503C00C0C0E0 ++:104EE000C0C00C410C410000000014D700FF0000BE ++:104EF00000000000000000000000000000000000B2 ++:104F000000000000000A0808000000004FFF010F29 ++:104F10000000020000000000C0C0C300FFFFFFFF50 ++:104F20000F000F0F00000000000000000000000054 ++:104F30000000000000000000000000000000000071 ++:104F40000084000404000000000000200020200075 ++:104F500000002100000204200000000040000000CA ++:104F6000000000000400000000010000002080009C ++:104F70000000000000000400800000000400200089 ++:104F8000000000001100040000000000000000000C ++:104F90000000000000000000000000000000000011 ++:104FA0000000000000000001000000000000000000 ++:104FB00000000000000000000000000000000000F1 ++:104FC00000008200008000000000000000800080DF ++:104FD0000000000000000080209000000021000080 ++:104FE0000000000000000000000000200000008021 ++:104FF00020000000000000008500200000000000EC ++:10500000010000C0000000000000000000000000DF ++:105010000000000000000000000000000000000090 ++:105020000000000000000000004000000000000040 ++:105030000000000000000000000000000000000070 ++:10504000000000000000000100000000000000005F ++:1050500000400000000000010089009000000000F6 ++:1050600000000000000000000004000100900000AB ++:10507000000000000000000000000003000000002D ++:105080002000000000800000000000000000000080 ++:10509000000100000001000000000000000000000E ++:1050A00000000000000000000400000200000000FA ++:1050B00000000000000000000000000000000000F0 ++:1050C000000000000000000000100021401100005E ++:1050D00000000000000800000004000400100000B0 ++:1050E00000000000400000000000008002200200DC ++:1050F000001100000010000000100000002000104F ++:10510000000001000000008000000000000000001E ++:10511000000000200000002000000002000000004D ++:1051200000020000000000000000000000800000FD ++:10513000000000000000000000000000000000006F ++:105140000000000000000000410000840000021088 ++:10515000020010000004041090002084A0208000B1 ++:105160008410080000A000000000002000000000E3 ++:1051700000200010090000000000000000000000F6 ++:105180000000000000000000000000008000008817 ++:105190000020008400840000000000008000000067 ++:1051A00000200010002000000500080000000000A2 ++:1051B00020000000000000000000000000000000CF ++:1051C0000000000000000000000000090000C00016 ++:1051D00001000105000088111140032185050380AD ++:1051E00002004110112010008400A00000A1C000A6 ++:1051F000A021888000800008100800000000000046 ++:10520000100000000000000000000000000040004E ++:10521000000000808400C0208240C0009000200078 ++:1052200000001080008000801000100001000000CD ++:1052300000000100000000008400000000000000E9 ++:1052400000000000000000000000000000000085D9 ++:1052500000000000000000100000008800000900AD ++:1052600002820000000080200020002000000020BA ++:10527000008380000000000000000000000010001B ++:1052800000000000009002000490054000001100A2 ++:1052900000000000000102902020410000200000DA ++:1052A000000400000020000000000000000000904A ++:1052B00000000000000000000000000000000000EE ++:1052C00000020000000000000000000000000000DC ++:1052D0000010840000000011000000000000000029 ++:1052E00000100111004000000480008000800000D8 ++:1052F00000801020200000000010000000000000CE ++:10530000000000000000000000000100000000009C ++:1053100000009000900088080000018000000080DC ++:10532000001100800000008000000000000000006C ++:10533000000000000000000000000000000000006D ++:10534000000000000000000000000000000000005D ++:10535000000020008000820110000000000021A059 ++:1053600000000004000180000084800800000200AA ++:1053700009000000000000200000000000011000F3 ++:1053800000000000000004A000000001000009006F ++:10539000000000000000000010858000C001208394 ++:1053A00041890000030000001001000000004120BE ++:1053B000050800C00000020000000000030000001B ++:1053C00000040000000000000000000000000000D9 ++:1053D00000000000110010000520884010000005AA ++:1053E00000030400048000400210002140008420DB ++:1053F0000200000000008203A088000000000020DE ++:1054000084210000000000000100000000040000F2 ++:10541000000000000041000000009108200021046D ++:1054200085040004000084008400840800008400D7 ++:10543000008000800000000001000000000000006B ++:1054400000000080000000000000000000000000DC ++:1054500000000000400000841040000800400200EE ++:1054600000000088000000004000020420C000840A ++:105470002090A000000841000020029000000820B9 ++:1054800000000020000000000001848500000000F2 ++:1054900000000004000011000000110000848000E2 ++:1054A00002820200200000002002099010900000FB ++:1054B00000C00000000000001000104000000000CC ++:1054C000000000008020000000000000000000003C ++:1054D00000000000000001000000C100000000808A ++:1054E00010001005001000000000011101800100F3 ++:1054F000000001002000008000000080000000008B ++:105500000080000000800000000000040304000090 ++:10551000000000000080000000000000000000000B ++:1055200020000000000001000000018000001000C9 ++:10553000000000000000000000000000000000006B ++:1055400000000000000020800000000000000000BB ++:105550000000000000000000041002022105900578 ++:1055600000800080200000000000C19011000000B9 ++:1055700091911184410909410000000000000000E0 ++:105580008080910002000000000000000000000088 ++:105590000040094000411010000000000000000021 ++:1055A000000080000980410000004010050000005C ++:1055B000410000008000030000000000A100410045 ++:1055C00000000000200000000000000000000000BB ++:1055D00000000000000000000000000100010100C8 ++:1055E0001101000400A0010000880820842100901F ++:1055F000000889828511018301010000000000007C ++:105600000000888291A001820000000000000000DC ++:105610000000000001000001010100000000000086 ++:105620000000000040A085020020002001000100D1 ++:105630000000010000000400000000000000020063 ++:105640000100000000000100000000000000000058 ++:10565000000000000000000000000000000000004A ++:1056600000840000A0018200C0884000080002C041 ++:10567000820090C1880183C01088C1C1000000046D ++:1056800000A000008801A0008888C0C100000000C0 ++:1056900000000000040002888900410100000000B1 ++:1056A00001000000010088000000020003900200D9 ++:1056B0000500A10003028301A000918882850800F3 ++:1056C000050205A0830100000000000001000000A9 ++:1056D00000000000000000000000000000000000CA ++:1056E0000000008000210020000000808000800475 ++:1056F00085800000800989024180809183890000B3 ++:1057000000800002001180020000808080C0000044 ++:105710000000000000108000C000A10090090000FF ++:105720000000080003000300034111118300C105BC ++:10573000090288008500A08540020200208084853F ++:105740008000118089848910000000000000090099 ++:105750000000000000000000000000000000000049 ++:10576000004000822104C088808000000380808087 ++:105770000080000888000080038980850089C1833B ++:105780000000040004008000000000000080808011 ++:1057900000000000400000800040004000090808B0 ++:1057A0000000000000000000800080000080908069 ++:1057B00000800040000220050005008000000080FD ++:1057C00000800080008000808080000000000000D9 ++:1057D00000000000000000000000000000000000C9 ++:1057E00000000089004100854182A08400C000A023 ++:1057F000884000028209852000080108909100A1DC ++:1058000089830000010000000400008800A082A03D ++:1058100088820000000000000088000000000001F5 ++:10582000080000000000000000000400022000103A ++:10583000058420100001000101008800000200A082 ++:10584000000400020088000400A08882000000001C ++:105850000000C00000000000000000000000000088 ++:105860000000000000000000000000008401C0886B ++:10587000C00040008300C000040004021101119127 ++:10588000910189C000A001100000010088898800F2 ++:1058900090008888000000A000000000008900003F ++:1058A000010100000000000000C100000000848928 ++:1058B00010914001042002050201820102029001C0 ++:1058C00088A09000C08201110100000100040000C6 ++:1058D00000000000000000000000000000000000C8 ++:1058E0000000000000000000000000000011800522 ++:1058F000008080008000831104000900218089035A ++:105900008585894190802000400004002000000827 ++:1059100080008000808000000000000000004083C4 ++:1059200040400221080000000000001000030000B9 ++:1059300080A08041800280008082802000050000DD ++:105940008011804100418080034004000521030054 ++:105950000000000000000000000000000000000047 ++:1059600000000000000000000000000B48000000E4 ++:10597000000000220000000000000080480000003D ++:1059800000000083C10021000000000BC2000000E5 ++:1059900000000008C200000000000010C20000006B ++:1059A0000000008302000A0000000000000BD0008D ++:1059B00000000000000BD0000000000000102000DC ++:1059C0000000000000100000008200000010020033 ++:1059D00000000000008048000000000000000000FF ++:1059E00000000000000000000000000000000804AB ++:1059F000DFEF00000000000000003F3F3CFFF0F040 ++:105A0000F0F00008AAA2424201C20000FF0000001C ++:105A10000000000000000000000000000000000086 ++:105A200000000F0F0F0000CF00CF000000000000AB ++:105A30000000000000000000000000000000000066 ++:105A4000FFFFFFFF00000000000000000055F3F31F ++:105A50000000000000000000000000000000000046 ++:105A60000000000000000000000000000000000036 ++:105A70000000FFFF000000000000000030303C008C ++:105A8000F0F0F0F00000AAAA414100C30020FF207E ++:105A90000000000000000000000000000000000006 ++:105AA000000000000F0F0F3C00CF30FF000000008F ++:105AB00000000000000000000000000000000000E6 ++:105AC00000005FDF55D70000000000000000005517 ++:105AD000FFFF0000000000000000000000000000C8 ++:105AE0000000000000000000000000000000BA8A72 ++:105AF000AAAA00000000000000000000000000FF53 ++:105B000000FF0F0F0F0F20000000424200000000B6 ++:105B10000000000000000000000000000000000085 ++:105B2000000000000000F0F082F0FA00FF05000025 ++:105B300000000000F0FF000A000000005500F5F032 ++:105B40000000FFFF3C3C3C3C00000000507C507CCF ++:105B50000000000000FF000F000000000000FFFF39 ++:105B60000000000000000000000000000000000035 ++:105B7000BA8AAAAA0000000000000000000000008D ++:105B800000FF00FF0F0F0F0F000000004242C3C3D1 ++:105B90000000000000000000000000000000000005 ++:105BA0000000000000000000F0F082F0FA00FA00AF ++:105BB000000000000000F0F00000000000007D3C4C ++:105BC000FDFC0000FFFF3C343C3800000000FFFFFC ++:105BD000507C0000000000FF0000000000000000FA ++:105BE000FFFF0000000000000000000000000000B7 ++:105BF00000000086006008B80000008600210080D8 ++:105C00000000058600600880000000860001080290 ++:105C1000001000860071A8B0000500860000080092 ++:105C2000000500860070A89000050086006000A0B6 ++:105C3000000000000086007100B00010A086503007 ++:105C4000A09000850086006108B00080000600205A ++:105C500000A0000005060061001000000086006042 ++:105C600000B0000000000000000000000000000084 ++:105C700000000000000000005C5C553CF0E8F0F023 ++:105C800010DF00FFFF0000FF50503C0000F700084D ++:105C9000424201C200000000000000000000F708BE ++:105CA000C2C201C200000000FFFF000000000000AF ++:105CB00000000000000000000000000000007F0065 ++:105CC0001F0007070107D3FFD3D300000000C1AABC ++:105CD000C300000010000000000000FF24240000AA ++:105CE00000000000000000000000000000000000B4 ++:105CF000000000000000000000005C5C553CF0E883 ++:105D0000F0F010DF00FFFB0044FF0000000000FF88 ++:105D10000000414100C3000000000000000000003E ++:105D2000FF00010100C300000000FFFF00000000B1 ++:105D30000000000000000000000000000000000063 ++:105D40000D0004000107010150FF50500000000049 ++:105D5000C100C300000000000000000000FF0000C0 ++:105D60000000000000000000000000000000000033 ++:105D70000000000000000000000000000000000023 ++:105D80003CFF3C000F3C0F0F03000300505000008D ++:105D9000005A5F5F0F001B000000000000000000C1 ++:105DA00000000FFF000000000000000000000000E5 ++:105DB0000000000030FF00CF0000000000000000E5 ++:105DC000000030F0FCFFC3EBEBFF00000000757536 ++:105DD000303000000000C0F0417100000000003CC5 ++:105DE000F5F50000000000000000000000000000C9 ++:105DF00000000000000000000000000000000000A3 ++:105E000000003CFF3C000F0F0F0F8C8C80803C008B ++:105E10000000005A5F5F0F000F000000000000004C ++:105E200000000FF00FFF00FF04FB00000000000067 ++:105E300000000000000000CF00CF000000000000C4 ++:105E4000000000000030F0FC008282C3000000006F ++:105E500075FF30FF000000001414417100000000C5 ++:105E6000003C0505000000000000000000000000EC ++:105E70000000000000000000000000000200000020 ++:105E800000002000000020000000000000000000D2 ++:105E900000000020000000000000000000000000E2 ++:105EA00003000000000004000000400000000000AB ++:105EB00000000000000000000000000000000000E2 ++:105EC00000000000000000000000000000000000D2 ++:105ED00000000000000000000000000000000000C2 ++:105EE00000000000000000000000000000000000B2 ++:105EF00000000000000000000000000000000000A2 ++:105F000000000000000000000000904000000000C1 ++:105F10000000000000000000000000000000000081 ++:105F20000000000000000000000000000000000071 ++:105F30000000000000000000000000000020000041 ++:105F40000000000000000000000000000000000051 ++:105F50000000000000000000000000000000000041 ++:105F60000000000000000000000000000000000031 ++:105F70000000000000000000000000000000000021 ++:105F80000000000000000000000000000000000011 ++:105F90000000000000000000000000000000000001 ++:105FA000000000820000000000000000000000006F ++:105FB00000000000000000000000000000000000E1 ++:105FC00000000000000000000000000000000000D1 ++:105FD00000000000000000000000000000000000C1 ++:105FE00000000000000000000000000000000000B1 ++:105FF00000000000000000000000000000000000A1 ++:10600000000000110000000000210000001100212C ++:1060100000200041004100080008000300000011BA ++:10602000000900000011000000000000000000094D ++:106030000020000000000000000000000000000040 ++:106040000000000000000000000000000000000050 ++:106050000000000000000000000000000000000040 ++:106060000000000000000000000000000000000030 ++:106070000000000000000000000000000000000020 ++:106080000000000000000000000000000000100000 ++:1060900004880000000004000400008800000000E4 ++:1060A000004002020000000000001000000000009C ++:1060B00000000000004000000000000000000000A0 ++:1060C00000000000000000000000000000000000D0 ++:1060D00000000000000000000000050002000000B9 ++:1060E000000000000000000000000000210000008F ++:1060F00000000000000000000000000000000000A0 ++:106100000000000000000000001000004021C0005E ++:1061100000001000100510400000000000090808F1 ++:106120000011A0200200000000000000000000009C ++:10613000000000000000000000000000000000005F ++:10614000000000000000000000000000000000024D ++:10615000000000000000000000000000002084009B ++:106160000000C000880000004000000000000000A7 ++:10617000000000000000000000000000000000001F ++:1061800000000000000000000040001000A000001F ++:1061900000000000200000000000000000000000DF ++:1061A000000000000082212010000000000000001C ++:1061B00000000000000000000000000000000000DF ++:1061C00000000000000000000000000000000000CF ++:1061D000000000001000000010000000000000900F ++:1061E00000000000000000000000000000000000AF ++:1061F000000000000000000000000000000000009F ++:1062000000000000000000000000040088002000E2 ++:1062100008009000000402040009000000000000D3 ++:106220009002000400000000002108000000A00807 ++:106230000800000000000000020000000000000054 ++:10624000900000000000A00000000000000000001E ++:10625000000000000000000000000000000000003E ++:10626000000400000000000000000000000000002A ++:10627000000000000000000000000000000000001E ++:10628000000000000000000000000000000000000E ++:1062900000000000000000001000000000000000EE ++:1062A00000000000000000000000000000000000EE ++:1062B00000000000000000000000000000000000DE ++:1062C00000000000000000000000000000000000CE ++:1062D00000000000000000000000000000000000BE ++:1062E00000000000000000000000000000000000AE ++:1062F000000000000000000000000000000000009E ++:106300000000000000000000000000000000100875 ++:106310000000000000000000000000030003000077 ++:10632000002002000409001100210011880000086B ++:106330000000000000090000000000210000000033 ++:10634000000000000000000000000000000300004A ++:1063500000000000100000000003002100110000F8 ++:10636000000000000000020000000000000000002B ++:106370000000000000008400000000000000000099 ++:10638000000000000000000000000000000000000D ++:106390000000100000000000000000000010008459 ++:1063A000000000000000000000000000009000005D ++:1063B0000000004000000008000000000000000095 ++:1063C000000000000090000000000000000000003D ++:1063D00000000000000000000000000000000200BB ++:1063E0000900000000200000000000000000000084 ++:1063F000410000000000000000000000000000005C ++:10640000000000000000000000000000000000008C ++:106410000000000002108440840004118411020076 ++:106420000810000882000021000010000000C000D9 ++:106430002004A00500000000000000000000004053 ++:10644000C000C009000800000000000000000000BB ++:1064500004000000040000001000000000000040E4 ++:10646000A04002000000000000000000000000004A ++:10647000000000000000000000000000000000001C ++:106480008800000000000000000000000000000084 ++:1064900000000000FFFFFFFFFFFFFFFFFFFFFFFF08 ++:1064A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC ++:1064B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC ++:1064C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC ++:1064D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC ++:1064E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC ++:1064F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC ++:10650000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B ++:10651000FFFFFFFFFFFF00A8BE430C440010000078 ++:106520000A0600006018000000000400044040005B ++:1065300000000400000404000000200080000800A7 ++:1065400080001100000000000000000004000000B6 ++:106550000000000000000401000000000000000036 ++:1065600000000000200000C000000000000000004B ++:10657000000000000000000000000000000000001B ++:10658000000000000000000000000000000000000B ++:1065900000000000000000000000000000000000FB ++:1065A000000000000000000000000000000000806B ++:1065B0000100000001000080000000000100040054 ++:1065C00005000800000000100000000000000000AE ++:1065D00000000000000000000004000000000000B7 ++:1065E000000000000000010000C0000000000000EA ++:1065F000000000000000000000000000000000009B ++:10660000000000000000000000000000000000008A ++:10661000000000000000000000000000000000007A ++:10662000000000000000000000000000000000006A ++:10663000000000014001000900010000000080206E ++:106640000000000000000001202080000000000089 ++:106650000000000000000000000400000000000036 ++:106660000000000100000000802100C000C0000008 ++:106670000000000200010000000000000001000115 ++:1066800000001100000000000000000020000000D9 ++:1066900000000000000000000000000000000000FA ++:1066A00000000000000000000000000000410000A9 ++:1066B000000800080420012000A0000800000000DD ++:1066C0000288000002000000000401101000000019 ++:1066D0000003000000100000040000800000000023 ++:1066E000004100000004000000000484008000005D ++:1066F0000000000000800002000000000000000414 ++:106700000004000000000000000000000000010381 ++:106710000000000000000000000000000000000079 ++:1067200000000000000000000000000000000090D9 ++:1067300000000011009100C00000000400000000F3 ++:1067400000000000850880090001048309020000A0 ++:1067500000000301000800880000000000040000A1 ++:1067600000008000058400C00004000000840000D8 ++:106770000000000080000020000000000800002051 ++:106780000400000000000000000000000000000005 ++:1067900000002100000000000010000000000000C8 ++:1067A00000000000000000000000000000000000E9 ++:1067B00000000000004000200000000000800000F9 ++:1067C000000000218400208020200020852000007F ++:1067D0000000000000020000000000000000008037 ++:1067E0000000000004000000002100800000000004 ++:1067F0000000000000000800008000000000010010 ++:106800000080010000000000000000000000000007 ++:1068100010000000000000000000008000000000E8 ++:106820000000000000000000000000000000000068 ++:1068300000000000800010008000020104008800B9 ++:106840008000050000000200200002008000090016 ++:1068500005010000030000000400410000000401E5 ++:106860000000804041009001050000000000009001 ++:106870000000000000000000000010000800000000 ++:1068800000000000210004200000410000840000FE ++:106890000000000080000000000000000000000078 ++:1068A00000010001000000200000000000000000C6 ++:1068B0000000000000114004000440052104010014 ++:1068C000090004008840A009041082009100020021 ++:1068D00084000010080000201000830000410041E7 ++:1068E0000140C000208000000840001100040000AA ++:1068F000000000000000000000000000C000400098 ++:10690000A0009000080000000021840000000000AA ++:1069100084000000000020008200820000000000CF ++:10692000000000040004000000000000000000005F ++:10693000000000000000110010000200050010001F ++:106940000000800000000582100002000884088416 ++:1069500011010801828408000000100008041000E2 ++:10696000000021000440004000100088004010009A ++:106970000000410000000000028800000000000448 ++:106980000800000021000300210004000000410075 ++:1069900005A00400030005004100044009000900AF ++:1069A00000000000000000000000000000000000E7 ++:1069B00000000000000000000000000000000400D3 ++:1069C00001000000100000000000000000000000B6 ++:1069D000000000040120051000000000000000007D ++:1069E000010000000000C1800000000000000080E5 ++:1069F0000000000000000000004001000000000056 ++:106A000000800000000000000009000001000000FC ++:106A10000000000001000011000000000100000063 ++:106A20000000000000000000000000000000000066 ++:106A300000000000000000000000080009000388BA ++:106A4000110004000004840004000082900005107E ++:106A500005830800002000410085050000000000BB ++:106A600000000800008490004104000000000000C5 ++:106A7000000400010000101002010000001041009D ++:106A80000500410000000090102005009000040067 ++:106A90000000030041A005A000C00300000400A006 ++:106AA0000000000000000090000000000000000056 ++:106AB00000000000000000000000000002000000D4 ++:106AC0001009020089102080030421000041404188 ++:106AD000C02110409110888010A0022000410000C9 ++:106AE000C000A0081040000010009040841000007A ++:106AF0000000820000400000008000040000000050 ++:106B00000000000000000000000001800000040000 ++:106B100000000008040000000000000000000080E9 ++:106B2000C00000008200A000000000008200000001 ++:106B300000000000000000000000000000004140D4 ++:106B400080112011101008840080002040A0000057 ++:106B50000000880000000888840902401105000038 ++:106B6000000000000000410080008500410000801E ++:106B700000001100008000A1000900210021000098 ++:106B800083910591800203111180000080000300B1 ++:106B90000203808008800000820300004080000023 ++:106BA000820300004080000091030904414109096B ++:106BB00000000000000000000000000000000000D5 ++:106BC0000101200000010000008200400089000552 ++:106BD000000004001100000002828203008300C054 ++:106BE00000000000000000000000C0009000000055 ++:106BF0000082080290000008028200850004000064 ++:106C000000009183000808A001C0018200A082A0BA ++:106C1000000005052020919000028903A0A00990A2 ++:106C200000C089A1C0C0099000A0910185010101A7 ++:106C30000101000000000000000000000000000052 ++:106C400000004000901009004100A040C0880940A9 ++:106C500003010000000008A00101C0038588042191 ++:106C6000830000000090000100000800840005403F ++:106C700091890800080002A0820000000182000043 ++:106C8000000100000000008500C1000000000000BD ++:106C90000004000090002001828803C19001A084BC ++:106CA000C088C1A090000284C0880302000008844C ++:106CB000A0018301000000000000000000000000AF ++:106CC00000000000890011808504C00000800921B7 ++:106CD00085858310090009009100052010830800B4 ++:106CE00000C189000000000000210002044089006A ++:106CF0000582091180000000800080002100418091 ++:106D000000002109000000000003008900022100AA ++:106D100000000500210080048041008003208003E2 ++:106D200000000080030080020000008003000000DB ++:106D30008000804189050000000000000000000084 ++:106D40000000000000001111000241029104030341 ++:106D50008208401021030080008020800000080489 ++:106D60002108008991C0000000002100800000116E ++:106D70000004004000090000800000800080030043 ++:106D800000000000800000000840001102092005FA ++:106D90000000801100030003000000800000C00319 ++:106DA000000000800000C003000000000000C0835D ++:106DB00040800000058911830000000000000000F1 ++:106DC00000000000000000000000002100A01020D2 ++:106DD0004100020002012001000800100184A0907F ++:106DE0000100A000048520830000000000000400D2 ++:106DF000004000880005020800C008840002A08846 ++:106E00000100880000008200000000010000010174 ++:106E10000300000008010000A001C0048890C0C069 ++:106E200089030090C09082C089A1020202A08282E0 ++:106E300089C1018800C001890191000000000000A3 ++:106E40000000000000000000000000000001000041 ++:106E50000102000501A0010101400000000800003E ++:106E60000010838402108200000201000002010071 ++:106E7000010083A08901040041100191000000007D ++:106E8000004001200100000000000000000400900C ++:106E9000000000000084008400000000900120C079 ++:106EA000020190029191A000C00190A00389C090BE ++:106EB000820190A001010182010001000000000098 ++:106EC000000000000000000000000000020441413A ++:106ED00010104000049005040240208000000009CA ++:106EE000001000808982111100101100030002803F ++:106EF000410010008308044000000880098310004E ++:106F00000200098009800405212121000000088079 ++:106F1000110041001100008000210020000000103D ++:106F200080000021890003100000002180000389F7 ++:106F3000008000218000091140800900110000003C ++:106F40000000000000000000000000000000000041 ++:106F500000800000000000000013D00006000000C8 ++:106F60000013C20000000060000BC2000A00008491 ++:106F70000013C200000000600013C2000000000007 ++:106F80000013C200060000000007C1000A820000D2 ++:106F900000000013C200824800000013D0000081EE ++:106FA00000000004C2000000000000040000060011 ++:106FB000000000048100000000840007E0001100D0 ++:106FC00000000000000000000000000000000000C1 ++:106FD0006C6C6C6C272727276666666600200000AD ++:106FE0000000000000000000FFE73C24EF2CCB086D ++:106FF0000FFF8181000000008100240004000000D8 ++:1070000000FC000C0000000003FF03000000000073 ++:1070100000003F7E0000FD9DF4940000000000FF92 ++:10702000660F3C3C3C3C66660000FFFF0000666665 ++:107030000000FFFF000066660000FBFF0400996689 ++:10704000999900000000000000000000000000000E ++:107050000000FFF00F00FF3CC300303F0CFC00209D ++:1070600000C00000000000000000FFFF0000FF0063 ++:10707000FF000F008181000000008100240000005B ++:10708000000000FC000C00000000FFFF00000000FA ++:1070900000000000034200006D0D640400000000C9 ++:1070A000000066663C3C3C3C666600000000000058 ++:1070B000666600000000000066660000FFFF00003A ++:1070C000FF006666000000000000000000000000F5 ++:1070D00000000000FFFFFFFFFFFFFFFFFFFFFFFFBC ++:1070E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 ++:1070F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 ++:10710000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F ++:10711000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10712000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F ++:10713000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F ++:10714000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F ++:10715000FFFFFFFFFFFF002C79740C4400100018A4 ++:107160000A06000094C6900090000081008183838D ++:10717000C3C3FFFF00000000000020DF00FF60F934 ++:1071800024BD3030FFFF00000000000000000000C0 ++:10719000000000E0E7070000000000000000C0C0A1 ++:1071A00000FFF1F170700000C042FC7E00000000A2 ++:1071B000000000000024003C000066660000FFFFA5 ++:1071C000000066660000FFFF00006666FFFF00002B ++:1071D000665AF0D4FFFF000000000000000000002D ++:1071E00000000000000000009000908100810889EC ++:1071F000E3E3C3C3F6F600600000000020DF0000F8 ++:1072000000FF00FF2020EFEF000000000000000062 ++:107210000000000000E0E7070000000000000000A0 ++:1072200000FF00FF707070700000000000000000A0 ++:107230000000000000004224C33C0000666600001D ++:107240000000000066660000000000006666FFFFA8 ++:10725000FFFF6666F0F0FFFF000000000000000086 ++:1072600000000000000000000000018602600090A5 ++:107270000080A0865070A8B900A5008600F1A8B0D3 ++:1072800000850086007500B000000886006500B02B ++:107290000000058600E508B00000008600E100B0AF ++:1072A00000000086006100B00000000000860CF1C4 ++:1072B000A8B80005008600E100B20080A2C6519087 ++:1072C0000884494002C7018000844940A2C7018068 ++:1072D000008441400006047C00B200000000000071 ++:1072E000000000000000000000000000000000009E ++:1072F0000500050000000000000000000000000084 ++:107300000000400000505000005500000000000048 ++:1073100000000000FFF03CAAFF00FFA300000000F7 ++:10732000FBD3FBD3000000000000000000000000C1 ++:107330000000000000000000000000000000080045 ++:107340000C00000E0000100014000000020A0000F3 ++:1073500000000000000000000000FFFFFFFF000031 ++:10736000000000000000000000000000000000001D ++:1073700000000500F5F00000000000000000000023 ++:1073800000000000000000505000000000AA0000B3 ++:1073900000000000000000F03CAAFFFFFFA3000077 ++:1073A0000000FBFBD3D30000000000000000000041 ++:1073B00000000000000000000000000000000000CD ++:1073C00000000000000000000000000000000000BD ++:1073D0002C0000000000050400000000FFFFDFFF9C ++:1073E000000000000000000000000000000000009D ++:1073F00000000000053D003C0202FF028A9ECBDF38 ++:107400000000000055FF55FF008A8A003404000088 ++:10741000000000000000000000000000FFF0FFF08E ++:10742000410014000FFF5C5C0A00A0000000000097 ++:10743000000000300C00000000000A00A000000066 ++:107440000000C00040000004000010000000000028 ++:1074500004000020000000040000000000000FFFF6 ++:107460000F0000000000000000000000000000000D ++:10747000000000000000050500000202FD00081CDD ++:10748000495D0000000055FF55FF008080000000AE ++:107490003404000000000000000000000000FFEBCA ++:1074A000FF414100140000F05C5C0A00A0000000F5 ++:1074B0000000000000300C00000000000A00A000E6 ++:1074C0000000000000000000040400005000000064 ++:1074D0000400040000A00000000C000000000000F8 ++:1074E0000F0F0F000000000000000000000000006F ++:1074F00000000000020002000210040882001000D8 ++:10750000000400008000110021048000000004003D ++:1075100000002120210000002100020300000000E3 ++:107520000000002000000000000000000000040037 ++:1075300000000488000000000000000000000000BF ++:107540000000000000040000000000000004000033 ++:107550000000000004000000000000000000000027 ++:107560000000000000820000000000000000000099 ++:107570000000000000000000000000000080400249 ++:1075800001000004000020000000000020000000B6 ++:10759000000000000080000000000000004000002B ++:1075A00000000000000000000000000000000000DB ++:1075B00000000000000000C000000000000000000B ++:1075C00000000000000000800000000000000080BB ++:1075D00000000000000000000000000000000000AB ++:1075E000000000000000000000000000000000009B ++:1075F000000000000000000080000001000000000A ++:1076000000000000004080002100400000400020F9 ++:107610000000000002000000000000000001000067 ++:107620000020000000000001000000000000000039 ++:10763000000000000002000000C000000000000286 ++:107640000000000000000000000100000000000039 ++:10765000000800000000000000000001000100011F ++:107660000003000000000000000000000000000017 ++:1076700000000000000000000000084100080000B9 ++:10768000021000100021009002100221000800A149 ++:107690000000002100000100001000000000002098 ++:1076A000002100A1040000020004000900210000E4 ++:1076B00000000000000000000010000000000000BA ++:1076C000000000000000000000000020000500098C ++:1076D00000210080000000000000001000040020D5 ++:1076E000002000200000000000000000000000005A ++:1076F00000000000000000000000000200100084F4 ++:107700000000002000C10000000100A000020008ED ++:1077100003000000008400050000828440A00000F7 ++:107720000004800000A000000020084000100000BD ++:10773000000000A000A000A0000000000000002049 ++:1077400000200000001000000000002000000000E9 ++:1077500000000000040000C0800000000000800065 ++:107760000000000400000000000100000000000014 ++:107770000000000000000000000000000000848005 ++:107780001000404000800002040000080011A080AA ++:10779000089010000000000000820000112084000A ++:1077A000C0118280040000000000008001900021D0 ++:1077B0000000100000050021000000110000000082 ++:1077C0000000020010000000200500000080000002 ++:1077D00000000000000001000000040000000000A4 ++:1077E00020000021008000000000000200000000D6 ++:1077F0000000000000000000000000000000000089 ++:1078000090000500830000001000210000010488A2 ++:1078100041C0200041000220414000000000100053 ++:1078200002001000020010000000038400000000AD ++:10783000000100000000C0000088410002000000BC ++:1078400000000000080000004100400000000000AF ++:107850000000000000000000000008000000000020 ++:107860000000030100000000800100000000000093 ++:107870000000000000000000000000000000000008 ++:1078800010000800A00004000000000000008808AC ++:10789000010090098500000008800000C000000081 ++:1078A000000500000000C000000000008200880009 ++:1078B000000000081000000003000040000000006D ++:1078C00000000000000000000000000000000003B5 ++:1078D00000000000000000000000000000000000A8 ++:1078E0000000000000400000000010200000000028 ++:1078F0000000000000000000000000000000000088 ++:107900000000000000000202080040000400040023 ++:1079100000C010008001A010030090400000000093 ++:107920002100419108000400100000009084000133 ++:1079300080200988000210200000808400000000E0 ++:1079400000000020000000000000001000100200F5 ++:107950000000000000000020000000008000001077 ++:1079600010000000092100000400000400100000C5 ++:1079700000000000000041000000000000000000C6 ++:107980000000000000000020C00200024000A00033 ++:1079900010000000000008042100002120830809D5 ++:1079A00000000020000200000000000000000405AC ++:1079B000004004000000C08001001000200500000D ++:1079C00000000000840000C01010840000100010AF ++:1079D000840000000000000000000000000004001F ++:1079E00000800000000084900000010000830083FC ++:1079F000C0000000000000000000000000000000C7 ++:107A00000000000000000000008400209001882099 ++:107A10000000418208000088111080400290800917 ++:107A200005000040108408001084410083004000DD ++:107A300000C0838400820000008400100010040154 ++:107A400000C01100008400C10000101000101000E0 ++:107A5000100040004100000005000000000002008E ++:107A600009000000000000200000000002000000EB ++:107A70000000000000020000009000000000000074 ++:107A800000000000000000000000000000000520D1 ++:107A9000048000000000000008110009209100008F ++:107AA00040840000820000000000000088001000F8 ++:107AB000014100001000000000000000C0000000B4 ++:107AC000034000000000000000040000000000006F ++:107AD00000000000000000000000000000000000A6 ++:107AE000000000000000000000800000880000404E ++:107AF0000000000000000080000000000000000006 ++:107B0000000000000000000000000000400800101D ++:107B10008005032002050505210209408303204159 ++:107B2000030509090005000540410021001100205E ++:107B30008420004002850390110811C14003090808 ++:107B400041100210000000000000000400000000CE ++:107B5000000000000000000000000000000009001C ++:107B600000004100020000000000800000000583CA ++:107B70008041828910110000000000000000000018 ++:107B800000000000000000000000000000000100F4 ++:107B900000012000010101011100010000000801A5 ++:107BA00085010001010090000400010000000001B7 ++:107BB000C000040100000089C005000500080001A4 ++:107BC0008800010000000000000000000004000028 ++:107BD00000000000000000000000000002000000A3 ++:107BE00000008800000000000000000040000000CD ++:107BF0000483400011890191000000000000000092 ++:107C00000000000000000000000000000000000074 ++:107C10000000000088008200C001C0C0C0032041F5 ++:107C20008300890291A182C1400084010300830086 ++:107C30000100012101400100410084828801C10846 ++:107C400000000082010000000000000000000004AD ++:107C5000000000000000000000000000000000A084 ++:107C600000000100000000000001000101008988FF ++:107C700083900500414089019191000001000000BE ++:107C800000000000000000000000000000000000F4 ++:107C900000C041000200850085000308200085C067 ++:107CA00000914003C18010A1888983000040A0207A ++:107CB0008300100008100883090291048880C02105 ++:107CC000A082200020804003054100000000000049 ++:107CD00000000000000000000000000000000000A4 ++:107CE0000800000011000900100041030202020018 ++:107CF000858091800804C180890290914100200014 ++:107D0000050000000000000000000000400000002E ++:107D1000000000004021002000200090100500918C ++:107D2000049083030589000900C0C04003000000DF ++:107D30000080008010820009410940090908808400 ++:107D40004120058804100020020285400000000048 ++:107D50000000000000000000000000000000000023 ++:107D600000000000800000040020214000A000115D ++:107D7000000021008089048400859189C089000069 ++:107D800000000000000000000000000000000000F3 ++:107D90000000000000000100000100010089000255 ++:107DA000000900110509000300000085830901C0D6 ++:107DB00000840040002001080008008203A0009019 ++:107DC0000811C089004000400003000911090000AB ++:107DD00000000000000000000000000000000000A3 ++:107DE000000000000000400000A000890091000396 ++:107DF00000010000010084890088C085898991897B ++:107E00000000000000000000000000000000000072 ++:107E100000000000000000000021000100010088B7 ++:107E20008241C001820110A041038502A100C1105E ++:107E3000009001000000000200020141000100006A ++:107E4000834004A0C10100C001020004010101003F ++:107E50000000000000000000000000000000000022 ++:107E6000000000000001000000000002000000010E ++:107E70000000829188018201888883854191830175 ++:107E8000C1C0000000000000000000000000000071 ++:107E9000000000000000000000000011000400408D ++:107EA0000080C01041100420910089091003400394 ++:107EB000C0800383400021050380088011C020108A ++:107EC0004000A00311080810108010001190094014 ++:107ED0001000000000000000000000000000000092 ++:107EE0000000000000000008000000000000004149 ++:107EF000000200008091800900208080898285C076 ++:107F000009210900000000410041000000000000BC ++:107F10000000000000000000000000000A00001344 ++:107F20000000006000000022D000004100500081ED ++:107F3000C2000041000000800100060000000013A4 ++:107F4000C2000000210000130100820000000013A5 ++:107F5000C20042000000000000001200000000000B ++:107F6000000000000000000000138100000000007D ++:107F7000000B440000502100000B00000000000036 ++:107F80000080010000000000000000000000000070 ++:107F900000000000000000000000000000000000E1 ++:107FA0000000FFFFFFFF5F7F5F7F0000FFFF000417 ++:107FB000FFFB283C2236A0C3A000000000000CCF2D ++:107FC0007D7D3FFFFFFF14001400004100FF3CFFD8 ++:107FD000171708500A5000000000000000000000C1 ++:107FE0000000000000000000000000000000000091 ++:107FF00000000000303001030000000000003C3CA5 ++:1080000000000000AA28AA280000000000000000CC ++:108010000000000000000000000000000000000060 ++:1080200000000000FDFFFFFF003C0F3F00410F3F3D ++:108030000014FFEB283C283CA0C3A0000000000077 ++:108040000CCF41413FFFFFFF14001430004000FF00 ++:1080500000C317170850085000000000000000007F ++:108060000000000000000000000000000000000010 ++:1080700000000000000000000103000000000000FC ++:108080003C3C20A00A0A2A28AA2800000000000080 ++:1080900000000000000000000000000000000000E0 ++:1080A00000000F000F00F0F80028555510108CCC80 ++:1080B0008CCC55AAFDFE0F0F0F070303030300002E ++:1080C000003CFFFFFFFF575557D7FFAAFF80003D39 ++:1080D000FFFF00C0828EFFB455B400000000000016 ++:1080E0000000000000000000000000000000000090 ++:1080F0000055005500000000FF0AFF0A00000000C4 ++:1081000000000000FEFEFFFFFFFFFFFF0000000079 ++:10811000FAFEFAFE0000000000000000000000006F ++:1081200000000000FCFC0C0C002800285555140031 ++:1081300080C080C055AA00000F0F0F0F000000FF85 ++:108140003C000000BFBEBFFF7F7D7FFFFFAAFF0096 ++:10815000003D003D00C08282AAB400B400000000CF ++:10816000000000000000000000000000000000000F ++:1081700000000055005500000000FF3CFF0000001B ++:10818000000020000000FEFEFFAAFFFFFFFE00002F ++:108190000000FFFFFFFF00000000000000000000E3 ++:1081A000000000000000000600E1018000000086E1 ++:1081B000006100B2008000860A6508B800000086F1 ++:1081C0007C60009000A000860CF1A8B800850086B5 ++:1081D000004101A8000000860A71A8B8000500004F ++:1081E000000000000000000000000000000000008F ++:1081F000008600E100B000000086006008980005DD ++:10820000000200A00380000000820AB0008000800D ++:1082100000000000000000800000000000000000DE ++:10822000000000000000000000000000FFFF000050 ++:10823000FFFAFC3C55005F00FFDFFFFFFFFFAA696C ++:108240000000000001010115000000003DFFFDFFDE ++:10825000555FAAA000000000000000000000000020 ++:10826000000000000000000000000000000000000E ++:1082700000000000000000000000000000000000FE ++:108280000008DF20DFDFFFFF000000BE00FA000073 ++:1082900000000000000000000000000000000000DE ++:1082A0000000000000000900000000000000FFFFC7 ++:1082B0000000FFFAF00055007D00FFFFFFFFFFFF09 ++:1082C000BE7D0000000000000000000000003D0036 ++:1082D000FD005555AAAA00800000000000008000A3 ++:1082E000000000000000000000000000000000008E ++:1082F000000000000000000000000000000000007E ++:1083000000000000FF002020FFFF000000BA00AEC8 ++:10831000020028AA00000000000000000000000089 ++:10832000000000000000002000000100000000002C ++:10833000AAAA55AA000000000000000000000000EA ++:10834000555500040000000055550CCF00000000FA ++:1083500000000000AA55FF0000FF04FB0000000021 ++:10836000000000000000000000000000000000000D ++:1083700000000000000000000000000000000000FD ++:1083800000000000000000000000AAAA55AAFFFF9C ++:10839000FFFF00C000C0000000000000000000005F ++:1083A000000000000000004000000000020000008B ++:1083B0000000555500FF0000000004000000000010 ++:1083C0000000000000000000000000000CCF0000D2 ++:1083D000000000000000A25DFF0000FF00FF0000A1 ++:1083E000000000000000000000000000000000008D ++:1083F000000000000000000000000000000000007D ++:10840000000000000000000000000000555500FFC3 ++:10841000FEFEBEBE4000C0000000000000000000E4 ++:10842000000000000000000000000000000000004C ++:10843000000000000000000000000000000000003C ++:1084400000000000008000000C800000000080C2DE ++:108450000000220542009313444000105908188080 ++:10846000881A92CC07004A3000000000000000008B ++:1084700000000000000000000000000008000000F4 ++:1084800000000000000000000000000000000000EC ++:1084900000000000000000000000000000000000DC ++:1084A00000000000000000000000000000000000CC ++:1084B00000000400040020A00400000003002101CB ++:1084C0000000800000000000C0000000210000004B ++:1084D0000000000000000200020020000300000075 ++:1084E00000201000000000000000820000000000DA ++:1084F000000000C0000000000000000011000000AB ++:10850000000000000000000000000000000000006B ++:10851000000000000000000000000000000000005B ++:10852000000000000000000000000000000000004B ++:108530000000000001000000000083009000000027 ++:1085400000100000080000000000030020000000F0 ++:10855000000000000000000000000000000000001B ++:1085600000000000000000000000000020000000EB ++:108570000000A000008000000000000000000000DB ++:1085800000000000000000000000000000000000EB ++:1085900000000000000000000000000000000000DB ++:1085A00000000000000000000000000000000000CB ++:1085B00000000000000000000001002103C1800055 ++:1085C000A1010020000000008001A1010011800530 ++:1085D000800000000000000000000000000000001B ++:1085E00000000000100000000001000000018000F9 ++:1085F00080000482040000C00000000000000000B1 ++:10860000000000000000000000000000000000006A ++:108610000000000100010004000040000000000014 ++:10862000000000000000000000000000000000004A ++:10863000000000000000000000000020008482080C ++:10864000020002040000900082004002104000027C ++:1086500010884041902000000000900000000020A1 ++:1086600000000000000900000000002000000020C1 ++:10867000200004100310010000800000000004002E ++:1086800000000000000000000000000000000000EA ++:108690000000001100040004008000000000000041 ++:1086A00000000000000000000000000000000000CA ++:1086B0000000000000000000000000000084050829 ++:1086C00009000000000000010008000100100484FF ++:1086D00002004100000005104108000000000020D9 ++:1086E000000000400000000200000000000009003F ++:1086F000800000000000000000000000000000A05A ++:108700000000000000000000000000000000000069 ++:108710000000000000000000000000000004000451 ++:108720000004000000000000000000000000000045 ++:1087300000000000000000000000000004118400A0 ++:108740001000881088090000001000A1001082802D ++:1087500010000103000000009021000884000000C8 ++:10876000C0000000C02100210000000000080041FE ++:108770000000100800090000004000400000000058 ++:1087800000000000000010000000000000000000D9 ++:108790000011000000001000000000000000008038 ++:1087A0000080008000008200000000000000000047 ++:1087B00000000000000000000000000000001000A9 ++:1087C0000500092091C0210003000810900010004E ++:1087D0004100410820001001C001A1042100210036 ++:1087E00000000000000000A00000020000000000E7 ++:1087F0000000004000000510000000000000000024 ++:108800000002000000000000000005002100200020 ++:108810004000400040004000000000000000000058 ++:108820000000000000880090000000000000000030 ++:108830000000000000000000000000000000000038 ++:1088400000000005828004000009C00082001100C1 ++:10885000000010008491850000080304408000009F ++:10886000C00000110800C00020001000080008002F ++:108870008809000000000000000000000000000067 ++:1088800000000880002108410800000010000800D6 ++:1088900000000100010009000900000000000800BC ++:1088A0000000000082000000000000000000000046 ++:1088B00000000000000000000000000000000000B8 ++:1088C000000002000000020010001082210090024F ++:1088D0000884C10340408488830204001002109081 ++:1088E00004024140418800200088009000040920D3 ++:1088F000092000000300000180000310100009009F ++:10890000000000000900020000020900000004A0AD ++:10891000000005000000000003000000000041000E ++:10892000080400A000000500000000001000000086 ++:108930000000000000000000000000000000000037 ++:108940000000000000000000000000008440000063 ++:108950000800000808100100020002C0C1210080C8 ++:10896000000001001000820010A0100084030080AD ++:1089700010C0A0C040110000000420000000000052 ++:108980000000004000000000000000800000000027 ++:10899000010000000000100000000000A000000026 ++:1089A0000000008000030000000000000021000023 ++:1089B00000000000000000000000000000000000B7 ++:1089C0000000000000000200419008820340020005 ++:1089D000100121C141A140C08800058520400284CA ++:1089E000024000840500059005400004410000009D ++:1089F00000000002000420080020000000008000A9 ++:108A00004000000400010000002003820000030079 ++:108A1000000000A000000000000000200000000096 ++:108A200000000300410000000000000000000004FE ++:108A300000000000000000400000000000000000F6 ++:108A400000000000000000000000A0000000A000E6 ++:108A50000841104084041040010008100008018003 ++:108A6000C0118590C00000400000104000000800C8 ++:108A70008800C000C080C080C01102C0000010008B ++:108A80004000010040000002000000800021A00022 ++:108A90001000100008000000080000000420000082 ++:108AA00000000400000000000000000000000000C2 ++:108AB00000800000A0000000000000000000000096 ++:108AC000000000000000000000004080000009805D ++:108AD00003800088058910214109400820110210F7 ++:108AE000412020859091210208410803080200409E ++:108AF000101103058009050520400000000040001A ++:108B00000000000000110000000000000083400091 ++:108B100080890000820310004180000000030040B3 ++:108B200000000000000000000000030040400004BE ++:108B300000200002000000000000000000002100F2 ++:108B4000000000000000000000000000018810107C ++:108B5000040800108883C1090141010801010100D6 ++:108B60000001010101898484018801A10000A001A4 ++:108B700000010100C10182010101010100000000AA ++:108B800001000000000000000000000000000011D3 ++:108B900005A010C100888901A1A0C19000C00001FA ++:108BA0000000000000008800000000000100C1017A ++:108BB00000000001000000000000000000000000B4 ++:108BC00000000000000000000000000000000200A3 ++:108BD000C1008900110001000089000100A1050009 ++:108BE000038203848301C0004002890191A1010036 ++:108BF000A0898990C0C1850082088589C1010000D3 ++:108C0000000000000001010000000002010000005F ++:108C10001001C000000089009001A084C088C1C07C ++:108C20000000014000000100000000010000000001 ++:108C300001000084010100000000000000000000AD ++:108C400000000000000000C0000000000000000064 ++:108C5000114008008800100010041188080211401B ++:108C600090009011A18483090000090089058320E8 ++:108C7000080009038808888391000800A191400931 ++:108C800000040000000000031000000000000300CA ++:108C90000000800800000000030080400000808089 ++:108CA0000380000008000000030000000004000032 ++:108CB000000240000400202000000000000000002E ++:108CC0000000110000000000000000000000000093 ++:108CD0000000000480111089008209800091088939 ++:108CE0000440001000C003890884040980A0100219 ++:108CF00010C1891000910388890810080002004003 ++:108D000041820080000010000080800041000011BE ++:108D1000000300800000009000008003000000803D ++:108D20004000C003000000000040000300030003F7 ++:108D300000030003000200040020050500000000FD ++:108D40000000000000000000000000000000000023 ++:108D50000000000000C0080141A104880008A041F3 ++:108D60000305040100A0000300A00382824090914B ++:108D700000C10088820800A001A18802000800024A ++:108D800000C10188000800400104008802000000C2 ++:108D90000000C00100C000C00490008888C10082AB ++:108DA000909005048901000000000000000100010E ++:108DB00000010001000100000000000100000000AF ++:108DC00000000000000000000000000000000000A3 ++:108DD00000000000000008A0888410001000C002FD ++:108DE0008505A0010501000300A1000100C08388E2 ++:108DF0000590040003C1A003A0890301C1A00102E2 ++:108E00000102010101C02020888400000000000050 ++:108E10000000000000000080C10491008201C090A9 ++:108E20000100A004C00190C001000000000000008B ++:108E30000000000000100000000200090000000017 ++:108E40000000000000000000000000000000000022 ++:108E50000000000000000000801180110008800068 ++:108E600010004108094040100811109109081080B5 ++:108E700083004080080040C184210489402188008B ++:108E80000310200202022080008080000000000009 ++:108E90000000000000000000008003100900002115 ++:108EA000008003000000002180800300000000001B ++:108EB0000000000000000000000004000284030322 ++:108EC00000000000000000000000000000000000A2 ++:108ED0000000000000000000000021000013C2009C ++:108EE00000000084000BC200000021810013C1803B ++:108EF000000012600083C200000081004083000077 ++:108F0000124211820183C100810000000013C200DF ++:108F100000500000000720000000000000000013C7 ++:108F2000000000000000001300000000000000002E ++:108F30000000000000000000E0000042000000000F ++:108F4000C20000000000000000000000000000005F ++:108F500000004100000000000000000000000000D0 ++:108F6000A505A5053F0F7F4FFF00FF003EFEFE3E1B ++:108F7000BDBDBD2DFF000F66F6F63F301400820028 ++:108F800004082010F0F06F630000000000000000F3 ++:108F90000000000000000000FF0000000000FF00D3 ++:108FA00000000F0F0000FFFF000066660000FFFFDB ++:108FB0000000FF00000000000000000000000000B2 ++:108FC0000000000000080000000000000000000099 ++:108FD0000000000000000000000000000000000091 ++:108FE00000003C0CC3033000704000000F0F02C2B1 ++:108FF000C202BDBD2D2D3C3C4E4E06063F30001436 ++:10900000008202014080FFFF666600040404000045 ++:1090100000000000000000000000FF000000000051 ++:10902000FF0000000F0F0000000000006666000057 ++:1090300000000000FF000000000000000000000031 ++:109040009000000000000008000000000000000088 ++:109050000008000000000000000000000000000008 ++:109060000000000000000000000000000000000000 ++:1090700000000000000000000000000000000000F0 ++:1090800000000000000000000000000000000000E0 ++:1090900000000000000000000000000000000000D0 ++:1090A00000000000000000000000000000000000C0 ++:1090B000000000000000000000000000000000218F ++:1090C0008000000000000000000000000000000020 ++:1090D000000000000410000000000000000000007C ++:1090E00000000000000021FF2103427E427E663C1A ++:1090F000663C667EF6FE5A5A20DBC3C0C0C0000044 ++:109100000FF00011002280401020F0F0F0FF181F37 ++:109110003C3F000000000000000000FF00FF0000D6 ++:109120003C3C00000000F0F00000FFFF000066661D ++:109130000000FFFF000000FFFFFF0F0F0000000016 ++:109140000000000000080000000000000000000017 ++:10915000000000000000000000000000000000000F ++:1091600000000000000000002BFF2B0FC0FCC3FF1D ++:10917000F0F00F0F667EF6FE666600FF8303800048 ++:1091800000000FF01100220001020804B0B0B0FF8F ++:1091900018FF3CFF000000000000000000FF00FF7F ++:1091A00000003C3C00000000F0F000000000000067 ++:1091B000666600000000000000FFFFFF0F0F0000C8 ++:1091C0000000000000000008000040004000000017 ++:1091D000000000000000000000000000000000008F ++:1091E00000000000000000860090098000800084DC ++:1091F000707500B0008000060C6501380010A5A64F ++:109200000044A9804C600086002001C0140008863C ++:1092100000640188000000860031A8900005A08647 ++:10922000016008B44940000002C701800084494041 ++:1092300002C701800084494002410100000441400E ++:1092400000005000000000050000001000000000B9 ++:1092500000000000000000000000000809000000FD ++:109260000000000000000000FF00CB0841C37DFFAC ++:10927000FFFFFFFF4D4D4D4D00000000000200823A ++:1092800030FF30FF0C0CFFFFFF0F3C3C0CFF0CFFCE ++:10929000000000000055F3F7FF00AAAA0010FFDF4E ++:1092A000000000000000000000000000008003003B ++:1092B00000000000000000000000000000000000AE ++:1092C000000000000000000000000000000000009E ++:1092D000000000000000000000000000002000006E ++:1092E00001000000000000000000FF00CB080000AB ++:1092F000FFFFBFBFBEFF417D417D000000000002B7 ++:10930000008230FFC3000008F3FB3C3C3C3C0CFFF8 ++:1093100000F3000000005555F7F7FF00AAAA00105F ++:10932000FFDF0000000000000000000000000080DF ++:1093300000000000001000100800080000000000FD ++:10934000000000000000000000000000000000001D ++:10935000000000000000000000000000000000000D ++:10936000000002000000000000000000FFEF1404F5 ++:1093700030FF00CF03C0FFFF00000000000000002E ++:10938000F359F355FFDFA08000FA04FE000000004F ++:1093900000FFAFAF000000000CFF0CFF000000005A ++:1093A00000000000000000000000000000000000BD ++:1093B000020000000000000000000000200000008B ++:1093C000000000000000000000000000000000009D ++:1093D000000000000000000000000000000000008D ++:1093E0000000000000000000000000000000FBEB97 ++:1093F000100000CF00CF03C0AAAA000000000000A8 ++:1094000000000C0C0C00FFDFA08000FA04FE00003E ++:10941000000000FF00FF000000000CAE0CFF000089 ++:10942000000000000000000000000000000000003C ++:1094300000000200101000000010001000002000CA ++:10944000000000000000000000000000000000001C ++:10945000000000000000000000000000000000000C ++:1094600000000000000000000000000000000000FC ++:10947000042084000400110002000408020182009C ++:10948000410000A002101100000040001000040084 ++:1094900000000300000003100000020000000004B0 ++:1094A0001100000011000000000005000000002075 ++:1094B000004000000000000000000000000000006C ++:1094C000000000000000000000000000000000009C ++:1094D000000000000000000000000000000000008C ++:1094E000000000000000000000000000000000007C ++:1094F0000000880010000000020004000080010845 ++:1095000041002000000000002000C0000100010018 ++:1095100000000000000000000080000000000000CB ++:1095200000000000880000000000000000000000B3 ++:109530000000000000000000000000000800000023 ++:10954000000000000000000000000000000000001B ++:10955000000000000000000000000000000000000B ++:1095600000000000000000000000000000000000FB ++:10957000000000000000000000008000000000006B ++:109580000000000000010000020100000000004097 ++:109590000000800000020001000000000000000048 ++:1095A00000000000110100000000000000000000A9 ++:1095B0000020040000C000000000000000000002C5 ++:1095C0000000000200030005000000000000000091 ++:1095D0000000000020080000000000000000000063 ++:1095E000000000000000000000000000000000007B ++:1095F0000000000000008821004120210221040019 ++:1096000000000000C0000004001191040010820856 ++:109610000091002110000080004000210021001175 ++:10962000000000000010004000000041A0100000F9 ++:1096300000000080000000C000000040002000008A ++:1096400000800000008000C00084000000000008CE ++:109650000000000000000180000000000000000089 ++:1096600000000000000000000000000000000000FA ++:1096700000000000000000000005041000040000CD ++:109680000010414000840010008400840010000499 ++:1096900000000002002003401184008400000090BC ++:1096A00000000000000804050240044004080440D3 ++:1096B00000000002800000A000002004200420918F ++:1096C000000102000000000000000000200008006F ++:1096D0000000000000000002000000000000000088 ++:1096E000000000000000000000200000000000005A ++:1096F0000000000000000000000090848205028548 ++:1097000008101000000040031009841000111021FF ++:10971000108010094091408000850000101000105A ++:10972000C002C0210020C0020190011000000040D2 ++:1097300000400000020040000000000001800180A5 ++:10974000910400040000000000000200000000007E ++:1097500000000000000010000000000000000400F5 ++:109760000000000000000000000000800000000079 ++:1097700000000000000000000000000010001000C9 ++:109780001000050009000500110002011000410051 ++:10979000020020A0040090001001209010000000A2 ++:1097A000100141012100000000001000090002002A ++:1097B0000300000000021082900241020000050434 ++:1097C0000004000410040000050100008390A000C4 ++:1097D00005000000000000000001000084012001DD ++:1097E0008008000480010000004000080000000024 ++:1097F0000000000000000000000000000000A005C4 ++:10980000C00008008205A0008809A0419102C003A1 ++:10981000C0000841080501004041A002A0408404A6 ++:1098200002000008100800000000102100000005E0 ++:1098300001001000C00002800804048000800000C5 ++:10984000C080C0A10089108082001040C0050200C5 ++:10985000210002401000A0000000000200000540AE ++:10986000010410800080020400000000008000005D ++:1098700000000000000000000000000000000000E8 ++:10988000000240850010090800000500000040406B ++:1098900003100082020404000008C04021009085EB ++:1098A000418820004100000000001000000005C1B8 ++:1098B000004005A108400040200040000091100138 ++:1098C00000001102100000002090000000000800BD ++:1098D0000800090004002100000000000000000052 ++:1098E000000000000200200004000088000000903A ++:1098F0000000000000000000000000000000000068 ++:1099000000009009820800080010400000051000C7 ++:10991000A1890000A01104C001004080218000093D ++:1099200010084002110040028800000000020041BF ++:1099300010020080000400051080052001000020B6 ++:1099400000200080008000090000001100000000DD ++:109950000000000000000100000400000000000002 ++:109960000000000000009000010000000002000064 ++:1099700000000000000000000000000000000000E7 ++:109980000000000002C00300030020A1210000C06D ++:1099900005000285009041A0088804212108910457 ++:1099A000008841840901000011080801100002002C ++:1099B0000000080000100000004085000400039033 ++:1099C0004000050000000020089005880008000005 ++:1099D00010020500410010000200000041000000DC ++:1099E00000000000000000000000210020008000B6 ++:1099F00000210020800000000000000000000000A6 ++:109A0000000000000000000000000800090210092A ++:109A1000A000C0008820C0210203C00002A0C091A5 ++:109A2000109100008440A002840002800140880060 ++:109A3000050000400200A000A0001000044000004B ++:109A400010210121000000000080080088090000AA ++:109A50008200C0800040C000000000400000840080 ++:109A600084000000A0008400C0000000000001008D ++:109A7000040000880080400000000000000000009A ++:109A80000000000000000000090309094108410925 ++:109A900020038000110020102103A10921021109D7 ++:109AA000808500858809000903004000050020002A ++:109AB0000020100800080040008203090082000511 ++:109AC00000000811890000000000000300001009D8 ++:109AD00000000003000009000000828300004080B5 ++:109AE000000002000000090005000009000208094A ++:109AF0000810088300092040020000000000000058 ++:109B000000000000000000000000200184000000B0 ++:109B100001000101C000000091018901090001015B ++:109B200000018804A084418200C0010004000000FC ++:109B3000010090018401000000000440400900C0C1 ++:109B4000000200000100C1000000000000C1A010E0 ++:109B5000A00100A000010000000000008905C0C0B5 ++:109B6000A1900000010010000000010000000800AA ++:109B7000010000000009040411A100000000000021 ++:109B8000000000000000000000000000040090C081 ++:109B9000A0010100080082000908850004009190DE ++:109BA000C0010201000004C18891840991000301F1 ++:109BB000840004894101040305A18290000000880B ++:109BC00000010010830002C008882100000000018D ++:109BD000A00010900300C000C0000200118290009D ++:109BE000C084408803020100010000100000000052 ++:109BF000008200000000C0010400A000000000007E ++:109C000000000000000000000000000000008900CB ++:109C100009000541090091000000C0009002910078 ++:109C200008801041A1090203020290A19120C00006 ++:109C30004008850000C1A0108840C1058290001135 ++:109C400000C100020080100080008091030000002D ++:109C50000002000400808304004180000000838231 ++:109C6000800000008080838011002000418000057A ++:109C70004000108041001000004000000000000083 ++:109C800000000000000000000000000000000000D4 ++:109C9000404000050909408000100000009009853F ++:109CA00011880005008480A103880011400400048D ++:109CB00000A000842188000303A000040988058017 ++:109CC00004000080C00041000000000000900083FC ++:109CD00000000000008084C0800305000080008434 ++:109CE0000083008000808080C0030040001000409E ++:109CF0000041108000050010100811058085000942 ++:109D00000309000000000000000000000000000047 ++:109D1000000001410041004191A0000900A0004065 ++:109D2000910900890085008890820008000902904E ++:109D3000000040A10090018440A1010400000084C3 ++:109D4000C188000840100282C0880010002000086E ++:109D5000000500000410A090020388010004001018 ++:109D6000008400410204C09040408901000500A029 ++:109D7000008302A000100009000900890000404192 ++:109D8000040401A00000000000000000000000002A ++:109D90000000000001C00111008500020000000168 ++:109DA0000001000801100088010100A011018902D2 ++:109DB000A0000009828984908800C00883918401F2 ++:109DC00010010940854010040800080001000190BE ++:109DD0000000010000001100A1020201A090090092 ++:109DE000A010400010C0C101C0004001900000025E ++:109DF000000000000000000001100000010004014C ++:109E00004040A00002C00000000000000000000070 ++:109E10000000000000000908410404C00800001010 ++:109E20000010001000000880100920212100830389 ++:109E300040410005408580C0008880000000A0826D ++:109E400040088540C080A08005004100020003104A ++:109E5000080020002000000003100900802100807D ++:109E600083090005840080800303000080218000B6 ++:109E70000000000400040000110010090811110086 ++:109E80000040808000000080000000000000000012 ++:109E9000000000000000000000840000C20000007C ++:109EA000000000810100000000000081810000002E ++:109EB00082000013440081000000000002008100C5 ++:109EC000410080838100210000840083C2000000E3 ++:109ED00000000013C2000000000000000013020098 ++:109EE0000000000000000000006000000013C1003E ++:109EF000060000000013E000000000000000C200A7 ++:109F0000820000000013000000410000000000007B ++:109F1000000000000000000000000101BFBF2A7F18 ++:109F20002A7F00000000417D7D7D550017003D0027 ++:109F30000500D700FFFF003C0C3F0000000036C9C1 ++:109F4000C1F7C3FF4D4D0CFF0CFFFFFFABBF00007F ++:109F500000000000FFFF000000FF0000000000FF05 ++:109F6000000000FF00000F0F000000FF0000FFFFD7 ++:109F700000005555000000003535C5C5033FC0FC45 ++:109F8000F0FF000F00000000FFFFFFEF00000000E7 ++:109F90000000000000000000000000000041BEFFC3 ++:109FA00000FF00FF00000000417D41410000030070 ++:109FB00001000500D70028FF003C0C3F0000000016 ++:109FC000936C40D3003C4D4D0CFF0CFF000001157D ++:109FD0000000000000202F2F000000FF0000000004 ++:109FE00000FF000000FF00000F0F000000FF000056 ++:109FF0000000000055550000000005F5F505003C87 ++:10A00000C3FF000FF0FF0000000000000000000090 ++:10A010000000000000000000000000000000B2B2DC ++:10A02000FF00FFBFC080BEBE4141AAAAAAAAF0F0AD ++:10A030003C3C003C00ACFFF3FFFFFFFEFFFA0000DA ++:10A0400000002EAF2EAF3C3CFFF03F3E0302AEA21D ++:10A05000EF2000000000FF00FF003C3C000000007B ++:10A06000F0F00000FFFF0000FFFF0000AAAA0000C0 ++:10A07000AAAA00000000FFFF00000000FA50FA50FA ++:10A08000FCFFFDFD3C3C2C3C5FFF5F5F00000000DF ++:10A0900000000000000000000000000000000000C0 ++:10A0A000B2B2B2B27F3F4000BEBE4141FF00FFC32B ++:10A0B000F0333CC3000000A0FFFFFFFFFFAEFFAA8C ++:10A0C000000000002EAF2EAFFFAAFFAA3F3C030006 ++:10A0D000FF00FF0000000000FF00FF003C3C00000C ++:10A0E0000000F0F000000000000000000000AAAA3C ++:10A0F0000000AAAA0000FFFFFFFF00000000BE143E ++:10A10000BE14FFFFFFFF3C3C7C3CFFFFFFFF000055 ++:10A11000000000000000000000000000000000003F ++:10A12000000000860A7400B000000086046100B0E0 ++:10A13000000000860A7100900000058650C001A052 ++:10A140000080A0865060A8B9008500820C6009904C ++:10A1500004050086707400B00000118601F00084D0 ++:10A1600049400000A2C75190A084494502C7016040 ++:10A1700000B44940A2C701800884414000860060C5 ++:10A1800008B800850086027008B0000000860A81C9 ++:10A19000008000000000000000000000000000003F ++:10A1A00000000000000000004100FF00000000006F ++:10A1B0005D5DDDFD000000003C3CFFFFFF5AFFA598 ++:10A1C0002D872D87000030006FFFF9FFA0A0D7FF7B ++:10A1D0003C00FFC3000000000F0F0F0F0000000045 ++:10A1E0000000200000000000000800000000C3FF85 ++:10A1F00003CF10D01FDF00000000000000000000AF ++:10A2000000000DF2FF0000000000FFFFFFFB000058 ++:10A210000800000000000000000000000000000036 ++:10A22000000000000000000000004000FF000000EF ++:10A2300000005D5D5D7D000000009C3C7FFF005ADA ++:10A2400000A5872D872D00030000F9FF6FFFA0A058 ++:10A2500000280000FFFF400000003F0F0F0F00002C ++:10A2600000000000200000000000000801000100C4 ++:10A2700041D741D710D01FDF00000C0001000100C2 ++:10A28000000000000DF237F800000000FFFFFFFFA4 ++:10A29000000008000000000A0000000000000000AC ++:10A2A0000000000000000000000000000055005504 ++:10A2B00000000000030FF5FF00000000283C2C2CDC ++:10A2C000F0F0F0F000FF00FF00000000FEBFBFFE56 ++:10A2D000000000005F575D55000000000000000016 ++:10A2E000000000000300000000000000000000006B ++:10A2F0000000000000001144BBEE00000000300030 ++:10A30000000000000000000000000000000000004D ++:10A310000000000A00001000100000000000000013 ++:10A3200000000000000000000000000000000C5DC4 ++:10A330000C5D00000000000F5F5F00000000283C83 ++:10A340002C2CFF3CC3000505AFAF00000000FD7FD3 ++:10A350007FFD000000000D010D0100010000000064 ++:10A3600000000000000000000000000000140000D9 ++:10A370000050000000000000BBEE1144000000A0EF ++:10A3800000000000000000000000000000000000CD ++:10A3900000000000000000000000000000000000BD ++:10A3A00000000000000000000000000040008800E5 ++:10A3B0000400044004000200020010000400040035 ++:10A3C0008400840040004000A102110000A01100A0 ++:10A3D00020000000800040002002000888004000AB ++:10A3E00021008004000080000008800400001000AC ++:10A3F00000000000800000000000000000000000DD ++:10A40000000000000000000000000000000000004C ++:10A410000000000000000000000000000400000038 ++:10A42000000000000000000000000000000001002B ++:10A430001100000000800000000001000100000089 ++:10A44000000020002000010001004080A00000006A ++:10A450000000000000042000010004800080400093 ++:10A460000100A00010800000040082800480000031 ++:10A470000100000004004000000000000400000093 ++:10A4800000000000000000000000000000000000CC ++:10A4900000000000000000000000000000000100BB ++:10A4A00000000000000000000000000000000000AC ++:10A4B0000000800980890001000100000000000107 ++:10A4C00000018000000000012000800080000000EA ++:10A4D0000000000100040001000000000000040072 ++:10A4E000000000000082800000000000000000006A ++:10A4F00000C000000000000000210000200100005A ++:10A500000008000000010000000100000000000041 ++:10A510000001000000000000000000000001000237 ++:10A52000000000000000000000000000000000002B ++:10A53000000000001088100804080020000000102F ++:10A540000020820420000011904000000400100050 ++:10A5500020110000902090808220201100008208AD ++:10A5600001000000000000001000000000000000DA ++:10A57000040000C000000000002100882000000846 ++:10A580000000000000000008000000400000000083 ++:10A5900000000004000000000000000000000004B3 ++:10A5A000008000000000000000000000000000002B ++:10A5B000000000004002058503011010000883C060 ++:10A5C0000084000080C0088982008000C000040070 ++:10A5D000000505400840400400A0100800C00585A3 ++:10A5E000004010C10008001000200010000000848E ++:10A5F0000084001000000000050040C0008400003E ++:10A60000009080C0800000000000004000080000B2 ++:10A6100000880000030000000000000000000001AE ++:10A620000001000100010000000000000000000027 ++:10A6300000000000000091898410820810210010A1 ++:10A64000044104000002200982042100202111009D ++:10A6500085050088088010410285001001801000E7 ++:10A66000820284C1000800C100030040000084048D ++:10A67000840484048440000084000000850082007B ++:10A68000000000000200020082000000888082803A ++:10A6900000000000A00000000000A00090000000EA ++:10A6A000001000100020001000000000000000005A ++:10A6B000000000000000000021000008050002006A ++:10A6C00083001000C0008200020005000300A0000B ++:10A6D00000001000020010000590030010000300AD ++:10A6E0008000100000000000000041A000000241B6 ++:10A6F000100003000300100400000200000010001E ++:10A7000000004000400000000000000000000000C9 ++:10A71000080200000000000000000002000000002D ++:10A7200000010000000080000001000000000000A7 ++:10A730000000000000000000000000040090040081 ++:10A74000000040030100110003000100822100000D ++:10A750002000000000001011400010041000200430 ++:10A76000020040008204000500009000C0040020A8 ++:10A77000C184002000000000038000000300880066 ++:10A78000830000000140111010000000004108404B ++:10A790000004A0000003000000000003000000000F ++:10A7A0000000022000000000200000040000000063 ++:10A7B000000000000000000000000000100408A0DD ++:10A7C0009000050810821000028221000585830098 ++:10A7D00000A0A1A08584908503884003000141402A ++:10A7E000412010100300101000A005080000000216 ++:10A7F0001084104004000020102010050000020109 ++:10A8000010000202C100C101034002884101100092 ++:10A810001090100000000000050000210940090010 ++:10A8200000000000211080008801800080010000ED ++:10A83000000000000000000000000000000085A1F2 ++:10A840009100110084030021A0001000A005042045 ++:10A85000041100052000020005088211098410047B ++:10A860000080000010090003840000000085000043 ++:10A870000080014091C001001000000900840080A8 ++:10A88000010884000000040940401000014100401C ++:10A8900000000000000000000000A0000008008090 ++:10A8A0001000A0210000C0A1040009200800202001 ++:10A8B0000000000000000000000000000000000098 ++:10A8C00011008901000490041088A1020000000218 ++:10A8D000028820008200020120C02020020810848B ++:10A8E0000001209021011000020041002085020893 ++:10A8F000100010041040100410001084040882009E ++:10A90000000009001000080000844100104000040D ++:10A9100008404000210009400300020000000090B0 ++:10A9200000000000002000040008800000218001D9 ++:10A930008020000000000000001000000000000067 ++:10A9400000000000100884804180110040000000D9 ++:10A950000080900901090440012001400080048525 ++:10A960000100002000000020000010000004000290 ++:10A97000908000002000008000800000C000A1C086 ++:10A98000202100000840C00010008400884011C051 ++:10A99000000000800100100000000800000000001E ++:10A9A0000200880000000080008000801000028407 ++:10A9B000401008C00000000000000000000000007F ++:10A9C00000000000110300040541030483038320F9 ++:10A9D00009050541000500C10289021020038041DC ++:10A9E00084200390008009A020411090402180081D ++:10A9F00005110310200000000000400000800080CE ++:10AA0000A00010800000848204C12040400840055E ++:10AA100002041005058841050011400003092000CB ++:10AA200080002000100020039100C12111050905BC ++:10AA30004141000041110000000000000000000042 ++:10AA40000000000000000001400021000100110191 ++:10AA5000400101000000008890840020008801412E ++:10AA6000088884A00108C00285850111000409003E ++:10AA7000400000010000010010000000010000087B ++:10AA80000010020400080000850503C000110089C1 ++:10AA900003A104A100080041000120000100010001 ++:10AAA00001004000010000000101C100830001001D ++:10AAB000010100040000010100000000000000008E ++:10AAC00000000000000000000000008201050000FE ++:10AAD000C0108808082105010221A000C0049010C0 ++:10AAE000C100880200000505C000400890004191A7 ++:10AAF000C000828403050800C00091000901110113 ++:10AB00000800010005100808000088001105081061 ++:10AB1000118890010282400084C0090000820385F0 ++:10AB2000C0000200C1000800090082019100A18854 ++:10AB300020900104004009A1010100000000000074 ++:10AB4000000000000000000000000000400005853B ++:10AB500011004180090290C003400010050005204B ++:10AB60000583110580A0401183408802C100410384 ++:10AB700010050400100040111100020020004010D8 ++:10AB8000200385090200050090840000000590055F ++:10AB9000A0411004801109800511858091000400F6 ++:10ABA000109000000000080080009000002091003C ++:10ABB0008980808509004180898310400000000061 ++:10ABC0000000000000000000000000000309000574 ++:10ABD00021A08890054111890241820302104002A0 ++:10ABE000C10980408284000302830241000004A066 ++:10ABF0000009020505C0001100849088008500044A ++:10AC00002140000500910002204100900080054095 ++:10AC100080919184408805200008000500402004B0 ++:10AC2000000000C140C0000000C1008500400002DB ++:10AC3000000921899185119140110005C140000052 ++:10AC400000000000000000000000000000000140C3 ++:10AC5000008901119182A0200004001010C101049C ++:10AC600008018482400482080410418400880004A2 ++:10AC7000C011204104A1001100A100A0890500021B ++:10AC8000000200A00003000800202004000900804A ++:10AC900000050411A084C111000520C082C0000578 ++:10ACA000018800A00084894100000004008400A104 ++:10ACB000008300C100A19183000901000000080188 ++:10ACC0000000000000000000000000000000000084 ++:10ACD00000080003000000000108000501080083CF ++:10ACE0008240888209008820A10291028800100811 ++:10ACF00041094104900140880105010100000088DC ++:10AD000000000100010001400001040010000210D9 ++:10AD10000080C12111830901C08885C04000A001C5 ++:10AD2000020201010001000000A00000000100017A ++:10AD3000004082018885200184880190010504007B ++:10AD40000100000000000000000000000000000002 ++:10AD5000000000802008414121000384104002854A ++:10AD600041A040840989C041110003100509410830 ++:10AD70000480098320101008110003400504040218 ++:10AD8000090011051002080508000002004080407B ++:10AD9000808000800382208582100380A000100242 ++:10ADA00004108280400304410303200000020010CD ++:10ADB00000100080800380C080218080038004090F ++:10ADC000030540000000000000000000000000003B ++:10ADD0000000000000810013C200065000000013B4 ++:10ADE000C200064100000081C200110000000013F3 ++:10ADF000C200816000810013C200110012000083B4 ++:10AE0000100000000000000044000050000000138B ++:10AE1000C2000000000000000013C200410000005A ++:10AE2000000000008200000000000000215000002F ++:10AE30000000C100000000000083C100218100006B ++:10AE40000013C200004100000000000000000000EC ++:10AE50000000000000007F1F7F1FFFFFFF7F00003A ++:10AE60000000000000000F7E0F18FCFFFC00699638 ++:10AE7000CA5C00000008FF7000700F000F000303A1 ++:10AE8000FD64EF6FE66FFEFC0E0CFF6F6666000060 ++:10AE90000000FF3F3F0F0000FFBD00013CC396963E ++:10AEA000E67FEF7653DBC35A96C3963CFF7E3C2485 ++:10AEB000000000006F0690F9000000004200400210 ++:10AEC000000066660F0F0F0F00000000000000007A ++:10AED000000000000000000070107010FFFFFFFF76 ++:10AEE00000000000000000000F7E0F180CFF0C0097 ++:10AEF000699635A300000000FF400040FFF00F00FE ++:10AF00000000FD640F0F0F00FEFC0E0CFF69020233 ++:10AF1000000000000F0C0C000000FF3C0000C33CD0 ++:10AF2000969680198910C33C333C69C3693C7E3CCA ++:10AF300024000000000090F96F06000000004200AD ++:10AF400042003000CCCC3C5A3C3C000000000000E9 ++:10AF500000000000000000000000000000000000F1 ++:10AF60000000C20804000011886100000000000019 ++:10AF700000000000000000000000000000000000D1 ++:10AF800000000000000000000000000000000000C1 ++:10AF900000000000000000000000000000000000B1 ++:10AFA00000000000000000000000000000000000A1 ++:10AFB0000000000000000000000000000000000091 ++:10AFC0000000000000000000000000000000000081 ++:10AFD00000000000000000000000000036363C3C8D ++:10AFE0006666666600000000000000000CFC0CFCB9 ++:10AFF00060F960F9A69540626666FFFF7EF07EF01C ++:10B000006EF7F76E00000000FEF0FFF00000000099 ++:10B01000F0FFFCFF000000003C7EFCFE0000CF09BA ++:10B020000F890606006630F3F3F396696969663C9A ++:10B03000663C74F674F600000000606000000808CA ++:10B04000FCFCFF9FFF9F24FFE7FFFCFCFCFA0000D5 ++:10B05000000000000000000000000000000006F6F4 ++:10B0600000FFF000F0FF00000000000000000C0CEA ++:10B07000FCFC009966FF596AE6F766663CFF7EF0C5 ++:10B080007EF008919108020000006E006F00000041 ++:10B09000000066007E3C0000000000000000000090 ++:10B0A00030F6F07F9F9F99FF3030F3309696966987 ++:10B0B000003CFF3C60746074000000000000000071 ++:10B0C0000808FCFCFFFFFFFF2400E7C30C0C0C0A80 ++:10B0D0000000000000000000000000000000000070 ++:10B0E00000860AFCA038000005860A6100B900A0AD ++:10B0F0000086007100B00000A5865A20A8B800158F ++:10B100000086005400A000000886006001980080BE ++:10B110000086006008B80085008600800080000579 ++:10B12000000008860271009000800086006000B870 ++:10B1300000800086006000B800000086006008B053 ++:10B140000000008204B00000000008000070083019 ++:10B1500000000000000000000000000000000000EF ++:10B160000000000000000F0F287D00000000FCFC24 ++:10B17000FCFCA0AA28AA000000000000505040FFDC ++:10B180000000000000017C1000000000000000FF33 ++:10B1900004FB000000000C0000000000000008009C ++:10B1A0000000000057565A5A3C003F0FFEFFB0F017 ++:10B1B000D782D7D700000000FFFFFFFF000000008C ++:10B1C0000FFF5F5F0802080A414203C00000F0F071 ++:10B1D0003C3C0000000000000000000000000000F7 ++:10B1E0000000000000000000287D287D0000000015 ++:10B1F0000CFC5CFCFAFFBEFF415500553CC35050AF ++:10B20000C2FF000000C000C1FD34000000000000CB ++:10B2100000FF0CF300000000000000000080008030 ++:10B2200008000000000097565AAA3D053C00FEF0B9 ++:10B23000B000D782D2D2000000007FFFFFFF0000E5 ++:10B24000000000F050500802020000000000000062 ++:10B25000F0F03C3C00000000000000000000000096 ++:10B2600000000000000000000000000000000000DE ++:10B2700000003D7D3D7DF0F0EB286DB27DA253FFD7 ++:10B2800000FF14141F1FF000F000FFFFFFFF00007D ++:10B290000000003C5FFD00000000040C0D0F0000EA ++:10B2A0000000000000000000FEAAFEAABFBEBDBC58 ++:10B2B000BEA2BEB60F7D0F410000000014D7D7D745 ++:10B2C000000000002BD4FFFF000000000039000048 ++:10B2D0000000FF0000FF0000000000000000000070 ++:10B2E000000000000000000000000000000000005E ++:10B2F00000000000156D1545F0F028EB1CE35DA281 ++:10B300000053000000000F0FF000F101555F7D7F3A ++:10B3100000000000003F5FFD0000000000040C0D75 ++:10B32000030000001400000000007E007EA0BEBEEE ++:10B33000BCBCBCA8BCA80F7D0F410000000014D706 ++:10B340001414000000002BD4000000000000003C9A ++:10B3500000000000FF0000FF0000000000000000EF ++:10B3600000000000000000000000000021001100AB ++:10B37000200011002000000004002008040020002C ++:10B38000201000000010400000000000110011001B ++:10B39000000420042104000000A0000400040204B2 ++:10B3A000000400000004840421000040000020008C ++:10B3B00084002001110000020000002000000000B5 ++:10B3C0000008000000000000000000000000000075 ++:10B3D000000000000000000000200000000000004D ++:10B3E00000000000008200000000000000000000DB ++:10B3F000A00090000000000000000000000000001D ++:10B400000000000000000400000004000000000034 ++:10B41000A00000800080A080000000000080A080CC ++:10B420000080008000000080048082000000000096 ++:10B430000100020001200000008000000000000068 ++:10B44000000000800000000000000000000000007C ++:10B45000000000000000000000000080000000006C ++:10B4600000000000000000000000000000000000DC ++:10B4700000000000000000000000000000000000CC ++:10B48000000000010001000000000000002000009A ++:10B4900000000000000000000000000000000000AC ++:10B4A000000000000000000000010001000000C0DA ++:10B4B00000000004000000A00000000000000000E8 ++:10B4C000000000200000002000000000000000003C ++:10B4D000000000000000000000000000000000016B ++:10B4E000000000000000000100000000000000005B ++:10B4F0000000000000000010000000080010000024 ++:10B50000000000000020002000000020901000003B ++:10B510000000000000000021000000000008A01052 ++:10B52000000000000000002000000040002000009B ++:10B5300000800000008000000000001100000000FA ++:10B5400000080000008000000090000000000000E3 ++:10B5500000000000000000000000000000000000EB ++:10B5600000200000000000000010000000000000AB ++:10B5700000000000000885048002000003000000B5 ++:10B580004100000000001100000100000000100058 ++:10B59000000000000000000000000000100020007B ++:10B5A0000501000000A010000010000008C000000D ++:10B5B000040400000000030003000000110000006C ++:10B5C00082009184000080210000002000042120DE ++:10B5D000410400200000030010000582100000005C ++:10B5E00005A00000000000000000000000000000B6 ++:10B5F000000000000000C0802080108082008200D7 ++:10B600008800840084218209A00084201000841016 ++:10B6100085008400C00010001003C02100108200CB ++:10B620000100002000030000C041840082000821C6 ++:10B63000C021C1910000C000900000000809100066 ++:10B64000100003004000000010888200008000808D ++:10B65000C080008084808400100010001000000072 ++:10B6600000000000000000000000000000000000DA ++:10B670000000000000000000000005000040000085 ++:10B68000100002000900100240001000030000003A ++:10B690000200000000000000008802040400100006 ++:10B6A00000000282208202001040000010004101D0 ++:10B6B0000200090082840000090041001000A0017E ++:10B6C00000904104020421040000000841400000F1 ++:10B6D0000000040020000400000000000000000042 ++:10B6E000000000000000000000000000000000005A ++:10B6F0000000000000000000000000210009000020 ++:10B7000082000000000000000000000000000000B7 ++:10B710000000000000001000000000000000010018 ++:10B7200000000000000020000000000000000000F9 ++:10B730000004000000002000000000211021002172 ++:10B74000040400000080018000A0000000800000D0 ++:10B75000C000000001001100010000000000000016 ++:10B7600000000000000000000000000000000000D9 ++:10B770000000000000000000000010001001410067 ++:10B7800000001000008210000000210000000001F5 ++:10B790000000000000000000410000000000100058 ++:10B7A00005400000000000048001100010000500AA ++:10B7B0000000030002A084002100000009088201AB ++:10B7C00000000201210002088041418911000400AB ++:10B7D0000800030000014100030000000000030016 ++:10B7E0000500200000000001000100010000000031 ++:10B7F000000000000000000000000000032101081C ++:10B80000000082218421822084210021A008880058 ++:10B81000842000214000C00010038202402100006B ++:10B82000002110800000000500832040000000205F ++:10B830008400C000000800210508A00800C000091D ++:10B840000304844101041000018002400440000010 ++:10B8500001008420020000048200C00000030000F8 ++:10B860008200000001000000C004C004C004000009 ++:10B8700000000000000000000000000000000200C6 ++:10B8800000A0090040030390418210000310004013 ++:10B890000500414011402004000000000488000021 ++:10B8A0000000000402000040008211401040090026 ++:10B8B000000000000200020002C04100030000007E ++:10B8C000050004900040410021844184028440101E ++:10B8D000410041001040040003004100030010003B ++:10B8E00003000400102005000000002000200000DC ++:10B8F0000000000000400000000000000000000008 ++:10B9000000000000000001820000000000000000B4 ++:10B910000000000000000000000000000000200007 ++:10B92000000000000000000000000000000088117E ++:10B930000000000000000100000000000000000006 ++:10B9400000000000C00000800000100000000003A4 ++:10B95000010000000000820083000000C000000021 ++:10B960000000000000000000000000000000008057 ++:10B9700000000000000000000000000000000000C7 ++:10B98000000000030004000940090000000000005E ++:10B9900000000000800089000000200080000000FE ++:10B9A00040000000000040000000080300094003C0 ++:10B9B00000008003000900200000000380098900C6 ++:10B9C000000000004005400911110908030880200B ++:10B9D00000090004052000202141020200098041E5 ++:10B9E0002010410200000000000000004020002163 ++:10B9F000050320000000000000000000000004001B ++:10BA00000000000010010000000001000000000024 ++:10BA1000000000000000020002000000000004001E ++:10BA2000000001000000000001000000010102010F ++:10BA3000010000000401000100010000A00120013C ++:10BA4000210000000000010082000001010101014D ++:10BA50004000000000000001A0010100000000C043 ++:10BA600010A0010500C00000000000000000C1019E ++:10BA7000A000A00001000000000000000000000085 ++:10BA80000000000000000000009001000001000024 ++:10BA9000000000000000820084000888040000000C ++:10BAA0000100000001000000000000000100000093 ++:10BAB0000000012001010000000001000101000060 ++:10BAC00021C088000501000008002188032184C1ED ++:10BAD0000400020091000308020004000400C009F1 ++:10BAE000C001A0A00401C04100000100010001004C ++:10BAF00005008484210105410100000000040000CC ++:10BB000000000000000000080500050021090240B7 ++:10BB10000000000000000000000080008080800025 ++:10BB200003004100040005020000000000000900BD ++:10BB300000000000210003090000000021000309AB ++:10BB40000005C0008000032000008440A08085A183 ++:10BB50008589000900100500209000090000000000 ++:10BB600000A020030500052102C0000010002000F5 ++:10BB70002000A00085008221A0A00200000000009B ++:10BB800000000000000000000080402000050008C8 ++:10BB9000C1110000000000000000008000800000D3 ++:10BBA000808000880091000900840000008000006F ++:10BBB00000800000008020838083000000020920B4 ++:10BBC000000340C0008000090003000020080002BC ++:10BBD000008410C002C10020040302C0040400C19C ++:10BBE000002003040302802089C0C08500000000FB ++:10BBF0000000000040A000A12010A0800000000074 ++:10BC00000000000000000000000000000100000033 ++:10BC1000000190010000000000000000000200C0D0 ++:10BC200000208820000900410002004000A0000818 ++:10BC300000040202000000080004020500000001E8 ++:10BC400001A1000101210004000100050000012103 ++:10BC500000840004A1210004000100200005002050 ++:10BC6000000800C1011001A188C1A185894100001F ++:10BC7000000000000000018900C0018303040000EF ++:10BC800000000000000000000000000000000100B3 ++:10BC900001010001000000000000000000000000A1 ++:10BCA00000002000208800000000000100000000CB ++:10BCB00000400000000001880140000000000188F1 ++:10BCC0000190010100000388038808000220004061 ++:10BCD000912090009101414008010200C000200421 ++:10BCE000020188008400A04085028501410104888A ++:10BCF00000000003000100000103048200000300B3 ++:10BD00000000000000000000000000000000000033 ++:10BD100020002005092102000000000000000000B2 ++:10BD200000050000000080800000000300100000FB ++:10BD30000000002000000000038004000303000056 ++:10BD4000038004002020000083850400801180808F ++:10BD5000000008A0102040084080802080020000E1 ++:10BD60008000000380008000000089000540090277 ++:10BD7000418000000020001000002083A12100006D ++:10BD8000890000000000000000000000000000002A ++:10BD9000000000820000C20000000000000000005F ++:10BDA0000000000000810000000000000000000012 ++:10BDB000000000420008C100000000880022C1000D ++:10BDC000000000820000C100000000820013C100DA ++:10BDD0000000000000000081C20000000000000020 ++:10BDE000E00006000000001300000A6000000013DD ++:10BDF000C200060000000000C200000000000013A6 ++:10BE0000C20006000000000000000000000000006A ++:10BE100000004100FFFFFFFF3000000000000000B5 ++:10BE20000000000000000000000000000000000012 ++:10BE3000000000000000000000000000000000F012 ++:10BE400000005500000000F000000F00000000009E ++:10BE5000000000C300000E0E0000000003030000FD ++:10BE600000007FFFFFFF0000000000C33CFF0A3E10 ++:10BE7000A0BC0300FFFF000000000000000000283D ++:10BE800000000000000000000000000000000000B2 ++:10BE9000000000000000BEBEF0FF300030000000D7 ++:10BEA0000000000000000000000000000000000092 ++:10BEB0000000BEBC3CBC0000000000000000000010 ++:10BEC00000F000005500000000F000000F0000002E ++:10BED00000FF000000C30000000F0000010001008F ++:10BEE000000000007FFFFFFF00000000171717177A ++:10BEF000003C003C030003000000000000000000C4 ++:10BF0000000000000001000100000000000000002F ++:10BF10000008000000000000FF55787800040000D1 ++:10BF20000000000000000000000000000000000011 ++:10BF3000000000000FFF0FBF00000000555500007B ++:10BF40000F000000000000000F00000000000000D3 ++:10BF5000000000000F0F00000000FCFCFCF8FF3C9C ++:10BF6000FF3A000005015555550004A004000000EB ++:10BF70000000FFC33C00F0F0FF00000000000000E4 ++:10BF80005000000050000000800000000000000091 ++:10BF900000000000041000000000AA0078780000F3 ++:10BFA0000000000000000000000000000000000091 ++:10BFB0000000000000000FFF0F8F0000000055552B ++:10BFC00000000F000000FF0000000F000000FF0055 ++:10BFD0000000FF000000000000000000F0F0F0F89A ++:10BFE000FF00FF00000004005555550000A10100AE ++:10BFF00000000000FAD27850B4B4BE140000000073 ++:10C0000000000000000000000000800000000000B0 ++:10C0100000000000000000000000000000000A0412 ++:10C02000080000000000000000000000008600E0A2 ++:10C03000008000000086006000B00080008600756F ++:10C0400000B00803C0C7C07530B04903C0C7C07492 ++:10C0500030B04903C0C7C0F43080430300000186FC ++:10C06000006008B0000000865260A8B0008500861D ++:10C0700000210090000000860021089000000000D0 ++:10C08000001008000000008600F108800000000099 ++:10C0900000000000000000000000000000000000A0 ++:10C0A0000000000000000000000000000000F3F3AA ++:10C0B000F3F3A0A028A000000000FFFFFFFF000096 ++:10C0C0000000000008000000000000000000000068 ++:10C0D0000000FF00FF00A566665A00000000000097 ++:10C0E000DFFFFFFFFFFFFFFF00C382823CC3C33CB3 ++:10C0F000753030300505FFFFFFFF3C7800FFD5FFAE ++:10C100000000000000000000000000003C3C7C7CBF ++:10C11000000000800100000000000008080000008E ++:10C12000000000000000000000000000000000000F ++:10C13000F3F3F3F30000280000000000F0F3000325 ++:10C14000000000000000080000000000000000A047 ++:10C1500000000000FF00FF00A566665A00002020D6 ++:10C160000000FFFFFFFFBE5FFFFF00C380803CC3F6 ++:10C170003CC3307530301405FFFFFFFF000000FFA7 ++:10C1800015FF00000000000000003C003C000A0F0A ++:10C190005A5F0000002000000000000000000000C6 ++:10C1A000010000000000000000000000000000008E ++:10C1B000000000000000F000F60000000000000099 ++:10C1C000000000000000000000000000000000006F ++:10C1D000000000000000000000000000000000005F ++:10C1E000000000000000000003C3C3C30000000003 ++:10C1F0001000000000000000417D00FF810082006F ++:10C200000905000000000000000000000000000020 ++:10C210003CFF3FFF000000000000020000000000A3 ++:10C22000000000000000000000000000000000000E ++:10C2300000000000000000000000060000000000F8 ++:10C2400000000000000000000000000000000000EE ++:10C2500000000000000000000000000000000000DE ++:10C260000000500000000000000003C2C3C3000033 ++:10C27000000000000000000000004D4D0F0F820084 ++:10C28000820009050000000000000000000000001E ++:10C29000000000C30FCF40000000000000000000BD ++:10C2A0000000000000002100200011000000040038 ++:10C2B000200020000000000020000000000000001E ++:10C2C000000004000004200011000400200004000D ++:10C2D000200004000000009020000000000020006A ++:10C2E000000000000000000000000000000000004E ++:10C2F0000000210004000000000000000088000091 ++:10C30000000000000000000000000000000000002D ++:10C31000000000000000000000000000000000001D ++:10C3200000000000000000000000C000000000004D ++:10C330000000000000002000A0000000000000003D ++:10C3400000000000000000000000000000000000ED ++:10C35000000000000000000090000000200000002D ++:10C360000000000000009000000000000400000039 ++:10C37000900000000000000000000000000000002D ++:10C3800000000000000000000000000000000000AD ++:10C39000000000000000000000000000000000009D ++:10C3A00000000000000000000000FFFFFFFFFFFF93 ++:10C3B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10C3C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D ++:10C3D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D ++:10C3E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D ++:10C3F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D ++:10C40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10C41000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10C42000FFFFFFFFFFFFFFFFFFFFFFFF0054B41CF4 ++:10C430000C44007000C00A060000405100000000DB ++:10C4400000000000000000000000000000000000EC ++:10C450000010001000100010001000100003000079 ++:10C4600000000000000000000000000000000021AB ++:10C47000004100080011001100110011000000002F ++:10C4800000000000000000000000000000000000AC ++:10C49000000000000000000000000000000000009C ++:10C4A000000000000000000000000000000000008C ++:10C4B000000000000000000000000000000000007C ++:10C4C00000000000410005000000410041000000A4 ++:10C4D000050000004100000041000400410041004F ++:10C4E00010004100410000001000000009000000A1 ++:10C4F00010000000050000000000410041000000A5 ++:10C50000000000C005002100000000001100000034 ++:10C5100000000000000000000000000000004100DA ++:10C52000000000000000000000000000000000000B ++:10C5300000000000000000000000000000000000FB ++:10C5400000100000000000001000000010000000BB ++:10C55000000000001000100000000000C0000000FB ++:10C5600000000000000000000000000000000000CB ++:10C57000000000000000C0008200000088000000F1 ++:10C580000000100000000200C000C0008200C000D7 ++:10C59000C00000001000C0200000100000000000DB ++:10C5A000000000000000000000000000000010007B ++:10C5B00000000000840000000000000000000000F7 ++:10C5C00000000000000000004000000010004100DA ++:10C5D0002000020005002000200000000000009064 ++:10C5E0000000200000000000020000000000200009 ++:10C5F00020020000000000002000030000001000E6 ++:10C600004120000000000000210010000000000098 ++:10C61000000020000000009000900000009000004A ++:10C620000000000000000002000000000000000008 ++:10C6300005000000000000000000000000000000F5 ++:10C6400000000000000000000000000000000000EA ++:10C6500000000000000000000000000000000000DA ++:10C66000C00000000000C000000020000009000021 ++:10C67000000000000000200000000000000000009A ++:10C680004004400800000011000084000000C000C9 ++:10C690001000000002110000000000000000200453 ++:10C6A000000000000000000000000000000000008A ++:10C6B000000000000000000000000000000000007A ++:10C6C000000000000000000000000000000000006A ++:10C6D000000000000000000000000000000000005A ++:10C6E000000000000000000000000000000000004A ++:10C6F0000000000000000000100000000500000025 ++:10C700000000000000000000000000001000000019 ++:10C710000002000000000000000000000000000017 ++:10C720000000000000000000000000000000000009 ++:10C7300000000000000000000000000000000000F9 ++:10C7400000000000000000000000C0001000C00059 ++:10C750000000000000210000000010100000000098 ++:10C760000000100000001000100000000008000091 ++:10C7700010000000000000000000000000000000A9 ++:10C7800000200000820000210000100000000000D6 ++:10C790008403080010000800080084000000C000A6 ++:10C7A00002000000000000088400000000000000FB ++:10C7B0000000000000000000000000000000000079 ++:10C7C000000000000000C000000011000000000098 ++:10C7D0000000000040000000000000000000000811 ++:10C7E0000000000000000000000000000000000049 ++:10C7F0000000000000000000200000000000000019 ++:10C800000000000000002000040000000000000004 ++:10C8100000000040100000000000000000000000C8 ++:10C8200000004100000000000000000000000000C7 ++:10C8300002000000000010000000000000000000E6 ++:10C8400000000000000000000000000000000000E8 ++:10C8500000000000000000000000000010000000C8 ++:10C860000002000000000000000000001000200096 ++:10C87000000000000000100088000000C000040458 ++:10C880000000044000030003000300030000000058 ++:10C8900000000000200000000000000090000000E8 ++:10C8A0000000000004000000000000000040002024 ++:10C8B0000000000000000000000000000000000078 ++:10C8C0000000000000000000000000000000FFFF6A ++:10C8D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:10C8E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 ++:10C8F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48 ++:10C90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 ++:10C91000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 ++:10C92000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17 ++:10C93000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 ++:10C94000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 ++:10C9500000500F080C4400F000000A0600006018A8 ++:10C96000000004000000410000000000000000087A ++:10C9700004000000000000000000000000000000B3 ++:10C98000000000000000034000008020000000A024 ++:10C99000040000000000800008000000000000000B ++:10C9A00000400000000180010405000000000000BC ++:10C9B0000000000100000001000000000000000075 ++:10C9C0000020000000000000000000000000000047 ++:10C9D0000000000000000000000000000000000057 ++:10C9E0000000000000000000000000000000000047 ++:10C9F0000000000000000000000000000000000037 ++:10CA0000000000000000A000008000000480000082 ++:10CA10000000000000000000020001000000000013 ++:10CA2000000000000000000202400084000000003E ++:10CA300000000000002000000010000000000000C6 ++:10CA400000000000000000000000000000000000E6 ++:10CA500000000000000000000000000000000000D6 ++:10CA600000000000000000000000000000000000C6 ++:10CA700000000008000000000002000000000000AC ++:10CA800000010000000000000000000000000000A5 ++:10CA90000000000000000000000000000000000096 ++:10CAA0000000000000800000000000000000000006 ++:10CAB0000000000000000000000000000000000076 ++:10CAC0000000000000000000000000000000000066 ++:10CAD0000000000000000000000000000000000056 ++:10CAE0000000000000000000000000000000000046 ++:10CAF0000000000000000000001000000010000016 ++:10CB000000000020001000000000000000000000F5 ++:10CB10000000000000000000000800000008000005 ++:10CB20000000000000030000000000000000000002 ++:10CB300000000000000000000000000000000000F5 ++:10CB400000000000000000000000000000000000E5 ++:10CB500000000000000000000000000000000000D5 ++:10CB60000000000000000000210000C0000000A044 ++:10CB70000000000010900004000000000000000011 ++:10CB800000000000000000000000000100000000A4 ++:10CB90000000000000000000000000000200000093 ++:10CBA00000000800800080400000000000A003009A ++:10CBB000000800002100000021000000000000002B ++:10CBC00009001088000000000000000000020000C2 ++:10CBD0000000000000000000000000000000000055 ++:10CBE0000000000000000000000000000000000045 ++:10CBF00000000000000000000080000000000000B5 ++:10CC000000000000000000000000000000400000E4 ++:10CC10000000000000000000000000000000010013 ++:10CC200000000000010002410200000000000000BE ++:10CC300000000000000000000000000000000000F4 ++:10CC40000000000000000000000000000000008064 ++:10CC500000000000000000000000000000000000D4 ++:10CC60000000000000000000000000000000410083 ++:10CC70001000000080009000000010000000000084 ++:10CC8000000009000000000000001001000000008A ++:10CC90000000000000000000000000000000040090 ++:10CCA0000000000000000200000000000000000082 ++:10CCB00000000000800000000000000000000000F4 ++:10CCC0000000090008000800000000000300000048 ++:10CCD0000000000010000000000000000000000044 ++:10CCE00000000000000000000000000000008400C0 ++:10CCF00000000000000004001100C000000004005B ++:10CD00000000000090000000000000000020000073 ++:10CD10000000000000000000000000000000000013 ++:10CD20000000000000030000000000000000000000 ++:10CD300000000000000020000000000000000000D3 ++:10CD400000000200040001000109000000000000D2 ++:10CD500000000009000000000000000000000000CA ++:10CD600000000000000000000000000000000000C3 ++:10CD700000004100100000C000040000000400009A ++:10CD8000000000002100040000000300000000007B ++:10CD90000000100000001000000000000000004132 ++:10CDA0000000000000000000000000000001020080 ++:10CDB000000000004108000000000000A0A00004E6 ++:10CDC000000010000400000002A0050000000000A8 ++:10CDD0000488004000000000000200000000000085 ++:10CDE0000000000000000000000000000000000043 ++:10CDF0000000000000000000000000800000008033 ++:10CE00000000000000000000010000000000000021 ++:10CE10000000000000000000000000000000000012 ++:10CE2000008400000000000000000000000000403E ++:10CE300001000040000000000000000000001100A0 ++:10CE40000080000000000100000001000000000060 ++:10CE500000000100008000000000008000000000D1 ++:10CE600000000000000000000000000000000000C2 ++:10CE70000000000010004100100041A0030041002C ++:10CE80004100000800000000050000000000000054 ++:10CE900000208000000000000400040000000000EA ++:10CEA000000400000002000000000000000002007A ++:10CEB00000000004000000000000000080000001ED ++:10CEC000C0A080408004A0200020000000A000003E ++:10CED00008C0000000020002000000020000000084 ++:10CEE00000000000410000000000000041000000C0 ++:10CEF0000000000000000000000000000000000032 ++:10CF000000002000840084000000C0000000000039 ++:10CF100082000080200000000000000001000000EE ++:10CF20000000000000000000000000000000000001 ++:10CF30000000000040000000000000000040204011 ++:10CF4000002005000800088005C000000020004007 ++:10CF500000000100000000000080000000800000D0 ++:10CF600000000000000000000000000000000000C1 ++:10CF700000000000000000000000000000000000B1 ++:10CF80008202000221A000820000000002000000D6 ++:10CF900000000000090000000000800041000000C7 ++:10CFA000000080004000000080000000050010002C ++:10CFB00000008000030000000000000000000000EE ++:10CFC000000000C0108280C10041008310008580F5 ++:10CFD00000808083000000800000008300A000002B ++:10CFE0000000000000000000000000000000000041 ++:10CFF0000000000000000000000000000000000031 ++:10D00000000009C002020311000800000200A00095 ++:10D01000000000000200A0000000000082000000EC ++:10D0200000000000040001000000900084000100E6 ++:10D0300001000000C000000000000000000000002F ++:10D04000000090000083012090100091008389A0CF ++:10D05000C090008488838800889000000009000345 ++:10D06000000200C0000000000000000000000000FE ++:10D0700000000000000000000000000000000000B0 ++:10D08000000000008801A08405880801000000005D ++:10D090000000000008008400C0000088000020009C ++:10D0A0004000048200000000000000A004002000F6 ++:10D0B0000000840040002000020082000000820086 ++:10D0C000A000049089008900A000200020009000AA ++:10D0D0000000A1008385000100849100830000000E ++:10D0E000000000000100000000000000000000003F ++:10D0F0000000000000A000000000000000A00000F0 ++:10D100000000000000000940020020918909000091 ++:10D110000000000000008000800000000082000588 ++:10D12000800080008080000000000000002180005E ++:10D1300080000000800000000000800080210000CE ++:10D140000900110080000300100980118000801088 ++:10D150008000000089008385001100000900830021 ++:10D1600000000000000003000000000000000000BC ++:10D1700004000000000000000000000000000000AB ++:10D18000000000000000000020090011000089914B ++:10D19000000000000000000000000080008000008F ++:10D1A000008000004180000000000080210000801D ++:10D1B0000082002103A000830080000005000080A1 ++:10D1C0000000000000000000000021000000C1007D ++:10D1D00003008091000000004083020000099100DC ++:10D1E0008083000080400000000300000000000079 ++:10D1F000000000000000000000000000000000002F ++:10D200000000000000000000000001C000A082003B ++:10D210008809000400A0009000000004000800102D ++:10D2200000C000040084008402C00090004000A000 ++:10D230000040000300400004000500020082018855 ++:10D240000882000000000000000000004000000014 ++:10D250008500010010890008008201410190C0C1D1 ++:10D26000A10090830000080182000001000000007E ++:10D2700000000000000000000000000000000000AE ++:10D2800000000000000000000000000088C105034D ++:10D29000A00105000000000000000000C000080020 ++:10D2A00000000004888882008400C0040000880018 ++:10D2B000020040000000000000000090000100009B ++:10D2C00000000002000000000001000000208301B7 ++:10D2D0002010840090C083204090010090C0010184 ++:10D2E000C090000000C001400000000000000000ED ++:10D2F000000000000000000000000000000000002E ++:10D30000000000000000000000000000000091404C ++:10D3100009200021110000000000000000000002B0 ++:10D32000800000000000002000008000008000005D ++:10D330008000000000000003000000000000000367 ++:10D340000000000000800000000200110011000039 ++:10D350008809808091000000830000801100808097 ++:10D360000303008000000080038000000002020030 ++:10D3700000000000000000000000000000000000AD ++:10D38000000000000000000000000000000000009D ++:10D3900000000013C20000000000001300000000A5 ++:10D3A00000000013C200000000000013000042480B ++:10D3B0000000001344000000000000000000000016 ++:10D3C0000000000000002100000000000000E0005C ++:10D3D000000000000207E000005000000081810012 ++:10D3E00000000000008100000600000000000000B6 ++:10D3F000000000000000000000000000000000002D ++:10D40000000000000000000000000000000000001C ++:10D410000000BD817E4266663333000000000000DC ++:10D4200000000000000000000000000000000000FC ++:10D430000000000000000000000000000000F333C6 ++:10D44000CC0F000000000000000000000000000001 ++:10D4500000000000FFFF0F0F000000000F0F000092 ++:10D460003C3C0000FFFF00000F0F00003C3C0000B0 ++:10D470000F0F00000000000000000000000000008E ++:10D48000000000000000000000000000000000009C ++:10D4900000000000FFC33C0066663333000000005C ++:10D4A000000000000000000000000000000000007C ++:10D4B000000000000000000000000000000000006C ++:10D4C0000F0F0FF00000000000000000000000003F ++:10D4D000000000000000FFFF0F0F000000000F0F12 ++:10D4E00000003C3C0000000000000F0F00003C3C2E ++:10D4F00000000F0F0000000000000000000000000E ++:10D500000000000000000000000000000000FFFF1D ++:10D51000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10D52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10D53000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:10D54000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB ++:10D55000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB ++:10D56000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB ++:10D57000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:10D58000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB ++:10D5900000085EBC0C4400F000180A06000090E78A ++:10D5A0000000000000000000FBFFF9FFFFFFFBFF91 ++:10D5B000000000000000000000000000000000006B ++:10D5C000000000000000000000000000000000005B ++:10D5D000000000000000000000000000000000004B ++:10D5E000000000000000FFFFC3C3BEFE41013C3C41 ++:10D5F0003C3C00006666000000FF0000FFFF0000EA ++:10D6000000FF000000FFFFFF00000000000000001E ++:10D61000000000000000000000000000000000000A ++:10D6200000000000000000000000FFFFFDFF000000 ++:10D6300002000000000000000000000000000000E8 ++:10D6400000000000000000000000000000000000DA ++:10D6500000000000000000000000000000000000CA ++:10D660000000000000000000060600006066FF9950 ++:10D670003C3C3C3C00006666000000FF00000000EF ++:10D68000000000FF000000FFFFFFFFFF00000000A0 ++:10D69000000000000000000000000000000000008A ++:10D6A0000000000000000000000000000086029161 ++:10D6B00008800000008600E100900000008600E184 ++:10D6C000008000050086006100B000000086002098 ++:10D6D00008B000050086006000B900000086006008 ++:10D6E00000B0000000000086006000B00010A1A0A3 ++:10D6F0005080A8B00845A249018100A449400245D4 ++:10D7000001810004494002C7016000B441400000AB ++:10D710000000000000000000000009000000000000 ++:10D7200000000800000000000000000000000008E9 ++:10D7300000000000000000000000002000200000A9 ++:10D7400000003D3D3C3C03050F0FF700F200C0C058 ++:10D75000C0C0D2825000000000004DBE4DB200009B ++:10D760000000005500100000000000000000000054 ++:10D7700082800080000000003C3CFF0000000000B0 ++:10D78000AA00AA000F0F0C0C00000000000000000F ++:10D790000000000000000000000000200000010068 ++:10D7A0000000000000000100000000000000000078 ++:10D7B000000800000000010100000000000000005F ++:10D7C000FF0000000505AAFF00050F0FF700F70096 ++:10D7D000C300C30000000000000000007D8E7D82B9 ++:10D7E0000000000000000000000000000000000039 ++:10D7F0000000828000800000000000000000002087 ++:10D800000028AA00AA0000000C0C00000000000084 ++:10D8100000000000000000000000004000000000C8 ++:10D8200002000040000000000000000000000000B6 ++:10D8300000000000000000000000000000000000E8 ++:10D8400000000000000005FF05FF000000000000D0 ++:10D8500000000000000000000000000000002B2B72 ++:10D86000E8E8000000000000FFEB000000000000FE ++:10D87000FA92FA00FF3F3F3FFFFFFFFF3C003030CE ++:10D88000003C0055A0A0AAAA00FF5555FFFFFDFCD3 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000000000000078 ++:10D8B000000000000030000000000C00000000002C ++:10D8C00000000000000000003D3D3D3D0000000064 ++:10D8D0000000050000000000000000000000000043 ++:10D8E0001717D4D4000000000C09FFEB0000000063 ++:10D8F0000000156D15FFFFFF3FFF7FFFFFFF3C009E ++:10D900003030003C0055A0A0000000000000FFFFE8 ++:10D91000FFFF000000000000000000000000000009 ++:10D9200000000000000000000000000000000400F3 ++:10D9300000000000040000000000000000000000E3 ++:10D940000000000000004000200020002000040033 ++:10D9500000000000040011000000110000010000A0 ++:10D96000000000000000800100018001800000C074 ++:10D97000040000000000040004000000000000009B ++:10D980000000000000000000000400000000000093 ++:10D990000000000000000000000000000000000087 ++:10D9A0000000000000000000000000000000000077 ++:10D9B0000000000000000000000000000000000067 ++:10D9C0000000000000000000000001000100010054 ++:10D9D000000000000000000000000000000000083F ++:10D9E00000000000000000004002000220042000AF ++:10D9F0000000000000000000000000000000000027 ++:10DA00000000000000000000000000800000000096 ++:10DA10000000000000000000000000000000000006 ++:10DA200000000000000000000000000000000000F6 ++:10DA300000000000000000000000000000000000E6 ++:10DA400000000000000000000000000000000000D6 ++:10DA500000000000000000000000000000000000C6 ++:10DA600000000000000000000000000000000000B6 ++:10DA7000000000C0000000000000000000000000E6 ++:10DA80000000000000000000000000000000000096 ++:10DA90000000000000000000000000000000000086 ++:10DAA0000000000000000000000000010000000075 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000001000000000000000100000000036 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000200000000000000100000000024 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000000000000000000000000000010000005 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000100000E5 ++:10DB30000000000000000000000000000084000061 ++:10DB40000000800000C0800000040002008200008D ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB70004000000000000000000080002000800045 ++:10DB8000000000000000000000020000000404206B ++:10DB90000000000000000000000000000000000085 ++:10DBA0000000000000000000000000000000000075 ++:10DBB000000000000000000000000000C0000000A5 ++:10DBC000C000000040000000040000800080000051 ++:10DBD00084000000000010000000000000000000B1 ++:10DBE0000000000000000000000000000000000035 ++:10DBF0000000010000000000000000002000010003 ++:10DC000020050000000000000000008000000080EF ++:10DC10000180000000030000000000000000000080 ++:10DC200000001000000000000000000000000000E4 ++:10DC3000000000000000000000000500000041009E ++:10DC40000000200009002000200005000000002046 ++:10DC50000000900000001000000000000000000024 ++:10DC60000000000000000000002000000000000094 ++:10DC70000000000010001000100000000000000074 ++:10DC8000000000002000000000000004110000005F ++:10DC9000050000000000000000000000000000007F ++:10DCA0004100000000000000000000000000000033 ++:10DCB0000000000000000000000000000000000064 ++:10DCC0000000000001000000010001000000000051 ++:10DCD00000800000200000000000000000000000A4 ++:10DCE00000000000000000000000008000000000B4 ++:10DCF0000000000000000000000000000000000024 ++:10DD00000000000000000100000200000080000090 ++:10DD10000000000000000000000000000000000003 ++:10DD200000000000000000000000000000000000F3 ++:10DD300000000000000000000000000000000000E3 ++:10DD4000000000004100400040010001C00003004D ++:10DD5000040003040300000800000000800100002C ++:10DD600000000900000000000000000000000000AA ++:10DD70000000000000001000000000000000000093 ++:10DD8000000000010000830000004101000584A1A3 ++:10DD9000000000010000040100000000000000007D ++:10DDA0000000000000000000000000000000000073 ++:10DDB0000000000000000000000000000000000063 ++:10DDC000000000000000000001000104C004212147 ++:10DDD00000000100008000008480820000004040BC ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000100000042100000004008455 ++:10DE100005200000000800000140C00000000000D4 ++:10DE20000000C00000000000100000000000000022 ++:10DE300000000000000000000000000000000000E2 ++:10DE40000000020041840084050020002000200022 ++:10DE50002000100005000000050400000000000282 ++:10DE60000040000000000000000000000000000072 ++:10DE70008000000000000000000010000000000012 ++:10DE80000000000000000000090000000000000089 ++:10DE9000109000200002000004040004002000A0F4 ++:10DEA0000000000010000020000000000000000042 ++:10DEB0000000000000000000000000000000000062 ++:10DEC0000000000000000000000000000100010050 ++:10DED00001000100010000000000008000000000BF ++:10DEE0000080008000000000000000000000000032 ++:10DEF0000000100000000000000000000000000012 ++:10DF00000000000000000000000000000000000011 ++:10DF10000000000000800080000000800080000001 ++:10DF2000000000000000000000000000000084006D ++:10DF300000000000000000000000000000000000E1 ++:10DF400000000000000000000000000000000000D1 ++:10DF5000000000400000400509C19140401000054C ++:10DF6000004002050040000000000000000000002A ++:10DF700000008000200000000000000000001100F0 ++:10DF80000000000009000000031100090010030058 ++:10DF900008038009050541411100800021000905A1 ++:10DFA0000000000000000000000000000000000071 ++:10DFB0000000000000000000000000000000000061 ++:10DFC0000000000000000000000000000000000051 ++:10DFD0000000000000010000C10301044101012113 ++:10DFE0000001A0010000000100000000000000008E ++:10DFF000000000008400000000000000000000009D ++:10E000000100000000000100000001008801000183 ++:10E0100000000101040100000000010020000000D8 ++:10E0200001000000000000000000000000000000EF ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E050000000000000010000000102000540030173 ++:10E0600005C00000000000000000000000000000EB ++:10E070000000010101008988829100000000000079 ++:10E08000000000000000010001010000000000008D ++:10E090000100010100000008010101010000000071 ++:10E0A00000C001000000004000C0000000000000AF ++:10E0B000000000000000000000000000010000005F ++:10E0C000000200000000000000000000000000004E ++:10E0D0000000000000000003000000204102A080BA ++:10E0E0002002A080000000020002004100000000A9 ++:10E0F00000000000110241008980A1910000000091 ++:10E1000000000000000000002100030900000000E2 ++:10E1100003002100030905000080212003090000FD ++:10E120000000000009000000008000410000000025 ++:10E1300000000000000000000000000000000200DD ++:10E1400000000000000000000000000000000000CF ++:10E15000000000000000000000020200000000209B ++:10E1600080C10910C0898500000021000300000063 ++:10E170000000000000000002001121008083000068 ++:10E1800000000000000000020011210980030000CF ++:10E190000300000209100083000000820205400312 ++:10E1A00000000080000980830000000000000000E3 ++:10E1B000000000000000000000000000000000005F ++:10E1C000000000000000000000000000000000004F ++:10E1D0000000000000000000A0000000010000009E ++:10E1E0000003C00403030504400200C000C001A0F6 ++:10E1F0000000000000000000000100000100208974 ++:10E2000000000000000000000001000101012001E9 ++:10E2100000000140000101410083009000030090D4 ++:10E220000391002000020083900300000000000022 ++:10E2300000000000000000000000000000000000DE ++:10E2400000000000000000000000000000000000CE ++:10E25000000000000000000000000040010000007D ++:10E26000000005A1030405010100010001000000F8 ++:10E270000000000000000000000082918489C001BD ++:10E28000888800000000000000000000000100017C ++:10E290000000000000A0008400010000018800C10F ++:10E2A0000101000000900000000000000088010053 ++:10E2B000010000000000000000000000000000005D ++:10E2C000000000000000000000000000000000004E ++:10E2D000000000000000000000000000008020009E ++:10E2E0000002000083020841C00209000300200070 ++:10E2F0000200020000000000000000008091008980 ++:10E30000800280800000000000000000000000117A ++:10E310000021000000000000000500100000038044 ++:10E3200005410220000000000000000000002180E4 ++:10E3300004002000000000000000000000000000B9 ++:10E3400000000000000000000000000000000000CD ++:10E3500000000000000000000000000000000000BD ++:10E360000000C2000A0000000013C200000000000C ++:10E370000000E00000600000000000000000060057 ++:10E380000007000000000000000000000000000086 ++:10E39000000001000000000000000007E0000A008B ++:10E3A00000000007E000000000880004E00000001A ++:10E3B00000880000C2000000000000000000000013 ++:10E3C000000000000000000000000000000000004D ++:10E3D000000000000000000000000000000000003D ++:10E3E00000FF00000F0F00003C3C0000E0F0EFFFDA ++:10E3F000FFFAFFFB0000000000000000000000002A ++:10E4000000000000FFFF000000000000000000000E ++:10E41000000000007D7E3FFC0000000000000505BC ++:10E42000AFFA0505AFFA555555AA00000000AAAA93 ++:10E4300055AA00FF00FF00000000000000000000DF ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E46000000000FF00000F0F0000AA55050010007B ++:10E470001F0FFFFAFFFB000000000000000000007B ++:10E48000000000000000F0F03C3C00000000000034 ++:10E490000000000000007D7D3CFF00000000000047 ++:10E4A000050505500505055000000F0F0000000090 ++:10E4B000555500FF50500000000000000000000013 ++:10E4C000000000000000000000000000000000004C ++:10E4D000000000000000000000000000000000003C ++:10E4E000000000000000F0F00000FFFFAF3FAA3086 ++:10E4F0002D7D7D7DF0F0D0F00000000000000000D8 ++:10E50000000000000000000080000000000000008B ++:10E510000000000000000000FFFFFFFF00000FF000 ++:10E520000FF050FAAA008EB23C00C33CFF00C3C3F8 ++:10E53000C3C30000FFFF0000000000000000000057 ++:10E5400000000000000000000000000000000000CB ++:10E5500000000000000000000000000000000000BB ++:10E560000000000000000000F0F000000000AF3FDD ++:10E57000AA3078282828F0F0F0F000000000000011 ++:10E58000000000000000000000000000000000008B ++:10E590000000000000000000000055AA55550000D2 ++:10E5A000FFFF0000FA50AA008EB23C00AAAA0000A9 ++:10E5B000C3C3C3C30000FFFF000000000000000051 ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E0000000000000000000A8005400A002001578 ++:10E5F0000886009108800000A5865260A0B0000542 ++:10E600000000000000000000000200A003890000DC ++:10E6100000000000000000000000000000020010E8 ++:10E6200000000086C07130104903C0C7C07130902F ++:10E6300041030086026C00B20400000000040800E0 ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E6600000000000000000000000000000000000AA ++:10E670000000000000A00000100000000000FFFFEC ++:10E68000FFFB0000000000000000D8F0D7FFFFFFF4 ++:10E69000000000000000000000000000000000007A ++:10E6A0000000000000000000C3003C00000000006B ++:10E6B000000088440000000000000000000000008E ++:10E6C000000000000000000000000000000000004A ++:10E6D00000000000000000800100000000000000B9 ++:10E6E000000000000000000000000000000000002A ++:10E6F000000000000000000000001000000000000A ++:10E70000FFFFFFFF0000000000000000F0F0280005 ++:10E71000FFFF0000000000000000000000000000FB ++:10E7200000000000000000000000000000000000E9 ++:10E7300000008844000000000000004000000000CD ++:10E7400000000000000000000000000000000000C9 ++:10E750000000000000000000002000000000000099 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000003000000069 ++:10E780000000000000000000000000000000000089 ++:10E790000000AAAA55AA0000000000000000000026 ++:10E7A0000000000000000000000000000000000069 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000020037 ++:10E7E0000000000000000000000000000000000029 ++:10E7F00000000000000000000028000000000000F1 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000555500FF00000000000000004F ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000000000000000000000000000000D8 ++:10E8400000000000000000000000000000000000C8 ++:10E850000000000000000000000040000000000078 ++:10E8600000000000000000000000000000000000A8 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000021000000000067 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D00000000000000000000000004000000000F8 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000000000000000000018 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000000000000000000000000000000D7 ++:10E9400000000000000000000000000000000000C7 ++:10E950000000000000000000000000000080000037 ++:10E9600000000000000000000000000000000004A3 ++:10E97000AB220C85004004000400040004000400E5 ++:10E98000040004000400CC26000000000000000089 ++:10E990000C44008800F0CC260000000000000000BD ++:10E9A0000C44008800C00C8500800A06000080200E ++:10E9B000000000000008000000000000000000004F ++:10E9C0000000000000000000000000000000000047 ++:10E9D0000000000000000000000000000000000037 ++:10E9E0000000000000000000000000000000000027 ++:10E9F0000000000000000000000000000000000017 ++:10EA00000000000000000000000000000000000006 ++:10EA100000000000000000000000000000000000F6 ++:10EA200000000000000000000000000000000000E6 ++:10EA300000000000000000000000000000000000D6 ++:10EA400000000000000000000000000000000000C6 ++:10EA500000000000000000000000000000000000B6 ++:10EA600000000000000000000000000000000000A6 ++:10EA70000000000000000000000000000000000096 ++:10EA80000000020000000000000000000000000084 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000000000000000056 ++:10EAC000C000000000000000000000000000000086 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB3000000000000000FFFFFFFFFFFFFFFFFFFFDF ++:10EB4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5 ++:10EB5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5 ++:10EB6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 ++:10EB7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5 ++:10EB8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:10EB9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10EBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10EBB000FFFFFFFFFFFFFFFF00DCBD450C440088A7 ++:10EBC00000900A06000000C30000000000000000E2 ++:10EBD0000000000000000000000000000200000033 ++:10EBE0000000000000000000000000000021000004 ++:10EBF00000000000002000000000000000000000F5 ++:10EC00000000000000000000000000000003000001 ++:10EC10000000840000000000000000000000000070 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000090000000000000000004 ++:10EC80000000000000000000000000001000000074 ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000000000000000000000000000000064 ++:10ECB0000000000000000000000000000000000054 ++:10ECC000000000000000000000000000FFFFFFFF48 ++:10ECD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:10ECE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10ECF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 ++:10ED0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10ED1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:10ED2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3 ++:10ED3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3 ++:10ED4000FFFFFFFFFFFFFFFFFFFFFFFFFFFF008C45 ++:10ED50002A4E0C44008800700A06000000410000A2 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA0000000000000000000000000000000000063 ++:10EDB0000000000000000000000000000000000053 ++:10EDC000000000000000000000000000000000043F ++:10EDD0000000000000000000000000000000000033 ++:10EDE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:10EDF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10EE0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 ++:10EE1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:10EE2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:10EE3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10EE4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10EE5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:10EE6000FFFF00F422F60C44008800680A06000048 ++:10EE700000C30000000000000000000000000000CF ++:10EE80000000000000000000000000000000000082 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000010000012 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000000000000000000000000000000001 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF6000000000000002000000000000000000009F ++:10EF7000000000000000FFFFFFFFFFFFFFFFFFFF9B ++:10EF8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:10EF9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 ++:10EFA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 ++:10EFB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 ++:10EFC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 ++:10EFD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 ++:10EFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 ++:10EFF000FFFFFFFFFFFFFFFF00EC6D7E0C4400886A ++:10F0000000D80A06000040D3000000000000000005 ++:10F0100000000000000000000000000000000000F0 ++:10F0200000000000000000000000000000000000E0 ++:10F0300000000000000000000000000000000000D0 ++:10F0400000000000000000000000000000000000C0 ++:10F0500000000000000000000000000000000000B0 ++:10F0600000000000000000000000000000000000A0 ++:10F07000000000000000000001000000000000008F ++:10F080000000000000000000000000000000000080 ++:10F090000000000000000000000000000000000070 ++:10F0A0000000000000000000000000000000000060 ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D0000000000000000000000000000000000030 ++:10F0E0000000000000000000000000000000000020 ++:10F0F00000000000004000000000000000000000D0 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000000AF ++:10F16000000000000000000000000000000000009F ++:10F170000000000000000000001008000000000077 ++:10F180000000000000000000000000000000FFFF81 ++:10F19000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10F1A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F ++:10F1B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F ++:10F1C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F ++:10F1D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:10F1E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F ++:10F1F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F ++:10F20000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E ++:10F21000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE ++:10F22000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE ++:10F23000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE ++:10F24000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE ++:10F25000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE ++:10F26000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE ++:10F27000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10F28000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10F29000FFFF000000000000000000000000000070 ++:10F2A000000000000000000000000000000000005E ++:10F2B000000000000000000000000000000000004E ++:10F2C000000000000000000000000000000000003E ++:10F2D0000000000008000092400000000000000054 ++:10F2E000000000000000000000000000000000001E ++:10F2F000000000000000000000000000000000000E ++:10F3000000000000000000000000000000000000FD ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000000000000CD ++:10F3400000000000000000000000000000000000BD ++:10F350000000000000000440000100000000000068 ++:10F36000000000000000000000000000000000009D ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000000000004D ++:10F3C000000000000000000000000000000000003D ++:10F3D00000000000000000001020000410200000C9 ++:10F3E000000000000000000000000000000000001D ++:10F3F000000000000000000000000000000000000D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F440000000000000000000000000000000A1001B ++:10F4500000850000000000000000000000000081A6 ++:10F460008181A181A18581000000000000000000D1 ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C0000000000000000000000003000000000039 ++:10F4D000000000000000000000000000000000002C ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000020000000000E9 ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000000000000000000000000000007B ++:10F590000000000000000000000000000000003C2F ++:10F5A0003FA90C850040040004000400040004008E ++:10F5B000040004000400CC2600000000000000004D ++:10F5C0000C4480800090CC26000000000000000069 ++:10F5D0000C4480800030CC260000000000000000B9 ++:10F5E0000C4480800008CC260000000000000000D1 ++:10F5F0000C4480800088CC26000000000000000041 ++:10F600000C4480800048CC26000000000000000070 ++:10F610000C44808000C8CC260000000000000000E0 ++:10F620000C44808000A8CC260000000000000000F0 ++:10F630000C4480800098CC260000000000000000F0 ++:10F640000C4480800058CC26000000000000000020 ++:10F650000C44804000E8CC260000000000000000C0 ++:10F660000C44802000A8CC26000000000000000010 ++:10F670000C4480200068CC26000000000000000040 ++:10F680000C4480A000E8CC26000000000000000030 ++:10F690000C4480E00030CC26000000000000000098 ++:10F6A0000C4480E000B0CC26000000000000000008 ++:10F6B0000C4480E00070CC26000000000000000038 ++:10F6C0000C4480E000F0CC260000000000000000A8 ++:10F6D0000C4480E00008CC26000000000000000080 ++:10F6E0000C4480E00088CC260000000000000000F0 ++:10F6F0000C4480E00048CC26000000000000000020 ++:10F700000C4480E000C8CC2600000000000000008F ++:10F710000C4480E00028CC2600000000000000001F ++:10F720000C4480E000A8CC2600000000000000008F ++:10F730000C4480E00068CC260000000000000000BF ++:10F740000C4480E000E8CC2600000000000000002F ++:10F750000C44801000E8CC260000000000000000EF ++:10F760000C4480900078CC260000000000000000CF ++:10F770000C44807000A8CC260000000000000000AF ++:10F780000C4480700068CC260000000000000000DF ++:10F790000C4480F000E8CC260000000000000000CF ++:10F7A0000C4480880040CC260000000000000000CF ++:10F7B0000C44808800E0CC2600000000000000001F ++:10F7C0000C44808800D0CC2600000000000000001F ++:10F7D0000C4480880030CC260000000000000000AF ++:10F7E0000C44808800B0CC2600000000000000001F ++:10F7F0000C4480880008CC260000000000000000B7 ++:10F800000C4480880088CC26000000000000000026 ++:10F810000C4480880048CC26000000000000000056 ++:10F820000C44808800C8CC260000000000000000C6 ++:10F830000C4480880028CC26000000000000000056 ++:10F840000C44808800A8CC260000000000000000C6 ++:10F850000C4480880068CC260000000000000000F6 ++:10F860000C4480880018CC26000000000000000036 ++:10F870000C4480880098CC260000000000000000A6 ++:10F880000C4480880058CC260000000000000000D6 ++:10F890000C44808000400C8500800A060000401067 ++:10F8A00000000000000080000000000000000200D6 ++:10F8B00000000000008800000000000000000000C0 ++:10F8C0000000000000000000000000000000000038 ++:10F8D0000000000000000000000000000000000028 ++:10F8E00000004100000000000000000000000000D7 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000100000000000E7 ++:10F9100008000000000000000010000000000000CF ++:10F9200000000010000000000210000000000008AD ++:10F930000110001002000000001000000000000094 ++:10F940000010002100000000001000000000000076 ++:10F950000010001000000000002100000010000056 ++:10F960000021000000100000000000100000000056 ++:10F970000000001000210000000000000000001046 ++:10F98000000000210040A000000000410000000035 ++:10F990000000004100000000000000800000004066 ++:10F9A0000000001000000000000000000000000047 ++:10F9B000000000000000000000C000000000000087 ++:10F9C0000000000000000000000000000000000037 ++:10F9D0000000000000C00000000000000000000067 ++:10F9E00000000000000000000000000000A0000077 ++:10F9F00000000000004000000000000000000000C7 ++:10FA000000000000001000C0000000000000000026 ++:10FA10000000000000A00000000000000000000046 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000000000000000000C6 ++:10FA400000000000000000000000000000000000B6 ++:10FA500000000000000000000000000000000000A6 ++:10FA60000000000000000000000000000000000096 ++:10FA70000000000000000000000000000000000086 ++:10FA800000008800000000000000000000000000EE ++:10FA90000000000000000000000000000000000066 ++:10FAA0000000000000000000000000000000000056 ++:10FAB0000000000000000000000000000000000046 ++:10FAC0000000000000000000000000000000000036 ++:10FAD0000000000000000000000000000000000026 ++:10FAE0000000000000000000000000000000000016 ++:10FAF0000000000000000000000000000000000006 ++:10FB000000000000000000000000050000000000F0 ++:10FB100000000000000000000000000000000000E5 ++:10FB200000100000000000000000000000000000C5 ++:10FB300000000000000000000000000000000000C5 ++:10FB400000000000000000000000000000000000B5 ++:10FB500000000000000000000000000000000000A5 ++:10FB60000000000000000000000000000000000095 ++:10FB70000000000000000000000000000000000085 ++:10FB80000000000000000800080008000000080055 ++:10FB90000000000000000000000000020000000063 ++:10FBA0000000000000000000000000000000000055 ++:10FBB000000000000000000000000000090000A09C ++:10FBC0000000000000000010000003000010000012 ++:10FBD000030000000000030000000000030000001C ++:10FBE0000000000000000000000003100000000002 ++:10FBF00000000300000000000300000000001000EF ++:10FC000000000000000005000000000000000000EF ++:10FC100000000000030000000000000002100000CF ++:10FC20000088000000000000000000000000FFFF4E ++:10FC3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 ++:10FC4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4 ++:10FC5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 ++:10FC6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 ++:10FC7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 ++:10FC8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 ++:10FC9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:10FCA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:10FCB00000788FF60C44808000500A06000000C3D4 ++:10FCC0000000000000000000000000000000000034 ++:10FCD0000000000000000000000000C00000000064 ++:10FCE0000000000000000000000000000000000014 ++:10FCF0000000000000000000000000000000000004 ++:10FD000000000000000000000000000000000000F3 ++:10FD10000084030000000000000004000000000058 ++:10FD200000000000020000000000000000000000D1 ++:10FD300000000000000000000010000000000000B3 ++:10FD400000000010000000000000000000000000A3 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000000000000000000000000000000000093 ++:10FD70000000000000000000000000000000000083 ++:10FD80000000000000000000000000000000000073 ++:10FD900000000000000000000000A00000000000C3 ++:10FDA00000000000000008000000080000008400BF ++:10FDB00082410800000000008200000000000000F6 ++:10FDC00000000000FFFFFFFFFFFFFFFFFFFFFFFF3F ++:10FDD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:10FDE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10FDF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10FE0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:10FE1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:10FE2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10FE3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10FE4000FFFFFFFFFFFF002C08030C44808000B081 ++:10FE50000A060000802000000000000000000000F2 ++:10FE60000000000000000000000000000000000092 ++:10FE70000000000000000000000000000000000082 ++:10FE80000000000000000000000000000000000072 ++:10FE900000000000000000800000000000000000E2 ++:10FEA0000000000000000000000000000000000052 ++:10FEB0000000000000000000000000000000000042 ++:10FEC0000000000000000000000000000000000032 ++:10FED00000000000000000000000000000000040E2 ++:10FEE000000000000000008800000000000000008A ++:10FEF0000000000000000000000000000000000002 ++:10FF000000000000000000000000000000000000F1 ++:10FF100000000000000000000000000000000000E1 ++:10FF200000000000000000000000000000000000D1 ++:10FF3000000000000000000000C000000000000001 ++:10FF400000000000000000000000000000000000B1 ++:10FF500000000000000000000000000000000000A1 ++:10FF60000000000000000000000000000000000091 ++:10FF70000000000000000000000000000000000081 ++:10FF80000000000000000000000000000000000071 ++:10FF90000000000000000000000000000000000061 ++:10FFA0000000000000000000000000000000000051 ++:10FFB0000000000021000000000000000000000020 ++:10FFC000000000000000000000000000020000002F ++:10FFD000000000000000000000000000FFFFFFFF25 ++:10FFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 ++:10FFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 ++:020000040001F9 ++:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 ++:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ++:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00248A ++:10006000C1900C44808000280A0600000041000076 ++:100070000000000000000000000A00000000000076 ++:100080000000000000000000000000000000000070 ++:100090000000000000000000000000000000000060 ++:1000A0000000000000000000000000000000000050 ++:1000B0000000000000000000000000000000000040 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000000000000000000000000000020 ++:1000E0000000000000000000000000000000000010 ++:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ++:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF ++:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F ++:10017000FFFF00E4B7440C44808000680A060000DA ++:10018000802000000000000000000000000000804F ++:10019000000000000000000000000000000000005F ++:1001A000000000000000000000000000000000004F ++:1001B000000000000000000000000000000000003F ++:1001C000000000000000000000000000000000002F ++:1001D000000000000000000000000000000000001F ++:1001E000000000000000000000000000000000000F ++:1001F00000000000000000000000000000000000FF ++:1002000000000000000000000000000200000000EC ++:1002100000000002000000000000000000000000DC ++:1002200000000000000000000000000000000000CE ++:1002300000000000000000000000000000000000BE ++:1002400000000000000000000000000000000000AE ++:10025000000000000000000000000000000000009E ++:10026000000000000000000000000000000000008E ++:10027000000000000000400000000000000000003E ++:10028000000000000000000000000000000000006E ++:1002900000002040000000000000000000000000FE ++:1002A000000000000000000000000000000000004E ++:1002B000000000000000000000000000000000003E ++:1002C000000000000000000000000000000000002E ++:1002D000000000000000000000000000000000001E ++:1002E000000000000000000000000000000000000E ++:1002F00000000000000000000000000000000000FE ++:100300000000000000000000FFFFFFFFFFFFFFFFF5 ++:10031000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED ++:10032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD ++:10033000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD ++:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD ++:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD ++:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D ++:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10038000FFFFFFFFFFFFFFFFFFFF00087FB70C44E9 ++:10039000808000D80A06000060DB0000000000003A ++:1003A000010000000000000001000000000000004B ++:1003B000000000000000000000000000000000003D ++:1003C000000000000000000000000000000000002D ++:1003D000000000000000000000000000000000001D ++:1003E000000000000000000000000000000000000D ++:1003F00000000000000000200000010000000000DC ++:1004000000000000000000000000000000000020CC ++:10041000000000000000000000000000004000009C ++:10042000000000000040000000000000000000008C ++:1004300000000000000000000000000000000000BC ++:1004400000000000000000000000000000000000AC ++:10045000000000000000000000000000000000009C ++:10046000000000000000000000000000000000008C ++:10047000000000000000004000000000020000003A ++:10048000000000000000000000000000000000006C ++:10049000000000000200000000000000000000005A ++:1004A000001008000000000010100800000000000C ++:1004B000000000000000000000000000000000003C ++:1004C000000000000000000000000000000000002C ++:1004D000000000000000000000000000000000001C ++:1004E000000000000000000000000000000000000C ++:1004F00000000000000000000000000009000000F3 ++:1005000000000000000000000000000000000000EB ++:10051000000000800100000000000000000000005A ++:1005200004000200000000001100040004000400A8 ++:10053000040000000000200004000400002000006F ++:100540000000110000000000030000000300040090 ++:10055000000000000000040009000000000011007D ++:100560000000000004000000000000002000000067 ++:100570000800080000000000040000000200000065 ++:10058000000000000000000000000000000000006B ++:1005900002000000000000000000008400000000D5 ++:1005A000000000000000000000000000000000004B ++:1005B000000000000000000001000000000000003A ++:1005C000000000000000000000000000000000002B ++:1005D000000000000000000000000000000000001B ++:1005E000000000C000000100000000000000010049 ++:1005F00000000000000000000000000000000000FB ++:1006000000000000000000000000000000000000EA ++:1006100000000000000000000000000000000000DA ++:100620000000000011000000000000C0800100C0B8 ++:1006300000000000000004000000000000000000B6 ++:1006400000000000000000000000030000000000A7 ++:100650000000000000000000000000210800000071 ++:100660000000008800C000000000000080000000C2 ++:1006700080000000000000000000000000000000FA ++:10068000001000000000000040000000000000001A ++:100690000010000000000240024000000040000086 ++:1006A00000000000001000000000000000412004D5 ++:1006B000000002008210004101000010000900004B ++:1006C000004000000010000000000000901000003A ++:1006D00000000000004100000000004100A00000F8 ++:1006E000000000100010004000000000000020107A ++:1006F0000000200000210010000000210010000078 ++:1007000000400200001000100200910000000041B3 ++:10071000000000800020001004A10100004100A0A2 ++:1007200000000041001000400002000000880004AA ++:10073000000000000090000000C000000000000267 ++:100740000000000000000000000000A000400000C9 ++:100750000000000000C00084000000000000000055 ++:10076000004000840000004000000300000400007E ++:100770000000000000900000000200100084004013 ++:100780000001088800880020002000A000A00000D0 ++:100790000000000000880000000100000000009040 ++:1007A00000000000008400000000000000000000C5 ++:1007B00000800000000000000000000000000000B9 ++:1007C0000000000000000000000000000000000029 ++:1007D0000000080000000000000000000000000011 ++:1007E0000000000000000000000000000000000009 ++:1007F00000000000000000000000100000000000E9 ++:1008000000000008000000000000000000000000E0 ++:100810000000000000000000000000400000000098 ++:1008200000000004000000000000000000000000C4 ++:10083000000005A000000000800100100000100072 ++:100840000000040000000000100000010000000093 ++:10085000000080A021C09000210085C0100003008E ++:100860000000000010001000030041840040000060 ++:100870008004050004040300C100101020A0000043 ++:10088000C00203004100000020000300200005001A ++:10089000000003840000000109080000840000003B ++:1008A00000000010100400040004000441050000D2 ++:1008B000904100410000004100214002C0210000A1 ++:1008C00000000005090000000000A000002010004A ++:1008D0000000000020000041202100002000000056 ++:1008E000000000000000C00000000800C000000080 ++:1008F0000000208000008580000004001000A1009E ++:100900008400118500008200000001000000C10089 ++:1009100000000000000000030040008500002100EE ++:1009200000000011000000A100800080A08000A055 ++:100930004100002009004100008803A005000400D8 ++:1009400040000900118400100000030000100004A2 ++:100950000300080000000400100020001010030035 ++:100960000000008403100320410003000020410028 ++:10097000000009001004200005401000008403005E ++:1009800004000588040000000400100021840020F9 ++:1009900041200500100003000200020010000020AA ++:1009A000104011C0800000000000000000000000A6 ++:1009B00003400000000000000000001100000000E3 ++:1009C0000000000000000000000000000000000027 ++:1009D0000080000001000000010000000100000094 ++:1009E0000000000000000000008000000000000087 ++:1009F00000000000000000000000000000000000F7 ++:100A000000000100000001000000010000000005DE ++:100A100000000000000000000000010001000000D4 ++:100A200000000000000008000000000000000000BE ++:100A3000000000000084000010001084000000008E ++:100A40000000001003000084001000C0050000003A ++:100A5000008480840500080000004100050000A01B ++:100A600000008010050000100000042041008001FB ++:100A70004100850100000000008400840300100094 ++:100A800000A0000000000000038400000310030029 ++:100A900020A003A02000000041A04110410000114F ++:100AA0000284089080000001000180000000000026 ++:100AB00000000000000200058200C000C01000001D ++:100AC00000000021844100410000000000000000FF ++:100AD00000000000200000001100000000000000E5 ++:100AE00000000000040000000010000001808400ED ++:100AF00004040000202000000005000084008400A1 ++:100B000000000021820082000000820000008200BC ++:100B100000000100C0001100004110000002C041AF ++:100B20004040110001000400000400042000A00067 ++:100B300000001000000000000000000000000000A5 ++:100B4000000000000000000000800800110000000C ++:100B50000000000000000000000000000000000095 ++:100B600008050004401140100000000000000000D3 ++:100B700002058902104108100080080500091010C4 ++:100B8000084008058009888440090000400005806D ++:100B90000000020920090011084140808500100072 ++:100BA000410080C000840211002080030409040079 ++:100BB00000808003080900008000000000000000A1 ++:100BC0000000000000000000000000088900C09044 ++:100BD0000090000000000000000000000000000085 ++:100BE0000000890100000100000100000000000079 ++:100BF00000000183C1880291010200000009021176 ++:100C0000A0C0000908410885091000020008C110B1 ++:100C100002A000080100010100010001050409848F ++:100C2000010201C00483A08401A1000308C10401E2 ++:100C30000002000882010101820082000000000021 ++:100C400000000000000000C00000000008000800D4 ++:100C5000904090C000000000000000010000010072 ++:100C600000000001000001C00101010100000000BE ++:100C7000000000008200090809400311000009007B ++:100C80001010100109A01000C0C01101038208005B ++:100C90008800110005C00000008201040100040169 ++:100CA0008400410000820000000000010182000178 ++:100CB0000100000401C1000001000000010100006A ++:100CC0000000000000090000008000020004801005 ++:100CD0000000000000820000000000000040000052 ++:100CE00041000000110904000880050209200000ED ++:100CF0000000000000000202410005400920000041 ++:100D00001104090090400900890489808502098442 ++:100D10000409400090000384090002000511090045 ++:100D20008920040085004180000400000040098003 ++:100D30000002410000000389000041000000030997 ++:100D400000000000000000000000000000000000A3 ++:100D50000080800008808080000000000900800082 ++:100D60000000000000000000044000400008402097 ++:100D70000000000000000000020800820890A002AD ++:100D80000000020980C0208820910340001100C0AB ++:100D900020820000808090800080020200111009F3 ++:100DA00020100010004080840040000080800480FB ++:100DB000898080000000C009008300000000400915 ++:100DC00000830000000000000000000000000000A0 ++:100DD00000000010C00408848888000000000000A3 ++:100DE0008200000800000000C000000000A0000118 ++:100DF00001010000000000008800000382C1888516 ++:100E00008904000000A010C14185A188010384C0AD ++:100E10004084018800A01008A08488880001000098 ++:100E2000000001000000A0A1048400A10008400807 ++:100E300083100282080400C008C100830000000083 ++:100E4000010108890000000000000000010001000D ++:100E500001000100840188001000C01000000000A3 ++:100E6000000000000000000000000000000000047E ++:100E7000010000000000000000000000058588025D ++:100E80008200A008000084018883C001081085C189 ++:100E900088080801A00884008800C00108880100B3 ++:100EA00000030001000084098402A000A0C0010228 ++:100EB0000288010003008588A182A0000400018847 ++:100EC00001C000000000000000000000000003005E ++:100ED00040004000200080028000800000000000F0 ++:100EE00000000000000000000008000400004000B6 ++:100EF00040020811400000000000000000000282D3 ++:100F00008809021008000000880391410840888089 ++:100F1000C040918282034000801080090008800058 ++:100F20000200092008401000808300410002008078 ++:100F300040000200400040008380040000000000E8 ++:100F4000038004800000000000000000C2000000D8 ++:100F500000420000C20000004160000BC2200000FF ++:100F600000000022D0000041004200066020000086 ++:100F700000420006D00000000000000B000000004E ++:100F80001242000BD000000000001242000BD00003 ++:100F900006001242000BD00006601200000B440055 ++:100FA000000000420000D00000000000000000002F ++:100FB0000A4800840013D000005000820013D000C3 ++:100FC000000000840042D00083A000000000000068 ++:100FD0000000000000000000000000000000000011 ++:100FE0000000000000000000000000000000000001 ++:100FF0000000FFFFFFFFFFF3FFF70000000000000D ++:101000000000DFFFFFFFDBFFDFFF0000FFFF7FFFD0 ++:10101000FFFFFFFFFFDFFFFFDFDFFFDF000000005C ++:1010200000000000FFFFFFFFFFFFFFFF00000000C8 ++:10103000FFFF00F6FFFF3C7C00000000FF00000007 ++:10104000FF000000FF000000FF00000000000000A3 ++:101050000000000000080004000000000000000084 ++:101060000000000000000000000000000000000080 ++:1010700000000000DFFFFFFFFFFFFFFF0000000098 ++:1010800000000000FFFFFFFFFFFFFFFF0000FFFF6A ++:10109000FFFFFFFF76FFFFFFFFFFFFFFFFFF0000E7 ++:1010A000000000000000BFFFFFFFFFFFF8FF00008F ++:1010B0000000FFFF0076FFFF3C7C00000000FF0007 ++:1010C0000000FF000000FF000000FF000000FFFF25 ++:1010D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 ++:1010E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:1010F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10110000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF ++:10111000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10112000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:10113000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:10114000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:1011500000944F4A0C44804000180A06000070DFDB ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:10118000000000006666000000C026E6464646767F ++:1011900000000000000000000018E0F84646467617 ++:1011A0000000D3D3D3FF00903CB4909090F6060695 ++:1011B00006F600000000FF00666699F9DBFB1010E0 ++:1011C00010F700000000E6E60000BC3CFFFF000056 ++:1011D000FFFF000000FF0000F0F0000000FF000033 ++:1011E000F0F000000000000000000000000000001F ++:1011F00000000000000000000000000000000000EF ++:10120000000000000000F6F6F0F000FF00FF424290 ++:10121000427E000000000000000000FF00FF42428C ++:10122000427E00000000002CF0F0F0F0B0B0B0F210 ++:10123000262626E6000000000F0F3C3C0060002040 ++:10124000F0F0F0F000000000E6E70000BC3CFFFF1B ++:101250000000FFFF000000FF0000F0F0000000FFB2 ++:101260000000F0F00000000000000005080000048D ++:1012700008000000008600A40190000500860061BF ++:1012800008B000050086006400300000008600758C ++:10129000009000000086006100B00000008600B4ED ++:1012A000019000000000008600B401980000008654 ++:1012B00000B401900000008600A009900010010019 ++:1012C0000014000000000086006000B0008001866D ++:1012D000007D00B00803C0C7C07C30304903C0C7E0 ++:1012E000C07C3090490300000000000000000000B6 ++:1012F000000000000000EBA8A8A80D0D0DFF0000E5 ++:10130000000000000000000000003C3C0000000065 ++:1013100000000A0A0A0A0000000000000000F7D7D7 ++:101320002000000CC3CF0000FA0A0A0AD3D3D3FF6F ++:10133000BE828282101010BFFA0A0A0A4141417D22 ++:1013400000000000000000000A0A0A0AFFFFFFFF79 ++:1013500000000000CBDF0A5F3C3C3000FFEBFCF8F4 ++:1013600000000000FFFF000000000000000000007F ++:101370000000000000000000AAAAAAAA0F0F0F0F89 ++:101380000000000000000000000000003C3C0000E5 ++:10139000000000000A0A0A0A000000000000000025 ++:1013A000F555A0000008D7DF0000EA2A2A2A00002D ++:1013B000002CAEA2A2A23C3C3C3CEA2A2A2A45458B ++:1013C000457500000000000000000F0B0F0A55F5E6 ++:1013D0005555004100410A5F0A5F3C3C3800FFFF61 ++:1013E000FCFC00000000FFFF000000000000000007 ++:1013F000000000000000000000000000FFFF8383E9 ++:1014000083830000000000000000000000000000D6 ++:1014100000000000000000000000000000000000CC ++:101420000000FDFFFFFFFFFFFFEF0000FFFDFFFFDC ++:10143000EFEFFFFFFF7FFFFFFFDFFFD7FFFFFFFDA6 ++:10144000FFFFFFFF0000000000000000AFAFAAAAEE ++:101450007D7D7D7D0000FFFF00000000FFFFFFFF9E ++:10146000000000000000000000000000000000007C ++:101470000000000000000000000000000000FEFE70 ++:1014800000838383000000000000000000000000D3 ++:10149000000000000000000000000000000000004C ++:1014A00000000000FFFFFFFFFFEFFFEF0000FFFF66 ++:1014B000FFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:1014C000FFFFFF7FFF3F0000000000000000AFAF04 ++:1014D000AFAE7DFD7DFD0100FEFE00000000FFFFC0 ++:1014E000FCFC000000000000000000000000040000 ++:1014F0008400100004000400000003000300040046 ++:1015000004000400040004001100000000000400B6 ++:101510000000210004000400110004000400000089 ++:101520001100110004000000000040001000000045 ++:1015300000000200020002000000A100040082007E ++:10154000000011000000800000000000000080008A ++:1015500000000000040004000801110000008200E7 ++:101560000000000000000000000002000000000079 ++:10157000000040000100000000000000000000002A ++:10158000000000000000000000000000000000005B ++:10159000000000000000000000000000000001004A ++:1015A0000000000000000000000000000100010039 ++:1015B00000C00000000000000000000020009000BB ++:1015C00020000000A0000000040000000000000057 ++:1015D00020000000000000100000010200000000D8 ++:1015E00010000000000000000000000000000000EB ++:1015F00000100000004000018020002000A0000535 ++:101600000021000000000001000400000010112073 ++:10161000000000000800000000100000008800002A ++:101620000000000000000000000000100011002079 ++:10163000808800C00000000000C002000020802060 ++:101640000020800100A00020000000000000001029 ++:101650000000002000012091024100210009000447 ++:1016600002011041800040A0000000900001000134 ++:10167000000000010021A0901010088000800010E0 ++:1016800000A00004000000000004008000200021F1 ++:101690000000002100000120000090100021002126 ++:1016A0000020042000009040000000100000000412 ++:1016B000001020200000000000200021002002A0D7 ++:1016C000208000A0202000100000000000108210E8 ++:1016D0000221001002400020012001200020009083 ++:1016E0000090010801044010010400410010002096 ++:1016F00090200021002000C00002001100A0000482 ++:1017000000A00020001100C00005009103400084EB ++:10171000000200100002000000020000008800101B ++:10172000009100000010000000000000008800840C ++:10173000000400010005000000000000000000900F ++:10174000001000000000000200C0000000A000A087 ++:1017500000008088008400C00010001000410010CC ++:10176000000000A0004082210000000800A000212D ++:10177000002000C000010084000000800090840070 ++:10178000008082000080002000000084C0020080F1 ++:101790000021000000211000C000C080C000000037 ++:1017A000000900020010000000001000000082216B ++:1017B000C0000080000400C0000084210009104027 ++:1017C000040520410000000584050000C0008200DF ++:1017D000002182000400C01100008200C00000C08F ++:1017E00000008200820082804120C0090080400009 ++:1017F000000290000000002000000000C1021082E2 ++:10180000A18400001001039041001000410040003D ++:101810002000200010200000C1000900200010104E ++:101820000001020005000000004041000002108895 ++:10183000802010C105000201051100000084040091 ++:10184000098410A010C010040300100000C0411053 ++:101850000000100000C085004100C10002C003006C ++:10186000050080A0000040030005800000004190BA ++:10187000000804000382058205828001000510A192 ++:101880008800041000000004081000090100000096 ++:10189000010000030100008000001005C0000000EE ++:1018A00008000004000000050000000500000080A2 ++:1018B000002120A10004000001020020000000001F ++:1018C000830000000000A00082900041A000000002 ++:1018D000000000410141000004000000041001006C ++:1018E0001000002110000041018800C04000A0004D ++:1018F000002100A10000820000100000100800007C ++:10190000090241002040031000204140050305006A ++:101910000300020080C1200002004010030200000A ++:101920001020000002840300408400002004051001 ++:1019300000000000110000000000200020840000D2 ++:101940004100040003400402050021000000058856 ++:1019500000C0048800A0414000002002020210C024 ++:1019600000000202034041080000008810021090AD ++:10197000008403020984C00200C0000000000500CA ++:101980000000008004090180200000910000000494 ++:10199000000088050100042001000400010000107F ++:1019A000000000000000012100000100000001898A ++:1019B00000000000000000000041100001000100D4 ++:1019C0000000102101000040050084008400A005F3 ++:1019D00090419000A100002110000400A10000052A ++:1019E000A000820001000080840040000200C0804E ++:1019F000000300001000C000100200000000000002 ++:101A000000000001800000C002018801042190A1B3 ++:101A100080A0000003100204412080A000A00090DC ++:101A200000010082038200100001410000020090CA ++:101A300000041000020000A00200850180010005E2 ++:101A400000040000021009100010821000C0418242 ++:101A5000000041110900108410100084000004A04F ++:101A6000418404C000000082000041098800008415 ++:101A7000002100080000101003918400000041853F ++:101A80000010800100021003880001022020018460 ++:101A9000202004050000840000C0009020000010F9 ++:101AA000C041002000000010C0410002000000C141 ++:101AB0000021008000000000000000050404202038 ++:101AC00000A08880000000009000000020000000BE ++:101AD0000005001084040000080000000010000051 ++:101AE000030010410121000000210810008841007E ++:101AF0001000108200850000010000082000001185 ++:101B000000040000100804808080408000008340B2 ++:101B1000410920400808850409400902090900001C ++:101B2000000011000080000080000900000000009B ++:101B30000000000000000000000021000000000084 ++:101B4000080005000000008000000580858000007E ++:101B50008920000900112009000000808500008014 ++:101B600088828509C09108418991214000848008BC ++:101B70000303082105004008090302100541090478 ++:101B8000109102400885100800820204000400A0A1 ++:101B90008840008500400008850001000001010127 ++:101BA0000008A004A0000008000090000000000051 ++:101BB0000000000000000000000004000100000020 ++:101BC0000000A10000000000000000408810C008D4 ++:101BD0000008080100010001010000C08208404027 ++:101BE00000400808C005C10588080483018400047A ++:101BF00082A1890100010000000100011001010122 ++:101C00000000098800A10011200001000800410027 ++:101C1000039088004040890040090800C000080087 ++:101C20004100C00004100001044000000100002039 ++:101C3000010000000000000000010100010001009F ++:101C400000000490A0000490020000008800400002 ++:101C5000080040040108008801910100C00009004B ++:101C6000900291C00801048405014104400820C08D ++:101C7000C0080240C000C01102218300018201009F ++:101C8000018401018204A09008891088400083002B ++:101C90000800038000004000A10020098800040023 ++:101CA00083038900000900800011008008004000C3 ++:101CB00004000300000000000000000340000800D2 ++:101CC00040000004850003028008800900000041F4 ++:101CD000000080000009200005000502090000093D ++:101CE000A00000002000C12002008503090400407C ++:101CF0000088008300884000408490048305110020 ++:101D00004100080003050000004000828000000838 ++:101D1000001180C0000003080004080900800310BF ++:101D200000840011A1A100000000008000800000DC ++:101D30000000000000800000000000000000000023 ++:101D400000800080008000801000408000000000C3 ++:101D5000008080000500808002081004034041409C ++:101D600000800080008080002089800491850488A4 ++:101D7000034010081140880904800921101108034C ++:101D800002C000C0048283830300004021840489D0 ++:101D900000212005408520900041008320410088DB ++:101DA00001C1001000A0830900C0A00404841040F9 ++:101DB00000880090009000820000000000000200F7 ++:101DC000000400080010008800040184010290A0B3 ++:101DD00000000040C0824102408800010100000074 ++:101DE00090000008C0C0908488040140C084108422 ++:101DF00088890101A1000100020001900003010097 ++:101E00008503A109000300034109010808A083100C ++:101E1000908882854001820004000340858940202B ++:101E2000C101019001C1008901408505A0C0830066 ++:101E3000C0A00000000000010000000000910000B0 ++:101E4000000000000000000000000102000000008F ++:101E500000A00000840104004000C040000001A078 ++:101E600000010100840102010801C00884A18883E7 ++:101E7000A0004188840384A0A0000411010801850A ++:101E8000000000A000040001000100000908A08873 ++:101E90001000C000808380110008000089030282C6 ++:101EA0004040A11003000421118209008308028030 ++:101EB000400009000000001100400000000000C0C8 ++:101EC0000000000000000011000000000383040572 ++:101ED00011030800000080108000800000800400D2 ++:101EE0000804404020008003000980210080840213 ++:101EF00085844004882083024080110088C10380CB ++:101F00000408000011000000001100210000020878 ++:101F100011808400892000000013C20042000000EC ++:101F20000042480000000042000BD0004148000081 ++:101F30000013C20000004100000602000000820001 ++:101F400000136000008100000013C20000000000C8 ++:101F500000104800000000001200000BC20000004A ++:101F600000840080D00000001200000B000006007A ++:101F70001242000BD0004141000000424800828123 ++:101F8000000000134800810000000000D00000485D ++:101F9000000000104800210000000000101F101F6A ++:101FA000000CFFFC01FD01FD4F41414105045010B3 ++:101FB0000900030000000000000000000000000015 ++:101FC0000000000000000000000000000000000011 ++:101FD000E1E1F0C30000000000000000000000008C ++:101FE0000000FFFFBFFFF3FFFFFF00000000000045 ++:101FF0000000FEFFFFFFBFAFFFFF04070707511000 ++:102000005DDF3CFF7D7DAAFFF0FF000000000000C7 ++:10201000F3FF0D0D0C0F000FF0FF00000000101F6C ++:10202000101F0000FFFF00FF00FF4F414141000073 ++:10203000551405000C000000000000000000000026 ++:102040000000000000000000000000000000000090 ++:102050000000E1E1F0C3000000000000000000000B ++:1020600000000000FFFFFFFFF7FFFFFF0000000080 ++:1020700000000000FFFFFFFFFFFFFFFF0404070455 ++:1020800051105DDF3C0028280055000F00000000C3 ++:102090005155F3FF010100030055AAFF00000000A5 ++:1020A000FFFFFFFFFFC0FF00FF00FF0000D000F0B8 ++:1020B00005005000000000000000000000000000CB ++:1020C000F0008282000000000000AAAA00000000C8 ++:1020D000A0B4A0B400000000000000000000000058 ++:1020E000000000000000F414FFFFFFCBCBCB00008A ++:1020F000000000000000F3C33000F8D0D0D0FABEDA ++:10210000501400000000AA3CAAAAACACAA3CFA0AEF ++:10211000FE3EF30059AAA220A22000000000000009 ++:1021200000003C3C80823F00FF00FF50AF000020D9 ++:10213000000001004000000000000000000000005E ++:10214000000000008282000000000000AAAA000037 ++:102150000000A0B4A0B400000000010101010000D3 ++:102160000000000000000000E0000000340000005B ++:102170000000000000000505FBEB1000FCC0C0C023 ++:102180000000000000000000AA3C3C3CACACAA3CB3 ++:10219000FA0A0434C0006AAAA2A2202000000000AB ++:1021A0000082026100B80010008600010880000073 ++:1021B0000586007500B00000088600B00890000099 ++:1021C00000860260013000A00086006009B004159E ++:1021D000008600600090008508865061A8B0000568 ++:1021E0000000008600A0019000050186007500B087 ++:1021F0000000008600A001900000018600B401905C ++:1022000000000086706000B8000005865A60A0B922 ++:1022100000A500860A6000B90010008670010080E9 ++:102220000000C3FFFF0FFFF141413C3C3C3C40003C ++:102230007FFF00000000081C495D3C3E3C3E00FF63 ++:102240003C3C00000000FCFF555500000000000071 ++:102250000000000000000004AAFF00000000FFFFD3 ++:102260000000000078F050F000EB04EF00000000E8 ++:10227000000000003CB400A00005AAAFF8D0D0D008 ++:102280005151515D000000000000000000000000FE ++:102290000404000000000000EBEFFFFF3C3C3F3C6B ++:1022A00040007FFFC3FFF000414141413CFC3C0C3A ++:1022B00040007FFF00000000081C495DFFFF000A8E ++:1022C00050FF7C7C0000000000FF000000000000C8 ++:1022D00000000000000000000000AAFF0000000055 ++:1022E00030B0000000007878505000C30CCF0000E0 ++:1022F000000000000000F0F0F0F00001BEBFFCC0E4 ++:10230000C0C04141417D000200000000000000000B ++:10231000000004040000000000000BEB0FFF3C3C39 ++:10232000303C40007FFF100000000000000FFF0065 ++:10233000FF3030FF00FF000000000530053FBEFF0A ++:10234000BE55F1F1FDFD000000000000000000009E ++:10235000000000000000000000000000000000007D ++:1023600000005F5F5F5F0000FFFFFFFFFFFFFFFFF9 ++:102370000000000000000000FFFFFFEFFFFFFF3F35 ++:10238000FFFFFFFFFFFFFFFF0001FFFE3C3C3C3C67 ++:102390000000000000043C380000000000000000C5 ++:1023A000FFFF00003C3C3C3C00001000000000002F ++:1023B000FF00CF0000CF00FF000000000530053F08 ++:1023C00014FF1455C1C1CDCD000000000000000075 ++:1023D00000000000000000000000000000000000FD ++:1023E000000000005FDFDFDF0000FFEFFFFFFFF80E ++:1023F000FFFF0000000000000000FFFFFFFFFFFFE5 ++:10240000FF7FFFFDFFFFBFAFFFFF0001FFFE1C1CB2 ++:102410001C140000000000043C3800000000000014 ++:102420000000AFFFA0003C3C0CFC11000490200019 ++:10243000202004881100040021C011400000040085 ++:1024400000000400040005001190040000000400D6 ++:10245000042000000000112011000400000004000E ++:102460000200040004000300040000000400000057 ++:10247000040004001100110004001000030000001B ++:102480000000000004000400020003100400030028 ++:1024900000000000040020000400040020000000F0 ++:1024A000110011000000040000C000000000000046 ++:1024B0000000A0000000000000000000000000007C ++:1024C000000000000200000000000000000000000A ++:1024D000000000000000000082000000000000007A ++:1024E00000000000000000000000000000C000002C ++:1024F0000000000000000200A00000000100040035 ++:1025000000000000000000000000000004001000B7 ++:10251000000000000000000000000000004100007A ++:10252000000000000000000000000000080000841F ++:10253000040000C0000000A0000000200000000017 ++:10254000008800020040040004000004000000882D ++:102550000000000100A00000001011200010000089 ++:102560000000000100C00000002100040021004024 ++:1025700000000020000000C000000000000010006B ++:102580000088002000880000008880000000000013 ++:102590000000002004000008000000000088002067 ++:1025A000000000000000111000000000000000000A ++:1025B00000000010A000024100200021A0800010B7 ++:1025C00000000021008000000000002000A000208A ++:1025D000001000410002000000000090A0C1002097 ++:1025E00000009000000200210020821000900008EE ++:1025F000000000100041001000000000000800036F ++:1026000001110000002100108211000008000011DB ++:1026100000000010024102100010004100210020C3 ++:10262000000800000020004100410041004100205E ++:102630000211001000A0214000C00088008400C0EA ++:1026400000001000000000A0001040C00090000238 ++:10265000008800900010001000A000400000000062 ++:10266000000000000000000000400002008803009D ++:1026700005900000408802820304008800100000DA ++:102680000010001000900810004021C0000200005F ++:102690000088082011000582000400A000900002BC ++:1026A0008001C000009000908084000000000002C3 ++:1026B00080C00085820000040200020082008410B5 ++:1026C000001000000000A0008205C0020000000011 ++:1026D000020000100041000000000008100010007F ++:1026E0000000100000000000040000800000000056 ++:1026F000000084000000400002108200041000006E ++:1027000040000020104002000800000010000000FF ++:1027100000008800000900000000000300411021B3 ++:102720000203202011050402000040000200000006 ++:10273000000020030004080000000800050111004B ++:10274000800005008500000000000000000000007F ++:1027500000902000100000001000000100000000A8 ++:102760000000100100C10000000005840000090005 ++:10277000110003011000000000A0000000900020E4 ++:10278000058400001000C10208A00020C0008000E5 ++:10279000000009080020910005000300100110004E ++:1027A0000500109010000000410000000000000033 ++:1027B000000000001088100810008811910900081E ++:1027C000C005080082111041000000000010000543 ++:1027D00020090010100020000000880000100020D8 ++:1027E00000000800080400080000001000100004A9 ++:1027F0000000100000200041000008000000082137 ++:102800000000000000008800108900000020090579 ++:1028100002400800080500C1100000000000001080 ++:1028200000008811022110030000000000000411C4 ++:102830009020100000000000000041904182400004 ++:102840004100008409A000A01000400000C0041056 ++:10285000000004100402400280C140C003880088C8 ++:10286000038800A0098410828088000040840090C2 ++:10287000080010880400000085880000008400A083 ++:102880004102008400000300028221A000A0008415 ++:1028900020020004020010100810000008000910B7 ++:1028A0008500880000C083002110000000004188DE ++:1028B0000091028810C0100100019020040000095E ++:1028C0008900880000000000000900000000A00945 ++:1028D000C0C0840200000020C0001004000090006E ++:1028E00000208400080000000009400010000000E3 ++:1028F00090110821000000001000200500000011C8 ++:1029000002008411000000000000C000020040002E ++:102910009000100010000000A0000000080900084E ++:102920008800400010020410081000000010400051 ++:102930000000C010C1000000001082201005091026 ++:1029400041100300108400001090800040A021007E ++:1029500000C000C000C1000080C0808809000010D5 ++:102960000000000011010084008441100008008272 ++:1029700003C000830810000005C0410000400000B3 ++:1029800010000084000003004188021000A0408471 ++:102990000000000000C005101010200041011001CF ++:1029A000108400082100050010884100051005C0B2 ++:1029B000108403820500054000A00088000010A0DC ++:1029C00000000809C0100240C000820020008300FF ++:1029D00000008400A0409040000008410410000066 ++:1029E0000041000008211008044000000000000021 ++:1029F00000000000001000000000000008110800A6 ++:102A0000000000000820000000000041000000114C ++:102A10000541000000000000200400001000100428 ++:102A20008404C0210200C000020000000400000075 ++:102A3000C00000002000C000C000002010200020C6 ++:102A4000002000008300008883C1800003800041D3 ++:102A5000C182038083000083034190008380800251 ++:102A600003008000A000001183C18000038080C1AA ++:102A700003830380830000830341C00083000002BE ++:102A8000030000000000830000C183C180800300B8 ++:102A90000002838803000300008303414080830019 ++:102AA00080C1030000008300008883C18080410052 ++:102AB0000002839003000400008303104080800024 ++:102AC000008503000082838208C183C182A00104C3 ++:102AD000029121C00110118200830101838283C011 ++:102AE00010830100828282828882834008820110E2 ++:102AF000100921C0010211820083010183828388B1 ++:102B00004083010000000082838204C183C182A04F ++:102B10000182408903C101A0A18200830101020258 ++:102B20008382A0C101000082838290C183C182A000 ++:102B30000082A041054101A09082008301010302AF ++:102B400082A0A00401008200088200834182A0824A ++:102B500041820000C182408382830083C1008320C0 ++:102B60000982008301C0820090820083C182828238 ++:102B700085820082C190088382830083C100832004 ++:102B800091830083012000008200888200834182BB ++:102B9000A08209820004C102408382820083C100B6 ++:102BA00004108483000501028200208200830382D6 ++:102BB000A0820582000441A00983838200839100E2 ++:102BC00020418482000901A00000808000831080E1 ++:102BD0000080048000008380208309880083C10076 ++:102BE000020984C000834109000000800083C08086 ++:102BF0000080028000808300408340C10083C108C0 ++:102C0000020904C1008341850000000000800083A8 ++:102C100041808080048000008300898303840083D6 ++:102C2000C10085C0039000034109000000800083BB ++:102C3000C080808004800000830090832090008307 ++:102C40001000200203820083100000050080A0C154 ++:102C500088C1000000804021C0A180C00000910216 ++:102C6000000000110000830200000003008083C107 ++:102C7000C04100000000830320C10011000083C197 ++:102C8000000000110000830280000000000200002C ++:102C900083C1114100000080890291C1000400003D ++:102CA000830200000010000083A180000003008068 ++:102CB00080C184C100000000830203C1000800003D ++:102CC000830200000020000083858000000000C017 ++:102CD00082C1832100000040828905A102C00084D6 ++:102CE000828300000002008483830000000000C093 ++:102CF00082C1832100000082838201C100820082A0 ++:102D000083C10000000400848283020000000001EF ++:102D1000008283C10091000000C0820982C100824C ++:102D200000828383000000C1008283A18200A00092 ++:102D300000C082C182030000008283C100C1008301 ++:102D40000082838300000005008283048200020960 ++:102D5000018289210482A18201038482C002C1828E ++:102D6000010101830000838301080101C003029176 ++:102D700001828303908383400183918310218388A0 ++:102D8000018301830000C18201010101C00800002C ++:102D90008389018221A1888204A000832182A0C0AE ++:102DA000838300010183000082040102010184C1C8 ++:102DB000020500828340088383A00183088302C048 ++:102DC000838201010183000082050102010102C129 ++:102DD00083830280410200A020800283110380854A ++:102DE000C18802030283000040A00411020800C150 ++:102DF000830302804188008802004083408880C0AD ++:102E0000020804834183000082C0044102080005D7 ++:102E100000000203208041020084040008839083A4 ++:102E2000000502C0410302830000090802082102D4 ++:102E300000C083834080412180C00200408311880C ++:102E400000040282080302830000411002032102F1 ++:102E500000C0000000000000124211480008D0002D ++:102E6000125081480004D00012420000000000000F ++:102E70001242000000000000124221480004D0006D ++:102E8000124221480004D00012420000000000005D ++:102E9000124200000000000000001242114800131E ++:102EA000440012428148000B020012420000000060 ++:102EB0000000124200000000000012422148000BF6 ++:102EC000480012428148000B4800124200000000F6 ++:102ED00000001242FFFFFFFFFFFFFFFFFFFFFFFFAA ++:102EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:102EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:102F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 ++:102F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 ++:102F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 ++:102F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 ++:102F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:102F5000FFFFFFFFFFFF0014C6670C44802000E85E ++:102F60000A0600006059AEDE00000000000000000C ++:102F70000000000000000000000000000000000051 ++:102F8000000000007B75AEDE0000000000000000C5 ++:102F90000000000000000000000000000000000031 ++:102FA000000000007B750000AEDE000000000000A5 ++:102FB0000000000000000000000000000000000011 ++:102FC0000000000000007B75AEDE00000000000085 ++:102FD00000000000000000000000000000000000F1 ++:102FE0000000000000007B750678C00000000000B3 ++:102FF0000000008C0700000000000000300000000E ++:103000000000000000031E600678C0000000000001 ++:103010000000008C070000000000000030000000ED ++:103020000000000000031E6000000678C0000000E1 ++:1030300000000000008C07000000000000003000CD ++:1030400000000000000000031E600678C0000000C1 ++:1030500000000000008C07000000000000003000AD ++:1030600000000000000000031E6000000240040099 ++:1030700000001100110004104000020002001100C5 ++:1030800004000000040004000820000011002100DA ++:103090001100001020200208201002008408840083 ++:1030A00004000200020004A004200000000004004C ++:1030B000040000000800040005200420040004109F ++:1030C00004000208004008000440840800000020BA ++:1030D0000400000000000310051020100000001084 ++:1030E000210000400000000100000000000000007E ++:1030F0000000000000000000008000000000000050 ++:10310000200000000000000000000080000000001F ++:103110000000000000000100000001000000088025 ++:1031200008002000100000000000200000C0000087 ++:10313000A00000000000010004000000208000004A ++:1031400000008800008000000000008002000040B5 ++:1031500000800000000000008280000000001000DD ++:10316000000000000000820082400000000000001B ++:1031700000000000000100000008410900020040BA ++:103180000004000100010000000000000001000038 ++:1031900000000000214000000400000000000400C6 ++:1031A000100880000000001000000000000100C0B6 ++:1031B00000008040000000400003000000C000400C ++:1031C0000000000000000004C100000000410020D9 ++:1031D00080010001000100A1000000820000000049 ++:1031E0000001000900000000000000018001000053 ++:1031F000002100000000002002000010204000110B ++:103200000411008000409004001090030041004031 ++:1032100000000000000000C10020000800000003C2 ++:10322000010001801011C00000080008000800081B ++:1032300000004000028000000280008400080009B5 ++:103240000208000388000000008040030409008297 ++:103250002090040400400004004000210021880365 ++:10326000000900100084A0080410000002200420BF ++:10327000000802C00020008800C000000000808418 ++:103280000004008800A000100002000005020004F5 ++:103290000088098500A12082000000200004402051 ++:1032A000002000048084800100C0008500000083AD ++:1032B00000110000208880100004008200840011AA ++:1032C00000048020000000020090800000088008B8 ++:1032D00002A0000000000000000200000002031035 ++:1032E0000902000010A140900020000808C088A03A ++:1032F0000000110084030000000300084000A0103B ++:1033000020080090000000000000001100210010C3 ++:103310000003004000040004110000000080004190 ++:103320000080008040A10800401000210020001013 ++:10333000882000040000880840001080C0418200FE ++:1033400088040084081000091089C00910100000CA ++:103350004000101190000041820510000000C000E4 ++:1033600084110000000291041100004100080000D7 ++:10337000040000080041020002000900080080006B ++:1033800010200000000000000500100003040800E9 ++:10339000000000000400000010004190020108003D ++:1033A00000001008000800002100210002000000B9 ++:1033B0000300050000880000000000001000050068 ++:1033C00000100002034010401100400002844141FF ++:1033D00009000000800804014100000000000811FD ++:1033E0001002210010000200001010001040000028 ++:1033F00009901001840104000811102082090800BE ++:103400000400008000000000C000201188000008B7 ++:103410000000A010000901000009001100000804CC ++:10342000000000000000C000100508008200010933 ++:10343000C000000000110000000008100000901003 ++:103440008200008000A010830089A02005080011E0 ++:103450008208900420050480030800001010C010AA ++:103460000040820404000000C1000880881088A089 ++:103470000000000008200320110041200021050069 ++:10348000100404102140000241108040100300038A ++:10349000000189C020008004001100A00005800008 ++:1034A0008082111000100090101009A088C0210027 ++:1034B00082C041C1A110111000A000008390040936 ++:1034C000214082104000800000A084C080020021C2 ++:1034D0000008400402C008102100210200404004FE ++:1034E0002088802002880200211010041020100182 ++:1034F00004000521030000C000001020040088849F ++:1035000000410088410000088811008304008820E1 ++:10351000002000202000010820908804A0008420C2 ++:103520000400044100888890A003888500000921D8 ++:103530000005031182100841000004000000204132 ++:10354000000400802110000502000000200040104F ++:1035500000020080A00089000000100300000000AD ++:1035600000080000028001000141008084A1008069 ++:1035700010200005A0A00000A0000000C0800040B6 ++:1035800000C000200810009083004182004000C06D ++:10359000020400840000008420900084008408203D ++:1035A00000840400008410C01020001000000010EF ++:1035B00000000308008500080020410003200000EF ++:1035C00000400084218400400010008400100800A6 ++:1035D00000C000C008101000100120004110410080 ++:1035E00000004183002021090000100400824000F7 ++:1035F00000C00920094000848840080190011000A3 ++:10360000000004000800080010002000A01108912C ++:103610000000010000000000000011000000900008 ++:1036200002800000080000000000008000900400FC ++:10363000000000200000000404001091A000088099 ++:10364000000008A082040409109004401003024006 ++:103650001103000000200008840800080005004055 ++:1036600000000000884008830410000000000000F3 ++:10367000000288410890008000000880002002209D ++:10368000080002100240A0A0411000C1408800883C ++:1036900041084005A00402024141081108104108F8 ++:1036A00009101011830909100000030503090041E6 ++:1036B000080588C0808409912104000000000000F2 ++:1036C00000000000000040800200000008008300AD ++:1036D0001000400003002100000008000800858061 ++:1036E0004080888000202141020480050080800005 ++:1036F000040000000080C1A084408009900302A063 ++:103700001120800301C18283214101080082040845 ++:10371000002101C1C101410101000101010040017D ++:103720001100000101001001000000000101000172 ++:1037300000090100908210400040000200000000DB ++:103740000000000000008800028401A000A000002A ++:103750000900000001000100000000000100000459 ++:10376000C084018882C0C00111009000C0000082A6 ++:10377000A0880188000402880809080582C0A10306 ++:1037800008858203A00403018383A10940108200FD ++:103790001000A00905C141911184A09003C0000050 ++:1037A0000190010001000182001000880101000267 ++:1037B0000982012101000000010201200000002017 ++:1037C0000800004000000000000004010000108418 ++:1037D00008000300010083880000000000000100D1 ++:1037E00010008410A08889A10520A0C005034140D5 ++:1037F000010001000100010082110805041101020D ++:103800001000C0A0894183859103028220A02180FD ++:103810004002800089088820914084008241058808 ++:103820000000100008000900108011801010090825 ++:103830000280418005200905110008000288090066 ++:1038400011000400100010210000004000100000D2 ++:1038500080A1910010032000C009090000000400AD ++:103860000320211080800800031188830480C08217 ++:103870004090080010001000090020C08503058258 ++:1038800003000008000090A083840380000521A0AD ++:1038900002080004808841084088038040202002FC ++:1038A000034080000008084140101011041008096E ++:1038B000C1412010041010200420101100080841FC ++:1038C00011830000030000800000000000808000E1 ++:1038D0001000008000400004054000840011091120 ++:1038E000211080000008008080400003410008098A ++:1038F0000489030580000080000000809080800023 ++:103900008080008003A104210480418301020040E3 ++:10391000A085200400C04005829100090004000831 ++:1039200001A1900104100082010521050100010898 ++:1039300000C1830901010100004190000082A0C084 ++:103940008301008390000100001008000000900433 ++:1039500010108302001090890088008282A000006D ++:1039600000000101840000400408088890118202D0 ++:103970000090018409A1A09008C000000882A01056 ++:10398000881084848488829011C0C184901184003E ++:103990000883A10190A0830391418300C008010224 ++:1039A000890510014010010000900000010001880D ++:1039B000004000000000014000400900000001A09C ++:1039C000018401010100000000000001000000006E ++:1039D000001000000800000082900200088400002F ++:1039E0000000000100000001004005A18300100854 ++:1039F0008200110120011004000808840400000165 ++:103A0000C00189008400881091201088840010C1B2 ++:103A10008000910310210300900940880804910060 ++:103A20000240408211048080090008080909100042 ++:103A300009004040000040001000108308042000EE ++:103A40000300058211400400000000080008000087 ++:103A5000000000000000800000008090000300844F ++:103A600000000000004000080003000990910410CD ++:103A70008000C0208508022090C0000000040011D2 ++:103A80000009411185219021808083118380832149 ++:103A9000C18300000013C2000A0021000013C2000D ++:103AA000000000000008C200000000000013100029 ++:103AB0000000000000424400428200840008D00060 ++:103AC000420041000013C200000000000004020098 ++:103AD0004200000000000000480000000000000854 ++:103AE00048008200000000004400418800000008F7 ++:103AF000D00000810000000BC200004100000080E7 ++:103B0000C200000000000013480082840000004250 ++:103B100000000082BD24BD249FFF06FFFFFF7F3F02 ++:103B2000FFFFFFFFFF0066666F6F0909CFFF0C0004 ++:103B3000666F66667EFF4200FF00EF08FFFFFFFE34 ++:103B4000FF3FFF7FBD3C0900F000FE7E000000004B ++:103B50000000000000000000000000000000000065 ++:103B600000000404FF04000000006F097E7EFF0FC8 ++:103B7000FF0F00000000FFFFFFFFFFFFFF0F00002F ++:103B8000000000000000000000000000000000F045 ++:103B9000FF0F050518189F9F9F9F9F990699FFFF8C ++:103BA0007F3FFFFFFF0C0F0FFFFFFF99FF99FFFF04 ++:103BB000000066606666FFFF0000FF00EF08FFFF81 ++:103BC000FFFFFFFFFFFF3C3C0900F0007E7E00008E ++:103BD00000000000000000000000000000000000E5 ++:103BE0000000000004040404000000006F0918181D ++:103BF000F000F00042002400FF6EFF0CFFFFFF0FFB ++:103C00000000000000000000000090000000000024 ++:103C100004D0DB0B05051818FFFFFFFFFFFFFFFFB8 ++:103C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 ++:103C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 ++:103C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 ++:103C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:103C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:103C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 ++:103C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:103C9000FFFFFFFFFFFFFFFFFFFF0018D9630C448A ++:103CA00080A000180A060000304D30303F3F1F183A ++:103CB0007F7E7EFFFEFFFFFFFFFFE360EF6F3D09AA ++:103CC0003DFF6662666E0009FFFF00FF00FF000116 ++:103CD000FEFF4F4F4FFF1C1C1C7C0000000024FF08 ++:103CE000FFFF00000000F0F40024000000000000CE ++:103CF000000000000000000000240024000000007C ++:103D000000FF427E000000003C3CFFFF3034FFFF1C ++:103D10006666FFFF000000000000000000000000D9 ++:103D20007E7081849FFF2000000000FF06F606F6EB ++:103D300018187E7E7EFFFEFF3C7EFFFF60606F6F87 ++:103D40003C003CFF6662666E0000FFF660F900FF13 ++:103D50000001FEFF000000B01818187E08000000E7 ++:103D600024FFF4FF000000000024002400000000F5 ++:103D7000000000000000000000000024F0F400003B ++:103D800000006666427E00000000663C00FF0024E2 ++:103D9000FFFF6466FFFF000000004000266603008E ++:103DA00003007E7E81811C3C83C3000000000086EE ++:103DB00070B0009800000082000109B00000008689 ++:103DC000007100B80000008600E008B00000008626 ++:103DD000006108B00000000000740030000005849D ++:103DE000004109B90000000600610830000500002C ++:103DF000A0865060A8B00085A0865060A8B8008555 ++:103E000000000000080900A50186006108B9001043 ++:103E1000008600E108B000000086007008900000F5 ++:103E2000A00650810890486000C7006100B05100B2 ++:103E30007D7F282F00C33CFF0200800003033F3F2B ++:103E4000F5A0F5A0551E551E000000003C17FF17F9 ++:103E500000000000000500000000F0F000FF00007E ++:103E600000000000CFCFAFAF0000000000FF000057 ++:103E70000000AAAAAAAAFFFFFFFFFF0000FF557DCE ++:103E80005F7F00000000000000003C000B0F0C30C2 ++:103E90005555FCC0ABBF000000000FFF0FFF3C3CBE ++:103EA0001E1E0000000000000000AAFFAAFF14C3AD ++:103EB00003007D7D28280ACB3EFF00000000003C67 ++:103EC000003C28282828001E001E000000000017C3 ++:103ED000C31700000000000000000000F0F000FF29 ++:103EE0000000000000000C0C05050000000000FFB1 ++:103EF00000000000A0A0A0A040403330F0F00F0F61 ++:103F0000003C0F3F00000000000000003C001F0FBD ++:103F1000FC3F5555FCC0A8808A0AAAAA0FFF0FFFD4 ++:103F20000F0F1E1EFB04000004005155AAA8AA2270 ++:103F300014000300FF3C003CFC05FCF5000041417F ++:103F4000553C0FFF00000000417D3F3F0000000096 ++:103F50000000000000000000000000000000F0F081 ++:103F60000F0F000040008000000000000000000073 ++:103F70000F0F00000000FFFFFFFF00000F0F000009 ++:103F800000000C0C03030000000000000000FFFF15 ++:103F9000FFFF5555545700000000FFFFFFFFD7FFFC ++:103FA000DFFF0000000000F000000000EBEBFFFF6F ++:103FB000BA30D4C00028F0FFF0FFFC05FCF510007B ++:103FC0000000553C0F0000000000417D030300008D ++:103FD00000000000000000000000000000000000E1 ++:103FE000F0F00F0F000000000000000000000000D3 ++:103FF00000000F0F00000000FFBAFFBA00000F0F13 ++:1040000000000000000000000000000000000000B0 ++:10401000FEFCBE3C5457555500000000B0F00000B7 ++:10402000D7FFDFFF000000000070008000F0FFFFFE ++:10403000BA30BA301400032B02000200000000C0A6 ++:10404000200404000200000000000000820020881C ++:1040500080880001210000900000040000009120F1 ++:10406000050000088410040808000200030004048E ++:10407000820000002002110800400020840141005D ++:10408000040004200420A0018811A0000440212085 ++:10409000840000A100004000009000000402021013 ++:1040A000000002840300030084C0000000A00000A0 ++:1040B0002108000021022108000500000000000086 ++:1040C000000002800000000000000000000004006A ++:1040D00000002000A00420000000000000000000FC ++:1040E0000480000000000300C10011001100100056 ++:1040F0000080110000000080008000C08480024029 ++:104100000000000005808580094003A009001080A0 ++:1041100010800800002000000100000000000000E6 ++:104120000100000000000000000020000000000965 ++:10413000000082C0000000000400C0888004000469 ++:10414000000402040000000004010001002000003F ++:1041500000000000210000A0000000000008000096 ++:1041600000000000004000000000000000000040CF ++:1041700085000020000200010800000000C00001CE ++:1041800011400000800100000040000120010000FB ++:1041900080000001009080A10000000100848000E8 ++:1041A000040202000008001000000020200000842B ++:1041B00080048000000180000000800080004080BA ++:1041C00000900084108000000000014000209080DA ++:1041D000041100000000000000200008000800900A ++:1041E00000200000020800800000000800110021EB ++:1041F00000A10200100000A10004A11100000000B5 ++:104200000004209090400204000000110010C12022 ++:1042100000032021004000001010000004100000E6 ++:104220000821031001058200008000000421910094 ++:1042300000090202024100200400A0000400040062 ++:1042400000000000892009000008020000020000B0 ++:1042500000A000011000800000C0000008A0004085 ++:1042600000C020A080008400004080A080908000DA ++:104270000084804000C00084000000400000002056 ++:104280000000002002040005008880410040080270 ++:1042900082044040040080904110020204050002A4 ++:1042A0008008038200C00040000200C021A000205E ++:1042B00020A000C005000010020200000082008261 ++:1042C0000000100508001000201000800100001000 ++:1042D000001000402004100002210805000801021F ++:1042E00000000004011020100541008004050411A5 ++:1042F0000405001002880810000900008240020036 ++:10430000000000400008038200A0024120200000BD ++:10431000C100050910000900080908000100094052 ++:104320008405020900028220101140110041840519 ++:104330008480111084098409000011050000C01157 ++:10434000C00000214000009008411040032000A060 ++:104350000000908500840400040088A00300000091 ++:1043600000000000030000000301C0008040902016 ++:1043700010219020404008001001020000000000C1 ++:1043800002000000000000008000001021910000E9 ++:104390002000200020000010000000C020000808BD ++:1043A000020008014101080000041040040003005D ++:1043B00002200440050005000200100000408000BB ++:1043C00080400088008488000000101000001080E9 ++:1043D0000040000002020000410001000400001043 ++:1043E0000010000000001000000084042000028083 ++:1043F0000280108805800180840000108400840001 ++:104400000000080000000040000040009010002064 ++:10441000000001000100090982800000A011850050 ++:10442000028082410820002000000080A08021003E ++:104430000009000301A100001000100900000000A5 ++:104440000440020004000000000010080400000204 ++:1044500000850000000841028284082003A00004B7 ++:1044600000011082090041000000000008C0801017 ++:104470001001042004108420008440C00340400048 ++:1044800000200040408441000000401000410040F6 ++:10449000050040082085201004408982A010A0203B ++:1044A00020851101088888C010030002200204C082 ++:1044B00000110502034004410000000002000082D8 ++:1044C0004111002100901001000200000841C008C5 ++:1044D00000418440841110210083201000900003CB ++:1044E0000088004000400405000800004010002142 ++:1044F000400000400188011111900005041090C097 ++:1045000000050010400000100021000002200020E3 ++:104510008282000902000120411110830210030869 ++:10452000031005209008A105020800100240910028 ++:1045300083050040C0210000012000099020912047 ++:104540008420840400080021C002004040112000A3 ++:10455000890500000041C190410080A0000800844E ++:104560002004410400830000051000C000004190B9 ++:1045700041A000000000831180208285834000025A ++:1045800004400085408241C0030009000000100083 ++:104590000204008400840400090400C0020020001A ++:1045A00003A010841108100011200400118404825B ++:1045B0000200100010C090C010040282100000021F ++:1045C000001002040984002000A0412000000040E7 ++:1045D000000008100021002004000000040000007A ++:1045E00000000080008000040000200000000000A7 ++:1045F000000000000000000010020480032008807A ++:104600000080008002400000002110000000000037 ++:1046100001000108000808000000840010000000EC ++:1046200001090000900000001000000500000008D3 ++:104630000100A0000000C000080000001000000001 ++:1046400000000000C1000000008000008880000021 ++:1046500010800000008020000000800089800000A1 ++:104660000000000020000000108300848000401142 ++:1046700000080041000005101005001188084041A5 ++:104680000480408008009100908300C00005041160 ++:10469000000009040588898288A104218803410358 ++:1046A0004040038320A10003911120914109118210 ++:1046B0000284051140100803034000008000090037 ++:1046C0000000000041002100000005008500880076 ++:1046D000118001820004104001C002100808A104EA ++:1046E00088400000040001000000008300088200F0 ++:1046F00001000000000000000001082184840988F6 ++:104700000090888285840108824040830084008371 ++:10471000000000000408050384C082852100838412 ++:104720000000C000408201A08284A0909183840890 ++:1047300082C000A0A001050182000000100020003E ++:1047400000000000000090000100000001C0851082 ++:10475000101000C000C0000100080000080410880C ++:10476000820540400002000100020000000000013C ++:1047700000000100010000890100010100000008A3 ++:1047800089A1018441010800000082C001010040AC ++:1047900001000102000040A00903031108200540A8 ++:1047A0001002090104840040A08820A18383834073 ++:1047B000A111C12183020882C003908582010804EF ++:1047C000C00004008301C1008300048810C10100FF ++:1047D0008590A18400030000002000000002000575 ++:1047E0008000000880050080002100000011020008 ++:1047F0001003100020001100404010401003110968 ++:1048000020808810108010408300110084910821BE ++:1048100008001000088000000421A0C0048283A0CA ++:1048200021A08385042103C0401183001183C1119D ++:104830004000C003C0059080008080A00020804020 ++:10484000800080000000890508041000000089082D ++:1048500005118200118905200011C004A004000484 ++:1048600000800400A0008080008009000800800013 ++:104870000541801080200904104000401100901074 ++:10488000050220048080110800820020C021004120 ++:1048900004050041C102830900008284888220C08F ++:1048A000A00540A100038503048883410221110271 ++:1048B0000808001100A0204182031108210005C052 ++:1048C00020410000410002000000800000000300C1 ++:1048D00000000002008541210005A00005019100B3 ++:1048E00000009008000809108208041000A00104CC ++:1048F0000804C00020019001000000000001000039 ++:1049000008010120414084840490C0849085020302 ++:10491000080200000000900091000000044005A083 ++:10492000830210030005A00485209108830109007B ++:104930000101100108880041C001400120000182EE ++:1049400001088304001001040010840404C0002046 ++:104950000020000000820840A04000400088009035 ++:1049600000000000821084824100C0880040008462 ++:10497000000000000084008400000000000001002E ++:104980000100000085008888090110C04010C0A106 ++:104990008821C000C1040490A083A001000011413F ++:1049A00020049182030983C183910483008900A0BC ++:1049B000A09001018440824141908500880100055A ++:1049C00000840000000200000000000000029001CE ++:1049D0008800100010101104C009100188C00000E8 ++:1049E00000000000000003402080A000880000803C ++:1049F000000000000000008000040010000008001B ++:104A0000111108404000900005C00804898300800F ++:104A1000008200400000838091040821800800008B ++:104A20008503088408829103A1A00808831040032D ++:104A30000311A12102401100828285880208112001 ++:104A40004190110003004000001100000000000030 ++:104A5000000300208008808003101104031083806D ++:104A600000880013C200000006420013C200424149 ++:104A700000000013C200000000000013C2000A8101 ++:104A80000042000BC20000420000001300000000C2 ++:104A900000000000C200008100000022C2000041AE ++:104AA000000000000004C20082900000001010000E ++:104AB0000A8800000010010007C400000008000080 ++:104AC0002100000000420100810011000013440099 ++:104AD000000000000042440042000000000B010002 ++:104AE000000000000000800000005F5F303FFFFF1B ++:104AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF20089C ++:104B0000100400C041C13C3C0303555F7D7F141479 ++:104B100014140000000005002D00FFFFFFFF552DBD ++:104B2000FF2D0000000002430F3F5F7F00010000E7 ++:104B30000000000000C2000200000000F8F830F0A1 ++:104B400028BE5F5F043C343C41557D5500000000A9 ++:104B500000000000000000000000000004AE404023 ++:104B6000585800A000000000000000005050303FE6 ++:104B7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:104B8000800240010000414100000303000F3C3F50 ++:104B900000000F0F00000000FFFAFFD200FF0F0F10 ++:104BA000002DAA2D00000000CBDF003C557D010147 ++:104BB0000100000000E10000000000000A0330F8DE ++:104BC000303028BE0F0F040034000014FFD700005F ++:104BD00000000000000000000000000000000404CD ++:104BE000EA40080800A00000000000000000FFFFED ++:104BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF69005A ++:104C0000FFFF22110000EBC328000000A000FFFFFF ++:104C1000FFBAFCFCF5BC00000000F0F03C3C0F0FBC ++:104C2000FFBEFFFFFFFF0000D7C3D7C38200808015 ++:104C3000404000C0008700000000020000000200A9 ++:104C40003F1D1D0C8BEB8B8B3C3C000000000000DB ++:104C5000000000000000FFFF000000002828F0F026 ++:104C600000000000AAFAAAF80000000000000000FE ++:104C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:104C80000069FFFF0000221128002800003C003CC2 ++:104C9000FFFFFF30C3C2C3C300000000AAAAFF0089 ++:104CA000F0F0FFBEFFFFFFFE0000D7C3D5C08200BB ++:104CB0000000000000000000000080008200820070 ++:104CC00002003F1D1D0C828B82822C202C200000B4 ++:104CD0000000000000000000FFFF00000000282886 ++:104CE000000000000000AAF8AAF2A08450F4A8B8BE ++:104CF0000005A08609E501B00800A0865070A0B0AC ++:104D00000805A0C450E108B0000000965265A0B8A4 ++:104D1000A085008600E000B000800086006008B832 ++:104D2000008505840A7008B800000000A086527152 ++:104D3000A0B000850080001100B000000086007067 ++:104D400000B000000186000000890080008670E04D ++:104D500000B800000086006103A00000008600602B ++:104D600000900000058600C00880000500000000DB ++:104D700000000000ACACFF0F55553C3C00000000AB ++:104D80003C3C0000000000000000000000000000AB ++:104D900000000000BEBEAAAA000000000000000043 ++:104DA0000CFF5DFF00000000000000000000FFFF9E ++:104DB00000000F5F3F5FF0FF55FF0F0F0F0FAAAA14 ++:104DC000AA3C00000000FCFCFF3C5C5C3C3C00009A ++:104DD0000000555500000000000028280000FFF8E2 ++:104DE000F8F88E828E82FEBEFAAAAEFF5DFF00004A ++:104DF000000000000000ACACF00000FF0F0F00004E ++:104E000000003C2C1000000000000000000000002A ++:104E1000000000000000BC3CA0000000800010006A ++:104E200000000C0C5D5D10000000000000000000A0 ++:104E3000FFFE00000F0A030AF0FF00FF7F3FFF3F65 ++:104E40003C3CAA3C000000000C0C003C5C5C55554E ++:104E50000000000000FF0F0F000000002F280F00CF ++:104E6000FF2828280C000C00FC3CF0005100A20098 ++:104E7000FF10000000000000F03C003C3C55FF0F1C ++:104E80000000000000000000FFAA00000000000079 ++:104E900000000000000000000000000055FF55FF6A ++:104EA000C300F2F00C0C0303FF00F0FF0000000051 ++:104EB00000007D7D0D0D3C550FFFAAAAFF00FFFFEE ++:104EC000FFFFAA3CACACAAFFF0FFFF3CFFF03CFFA9 ++:104ED0003F3F00000000AAC0553F00000000FFFF58 ++:104EE0000082000000000F5F3F7FEFFF10005AA517 ++:104EF0005AA5FF10001000000000F00000003C5513 ++:104F0000000F0000000000000000FFAA5500000094 ++:104F1000000000000000000000000000100055FF2D ++:104F200055FFC30082000C0C03030000F0000000DA ++:104F300000000000007D000D3C550F00FFFFFFFF4B ++:104F400055557FFFAA3CACAC0055000FC3000F00C5 ++:104F50003C00303000000000AACF553000000000B7 ++:104F60004F0F00820000000000553C7DFDFF020055 ++:104F700000FF00FF04001100030005A021404100D4 ++:104F80001100040021001100000041102000210048 ++:104F900011A01100090000A01190041021000010C0 ++:104FA0000400040000002100000011000020021095 ++:104FB00004000490000005000200040009900400B1 ++:104FC000000041000820030011000000200800003C ++:104FD000020002201100029004000088000000007E ++:104FE000200021000410119000000084000008102F ++:104FF000000000A00010900004000000004090009D ++:105000000000000000000400000084000400040010 ++:1050100000002000000020009000000000000200BE ++:1050200020000000C000040000090000040000008F ++:1050300000000000C000000000000000A0002010E0 ++:10504000000082000000000000000000C0002000FE ++:10505000000000000000001090002000001100007F ++:10506000100010000000A020000000000000000060 ++:105070000000000000000000000000000000000030 ++:105080000000000000200000000000000000000000 ++:105090000000000000000000000000A00020000050 ++:1050A0000000000000400000000000880000000038 ++:1050B00000000000000000000000000000C0000030 ++:1050C00000000082000000820020000000000010AC ++:1050D000000000000000008400200000000000A08C ++:1050E00000000000000000000000000000000000C0 ++:1050F000000000000000002000000000001004007C ++:10510000001100100040000000000011001100001C ++:10511000001000000000000000100041000202200A ++:1051200000200010040000110041000000000041B8 ++:1051300002210008002000000008000002410000D9 ++:1051400000000021022100030020001000000010D8 ++:105150008200001002090010002100000020020857 ++:10516000A000002000210000000900020000000251 ++:10517000001000100000000800410041201041080C ++:1051800041904100000000400000000000000000CD ++:1051900000104140000210002000000000000084C8 ++:1051A000044000000000000004104000000005085A ++:1051B0000000004000000090090003000000000013 ++:1051C00011400988000800000300210008040900BC ++:1051D000000040820084410200900200210009008A ++:1051E0004184000210844000008208100040081032 ++:1051F000101011020502210800824100000002097E ++:105200000400020000218800A041A000821000409C ++:105210000220100082410010000000000000000089 ++:105220000840000084051008000082008421C000AE ++:1052300000050440824010108811C008400500009D ++:105240008810841100118241000000118440004048 ++:1052500000401040004104110011C0050220C005AB ++:105260008205A0021040C00210020010C0400800D9 ++:105270000000C01000200008A00000000010000086 ++:10528000210005000584200020901088029008C0AD ++:10529000008210000800022000C0119000000300EE ++:1052A0000504008410A008000090008410904100C4 ++:1052B00000001000050000000000000000000000D9 ++:1052C000000000000500000010100800039010000E ++:1052D00021002000410000001000000000001088A4 ++:1052E00005001090400000000500000000101000B4 ++:1052F00040900000000000000000080000002000B6 ++:105300000000000800110010080000050000A021A6 ++:10531000000000000005C0050800000000100000AB ++:105320000000000000088220C0050000C04100000D ++:1053300000000209000088058808004102000009F9 ++:105340000200000010000000881140090000022146 ++:105350000010A00884000004842108400241A0003D ++:1053600000102000021002008802C020A0040000EB ++:10537000000200110004C000080000008440101169 ++:1053800010001010030200000000001010000500C3 ++:10539000000000004182000000C000002000411019 ++:1053A00000021000000010000000030203000000D3 ++:1053B00000020000040204080000001010000000B9 ++:1053C0000010002000000800090009000040000053 ++:1053D00000000090000800000000000005820000AE ++:1053E0001008030000000002008208000002000014 ++:1053F0000084000000000000000000000000000029 ++:10540000000000000000000000030040400904000C ++:1054100002090240A04182000002C0000021C00930 ++:10542000000090030000002100008411002184414D ++:10543000100000414010884140100005404100111B ++:1054400000008403901100004021C010C005020933 ++:10545000001000050403A0100021000502119002B5 ++:10546000040984410041022184038221004140401B ++:10547000000082090000C000900988008400100923 ++:1054800000108400001000090088108800400010FF ++:1054900000000000100000040000000000C0000038 ++:1054A0000800000040000240100000020000200040 ++:1054B000008809001020004000000000410000406A ++:1054C0000000100000000000000000004100110476 ++:1054D000000009C000000200102000001190000030 ++:1054E0004100218800000020100000002100000081 ++:1054F00000100000008408002000100008000500D3 ++:1055000000000000000020004100020000090040EF ++:1055100010090000C04110100010000000008410AD ++:105520000008000000210000080082100005C000F3 ++:105530001041000000419040000000000000020007 ++:105540000000820000110021C04000000241000064 ++:105550000000002182208411040882000000000362 ++:105560000005C02000000041C0208840000000006D ++:1055700010000000202084110000020004008800B8 ++:10558000082010008420020084001000FFFFFFFFAD ++:10559000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:1055A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:1055B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:1055C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB ++:1055D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB ++:1055E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB ++:1055F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:10560000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00BCEC ++:1056100022200C44801000000A06000060180800D8 ++:105620000200020411000000040004000404000051 ++:105630001100200005040000040004A02100040063 ++:1056400004000000000000000420112004000304F6 ++:10565000042000008000000004000400849000008A ++:105660001004829000A082088410801004000008BA ++:105670000000032003900209200004C004200090D1 ++:1056800000082108030004000404000000020004D4 ++:1056900020A01120000440900440000041100000B0 ++:1056A000000008400480200082000100000001800A ++:1056B000002100000500200500000000000000009F ++:1056C000000021001000000000000080A080000009 ++:1056D0000080008000002000000000000000410069 ++:1056E00000400180410000111080210010002100C5 ++:1056F000000004000490C00000208500010000802C ++:105700000000000000000010000000800000208069 ++:105710000080000000800080000000800000004049 ++:1057200000000000000000C0000000820400802093 ++:105730000020000000000020000100C000A00000C8 ++:1057400000200000000000018000000800000000B0 ++:105750000000000000000040002000C00000000029 ++:10576000000900C000C18003000500020000000322 ++:10577000000000200000800000A000000001802048 ++:105780008000000000008001001000000000000008 ++:1057900000000011000100010000000100A0000055 ++:1057A0000240000004110010001000000000010879 ++:1057B00004A12000001000100010000400210000CF ++:1057C00082000090000000100020042100089000DA ++:1057D000000390200009001000A00000000000203D ++:1057E000001000820000000220820084008800086F ++:1057F00000C00000001090001020000900000020F0 ++:1058000020212008000000000420900000109010CB ++:10581000001002410040001000048210002000210E ++:1058200000000141000000050000850810A00940AB ++:1058300009200011110011000090000100000484F3 ++:1058400004820420040200100308001000110284E6 ++:10585000008400C00010000000000090004021A162 ++:1058600010A01001004000002000A0C08040A00453 ++:10587000204109010001000900C0000000A0020051 ++:1058800005000401001100411010002004200084D4 ++:105890000500214000102100000440A02085208543 ++:1058A000000010001000400000409011048491108E ++:1058B0000090008000200011000000100002000095 ++:1058C000010501000180014100000000000000040A ++:1058D00001100010004000000000000800000085DA ++:1058E00000400110010800850000010011001000B7 ++:1058F0002180834000081040008288008408004016 ++:1059000089210010C120002000A082000000018039 ++:1059100000000000000000400040A0000100012045 ++:105920000110000001000100010000A01000410072 ++:1059300008A11100410000001020000010A000008C ++:105940001000400005000900410000201000100078 ++:10595000100480010400040004000001090010008C ++:105960001000020000018200000000001000100181 ++:105970008001020009011001412010209000410027 ++:1059800009004100040000840900A0890201100000 ++:10599000002000000300040090000040A10010005F ++:1059A000108400000900110021000000A009C005BA ++:1059B000200082200005000300090085000400117A ++:1059C000004000210041C021001010058284000326 ++:1059D00090100080024000000000000000400041E4 ++:1059E000001020000121C040100084090000900038 ++:1059F000C0082008850484040020008010A104054C ++:105A00008204001084080520002184000204004064 ++:105A1000000000058410880001000420824102007B ++:105A200000000800840288110000000400108000BB ++:105A3000000000A0101100008420410088000088B0 ++:105A400000C00020080200084084080008821100FD ++:105A5000008200024108110104001000000200C091 ++:105A600041020040098410C04108C1891020000093 ++:105A700005842011A0050510008908000800840095 ++:105A800002820500800008008008109104050820AB ++:105A900041820388038400000400050000004100E7 ++:105AA0008582880100028388410010000000830085 ++:105AB00020080000000000200000218000000400F9 ++:105AC0000000000000000000880009000000000045 ++:105AD0000000000000000021004000000000000065 ++:105AE0000000000000000000011000C10808008054 ++:105AF00000000800010821840003000400000010D9 ++:105B0000050500100000040000100410000201A0B0 ++:105B1000008000000000000000000000880000007D ++:105B2000000002002004000040000000000000000F ++:105B3000400041A02084202000200084009000200C ++:105B400002200008080000851140008440100288EF ++:105B5000801000C0001003100000000000C0000210 ++:105B6000020404828200880083000540000800824D ++:105B70004100000020044004020010080411041039 ++:105B8000048440080488088420C020408000200845 ++:105B900080841004028420900083000020000240D2 ++:105BA000020004000200200008001004000180210F ++:105BB0000408210500000002828304090041844199 ++:105BC0009080009000000003C004008000050003E6 ++:105BD0000000200310008809880000000041000533 ++:105BE00000000080000020002000080082A10000CA ++:105BF0000000000000000180018005040183832073 ++:105C0000A100A1008291100000418800844020037F ++:105C1000C1912000C080010084204040A00000000D ++:105C200000800000890001000000010010208402B3 ++:105C300010021021840202008200A100038010855E ++:105C4000A020044041088003C004084100210980CD ++:105C500040000400418080008080040000808003B8 ++:105C60008009080800808003000908004040A183E3 ++:105C70000090408502000080C0030909C002A0090D ++:105C8000418300C10285038500059008A003004000 ++:105C900008080920411140410080000000800000F8 ++:105CA00080114120040502410283200900050903F7 ++:105CB0004083832141C00988018421900290000221 ++:105CC000010820A000A101092000820100010000BC ++:105CD00000880082418401100204080800A000042A ++:105CE000088304890021002020914005208241037F ++:105CF00041838409010900400000910101018501EF ++:105D0000410191C1A0852141000800014001090025 ++:105D100000000001410188010101008200400010E3 ++:105D2000000240010801020100010183A0910090DE ++:105D300001C0410509040205000482018400218894 ++:105D40000500080020008900100484004000900134 ++:105D50008800830101008908848504100300040081 ++:105D6000050408002184A0218503020105880300A1 ++:105D700009A0C1000300A00102880000910009836E ++:105D8000C00089200909A10020908508C0040408EA ++:105D900004A1400110901082A1118800020190001E ++:105DA00002000002010001C001030140C001910096 ++:105DB00011048283050040008308850003408202AD ++:105DC00089808800100884008500A10088001100E7 ++:105DD00000031100110208009000040800041000E4 ++:105DE000000089800921410000888309800888001B ++:105DF000100083402011A00091058541000091040E ++:105E0000099080038390C010C0000900901000002A ++:105E1000000000C00008020003840590030400088D ++:105E200000000000000011052000058241800540AF ++:105E30008200A1808089020082002080C10000844D ++:105E400080909182809020028040009003904000DA ++:105E500000020989400900080040808200A000007B ++:105E600000004000008009090008C08900030808FC ++:105E70000000118900030010800220020088000049 ++:105E800009C00004400985032041900304028504F1 ++:105E900008000800038083000904040504204189E8 ++:105EA000000080008500000002082180418041033D ++:105EB000858500910009A185032080A00021A141D2 ++:105EC000200208C1820504890100100820A18889E8 ++:105ED00001880085018408A000900009A0A188899C ++:105EE0000004020204900004009040C1C10300219C ++:105EF0000109889088090089009182088308A0A17F ++:105F0000000091090001000390030108038882A1A9 ++:105F100083A000A000900084C0C091020084000310 ++:105F200004A00000C000850008000121010800084D ++:105F3000859140C0040500A191820101104140C13A ++:105F40009005000204410001008800402000A001EB ++:105F5000C08801900101000000020041880010008B ++:105F60008808020804A0820002C0858883210800F6 ++:105F7000C040838911008501080440908301048496 ++:105F800090020000018941080100049009050409FC ++:105F9000C00040200100001000000182000201103A ++:105FA0000084011002008200900020080500218971 ++:105FB000040210008200A0C1A088089000000085A3 ++:105FC00000010002000380100040008000008009F2 ++:105FD00080020000030805080402028000038020FC ++:105FE0008020000000890000000800808391048860 ++:105FF0008000000083C08400C04000000004100541 ++:106000008491008000002089C180401182000989AC ++:1060100080408003800002091080040010804185C8 ++:10602000110220C1208000050000800000C1030093 ++:1060300085080341820080200091008580000005D2 ++:1060400000850021000000000013C200008800004D ++:106050000013C200000000000000C200068482009D ++:106060000013600021001100001344000000000034 ++:1060700000131000000000000013440000000000A6 ++:10608000001000000A00000000000000C2004200F2 ++:1060900000000022D000004100000042000000414A ++:1060A0000000001002008200000040130000000009 ++:1060B000000000080100000000000042C200006073 ++:1060C00000000000000042000000000080BF00004F ++:1060D00000000000FFFFFFFF2424CF0FFF0F000F81 ++:1060E000000000006E660C000000000000000000D0 ++:1060F000FF000000FC0000000F000000FF00000097 ++:1061000000060006000000000000FFFF6F2F00C324 ++:1061100000000000FFFFFF67FF0366660F0F00002F ++:106120000000B818BDB86FFC60FC00000000000063 ++:106130000000333C6A66C3C33C3C0000000010080A ++:10614000180000000000FFFF6E0C0000000000FFC0 ++:10615000000000000000FFFF666E2424CF0FFF0F39 ++:10616000000F000000000C000C0000000000000008 ++:10617000000099000000FC000000FF000000C300C8 ++:106180000000000600060000400000006F2F6F2F87 ++:10619000000010000000FFFF676703033C3CFF00A6 ++:1061A00000000000B818B8186F0C600C0000000068 ++:1061B000000000003C3C66663C3C00000000000023 ++:1061C00018001800000000006E0C6E0CFFFFFFFFAF ++:1061D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:1061E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:1061F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10620000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10621000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10622000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10623000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10624000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00F468 ++:1062500043930C44801000180A060000906500006B ++:10626000000000000F0FFFFFFFFF00FF00FF60E3D3 ++:1062700060E3FEFEFFFF00000000FCFCFEFC0000EF ++:1062800000000000FFFF000000FF0000B0B00000B1 ++:10629000003C000000FF00F0F000607CFFFF000009 ++:1062A00030000000303000003076000000000000B8 ++:1062B0000000818100000000F6FFF6FF00C33CFFF4 ++:1062C00000000000000000000020006466565696A2 ++:1062D000FFFF020D04080C007E3E8101FFF4000B5D ++:1062E0000000000000001F07F6FFFEFF60FF7CFFBC ++:1062F000606060E3FCFCFFFF000000003C3C7E3C73 ++:106300000000000000000F0F0000000F0000B0B000 ++:10631000000000FF0000000F00F0F000607C607CD7 ++:1063200000003000008100000C0C30306666000078 ++:1063300040000002818300000000F6FEF6FF009F8F ++:1063400060FF0000000000000000000000246666FE ++:106350005656F0F000000404000CBD3D4202FF243C ++:1063600000DBA08600F0A8800000008600210880E5 ++:1063700000000886006008B00000008600800188E8 ++:1063800000850086000101800803C0C7C02130A03D ++:106390004903C0C7C0A130B0430300860A6100B002 ++:1063A00000000000A0865A70A0B900A500860AE18E ++:1063B00000B00080008600E100B00000A18650F12E ++:1063C000A8B000850086002100A00000088600E03B ++:1063D00008B9000000020A310880001000860A6037 ++:1063E00000B80080FFAAFFAA00000000BFBEBFBE29 ++:1063F000FF05FFF50000000005FF0DFFFF00FF0097 ++:1064000020A07FFF2000000000000004FFE3FFA0A9 ++:106410003DFF3DFF0F0FFFBEFFFFFFFFFEBEFC3C39 ++:10642000555DFFFF000000000000000000147F2009 ++:10643000FF0014FF1FFF000000007FFFFFFF0000B0 ++:106440000000141EFFFFFFFFAAEA0000000050003A ++:106450007C3C3C3D000503FC56AA0C3F33CC0000BD ++:106460000000F0F0F0F0FFAAFFAA040001001F14E2 ++:106470001F140505F5F50000000000FF0CFFFE5499 ++:10648000FE5420A07FFF0000000000000000FFA0DD ++:10649000FFA03D3D3DFFF0F0FFBE7FFFFFFFFAAAEA ++:1064A000F000000CFFFF00000082008200000014DA ++:1064B000FD08FF0000FF0FFF000000000FFF0FFFAF ++:1064C000000000000000EBE1FFFFFFFF0000000004 ++:1064D0005000500000050005CF309AAA000033CCD0 ++:1064E00000000000F0F5F0A00000F0E00000006007 ++:1064F000AF3FAF300ACB3EFF000000000C5D5555AA ++:10650000FFF00000003C00FF20000000000000043D ++:10651000000000007FFFFFFFFFBCBCBC58F85DFD22 ++:106520003C3CAA000F3F5F7F000000000000050513 ++:106530000D05FFBCFFA07FFFFFFF000000003C3CFB ++:106540003C3C000000000F550F55C3C300AA5FDF9D ++:106550005FDF00000000000000000C00F7FF04FBFC ++:1065600059592F0F28005F3C0A3C0010F0F0000042 ++:106570000030A03FA0300ACB3EFF000000000C5DC1 ++:106580000000FFFC000C417D00FF00000000000047 ++:106590000000000100005FFFFFFFFFA0A0A008A80F ++:1065A0000DAD00003030003C557D000000000000C3 ++:1065B00000000C00BCBCA0A03CFFFFFF00000000DE ++:1065C0001C3C3C3C000000003C003CFFC3CB00AA4C ++:1065D0005F5F5F5F00000000000000000C00F7FF3D ++:1065E00000FF555528002800AF3C053C044011052C ++:1065F000041004048400020004A00200031004003C ++:106600002020840091000800000904000200110409 ++:106610001100210000881101040411000000020093 ++:10662000002004200000000003100400000004907B ++:10663000040021082100C0048408800821200300F0 ++:1066400011000000040020012000914021020401FB ++:106650008421000002A004401100001011A00020BD ++:10666000002011C00204000411002100112000804C ++:1066700000C09000A0801000000000002100001069 ++:106680000800048004000200000000020000000076 ++:1066900000C1000004000000102000800000020083 ++:1066A000900000000000080000000000A011004061 ++:1066B0000000000000002000058004800408008223 ++:1066C000200008008400001000080100208088805D ++:1066D000C00805A0900000000280000000800000BB ++:1066E0000480008000008291000000000000828091 ++:1066F000001100010001804100A000200000000006 ++:10670000008200018010002100100000001008012C ++:106710000000000000008010000000C100A0000088 ++:106720000000000000200000000000000000000049 ++:1067300000C00000042004C000000001000100218E ++:106740000020000000000000804000000001000068 ++:106750000040100000008040800000008000000128 ++:1067600000A01020000880000000000000002000B1 ++:106770000000022000200220202000030041001021 ++:1067800000210011902004080220000000110011D7 ++:106790000020001100000021204100100004001022 ++:1067A00000210010000000A1020000100041004183 ++:1067B00000100000000000100000901000200040B9 ++:1067C000A02000A0000900000041201000100002DD ++:1067D000001100900121001020A1201120000200D2 ++:1067E0000040001001100090041000110041000052 ++:1067F000010000100301000209A0418800200220CE ++:1068000021090020000020022000002000840090C8 ++:1068100000840040008400000002000400C000105A ++:1068200000840010001000080921008800A00082E8 ++:10683000001000080000041000A000C009000000C3 ++:10684000009000008002000000100440000000A042 ++:1068500020042082A0400000002000A009100010A9 ++:1068600000840020101000840001000304200010A8 ++:10687000800200C000A090400440400084000080DE ++:10688000008000A0848200000111090584A110414C ++:10689000004110000010000300080000009082007A ++:1068A000A000002000401003C00800208200100259 ++:1068B00000050002004000000011C0218805100002 ++:1068C00088028800881004110203880582C18800AC ++:1068D00000400140A1110920000010A11000C000DB ++:1068E00082001000C000000390038220C0A0C1C03D ++:1068F00000000400900090000300200120000884A4 ++:1069000041010000410010000000040141018084A9 ++:106910000000100040104100000082C09000A10063 ++:106920000000000000001000020040002000C10034 ++:10693000030011000310030000000000100010000D ++:1069400008000000008410C00000080010000900CA ++:10695000020002000300100020844100100020000B ++:1069600005000200080008000800002003000001E4 ++:10697000800003004000100480000000A104010911 ++:1069800000000040000000210000000089200020DD ++:106990000441000900000100000500212000200042 ++:1069A00002000000000200000000000000000000E3 ++:1069B00004100010000900218800000000000800F9 ++:1069C00000000000000000090000100800000000A6 ++:1069D0000000A00000000005000001000000000011 ++:1069E0008240C000A12100000005000000800000DE ++:1069F00000080400C00001000080020004A0100094 ++:106A00008005041000820000820080009041000494 ++:106A10000008800400000400009000C000821010F4 ++:106A2000050480C0102010840002004010821082F3 ++:106A30000000032020080002000800A00000410020 ++:106A40000084410003A000012021410291100000B8 ++:106A5000100241101085008420044182058400202A ++:106A60000400030010C000000001050880824100FE ++:106A70000200000410000484C000C10120828510BF ++:106A80000000048401090009101004404020200483 ++:106A90008288400320830010000000104011100085 ++:106AA00000000080100000000040C0110200001132 ++:106AB0000400104100908400100084410010000088 ++:106AC000000084000000A003044084C0A0801040A7 ++:106AD000A00020000011010400110180900200219B ++:106AE0000000030000000021C011A01000210200DE ++:106AF000000001000003000011002100202011000F ++:106B00001100048400040204001000C040844110FD ++:106B100000C04000058241840021051021841040FE ++:106B2000000080840000080200A080010020021004 ++:106B3000028400080911004000082082008241847C ++:106B4000000000C0020002100588000000400200A2 ++:106B50000010001041C021084140200010001082A8 ++:106B600010820010C10090900040004005100910F4 ++:106B70000020008420000205004010A0200020001A ++:106B800003840010010000800180900000000000DC ++:106B9000000004000100000000009004000000005C ++:106BA000018004002000000000100000042000000C ++:106BB0000900020200000020009000000010000008 ++:106BC0000000004000000003000000000000008002 ++:106BD0000005088000000000000008C140000141DD ++:106BE0009100A000000020002000000000800400B0 ++:106BF00000000000000010000008088000000100F4 ++:106C0000010000000800094021414041409080C13E ++:106C1000A1021141800040001000000082804080ED ++:106C20000880410040008000210008000405800821 ++:106C30000808100405000500C10004000000000061 ++:106C4000000000000080800000000000000088823A ++:106C50008541C00908840000000010000000C00346 ++:106C6000852020402000000020000200000000805D ++:106C7000008000000000091040111108004120119F ++:106C8000A020A10303050100210388030102A089BC ++:106C90000820080500C02000C10001000000090212 ++:106CA00084C0019001C00100040000000100000147 ++:106CB00002002100010140009000110000000000CE ++:106CC00000000000000000008200008400000000BE ++:106CD00003408484110200840000C0000100000011 ++:106CE0000501820101000100A000850000000000F4 ++:106CF000008202080000000488010000A0010001D9 ++:106D000000010500C100000108C00900C110090010 ++:106D1000010400A0004001008800C000880000C0FD ++:106D200000000120018800000100000001A0010115 ++:106D3000010000900110000041082100048283003E ++:106D40000000000100000000000000000020000022 ++:106D500000002011C08841A1840400408800A000E8 ++:106D6000400009008400110005C0C1000900A10015 ++:106D7000859000000000C000400800100000008264 ++:106D8000014005100300C0044101000340001080D1 ++:106D90008900200041002004100020000508A00008 ++:106DA00021831100100005082003110004081000C1 ++:106DB00020100200400004C10300910008000200FE ++:106DC0002000000000080000000000000000000596 ++:106DD0000000000003844021A09040894080020010 ++:106DE000200005031120C1008200838010004005AF ++:106DF000A000C103000900000000808000410000E5 ++:106E000000040980918090002000830903C01000D5 ++:106E10002090C04102058803A041C1850000000008 ++:106E20000880808000808083400880A0008800A0C7 ++:106E30000283804020214100102182050090111022 ++:106E400008900008000000000000000000000000A2 ++:106E5000000004048000049008100482020880806E ++:106E60000000000000000240008005000883008050 ++:106E70000000028080000000000080000080080305 ++:106E800004040009104002850403052083830109DE ++:106E9000010804850320018809C0020421890290A9 ++:106EA000000000A002880002020220018209000501 ++:106EB000000901A004C000820120010811A10009FD ++:106EC000018900859089000000000000000000009A ++:106ED000000000820105200082050203C1410891E3 ++:106EE000A002000000A00090010500100190100514 ++:106EF00000400000010202A000C000A0900000823B ++:106F000001000011000811080104008401A010050F ++:106F100084040401400090080040012101000000A9 ++:106F200040218805900102020100000001000100DB ++:106F300000900010000000000000000000010100AF ++:106F40000010000000010020000000000000000010 ++:106F5000000082020083008500008388A120840055 ++:106F600041C000040000000100088320C089C00166 ++:106F7000040504898401A00084C04084840040008A ++:106F800090000340A100080004000002001100006E ++:106F900000C080A080048004000021800904082033 ++:106FA00004000003801000028080030021022003FF ++:106FB0001000000000A1000400004100042121088D ++:106FC00040000082004000020000000000000000BD ++:106FD000000000000080000400210000832005055F ++:106FE000A005A020008300100002008088058340D7 ++:106FF000A10380858803002180208000008000009C ++:1070000000000000030005008000090000C10082AC ++:107010000011000021000013C20042000A0000130A ++:107020000000000000820013C2004200008400063D ++:10703000C200005000880000C200000006000013DB ++:10704000C20000002100001300000000000000004A ++:1070500000000000000000000000000081000000AF ++:107060000042C200000000000000C20000000081D9 ++:107070000000C200825000000013C2008200000025 ++:1070800000210000000000000080C200000000009D ++:107090000080D0000000000000007DFF7D7D15977E ++:1070A0003DBF143FD73F000000000000000000017A ++:1070B0000002000F050F000000005FFF7FFF7D7FD3 ++:1070C000FFFFFFFFFFFF00000000040F0F0F000095 ++:1070D00000000000000000000000000000000000B0 ++:1070E00055553CC31FDFDFDF00000000000000003B ++:1070F00000FF0F0F82820000FFFF00000000000071 ++:107100000000000000000000003C0055000F353575 ++:10711000000000002000270F0000000041FF414157 ++:10712000018329AB1403D703000000000000000016 ++:107130000000000000000505000000005F5F7F7F89 ++:10714000555FFFFF3C7DFFFF0000000004040F0FB0 ++:10715000000000000000000000000000000000002F ++:1071600000000F0F3CC31F1FDF1F000000000000C6 ++:10717000000000FF0F0F14142828FFFF000000007C ++:1071800000000000000000000000003C0055000F5F ++:10719000353500000000FFFB0F1BEBF3EBF3FFFFA7 ++:1071A000F5F000BF00000F0B000000000000FFBA68 ++:1071B000BABA00000000FF30FFBA00000000FFFF75 ++:1071C000FEBEFFFFFFFFFFFFFFFF00000000FFFF0D ++:1071D000FFFF0000000000000000000000000000B1 ++:1071E000000000007DFA7D50BCBCA0A000000000A3 ++:1071F000848484FF00505FFA0000BEBF00000000DE ++:10720000FFFFFFFF00000000000000000000000082 ++:107210000000FFFF5A5A4E5AFDEFA99AAAF0AAF0B1 ++:107220005F0F550040FF00000F1F0000000000002E ++:10723000FF30303000000000FF30FF300000000061 ++:10724000FFFFBEBEFFFFAEBEF828F000000000004A ++:10725000FEBEFC3C0000000000000000000000003A ++:1072600000000000000028FA2850FFBCA0A0000089 ++:107270000000FF8484840050000000F0FEBE000087 ++:107280000000FFFFFFEA0000000000000000000017 ++:1072900000080000FFFF5AD85A5A0210A99A008627 ++:1072A00000E109B00000008602E101B00000A08604 ++:1072B0005035A88000850886006508B0000000866B ++:1072C0005074A8B80005008600E109B000000086EF ++:1072D00000E101B800800000000000000000000094 ++:1072E0000000000000000000058600F108B8000062 ++:1072F0000086006008B0000500860A6C08B900A08E ++:1073000000865020A8B000000084006100B000009A ++:10731000058600E100B00000008600F100B9001011 ++:10732000B8202000FFFFFFFF00000000550F550FA1 ++:10733000FFFFC0C07D3C7D3C000000003030353593 ++:1073400000000000AA0F280C000000001400140028 ++:107350000000000005FF3DFF0000000000000000ED ++:107360000000000000000000000000000000001409 ++:107370000F1F00000000D700D7C3FFFAFFFF14144F ++:10738000141400000000FF00FF00F0F030000000C7 ++:107390003030FECEF2C2A000000000000000141F3A ++:1073A000FFFFB820200010FF15FF00000000003C88 ++:1073B000FF3CFFC0FFC05500FFFF000000000000C1 ++:1073C000050500000000AA0FAA0F0000000000053C ++:1073D00055050000000000FF00FF00000000000055 ++:1073E0000000000000000000000000000014001079 ++:1073F0000014001400000000140014C3FFFAFFFE84 ++:10740000041414140C0C000CFF14EB00F0F02020FA ++:10741000030300003E0E3202A00000000000000046 ++:10742000141F141FCFFCCFFC3C3CFFFF7F757A700C ++:107430000000000000000000AEFEAEFE14140000CC ++:10744000000000000000000000000000000000003C ++:107450000000000000000000555DFFFF000000007C ++:107460000000000000000000000000000000FF7CA1 ++:107470007C7C000017C3000000000F000F0000001C ++:107480000000FFFFFFFF000000009FFF0F6FFFFFE6 ++:10749000FFFFFFFF00FF00000000000000000000F1 ++:1074A000000014FF1FFF00000000555FFFFF2F25A5 ++:1074B0002A2000000000000000000CFC0CFCF4146A ++:1074C000F0000000000000000000000000000000CC ++:1074D00000000000000000000000000CFFFF0000A2 ++:1074E000000000000000000000000000000000009C ++:1074F000FF3C3C3C0000170000000000550055FF19 ++:10750000000000007FFFFFFF0000000090F000601F ++:10751000FF003C3CFFFF00FF0000000000000000F7 ++:107520000000000014141F1FFFFFFFFFFFFFFFFFFD ++:10753000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B ++:10754000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B ++:10755000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B ++:10756000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B ++:10757000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10758000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10759000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:1075A000FFFFFFFFFFFFFFFFFFFF0070BC080C4461 ++:1075B000805000000A0600002409080004000401AD ++:1075C0004004031084200020040400000000000098 ++:1075D000040040001000040011C0000004008020DE ++:1075E000111011001100200002108000009000C056 ++:1075F000020000000400400020080000020000C05B ++:1076000000092120040010110200110100000200F5 ++:10761000020003001100040104002010080040884B ++:10762000C0002000040011100400400011000200FE ++:1076300020000001200003002000000000002000C6 ++:10764000000802800000208084802080000200006A ++:107650000000010000000100000000000005000023 ++:107660000400000000000000000001000200000013 ++:10767000000020000000200090000000000000003A ++:107680004000004084000000012001004020000074 ++:107690000000000000000000004090000100010018 ++:1076A000410004000100000000000000000088000C ++:1076B00000000100000200000000000000000000C7 ++:1076C000000100000001000100000004002000A0F3 ++:1076D00000218000002000000010000100030020B5 ++:1076E00000000010800000C1000000200000000128 ++:1076F000000080A10021000000882000000100C0DF ++:10770000000000C00001004100A0000000A00040F7 ++:10771000A0040020800000110000001000200008DC ++:1077200000008010000000400008000000000088F9 ++:10773000000000030004000000000000000800C07A ++:107740000021000402200020002000108282020894 ++:1077500000100020042100900021A0A10220A0A080 ++:1077600004C1000000084021000404109020A01172 ++:1077700000040241024000840010001001000004D7 ++:10778000000000000221020402A000000008001016 ++:10779000009005800010082000400021902000008B ++:1077A000022100111021C0110080000000210008FA ++:1077B00004208200008800A10020001000100010AA ++:1077C00000210040009000C000844102000400102D ++:1077D00000100082001000032084008400100002CA ++:1077E0008004020280A000A0009000C0008400C0BD ++:1077F0000000008420C000820002000200A000847B ++:107800000010000000C00020008404C08020004060 ++:107810000041400921840310034082102110218877 ++:1078200004200008000200024010000200C0008492 ++:10783000008200880000001000008004004000A0CA ++:1078400000000040820000008400002084080088BE ++:1078500084000003000000058820010000081000DB ++:107860000021400082410403100000210008002193 ++:107870008200C041000801108208000800050000D5 ++:1078800040408400000084000090820210090480BF ++:107890000000100890A084000085841021050000DD ++:1078A0000010001000400441C0020040C021000848 ++:1078B0000400C000040090000200020020800000CC ++:1078C0000800004000400000200000000500800883 ++:1078D00020000800418420820400052041902100FE ++:1078E000030020002000110003000500040900002F ++:1078F00000004100000020000000410020000300C3 ++:107900000300100008000000030004000000040051 ++:107910004000080009011000032020830004020138 ++:1079200000C008002000001009000000000010A1A5 ++:1079300000C020002000030221002084002011004C ++:107940002100050010000800841085008203A010AB ++:107950000800000300030400004183100880A041D8 ++:1079600000008409080500100000000008008920BC ++:107970000811004102000000012108000010C105AB ++:1079800000410005822102100000000001000810E3 ++:10799000010001410800A0080000C080C004008868 ++:1079A000C0040800000009000041004182000003FB ++:1079B00008040005A0000041000000000000004194 ++:1079C000080082000000A00000002082039021082F ++:1079D000030000A000A04088059000C041400302C1 ++:1079E00008200082410008020003400041100910F5 ++:1079F0001000000020841104100800C02010200591 ++:107A000010401140020004001008000000001000A7 ++:107A1000000202044000218503C104020240040266 ++:107A2000000403A0030000A0081041C01040400063 ++:107A30000004000400000000084080840000C088AA ++:107A40002020A11008000390050041000000000064 ++:107A5000C01010008441C000000088000011000028 ++:107A6000001100800005000082212008C0000000F5 ++:107A700000050000000801000090000300000188DC ++:107A800001C00210000000000000900000C00005CE ++:107A90000021002000C001211020882001050000E5 ++:107AA0000105008000050000900901C010400000A1 ++:107AB000010000800085840000110400100000090E ++:107AC0004100899020110009C000C0211021101030 ++:107AD000030020004120000000C01084030000A02B ++:107AE0000810001090000310000041C00000112099 ++:107AF000000005080400100400040904000400004C ++:107B000000840002040090108008000000000000C3 ++:107B10004100100400C0C100038408109020002020 ++:107B200000840484A100008402C005040090028443 ++:107B300020C0000280820010000000000000002031 ++:107B40000200100010041000100010000800800057 ++:107B5000000000000008000082210041C021C04157 ++:107B6000A000820000000200000000000000A00051 ++:107B700090110005000000000080828000A182803A ++:107B80000009C0000800C10920002000C009004110 ++:107B90000000001082800010040500000040114128 ++:107BA000A0000000010008001041010000A18400B5 ++:107BB00005400000208002000000000010000000CE ++:107BC000000088001000880008000000000000008D ++:107BD0000200210900090008100888918209C010DC ++:107BE0004140000000000000000000039111C104AA ++:107BF0000020008880110908000808004108402082 ++:107C0000404008118009008208888003114100214A ++:107C10000340000002028009830440408002000209 ++:107C20000910032000800900008000000989C009B4 ++:107C3000104140040205000809110920000000005D ++:107C40000000000091039100020841020000800042 ++:107C50000800000000000001200000000888410921 ++:107C6000838301880000C000900000000001030031 ++:107C7000A10000010089C008020400050100000104 ++:107C800000010101080002210009000410010001A7 ++:107C90000001010000008901C00108000101880005 ++:107CA000840089000001888201A000040010008285 ++:107CB00020A1850501000101040000000101000070 ++:107CC000000000000000910191000100010000008F ++:107CD000C00000000000010000890001010009004F ++:107CE0008289888983C10000000000880100820029 ++:107CF0009100890240000400C09088000804C00080 ++:107D00009082C101030004000984110009000100F0 ++:107D10000182018201010000100084002002039111 ++:107D20000890C000081082000001000100000088D7 ++:107D30000401050090A0030905A005824104830108 ++:107D40000100010001000000910091008900830002 ++:107D50000800820008C0A00008001190001009006F ++:107D6000C00904828010898500000000000009001D ++:107D70000000910089800504000880408011000403 ++:107D800000000880A020890008000800080489007D ++:107D90000200418021800303000088118900020055 ++:107DA000891180008000808080090010000400009C ++:107DB000001109024100400090098200C080211199 ++:107DC00083090800410010004121910091008900C1 ++:107DD0008300800000000000004108400003000212 ++:107DE000C00002000020900911090000218000005D ++:107DF00000001000000040809180200080000400FE ++:107E000008800820000409A04000020200820489C2 ++:107E1000889103020004030200030080049010090B ++:107E200040090840208810800000088380800000FE ++:107E30009000008002020040C08910100340112011 ++:107E4000218911400000000000000000409100A1C5 ++:107E500000A1C08300000000050000000100000038 ++:107E60000001830001C08841A003880200040008CB ++:107E7000000420A00182000400A0898201040804FB ++:107E80000808088800410009008501A021A0900988 ++:107E9000A0A1888201010001010100010080000908 ++:107EA0000120009121C001900188000290C1821040 ++:107EB0001090A140108201910088908501830103F8 ++:107EC000000900850805000000000000080001917D ++:107ED00000A100A1898300040082010800080110AC ++:107EE00001410000010041018891000001080000EB ++:107EF0000000000000000004000100010088831160 ++:107F000089000900091001080005010101400088ED ++:107F10000108000000100182010001110000008032 ++:107F20008211820888010890000000A000000088EB ++:107F30008802002090008800040010C1200040103A ++:107F400001A0018500010004000000010000000103 ++:107F500000910001000100880001000000000008FD ++:107F60004000081040000800100389084005080080 ++:107F70000000000900110000000400410002008020 ++:107F80001003C100900090800909000840400400DF ++:107F900020820404080811000380040002834010BA ++:107FA00000808083001100400000000900000000F4 ++:107FB0000080008000008000000080118002000529 ++:107FC00080800800401120401180000000410041E5 ++:107FD0000008009100410002008000200000000025 ++:107FE000000000410013C200004182410013C200A2 ++:107FF000118182000013C200000000000013C200C3 ++:108000000000810000130000820000840000C20014 ++:10801000820000600013C200000000000000810028 ++:108020001242000081820013C200420000000010D2 ++:1080300000000000810000138100410000000013D7 ++:10804000C200000000000022C20021000000000069 ++:108050000000000000000013C2000000000000004B ++:1080600000000000FFFF7F7C1E181E18FF7FFF67C7 ++:10807000FFF0FF0000000000000000000000000012 ++:10808000000000006F7E097E00000000FFFF00007E ++:1080900066F666F6FF00FF00FF006F0000000000BC ++:1080A000000000000000000000007F107F100000B2 ++:1080B00000003C3CC3C300000000000000000000C2 ++:1080C00000003636360042424F42090009000000E7 ++:1080D000000000000000000000006F6F6A660000F2 ++:1080E00000000000000000004340060006000019E8 ++:1080F00000016F60FF0000000000000000000000B1 ++:108100000000000000006F180918000000007676DB ++:10811000101066366636FE807E00FF007F1000007D ++:10812000000000000000000000000000FF906F0051 ++:10813000000000000000FFFF000000000000000041 ++:1081400000000000C9C9C9007E7E7F7E09000801C9 ++:108150000000000000000000000000006B6E62667E ++:10816000000000000000000000000000000000000F ++:1081700000000000000000000000000000000000FF ++:1081800000000000000000000000000000000000EF ++:1081900000000000000000000000000000000000DF ++:1081A0008210020000218440000000000000000056 ++:1081B00000000000000000000000000000000000BF ++:1081C00000000000000000000000000000000000AF ++:1081D000000000000000000000000000000000009F ++:1081E0000000000000000000000089FF80FFC2C204 ++:1081F000FEFE02FE00FF8080BFBF0000000066663A ++:1082000066666630FFFF00000000907EF67E00008C ++:108210000000666666660000F0FF00FF00FF0000D9 ++:108220007EFF0000000000000000000000FF00FFD3 ++:108230000600F6FF686EF8FE000000000000000077 ++:108240000000000044CC243C6030663C0000F0009C ++:108250007D7D3DFE00000000647CE5FD3636F6F6CF ++:1082600000387EFB00000000000000000076007F68 ++:10827000C2C2FEFE02FE06F600003F3F0000000004 ++:108280000000FFFF663000FF000009009018F6189C ++:1082900000000000606360630600F6FF02F200FF6A ++:1082A0008000FEFF00000000000000000000E4E489 ++:1082B00000FF0C00FCFF080E989E0000000000006C ++:1082C00000000000000042C3223390C099C3080898 ++:1082D000F8083C3C3C3C000000004058C1D9363610 ++:1082E000060600343CFF000000000000000000868D ++:1082F00070F500B000000086709401A000000086B8 ++:1083000000E109B00000008604E0000000000086E3 ++:108310000C80018000000086007400B00000008620 ++:1083200000750010000000000000000000000000C8 ++:10833000008600F501B00000008600E100B90000F1 ++:10834000A0865011A1B00005008400F008B0000024 ++:108350000086007100A00010000000000000000076 ++:1083600000060A60000200100086006000B00000F5 ++:108370000000000000000000AA00AA0001000000A8 ++:1083800000000000F0FCF3FF00000000424201C2C8 ++:10839000FCC0FF001400D7FF0000000041E100A076 ++:1083A00000000000FFFF0CFC0000000000000000C7 ++:1083B0000000FFFCFFFF00003C3C0000000000004C ++:1083C00000FFF0F0F0F0003C0C0CFA0AFCFC000F8F ++:1083D0000202000000000014000000000000000085 ++:1083E0000000000000000000FF00000000000C285A ++:1083F0000C000000000000000000FF55AA00000073 ++:10840000000000000000000C030F0000000000004E ++:108410000000BE82FF000C00CFFF0000000041E121 ++:1084200000A00000000000000CFC000000000000A4 ++:1084300000000000FFFCFFFE00001C3C00000000EC ++:108440000000007FF0F0B0B0003C0C0CFA0A0C0CFD ++:10845000000F000000000000040400000000000005 ++:108460000000000000000000FFFB00FB0000000017 ++:108470000C000C000000000000000000F4F40404F4 ++:10848000FFFF437F0000000000000000000000002C ++:1084900004380000FFFF000034F700FF0000000078 ++:1084A0001414BEBE3CA03CA0F3FFF5F50000000094 ++:1084B00000000000000000000000FFFFFFFF0000C0 ++:1084C0000000FFFFFFFF2FFFF00000000000FFF0A3 ++:1084D000F0F02D552DFF00000000FFFC00550000BE ++:1084E00000000000000000000000FAEA05EA0000B9 ++:1084F000000028AF7DAF0000000000000000F5F094 ++:1085000005000F0F437F0000000000000000000086 ++:108510000000003C0000EF2FE02004C700FF000037 ++:10852000000005AF05AF00A000A0F3FFFFFF0000B3 ++:108530000000000000000000000000007FFFFFFFBF ++:10854000000000007FFFC0FF28280000000000009E ++:10855000FFF0FFF02D002DAA00000000FFFC0055E9 ++:10856000000000000000000000000000050500FF02 ++:108570000000000028057D05080020008208910009 ++:108580000020042121202104110004880200200180 ++:10859000040003020400002011000204040004107F ++:1085A00000000200021104000200020011A00300FA ++:1085B00004A020002090A10000000000020003A001 ++:1085C00010A0400402040405100104000310000080 ++:1085D00000000440900000109108030011A0210049 ++:1085E00000000400210002C0020011008000A00071 ++:1085F000A00009001000020021000000010002009C ++:10860000400800C1008400800080200000000000BD ++:108610000420000000C1010004800200208000004E ++:1086200090000000010000040000010005000000AF ++:108630000400000001000100200000000200010011 ++:1086400000008500018001800084012000000000FE ++:1086500000002000908003002000100000000000B7 ++:10866000000020000000000001000000C000040025 ++:108670000400040520008500C00082000000000006 ++:1086800000080008080000000020000000000009A9 ++:10869000000021A100011021000400000090000052 ++:1086A00000010000000000000090800100000200B6 ++:1086B000000000C0800000100000000800C00000A2 ++:1086C0000004000400008020002110200041000070 ++:1086D0000000100000000001000080010000801078 ++:1086E0000000001000000000000000A0800000203A ++:1086F00000210005800000010001000900010220A6 ++:108700008200001000008310001000100209001009 ++:10871000028200002020022002840090004100001C ++:1087200000110004004100210021002102049011E9 ++:1087300002210008002010100020021090200000EC ++:108740000010829000A000104090048403A10084D7 ++:1087500000210041000000200004001010108210D1 ++:1087600002080010004100410041000000412021AA ++:108770000080008400A01010002020200020004075 ++:10878000000000C0004000400000110220000088EE ++:10879000020080C000C08082002000100084001011 ++:1087A00000C00084008400200084200280020400B5 ++:1087B000004000C000C0040200080002000800A041 ++:1087C000000000C000C1002080C0808800A08000A0 ++:1087D00080840584042021200020004000000091B6 ++:1087E00000042040200800910001000000840000E7 ++:1087F00011A0820000218485002103400010001098 ++:1088000080C010410440C00900800408002109090B ++:10881000C0218821400082001008820088210800C1 ++:1088200002000000000004000084882001410211C1 ++:108830000121004000080000014088C000054011EF ++:1088400000100000000510041083201020000021FB ++:1088500004030405824185908890C08200201000A6 ++:10886000A004108001000520000400041021000570 ++:108870000003C0410420100405040084100010030C ++:1088800002000200850003008000020010000500C5 ++:108890000000000002000000200008000301410168 ++:1088A00000000041030010044100200103104100BA ++:1088B00010000500000003008390A00009002000C4 ++:1088C000100104000000000010000502200020003C ++:1088D0000300C10120090000100005002000050070 ++:1088E00002008082200009002000051100004100E4 ++:1088F00010000001100004000200800002000500CA ++:10890000050021004100200010214010110000034B ++:108910001000840002000000100310008200080410 ++:108920000820A00008088200840020088204C010EB ++:1089300000000000084100100010100302000000B9 ++:1089400001000002A10500000005C141C0C10000F6 ++:10895000011082001008A120A0410941000001413E ++:10896000A010000010090103020009050240A01038 ++:108970000005000084400000A10085000400A10063 ++:1089800000000000A000A02100000240040002102E ++:108990000310050010081084000041840084411079 ++:1089A00041104104000000820900208420002002C0 ++:1089B00041822100210021100082408410400240A9 ++:1089C00009C0000400880040000010901100040459 ++:1089D0000904C110A09090049010058810100000A8 ++:1089E00002028002A0030541089000040084418433 ++:1089F000004010404100108804200411112004217F ++:108A0000840041C00440210020000000001000212B ++:108A100040110041042104088410900082030010DA ++:108A2000002100000080000800001004090021104F ++:108A300001409000880000008811101010110400FF ++:108A4000008000100091200288A00040A00040217A ++:108A5000019010002000210021902000000000055E ++:108A60000000001020032004000404000090900087 ++:108A70000010000500000000000900000320900025 ++:108A800001842100821001000009110020002184CE ++:108A900010841121080003A0000820002100081004 ++:108AA0000001410900A004000290102000100410F1 ++:108AB00080000500001000102190080008A0088820 ++:108AC0000201831041A010C004000088000000894A ++:108AD00010000800000904C00490109003822100D7 ++:108AE00000C01010100020C0210002000584218267 ++:108AF0001090100400014100030000C0800010200D ++:108B00002010001000410000000040000801000893 ++:108B100008008200A0C08400000000090005820057 ++:108B20000800884000408200C1000800A180820047 ++:108B3000000002000000C000100002000009000058 ++:108B400000058440400008000040C0008400008010 ++:108B50000004100084000040011001000121000009 ++:108B600090098840C0000003030300001103044083 ++:108B700082030000008510048400822100000200AE ++:108B800088800111000000A0000500000100824063 ++:108B90008003090410200041208989100241030547 ++:108BA0000010802021100408802080098040108857 ++:108BB0000390090941C105110302000909052009B3 ++:108BC0000280400040804000080508094004200958 ++:108BD0000000000488208808000910002000C1005F ++:108BE00000800305C0000409081080838502082066 ++:108BF0000041088000800080000005000000110096 ++:108C0000040000808000090000808085000211407F ++:108C100000404001C1010001000188884111C041AC ++:108C20000088000008010100000088C1408982829C ++:108C3000000991090885010200040101C00100003A ++:108C400000000002C090014001200101C1010100AB ++:108C50000100000088000801090100010008A000CF ++:108C600010040010090109008900000108824085F4 ++:108C70000002000101400084000800080000040018 ++:108C800000000000400840C08804000808890084F3 ++:108C900010010091C00082C0204120008300108894 ++:108CA0008804830188004000840021000800081027 ++:108CB0008820100020009041030141001100C1886C ++:108CC00004108988C0004103C020C0834100880887 ++:108CD000A1010101000000010021010200090110B1 ++:108CE0000000002001880400C0088900418910C0EC ++:108CF00090004190840888A0200111000300020028 ++:108D0000C00005001000011000000110000808005C ++:108D100000C0880084080000008000910002040068 ++:108D200011A09008890500000000A00083048809B4 ++:108D300090808080080000000003900809009005E2 ++:108D400088A00591098410054102000490202000AC ++:108D500091C12141092000000020040408C10941FB ++:108D600011830408098041400403098085104140B3 ++:108D7000820920040400A0110404082085000220B8 ++:108D8000000000080500C10040040211020040116B ++:108D900080090000800580400200000005001100ED ++:108DA0000888008004890910402000041090A00564 ++:108DB000108000C00009208505000080090940845A ++:108DC000088800400009C0000008808400110005E8 ++:108DD000008200020489A002000089800080100047 ++:108DE00040000084041108008000024000C00820F8 ++:108DF0000591200000008884A184002080041009CF ++:108E0000000800900020009000880000840003000B ++:108E1000000040008000000011000110000401C0AB ++:108E20004108014082048205000301110082008490 ++:108E300009C000080009101101890100844010A137 ++:108E40000089890500C000414090000904104008D5 ++:108E5000900900090004008505A00000040800C076 ++:108E600001C005904088090200A08202019000C163 ++:108E7000000905880804840209A0094088009000C0 ++:108E80008301000100100085008500C000A011A032 ++:108E90008910C0040090104004080040018801A01F ++:108EA000010001208241882008000804000100839D ++:108EB00000000040410089A0100004840110000857 ++:108EC000000101000910A008880190041001410070 ++:108ED000080008C0010200A000000140000090024C ++:108EE000400840014000840810219000080008401C ++:108EF00089000401C1104011020582891088C0094F ++:108F000088104000A00800410009000000108410F3 ++:108F10000240C000020011088904C100C0C00382E1 ++:108F20000400200020800303834005052080000802 ++:108F30000091002000800900C040101110800584BD ++:108F40001120080440000880050089404080C1408D ++:108F5000100282042000038510040909208000000B ++:108F60001100050202024100800000880003800019 ++:108F700082408405410220808090008800C08000EB ++:108F8000000900048041008000200088000000806B ++:108F9000800000000005000083002000880002809F ++:108FA00000000013C200000011820013C200110073 ++:108FB00000000008C200420041880013C200008186 ++:108FC00000840021C200420000810004C2000A00A7 ++:108FD000000000130000000000810013C200000028 ++:108FE00000001200001381000000000000100200C9 ++:108FF000008211000013C2002100000000000200E6 ++:1090000000000000000002000000000000008100DD ++:10901000000000000080010000608100001381005A ++:1090200000007171F0F000000000BFBFAFFF00FF53 ++:1090300000FF000000000F0F003CFC00FCFF000FD1 ++:10904000000F3C3C3C3CAAAA00FF503CFFFF437F82 ++:10905000437FCF41CF7D080A080A5C5C5555013D2E ++:1090600083BF000000FF5555000000000000000015 ++:109070005C5C5C5C7F3CFF3C00000000000000008A ++:1090800000FF000000000000081C495D0000000017 ++:1090900055FF0F3C00000000000000000000000031 ++:1090A00000000000717100FF00000000101000506F ++:1090B00014D73CFF000000000000003C0C000CFF37 ++:1090C000000FF0FF0F553C3C000000FF503C00003B ++:1090D000023E023E0C410C7D080A0D0F0CFC00FF05 ++:1090E00000FF00FF00000F0F3C3C000000000000EC ++:1090F00000005C5C5C5C7D3C7D3C0000000200008C ++:10910000000000FF000000000000081C495D000096 ++:10911000000055000F3C00000000000000000300AC ++:109120005555000000000F3C0F0F00000000F2F347 ++:10913000F2F0FFFF0000BEFCBEC0FFFF0000AA006F ++:10914000BE1435353A3AFF00FF00FFFF0000FF0074 ++:10915000FF00FFFC0F0C00000000FEFEAEAEFF0A99 ++:10916000FD08BEFF1400000050001010A0FFA0007A ++:1091700000000000F775B634FFFFBABAC300C3029F ++:10918000ACACACACFA0AFCFC00000000FA0A3808EF ++:1091900000000000FFAA550000000000F0FF3C00A6 ++:1091A000C505C000000000000F3CAAAA0000000096 ++:1091B000703070F0BF8FB08082FC82C0FF0055001D ++:1091C000AA00FA503A3A3535FA0ABE82FFAAFFAA37 ++:1091D000AFAFACACF0FC000C000000000202A2A299 ++:1091E000FF0AFD08FAFF500000005F001C1CA000F1 ++:1091F000A00000000000E361A220BABABABAC3001E ++:10920000C300FF0FF000FA0A0C0C00000000000081 ++:10921000380800000000FFAA550000000000F00020 ++:109220003C0000000000000000000886047108B047 ++:1092300000000086709401A000000086007000B05D ++:1092400004100086009401800080008670750090F4 ++:1092500000000086707500B0000000860C6100B050 ++:1092600000000586007500B000000000A18650F1E6 ++:10927000A1B00005A08650F1A8B80005008600A0A6 ++:1092800009800005A0865070A8B00005A086507027 ++:10929000A8B000850086006008B00000008650F08D ++:1092A000A0B000050586008009A0000500000000B0 ++:1092B000FFFFFFFFFF000C0C00000000000000009B ++:1092C000FFFF3F00EF04EB000303FFFF000000007F ++:1092D0000000FFFFFDD5BC94033FD7D7FEFFFEFF84 ++:1092E0003FBFFFFF00000000171700170000AAAAE9 ++:1092F000FF00000282022F2F282800045554FF008F ++:10930000BF830000FFFFFFFDFFBCDF8FFFFF3F7D3E ++:10931000302800000000000000002F0F0F0FC3C313 ++:10932000C3C32A3FAA3F2D2D2828990099FF00008A ++:109330000000BFBFFF3FFF000C0C0000200000003A ++:109340000000FFFF7D00EF04EB000003FCFF0000C6 ++:10935000000000A05FFAE9C1A880033F1414FEFFDB ++:10936000FE3CFFBFFFFF00000000000000170000F0 ++:10937000F0F03C3C0007D7072F2F2A280000000000 ++:10938000FF00BC80202A757FC3C1C380FFFFFFFFA1 ++:109390003F7D302800000000000000003F0F1F0F3D ++:1093A00002020200AA00A8002D282D28990099FF8A ++:1093B0000000000000900006AABE0014FFFF437FDB ++:1093C00000000000000C00CF3030F0F001FD03FF82 ++:1093D000FFFFFCFF003CCFCF000000003CFF5F5FC1 ++:1093E000EBFC28FC0505000C000000000E5E0E5E84 ++:1093F000000000000000000000007C7C3C3C0000FD ++:1094000000000000000000FF00FFFAFFAFFF00288F ++:109410000000000038380004005500000000FDFD89 ++:10942000FFFD0000BF1F00000000FFAA00AA003CD3 ++:1094300082BE0000000090000600AAFA00500F0F44 ++:10944000437F0000000000140014F330F0F001FD31 ++:1094500003FFFFFAFCFA003C0C0C000000003CFF8C ++:109460005F5FEBC028C00000000C00000000045447 ++:109470000454000000000000000000007C7C3C3C24 ++:109480000000000000000000007F80FFFAF0AF0F36 ++:10949000080800003C0038380000005100000000BF ++:1094A000FFFFFFFD0000B01000000000FF3C003C8B ++:1094B000003C82BE400982828001840000000400DA ++:1094C00021A0020811001100040804000084021009 ++:1094D000040011900300041021100000000002009D ++:1094E000211002A02110000084100500110040008E ++:1094F000030811000000090002000400200800C059 ++:109500000308040080000200200004C002202100A3 ++:1095100040008040119000000010040811009000ED ++:109520000208401000000421042004000420000070 ++:10953000040020010408010221082004400000006A ++:109540000000840001000000000090000000900076 ++:1095500000000000000000008400200090000000D7 ++:1095600000000000050004000200020020000000CE ++:109570002100000000000000000021002000010088 ++:1095800090009000A0000200010000000000208078 ++:109590000000010002800000000004000000040040 ++:1095A000110090800500200001A00180A100018031 ++:1095B000A0000000830820800000000000A100023D ++:1095C0000011009000C10000800000000000009029 ++:1095D0008000008800908000109100A00000000032 ++:1095E000009000000000800800000000000010084B ++:1095F000904000001000020800C0000000080010A9 ++:109600000000000100000000000000000082800057 ++:109610000000000000000002000080000000800048 ++:1096200080010001800100000082000000000000B5 ++:10963000000000000000000000000011000800040D ++:1096400000880420000802100410401100102003BC ++:109650000210101000100210020003200000020887 ++:10966000001000112011021104C10021041000415A ++:109670000111038800100521A11000000008000856 ++:1096800000100011000490110010000000110008EB ++:1096900008219008000000410090002104410000D2 ++:1096A0001010100482400420902182080000200342 ++:1096B000001000100000A0004021900000104104A4 ++:1096C000000403114088000005000202008400002D ++:1096D00080C00040000800C000840040044021C059 ++:1096E00000C00082001000C000A000200010008414 ++:1096F000828209888385400011100020000010A09C ++:10970000008400C02000008300000908008221C0FE ++:109710000010C004891005840085008404C000A0E6 ++:109720000000048200008011004080090020111018 ++:109730000900090900080084000000090021100048 ++:109740000080A090000203050810001008400041AE ++:10975000820502098203A000C00000080802000080 ++:10976000840902408808000590101010C004009081 ++:10977000A0080200C00002401103C00308C100009D ++:109780008221C000C0008500C00410211040C0101C ++:109790008211881105C1044082008420C005110097 ++:1097A0000040A021C108A000100800001088C0A13E ++:1097B000004100008220102110000000004090A015 ++:1097C000C100100010000000020040001000020064 ++:1097D000001005841000100004004100100020213A ++:1097E000000000000300200021000000200008000D ++:1097F0000000900009014000020002000200040085 ++:1098000000000000050000008400040000002000AB ++:109810009000100002A005020500100802200800B8 ++:1098200003202004800002000500020000088408D4 ++:109830000400000100000500800000008300030018 ++:109840008301100900000805000082000021844106 ++:1098500088059010080308109111011102050005F8 ++:10986000008284100011A0000900C003C000C000E5 ++:1098700020410000400000400140C100830003047B ++:10988000A104000088000005080021000100080074 ++:10989000012120001005010020900000108008899F ++:1098A0000021088900C10408200000410000008058 ++:1098B0001100030810041000002020000200100016 ++:1098C000C0000420400221402004021009000000D2 ++:1098D00021020084110810840800090021C01090A2 ++:1098E0004102084000820000414003C005A010C0B2 ++:1098F0000840048808840300414010A1020203A02C ++:10990000051010C1000003A0108402820211021091 ++:10991000A110030400A0828505A0000108000340F7 ++:1099200020830500002010040000008441044089C9 ++:1099300010000320051010C0000110040383000074 ++:109940000000000004200188000041800180822086 ++:109950000021020040000400000084109000A010CC ++:109960000120888010091020A0200090880000218C ++:109970008808041040410021002084C100404100BB ++:109980000010A08284200040821004119100030482 ++:109990008540200000C10008034004000020820030 ++:1099A000000811049000A0089080C00000210090E1 ++:1099B000010810111080C005900082201188C0207D ++:1099C000000300058409099009C0208802900884DA ++:1099D000008820000800050400200984008400207D ++:1099E00090848891A0208010028400C0088410A078 ++:1099F00011840200080020C005A040C088A1021008 ++:109A00000540200000A041080000058400A000A03F ++:109A1000418400A002C002844108044102208588DC ++:109A20001020112000A010000320028400A0088450 ++:109A300041008008A0C009090308118400841108AE ++:109A4000808202888200A10002838200010000005F ++:109A50008241C0001100010000000011000300213C ++:109A600000004011402010801000000000000000A5 ++:109A70008811A04100408440894120408511024066 ++:109A800084400080000000110080008000008205FA ++:109A900000000000000000000000008000C0000086 ++:109AA00040400080020000000005824100000000EC ++:109AB0008400000010800404008802800000100070 ++:109AC00020001000020004000400022091038940DD ++:109AD00002024141218080094000004003042041EE ++:109AE00021410905080320094004411180A00041DB ++:109AF000000000410200C1004000090040100008C1 ++:109B0000041003084088802011910405000009809A ++:109B1000100011004100000009000300008005A1B1 ++:109B20000000111105028380000008004080A08021 ++:109B30000000A0000300A04180048841408510007F ++:109B4000090000000500004100418040000991012A ++:109B5000050100019101008284A1000000C1010003 ++:109B60004000010100009001110000000000888306 ++:109B7000008400000000010082000000000091014C ++:109B8000A000000101010082C021000200C000000D ++:109B90000002010400C000C0880803080108000298 ++:109BA0000182C0A001A100908582108883880104F1 ++:109BB00009888484098800008540400103880004E6 ++:109BC00089000100020000000000000010000000F9 ++:109BD00041001182A1024185A1014089A009080428 ++:109BE0001000820090108500C08890C0408405005D ++:109BF00082C02000A08810000500040889C0090167 ++:109C000008001085100183008901111088081100D7 ++:109C10000000C0000900028410C004C0C00102009E ++:109C20004100040002020301200803000401059022 ++:109C300004080300830089A0091008019040110165 ++:109C4000000000100101008201014110400000905D ++:109C500009008808898021888590024082A1C0403F ++:109C6000A108830004009191900805000504891162 ++:109C70000311000000000008002185008480058099 ++:109C800010200000800880058300100308800080F9 ++:109C90000305000009048200888011800200090485 ++:109CA00003004004A1408200911141801110C102C3 ++:109CB000C09020801002400085009005C0104080B8 ++:109CC0000508040002802004000020042080A00079 ++:109CD0000500880002400011098991034010808826 ++:109CE00021801082021100100284081184054005B1 ++:109CF00040891003080000008000400000400089F7 ++:109D00000090800840C000C008C000910409800491 ++:109D100000A000400080000800C100C10089800050 ++:109D200000001180000000830002A08941A0009083 ++:109D30008009114000A080038003208580A10508D0 ++:109D40000041802140038008034011418000020847 ++:109D500008041000410501A1000301C1910301099C ++:109D6000A09183849110019000110040004182086D ++:109D7000014001844189010002009000000000219F ++:109D800000100084404100400009008408080040A1 ++:109D9000081002C190400080000188C120C1A08944 ++:109DA00082400040048402A000209089A085A08801 ++:109DB0000009C010111010898202A000A11088882B ++:109DC000008900904001A0C18201010100008200D1 ++:109DD0000001010000009001824184C18401A009BA ++:109DE00041C003019100414001000001000000A0BA ++:109DF00001C10004000900080191000800000108E9 ++:109E000000410101000101040100000100010040C6 ++:109E1000208589A0830089880080908484A1900097 ++:109E20009002000100910000001085418401200093 ++:109E3000058485418901A00188C08220880108012C ++:109E40000402210090004101094000000090000040 ++:109E50000000000000000000004084101020C1211C ++:109E60004091404020104010100008094008401068 ++:109E700041000308099105021110400340800400CD ++:109E800011000490404011020800400410410340BA ++:109E900003800585400008001100008000A000201C ++:109EA0000040000000100002000900808310040838 ++:109EB000910211808382881090029002001180101C ++:109EC000804000008311020020104000000000804C ++:109ED00000210000004100030041008000880013C1 ++:109EE00084008200210002218400000000000000A4 ++:109EF0000000420000000013C20042008100001375 ++:109F0000C200060000000013200042000000000014 ++:109F100044000048410000131000420000000050BF ++:109F20000013C200000000000081810041840A503B ++:109F30000013C200000000000081100042008100F8 ++:109F40000013810021000000001300000000000049 ++:109F50000013C200414100000013C20000002404AD ++:109F60000020992409CBFCBC3C3C6E6E0C0C000814 ++:109F70000000FFFFFFFF00000000000000003F6640 ++:109F8000036600000000000000000000FE0E00005C ++:109F9000000043434040FFF3FCF0FF7E99180000AF ++:109FA00000000000000000000000000000000000B1 ++:109FB0000000C0C099009900FE7E03C300000000AD ++:109FC00000000000FC000C006F0910760F0F0F3C22 ++:109FD000000000006F636F63000000000F0F3C3C47 ++:109FE00000000000FF000909C08000006E6E0C0C2C ++:109FF00000080000363636060000000000000000B1 ++:10A000003F6603660000000000000C000000F80836 ++:10A010007E0E7000C300C3000F030C00FF6F990990 ++:10A020000000000000003C2430240000000000007C ++:10A030000000000960699900D940FE7E03C39F3C7F ++:10A04000063C00000000F600F6006F09101066667E ++:10A05000663C000000006C606C60000000000F0FA8 ++:10A060003C3C000000000000000000000000000078 ++:10A0700000000000000000000000C2080400001101 ++:10A0800088610000000000000000000000000000E7 ++:10A0900000000000000000000000000000000000C0 ++:10A0A00000000000000000000000000000000000B0 ++:10A0B00000000000000000000000000000000000A0 ++:10A0C0000000000000000000000000000000000090 ++:10A0D0000000000000000000000000000000000080 ++:10A0E000000000003636CCCCFFFFFFFF81E781E7A0 ++:10A0F000780000004246626600F6C3F600000000E9 ++:10A1000000000000666666660000000000000000B7 ++:10A1100000000000000300000000FFFF30F330F3F8 ++:10A120000303FCFC0000000000000000F100000040 ++:10A1300000000E7E0E0019191F1F00800000000095 ++:10A1400000000000000000000000FBC3FFC300008F ++:10A150000000F3FFF3F00000000000000000C0C0AA ++:10A16000F0F0000000000606BC8CFEFEF2FE006669 ++:10A17000006678780078000420240090C3900000E6 ++:10A18000000000000000C3FF00FF0000000000000E ++:10A1900000003CBCBCBC0000000099996666F3F36B ++:10A1A00030F30303FCFC0000000000000000F0009E ++:10A1B000000000000242020019191F1F00000000E9 ++:10A1C000000000001C049F0600000000E3C3FFC362 ++:10A1D00000780000F3FFF3FF0000000000003030C3 ++:10A1E000C0804040040000000082046508B2008086 ++:10A1F0000084704109B800800186026000B8000048 ++:10A2000005860A6100B900A00084025109B000056A ++:10A210000086006100B0000500860C6000B00010F0 ++:10A220000086026101B0001000000086006508B0E1 ++:10A230000000A0865071A0B0000508860265098064 ++:10A240000000058650A000980080A086008009804C ++:10A250000005058600A000890000A08650F0A8B087 ++:10A260000085008600E0A8B000003CF0AAAA00101B ++:10A2700030100F030B0B414141410000000000AAC8 ++:10A2800000F00000000041414141000000000000DA ++:10A2900000000000000017D7FFFF00000000410091 ++:10A2A0007D00FDFC515543437F7F0000000000000E ++:10A2B000FFFAFFFF000000002DAFAFAF0000BEF0BF ++:10A2C00000D0FFD010405555B0F010007F20FFA007 ++:10A2D000143CD7FF3CFA3C5035353F3F00000000AE ++:10A2E0000000000000000000000000003CF0000042 ++:10A2F00003060C060C0008080000014100000000E5 ++:10A30000282830300000000000010101000000009A ++:10A3100000000000000000001414FFFF0000000017 ++:10A320004D004D00FDFC515503C33FFF0000F0B050 ++:10A33000F000FFFAFFFF0000000005AFAFAF000024 ++:10A3400014F080D0FDD010400000100010007F20DD ++:10A350005F000000FFFF3CFA3C5030303A3A00000A ++:10A3600000000000000000000000000000000000ED ++:10A3700000000A0A5F5F0000FFFF14001455000090 ++:10A3800000000FFF0FFF0000000004045454000001 ++:10A39000FFAA4070000000000000003C00550000D3 ++:10A3A00000003A3FAAFFFFF03C3A2D002D000000CC ++:10A3B000AAAAA8800183018300FF00FC00002AAA4A ++:10A3C000F5A0F5A055555555FFFF3C7D0FF02D78B4 ++:10A3D000FFFFAA0000FF34F700000303F8FDF8FDBB ++:10A3E000000000000000000000000000000000006D ++:10A3F0000000000014BE14BE0041EBFF050505057A ++:10A400000000000004FF0CFF000000000005505594 ++:10A4100000AAFF00417D010D00000000000F000FA9 ++:10A42000000000003035005500F0AA3A28007D00F9 ++:10A430000000AAAA000005AF000000FF00F0000025 ++:10A4400000AAF5A03C3C755555550F0F3C7D3C3C92 ++:10A450002D78F5FFA00000FF04C70000F3F3080DFE ++:10A46000080D0000000000000000000000000404CF ++:10A47000000003008408840011000400910011080A ++:10A4800084002010800004C00200200021C00308C6 ++:10A49000200004000300100011000000040004006C ++:10A4A00021000400000011000411110004400310F9 ++:10A4B0002000000020042000000004A02000001064 ++:10A4C0000090042000112100001000000000000195 ++:10A4D0002000800000000000000000A00402211005 ++:10A4E0001100A000200010000201800011002100D6 ++:10A4F000040020000000118004000210020040004F ++:10A500002000040008031000000001000005000006 ++:10A5100004008900900020000100000010000000ED ++:10A520000200000008000000C000002000000080C1 ++:10A530000480000000000000A000000000000010E7 ++:10A5400000000000A0000002200000000010000039 ++:10A55000001000001000000000000000000001805A ++:10A5600000008200200000000100A1201000A000D7 ++:10A570000000000001000000000000A0200000001A ++:10A580000000000000010000000000000001009039 ++:10A59000000000088020000000000000800000C1D2 ++:10A5A000004000100000000000000000000000005B ++:10A5B00000008000800000C000008000000000005B ++:10A5C000000000000040000800000000000000043F ++:10A5D000000800000000000000000000000000086B ++:10A5E0000001000000000001000000010000000167 ++:10A5F00000010000000000040000820002110100C0 ++:10A6000090110010A0000008000820200010002079 ++:10A6100000100010009010A00000000002001010B8 ++:10A6200000040088000000080009820800100000F3 ++:10A6300000080008080802000000000002100421C1 ++:10A640000010A020002100A00083000000000011E5 ++:10A6500000A1009000110008000040000020000848 ++:10A6600000900020001000210004000200200010D3 ++:10A67000000800200010400000A0020103A103A078 ++:10A6800040A0001011088400001020C0408420A0C9 ++:10A690002120802004000040210005C000A000000F ++:10A6A00021000040402080820008038400C0000890 ++:10A6B000028400C00002080000A100000590000014 ++:10A6C00000002009110200000584001000000000B5 ++:10A6D0000284851000000882009000000008000934 ++:10A6E00003A00008008441000008000404000421C5 ++:10A6F0008400051100020400411000A000200008A1 ++:10A70000A0059108100010211000000083400910DE ++:10A71000851090C14080400040111021C00384008A ++:10A720000020000810108290204100C18400841194 ++:10A7300002908410101082800105000400001000B7 ++:10A740001000C000838420A10021820000C11008F5 ++:10A7500000030010040000038500004110101041A8 ++:10A7600000080000108000210000000000800100AF ++:10A77000118209000008C08082000000C00041086A ++:10A7800010408300100820400383000041020300B2 ++:10A790004108004041A00500412010404000000059 ++:10A7A00004001000208541000500050080000040E5 ++:10A7B00005400900110000014100080000000000F0 ++:10A7C000000010000808C1400000100220400040B6 ++:10A7D00000004188050041002020202010000000DA ++:10A7E0000300000800000400090000001000210020 ++:10A7F00000010200100010002100090000002000EC ++:10A800001080208004000080008000400000008054 ++:10A81000C0000084000000001000008000800000E4 ++:10A8200000000010000010080000000900032000D4 ++:10A830000080008000008800004000000810000038 ++:10A840000000000421001090108000000080001023 ++:10A850002080000000000000000000800080000850 ++:10A860000000000000800000010000000000010066 ++:10A8700000000004010003000100020000000000CD ++:10A880000000200021A041044188418405A00088E7 ++:10A8900005400082100105A0A10041001000004009 ++:10A8A00000C005A010000510884005000304030542 ++:10A8B000000505A000C010080001084000000800C5 ++:10A8C00008030000080008402100A0020000000268 ++:10A8D000080000200000000041081000100010A037 ++:10A8E0008000820000040091000400830500000045 ++:10A8F00000001004000100010301A0000500000099 ++:10A9000010000089012000080080000504030000F9 ++:10A9100010004080A00001088803400382218500C8 ++:10A92000000500200000020000001089840000885B ++:10A93000C08800A010090020C02084200800021058 ++:10A940000005102000C0A0001000001021A19003FD ++:10A9500000801021002100000010100800211100CB ++:10A96000840004080500008010088480C0081003DB ++:10A9700000100021108000040020002005210000AC ++:10A980000000840000400220830405A004A103828B ++:10A9900005A0208408C110849008414005000300F0 ++:10A9A0000384058541A00588080021840582204094 ++:10A9B0002088112010000000020008880000088490 ++:10A9C00041A080A01008000000C00002040200089E ++:10A9D0000040004002400210001020900010414052 ++:10A9E00000C000100284008403400084002000A006 ++:10A9F00000002100201011900220009002854100EB ++:10AA00001188020041000040828004C00000014023 ++:10AA10008800000020000020000011808289C00012 ++:10AA200000000000082000040000000000000008F2 ++:10AA30000000000000800010000001000000000085 ++:10AA4000010000000200000000000000840000007F ++:10AA50000080000000800080000000000000000076 ++:10AA600000000000000000000000000000000000E6 ++:10AA7000000000000000C000000001800000000491 ++:10AA80000000000000000000000000C00941852017 ++:10AA90000088090580A040201020400300112008F4 ++:10AAA0001040C005040320102040090000001000E1 ++:10AAB000090009008980098020008205008820841F ++:10AAC000408584808080000008000000110900A0FB ++:10AAD00003101008040000004100040010004100B1 ++:10AAE00000002000030000002100200000090041B8 ++:10AAF00000044041000000000000050091840909A5 ++:10AB000000084040030080000200050088112190E9 ++:10AB100082A104410091A0A1008900040101040068 ++:10AB2000000001019001050001010100000000008A ++:10AB30000100000088101184004001040911008404 ++:10AB4000000801081082408400820110000000000B ++:10AB50000085000500110000020000000000010057 ++:10AB600001000000000001000000000000000000E3 ++:10AB7000000100000100000000000000000004824D ++:10AB800001A0A0820021A1004000010000000010EF ++:10AB900008410909C1080001009000000140C000FF ++:10ABA000902090110000900489A008048401030003 ++:10ABB0004000100089000500A001880085080300FE ++:10ABC0009084908902041100C100A1008205000058 ++:10ABD0000200100008000208040102000800010041 ++:10ABE0000000000001000101000800C0018901000F ++:10ABF000000000040000000000100100000000013F ++:10AC00000310A00108100808000400000100010161 ++:10AC10000983410490100905112100000020030060 ++:10AC20000900100000100200038040008380C04132 ++:10AC30004000820085004000090403040000C002B7 ++:10AC4000C00403000320050090008500050090402B ++:10AC50000000C1400900410004A010400900880024 ++:10AC6000400000000000050009200380400005218D ++:10AC70001009040002800200410409804100040020 ++:10AC8000030910C004088080804109800000210071 ++:10AC900020099000110010800000C14000082040F1 ++:10ACA000830220A000022089889100090508000085 ++:10ACB00084830040004000090005802110821110AB ++:10ACC00000910305808400C11005008500108011EB ++:10ACD0008090000005C08008008980050010008277 ++:10ACE0000089004100400040001000830003110271 ++:10ACF0001002008304000005000909050002000994 ++:10AD000020100003850583402111200500204020EC ++:10AD100000200000829084024084102008A1C08995 ++:10AD200040C00504014000210141418900C000C12B ++:10AD300000080441000200A00082002182104004AB ++:10AD40008211200888C0C040088409210009A02081 ++:10AD50000803C08900000105100282A040A100C0C4 ++:10AD600000900084000500C0009000010089008868 ++:10AD7000008201088882000000000001100100002C ++:10AD800000000001000082010900C10182010004ED ++:10AD9000019000831090848889401100048810007D ++:10ADA00002000400A10001010103010000C0000035 ++:10ADB00000010000000200A00000000100C04004EB ++:10ADC00004028400400840000310C10090409090AD ++:10ADD000008488009000000010899001100110008C ++:10ADE00082000204100010C00000000000010000FA ++:10ADF000009001010000010001000140010000007D ++:10AE0000000000000000000084014004909084A035 ++:10AE100000020000000100008403400484040200DA ++:10AE20008200110041050800090220852003080066 ++:10AE300009412020034121000011001000050000FD ++:10AE400000090085000500008502C104C010828051 ++:10AE50000089000900040000000080100040800507 ++:10AE600080008010001180090080000000000008B0 ++:10AE70000000410004401005200009000584400442 ++:10AE80000000000000050041000080100084808068 ++:10AE9000808000800000002100000000008181000F ++:10AEA0004181000000814400004800880013C20076 ++:10AEB000000000000013100000000000000000006F ++:10AEC000000000000013810041000000001300009A ++:10AED00000000000000881000000000000000000E9 ++:10AEE000C20000000000000000000000000000138D ++:10AEF000480000000000008100000A00004100132B ++:10AF0000C200000000840004C20000000000001322 ++:10AF1000C200410000000013C2000A00040404AE95 ++:10AF200000000000020243430020002A0000FFFF4F ++:10AF300000FF00FF003C0F3FF0F05F5F00000000EB ++:10AF40000A0FFCFF000000000B08EB280EFE0000BB ++:10AF500000000CCF00000000FFFF99FF0000000080 ++:10AF60000000000F777F00000000051D1D5F00003E ++:10AF7000000000080000BCFFFFFFAAAA088A00002A ++:10AF80000F0F00FF00FF00000000000000C00000E5 ++:10AF90000000000C000C0000000000000000000099 ++:10AFA00000000000000000C300C330203F2A200042 ++:10AFB0007FFF007F80FF00000F0FC0C07F7F000079 ++:10AFC0000000000F3F3F000000000B08000004F4E9 ++:10AFD0000000000055550000000099FFFFFF000031 ++:10AFE000000000000C0F777F000000000000000050 ++:10AFF0000000000000000040BFFFFFFF0000088AC3 ++:10B0000000F00FFF0000F0F000000000000000FF63 ++:10B010000000000000000200000000000400040026 ++:10B020000C0C0C3C8300800082C282C2FFFF000037 ++:10B030007D7D7DF03D3DBFBF555500543410340437 ++:10B0400000000000FE7DBE3C00000000000010106B ++:10B05000000F000A0000030000000000FFDBFFE714 ++:10B060000000FFF3FFC33030FBFB000000000000D6 ++:10B07000000000000000FFFFFF00000000000000D3 ++:10B080000000FFFF00007D71417100000000FFFF24 ++:10B09000FFFFFDFDF8FDE8E8E8E800000000000023 ++:10B0A00000000000000083AF80A082C282823C3C8E ++:10B0B000C3C3282828F0BFBFBFBF55550054341460 ++:10B0C000340400000000FE3CBE3C00000000000014 ++:10B0D000000000C300825000530000000000FF7E0B ++:10B0E000FFBD00003C303C003030FBBA00000000E7 ++:10B0F000000800000000000000FF00000000000049 ++:10B10000F3F2F0F096669666BEB282B200000000DE ++:10B11000047000F0FFFFFAFFE8E8E8E80000000034 ++:10B120003C3CFF00A08652F0A0B000050086026102 ++:10B1300000B0001000860A7500B000800086006133 ++:10B1400000B900050086006000B00000A0865050E5 ++:10B15000A0A0000500860261009004000086006047 ++:10B1600008B0008500000086026008B00005008677 ++:10B17000006000B800800086006108990000008629 ++:10B18000006100B000000086007500B0000000867D ++:10B19000006508B80000A08650F0A8B000850086C1 ++:10B1A000006000B800003F3F3F3F00C303030F00B3 ++:10B1B0000C0C04540000000000000000010000001E ++:10B1C0000000FFFFC3C300000000000010000000EB ++:10B1D00000004100D100FFFFFC0A000000F73F3FE4 ++:10B1E0003F3F0F030F0F0000CFCFA5A545414555A9 ++:10B1F000DCD8E433151515550000000030303F3F12 ++:10B2000000000000004000200000000000000000DE ++:10B2100000000000000000005F5FF6F70000000083 ++:10B2200000000000000020A03F3F3A3000C3414131 ++:10B23000550014140CFC08A80000000000000000D9 ++:10B2400000000000D7CFC3C30000000000001000C2 ++:10B2500002020207D100D700FC0AFC0A000000F736 ++:10B260000C0C3F3F0F000F0C00000FF00FF045419A ++:10B270004555DCD8E4331414145500000000303078 ++:10B280003F3F0000000000400020000000000000E0 ++:10B29000000000000000000000005F5FFBFD0000F8 ++:10B2A000000000000000000020000F000E00000A57 ++:10B2B000F5FF838380800000000000000000000094 ++:10B2C00000000000000003830303000000000C7D69 ++:10B2D000CF7DFF00FF003DFFFFFFFFA0FFA8FEFEA8 ++:10B2E00000FE2E0A99A5F0F03F3F00004B1E4B1EBA ++:10B2F00000000000000000001D3F1D3F0000000096 ++:10B30000000000000000000000000000000000003D ++:10B31000000000000000000000000000FF3CB2B28E ++:10B320004141000000000000000000000C000C0083 ++:10B3300000FA05FF00AF00A00000000000000000C0 ++:10B340000008000800000000838383030000000061 ++:10B350000C41CF410000010105FFFFFFB6A0B6A8D8 ++:10B36000FEFEFEFEAF2E5A99F0003FFF0000E1B452 ++:10B37000E1B400300000000000000C1D0C1D0000B6 ++:10B3800000000000000000000000000000000000BD ++:10B390000000000000000000000000000000C300EA ++:10B3A000B2B2500050000000000000000000210078 ++:10B3B0008200020091002000A1080004C00080006B ++:10B3C00004081100910000009100042011052000E4 ++:10B3D00011000400200000001100200020A0200027 ++:10B3E0000400110003000000040011902000000080 ++:10B3F000000004000400048420A0040020082000B1 ++:10B40000040004000400110000000400000011000A ++:10B4100000000000040000000400410004000000DF ++:10B420002000110020002000000004002000200067 ++:10B4300000002100A100100000000800828011001F ++:10B440000800010084000200000040009085208870 ++:10B45000A000040020000000000000000000A00088 ++:10B4600000000000020000000000200000000000BA ++:10B47000000000000000000090000000A00090000C ++:10B48000A0000000000004000000000020000000F8 ++:10B4900000000000000000000000000000000000AC ++:10B4A0000400000000000000000000002000000078 ++:10B4B000000000000000800000000000000000000C ++:10B4C0000000000000000000000000000000000478 ++:10B4D000000000000000000000000000000000006C ++:10B4E000000000000000000000000000000000005C ++:10B4F00000000080000000000000000000000000CC ++:10B5000000840000000000000000000000000000B7 ++:10B51000000000000000000000000000000000002B ++:10B52000000000000000000000000000000000001B ++:10B5300000000000000000000810000000210000D2 ++:10B5400000080010000000030000002100000011AE ++:10B550000080000000000011002100000000001029 ++:10B56000001000080000000800100010000000108B ++:10B570000010A010000000000004000000100021D6 ++:10B58000001000100010004100000010A01000107A ++:10B59000001000100010000000000000004100003A ++:10B5A00000410041004100000000001000100010A8 ++:10B5B00000100010001021000010030000004000E7 ++:10B5C000201004101001008400008300211000C02E ++:10B5D000A1000491808404A0030003000510000072 ++:10B5E000000000A0111005000000418410000000C0 ++:10B5F0001100100010C00000000000000082410097 ++:10B6000000000000000000000000000000820000B8 ++:10B6100003C01100110009000900000000004100F2 ++:10B620000000000003000000000000000000000017 ++:10B630000000000000000500901100000000C000A4 ++:10B6400084218321011111020000881040000200B2 ++:10B650000008084010201040020990410820040012 ++:10B66000840010008200C000021000001020A040E2 ++:10B67000C0030000824190110000C0110000C00012 ++:10B680008800000000110000000000000009000018 ++:10B690000000C00000000200840000001000C02173 ++:10B6A000100082001000C000000010000000000028 ++:10B6B00000000000C00300030000410005004040FE ++:10B6C000100041002090A000200005004000000074 ++:10B6D0000000000003002000088200002100050097 ++:10B6E000050010000000410000000382410020001E ++:10B6F00041000800000020000000000000000000E1 ++:10B7000000000300410000000540100000000000A0 ++:10B7100004000200000000004100100000000300CF ++:10B7200010000000000009000000410000001000AF ++:10B730001000110000000000020010000000820054 ++:10B74000910000000000821105001000101101009E ++:10B750000021000000000000001000080009820025 ++:10B76000000300000000000082040000000300004D ++:10B7700020000800001000110002000000008800F6 ++:10B780008208000084002000020010400000000039 ++:10B790000000000010000000000000000000002079 ++:10B7A0000000200000000000000000000000000079 ++:10B7B0000000000000000004000000000000000085 ++:10B7C000100003001100008810009000100008C055 ++:10B7D00000A00888100000001000042020110000C4 ++:10B7E0000000000010080010110000000000080018 ++:10B7F0000200000021000300000003000000000020 ++:10B800000000418800400000000000000000080027 ++:10B810000000040000000000000000001100000013 ++:10B820000000100000001088000000000000000070 ++:10B830000000000000000000000000000000000008 ++:10B84000002104410421C002400000030402110051 ++:10B8500000000000112088001000C00001851108C0 ++:10B860000000A010A003900090089000A0111021EB ++:10B87000A010C00090081000900004090021A00052 ++:10B8800000001009C00984118811A00008001040B0 ++:10B8900084110000000000000000000000001020E3 ++:10B8A0009008000900000811A0001003000000002B ++:10B8B000840010001008C008000000000000000014 ++:10B8C000C000119000004100210010880800804055 ++:10B8D000000000081090001000000004001020205C ++:10B8E0001000100000000000000020880000000090 ++:10B8F0000000000000000082004000000000030083 ++:10B900000300000000000000088441000000000067 ++:10B910000000000000000000000010000000000017 ++:10B9200000000000000000000000200000000000F7 ++:10B9300000200000000000000000100000000000D7 ++:10B940000000000000001003100988088221880010 ++:10B9500004008800040804008800904110000000E2 ++:10B9600001809120000000000000000000000000A5 ++:10B9700000000000000000000000000008000000BF ++:10B980000000000000000000C000C040A0008200D5 ++:10B990000800100000404000040082000000002069 ++:10B9A000002010000400040000000000000000005F ++:10B9B0000000000000000000000000000000000087 ++:10B9C00000000000000000008300008083410000B0 ++:10B9D0000300004189888300030000030341000045 ++:10B9E000030000C10900000000000000000000008A ++:10B9F0000000000000000000000000000000000047 ++:10BA00000000000000000000000000000000000036 ++:10BA10000000000000000000000000000000000026 ++:10BA20000000000000000000000000000000000016 ++:10BA30000000000000000000000000000000000006 ++:10BA400000000000000000000082838200C08341EB ++:10BA500000820102024182C0098885820001010141 ++:10BA6000000201A0C0C100000000000000000000B2 ++:10BA700000000000000000000000000000000000C6 ++:10BA800000000000000000000000000000000000B6 ++:10BA900000000000000000000000000000000000A6 ++:10BAA0000000000000000000000000000000000096 ++:10BAB0000000000000000000000000000000000086 ++:10BAC00000000000000000000000820040820083AF ++:10BAD0000000820411820082C0029083838200836E ++:10BAE000C100820003820083010400000000000006 ++:10BAF0000000000000000000000000000000000046 ++:10BB00000000000000000000000000000000000035 ++:10BB10000000000000000000000000000000000025 ++:10BB20000000000000000000000000000000000015 ++:10BB30000000000000000000000000000000000005 ++:10BB40000000000000000000000000000000008075 ++:10BB50000083000000008280008080001083208924 ++:10BB60000083C100090082800083410000000000C2 ++:10BB700000000000000000000000000000000000C5 ++:10BB800000000000000000000000000000000000B5 ++:10BB900000000000000000000000000000000000A5 ++:10BBA0000000000000000000000000000000000095 ++:10BBB0000000000000000000000000000000000085 ++:10BBC0000000000000000000000000000000000273 ++:10BBD000000083C1000000000000802011C100406F ++:10BBE00000008302000000000080800000000000D0 ++:10BBF0000000000000000000000000000000000045 ++:10BC00000000000000000000000000000000000034 ++:10BC10000000000000000000000000000000000024 ++:10BC20000000000000000000000000000000000014 ++:10BC30000000000000000000000000000000000004 ++:10BC400000000000000000000000000000000000F4 ++:10BC50000001008283C10000000000C0828940C151 ++:10BC600000830082838300000000000482820000C1 ++:10BC700000000000000000000000000000000000C4 ++:10BC800000000000000000000000000000000000B4 ++:10BC900000000000000000000000000000000000A4 ++:10BCA0000000000000000000000000000000000094 ++:10BCB0000000000000000000000000000000000084 ++:10BCC0000000000000000000000000000000000074 ++:10BCD0000000834101820183000004400182A183AE ++:10BCE00002A183820101018300004082000401015E ++:10BCF00002C1000000000000000000000000000081 ++:10BD00000000000000000000000000000000000033 ++:10BD10000000000000000000000000000000000023 ++:10BD20000000000000000000000000000000000013 ++:10BD30000000000000000000000000000000000003 ++:10BD400000000000000000000000000000000000F3 ++:10BD5000000000000203048041020000008008800F ++:10BD60009082004002820403028300008080000071 ++:10BD7000024000C0000000000000000000000000C1 ++:10BD800000000000000000000000000000000000B3 ++:10BD900000000000000000000000000000000000A3 ++:10BDA0000000000000000000000000000000000093 ++:10BDB0000000000000000000000000000000000083 ++:10BDC0000000000000000000000000000000000073 ++:10BDD000000000000000000000000000124200000F ++:10BDE00000000000124281480013C200124200000D ++:10BDF00000000000124200000000000000000000EF ++:10BE00000000000000000000000000000000000032 ++:10BE10000000000000000000000000000000000022 ++:10BE20000000000000000000000000000000000012 ++:10BE30000000000000000000000000000000000002 ++:10BE400000000000000000000000000000000000F2 ++:10BE50000000000000000000FFFFFFFFFFFFFFFFEA ++:10BE6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10BE7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10BE8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:10BE9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:10BEA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:10BEB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:10BEC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 ++:10BED000FFFFFFFFFFFFFFFFFFFF00243B8F0C442E ++:10BEE000807000E80A0600006059AEDE0000000025 ++:10BEF0000000000000000000000000000000000042 ++:10BF000000000000000000007B7500000000000041 ++:10BF10000000000000000000000000000000000021 ++:10BF20000000000000000000000000000000000011 ++:10BF30000000000000000000000000000000000001 ++:10BF400000000000000000000000000000000000F1 ++:10BF500000000000000000000000000000000000E1 ++:10BF6000000000000000000000000000067BC00090 ++:10BF7000000000000000008C07000000000000002E ++:10BF800030000000000000000003DE600000000040 ++:10BF900000000000000000000000000000000000A1 ++:10BFA0000000000000000000000000000000000091 ++:10BFB0000000000000000000000000000000000081 ++:10BFC0000000000000000000000000000000000071 ++:10BFD0000000000000000000000000000000000061 ++:10BFE000000000000000000000000000000003004E ++:10BFF000C100100011000300210003000200000036 ++:10C000002100210021002100000010081100000083 ++:10C0100020090300040080A00410040004100000A4 ++:10C02000040021000420030820018000000000001B ++:10C030001100200000000000110004000000200892 ++:10C0400000000300040004000405000000040304D1 ++:10C050000300040011000000000000002100200087 ++:10C06000200000200000000000000000000011007F ++:10C07000000040000100000000000000200001005E ++:10C08000000090002000400000000000210000009F ++:10C09000000300889000002104000080900021002F ++:10C0A0009000820020000080008001042000000039 ++:10C0B000000000000000000000410000000000003F ++:10C0C0000180000000000000000000A000000080CF ++:10C0D00000800000000000000000000000000000E0 ++:10C0E00001000000008000000000000000000000CF ++:10C0F00000000000000000000000000080000000C0 ++:10C1000000000000000000000000000000028000AD ++:10C1100000C00000000000208011000000000000AE ++:10C12000040000000000000000000000000000000B ++:10C13000000000C0004000000000000900000000F6 ++:10C1400000000000000000000002000000000000ED ++:10C150000000040000000082000000000000000059 ++:10C1600000000001000000000000000100010000CC ++:10C1700000010000000000000000A01000000410FA ++:10C1800000080000000000000000001090100000F7 ++:10C1900002100000000000210480042000000010B4 ++:10C1A000000005000011C0109000201000100000D9 ++:10C1B000001000100000008000000000004000009F ++:10C1C00000100041001000000010A000001000103E ++:10C1D000000000100110000000000000000000003E ++:10C1E00000410000000400000010000000200020BA ++:10C1F00000000020001004002000000040C0418426 ++:10C2000000010000058800008400094000000008CB ++:10C21000008400C000401000052083A040C1080039 ++:10C2200005202101210021000882410090A00090FA ++:10C230000900410805840000000010080000050006 ++:10C2400041084100000800A00900000002000008A9 ++:10C25000000000000000A10000000000000000003D ++:10C2600011000000000000000000000000000000BD ++:10C2700000000000001000001000111182000000FA ++:10C2800000080002000010000000100010831000E1 ++:10C2900000008400C00000000100009104000108BB ++:10C2A000110000800040C0000000010000000400F8 ++:10C2B00000000000000084080000901100800000D1 ++:10C2C00000000000000000910000000000000109D3 ++:10C2D000008000400000000002000000000000009C ++:10C2E00000000000000000000040000000400011BD ++:10C2F000001000000000000000001000040090008A ++:10C3000002000900C100410020004100200003009C ++:10C3100000000000C00041000201C10010008301C4 ++:10C3200000000000410083000200410041001000B5 ++:10C330001000030003000000090000000500800059 ++:10C34000410010200200040004010000000003006E ++:10C350002100030100000000000021011000410045 ++:10C360001000000000000300050010000000900114 ++:10C370000000040010000500210010008900841056 ++:10C38000410085200002040000000508C000A02034 ++:10C3900000000020A0414120004101404000014137 ++:10C3A000102004000000020004058300C000000506 ++:10C3B00020000100000000000200820800000000D0 ++:10C3C000020088000000910000002040C000000032 ++:10C3D0000200000000080000000000000002000051 ++:10C3E0000000010000001000820082000008C00070 ++:10C3F0000408C000010082000000000000004100AD ++:10C4000002C10040000000400020418441A100889A ++:10C410000985412041010400210800002100C000DD ++:10C420000408040004400884000041100089210031 ++:10C43000410005A00300000003821000020000007C ++:10C44000020182A0028840000588028810001000C6 ++:10C4500004001000000020A09001108800002101BD ++:10C460000000000010004100000010002100A100A9 ++:10C4700000000400030010840020008800840000F5 ++:10C480000000010410008400102100A184000002BB ++:10C49000840000408480082000000000100010107C ++:10C4A0004100018011000100830000009000C040A5 ++:10C4B0000000820000000000104004008400110011 ++:10C4C00000C0C14011400100010500090100004009 ++:10C4D00000000000A000000001000420040088000B ++:10C4E0000020820000000100001100000000000098 ++:10C4F00004000000010000000000008000000000B7 ++:10C50000000004090310080202A020200501100009 ++:10C5100005040010211000C08021208210000000BE ++:10C520008000100190008400842005100011052077 ++:10C5300000000400400041C0200005000000004051 ++:10C5400003080000410000410409000041900090F0 ++:10C550004000804003002004000410900000000010 ++:10C5600000000040000000000300009000000300F5 ++:10C5700003004100C10103011000850904200000EF ++:10C5800000210000008888030080200000000020B7 ++:10C5900002050080C000C005A0000240000082002B ++:10C5A000C0000211C004100021002100008084900E ++:10C5B0000080840000000420000000000000C00093 ++:10C5C000000084C10000000000881088000090086E ++:10C5D0000420040002840000000010001108200064 ++:10C5E0000011000000C0000000000000000000007A ++:10C5F0000000000000001008820882001082018004 ++:10C60000000000A00000050802020308410804051C ++:10C61000000008410810000502104121000511002A ++:10C62000800021000800400302084140044000004F ++:10C630000000400000000000000020000000400555 ++:10C6400000091020000800000489020440842089A9 ++:10C65000410021802000418000000000090000000E ++:10C660008983088011834189030000000000400095 ++:10C6700011000000000009008003000411110008EF ++:10C68000008000800280000001018901000001019A ++:10C690000000040001000101000040000100000052 ++:10C6A00000008200000000000901080105010001EE ++:10C6B00000000200910000000000080000000000DF ++:10C6C000010190010101000100000008009001C07B ++:10C6D00001080082904001040104000000000000F5 ++:10C6E0000000898382C0000401890100000000006D ++:10C6F000010000000000000001008401A001010011 ++:10C7000000010088A08400880090020008040491C1 ++:10C710004088000100400001001040010000A00816 ++:10C72000408340000000A0009001040109008389BB ++:10C730000010C082A000A082820100000000010061 ++:10C74000000000000100000000000000C100050022 ++:10C75000A10002A1C000010009C08408410020001E ++:10C76000A00085010200A0841103A10000000000C8 ++:10C77000000000000100010000000000C101C182B2 ++:10C78000A091A0820001C00088008404C0058380BD ++:10C7900082880000004005904005208200080300C8 ++:10C7A0008380C0A020000200850004050011100055 ++:10C7B00005050880008000008080800504000400DA ++:10C7C00010000900000040004100020000002005A8 ++:10C7D000850085002005080308008500A141A00010 ++:10C7E00084004100C0080800080002411003000056 ++:10C7F000000000000000110040000400400010058F ++:10C800000280080811800020000080008000088855 ++:10C81000004000880088202000A1008509901000B9 ++:10C8200000000000058000C000A000028005040296 ++:10C8300000852120C0090000110000800080000058 ++:10C8400000000080808040400082200900850000B8 ++:10C85000020500850090830300C0800490218000C1 ++:10C8600000800000000000000221000509A10389EA ++:10C8700000040010000200110008000811210090BF ++:10C88000090000000200C08000000000000000005D ++:10C890000010002100840009000800880008090534 ++:10C8A00001C000040002C1C0000300C10020040553 ++:10C8B00000A0001101C09000002000040008408288 ++:10C8C00000A0000000A0888200A0001101C10009A2 ++:10C8D000000000C004910010039000850884A1C0EE ++:10C8E00010C0000400C00002000201008203838522 ++:10C8F0009141000000000000000000010000000164 ++:10C900000889000200400082890800A002C082104D ++:10C9100000400503A105830009021108840090016D ++:10C9200002000408200982000088000000000000C6 ++:10C93000001091050111200108400001008800004D ++:10C9400000880000000000010000001001A00000AD ++:10C950000000000010010401A001904002A1C001EC ++:10C960000400040200000000000000C00089010271 ++:10C9700001010110000000000000000000000001A3 ++:10C9800000000000832089018501408888C0A00044 ++:10C99000A000A004831020082041C180A0800403CF ++:10C9A00041404000800080200041008000000009DC ++:10C9B00000050080100840402002890000400080EF ++:10C9C0000000000000000040002000000080400443 ++:10C9D000054041000000801080088008800080022F ++:10C9E000000380040000000500040009000020A0EE ++:10C9F00040A111400980000000000000000000007C ++:10CA00000040000400000302C10990214000000220 ++:10CA100000000000000000410000C2000000000013 ++:10CA2000001381000000820000130000005000008D ++:10CA300000000000060000880013C2000000000093 ++:10CA4000008100008141000000130000000000810F ++:10CA50000000C2000000000000000000000000888C ++:10CA600000000000C2008200000000008100000001 ++:10CA7000000000818100005000000000000006005E ++:10CA800000000022C2000000000000130000066049 ++:10CA900000000013000000002D2DFF6600010000C3 ++:10CAA000F0C060400000F7C7000000000000000078 ++:10CAB000000000006FFFCF0F0FBD0F24FFFFFFFF2F ++:10CAC0000000000000000000000000000000000066 ++:10CAD000FC0CFC0CFEC23E020000000000003E66A2 ++:10CAE0007E0600000000660F660F000000000000D8 ++:10CAF0000000890809090000000000000000000093 ++:10CB000000B0000000003C3C3F3CF9FFC1020000C7 ++:10CB1000000000000000000000002D2D9900000022 ++:10CB2000000030002000000034040000000000007D ++:10CB3000000000000000FF6600000FBD0F24FFFF93 ++:10CB40007FFF000000000000000000000000000067 ++:10CB50000000FC0CFC0CFEC23E02000000000000C5 ++:10CB6000BF667E0600000000663C663C00000000D8 ++:10CB7000000000008100000006063C0600000000E6 ++:10CB80000000002000000000FDFDFDFDF9FF000099 ++:10CB9000000000000000000000000000FFFFFFFF99 ++:10CBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:10CBB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10CBC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10CBD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:10CBE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:10CBF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10CC0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10CC1000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00041E ++:10CC200043030C4480F000180A0600005014C000B2 ++:10CC30000000D8FCD8FC0000000060FFF9FFC0C075 ++:10CC400000C360666F6600000000FCFF6666C6F603 ++:10CC5000C3FFF666F6FF00000000000000000000C1 ++:10CC60000000CCC3CFCA00FF00FF6FF6F66F0000D4 ++:10CC7000210000C360F666FF00000000FFFFFFFF19 ++:10CC800000000000000000003535FEFE000F020E1F ++:10CC9000000000000000000000000000C3E3D3E338 ++:10CCA00020202000FFFFFFDF000000000000000048 ++:10CCB000C0C00000C0E4C0E404040000009F0006FF ++:10CCC0004242424260006FFF00000000FCFC6666CA ++:10CCD0000636003C90009099000000000000000023 ++:10CCE000000000003C5A3CC330303F3F099090099F ++:10CCF000000028000000247E247E00000000FEFFCB ++:10CD0000FFFF0000000000000008353501010000B1 ++:10CD100002020000000000000000000000000060AF ++:10CD2000906020200000FFFFFFFF000000000000D7 ++:10CD300000000586006408B0008000860C2008B062 ++:10CD400000850086006101B000000086006000B030 ++:10CD5000008000860ABCA0880000008600E000B0C9 ++:10CD6000000000860061001000000086007400B022 ++:10CD7000000000000086026000B0008000860060B5 ++:10CD800008B000050086006008B0000500860A5162 ++:10CD900000B00000000000000000000000860061FC ++:10CDA0000898000005860A210090000000860041D6 ++:10CDB00000A00000FFFFFFFF10303030140014F01F ++:10CDC000BFFFBFFFAAAFFFAF6FB07FA000000000A2 ++:10CDD000FFFFFFFFF0F0F0F0553C553C0000000075 ++:10CDE0002ED1FF2E00000000555500FF000000006E ++:10CDF000EB82FFAA0000405503FFC3F0C355C3C92F ++:10CE0000CECEAAAAFF0F000000000E024F7F000046 ++:10CE100000005555555500000000000000000000BE ++:10CE20000000FFFF0000F2F18241577F55FFF3F74A ++:10CE3000F3A205AF05AFE8EBFCFF00300030410086 ++:10CE400041F0BFFF8FCFAAAFAAAF14EB55AA0000E5 ++:10CE500000005D5D55FF7D7D28280F0F0F0F00003E ++:10CE60000000D12E2E000000000055553C3C000073 ++:10CE70000000EB82FAA00000BFFAFC00C3F0C3552B ++:10CE8000C3963C3CAAAAC3C3000000000E024F7F19 ++:10CE90000000000000F00FFF000000000000000094 ++:10CEA00000000000FFFF0000F0F000005555555550 ++:10CEB00030753020042CC7EF000000000000FFFF99 ++:10CEC000000000000000000000000000AA2882000E ++:10CED0000000000000143C7D000000005C5F5C5F0F ++:10CEE00000000000CC9955AA0000000000000000DE ++:10CEF0000000000000000000000000001000EE44F0 ++:10CF000044EEFF7C3F7C55FF55C3000000000070DD ++:10CF1000F070FFFFFFFECFC055550000000000007D ++:10CF200000000000000000000000000000005C3C69 ++:10CF30005FFFAB03EAC00A00FFFF00000000000033 ++:10CF4000001E000000000000000000000000AA28F1 ++:10CF500082000000000000143C7D000000005C50D6 ++:10CF60005C50000000009933AA550000000000004A ++:10CF700000000000000000000000000000001000A1 ++:10CF8000BB1111BBFF00F000553C55000000000034 ++:10CF90000040F040FFFE0001303F5555000000000A ++:10CFA0000000000000000000000000000000000081 ++:10CFB0005C3C5000AA00AA000A000A00040000001D ++:10CFC00000000400000002000208800011000400BC ++:10CFD000A000042011000000119004004000210076 ++:10CFE0009100040011001100040011014000210013 ++:10CFF00000000000400080004000400000000400ED ++:10D000000000000004000000040004000400000010 ++:10D010000000800000000400000004000400040080 ++:10D0200000000000040000000000000000000000FC ++:10D030000000000000000400000004000400A00044 ++:10D0400000000000000000000100010002000000DC ++:10D05000000002000080000000000000000004004A ++:10D06000000010009000A000000000000008010077 ++:10D070000000040000000000400000000400000068 ++:10D0800000000000000000000000000000000000A0 ++:10D090000000000020000000000000000000000070 ++:10D0A0000000000000000000000000000000000080 ++:10D0B0000000000000000000000000000000000070 ++:10D0C0000000000000000000000000000000000060 ++:10D0D0000000000000000000000000000000000050 ++:10D0E000000000000000000100000000000000003F ++:10D0F000000000000000000000000000000000012F ++:10D1000000C000000000000000000000000000005F ++:10D11000000000000000000000000000000000000F ++:10D1200000000000000000000000000000000000FF ++:10D1300000000000000000000000000000000000EF ++:10D1400000000000000000210000000000000000BE ++:10D1500000000000000000000010000000000000BF ++:10D1600000000000000000000004000000000000BB ++:10D17000000000000000000000100021000000007E ++:10D180000008000000000000000000000000000097 ++:10D19000000000000000000000000010000000007F ++:10D1A000000000000000000000000011000000006E ++:10D1B000000000000000000000000010000000005F ++:10D1C00000000000000000000000000000018000DE ++:10D1D000800100000500000010C0840000C080082D ++:10D1E00080400002400200008082A0A10000008276 ++:10D1F0000040000005841000000810A0000000009E ++:10D2000000000000000000C000020082800000C09A ++:10D2100000A0000000010004000400010000000064 ++:10D2200000A003002000000100000000000000003A ++:10D2300000000000000000000001000000010000EC ++:10D24000000100000000C021C00084000010004068 ++:10D25000020510100000C0418200010005411010BD ++:10D260001085208084A10180820020411104C041EA ++:10D27000100000C100211000000084800100C041A6 ++:10D28000840082000000000000051080C000100033 ++:10D290001000C02182000008008000800004A0036C ++:10D2A000C00000000000010400200000C000A00039 ++:10D2B0000000000000000000000000048400C00422 ++:10D2C0000400002000000000200000000200020016 ++:10D2D0000200200011000000400002000500400094 ++:10D2E0000900100020000300000005001000850068 ++:10D2F000030040000900000003000300210041007A ++:10D3000010000500020000000000000009001001EC ++:10D310000500410011000000100002000000410063 ++:10D3200005000000000000000900000000004100AE ++:10D3300041000000100000004100000020004100FA ++:10D3400020000200040005000400000000000000AE ++:10D3500001000000000000000000010000000000CB ++:10D360000100000001008300000000050000010032 ++:10D37000200000000100000000000000000000008C ++:10D38000000200000000100000000000000000008B ++:10D3900000400000900000000000010000000000BC ++:10D3A000000000000000000000000000000000007D ++:10D3B000000000000000000000000000000001006C ++:10D3C0008400010000000100000001000000410095 ++:10D3D000410000008200100108100040100082018E ++:10D3E0000500C1200000808203C000A000000304EB ++:10D3F000000000880000900210000000050000847A ++:10D40000410021A000004100100000880000000041 ++:10D410001000020041110000000041C01083000014 ++:10D420000004000020040001A000000100A0000092 ++:10D4300000000000000000C000000000000000002C ++:10D44000000041008040000080A00000000090002B ++:10D450000021100500000300100801808885C0002D ++:10D46000034000410480001010050000000000008F ++:10D470000080C005000500004080012184040000F8 ++:10D480000000A000100000000021890800000040FA ++:10D49000000000051100C040104182000000014062 ++:10D4A00000001080C0000180000821000004000975 ++:10D4B0000021000000000000000000030000101028 ++:10D4C00000000000C0002021000004000000000057 ++:10D4D00009001100040000001040038202000082D5 ++:10D4E00000C0034010000300418805820040051081 ++:10D4F000099002000000410403000000020000A0A7 ++:10D5000009004184114000820590030005080420B1 ++:10D510000000008400A005000000000000840288D4 ++:10D5200020001000000420000240000000000088DD ++:10D530000000000000C00000000400C00000100057 ++:10D5400000000000000002000900020000000000CE ++:10D550001120000000000400000000800000000016 ++:10D56000000000000000010000000000000000803A ++:10D57000000000000000000000800000000000002B ++:10D58000000000000000000000000000000000801B ++:10D59000018000000000000000000000000000000A ++:10D5A000000000000000008001000080000000007A ++:10D5B000000000000000000000000000000000006B ++:10D5C000000000000000000000000000000000005B ++:10D5D00000000080000080000000000010C000106B ++:10D5E00020C1110304000008104041204103000243 ++:10D5F000004020100520000200020509C0000000C4 ++:10D600000000090021400008001041202000000017 ++:10D61000090000000000034000400300050903006A ++:10D6200000002000200000008040201002020220A4 ++:10D6300000020004200500000000000000000000BF ++:10D640000000000000000305004100410940008087 ++:10D650004080108000000000C00000000000C18277 ++:10D6600020850110008408008400010000000001F2 ++:10D6700000000000010100010000000000010500A1 ++:10D680000000000000000000000100010000010097 ++:10D690000000000000000000C10184010000010042 ++:10D6A00001000000010000000000880101010000ED ++:10D6B0000101000000000100000000000000000067 ++:10D6C0000000000000000000010100000000010057 ++:10D6D0000008C140011000A020004000040002002A ++:10D6E000A00140008200104090020804050185045A ++:10D6F000050041004020200000000001010201015E ++:10D700000800A00082004100A100890090000200F2 ++:10D7100000000000010000000000030040000200C3 ++:10D7200002008900400040000800000000000000E6 ++:10D730000000000000000005010000900000000053 ++:10D74000000000000000000000000000008801014F ++:10D75000010108004000000010C0000080008000AF ++:10D7600080020008800000008080850000C08505E0 ++:10D770009080900088000500210000004002058094 ++:10D780001003C000020041008300100040000200AE ++:10D79000C0000500020005000000000011000000AC ++:10D7A0004100890011008500C100800009000300CC ++:10D7B00000410200000002000020090000000000FB ++:10D7C0000000000000000000000000004100418057 ++:10D7D00005210809804180000000808000000000D1 ++:10D7E000008000000240008291C000080510002067 ++:10D7F00040204089044000200002054141090020EA ++:10D80000020220200002002000050040050800114F ++:10D810000000090900900040000500890000090887 ++:10D8200000820020408300C000C100A10090089148 ++:10D830000005002104200041000200094002000010 ++:10D8400000000000000000000000000000000503D0 ++:10D8500000030002090800808000C1808000008869 ++:10D8600000900084002001898404A1C0C0200089A8 ++:10D8700000A00102C0110001000100000101000030 ++:10D880000001010001010000000000000001000192 ++:10D89000000100000000000300A0008200880000DA ++:10D8A000000300C00002C140000500040084000520 ++:10D8B000018800040005040100010000000191003E ++:10D8C0000000000000000000000000000000000058 ++:10D8D000000000000001000000408882A08488024F ++:10D8E00000000000000000908441A020400002C021 ++:10D8F000C0088340A100C084000000850001000230 ++:10D900000004008400000000000100030000000487 ++:10D9100000000001000100200040000000010000A4 ++:10D92000000000010085000100400001000000002F ++:10D9300000200002018400400000000001400001BE ++:10D9400000000000000000000000000000000000D7 ++:10D950000000000400000000000084038400400078 ++:10D9600040A00020000000000000808200808000B5 ++:10D970008000032011910203C080000500C0002038 ++:10D980000000008000800000000000200010000364 ++:10D9900000800040000500050000008000020040FB ++:10D9A00000000000002000A0001000800003000420 ++:10D9B0000003000009004005028441000300408488 ++:10D9C0000021020000000000000000000000000034 ++:10D9D00000000000058005020341080080030000EC ++:10D9E00080000000000000000000000000000000B7 ++:10D9F000000000001200001300000000008800007A ++:10DA0000C200000000000000C20000500000000042 ++:10DA1000C20000000000000000000000120000131F ++:10DA20000000000000000000000000008100000075 ++:10DA3000000000000A0000000000C20000000042D8 ++:10DA40000000C20000000000008100000000000093 ++:10DA500000000000000000000000C2000A000000FA ++:10DA60000013000021000000000000000000000082 ++:10DA70000000E1FF00E1D4D71417FFFF00FF000012 ++:10DA80000000CF000F000000000000800000000038 ++:10DA9000000069BB69C3000000000F0F0F0F0000FA ++:10DAA0000000141D1D7D000000000000D7D41714D5 ++:10DAB000000000000000FFFF40704F7F000FFF0FCD ++:10DAC00069696996000FA0AF000000000000000027 ++:10DAD0000000000000000000000082C300550000AC ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000FF00001417D4D75D5D00FF98 ++:10DB000000000000F2000200000000000000000021 ++:10DB100000000000396939C3000000009696696969 ++:10DB200000000000141D1D7D0000000000001417FF ++:10DB3000D4D70000000036C636C640704F7F3C3C4C ++:10DB40003C3C69696996202F202F000000000000EE ++:10DB5000000000000000000000000000030300308F ++:10DB600000000000000000000000000000000000B5 ++:10DB70000000FFFFFFFF00000000FEBEFEBE3C698C ++:10DB800069C3FF3CF0B2BFBCB3B000500040FFFF20 ++:10DB9000FFF000000000AAFFB2F3428100003C0544 ++:10DBA0003C5000000000FCB8FCB80000AA69559683 ++:10DBB000FF55AA0000000000AFA0AFA0FBD3FBD32D ++:10DBC000AAAAF0F0AA3FAA30FFFF0F0F0000000042 ++:10DBD000000000000000000000000000FFFFAA009D ++:10DBE000FF30FF30000000000000000000000000D7 ++:10DBF00000000000FFCFFFFF00000000FC3CFC3CE9 ++:10DC0000C396963CC300E8AA8F8C83800010000066 ++:10DC1000FFFFFFF000000000AA00B2307EBD3C3CD8 ++:10DC20003CF53C5F00000000B830B830000069559A ++:10DC300096AABE14BE1400000000ACACACAC381008 ++:10DC400038103C3CF0F0AA3FAA30FAFA0A0A000069 ++:10DC50000000000000000000000000000000FFFFC6 ++:10DC6000AC00FF70FF2000000000000000000086F4 ++:10DC7000006000B000000086006000B00000008678 ++:10DC80000C6101B8008000860A6408B00000000042 ++:10DC90005010A00800050086007000B0001000863B ++:10DCA000006000B8008000860061019000800000E4 ++:10DCB0000086006000B800800086006000B80000A8 ++:10DCC0000086007000B0000000000014000000009A ++:10DCD0000086006100B000000000000000000000AD ++:10DCE00000000000080000000086002100900000F5 ++:10DCF00000000000FFFFFFFF5F5FEEEF005F005FCF ++:10DD0000C3000000FFFFAEEF0000000000000000B5 ++:10DD10000000000000000000000000000000000003 ++:10DD20000000000000000000000000000200575545 ++:10DD30000000000000003FFDC0C20000000005C55B ++:10DD400035F50000000066CC66CC00000000000045 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000FFFFF00000FFC6 ++:10DD70000FFF00000000000F3C3F5F5FFBBFC3438D ++:10DD800083C3C3030000AAAA088A000000000000A1 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000000020071 ++:10DDB0005755000000000000050FFAF000000000B9 ++:10DDC00005C535F50000000033663366000000002D ++:10DDD0000000000000000000000000000000000043 ++:10DDE000000000000000000000000000FFFFB01075 ++:10DDF00001FF0DFF00000000FFFFFFFFFF0FACACB5 ++:10DE0000A0A0C300000000003C3C3C3C000000001F ++:10DE100055558FDF000000000000000000000000EA ++:10DE2000417D417D00000000DD7788220000000078 ++:10DE3000000000000000000000005AA9AAAA00008B ++:10DE400000001E4B4B1E0000000000000000000000 ++:10DE500000000000000000000000000000000000C2 ++:10DE60000000000000000000000000000000090A9F ++:10DE7000000034340000000000001F5F0000F000CC ++:10DE8000ACAC0000000000000000F50505F5000046 ++:10DE9000000000555F5F000000000000000000006F ++:10DEA00000000C0CCFCF00000000FFFFAAAA00006A ++:10DEB000000000000000000000000000595B595BFA ++:10DEC00000000000B4E1E1B4000000000000000028 ++:10DED0000000000000000000000000000000000042 ++:10DEE0000000000000000000000000000000000032 ++:10DEF0000A0A0000080800000000000000000000FE ++:10DF0000000000002000200100000000008420002C ++:10DF100000002000000000000000000021000000C0 ++:10DF2000200000000000210100000000200004008B ++:10DF300000000000000020000000000000002100A0 ++:10DF400020010000000000000000000000000000B0 ++:10DF500004000000000000000400000000000000B9 ++:10DF600000000000000000000000000000000000B1 ++:10DF700000000000000000000000000000000000A1 ++:10DF80002000000000000000004000000000000031 ++:10DF90000000000000000000000000000000000081 ++:10DFA0000000000000000000004000000000000031 ++:10DFB0000000000000000000000000000000000061 ++:10DFC0000000004000000000000000000000000011 ++:10DFD0000000000000000000000000000000000041 ++:10DFE0000000000000000000000000000000000031 ++:10DFF000000000000000000000000000FFFFFFFF25 ++:10E00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 ++:10E01000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:10E02000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10E03000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 ++:10E04000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ++:10E05000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10E06000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10E07000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00F4BA ++:10E08000BBCE0C44808800C00A06000080A20000BD ++:10E090000000000000000000000000000010000070 ++:10E0A0000000001000100000000000000000000050 ++:10E0B0000000000000000000000000000011000847 ++:10E0C0000000002100080000000000000000000027 ++:10E0D0000000000000100000000000000000000030 ++:10E0E0000000000000000000000000000000000030 ++:10E0F0000000000000100000000000000000000010 ++:10E10000000000000000000000000000000000000F ++:10E1100000000000000000000000050000000000FA ++:10E12000000010000084000000000000000000005B ++:10E1300000000000031000000000000000000000CC ++:10E1400000000000000000000000000000000000CF ++:10E150000000000000000008410000000000000076 ++:10E1600000000000000000000000000000000500AA ++:10E17000000000000000100000000000000000008F ++:10E18000000000000000000000000000000000008F ++:10E1900005000000000000000000820000000000F8 ++:10E1A0000000C000000000000008000300000000A4 ++:10E1B000000000000000000000000000000010004F ++:10E1C000100000000000000000000000000000003F ++:10E1D00000000000000000001000000000008400AB ++:10E1E000C000100000000000C0000000000000009F ++:10E1F000000010000000000000000000000000000F ++:10E20000000000000000000000000000000000000E ++:10E2100000000008050000000000400000000000B1 ++:10E2200000000000000000000000050000000000E9 ++:10E2300000000000000000000200000000000000DC ++:10E24000200000000000000000002000000000008E ++:10E25000410000000000000000002000000000005D ++:10E2600000000000000000000000000000000000AE ++:10E27000000000000000000000002000000000007E ++:10E28000000000000000000000000000000000008E ++:10E29000000002000000FFFFFFFFFFFFFFFFFFFF86 ++:10E2A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10E2B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10E2C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:10E2D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:10E2E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E ++:10E2F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:10E30000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D ++:10E31000FFFFFFFFFFFFFFFF00A8A5EF0C44808871 ++:10E3200000100A06000080200000410000C000002C ++:10E3300000000008000000000000000000000000D5 ++:10E3400000000000000010000000000000000000BD ++:10E3500000000000000000000000000000000000BD ++:10E3600000000000000000000000000000000000AD ++:10E37000000000000000000000000000000000009D ++:10E38000000000000000000000000000000000008D ++:10E39000000000000000000000000000000000007D ++:10E3A000000000000000000000000000000000006D ++:10E3B000100000210000000000080010000000080C ++:10E3C000000000000000000000000000000000004D ++:10E3D000C000000000001000100000000000C0009D ++:10E3E000000000001000C00300000000000000005A ++:10E3F0001000C00000000000C00000008400000801 ++:10E4000000001000000000000000000000000000FC ++:10E4100000001000000000000000000000000000EC ++:10E42000C00000000000000000001008000009000B ++:10E4300000000000000000000000200000100000AC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000200000000000100000000000000002006A ++:10E48000000010000000000000000000000000007C ++:10E49000000000000000000000000000000000007C ++:10E4A0000000000010000000000000000000FFFF5E ++:10E4B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:10E4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:10E4D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10E4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10E4F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10E50000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10E51000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10E52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:10E530000080EFA70C44808800700A06000000C32A ++:10E54000010000000000004000000000000000008A ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000200000000000006B ++:10E59000000000000000000000000100000000007A ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C0000000080000000000000000000000000043 ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000000000000000000000000000000000001B ++:10E60000000000000000000000000080000000008A ++:10E6100000000000000000000000000020000000DA ++:10E6200000000000000000000000000000000000EA ++:10E6300000000000000000000000000000000000DA ++:10E6400000000000FFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10E65000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:10E66000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:10E67000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:10E68000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10E69000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A ++:10E6A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7A ++:10E6B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A ++:10E6C000FFFFFFFFFFFF00607B330C44808800E802 ++:10E6D0000A060000004100000000000000000000E9 ++:10E6E0000000000000020000000000000000000028 ++:10E6F000000000000000000000000000000000001A ++:10E700000000000000020000000000000000000007 ++:10E7100000000000000000000000000000000002F7 ++:10E7200000000000000000000000000000000000E9 ++:10E7300000000000000000000000000000000000D9 ++:10E7400000000000000000000000000000000000C9 ++:10E750000000000000000000FFFFFFFFFFFFFFFFC1 ++:10E76000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9 ++:10E77000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9 ++:10E78000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 ++:10E79000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10E7A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:10E7B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69 ++:10E7C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59 ++:10E7D000FFFFFFFFFFFFFFFFFFFF00445F9E0C44B2 ++:10E7E000808800D80A06000040D300000020000006 ++:10E7F0000100000000000000000000000000000018 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000000000000000000000000000F8 ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000100000000000000000000000000D7 ++:10E8400000000000000000200000000000000000A8 ++:10E8500000000000000000000000000000000000B8 ++:10E860000000000000000000000000000040000068 ++:10E870000000020000000000000000000000000096 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000004028 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000200000046 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F00000000900000000000010000000000000FF ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000010000000000000E7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000010080000000000000000000000BF ++:10E9400000000000000000000000000001000000C6 ++:10E9500000000000000000000000000000000000B7 ++:10E9600000000000000000000000000000000000A7 ++:10E97000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 ++:10E98000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 ++:10E99000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 ++:10E9A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 ++:10E9B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 ++:10E9C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 ++:10E9D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 ++:10E9E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 ++:10E9F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 ++:10EA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:10EA1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:10EA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10EA3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:10EA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10EA5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:10EA6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 ++:10EA7000FFFFFFFF0000000000000000000000009A ++:10EA80000000000000000000000000000000000086 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000800010048800000000085 ++:10EAC0000000000000000000000000000000000046 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB30000000000000000000004000000000000095 ++:10EB400000000000000000000000000000000000C5 ++:10EB500000000000000000000000000000000000B5 ++:10EB600000000000000000000000000000000000A5 ++:10EB70000000000000000000000000000000000095 ++:10EB80000000000000000000000000000000000085 ++:10EB90000000000000000000000000000000000075 ++:10EBA0000000000000000000000000000000000065 ++:10EBB00000000000000000000000102000001020F5 ++:10EBC0000000000000000000000000000000000045 ++:10EBD0000000000000000000000000000000000035 ++:10EBE0000000000000000000000000000000000025 ++:10EBF0000000000000000000000000000000000015 ++:10EC00000000000000000000000000000000000004 ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000004000000000000000A4 ++:10EC30000000004010000000000000000000000084 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC8000000000000000000000000000000008007C ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000020000000000000000000000000062 ++:10ECB0000000000000000000000000000000000054 ++:10ECC0000000000000000000000000000000000044 ++:10ECD0000000000000000000000000000000000034 ++:10ECE0000000000000000000000000000000000024 ++:10ECF0000000000000000000000000000000000014 ++:10ED00000000000000000000000000000000000003 ++:10ED100000000000000000000000000000000000F3 ++:10ED200000000000000000000000000000000000E3 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED8000008082A30C8500400400040004000400FD ++:10ED90000400040004000400CC2600000000000071 ++:10EDA00000000C44408000A0CC26000000000000C1 ++:10EDB00000000C4440800030CC2600000000000021 ++:10EDC00000000C44408000B0CC2600000000000091 ++:10EDD00000000C44408000F0CC2600000000000041 ++:10EDE00000000C4440800008CC2600000000000019 ++:10EDF00000000C4440800088CC2600000000000089 ++:10EE000000000C4440800048CC26000000000000B8 ++:10EE100000000C44408000C8CC2600000000000028 ++:10EE200000000C4440800028CC26000000000000B8 ++:10EE300000000C44408000A8CC2600000000000028 ++:10EE400000000C4440800068CC2600000000000058 ++:10EE500000000C4440800018CC2600000000000098 ++:10EE600000000C4440800098CC2600000000000008 ++:10EE700000000C4440800058CC2600000000000038 ++:10EE800000000C44404000E8CC26000000000000D8 ++:10EE900000000C44402000A8CC2600000000000028 ++:10EEA00000000C4440200068CC2600000000000058 ++:10EEB00000000C4440A000E8CC2600000000000048 ++:10EEC00000000C4440E00030CC26000000000000B0 ++:10EED00000000C4440E000B0CC2600000000000020 ++:10EEE00000000C4440E00070CC2600000000000050 ++:10EEF00000000C4440E000F0CC26000000000000C0 ++:10EF000000000C4440E00008CC2600000000000097 ++:10EF100000000C4440E00088CC2600000000000007 ++:10EF200000000C4440E00048CC2600000000000037 ++:10EF300000000C4440E000C8CC26000000000000A7 ++:10EF400000000C4440E00028CC2600000000000037 ++:10EF500000000C4440E000A8CC26000000000000A7 ++:10EF600000000C4440E00068CC26000000000000D7 ++:10EF700000000C4440E000E8CC2600000000000047 ++:10EF800000000C44401000E8CC2600000000000007 ++:10EF900000000C4440900078CC26000000000000E7 ++:10EFA00000000C44405000E8CC26000000000000A7 ++:10EFB00000000C44403000E8CC26000000000000B7 ++:10EFC00000000C44407000A8CC26000000000000A7 ++:10EFD00000000C4440700068CC26000000000000D7 ++:10EFE00000000C4440F000E8CC26000000000000C7 ++:10EFF00000000C4440880040CC26000000000000C7 ++:10F0000000000C44408800E0CC2600000000000016 ++:10F0100000000C44408800D0CC2600000000000016 ++:10F0200000000C4440880030CC26000000000000A6 ++:10F0300000000C44408800B0CC2600000000000016 ++:10F0400000000C4440880008CC26000000000000AE ++:10F0500000000C4440880088CC260000000000001E ++:10F0600000000C4440880048CC260000000000004E ++:10F0700000000C44408800C8CC26000000000000BE ++:10F0800000000C4440880028CC260000000000004E ++:10F0900000000C44408800A8CC26000000000000BE ++:10F0A00000000C4440880068CC26000000000000EE ++:10F0B00000000C4440880018CC260000000000002E ++:10F0C00000000C4440880098CC260000000000009E ++:10F0D00000000C4440880058CC26000000000000CE ++:10F0E00000000C44408000400C8500800A060000AF ++:10F0F0008020000000000000000000000000000070 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F140000020000000000000000000000000008817 ++:10F1500000000000000000000000020000000000AD ++:10F16000002002000000000000000000000000007D ++:10F17000000000000010000000000010000000006F ++:10F18000001000000010000000000010000000004F ++:10F19000000000100010000000000010000000003F ++:10F1A000001000000010000000000010000000002F ++:10F1B000000082100000001000000000021000009B ++:10F1C000000000100000001000000200001000000D ++:10F1D00000000000001000100000000001100000FE ++:10F1E000000000108300001000000000001000006C ++:10F1F00000000000001000000000000000000000FF ++:10F2000000000000000000000000000000000000FE ++:10F2100000000000000000000000000000000000EE ++:10F2200000000000000000000000000000000000DE ++:10F2300000000000000000000000000000000000CE ++:10F24000000000000000000000002000000000009E ++:10F25000000000000000000000000000009000001E ++:10F26000000000000000020000000000000000009C ++:10F270000000000000900000FFFFFFFFFFFFFFFF06 ++:10F28000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10F29000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10F2A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10F2B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:10F2C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:10F2D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E ++:10F2E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:10F2F000FFFFFFFFFFFFFFFFFFFF00FC3BEC0C44A5 ++:10F30000408000600A06000080E30000000000006A ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000010000000BD ++:10F340000000000000000000000000000000008835 ++:10F35000000000000000000000000000000000C0ED ++:10F360000084000000000000000000000000000019 ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000A000A0000D ++:10F3C000A000000000000004080000000000000091 ++:10F3D000C000A00000000800000082000000000043 ++:10F3E000000008000000000000000800000200000B ++:10F3F000A00000000000000000000000000000006D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F4400000000000000000000000000000000000BC ++:10F450000000000000001000090000000000000093 ++:10F4600000900000000000000020000000000000EC ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000000000000000003C ++:10F4D0000000080000000000000000000000000024 ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000000000000000EB ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000100000000000000000000000006B ++:10F590000000000000000000000000000800000063 ++:10F5A0000000000000200000000000000000080033 ++:10F5B0000000A000000000000000000000000000AB ++:10F5C00000000000A000000000000000000000009B ++:10F5D000000000000000A000A0000800A000000043 ++:10F5E00000410000000000000800A00082000000B0 ++:10F5F0000000000008000000A0000000A0000000C3 ++:10F6000000000000000000000000000008000000F2 ++:10F61000000000000000FFFFFFFFFFFFFFFFFFFFF4 ++:10F62000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA ++:10F63000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA ++:10F64000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:10F65000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:10F66000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:10F67000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10F68000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A ++:10F69000FFFFFFFFFFFFFFFF0040C62F0C4440802D ++:10F6A00000700A0600000041000000000000000099 ++:10F6B000000000000000000000000000000000004A ++:10F6C000000000000000000000000000000000003A ++:10F6D000000000000000000000000000000000002A ++:10F6E000000000000000000000000000000000001A ++:10F6F000000000000000000000000000000000000A ++:10F7000000000000000000000000000000000000F9 ++:10F710000090000000000000004000000000000019 ++:10F7200000000000000000000000FFFFFFFFFFFFDF ++:10F73000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD9 ++:10F74000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9 ++:10F75000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9 ++:10F76000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9 ++:10F77000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 ++:10F78000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10F79000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:10F7A000FFFFFFFFFFFFFFFFFFFFFFFF00F03CD564 ++:10F7B0000C44408000E80A06000000410000000000 ++:10F7C0000000000000000000000000000000000039 ++:10F7D0000000000000000000000000000000000029 ++:10F7E0000000000000000000000000000000000019 ++:10F7F0000000000000000000000000000000000009 ++:10F8000000000000000000000000000000000000F8 ++:10F8100000000000000000000000000000000000E8 ++:10F8200000000000000200000000000000020000D4 ++:10F830000000000000000000000000000000FFFFCA ++:10F84000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8 ++:10F85000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8 ++:10F86000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 ++:10F87000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98 ++:10F88000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88 ++:10F89000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF78 ++:10F8A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:10F8B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 ++:10F8C00000584E4D0C44408000D80A06000060DB12 ++:10F8D0000000000000000000000000000000000028 ++:10F8E0000000000000000000000000000000000018 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000000000000000F7 ++:10F9100000000000000000000000000000000000E7 ++:10F9200000000000000000000000000000000000D7 ++:10F9300000000000000000000100000000000000C6 ++:10F9400001000000000000000000000000000000B6 ++:10F9500000000000000000000000000000000000A7 ++:10F960000000000000000000000000000000000097 ++:10F970000000000000000000000000000000000087 ++:10F980000000000000000000000000000000000077 ++:10F990000000000000000000000000000000000067 ++:10F9A0000000000000000000000000000000000057 ++:10F9B00000000000004000000000000000400000C7 ++:10F9C0000000000000000000000000000000000037 ++:10F9D0000000000000000000000000000000000027 ++:10F9E0000000000000000000000000000000000017 ++:10F9F0000000000000000000000000000000000007 ++:10FA000000000000000000000000000000000000F6 ++:10FA100000000000000000000000000000000000E6 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000010080000000000AE ++:10FA4000001008000000000000000000000000009E ++:10FA5000000000000000040000000000030000009F ++:10FA60000400040011000300040004001100110050 ++:10FA70000400110002000000000011000800020054 ++:10FA800088000400100000000200000004000000D4 ++:10FA90000000020010000000000000001100110032 ++:10FAA000040000000000030000000000000003004C ++:10FAB0000200020002000200090000002100030011 ++:10FAC00000004000100002000300110000000000D0 ++:10FAD000040004000200000000000000000000001C ++:10FAE0000000000001000000000000000000000015 ++:10FAF0000000000000000100000000000000000005 ++:10FB000000000400000001000000010000000000EF ++:10FB100000000000000001000000000000000000E4 ++:10FB200000000000000000000000000000000000D5 ++:10FB300000000100010001000100000000000000C1 ++:10FB400000000000010001000100000000000000B2 ++:10FB500000000000000000000000000000000000A5 ++:10FB600000000020000000209120000000020000A2 ++:10FB70000000000080008020100000000000000055 ++:10FB80000000000004000000000000000000000071 ++:10FB9000080000000000041000A000C000000000E9 ++:10FBA0000020004000C000000000032000200004EE ++:10FBB000000000218001800080A10020040280203C ++:10FBC0008089201000200020000804000040004030 ++:10FBD00000412088000000000000200000000041DB ++:10FBE00000000400008000000080109000000090E1 ++:10FBF000000000000000082020A103000000000019 ++:10FC00008220002000200000002000100000840955 ++:10FC10000000002000100000002000000000000094 ++:10FC200000000200009000100200021000A00090EE ++:10FC300000C082000084020440001008009001808F ++:10FC40000400101005200010000982C1012100A14C ++:10FC500000A082828320002000000000012000001C ++:10FC600000900010000000100000001000001000C4 ++:10FC70000000000000000000000000000084000000 ++:10FC8000000000000000801080848010000200103E ++:10FC90000010000080200000004000000010000064 ++:10FCA000002000900000000000A000900000001064 ++:10FCB0000000009000100000002000000002000082 ++:10FCC00000840084008800100088000000A000006C ++:10FCD00000C00090009000A0000000000040000460 ++:10FCE0000000000000000000000000000000000014 ++:10FCF00001000000000008000000000000000000FB ++:10FD000000000000000000000800200004000000C7 ++:10FD100000000000000004808200C000880008008D ++:10FD200000000000000000000000000000001000C3 ++:10FD3000000000000000000000000080C000008003 ++:10FD40009000000000000000108000000000000093 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000080800080018000080104000500080078 ++:10FD70000400050080008304800000200001801042 ++:10FD800000010004000020000004400003010310F3 ++:10FD9000041005001021102188010000100000004F ++:10FDA00080000000210485010204000421011000EC ++:10FDB00003002109850400840000100000C10540F3 ++:10FDC000100090C0000105010220102000C00200B8 ++:10FDD0002100041105000000050190020800000048 ++:10FDE00041840800200020042000000401000000DD ++:10FDF0000000A11100002041208002001080C020DE ++:10FE0000020010201080A0000100008001001010EE ++:10FE1000A000114100000882C0A00220840001005F ++:10FE2000A00020000000C0C1102000901080A0049D ++:10FE3000C0419000108840A18210004100000020C5 ++:10FE4000008088210400081082108280088500004C ++:10FE500000400000014084000000001008800021E4 ++:10FE6000C000C000000008000800092000100000C9 ++:10FE700000000000100010004002202010040010BC ++:10FE800000000040000020842000410020A011A0BC ++:10FE900008000400042010C04082020420041084E2 ++:10FEA0001000100403400000034040001084410093 ++:10FEB00002A02100080021A00320404102400000D0 ++:10FEC0002088414040C0034008400888102041215C ++:10FED0000000032021004100000000004100200438 ++:10FEE00000000010100000A00100010000800000D0 ++:10FEF0000000000000000000000001800100008000 ++:10FF0000000000000080000001000100000001006E ++:10FF1000000001000000018000000100018001805C ++:10FF200000000000008000800000000900000000C8 ++:10FF30000000000000000000000000000040000081 ++:10FF400000000100000001000080010001000080AD ++:10FF5000008400000000000000000000000000001D ++:10FF60000100000000000000001080051001412188 ++:10FF7000C101100080000000800100A0A0058005E4 ++:10FF8000201100840000000000000000200080001C ++:10FF90002010030020A00020008488C0A0A18400BD ++:10FFA00000010000088480011000000080000000B3 ++:10FFB0000000009110841040210003000084100014 ++:10FFC0008500881080104000004000218001000161 ++:10FFD0008084000110004140038490000000000074 ++:10FFE0000010020000000010000005200884A0207E ++:10FFF000C0A020208200400084000208000041824E ++:020000040002F8 ++:10000000208401048211840000004000C000090522 ++:1000100020001100824183000080820040004104E2 ++:100020002100100400000000024040000000040015 ++:10003000000000110040080082900241404100058C ++:100040000820020004050405C141008084A00420AA ++:1000500008200811101000000240000010000010DD ++:10006000000000100110000000000041108000009E ++:10007000800021000000000000800080008002025B ++:10008000000921110909030080004000110000004F ++:100090000000000000000002911100400008111152 ++:1000A000880989210904100500400002021000009F ++:1000B0000409401000100911000000004000000079 ++:1000C000021100C182021120000000008000000027 ++:1000D0008480800010001100080000000000100063 ++:1000E0000080000040000000000000000000000050 ++:1000F00000009000110000000002008402A000082F ++:1001000001011001010101018900C000830000000C ++:1001100000000000000000000001910188010001C2 ++:1001200009C11105C1C1010000010001000000006A ++:1001300000000400000104000000000008000000AE ++:1001400000000109A0850440000500880010400857 ++:10015000000088829090908200040000000000005F ++:100160000000C082A0C001A000020000000000004A ++:10017000000088019001A00283890300850005002A ++:1001800009908900C10009890901C110A00000106F ++:10019000A100000000000000010082019083C089DE ++:1001A00082C09001C10002201101880000A001015D ++:1001B0008201000000040184000001000000000032 ++:1001C00000000000040088101010C0082110000278 ++:1001D00009080800C0011000880082910000010099 ++:1001E0000002000000019000000411040000000063 ++:1001F000000000000008801180008989100890002C ++:10020000100083021000C10088088309110011004A ++:10021000400010020000001100000900400289099E ++:1002200009C091808002C10000008309000009001C ++:100230000520900300000480410041414009000076 ++:100240000000000000000504098082824040020096 ++:1002500011002010910000400000800080C00800C4 ++:1002600002000800210000020000000089000000D8 ++:10027000000000000000800000002100808000805D ++:1002800000000000000002100091098940080009E8 ++:1002900004000009808380000000020000001100BB ++:1002A000000000C08988020220910940C0830241F9 ++:1002B0000041110908090000104005050041032014 ++:1002C00000000000000000804108800810C00440C9 ++:1002D000000910089091009000910080800080C07B ++:1002E0000000000800C000800080800000000000C6 ++:1002F0000000000000000000C000008201008882B1 ++:100300000008000004C0A0000183009101850904D9 ++:100310000004000200C10883820000000100000008 ++:10032000010000C000A1898301C189890503050975 ++:100330000040008800000100000001090089000061 ++:100340000109C0400008000800880002040303857A ++:100350000083008200081010A0880004C0C09088AC ++:10036000888300040084001104C00008C0040888C9 ++:10037000A090000000000000A00090018810A000E4 ++:10038000C0880888080100014000019001030001B5 ++:1003900000C0008900010001000000880088000002 ++:1003A000000091018989A101A18884001009000041 ++:1003B000008800910184000001C000000008018451 ++:1003C000000001004008084082000800820110057A ++:1003D00008000390C10004081000C0828201880058 ++:1003E0000400100800080008000000008384850451 ++:1003F000400041000000000100000000801180006A ++:10040000800000800009000400080000031004912F ++:100410000021080000400008000200000000000069 ++:100420000000000091118920A1404080804080118F ++:100430000004008004824002044110800000028019 ++:100440004008090440000000008000008000000314 ++:1004500089C0844102000300020082008280801172 ++:100460008000000000800000000000000000888084 ++:1004700010801100100000000040000200004188C0 ++:100480000013C200000000600013C2000000000062 ++:100490000000C200000000000013C2000A00004279 ++:1004A0000000C200420012420013C200000012828B ++:1004B0000013C200000082000013C204008100008B ++:1004C00000000013C200008800000013C2000000FA ++:1004D00000000013C200820000410013C20000416E ++:1004E00000000013C200000006000013000000001E ++:1004F00000820013C200000006000013C2000000CA ++:1005000000000000000000000000000000000000EB ++:10051000FF7E3CFF0000100800000000C342000006 ++:10052000000000000000000008000000FF0000FFC5 ++:10053000000000003C33666A4444004405A000000B ++:1005400000006E086E083C1E3C1E0000000000000B ++:1005500000008E0E8E0EFF2FFF2400100020FC0CDA ++:100560000C0C000000007E7E4242000000006F6024 ++:100570006F603000F000000000000000000000008C ++:10058000000000000000000000000000000000006B ++:100590000000FF7E3CFF0000180000000000C34286 ++:1005A000FF00000000000000000000000000FF004D ++:1005B00000FF000000003C3C66668888008805A0BB ++:1005C00005A00000FF906F003C003CFF0000000011 ++:1005D00000000000860686060F2F002400000000A1 ++:1005E000FC0C0C0C000000003C3C00000000000073 ++:1005F0000F000F003000F0000000000000000000BD ++:1006000000000000FFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10061000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA ++:10062000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA ++:10063000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:10064000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:10065000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:10066000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10067000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A ++:10068000FFFFFFFFFFFF00FC8B5C0C4440400018A5 ++:100690000A06000070DF00000000FFFF00000000FD ++:1006A000000000000600040B000000000000000035 ++:1006B00000003030303000000000FFFF0000FFFF7E ++:1006C000FFFB8040102000FF40BF6666F0F0000096 ++:1006D000004400600090000024F4FFFFE0FFE3FF0F ++:1006E00000000000000000003938393E993C783C99 ++:1006F00000000000003CC0FC000000000000000002 ++:1007000000000000300030FF00000000FFFF00008C ++:1007100000000000FFFFFFFF00000000FFFF0000DF ++:100720000000000004000900000F00001800140081 ++:10073000000000003030307600000000FFFF0000B5 ++:10074000FFFFFFFF0102080400FF00FF96960F0F56 ++:100750000000000000060009000024F400F0200062 ++:10076000230000000000000000003038303E003C54 ++:10077000783C00000000003CC0FC000000000000CD ++:10078000000000000000300030FF00000000FFFF0C ++:1007900000000000000066666666A00650B4A10076 ++:1007A0000000008600C508A000100586007000B09B ++:1007B0000010008600E100B90000A0005014A00065 ++:1007C0000000000670B401080000008600F401B2C9 ++:1007D000001000060060A1B000050000008600F0D7 ++:1007E00008B00000A086007100900000008600D1D3 ++:1007F00008980000088600E508B00080000000812D ++:10080000080800050086006001B0048001820274BF ++:1008100000B000000086006009B00400FF00FF0087 ++:10082000F5F5A5A5BE000000C33CC33C00000000D8 ++:10083000407C427E00000000FCFCAFA000000000F5 ++:10084000000000007F80FF00FF0FF00FAA5500009E ++:100850004400004400000000303030300000000050 ++:1008600000000303FFFFFF3000300454AEFEFEBE65 ++:10087000FC3C5F5FD7FFFCC03C0000300F3FFE0434 ++:100880007F7FEBFF0D8F000000000C0C00FF550078 ++:10089000CCCC5514FFFC0000000000000000DF205D ++:1008A000FF000A0AA5A514000000C33CC33C0000D9 ++:1008B0000000003C023E000000000C0CAFA0000055 ++:1008C000000000000000FF00FF0000F0F00FAA553C ++:1008D0000000880000880000000030303030000048 ++:1008E000000000000303FFFFFF3000300404AEAE41 ++:1008F000EAAAC0000A0A0028FCC03C0000300F3FF2 ++:10090000FE04202000140D8F000000000C0C00FFDE ++:10091000FF0000000000FFFC0000000000000000DD ++:1009200000000000FBFF393CFFC0C0C030FF30308A ++:1009300000000000707A757F0000000000000000D9 ++:10094000000000000000000000000000FBFF393C38 ++:10095000A00000A000009606000000000000414139 ++:100960000000000000000000000000000000000087 ++:100970000000FFFF00000CFF5D5DFFF00F001400A2 ++:1009800014FFF0B2EBFFDFDF027F00000000000089 ++:100990000000000000820F0F0000000000000000B7 ++:1009A0000000000000000400393CFF00000030306F ++:1009B000303000000000202A252F00000000C0C0B9 ++:1009C0000000000000000000000000000000040023 ++:1009D000393CAA0000AA9606000000000000555508 ++:1009E0004141000000000000000000000000000085 ++:1009F00000000000F2C232020C0C5D5DF0F000005D ++:100A0000140014FFF0B228000808027F0000000064 ++:100A100000000000001000820F0F00000000000026 ++:100A200000000000000004000000040000000400BA ++:100A30000000040002000400020000001100200079 ++:100A4000200011010200000002001100110000004E ++:100A50000900040000000000000082000000020005 ++:100A60000000040000000000040003000400000077 ++:100A70004000A000A00110001000000000000200D3 ++:100A800004000008110040001000020002000200F3 ++:100A90000400030000000400040011000200040030 ++:100AA00004000090040000000000000000000000AE ++:100AB00088000000000000000000000004000000AA ++:100AC0000100010000200100000001000000000002 ++:100AD000000090000000040000000200200004005C ++:100AE00000000000004000400000910004000000F1 ++:100AF00000000100050005400100010000000000A9 ++:100B000001000000000000000100010001000400DD ++:100B100001000000000000000000000000000100D3 ++:100B200000000000000000000000000000000000C5 ++:100B30000000000000400000000000000000000174 ++:100B40000000000004000000000008000000800019 ++:100B500000C0000100008001000000000000030050 ++:100B6000100000000000200000C000200000004035 ++:100B70000000008800002020800100020210110007 ++:100B800000000002A14000A0002100A0002000847D ++:100B9000000000014004219080A1008800080000AE ++:100BA000004100A00000000411000000000000103F ++:100BB00000100000000000800000020000000000A3 ++:100BC00000080400002100100000000004210010B3 ++:100BD0002010001000080000040800000841001068 ++:100BE00082000110000000100900000000800010C9 ++:100BF000904000400410000001001020008090216F ++:100C00000021001000A104000010000400410010A9 ++:100C10000021000000100190A0100202000000A0BE ++:100C2000002100840009000090A0001000000010C6 ++:100C30000084000000100010000000100000000000 ++:100C40000010000000000000000000000002000092 ++:100C500000400020004080A08000800000000003D1 ++:100C60000000001000000090000000C0000000889C ++:100C70000090800000000020000000000011002013 ++:100C8000000000A000880002404102410010000066 ++:100C9000008400A00083000300A000024002008442 ++:100CA000008400110000000000900000008400009B ++:100CB0000000C01004000800001000008802C005F9 ++:100CC00088400000000000000200C0000041000059 ++:100CD0000000040000800000040004000400000084 ++:100CE000C00402008402900000118400840000000F ++:100CF000040008410400A000824100088200842012 ++:100D000000C10005A0400009889101200120A00039 ++:100D1000A00000051000844084028200100011022F ++:100D200000050005000400000000000000030000B2 ++:100D300010000088A1080008030008A01041020567 ++:100D40001000008241A00584209010001040204037 ++:100D500041A0090103000020049000A00400C1008C ++:100D6000030202C0890008080585090410900200EA ++:100D700000000020850985C0058205820000110061 ++:100D800010A110C1000102000201C10080A0840175 ++:100D9000A101000882020840C140400102A0419127 ++:100DA00005000000410002002000004000048420F3 ++:100DB00085400000000020900080C000C000008836 ++:100DC00085848209000090000000010000000000FE ++:100DD00001808821000808091080A100C0050103D6 ++:100DE000040384808400202100A1C00884800121A4 ++:100DF000080000009080048404100000C0008400FB ++:100E00008205820201020040011101022041040911 ++:100E100021404004C090038900891089C14000002E ++:100E2000840200210800084101009109101000808F ++:100E300021A10410040041000484020004001000F9 ++:100E40004100000005000000800040004000040058 ++:100E500041202100000000000010000080008200FE ++:100E6000000084000000020000012103088220002D ++:100E70000300090000000800090008100800200411 ++:100E800003042089089003C0214180A110A1118290 ++:100E90000400A100008400A00382411003A0A1046B ++:100EA00000042002000100840000211180414188DB ++:100EB000410000880088000000000110010090003F ++:100EC0000100100084000000040004000100001074 ++:100ED00001219080080000000003000000000400D1 ++:100EE0000400000005210000000084040020C00070 ++:100EF0008400C0080021000011050000A10989003C ++:100F0000000000000020000002110202040804207A ++:100F10008200010904088205000510051000000088 ++:100F2000208000800180C0040000000000400420F8 ++:100F3000000000000000000011008000A0008400FC ++:100F40001140004000400800110002100000022083 ++:100F50000084418410A000A00000801000400084A4 ++:100F60000491040004000900100020101000020584 ++:100F7000218410821082418400000810880041847E ++:100F8000A1401090021010A0410002820440001005 ++:100F900000842040C0040003108382010008200563 ++:100FA0000200009040118040000400008085808491 ++:100FB000418800C0001100822001000010002111B2 ++:100FC0002100020082400040A10090008300A000A8 ++:100FD000018000000005080010000040081100001A ++:100FE0000005030811400111881000001105C00020 ++:100FF000008400218400C040C009000000000921D5 ++:101000000000040302008203C0102005900005C107 ++:10101000A02000049110218390848802030800A17D ++:1010200088080000000001022090009000001008D5 ++:10103000200000000000000400050004C000800043 ++:1010400089000300020080000500090000838884F5 ++:101050000391008988088441044041400000808059 ++:1010600000000000001140108000004010008000CF ++:10107000C000110010400000001111000000A08508 ++:101080008008030005100309091020411009050814 ++:1010900085C0A080400411038009100804040040AA ++:1010A000400500C1000911830009110202822000DD ++:1010B0002000110040001010C00905081141050072 ++:1010C000820011000100010084000000900008A0CF ++:1010D0000409900300108900C00090010001008203 ++:1010E000C084000200C000000001C00000004100F8 ++:1010F000C0008300000001010000000100000000AA ++:10110000888390119182884001000801010100014B ++:1011100000110210200801000509104190830040D1 ++:1011200000A000408809900803C188910089004010 ++:1011300088000100000000001000C0010000000154 ++:10114000010001000182010005000000204000892B ++:101150008908020210C1C1022082C184080209006C ++:101160008800090002A0080400200000000200001E ++:101170000400020101000000000000200100000046 ++:101180000000A00182094188019008000201098342 ++:10119000880000A1C000C102A0C0C00009404003F7 ++:1011A000850140000500C00088000800C18241910F ++:1011B0008301050041004100C100880004000300D4 ++:1011C00089002000200040000905A00402000280E0 ++:1011D000058590918080808210C10580A00080915B ++:1011E000C00505094000090085C100000800008015 ++:1011F00008008400910302001105000000000509A9 ++:1012000000000000092008C0858040800300C02144 ++:101210000885200441108400050011890500C18063 ++:101220000511830909052000C00011008500A100F7 ++:1012300040C0830511000800020089000900110068 ++:101240000200090200100090034000A000400002CC ++:10125000200200A0058003800380838000092141D3 ++:1012600041C0408000008000000000000800200015 ++:101270000000808000090090038980890008001028 ++:101280000002000400000409004080088088100467 ++:10129000041103888088080402900082000302057C ++:1012A000044000091103004000400084000505854A ++:1012B000004100099103000300031009000311110C ++:1012C000004004090390008300A100C12003001125 ++:1012D00000C101C0008500028510088410A000A094 ++:1012E0000182008511080000400004000800000091 ++:1012F000000000001088008200050084888800003B ++:1013000000000001000000009003840590828883A3 ++:1013100000A1004000848240010800400085029145 ++:1013200000A000A1008389C10040004000A0048803 ++:10133000004000010009090100C0004001C1020194 ++:1013400000C000040089000800000009000100003E ++:1013500082009000840100008503850108C002829C ++:1013600000010004010001C1A0A0080104001082D6 ++:10137000008800010001000000040041000000009E ++:101380000008004000000100000082A18820020047 ++:101390004140000300040000000285C0A14041C09C ++:1013A000854001C101C1010000C00240408400002D ++:1013B000C10001880183000000400090008400010A ++:1013C0000000000100100001000400000090001067 ++:1013D00000008000000080050000828209100940A2 ++:1013E000C1840020410540112088808480200004B1 ++:1013F0008080090000100421020000000004004168 ++:10140000000008800584040040000000C111A0898C ++:1014100009000500091004800500008088001008FC ++:10142000A003C1890383219108041100C00040007A ++:101430000300C000038904910304090000000008B0 ++:1014400000090000004000200003008082500013CB ++:10145000C2000A5000500000C2000000000000134B ++:101460000000114100000013C20041000081001380 ++:10147000C2000050810000130000000082410013F0 ++:10148000C200218100000000C20000000000000036 ++:101490000013C200008481500013C2008242000089 ++:1014A00000130000000000000013C20082000000D2 ++:1014B00000000000000000000000C2004200128492 ++:1014C0000013D000000000840013C2000088000058 ++:1014D00000000000812400000000000088443C3C23 ++:1014E00000FF000000003DFF3DFFF5FDF5FD0000A1 ++:1014F0000000000000003F3F0F0F00000000000050 ++:1015000000000CFF5DFF0FFF3535CFCF417D0000A0 ++:101510003CFF3FFF0CFF5DFF000F555F55FF0F3C89 ++:10152000003C033F00040000555FFC3C4D4D00FFB4 ++:10153000000F3C0F00300F3FFDFD10BF5555033F1E ++:1015400000000000FFFF000000000000407FC0FF1F ++:10155000000000008124000000000000884400001A ++:101560000F0F5555000000003D053D05053D053DAB ++:1015700000000000000000003F3F0F0F00000000CF ++:10158000000000000C0C5D5D00F035350C0C417D59 ++:1015900000003C3C3F3F0C0C5D5D000F555F55006B ++:1015A0000F3C003C033F0000040055500C3C5555D7 ++:1015B000033F000F3C0F00300F3F080810BF4D4D98 ++:1015C00000FF00000000BABA450000000000003F24 ++:1015D00080BF00000000240081000000000030C037 ++:1015E0000C03A0A0B4B4BEBE1414BEFCAAF0FFFF4E ++:1015F000E8E800000000000000803CFF3C00FAFA30 ++:10160000505000000000FFFFBA300F0FF0F055AA55 ++:1016100055AA0000FF003C00FFBCFFA0FFFF300008 ++:10162000F0F03C00FF3C003CFBF8EB28FF0CABABC0 ++:10163000F0F0BE82FC0CF000F03CF000FCC0B2B256 ++:10164000F3F0AAEB0000000043C38000FF00FF009E ++:10165000FFFF0000000000000024008100000000E7 ++:1016600000000000F5A0A0A0AAAA0000BEFCAAF0FD ++:10167000E8E8E8E800000000000000003C003C0052 ++:10168000AAAA000000000000BA30BA300F0FF0F034 ++:1016900055AA55AA0000FF000000FFBCFFA03000C3 ++:1016A0003000F0F03C00FF000000F8F82828F300BC ++:1016B000A8A8FCC0AAAAFC0CF000F03CF000FF00B7 ++:1016C000AAAA30F0AA2800000000C3C30000FCC092 ++:1016D000BE82FCFA0C0A008600F4A1B00005008668 ++:1016E000006400B08005018602E100B000000086C1 ++:1016F00000E108B000000086006408308000008629 ++:1017000000E001900000008650F4A198000501005F ++:101710000010080000000000A00050910000000030 ++:1017200000860C74A9F00485008602E100B90080EF ++:10173000088604F108B200100086006000B800803E ++:101740000886047008B200100086007401B9040015 ++:1017500000860074008000000000000090000090EF ++:10176000AAFF550000FF05FF3CFC00C000FF00FF82 ++:1017700000000000404F404FFFFFFFFFFFFF000051 ++:1017800000000000FFFF0000000000000008FFF75D ++:1017900000000000000000000000FB10FDFDFF3F06 ++:1017A0004D550000000000000000000000004F0F39 ++:1017B0004F4F0000000002003E3CFF280028003090 ++:1017C0000F3F0000000041414141000000000C5C5F ++:1017D0000C5C000000007CFC3C3C000000000600AB ++:1017E0000006AAFFA5F000C300C3BE3C82000101B1 ++:1017F000292900000000000F303FFFFFFFBF00005D ++:10180000000000000000FFFF0000000000000000DA ++:10181000FFFF00000000000000000000FB108080BF ++:1018200000034D55000000000000400000000001D2 ++:101830004F4F4F4F0000000000003C3CFF280028A5 ++:1018400000300F3F00000000005500550000000070 ++:101850000C5C0C5C000000007C3C3C3C0000000088 ++:1018600000000000000000003CFF3CFFFDAD5D0DEE ++:101870000C0CFCFC000000000CFC0CFC0014003004 ++:101880000000010000000000000000000000000057 ++:101890000C0C0C0C00000000000000000000F4E044 ++:1018A000FFD7D7FF0E4F00000000FFFFFFFFFFFF35 ++:1018B000FFF000005005FF3000300C14FFFFFF3038 ++:1018C00000300C000CFFFF3000307BE29966000016 ++:1018D0000000FC00FCFF000000003C3C3C3C000021 ++:1018E000000000000000000000003CFF3CFFF8A8E2 ++:1018F000580805F505F50000000050505F5F000036 ++:1019000000300000000000000000000000000000A7 ++:1019100000000C0C0C0C0000000000000000000097 ++:10192000F4E0280000280E4F000000007FFFFFFFBA ++:10193000FFFFFFF000005005FF3000300014FFFFF4 ++:10194000FF3000300C000CFFFF3000301D7B66992B ++:1019500000000000FC00FCFF000000007C7C3CFC60 ++:101960000400210002002000040000000300030026 ++:101970000000000004000000030002000400030057 ++:101980004100080000004100210002208200A00068 ++:10199000000008002002034000080400042000C0EA ++:1019A00000000000040008001108040004000420E6 ++:1019B0001000004088000420800002000400200085 ++:1019C000111121A00400000004000400080002001E ++:1019D00084000200001020000020042004400400C5 ++:1019E00011000000000000000200000000000000E4 ++:1019F000820000000400000000000400000000005D ++:101A0000000084000800000004000000208008009E ++:101A1000030000000000C08000808200A0008280DF ++:101A200000000040000010000100900000000000D5 ++:101A30000000010002001100008002000000000010 ++:101A40000000001000000000000000008200010003 ++:101A50002000400000000200000000000000000024 ++:101A600090000000000000000020200000000000A6 ++:101A70000000000000000004000200000000004020 ++:101A8000040402000000000000000000000000014B ++:101A90000000000000000001000000000000000045 ++:101AA0000001000900C00020008800208000002004 ++:101AB00000880000004000000001000080000020BD ++:101AC000840000000000030000008000A1000088E6 ++:101AD00000C00488020000A00000000000400000D8 ++:101AE0000000000000108200000000000400000060 ++:101AF0000000000004100000009000A00020000082 ++:101B000000800490001000000000000000000000B1 ++:101B1000000802000021000000200000000000007A ++:101B20000009000400080000000000000000101080 ++:101B300000000020000000200041000200211009E8 ++:101B400000091108000800030008000840081010F0 ++:101B50000020902101000003000020400209002124 ++:101B600002000011000000410000000021C08000C0 ++:101B700000000000000800008001880080001000C4 ++:101B80000301000005410009000000000000000002 ++:101B90000084001000010010001000000810001068 ++:101BA0000510000200820504000000104120209072 ++:101BB000000020820010008400408000100888840B ++:101BC0000010880085C010A1840041A005A08308F2 ++:101BD000110841C0001010C041400004000000A0E6 ++:101BE000008411400008008480A002000000000072 ++:101BF000100300000000C0050005020811000200EB ++:101C000011210008C0101088C0C090000000000022 ++:101C1000C0008220880200021008A021001091411B ++:101C200020001000A0101000108000000020820092 ++:101C30000200C004A0098200840910084041A010DD ++:101C40002120100408084041841011218400000262 ++:101C50000821100082100000821100000000200006 ++:101C600002050000820084080000200400000090AB ++:101C700003400000090041004100C10080008000D5 ++:101C80000500100000008001090010001000110084 ++:101C900010000500000000000000040000820400A5 ++:101CA00000004100000009880200118400000200C9 ++:101CB000020083000500110089008000400002003E ++:101CC00020004100000088014100000120000800C0 ++:101CD00000901040000000001082100482000240BA ++:101CE000090041400200084083408488020000004F ++:101CF00002001000A003000308000800040408000C ++:101D0000400000208804000310100000A021000003 ++:101D1000820000008400000000000204A1000021F5 ++:101D2000000000080021900500218800002100002B ++:101D3000082108084000C003082108052003A1006D ++:101D400009400120080802004002002000409141A3 ++:101D50000003A00904030809040408040089100012 ++:101D6000C0000000002185009000084120410000D3 ++:101D70000000000003000000000002100900400005 ++:101D8000A10040018805800100002182C02180035C ++:101D9000080040A008000884000100A1030800001A ++:101DA00000000000008200020000008420004100CA ++:101DB00000001000000220880000051041004108CA ++:101DC00005000885400840C0000400840810102069 ++:101DD00005894002030204902000410204C0000073 ++:101DE000008409821004108200A0008841100000C5 ++:101DF0001082000082000011001100210000840008 ++:101E00001121042101200504024000008200041079 ++:101E10000820002110000200100010100002000035 ++:101E2000000000400805C005404020048400002157 ++:101E3000101100000200200402102004080300001A ++:101E40000811200901082010830300028821834023 ++:101E5000018984400000C000C000840288000000A6 ++:101E60001000A010000000000000824002040009E1 ++:101E7000A004030000000000090011010900000097 ++:101E800010000088022182014000000880109001AB ++:101E9000000008041184050041002110094003845A ++:101EA000109000881100212010C0020800080000D6 ++:101EB000001005100000090041100910102009C091 ++:101EC000020002C10410802084C002041008109097 ++:101ED000900400890388004000100008004000883A ++:101EE0000090008408200000098480C1000800825E ++:101EF000008400111082000000080003821000001E ++:101F000082000011C000828204408320209140A002 ++:101F100040200209208088000000000000410041AC ++:101F200000000800820400050005082100000005EB ++:101F300084038441080000000408201004000840C5 ++:101F4000A00088030020080304080340A11090416A ++:101F50000100020900048405820000002000041131 ++:101F600000400200A0000010000000410802200410 ++:101F700000000000202000108080830000C141C1CB ++:101F800000000380804183A0088088000002C11106 ++:101F90000380C08000C108000000830000C183C12D ++:101FA00080000380801021C10380830000A00341D2 ++:101FB0000500800080A103000080000083000088ED ++:101FC00083C18000038000C183A02000800000C086 ++:101FD0004008C0808300800808000000830000885B ++:101FE00083C1800008000021832005000880008351 ++:101FF0000321900083808002030082048384A0C1B7 ++:1020000011C10082010882A183C10504051000836B ++:1020100041000108821008A101000082838290C162 ++:1020200083C1028201C0200302C001044182000377 ++:1020300001010082C00882A10100000000828382A9 ++:1020400008C183C140820110880583C101C0C0401E ++:102050000082910021A0838410910100008283827C ++:1020600008C183C10282019082912184008291C0C3 ++:102070000083010083828310208301000400088212 ++:10208000000191C0828283820083C010411082834C ++:1020900000830900888340830011012182000482AB ++:1020A000008303828282A1820082C1210283828214 ++:1020B0000083C100838311C000830083000082007D ++:1020C000C08200830282828283820083C190038364 ++:1020D000A12000A103002102C005008301048200A9 ++:1020E00088820083028282824182008285919004EC ++:1020F000C0C1000902018320C1830083010980005F ++:102100008080004141800080028000A1890982898D ++:1021100041C10083884141A11020002140400000BE ++:1021200000800083888000800280008390204183AB ++:1021300009820083C100022082C100904003000098 ++:1021400000008089008388C00080028000828300B4 ++:10215000210390030003A00202408390008341A06A ++:10216000000000800083C0800080028000800303A4 ++:10217000048588830083830302098490008341409F ++:1021800000050000C1C183C10000000083C103C17C ++:10219000002000008208800000020000A141000031 ++:1021A0000011008080C1A0C100000080030309C1AC ++:1021B000004000008302000000820080C102000095 ++:1021C000000000030000830240410000000083097A ++:1021D00002C100C0000083828000001100000002E4 ++:1021E00080000011418088C1C041000000008321AF ++:1021F00089C10011000083830000001100008302E8 ++:10220000000000000004C1C111C10000008483412E ++:1022100000C100C100100882820000A0008208C135 ++:102220004000000000C082C182C1000000084104DB ++:1022300000C100830082838300000041001082837C ++:10224000A000000000000082838300910000008253 ++:10225000839000C100050020A1C1400000200020A3 ++:1022600040912000000000C083C1829100000082E4 ++:10227000834110C10082008283022000002000847C ++:10228000838300008305018283A102C083820183CE ++:102290000283C0830408011001820000908900823B ++:1022A0000101C010100500822141908283A00083AB ++:1022B000A08220888383010101830000C0C1011135 ++:1022C000010088C0000002830082219008838300FF ++:1022D0000183058210030508010900820000908235 ++:1022E00001040001C021108901829189088283C004 ++:1022F00000838382C0038300010100830000828287 ++:102300000120010110030283418041A1008302806A ++:102310000483858380830911418441900000050373 ++:1023200020822102008891032080410200A1020046 ++:1023300009830510001102A020030283000085C15B ++:102340000441021100840000838340800240008821 ++:1023500002002083C0838088908202204185000093 ++:10236000088904C00821800291030280410200A074 ++:10237000020011834088008802404102038300006C ++:1023800004C00440020880C1000000000000125098 ++:1023900081600013C200124241840013C2008242D5 ++:1023A00000000000000012000000000000001242C7 ++:1023B00041820013C20012428150000660001242A6 ++:1023C00000000000000000420000000000000000CB ++:1023D000124241480004D000124221410013C200C1 ++:1023E0004242000000000000124200000000000015 ++:1023F000124221480042D000124221480042D0003F ++:1024000082420000000000001242FFFFFFFFFFFFBA ++:10241000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC ++:10242000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC ++:10243000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC ++:10244000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C ++:10245000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C ++:10246000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C ++:10247000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:10248000FFFFFFFFFFFFFFFFFFFFFFFF00300283A3 ++:102490000C44402000E80A0600006059AE5E0100CE ++:1024A000000000000000000000000000000000002C ++:1024B000000000000000000000807A75AE5E0100A0 ++:1024C000000000000000000000000000000000000C ++:1024D000000000000000000000007B750000AEDE80 ++:1024E00000000000000000000000000000000000EC ++:1024F0000000000000000000000000807A75AEDEE1 ++:1025000000000000000000000000000000000000CB ++:102510000000000000000000000000007B751E7B32 ++:10252000C002000000000000408C07000000000016 ++:10253000000030020000000000004003DE781E7B37 ++:10254000C002000000000000408C070000000000F6 ++:102550000000300200000000000040031E78000070 ++:102560000678C000000000000000008C070000009A ++:102570000000000030020000000000004003DE7890 ++:102580000678C000000000000000008C070000007A ++:1025900000000000300000000000000000031E608A ++:1025A000910000009100040004000400210091004B ++:1025B00004012000840020000000000020002020F2 ++:1025C000200008000000200490009100110020006D ++:1025D000044020000000020000000200000004008F ++:1025E00000000000040802000904040000000500C7 ++:1025F000020000012100A100840000000000111071 ++:10260000110000000400020021000200200021004F ++:1026100000A0020004081100040080884100A00806 ++:102620000008020000000800000000000000200078 ++:102630002000004001002000010000000000010017 ++:102640000180010001000400910021001000000041 ++:102650009100908082000000000000000100000056 ++:10266000200000000000900000000080000000003A ++:102670000000000000040000100002000000000044 ++:10268000000000000800020001000000000000003F ++:10269000000000000000008000000000200000009A ++:1026A0000200000000000004800080010000000023 ++:1026B000800000008000000000A1030180000000F5 ++:1026C00000000000040000000000110000000000F5 ++:1026D00000000484000080008000200000C003008F ++:1026E0000020000000C000000000002000000000EA ++:1026F0000000000080200000002091000000000188 ++:1027000000000001000800110008000040C000089F ++:102710000000001040C0000800004001004084009C ++:10272000001000110001004100C10800400200003B ++:1027300000410800041002000010000804082000F6 ++:1027400000000000001000000000820002030000F2 ++:102750000000820004200000202020002110000042 ++:1027600000000008002000000000041100800000AC ++:1027700000080000000004880411009002110010FD ++:102780000010000002400400C04082A1002100109F ++:102790000421001000110010009000080140A088E2 ++:1027A00021000008000202080001008400008000EF ++:1027B00000000300000000A08000008400000082F0 ++:1027C00000001000000000000584001000820020BE ++:1027D00000001104000000000010408805200000E7 ++:1027E00000A00000021000A00000008921100010CD ++:1027F0000941000021080000020840881000020280 ++:102800000000004000A0084000028040000280104C ++:1028100000400000004000840040002009400010FB ++:1028200000004008020009C0000800080000100075 ++:1028300008008400900020000000200040000000FC ++:10284000A0000004820000201000000000028200AE ++:102850000884A00020800000A0002000A0008400C8 ++:102860000000844000000000004000000240000022 ++:102870000000908800008490041000900000000088 ++:10288000000000208284400800830000108800843B ++:10289000088308804000009000000090002188C15B ++:1028A00002030010001001000800000811002002BF ++:1028B000100082000200000004000000040000007C ++:1028C00008000300100020844100040010002010C4 ++:1028D000050003008020032084014121200003889B ++:1028E0000300020008002100210103000000040091 ++:1028F000200005008804029000080200110000007A ++:1029000008090201020008901001050800000809EA ++:102910002000090400A000000000080002001108C7 ++:1029200009010002110304000900840041000000B5 ++:102930008380000005100100842011200020090080 ++:10294000004001000800C00001000000010000007C ++:102950000180C000A00004208289212010A08300F3 ++:10296000C000000810050041001100209000000088 ++:1029700000090009A0000400C01100001009004077 ++:102980008800882021400100030000088421A00461 ++:1029900002C00041C08000009000084100001021EA ++:1029A000C08008020880088200400000081020084B ++:1029B0008001000010002000410000888082000497 ++:1029C000000004014110040821020000000421005D ++:1029D0001000000110004100020004A003004102A9 ++:1029E00004901000088400002110034100200241DF ++:1029F000000080000090C088009100821140100209 ++:102A000000880010058802100002088800000200FB ++:102A10000088024003C041400008008809002120CE ++:102A20002090090220081008020400C003001000D2 ++:102A300003001008000001000103904000000204A0 ++:102A400000802011050820C089C100110400001178 ++:102A500040000000000800001000C01010401000EE ++:102A60000000840004000000000000400008002175 ++:102A700001020000100000000800000484104080E3 ++:102A800090080004C0080000018820804100001068 ++:102A90000300004001820008C08088210008000077 ++:102AA00040030005008088A1008000C0880840081D ++:102AB00000088800104002040000400100000520CA ++:102AC000000020820001110004840210020800901E ++:102AD0002110008811008040210108912088020007 ++:102AE0002100101002080410411083888008210181 ++:102AF000100088000000101021000502001041C0E5 ++:102B000010081000200000A011848284008420108E ++:102B100000848040828205A0804004101020009034 ++:102B2000002041080084000840820902A102110827 ++:102B3000000804101010010005800000C110000002 ++:102B40000000000000000002000089008500000075 ++:102B500000000000000000044000100402400009D2 ++:102B600088418800030001000000100020000400DC ++:102B70000020900004000000000808009091100060 ++:102B8000A040A040A000101100008211031008090D ++:102B90008280080002910210000020801091002124 ++:102BA000A04100401000000082C001000089208583 ++:102BB00000000041C0A0A008008308890320004154 ++:102BC0000880000000004100108010008300100009 ++:102BD00021C04180009003A000000000110000000F ++:102BE00085A000A109004000A08804A04182A1089E ++:102BF000C0038020040504020000C01000A11009D9 ++:102C000008C01005080220100985808508908008FA ++:102C10000004200500842084101103C11040020923 ++:102C20000884000005001000000091838204000069 ++:102C3000000940800900000041802083858500054F ++:102C400000910082000200040020038291A0200471 ++:102C500003A00105000200C00141900040000000F7 ++:102C60000400118800A0820000C01008888500853B ++:102C70008421052182A0A1830088000040010884EE ++:102C800088020105009108210040002140830011C5 ++:102C9000C00500000205888589400140898321899B ++:102CA00001020011C002C008008208C0910910058D ++:102CB00000C000910182002000A000080300110064 ++:102CC000118402020400000021100100050220000E ++:102CD0002182020000000084000100400000000189 ++:102CE000000001000500820089040909010040017B ++:102CF000102011011188880008A0A0080000040815 ++:102D0000A020090482A0010102909103918289010F ++:102D1000C0100911090201008302A1108202020100 ++:102D2000C000C102A08308038200100410A0A1000B ++:102D3000C084A10085C00800098221058390A041BC ++:102D400082009180A11184004100850020009180C3 ++:102D500082100800A10521050080050321800900DB ++:102D600011041000081020044003850090A00811F1 ++:102D700009401100A041A1080400C0800009000022 ++:102D8000A0001000050204210803904005200880DF ++:102D90001002C00005829008100240800580C080AB ++:102DA00084029102850004108003000980008000E5 ++:102DB00091044000900083898411028085114100B4 ++:102DC0000380000008A111030008004080100011DA ++:102DD00000C08540C19080C0212100100020030068 ++:102DE00080000080040000809009808520C08382DC ++:102DF00010210805A088210509800283A18405C04F ++:102E0000000082828090C1A10388898900028885A0 ++:102E10000091048380021183902040910020A1053D ++:102E20008404A0C0411004109008000080000080BD ++:102E3000000000400080809082030010A04020022B ++:102E400000040110A082888441880001A0010801CB ++:102E5000000020020820048540020000A001820139 ++:102E6000910020880010004090822104080911A0E0 ++:102E700089090320C1850984050300208202108589 ++:102E8000C1100000820904A184100310102088845E ++:102E9000C0840404A020880282A004A0019108A09C ++:102EA000098984838484018400C010C100A00202C7 ++:102EB000A084000800084040A01191110001050104 ++:102EC0008200400001044182820103C00010000022 ++:102ED00000000021000400A1000000828404A085FD ++:102EE0002000C0000008000900020001C0A0880402 ++:102EF0000400000010904003100210A0088420007D ++:102F00008200008900008900A1C0080085C08541B9 ++:102F100040101000C0C085058904A0011011830075 ++:102F2000048205A1A1108402211002001100840175 ++:102F300090022088C08385C109A182A0A0901120A1 ++:102F4000C090C001A0200320900510402080008088 ++:102F50000005001000880003008400400080A1806C ++:102F60000040850382000080008400040005A089E1 ++:102F7000A18020082000000500C100890080808019 ++:102F8000800200080008000003000500A040058042 ++:102F900082C00880A00208C08802A1A01010C185CC ++:102FA000210021802010C1008580908005099000BB ++:102FB0008010000080008088834191914040808093 ++:102FC000838080004041210000000013C200820085 ++:102FD00000810013C200000000000013C20000883E ++:102FE00000000013C200005000000013C2000000E7 ++:102FF00081000013C200004800880000C2000000E9 ++:103000000000001300000A00000000820013C2202C ++:103010008250000000130000418100000013C20034 ++:103020000000000000000000420000000000C2009C ++:103030004200000000000000414800000000C20003 ++:10304000000021000013C2004200F0000303FF0053 ++:10305000000000000000FFFF000000000000FFF083 ++:10306000FF003E3EFFFF7F4F7F4F0000000000004B ++:1030700000003C0F3C007F3F7E3C00000000FFFF53 ++:103080006F6F00000000FFFF0F0F00001E1EFF66A5 ++:1030900099FF990CFFFFFFFF06C70606FFFF3E06DC ++:1030A0003F300F00FFFF3F0FFFFF2F24FF0C000CEE ++:1030B000FF0F663C00000000000000000000F00070 ++:1030C000FF3C8100FFFF3C3CFF663C0FF000030328 ++:1030D000FF00000000000000FFFF103000000000B3 ++:1030E000FF42FF003E3E06067E427E420000000098 ++:1030F000000000003C0F3C006F0F66000000000065 ++:10310000FFFF6F2F00000000FFFF060000001E1EE3 ++:10311000990000FF000C6E0C660000C30000FFFF6A ++:1031200000003F300F00FFFF3C002F242F24FF0C36 ++:10313000000C000F663C0000000000000000F000E2 ++:103140000000FF3C81000F0F7E7E00663C0FFFFFFA ++:10315000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10316000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F ++:10317000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F ++:10318000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F ++:10319000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:1031A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F ++:1031B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F ++:1031C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F ++:1031D0000038239A0C4440A000180A060000304D25 ++:1031E0000000C0C3003F667F000000000000000038 ++:1031F00000000000F3F3F3F36060FFFF24FFE7FF3C ++:10320000000000000000000000FF66FF3CFFFCFF24 ++:1032100000603C7C0010F0107E7EC0FC7CFF7CFFD8 ++:1032200000007CFFFFFF0C0FFCFF3CFF3CFF30FF6A ++:10323000FFFF0000000024F4FFFF000000063CFF39 ++:10324000FCFF3CFC7EFE0000F0FC000000000000E3 ++:10325000000000818100000A000B000000003030F7 ++:10326000303C7E7EC0C3003F003F000000000004F1 ++:10327000000000000000000091007C7C7C7C242485 ++:10328000E7E700000000000200000000660000FF09 ++:10329000F0FF00600060000000004242C0FC3CFF04 ++:1032A0003CFF00003CFFFFFF000FF0FF3CFF3FFF33 ++:1032B00000FFFFFF04069D9F24F424F40020002655 ++:1032C00000FFF0FF00F066F60000003C0000000088 ++:1032D0000000000000818100000A000400000000DE ++:1032E0000000003C0586046100B000850086006493 ++:1032F00008B00000A08650F1A0B80005008600616B ++:1033000008B00000A0865071A0300085A0865091C2 ++:10331000A3800005A086507CA8B0000500860AE0C6 ++:1033200000B000000000058600E400B00005008643 ++:10333000006100B00000A08602B108B00000008665 ++:10334000006000B0000000865070A8B000800086C9 ++:10335000006000B0000005860A7000B2001008840A ++:10336000004101B0000000003C3C0A0A00FF0000E0 ++:1033700000000000000000000000414100FFF2F2E8 ++:103380000202000000000000000000000000A05F3A ++:10339000FF0000FF51AEFEBEBEBE143C1C3CAAA006 ++:1033A000AA000C0F0D0F0000FFFFFC3C0F3F5F7FDA ++:1033B0001414140000000808FFFFFFFF00300F3F47 ++:1033C00080A080003C3C3C3EF4F0140014FF1FFF42 ++:1033D000FFFFBCA01F1F1FFFFF3CFF203FFF3FFF61 ++:1033E000FBCB3B0B00000000A0001C3C141400FFB2 ++:1033F0000000000000000000000000000C0C00FFB6 ++:10340000FCF00C00000000000000000010000A0AA0 ++:10341000FF00FF0000FF51AEFEBEBEBE003C0C3CF4 ++:10342000A0A00000000F050F0000FFFF3C3C003C87 ++:10343000557D343434200000000FD020F0000030DF ++:103440000F3F00A000000000000AF0F0000014147C ++:103450001F1F000000001F1F1F1F003C00203CFF1B ++:103460003FFFF8C8380800000000FF20FF0800FFF9 ++:103470003C3CAAAAAAAA3CBE3CBEFF08FF012D2DD7 ++:103480002D2DFFC33C0000000000000000000000E4 ++:103490000000EBFF140000FF03FC78787878555F9C ++:1034A000FFFFF3F3BE820CFF5DFF00003F30AFAFC4 ++:1034B000555DFFFFFEBEFAAA555FFFFFF0F0FFFA71 ++:1034C000FFFFFFFFFFF0FFF05000A000000C0C001A ++:1034D0000C000CFFFEBEFC3C3C7D3F7FFFFFFFBCB1 ++:1034E0003C3F7D7F50000020000F553CFF00FF0057 ++:1034F0000F0F5555AEAAAABA3CBE3CBEFF00FF0056 ++:103500000055AAFFB2B2B2B20000000000000000F5 ++:1035100000000000C3FF3C0000FF0FF078787D78CA ++:10352000000FFFFF3030BE820CFF5DFF00003F3018 ++:10353000A0A0555DFFFFFC3CF000000FFFFF000066 ++:10354000FFFAFDFFFFFFFFF0FFFE5000A000000CA0 ++:103550000C000C000CFFFAAAF00000550F5FFFA052 ++:10356000FFA0000F555F00000000000F553C080051 ++:103570000000210004400000A1000000A000800025 ++:103580000400041000000400910004002000040066 ++:103590009100802120101100002020000240000234 ++:1035A00000000200800088000220C000040000002B ++:1035B00020000400900203100000004002000400FC ++:1035C0000202020411201100042003408440034041 ++:1035D000C008910002000208904002004100040867 ++:1035E0008020828810000091000811000000000077 ++:1035F000000000000000008000002000000020000B ++:1036000008000000A0002000000008009000010059 ++:10361000000004002002010000050080000090006E ++:103620009000040000004000090000800200C0007B ++:1036300000000300000009800000040000000000FA ++:1036400000008200004000802000000010004000C8 ++:103650000400020002008400000008800000000056 ++:103660000000048010000100400400000000000081 ++:1036700000000000800003000001000020000000A6 ++:103680002000000000000000000191108000910067 ++:1036900002100000100004000001110004000400EA ++:1036A0000020000100000000000000000000800079 ++:1036B00000A000C08020800080008000000000008A ++:1036C0000091000000000000000000000000000069 ++:1036D00000000001000000000000000100110021B6 ++:1036E00000A1002100408008800800410000000285 ++:1036F0000000000000214021000000040000010043 ++:1037000000000500000082410021002020902000E0 ++:10371000200040A00000010002000008000000108E ++:1037200001100408000800200008002104210020E6 ++:1037300002000241000004000400040020210008EF ++:1037400000100004004000200009001100100000DB ++:103750000000020002400200000000000040009053 ++:10376000C0A0002040A00080108010A0048800218C ++:1037700000800011402011C000000084118400C1AD ++:1037800040010000110400C00284910402040010F2 ++:1037900002102000020020000090400800000000FD ++:1037A000110400001100001080C180008041001051 ++:1037B00000081001000000004009C041900900C14C ++:1037C00000108000840180C0002000900020212093 ++:1037D000200020820084001080C00000804000C0D3 ++:1037E0000084082000208482000800A020081041E6 ++:1037F00009400088004020088400004184410041C5 ++:10380000000411041008C090101100100280828082 ++:10381000008400001004080083410000118084002F ++:10382000000010000000400084111020401002022F ++:10383000008210801102C0020000038802A01188DB ++:1038400008108809400921024002A0A00020088534 ++:103850000890100810050205820004000041108045 ++:1038600000029000C180008905021088000010C08D ++:10387000098800A0000000808890020008A00000D5 ++:1038800000002000A0002001880341001100030473 ++:1038900005004100032183C190C01108209005401C ++:1038A00011000800050002824005040000000983A1 ++:1038B0002000081000200200020100000200200980 ++:1038C0009000040500000000100040008900410045 ++:1038D0008810051082000200000200A04040008510 ++:1038E000008410000801200408A0880180028009DB ++:1038F0000921C1894189108303101088000000004C ++:10390000000000000100210001041020004100001F ++:1039100000801000000000A00420080000800100CA ++:1039200000801000C0000002000011A00040000054 ++:1039300010040140C180000001000840000085051E ++:1039400091C0210001C0001000100005000004001B ++:1039500000000400A0002000110000800000110001 ++:1039600000200000200001408489100004044080F1 ++:103970001088000810088402000482000000000083 ++:10398000008441844184108403100010100421003D ++:10399000050003002010080003000520081084041F ++:1039A00005880020040000200000210803102109E0 ++:1039B000400900024001C0098008044003200000C3 ++:1039C000C0018920C000100341C000830010101006 ++:1039D00008858800C11180210008400000104008BF ++:1039E000410882404100C1008041108209118220BB ++:1039F0000840020810C09041050004040000088837 ++:103A000000000008000800218821822100000280B7 ++:103A1000820000110000010901000005008000047F ++:103A20001100821100028505A090102084804000C2 ++:103A3000C02020089020200808200200038084086D ++:103A400000004102020011028410A0218240840380 ++:103A5000032102201000049010A08210A000000892 ++:103A6000008000C10210101010020890011100081F ++:103A7000108500A11190090803C010000110100565 ++:103A80008510050000840900051000001084100056 ++:103A9000104020102184020000200000410010008E ++:103AA000A000090109008300050040010989800484 ++:103AB00000000040051083A0C01088001040A0A0A6 ++:103AC0000410000010091103100388A000109110C9 ++:103AD0000004081002C009C0080003840588020819 ++:103AE00000840000410010208384028283C009C04A ++:103AF000218500A0410190098008A0A108A0208292 ++:103B000008008841000900000000000000000008D3 ++:103B10000000410000000000010000C11000000092 ++:103B2000000004040208000004000000012000203E ++:103B3000042100000000000004050400090000004A ++:103B40002000110000001184008483C0110088004F ++:103B500004008490000000000000C040C00000008D ++:103B6000000000000000880000001000400020401D ++:103B700020000004001000201188108402080000BA ++:103B80000000000802840000820021000000000004 ++:103B900000000000000008000000080011001141B2 ++:103BA00091099108020211050311800240049088D6 ++:103BB00011100502881021031010400988100040E0 ++:103BC000101108050009008010058085891184887E ++:103BD000088580C0051109828305A0200511880988 ++:103BE00000808580200040800090021000800088C6 ++:103BF0001103111091A0110420118204A00400856A ++:103C0000200005C002840891000040000000000070 ++:103C10000000000000009000000002000000000012 ++:103C2000000091010800000000010000C000010038 ++:103C30000989020310A0C1A105010100040041008F ++:103C40009089098402900011000091018485090384 ++:103C500083020009A00404C000858801C08588C0D3 ++:103C600008A02010A0C0019001100003090110104D ++:103C7000000200C101C1C04100A0208809112040FC ++:103C800000C0048209059102010809000100200416 ++:103C900021000100000000000001C0004100A00060 ++:103CA0008201890190080289839000080001880937 ++:103CB0002000040103018909A00009100904C18240 ++:103CC000100040A04188C010820500009004C09000 ++:103CD00085A19010A188C100024040020400849098 ++:103CE0008900A1018800A1908388C0834104050850 ++:103CF000A1851101A0018300C18800820920848868 ++:103D0000C0851100044140010804C08482001000F5 ++:103D10004000030020004102200002200900A10011 ++:103D2000400080052003898008218982110040100D ++:103D30004090110291400402900808100800088089 ++:103D40008520820441800882840988880040C0114F ++:103D500040209002C084400508004080C0008200DE ++:103D60008840850041110511020005418588200029 ++:103D70002080858510051002100910800583A0841D ++:103D8000800003858341048989088980840200803A ++:103D90000080008000000000000002800080008998 ++:103DA000004000820089040409090889C1890302CE ++:103DB00005092010A005400491400003A083114094 ++:103DC000411102908888842082A04091A1050000C2 ++:103DD00005112091100209830811041100894088FF ++:103DE000101000899183418300C08008888280A0E0 ++:103DF000881105200088110308040040880890C03D ++:103E000000828020A18885218984210582C1A108A2 ++:103E10000004002000840000020000080010008858 ++:103E2000000800400011C08901C0000000A1888284 ++:103E300021000000010109010005A10000A08889FE ++:103E4000002000020085081108900804A184830561 ++:103E5000000002A001110421200300000011C08510 ++:103E60000405104182C0414009880009C0A008052E ++:103E7000C0A18440408400090841100084C010C1E2 ++:103E8000908300038405098485C1210804A12008CA ++:103E900091820000000000000020000000010001ED ++:103EA00000000002008200000082830388A08300DB ++:103EB000C0C0014000840000002002A08905A100CC ++:103EC000A04000C00084000001018488C1A1828458 ++:103ED0001190000083889141C10385408503A19121 ++:103EE0000200A188820409849000880884410405A6 ++:103EF0008884C08402414111210002C09091880849 ++:103F0000C0018888C00010410910850982C18483DE ++:103F1000C0890440000000080008000000000040C4 ++:103F20000020000000050088000000808911881032 ++:103F30004002040003800520100800020800C14070 ++:103F400008040980000440000841111084914021B8 ++:103F5000038921000000830911080208888083C1B9 ++:103F60000408A008048091C084042010A0008002EE ++:103F7000020302890300848305C19041208080915F ++:103F800080100021808008410891A00491118021B7 ++:103F900000A000A100800000000048000000120006 ++:103FA0000006C200000000000013C200115021886A ++:103FB0008013C200410000000013C200060081000F ++:103FC0000013C200000000000013C2000000000047 ++:103FD0000013C200008200000A900013C2000050CB ++:103FE00000000013C20000000000001300000000E9 ++:103FF00000410000C200824800000013C2004100DE ++:1040000000000013C200006000000013C2000000A6 ++:1040100000000013C2004200000000000000000089 ++:104020000000000000000000000000000000000090 ++:104030000000FFFF207F207F00500500AA0AFF0F2D ++:104040000000000100553F3F000C00000C5DFFFF29 ++:1040500005FF3DFF0CCFCFCF00000020000800017E ++:10406000000000C30030FFFFFFFF0CFFFFFF3C3FDD ++:104070007D7F000400000C0C0CFF053DFFFF000CD1 ++:10408000300000000000A575AF7F495DCBDF002048 ++:10409000DFFF00000000013D83BF000000000000C2 ++:1040A000000000000000000000000000000040C010 ++:1040B00000001E001EFF005FA0FF005005008202EE ++:1040C000C3030000000100003F3F000C55550C5D8C ++:1040D0000C5D05053D3D0CCFCFCF0000000000007A ++:1040E0000000080000C30030005504510C0CFFFF15 ++:1040F0003C3F3C3F0000050000000000053D053D41 ++:10410000000C30000000000000200A2A081C8A9ED3 ++:104110000020DFFF00000000019701970000000071 ++:10412000FF0FFF1F00000000F0F0F0F000000000A3 ++:1041300000040004FF00FF00FFFA000A0020000056 ++:10414000AAAA0000FF3CFE3CFFF8FF280000008008 ++:10415000FFFCFF3CFEFABEAAFFFFFFFF0000FFFFCF ++:10416000BA3000000000B23C000020000000100047 ++:104170001000FFFF3C3C00000000FFBCFFA0FFFF61 ++:10418000FFAABA303030F0FF3CAA7D747D24FFFDD9 ++:1041900000088200FFFFF0AA3CFFFEEBC282000095 ++:1041A0000000FFFFFFFF00000000E8F0F0F000005B ++:1041B000000000040004FE0EF202FFFC000C0000F0 ++:1041C0000000A8A00105FF00AA00F8F82828800038 ++:1041D0000000FFF0FF00FCF03C0000C000E8000021 ++:1041E000BA30BA3000000001B20000000000000048 ++:1041F0003C000000FFFF7D7C00000000FF3CFF0052 ++:10420000FFFFFF2830303030F0003CAA287428240B ++:10421000FFFD000882000000F0AA3C007C6940001D ++:104220000086006008B000A0A0865061A9900085BB ++:104230000086007100B00000000200B5010000001F ++:10424000A58650F0A0B0000500860C91038900857A ++:1042500005860AF0A0B00005A18650F0A0B00005C8 ++:104260000000A58650F5ABB90085058602F008B0C0 ++:104270000080008400C100800000088E006408B047 ++:104280000000008600E108B20000A0065AB1A88034 ++:104290000005008602F100B80015A0865AF1A8B802 ++:1042A0000085000000000006000600000000000F6E ++:1042B00000FF00000000F5F55555F720FCFC7D7D62 ++:1042C00014D700000000000000007F805FA00041C4 ++:1042D000FFBE0000000005FF3DFFFFFFFC3C0CFFA0 ++:1042E0005DFF0000001000000000555DFF00BC00F5 ++:1042F00005FFFFFF3000F000555D55F7AA8228004A ++:1043000010BABABAF03CF0003C3FFFFFFFFFFFFFDE ++:104310000FFF0FAFFF04FB000FFF0FFF3CFFF0AAE2 ++:1043200024B42EBE000000000090009000000000A9 ++:10433000000F00FF0000000075F55555F720C0C0C4 ++:10434000414100FF00000000000000007F805FA0EE ++:104350000055FFAA0000000005FF3DFFFFFFF00031 ++:104360000C0C5D5D0000000000200000000CFF0050 ++:10437000A00005FF05FF3000F000555555FFA28253 ++:10438000200000000000F03CF0003C3CFFFFD0208B ++:10439000F0000FFF0FAFFF04FB0003FF0AFF3C001C ++:1043A000F0AA24142E1E0000000000C300410000EB ++:1043B000000000000000000000002F0F0F4F000061 ++:1043C000000055FF383D0000000055FFFFFF7F5FF4 ++:1043D00080A014EB10EF000000003C3FFFFFFFBC8B ++:1043E000FFA000000001000030003C003C7D3F7F4A ++:1043F000FFFFFC3C0F5F3F7F7FBC7E7E0438FFFFEA ++:10440000FF3AF03A0F3F5F7F78782828053DFFFF9D ++:104410000000000028FF18FFFEEAD6C28F8C0C0CAB ++:10442000AAF0FF3C0C0CCFCF0000000000C30041FD ++:104430000000000000000000000000000F0F0F0F40 ++:104440000000000000AA383D0000000055FFFFFFFB ++:104450007F5F80A014EB10EF00000000000FFFFF53 ++:10446000BCBCA0A0002000000000300000000055EF ++:104470000F5FFC3CFC3C00553C7D3C3C3C3C003C24 ++:10448000FFFF0F3A003A003C557D78782828053D1B ++:10449000053D0000040014FF0CFF7C685440BFBCC5 ++:1044A0003C3CAAF0003C034D034D210021002000BC ++:1044B000000011820000200004000400000004003D ++:1044C000200004000400000020000920110000006A ++:1044D000110000A003000008210004000888040067 ++:1044E000040004000400020004C0000021C0000811 ++:1044F0000300200003000400032004A005000010B6 ++:10450000000011004108000000840488040011002C ++:10451000048204A021400400200004202020200068 ++:104520001100041004002108000004000200000033 ++:1045300000008200000000000000000000000000F9 ++:104540000000A000000000000000000000000000CB ++:1045500004002000200000000000C00000009000C7 ++:104560000800A000002000000000821000000000F1 ++:104570001000001090030040C003820000000400FF ++:1045800004000000880082009002820000002000E9 ++:104590008200840088000000000008000800040079 ++:1045A000A0008800A0008200000000008800000039 ++:1045B00000000000000000000000000000000000FB ++:1045C00000000000000000000000000000000000EB ++:1045D00000000000000000200020000000C00000DB ++:1045E00000000000030000000000000000200000A8 ++:1045F0000000000000100000000000C0000000A04B ++:1046000000000000000000000000000000000004A6 ++:104610000000000000200000000000200020000436 ++:1046200000900020008200000084008400C0000090 ++:104630000000020000110041001100000000901075 ++:104640000200000000100021001000000010000017 ++:1046500000000400900000000421001082000010FF ++:1046600000000010002100100011000000100000E8 ++:104670000000001000100200021082100010002143 ++:104680000008101000410020820800000000020312 ++:104690000220000500100020000802100010000099 ++:1046A0000041001000210020002000000000002038 ++:1046B0004010000000000008090000100000030086 ++:1046C0004100000041000000001000000000410017 ++:1046D00021840010001003000502211000000000DA ++:1046E000210200100400030009A004C000004000E3 ++:1046F000080000000400110041840088410005000A ++:10470000210002400000110011400290030000004F ++:1047100008900010090800000888050005A0008422 ++:104720004100410000000910088402100400094003 ++:104730000008000000210000000000001000100927 ++:1047400000410000A00000050000000582000041BB ++:104750000000100084000041C00288058200C000F3 ++:10476000C01084009040A01190418441844000001A ++:104770008821844100000421100982411040A000DA ++:104780000000A021042100088200402110008421A3 ++:104790008400002100110800000540410200104182 ++:1047A00004031005A0038840C021A00982008240B4 ++:1047B0008240820308400000110010000000000049 ++:1047C00000001100000000004100200002000088ED ++:1047D000040020000200200009001000000000007A ++:1047E0001100000000C000100400090002000300D6 ++:1047F000410020000000000000000000200009002F ++:1048000000002100410009000000400405000000F4 ++:10481000000000020800210000000200419000900A ++:10482000009040824082000408000500040011004E ++:1048300020004100050000000021200000000803C6 ++:104840000000001008410005100982030803000061 ++:1048500090098400881182002000400902000003B2 ++:10486000040382110009002100410000C0009000F3 ++:1048700000008800A000880800008400904190009B ++:104880000205A0408440A000A009A0001011C011A2 ++:10489000000004411041C00000218408C011080438 ++:1048A00008418809904110000041A01188110209B7 ++:1048B0000421000900410000002100000000000068 ++:1048C00005000000000010000000050010100000AE ++:1048D00000000000000000001000001010000500A3 ++:1048E000000000200000000004004100050000104E ++:1048F00000000000058200C0038400000900009051 ++:1049000000C0418800C000882100210005A00300EC ++:104910001002000200000300200800000082009046 ++:104920000000001021000008100805000010210000 ++:1049300003A0084000002100000000000009000062 ++:1049400088008800000000008800001100050802AF ++:104950000020100520059021840008081021100374 ++:1049600010020010100000001003C000001104111C ++:10497000C00888038821042104400803000082093C ++:10498000C003842100408400C0418200081040051B ++:1049900088088209004100020203881004080440CC ++:1049A0000403000500218809001184219021A02121 ++:1049B00002118400881102098400A0008411000003 ++:1049C000000000080084411000000000000000000A ++:1049D000020041000200110000002000050000005C ++:1049E00000C00000410000080400000011000200A7 ++:1049F00009000000218440000000020000040000C3 ++:104A000010822082000400000890000002020000D2 ++:104A100008000400008400881040000000400200EC ++:104A200004820000100410100000210020820940C0 ++:104A3000048409820884054000A02184419000403C ++:104A400000000420000000000000000088000800B2 ++:104A5000000000000000000000000000400088008E ++:104A60000005002010408840820004000000100370 ++:104A7000000000002000200200000000001140049F ++:104A800000000000001188039020022000110200A5 ++:104A900082411010200440100010100582051041C2 ++:104AA0008200820082000421040310000021200300 ++:104AB0009009000982090011000084410221C021EF ++:104AC0009008FFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:104AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:104AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:104AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:104B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 ++:104B1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5 ++:104B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:104B3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:104B4000FFFFFFFF00A0E41C0C44401000000A0619 ++:104B50000000601804002000040040001100214003 ++:104B60000400110004002000410104009100110024 ++:104B7000040004000001A0008200400004000200C4 ++:104B8000040084080001110020A08400020000003D ++:104B900000080320000080038421A00988912108D7 ++:104BA000000409000484211121004020040911009F ++:104BB000110021000202C1089100900103000008C9 ++:104BC0000000211004000001820104000221830082 ++:104BD000200104012040000000000000000000004F ++:104BE00000000000C00000000000044000002000A1 ++:104BF00000000000900000082000200001000000DC ++:104C00002000000041008204000000100403004165 ++:104C1000000304002000000008820590058805407C ++:104C2000008000808411200320C00000218020A08B ++:104C30000000400082000380040040000308900050 ++:104C40000480000020802000200820209100088897 ++:104C500008400008844000C00400800008000000F4 ++:104C6000000000000000000110000000808800002B ++:104C7000000102000020001000400000800210002F ++:104C8000002000880000002080000000000080104C ++:104C9000000000000020002000C0002000000010E4 ++:104CA00000000000040000000041800000008001BE ++:104CB0000000002000008000000000100000001034 ++:104CC00000000000000000002000000080900010A4 ++:104CD000009000200082002000210100040001005B ++:104CE000000000000200000002200100000040104F ++:104CF000000082040200002040000000000002804A ++:104D0000050000000021A00020100220002020212A ++:104D100004000020001000100010000084A000001B ++:104D200004A000100010910000000284081004206C ++:104D3000024000110010001002200020002100009D ++:104D40000000400900090021001041000021100866 ++:104D50000408002000100220000004080000800069 ++:104D6000000000A00000000000000208008210A067 ++:104D7000000082A00000020211C00884800200002E ++:104D80000084108500108000030004200510040436 ++:104D90000003848800000002110005010000C00526 ++:104DA0000001851182C18001001005A083A085103B ++:104DB0002110C14191000008800902010008800013 ++:104DC000100002080284C1C10208C0402040A109AD ++:104DD0008910042004200089059100A00010000023 ++:104DE0004000000000001000000000000110000062 ++:104DF00001000000410000000180000001002000CF ++:104E00001000820084040000200000009080000058 ++:104E100000001004080200410000C0000040000033 ++:104E20000582C00808880420044000000000200516 ++:104E30001080004104A004100000202000408200E7 ++:104E40002000A00000C111411008840005890080E5 ++:104E5000104004009180019020040020A000000474 ++:104E6000410005000082C100050010000000100094 ++:104E700000000500050003001000100000000008FD ++:104E8000004005880002001020040000A00000007F ++:104E900003A00200040088000500050004000401CE ++:104EA00000000801080082018400100420001000A6 ++:104EB00004000089200090008491209021000000CF ++:104EC0001090400000820201000104000200400036 ++:104ED00088000800040003001000100010014001C9 ++:104EE00000000000002000004000000000008200E0 ++:104EF00000000010000082008400000004218200F5 ++:104F00000800100020000080008000030000200046 ++:104F100008008208831000102105000000000140F5 ++:104F2000012000000920010003200200020091007E ++:104F3000000001000010C0000410054011008800AE ++:104F4000C000820085030003C040002001218220B0 ++:104F500010210405001011100000040000200004BE ++:104F600009040800000000000901100120410000B0 ++:104F700000890588410009100082050000880010A2 ++:104F8000001003001000004010100200200010006C ++:104F900005001002090000010000090010000000D7 ++:104FA000084010200000841084C01021102000A0B0 ++:104FB0004082041004844108044091200482048447 ++:104FC00000820508008821A0000802090982210941 ++:104FD00000108085410802C120000401200905015C ++:104FE0000400000008040400000000080004012080 ++:104FF00008000040000000000000000000009000D9 ++:1050000000000000000001000080000001210100FC ++:105010000000000000800005040400058421002138 ++:10502000000000C100800000058021000188008090 ++:105030000000850001008900C082A021408000009E ++:1050400000080000000300210020000010200000E4 ++:1050500088880000020200800040012008200040F3 ++:10506000C040011100000080030010000000020099 ++:1050700021082090200084200000100021822100BF ++:105080000010098304002004001084850200001031 ++:105090001188020009002020100010000000030009 ++:1050A00011101084022000C00000881004849000B9 ++:1050B00002000384008483042000110400100420F3 ++:1050C0000420080040082082001082C0041041081B ++:1050D000080905090200090309101008022105202A ++:1050E00021200020002011A1000088001000A00055 ++:1050F0000000000085100100204000210841084008 ++:105100000000000000024000202010000240024089 ++:10511000900000002000000083000000000000005C ++:1051200000000000000000800000000005001100E9 ++:1051300005001100000010000200000000008209BC ++:10514000008000C0020002118900C0004002030874 ++:105150000005C0409088880300820280008001A082 ++:1051600000800080000000200040000009030420AF ++:10517000000841A0200280091120032108039009A2 ++:105180000805080400000000410000000809850827 ++:1051900040030320000000000000000000000000A9 ++:1051A0001000008008030009050840110080908568 ++:1051B00002A08909030888888909098209828480F4 ++:1051C0000500400003000905002002201020000017 ++:1051D000050008000000800005802100000080829A ++:1051E00083048089009105118304094005C04001B2 ++:1051F0000090008201400001C00100000100000198 ++:10520000C1000101000000000400000000000100D6 ++:105210001001090001000000C00000000000009023 ++:10522000889001080010880184000000010000003F ++:1052300089838408C1040005918810098904A0109D ++:1052400009A08502A14001400089908800C0880122 ++:105250000000C1000200000084008508A00090004A ++:1052600084A00209204100C000C004000003002106 ++:105270000000010001000100898284820521058966 ++:105280000800842004010541900041820400098443 ++:105290002100824020202091000000010020000019 ++:1052A00000010000000000010400200010C04000C8 ++:1052B00000008900082001A083830940899184109F ++:1052C000400109040020A1038208A10000C0098850 ++:1052D00002408410A0001108C0C1854020040910BC ++:1052E000C082010000000002001040000282411054 ++:1052F00083111140080008004003028985009010C6 ++:105300000911081090000841081104402080A000F5 ++:10531000C08011410221028302C1000000200080F0 ++:105320000008004000030000000304009100840016 ++:10533000090000001102410310808291A080044006 ++:10534000090885414082040585A1C184020320909B ++:10535000051190214103A103858088118588208053 ++:105360008500840210094120110003800300C02041 ++:1053700005C1A0C11108000584091008028200209F ++:1053800040090821402000900004058800000080AA ++:1053900008000000088300002089880980000000C0 ++:1053A0002100800080000080020000800290002028 ++:1053B0000002008300004008219003824103028321 ++:1053C00083840810009000888004108800108004F6 ++:1053D00000891188400880114120000580C000002C ++:1053E0000208401100A141802080000041001041CE ++:1053F0008541A0A0820400014001A00040010111EC ++:10540000000400034108000500100004A111000879 ++:10541000000800A00090902000A001A0400402021B ++:105420000002010404084000A0C005A0208800215B ++:105430000088000020400000A1090089C0910201FD ++:1054400000C0400483090411009082890085100384 ++:1054500010084002822190090408008900A004A0DD ++:10546000008200850110A0C100040188C09083A0C3 ++:10547000C00882022085409090000000900000004B ++:10548000830011410800100883000904C10009C00D ++:10549000830404008401A004010841048401A004E1 ++:1054A00000400084000000008204C04004000000AE ++:1054B000000000010000004000008304A010044030 ++:1054C00001C001C101000000000989A0A102400043 ++:1054D000C0A185C0A1090801412082058440208225 ++:1054E0000803822089A1022002102100219041009E ++:1054F000080001012091900001880000000880113F ++:10550000000089080202A020A1808302C004A10239 ++:10551000100089C100418202080003A0858488022E ++:1055200011800080000000000000808000800000EA ++:105530000000000800100008000000008480050240 ++:10554000410905004183090041031108032082201D ++:10555000830091409000C183880805008083000586 ++:1055600080898090C01190C0C021A080A0008900D7 ++:105570004100110010080841400911008284001305 ++:10558000C220000000600006C200064800000000C3 ++:105590000000000000840000600082008200001310 ++:1055A000C200004141000006C200000000000013DC ++:1055B000C2000050000000130000000000000000C6 ++:1055C0000013C200006021000013C20082004100ED ++:1055D00000130000414800000013C2004200000018 ++:1055E0000013C200428200000013C200000000004D ++:1055F0000013C200000000000013C2000A000000F7 ++:105600000000C280C2C2FFFB0400FE08FF000000D1 ++:105610000000BD9F249FF3F3C3C300000000990066 ++:105620000000FFFFFFFF00000000FFFFFFFFFFFF84 ++:10563000FFFFFFFFFFFFFFFFFFFF04082010000038 ++:10564000FFFFFF3F000000003F3F7E420FFF663C30 ++:10565000000000C0F6F63606FF7FFF7E3C0F66FFB7 ++:10566000000000003F3C0300FF00FF00FF000F0FA1 ++:105670003F300F000000000000000000EFC32C00CE ++:1056800000000000C2808080FFFF0000FF00FF00DC ++:1056900004000200BD062406F0F000000000000037 ++:1056A00099000101FFFFFFE700000000FFFFFFFF7F ++:1056B000FFFFFFFFFFFFFFFFFFFFFFFF0201408033 ++:1056C0000000FFFFFF3C0200080003037E420F00C2 ++:1056D000663C00400000060606063F3F3C3C3C0F8F ++:1056E0006600000000003F3C0300FF00CF0CFF00FD ++:1056F0000F0F3F300F00000000000060300000007E ++:105700000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 ++:10571000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 ++:10572000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10573000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:10574000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69 ++:10575000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59 ++:10576000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49 ++:10577000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39 ++:10578000FFFFFFFF0070FF910C44401000180A0655 ++:1057900000009065F909C0C00008000E00FF10FF6E ++:1057A0000000FFFF7E7EC0FC34B576F700000000ED ++:1057B0000000001003030303FFFFFFFFFFFFFFFFD5 ++:1057C000FFFFFFFFFFFFFFFFFFFFFFFFFFFF0C30AB ++:1057D000000005A00000707070FF24FFF4FF333359 ++:1057E000FFFF003C303C000000007E7E7EFE00207B ++:1057F000303000C030F00000000000000000000069 ++:10580000000024E724E787000000F300F3FF0066B0 ++:10581000606064FFFFFFF909CFCF0F080F0E00FF94 ++:1058200000EF2000EFFF4242C0FC109152D3000075 ++:1058300000000000000002030303FEFFFFFFFFFF64 ++:10584000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:1058500003C005A000000000606060FF2424F4F491 ++:10586000003300FF00003030000000007E7E7EFE2E ++:105870000020303010D030F00000000000FB000BA2 ++:10588000000000002E2EEEEE9F000000F300F3FF5C ++:105890002424606064FF64FF00860A0501B000856F ++:1058A00000A6007408B0000005860A6000B0000081 ++:1058B000008E006400B00080A58252F1A1B80005FE ++:1058C000A0865971A1900805A0865070A090080587 ++:1058D00000C6006100B000000000A0845090A0B994 ++:1058E0000000008600E101B80085058600E101A006 ++:1058F0000000A0865230A8B00000A08600F108B8D1 ++:105900000080018400E108B00005008600E100B0DD ++:105910000000A1865231A8B00005000050500000E0 ++:1059200000000505C0CF0000022AC0CF0505001009 ++:105930005010FCC0EBEB0F35FF35F7F7FF3C0000D4 ++:1059400000000000000000000000FAFA0A0000F564 ++:10595000F5F5000000000C0C0D0D00000A0A0A000D ++:1059600000000010000000000CCF7D7D0000000052 ++:10597000D70CD7CFFAFAFAFA0CFF5DFFFFF0ACAC08 ++:1059800020AD70FDFCC0EBEB1C1C1C1C3CFFAAF006 ++:105990000CCF0F0F000000000F0F05050000505046 ++:1059A00000000000F5F5C0CFAAAA022AC0CFF5F585 ++:1059B000A0B0F0B0FCC028280035F035F7F7C300E0 ++:1059C000000000040000000000300000FAFA0A00A5 ++:1059D00000FAFAFA000000000000050500000000CF ++:1059E0000A0000200008000000000CCF41410E0C0E ++:1059F0000200140C14CFFAFAFABA0C0C5D5D0F0019 ++:105A0000ACAC008D50DDFCC0282820702F7F3C00FE ++:105A1000AAF00F0F0F0F00F000F0EF4FE545002048 ++:105A200000000000000000000000008228AA000022 ++:105A30000000D4FC0000000000005F5F287D000033 ++:105A40000000FFFFFFFF000000000000000030BA70 ++:105A500000AA0000000000000000AAFF1E1E0000B7 ++:105A6000C000C30001010404B2B2B2B200FF00FFE3 ++:105A7000FC3CFAAA0000C3C3FFFFFFFF14555541C9 ++:105A8000000000001C1C1C1C0000FF009CDC9FDFB1 ++:105A9000FFFF000000000000B2B23C3CFBFF7DEBCA ++:105AA000000020000000000000000000A0A0A0A056 ++:105AB00000000000D4C00000000000000A0A287D99 ++:105AC000000000007FFFFFFF00000000000000005A ++:105AD00030300000000000000000000000551E1ED5 ++:105AE0000000C000000001010404FF3CC3007FFF70 ++:105AF000FFFFFC3CFAAA41C34100FFFFFFFA145527 ++:105B000055410000000020702F7F0000FF00004082 ++:105B10000343FFF30C0000000000B2B20000FBFFE3 ++:105B20000000040084008200080004001101040148 ++:105B30008401000020012100040004014000040150 ++:105B400011002000000811002101030104000200DF ++:105B50000301004020008408202020901110040040 ++:105B600004100000040011000400040010201120A3 ++:105B700011004003828403000400A00020014100C2 ++:105B800004100408210003918420821004040400FE ++:105B9000020120880200110204A00400200021203C ++:105BA0001120118282001000040001000000000892 ++:105BB0000040020200000008000000000040010058 ++:105BC000001000000000008000000002000401003E ++:105BD000030040200080010020004100040000007C ++:105BE0000000A00000008400000000000000008011 ++:105BF0000080A00005A00400000020102000044048 ++:105C0000000000800003200000200200410000800E ++:105C100000000040040000050000000084000000B7 ++:105C200000000000A0000000004000000001000093 ++:105C30000000000000000000000000000000000064 ++:105C4000000000000000000000000088000080004C ++:105C50000000000000000000000010000000000034 ++:105C600000000000000000C0000000000000002054 ++:105C70000000000000200000000000000000000004 ++:105C800000000020000000000000002000C000888C ++:105C900000C0000000C0000000000000082000005C ++:105CA0000000000000000000000004800800001058 ++:105CB0000000000000000000000090000000400014 ++:105CC00000080000A01000000000A000002100005B ++:105CD00002410000820002009000000090200000BD ++:105CE0000021A0210011820000000000904100006E ++:105CF000001000100000029082100021000000102F ++:105D000000210041000800080021001000100010D0 ++:105D100040020011001000080010020900210009D3 ++:105D2000004100200010002102108000000200103D ++:105D30000089002000200000009000A000000090DA ++:105D400040200010008800200002004000100000E9 ++:105D500000100084210200840000002000000808D8 ++:105D60000040009000C0001000A0000000000000F3 ++:105D7000000000008084001000A0890011110011B3 ++:105D800000010200001004100000001002020000D8 ++:105D9000028803020010008400848084001008A0A0 ++:105DA0000002098408C0008200080002040082008A ++:105DB00000001002C0000005400040008441C00007 ++:105DC0000200018990000008C0058208004100001F ++:105DD00082050009884100111010C00882000000EF ++:105DE00083031021000300098203C0410000000565 ++:105DF00082100021080004218400000040080404EF ++:105E0000900408040105402185030003080385056B ++:105E100000080008C083C00800080021022110000B ++:105E200010009000820010030021000000214100BA ++:105E30000500050084000500100009004100410034 ++:105E4000000010000088030000C02100A000100224 ++:105E500010001084080009001000200041002000FC ++:105E600010000208410000001000200005000000A2 ++:105E70004100080000004100040004000400040088 ++:105E8000200004004004040020000300040000017E ++:105E9000410003A0080020000200000010004000A4 ++:105EA0000000080008000800400000001000050085 ++:105EB00000000200000021000000000000000000BF ++:105EC00000000000000008000000880088000400B6 ++:105ED00000020000100000000200080001000000A5 ++:105EE00001000000200000000000A00000000000F1 ++:105EF0000000000000000000000011008900010007 ++:105F00000100C10001000080090001410000010002 ++:105F10000020100900210200100000050000001000 ++:105F200000000003A021000000000000002100216B ++:105F300000000000020241400010081002020202AC ++:105F400002C005C1088508404188100000100240C9 ++:105F500090898088A14088001089101120828002D9 ++:105F600020100000200000040510098800A0410056 ++:105F70000040000009C0000021100302880000203A ++:105F8000900085824100410004009000040210C08E ++:105F9000032000000089410080408003029002A09D ++:105FA0008020000100000082008205004100098479 ++:105FB0000300100000000840001004A100030005C9 ++:105FC000400088411020882000400400900002001A ++:105FD000900002200402040004058820000401004F ++:105FE000020001000010010000000003C02184082D ++:105FF000C0214000000084008400C0000000200395 ++:106000001080040340090021040083002000910057 ++:1060100088418810A040000410410291048489083E ++:10602000030920808420000388100021081010003C ++:106030001020841000030300100190100801208438 ++:106040000084000080400000100000204084008494 ++:106050000300110002000082000000840984C100D6 ++:1060600008000800100004002000001021000210A9 ++:1060700040000084000800002110098408C009A025 ++:1060800000000000008200200988100020C04100AC ++:1060900020C002820040004000088040202004848C ++:1060A0000000048209040820000400844088414064 ++:1060B000108400C0008808840011004004410204DC ++:1060C0001000840000000441000500000090000062 ++:1060D00008000000000008212000820000000002EB ++:1060E00002058200820000008410C00000008200CF ++:1060F0000000000000000000008000110000880087 ++:10610000000000008200000002800800C02090080B ++:1061100000100000100508090000000020000180A8 ++:1061200000000000010000000800008000000000E6 ++:106130000000000008000000000008838082418504 ++:1061400008824003C0044005414003830410040555 ++:1061500008118080828002000080848380C0418595 ++:10616000088902100004800811090490048200418B ++:106170004084000000000000000000C0000000009B ++:1061800000000000008000002180000000004000AE ++:1061900008008000A08310A000800840000020803C ++:1061A000C000008080008980838000801003000090 ++:1061B0000009100800000000000000000189844070 ++:1061C000104101408901C00100010100C18984C062 ++:1061D000028301042082C084011000080889044160 ++:1061E000A003000221880084042000200082008493 ++:1061F00000A10108000000000000000000000000F5 ++:1062000000000000000000881008C1A000C00400C9 ++:1062100085004100080004830085040800A100886F ++:106220004184200400C0409003204020000400016D ++:10623000000000000101000000000000000041001B ++:1062400000008900900441008400410040C1C00169 ++:1062500000008800C0C002000900C1001111040044 ++:1062600040008900A1820800C004910821010900B2 ++:10627000A0040509891000000000000000000000D3 ++:10628000000000000000000040001002880002C072 ++:106290000082000000040001A1110800831040905A ++:1062A0000001080088028441C021200020828483EC ++:1062B00001C00001004000000000000000000000DC ++:1062C0000841040088009005040889080800099125 ++:1062D00005400800830009800803080041000320EE ++:1062E0009005C00082000880100084004008090961 ++:1062F000880204002108099000000000000000004E ++:106300000000000000000000000080050000800088 ++:1063100000020080004100000041A0C08200410056 ++:106320000200000300110000008800888040800007 ++:10633000001102001020108010000000000000007A ++:1063400000000890000900848591400800081003AF ++:106350000520020800050803058800800080908061 ++:106360008080028980A0C08405C0000280048289E8 ++:10637000C0002008800880094004000000000000E0 ++:10638000000000000000000000000000000000000D ++:106390000000008080000400400000004002054032 ++:1063A0008020110580000380108000800080840020 ++:1063B00040000080100200110011110900000000CF ++:1063C00000000000010500C000A0418801830040DA ++:1063D00001A0918901C00000C0C001890002A00491 ++:1063E0008540844000048241400401890001C0408E ++:1063F00088852100010008018401010000000000DF ++:10640000000000000000000000000000000000A0EC ++:10641000000082A0008840020108019088900800D6 ++:1064200090018401C000082000102084900420C046 ++:10643000820202A004A0050000000000000000008D ++:106440000000000000008241C00100000440820002 ++:10645000100008010888C0918800C00000040401F1 ++:10646000400188001010040188414001C0028540AD ++:106470000040000009409111050990001008010139 ++:10648000000000000000000000000000000000000C ++:10649000A1A1880002000000001000080000000018 ++:1064A0000804844008910804C0A0049082020402F9 ++:1064B0008200204088828802000000400001000025 ++:1064C00000000000000000008020001000408080DC ++:1064D000800380400008000000408020000300008E ++:1064E000001000110002000080038088804080803E ++:1064F000892009880000200009880488040441805C ++:106500000820000000000000000000000000000063 ++:1065100000000920C00000004000000000800000D2 ++:106520000000800400028003008080008000008062 ++:1065300080808009800000800080000000820020B0 ++:106540000000000000000000000081500013C200A5 ++:106550000000000000210000000081000013000086 ++:106560000600008400066000000021000013000007 ++:106570000A5000810013C200000000880000C20021 ++:10658000000000000000000000000000000000000B ++:10659000000000000600001360000000004200132D ++:1065A000C200820000000013C2000050000000136F ++:1065B000C200420000000013C2004182000000003F ++:1065C000C200000000000000000000000000000009 ++:1065D0000055AAFF0000000000C33CFF00000000BF ++:1065E0003C4DFF4D000000000000000000000000D6 ++:1065F0000CCFD7D70000FFFF00FF00FF20207F7FD8 ++:10660000707F00FF0000000000000000000000009C ++:10661000000000000000FFFFFFFFFFFFFFFFFFFF84 ++:10662000FFFFFFFFFFFFFFFFFFFF008100240000CF ++:106630000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:10664000FFFF0090000600000000000000000000B6 ++:1066500000002D2D2D2D000000001717171700002A ++:106660000000004DC34D00000000000000000000CD ++:1066700000000CCF1414280028FF202F202F00A08A ++:106680005FFF404F00FF000000000000000000001E ++:1066900000000000000000000000FF3CFFFFFFFFC3 ++:1066A000FFFFFFFFFFFFFFFFFFFFFFFF8100240051 ++:1066B00000000000FFFFFFFFFFFFFFFFFFFFFFFFE6 ++:1066C000FFFFFFFF90000600000000000000000038 ++:1066D000FF003C3CF775E361FFF03CAAFABE50BEF8 ++:1066E000FF003C3C3F3F303000000000AAAAFFA260 ++:1066F000FFF03CAAFCEBFC28AAAAAAFCFFFE0302BE ++:10670000AAAAEBE8FFFF0000000000000000000064 ++:1067100000000000000000000000FFFFFFFFFFFF7F ++:10672000FFFFFFFFFFFFFFFFFFFF6900FFFF6009A3 ++:106730000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF67 ++:10674000FFFF2222FFFF22110000000000000000D6 ++:106750000000F0F0AAAAB634A22000F03CAAFA1475 ++:106760005014F0F0AAAAFA0AFA0A00000000000089 ++:10677000FFA200F03CAAC0EBC028AAAAAAFCFFFE18 ++:106780000302AAAA2B28BFBA1510000000000000BF ++:10679000000000000000000000000000FFFFFFFFFD ++:1067A000FFFFFFFFFFFFFFFFFFFFFFFF0069FFFF8E ++:1067B00000006009FFFFFFFFFFFFFFFFFFFFFFFF7C ++:1067C000FFFFFFFF1111FFFF00002211000000007A ++:1067D0000000000000860AC40180800500860A606F ++:1067E00000B0000000860A8001800000008600657D ++:1067F00000B0001000860A8101800000008600B50C ++:10680000009000000086007400B00000000000004E ++:1068100000000000000000000000000000000086F2 ++:10682000098001800800A08650F5A8B00805A0C620 ++:1068300000F108B00000A08659F1A8B00805A086B4 ++:1068400050F1A8B00800A0400010080000000000AF ++:1068500000004CE8100055557D418AAADFFF5555D0 ++:1068600000FF10150000FF0FFF000000C3FFBEBEB9 ++:10687000828200000000FF00BF800000FFFFC3C352 ++:106880003C3C0FF00FF0EBFCEBC000000000000000 ++:1068900000000000000000000000000000000000F8 ++:1068A000FF00FF0F8282FFFF00000000550F3CFF3A ++:1068B000F0AAFF3C000000000302010000C300003A ++:1068C000FFF0AA3C007D007D0000000000000000F9 ++:1068D0000000000000000000AAAABE8208AA5DFF16 ++:1068E000C3C30F0FBABF0000FA0AFF001400D7FF9E ++:1068F000FCC0FCC000080000FF00FF001000BFFF4C ++:10690000C3C33C3C0FF00FF028FC28C0000000007F ++:106910000000000000000000000000000000000077 ++:106920000000FF00FA0A00827DFF00000000550F02 ++:106930003C00F0AA003C00000000020200000043FE ++:10694000000000F0AA3C088A5DDF000000000000A3 ++:1069500000000000000000000000FFFC0F0C00FF22 ++:1069600000FF00000000A0A028AAFFFF00007D7D1E ++:1069700000FFAFA03F3F5F5F287DFFF7002000FFD3 ++:1069800000FFFF3AF03A55550F0FAFA03F3F0F35CC ++:10699000FF350000000000000000000000000000C3 ++:1069A00000000000FFFF000000FF00FF00000000EB ++:1069B000000000007D28F5F50505F5F5FFFCFFF06A ++:1069C00000550F55FFACF0ACAD55ADFF0000000019 ++:1069D000000000000000000000000000FFFC0F0CA1 ++:1069E000003C82BE00000000A0A028000CFF0C00AC ++:1069F00000FF00FFAFA030300A0A287DFFFF000033 ++:106A000000FF10BF0F3A003A00FF3C3CAFA030300F ++:106A10000035F0350000000000000000000000001C ++:106A2000000000000000F3F00300303000FF000021 ++:106A30000000000000007D28A0A0303F303F3F3C18 ++:106A40000F0000550F550FAC00AC080008AA00005D ++:106A50000000000000000000000000000000FFFF38 ++:106A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36 ++:106A7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26 ++:106A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:106A9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:106AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:106AB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:106AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:106AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:106AE000005492620C44405000000A0600006018F6 ++:106AF0000400040040000400000000000400110035 ++:106B0000000020000400110000010001000102014A ++:106B100004001000040004004100110108400401B9 ++:106B200008822100200004000220030003008404E6 ++:106B30000000202021200420042004080421032038 ++:106B400011052108080104080501040120010401C0 ++:106B5000040120040420840004000008080009083F ++:106B600091080000000080000300000004001000F5 ++:106B700080000100A000840000000000400001002F ++:106B8000A0000000000090000000000890400002FB ++:106B90002010001001000000000020000040400014 ++:106BA0000010020800000008000000800000000043 ++:106BB000208000000080008000800080900000881D ++:106BC00000808282000001080000040200080040EA ++:106BD000000220100480208004000800000005004E ++:106BE000200004000000022120002000000000110D ++:106BF00001201000000000400000800000000000A4 ++:106C00000000402000A00000000000000000000084 ++:106C10000000000000000020218200000000800031 ++:106C2000000080000000000000A000000020000024 ++:106C30001100000000C000000005800000000000FE ++:106C400000000000001000820000000000000000B2 ++:106C50000000000000000000000000A00020000074 ++:106C60000020800000A000C0000000900000000094 ++:106C7000000008208010002000C100004000022019 ++:106C8000000000004080000000000008002000001C ++:106C90000000000090000000A0039009C000001058 ++:106CA000200000102000001000410400022100100C ++:106CB0000021000000100000900900842020024103 ++:106CC000001000000420002000210010002190107E ++:106CD00000410020001000200011001000100008EA ++:106CE00000100010022002100021002000210021CD ++:106CF0000010002101102020000000020000000010 ++:106D00002090000120000000040108010803030195 ++:106D10000008000800900008001000A08004808493 ++:106D200000880041100200040000000000028010F2 ++:106D3000001000C000880010000000100020052096 ++:106D400085020000000203000020001000C00010B7 ++:106D5000840005000300210220004188040820204F ++:106D600000202084204005C109A010100000204010 ++:106D70000084800841100584000800110080000094 ++:106D80000000010008040305900841048404102059 ++:106D9000002010118800840900A1082110001010A3 ++:106DA0001000084108048208088200411005000014 ++:106DB0000221A0200020020000410000000000008D ++:106DC00000002010100084108800008000201000B7 ++:106DD000C00021039003C010C00001000005850021 ++:106DE00000A184A1090309000004000000020000C2 ++:106DF000011000000400C00008001041048800C019 ++:106E00000400040003008802C100200041A000002B ++:106E100003A041000082200003840002090010103A ++:106E200000020200030209044100090402004100BB ++:106E300010000090C10005100000200000001000AC ++:106E40000988200020000000210009002100050021 ++:106E500010002000000002000000000008002000D8 ++:106E60000000208200004100058210000200200185 ++:106E700000000300200090000500410041020100D5 ++:106E800082100108A100C0110400040000000810D5 ++:106E90008204000090000002C00040418408040009 ++:106EA000401020050800A000080282000000000039 ++:106EB000820008000004040082102000000000008E ++:106EC0008200081008000800080000001000000000 ++:106ED000102000000000002100000000000000055C ++:106EE000001010200005000000410005080000000F ++:106EF000010400001041010040000003A041008097 ++:106F000000020240401021000402052021080485EF ++:106F1000001040C1418810110010101010200810FE ++:106F20002191031000A0211000000000200484081B ++:106F300000100040080000840000030041000084AD ++:106F400000000002080004100500000240C0218477 ++:106F500000000002830209009010001005000040AC ++:106F600080208400040004400000208804400000C9 ++:106F700010880501A0838800034121A00241020876 ++:106F800008000221000000000000A1020080101093 ++:106F9000A10400090020A0000004000088000800EF ++:106FA0008800400200000400A00800099000C120F1 ++:106FB0000500A0099020A0000211A0208820000058 ++:106FC00010000000000000000000000000000000B1 ++:106FD00000000010C009080088000420820510038A ++:106FE0009021040005210120210304108500A00840 ++:106FF00000000000000421042008000400000140FB ++:1070000000000000000041000020000080109040BF ++:107010008040214003080010200005840002038402 ++:10702000090210000000000100010240000400A05D ++:1070300000040010008402100010008400004100D1 ++:107040000200410800008000100000000000040061 ++:1070500041000010080020889084211000C000909A ++:1070600041000000101009A0410041080420104018 ++:1070700080A0801080044100108441C010102100C5 ++:10708000410005C02008004082000000A000040567 ++:1070900004000480A0910005A000A10508410003A0 ++:1070A0000000C041880890090040044000000880AA ++:1070B00040000880A0000811000000118800A00016 ++:1070C00000000010000000C02000000000000000D0 ++:1070D00000410000000510008200020000100009BD ++:1070E00000000005080000000000002000000180F2 ++:1070F0000041200020052080000000100000002139 ++:1071000000000000100500008388001083A01040DC ++:107110001008100904419111A1A1894008414009BA ++:10712000110300041111830511090021000010044E ++:107130008840000910080808000080004000000096 ++:10714000000000000000000000800482028910108E ++:1071500041C1820302400805100910032004030501 ++:10716000400440090020C002110900808800888086 ++:107170000000000400090500401103400010001049 ++:107180000910089004C1004041108983A084A00523 ++:1071900089030100C101C00110001189A108820901 ++:1071A00000000000C0000000890001000001000094 ++:1071B0000100820040010001010100000200010005 ++:1071C00000000000000000000000000000884009EE ++:1071D000419001110401000191010000010103002F ++:1071E00000010000C10084010301000000881108B3 ++:1071F00083080010000000010000000001010000F1 ++:107200000000000101820084208801080101900231 ++:107210008900011002A00388A1858500108200A0CA ++:1072200088C18900A000880810010484C100C00042 ++:10723000C00404100400850041030984000000001C ++:107240000000000001820000000000010000820137 ++:10725000400490888988830108008888018800009C ++:107260000000010000211001A00882A14085080152 ++:10727000820088101010C000C0089000C1000100FA ++:10728000010800010100880040C0100090C01120DA ++:107290000008881020898980880088088940911119 ++:1072A00000809108090003044000890540A1020202 ++:1072B00084000900911040050800888809800000BA ++:1072C0000000000000000980090000000009000023 ++:1072D00004030200029009004010040004804108E9 ++:1072E00002050800410005A0000200800005009092 ++:1072F00000020000808000004000088000040900B7 ++:1073000040004180100809110402020880080200B0 ++:107310004104008402888880080840100009881011 ++:10732000000088C0800911C01182000805024008D1 ++:10733000080000114100200308110008000908900E ++:1073400000000000008000000000000000000000BD ++:10735000000004400090000900800904009100042E ++:107360000590024000A004918520112100080084AE ++:1073700021400080808008000080088800904089BB ++:10738000888803080009100940400540000289046C ++:1073900041100082820290A0418801030005001183 ++:1073A00083110088A002A0010889001000110108C3 ++:1073B00000090100000101000101010400C100C138 ++:1073C000A01100080084001000020000000000006E ++:1073D00000000000000188088889008800900008EB ++:1073E000004001890121004100A08901001000A096 ++:1073F000001040030010100883100088014000C0F6 ++:107400000041888209000000010101000000000124 ++:107410008400010188110800900111820110010906 ++:107420000100004085418890080008088308830116 ++:10743000080110820801A020020188888301110838 ++:107440008400028200200000000000000000000113 ++:1074500000000000000009108902100088001001DF ++:107460008889C00000C088C0081108000400830596 ++:10747000852084004088110808828200C004010130 ++:107480000008000101A1010000A000000000A00010 ++:107490004108A000034005824104C003888009C060 ++:1074A0001010080808910904C040110400008391DD ++:1074B00005048908C18080400082002000008910F6 ++:1074C0009009804040800080000000000000000023 ++:1074D00000030011000000008909A0908400000052 ++:1074E00080100090801100000000800480080000DF ++:1074F0008390050084008300898400000000000060 ++:107500000902000904044041090010911108080013 ++:1075100010114002400920008100001300000650B5 ++:1075200000810021C200005081810013C2000000D0 ++:1075300000000000C200004100840000840100003F ++:1075400000880006C200064800000000000000009D ++:1075500000000013C2001100000081810013C2006E ++:10756000420011000013C20000000A000013C20014 ++:10757000000000000013C2000000120000134800C9 ++:10758000008100420013C200000000840000C2001D ++:1075900082000000001384000000EFE32F236E0C34 ++:1075A0006E0CFFFF0000FF03FC00FF660066FFF0AB ++:1075B0006F60FF0F6C6CBD24BD2400000000666688 ++:1075C0006060FF7E007EFF00FF0000000000000002 ++:1075D000000000000000000000000000FFFF0000AD ++:1075E000FF00FF000000000027FF273C0000000014 ++:1075F000F7F4C7C4CF0C7E7EBDBD6F090000FFFF4E ++:1076000000000000EFEF8080FF00CFCFFF3F003091 ++:10761000FF00FF00FE6EF86804082010ECE02C204C ++:107620000C0C0C0C1EFF1E00FE02FE02FF0F000FD2 ++:107630009F900F00F0006C6C9F9F060600000000FA ++:1076400000006060FF7E007EFF006C6C00000000A8 ++:107650000000000000000000000000000000F9F041 ++:107660000900BF26BF260000000027C32700000036 ++:10767000000037340704CF0C424224246F09000075 ++:10768000FFFF000000006F6F0000FF000C0CFF6F99 ++:1076900000607F1976109E0E980802014080FFFF5F ++:1076A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA ++:1076B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA ++:1076C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:1076D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:1076E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:1076F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10770000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10771000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:107720000038F5920C44405000180A060000F0BEE4 ++:1077300090F6BDBD0000000000FF00FF0406FDFF45 ++:1077400066F03CF08199E7FF00F00FFF300030F069 ++:10775000E724C3000000FFFF00FF00FF0000FFFF61 ++:10776000000000000000000000000000C2C2C2C211 ++:107770000000003C033F040CF7FF427EFCFCFF3C92 ++:1077800066F000FF3C3C90BDF6BD0F6CFF6C000046 ++:1077900000000000000000000000187E99FF191989 ++:1077A0007F7F666666660700F7FF16761F7F08080C ++:1077B000000090F624247E3CFF3C202FE0EF0400E4 ++:1077C000FDF966F03CF00018667E363636363060DD ++:1077D0003060242400000000FFFD023EC2FE060CC3 ++:1077E000F6FC000000000000000000000000E6E6DB ++:1077F000E6E6000000FF00FF040CF7FF427EC0C079 ++:10780000003C66F06666F0F09024F624006CF06CA4 ++:10781000000000000000000000000000187E00666C ++:10782000101076766C6C606F0400F4FF107019799C ++:107830000000000000860CC001880080008600F572 ++:1078400000B0000000860094018000000586006002 ++:1078500008B000050086006408B20080008600754C ++:1078600000B000000086006000B0000000860060EC ++:1078700008B000000000008600940180000000862F ++:107880000AA00980000500860A7109900005058696 ++:1078900000F108B000050086008009800000008625 ++:1078A00000750010000000000014000000000086B9 ++:1078B0000CC100B80000F5F4F5F4C3C3FFFF0000ED ++:1078C000000020300000FEC2FF000000AFAFAFA0FC ++:1078D0003F3F153D97BFFF3CC30000000000FCC0C8 ++:1078E000EBEBC4C7F4F7000000000030A0B00000CC ++:1078F0000000000000000000BE14FF000A0AFFFFA5 ++:10790000F5F5F5A002433E7FFFAA3CF028000FFFEB ++:10791000FA507D7D0505F5F53C3C3C3C0000FFFF41 ++:107920000000000000FF1E1E00000000000000001C ++:10793000FAFAFC0C00000000F5F4F4F440437C7FFC ++:107940000000000000100000FEC2FF001010BFBFCA ++:10795000AFA03030012983ABE8E8E8E80000000080 ++:10796000FCC0282804073437000000000030003035 ++:1079700000000000000000000000FA50FF00000AB4 ++:10798000F5FFA0F5A0A002433E7F00AA3CF028002E ++:1079900000F0FA502828303F303F3C3C2D28400072 ++:1079A0007CFF0000000000FF1E1E00000000000021 ++:1079B00000000A0AFC0C00000000AE04FFFF00FFFC ++:1079C00000FF0000000000000020FFFF0000287DF5 ++:1079D000AAFF0000000014BE14BE000000001ABA86 ++:1079E0001FBF00000000707C737F000000000000DB ++:1079F000000000000000000000000000FAFF0A0084 ++:107A00000F3C003C000000003C3C3C3C00000000FF ++:107A10000000000000000000503F5F3FFEFE00003D ++:107A200080BF00FF000000000F000FFF00000000FB ++:107A3000000000000FF03C3C03FF10DFAE04F0F04C ++:107A40000A0A0A0A00000000000000005F0F500050 ++:107A500000FF00FF000000000A0A5F5F0000000056 ++:107A600010B015B500000000404C434F000000006E ++:107A70000000000000000000000000000000FCFF0B ++:107A80000C003C3C3C3C000000000F550F55000032 ++:107A90000000000000000000000050305F30FFFEDA ++:107AA0000100003F00FF00000000553C553C000075 ++:107AB0000000000000000FF0000000FC10DF0400D8 ++:107AC00021009100210091000300020080002100AC ++:107AD00040A0850082001100A10280040400030080 ++:107AE000040005001100110021001100110204A181 ++:107AF000A0010400040002002190000804000040DE ++:107B0000210005002188020800010400840204000D ++:107B10000000040003000320080011000000200002 ++:107B20000300840083008204839002A0200184006B ++:107B300000081120040404000200000000000400FA ++:107B400001002000200020002000000000000200B2 ++:107B50000000010040002003000040802080080059 ++:107B60000000000000000000000000000000008095 ++:107B700001200404830041002000000020000000D8 ++:107B800000008200000082000580001000002080BC ++:107B9000200000000000C000008000000010200055 ++:107BA000210008000400040004800441901001201A ++:107BB00020000200000002802000000002000000FF ++:107BC000001104C0040004200000000004000400B0 ++:107BD00000000000000002000000000000020000A1 ++:107BE0008005002100C0008400200000000000107B ++:107BF00080000000009004A00000000100210000AF ++:107C0000000000C0000000200000008800010040CB ++:107C1000000000000000000400000000000000015F ++:107C200002000001009000000020000100A00004FC ++:107C3000000000040010001000010000800000009F ++:107C40008040000801000100030004410000011011 ++:107C5000011000000041004100200010821000903F ++:107C6000820040C0C0408820000082210009000935 ++:107C7000A0202010000000100010000800080008DC ++:107C8000A010001000000020A090001000210002B1 ++:107C900000880020A01100200088021000100211AE ++:107CA0000204020800400200001100900020900031 ++:107CB0000090000002A10000021100400010081016 ++:107CC000001002C10091850020851040A000000036 ++:107CD000830091022000800020402000000000006E ++:107CE00003202004A00203C000A000000202C11073 ++:107CF000800380900002118420A00001031005047D ++:107D0000008400000084000041C000000002001058 ++:107D100000908885000000A000C0051000910004BC ++:107D200000102140051041200000802020000901A2 ++:107D3000201004840011008820002000208820A04A ++:107D400000820008418200402000052082000521B9 ++:107D500000212041202105054000C19001418211F0 ++:107D60008402C002C1A121108221000000109040B5 ++:107D70002000400440000040900011101004001149 ++:107D8000C0109002000082000000840010008400F7 ++:107D9000A000000020021000084010410000100464 ++:107DA00084800021880000050000020320C14111E9 ++:107DB0008408011001050004C000C1411102C10086 ++:107DC000010500410000C0090804100011108000E6 ++:107DD00021000400418202002001108210000000F6 ++:107DE000400021A01040200004000020028808006C ++:107DF00010004100050000000520200020000500C3 ++:107E00008400100003002100200000002001020176 ++:107E10002001000120C0200004A0210008880500E6 ++:107E200000000000104090041100100510008800B0 ++:107E300010001000200010001000020000001000D0 ++:107E400002004100800000004140020000000010DC ++:107E500004000800010900090905092090008404B4 ++:107E60000803C109820004200103010904009009EC ++:107E700002002141004110001011008301000000A8 ++:107E800004202141A000000000008200000010201A ++:107E900001200820082083000009850000058211C8 ++:107EA000A0000000000802052085A00300C0820099 ++:107EB000040010090000010000410800011000004A ++:107EC0000000A0030808400800000880C100050069 ++:107ED0001002212009011088112041004100C188B1 ++:107EE000110002004100038840419020000300007F ++:107EF0004182100200111000101041892120100150 ++:107F00002002200210028000100000200901000061 ++:107F100003000200109011004084414003C0801013 ++:107F2000008804020000000220024100409041103D ++:107F3000024083894002402004400204001004A152 ++:107F400000C021000000808421001008020210847B ++:107F50000010002110809040000300210400040064 ++:107F600020410010404100119005910220100004B2 ++:107F70008400C01000001040C02140210004000017 ++:107F8000820401000100000204000010400000040F ++:107F900000804005000000000002400000101009B1 ++:107FA0002002C000820010080003C00884104000B6 ++:107FB000840202004002000200000405418000002B ++:107FC0000020200000000240040900001011C11030 ++:107FD00000000400210004000510041083A010908C ++:107FE0000910098409880210048410001184050016 ++:107FF00008001010090411C00800100210841000BD ++:1080000009C002100382028420840500411005018A ++:108010002190000000000500418405844182020493 ++:108020000000400111402000414010C0050109013D ++:108030000000021100C00000110004000004200034 ++:108040000000000021880500210021C010004184AB ++:10805000020105100100100001008200010004006F ++:1080600000000021024000002108A00300400000A1 ++:1080700000410840A00084030440841188C08800A7 ++:10808000200000218400C009C0008300000000001F ++:108090000040000000C0000000000000000010418F ++:1080A0000010001101408400C00500000000821093 ++:1080B000000400000140C010100090080100008082 ++:1080C0000140840084050000100000400000000012 ++:1080D00000000040100040200009C0040809090207 ++:1080E000894089040041008340C1004100880308A1 ++:1080F0008805400510200000008020000080030358 ++:108100000040000940080289808202A005020305A0 ++:108110000084000410040000000000004100000082 ++:108120001083804040044100020200090008050855 ++:1081300008080011100203080000000040000000C1 ++:108140004008000905084000111100090004040856 ++:10815000080080000400080001000801050001007B ++:1081600000000501A100000100110008002100022B ++:1081700008004100010000010004C01001100010BF ++:108180001101000000000001C188C0028205000446 ++:10819000090100C00008019000000000400000003C ++:1081A0000000001140000140000801010001000131 ++:1081B000000008008800000001000000000001002D ++:1081C0001000000008014001010000000001000152 ++:1081D0000101C100C00000000100000400C00190C6 ++:1081E0000101A0104102A0C0A10082004100400492 ++:1081F000A182C100C0A02101C10008000800400008 ++:10820000090003000310A1001100A000401089A183 ++:1082100005A0C00085081101A000000000020000B8 ++:1082200000080104010088C0104083C00000000065 ++:10823000000801000500000903208200A001A00140 ++:108240008800C00109C0A088091108110400C18874 ++:108250002100410011081000A100830000801100DE ++:10826000210809400980C0800010094109119000CF ++:10827000898503800800030841020300090000000B ++:1082800004002000C0000800024003000900C18073 ++:10829000A0200904000020008540000200000084A6 ++:1082A00004000000080002091000094183000300D7 ++:1082B0001000080009001100080302118800402086 ++:1082C0000908890010089011910021089089000088 ++:1082D000880004400903208009000200901000007B ++:1082E00011880009400909C0408800090989001067 ++:1082F0000040004100032088008204C008110000F3 ++:10830000800000800080200900400084008308096C ++:1083100080410009408202200010C0204008000077 ++:108320000000400000000000411080408080008379 ++:1083300010100008090989900888008208050004C7 ++:10834000000000800200008008C02183000900C0F6 ++:10835000080800402009008000020020059000036A ++:10836000009000090011A104000500880085100498 ++:10837000A0001000A0000001014100090084054098 ++:1083800000028204C08400400140000000840041DB ++:10839000000840C00011018801011000A1018901FD ++:1083A000000000900190008288080009088810A051 ++:1083B00004090000000100010289000800C10089D1 ++:1083C000408800A000C001C04088010501040021D0 ++:1083D0000803010100010001008800040083010975 ++:1083E00000100100000800000001010100A00100D0 ++:1083F00001888541881082C00502010501840000C2 ++:1084000001100010000100000090010100A0000018 ++:108410000010090088A004000310004101000100C1 ++:10842000000200001002040102000400850002A006 ++:108430000201A008000000C1000100000100008846 ++:108440000000000802918820C000400109010803D3 ++:1084500004010808010000080001000000040001F8 ++:108460000001001009000484090900090921090913 ++:108470004004408083C040C0000920004110100427 ++:108480000240080000C00004000400000340104047 ++:10849000080011000900C104020290001140040804 ++:1084A0001000080000008000000800050000831094 ++:1084B00040101010048000000088004000000200FE ++:1084C0000211040008800003808000400008890336 ++:1084D0008008080580800904101000400900009100 ++:1084E00000100002000000420021C2000000004213 ++:1084F0000021C200000000000000840000600000B5 ++:108500000013C20000000000000000008200000014 ++:1085100000818400420082410013C200000000007C ++:108520000013C20011000000000000130000000052 ++:10853000000000218400000000840007C200000049 ++:10854000008800008400824100000013C200210066 ++:1085500000410013C200060000840004C2000000B5 ++:108560000000000000000000F050FF5F555500FFC4 ++:1085700070007FFF025700FFFF55003C000F0C0CFE ++:108580001C9E5DDF000000000000000000000000F5 ++:108590005F5F287DF0FF5C5C8000FF7F80FD00FF57 ++:1085A00014051405C3E800E8000000000000000006 ++:1085B00000003C550FFF0F0F5C5C0000000004F74B ++:1085C0000CFF0000808013933BBB00000000000004 ++:1085D00000000000FFFF033F00FF00003CFF00FF22 ++:1085E00000FF00000000555500FF00500F5F0F0F07 ++:1085F00000FF20002FFF025700FFFF55003C000F37 ++:108600000C0C088A49CB000080000000000000002C ++:1086100000000A0A287D000F5C5C00007F7F007D5F ++:1086200000FF55005555FFE83CE800000000000041 ++:10863000000000003C550F0000005C5C00000000E2 ++:1086400000F308FB149600001B9B3BBB00000000DE ++:10865000000000000A0A0A0A417D00FF41007DFF78 ++:1086600002570257000000000F0F3C3CBF83BC8044 ++:10867000FFFF00003C3C3C3CBFBF0101F0003F3F1E ++:10868000BEBEFA507878FF550000000000000000E0 ++:10869000FFAAFFFFF03CFF00FA502828AAAAA8A8CA ++:1086A000FFFF00000000FF785F505F5000000000F7 ++:1086B0000000FFFFFFFFFFFFF000BEBEFCC03F3029 ++:1086C000AFA07FFF20A000000000141F14140000C2 ++:1086D0000000FFFFF3F3FF00FF00FF00FF00FF00BB ++:1086E000FF0FFFFF005500000000E0F02000BF83F7 ++:1086F000BC80F5A0F5A0787D7828BEBE0000F00013 ++:108700003F3F1414FA507878AA00000E0F040000BE ++:108710000000FFAA3C3CF03C0000FA502828AAAA1E ++:10872000ABA8FF3E0002FFFFFFFF5F505F5000005D ++:1087300000000000FFFFFAFA00FFF0008282FCC098 ++:10874000FF00FF007F5F2000C3C300C0141F14148C ++:1087500000000000FF3CF330FFFFF0F0FF00B4B476 ++:10876000FF00FC0CFFFA00500000000000000000B9 ++:10877000008600F500B00000008600F500B00000A3 ++:108780000886047008B2001000860C7000B000105B ++:108790000086006000B00000088604710892001096 ++:1087A00000860094018000000086004000B00000B8 ++:1087B00000000086006100B000000886047008A276 ++:1087C000001000860074009000000086707408B8E5 ++:1087D000000000865031A8800085008600F500B0BA ++:1087E000000000860075009000000086006000B860 ++:1087F0000000000000003434202000000000FFFFD3 ++:10880000FFFB00FF00FF000000000000000000A0D0 ++:10881000A0A00000000000FF00FF0000000000C357 ++:108820003CFFFC0CFF0F0000FFFF000000000000F9 ++:1088300000000000B2B2FFC30088004438381010B6 ++:1088400045C76DEF00000000FFFF000000000000C2 ++:10885000FFFF5FFFFFF28F823075FF75FFFFFFF3B1 ++:10886000FF0F553C00000000FFFF0000000000006B ++:108870000A0008000000000000F500A00000000051 ++:10888000FFFFFFFF00C000800000000000000000AC ++:1088900000C0C0C000000000007F00FF000000001A ++:1088A00000C33CFFFC0CF000024302430000000048 ++:1088B000000000000000B2B23C0088004400FA0052 ++:1088C000500004862CAE00000000FFFF00000000F6 ++:1088D0000000FFFF5CFCFFF28F823075FF75FEFE2B ++:1088E000FEF2000F553C00000000FFFF00000000FA ++:1088F0000000000008000000000000000000000070 ++:108900000000FFFFFFFB00FD005DFFFFFFFF000019 ++:1089100000000103C1C300000000000000000000CF ++:1089200000001E1E55FFFDBCC180353500FFFFFF56 ++:10893000FFFF0F35FF3500000000000000000000C1 ++:10894000F5F57D7D050F0A00000000000000000025 ++:1089500000000000001400410000000000FF0F0FA5 ++:1089600000000000FFFFFFFF0000000000C33CFF0D ++:10897000000000001400AAFF00000000000000003A ++:1089800000000000FFFFFFFF00A800087FFFFFFFBF ++:10899000000000000100C1C0B2B2BE8200001000A1 ++:1089A000000000001E1E00AAFDBCC180353500FF7E ++:1089B000FFFEFFFE0035F035000000000000000063 ++:1089C0000000A0A07D7D0A00000000000000000063 ++:1089D00000000000000000140041000000003CFF07 ++:1089E0003F3F000000002DAF7DFF000000000C0C99 ++:1089F0000C0C000000001E0A00552000A000A10081 ++:108A0000050000A004010420000000080482030007 ++:108A1000000004400400840084820410040000C0AC ++:108A200040088000000005002002040090080200B9 ++:108A3000200002002000028820080000040000003E ++:108A40000204200020C02000200084002004200018 ++:108A50002004049002102108041004100210A01039 ++:108A600020002000020002C0840940100000030022 ++:108A7000210184A1040000108240020121000500B0 ++:108A80000400A000000000202080200004800000DE ++:108A9000000020009080A000040010008210000060 ++:108AA0008400038020000000000000800100059089 ++:108AB00020000300020000000000A00000000000F1 ++:108AC0000000000000000100010091002100018071 ++:108AD000010000800000A00004002000020001004E ++:108AE00005009100000000000000100804000000D4 ++:108AF000000004400210001000000280212040000D ++:108B0000000000C009C00000000000080008800349 ++:108B1000000100000000008303080001100083042E ++:108B200080088082402100880200029104018000B8 ++:108B3000000000000002000000000000000000C073 ++:108B40002000A00000010000000100000000000063 ++:108B50000000004100000001800000000000002033 ++:108B6000000400010204800400200020000300082B ++:108B70000000114000000010000000000090000103 ++:108B8000000000000000000084000041909004C13B ++:108B90001040000200200010000890C10002830075 ++:108BA0001080028040100040A010832190400140BE ++:108BB000202100410010909000210200002100417E ++:108BC000000001100341000400419040900000208B ++:108BD00002110011008400080040200000008800FD ++:108BE00000080088000401C1029002A1009002A0C8 ++:108BF00000880011009000100090901002410008C1 ++:108C0000822004004100100400C000C00000412187 ++:108C10008802050080000000008280400040102093 ++:108C200020000082000000000402009000081002F2 ++:108C30001004004000A041A004C000820208408847 ++:108C4000008200000040030011900904001000029F ++:108C500000100410008410844008A00105010910D0 ++:108C60000000000840080082030804000091000092 ++:108C700004C08088002003C00920002005C085C0F2 ++:108C800002009020010084419080840500050011BD ++:108C90000082041084000208841082000282820292 ++:108CA000080209020002001008001090000800826B ++:108CB00008108590820010001005A121102010805E ++:108CC000100010020000402100410800C090840004 ++:108CD000201010001041C0418410C010050484040D ++:108CE0000041104100211005002100050405100875 ++:108CF000100002000210A090004088C100A10000F6 ++:108D000010400141408000100400410003000500B4 ++:108D1000201000C002002000A00002208500A00357 ++:108D20000210020184400201800010000388020446 ++:108D30000003008309102000020020400404050104 ++:108D40000500850091000000040041004100000082 ++:108D500000000300000000000800000020400800A0 ++:108D60001000030108008501090302001000100033 ++:108D70004100000041004101030002000301200006 ++:108D8000100290012100C1000091002140008205E5 ++:108D900090050005000300210521110010C00421E9 ++:108DA000108440838310048903202000042088114C ++:108DB00004800484020404918510840809000921B8 ++:108DC00008020800104140000000011000100800D7 ++:108DD00084000000C000000000000010C00011214D ++:108DE0000808A000C010010910200884824010006B ++:108DF00011000010000000100020000009210008F0 ++:108E00000121C0A1100800001000000200000000B5 ++:108E1000201010A040820484000084020410080284 ++:108E20000540904004402102411000004100C1C0B3 ++:108E300005C02120104010200084000000A1000087 ++:108E400000C000000002408208000000410810023B ++:108E500003100801801008010200038400000000D4 ++:108E6000098404A011840408058209020010081076 ++:108E7000001009841000218404202090000041206B ++:108E80000984214021A0841041028420902184097A ++:108E9000A0210103841088000400C000111041408B ++:108EA0004088048003900180000004000040000915 ++:108EB0000208A02000C090004180022100050008A7 ++:108EC0000041C00084000041004100050040000056 ++:108ED00000024000000420002004C0008441100073 ++:108EE00082008400A1100000010800054005044034 ++:108EF00004000000840391009040028341020000BE ++:108F000000910400048002001020401003804108FA ++:108F100000000000004021900420034010000008E1 ++:108F2000089010902082900920002011080480846D ++:108F30008001822182042184C14000000884080449 ++:108F4000080404040084000104850283C1100000A9 ++:108F5000040004002000020000044084110002000C ++:108F600010040000080004000088C11103892121B9 ++:108F70000084000004841084210880A000C0000246 ++:108F800010001084000008840300020920910408E6 ++:108F9000200000412010C005000000000000A000DB ++:108FA00040A100000240850009A0010083082004C0 ++:108FB0000800040805040989A0001020020500002B ++:108FC0000080A0000380C000842000200220040054 ++:108FD0000040090000008400000000C10000020001 ++:108FE00000000200100008002121000008201020CD ++:108FF00008A000210005000001008280040000009C ++:109000000080C0000021C00001000000118810088D ++:109010000209208400092040090811000000000016 ++:10902000110008850483411041A04085C00491A12E ++:1090300020881003C04002C0000809030008090886 ++:1090400003088283C10591410310000300208020A2 ++:1090500000200000080809200041080802100489C7 ++:1090600000C104A00280808902082020008088803E ++:10907000A080408002008400100009800303A11139 ++:109080008502081008000000100003000003891189 ++:1090900041410341C0882083821100110400000077 ++:1090A00000000000A185891020830110018308A021 ++:1090B000C008911002A1831020C000050001040126 ++:1090C000A0000101058908C0C00201C00001000024 ++:1090D00010000000000089010101000100000203EE ++:1090E000000300110009010882110000000800823D ++:1090F0009090A08800040082104000109088090120 ++:10910000400010010001A0008800010000000001E3 ++:10911000100000010000040182088804830100009F ++:1091200001400191000021200401092002010221D7 ++:109130008810C0908241890588A0402182020221C6 ++:1091400002009040100083001110884003020002CA ++:10915000000000040000000001080108000101C037 ++:109160000800028411110201010100100008011021 ++:1091700083019108118820C11001100109A088887D ++:109180000010018801C00101008284009082908853 ++:1091900088004100210011A00402080085418905D2 ++:1091A00011004100080211400580092005820510C8 ++:1091B000899040020405908311C0088310829103B6 ++:1091C00020C085410380C10520028480C1C109807F ++:1091D0000000000000000000000008C14100400243 ++:1091E000098882008400A141050910400080080818 ++:1091F00009801008880085894091C008C02020801F ++:10920000C002038021002040052000C08000000033 ++:1092100080821109400010001000058200040089BE ++:109220000808000810400008804089402002A188FA ++:109230000808839120409040A083900910A1A1804C ++:109240009000C04021040284C00409000005088980 ++:109250000389202004404100410000000840002014 ++:109260000009202002410004008900A02000002005 ++:109270000089888800108083809080A08088800387 ++:10928000834100051188210500A0111180110010F3 ++:109290004008000811C000050008109000200408D4 ++:1092A000A0A10905000000000001820120C08984FE ++:1092B00010859005204010C141C0028305A0C1085F ++:1092C000040883A040C100C0018420200002A085C2 ++:1092D00005050188000000000000030000000100F7 ++:1092E000000000010000000084C00485A0110000FF ++:1092F000C0880203041000098810A0A18883408957 ++:10930000104009824010004001030041208404A065 ++:1093100000020110C004001100110009004104887E ++:1093200089A00000A082010001000000000003905D ++:10933000002000880010850102A0A00008408341A1 ++:10934000A140A021054082C18841080008101111E8 ++:109350008941100020A00000004000000000000033 ++:10936000110010901000C000011000A101010004C4 ++:10937000850008904001A000838410828201C1888A ++:1093800000419005C00100C1010201080100010077 ++:109390008200C082040008C1A00104C1C00088404E ++:1093A00004898409090909801000080809091000C6 ++:1093B00083110409108941408341C18504020400DE ++:1093C000839008880282890080908010800200804B ++:1093D00089A0A0A08509890000000000000000000D ++:1093E00000008900C0088840110009A00441212024 ++:1093F00003808900C040A00820008588918020104B ++:1094000040800083004100100008038010A1020387 ++:10941000080080400000000080408010800580042B ++:10942000800006600013C20000821200401300009A ++:1094300000420A500013C200000082410013C20023 ++:1094400000840A500013C2000A8282410013C20045 ++:10945000006021840013C2000041210000130000BD ++:109460000000000000600021C200000000880081B0 ++:10947000C200000000600021C200060000000021C0 ++:10948000840011000A004021C200118800500081B0 ++:1094900084204100000000218400420000000004FC ++:1094A00000000000FC0CF6063636FF0000007E18B7 ++:1094B000BF2600009F0640C1662666209F9F9F3CF6 ++:1094C000FFF036366F60FCFC3636363600000000A2 ++:1094D000FFFFBFBFFFFF0000FF00FF6600000000AE ++:1094E0000C0C0C0C0000FDFF04069F06BD24FFFFC2 ++:1094F0000000FE98FF00FF7F8101FF00FF00F0F0F9 ++:10950000F0F000033C03000000002D0F000020805D ++:109510002400FFFFFFFF00000000F099301800005A ++:1095200000003FFF3F3FFF00FF00FF00FF00000083 ++:109530001E1EB92000009F0640C166006600060698 ++:10954000063C0F0036366F600C0C3636363600009F ++:109550000000FF7EBF3EBD9F2406FF009F06000067 ++:1095600000000C0C0C0C0000FDF90400FF00FF00D3 ++:10957000FEF80E086E08FF007E7F000166006F098E ++:10958000006000A0000300030000000000000000D5 ++:1095900020002400FFFFFF7F00000000C0810000CA ++:1095A0000000000000CF00FFFFFFFFFFFFFFFFFFF5 ++:1095B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:1095C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB ++:1095D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B ++:1095E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B ++:1095F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B ++:10960000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A ++:10961000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A ++:10962000FFFFFFFFFFFFFFFFFFFF00C02A7C0C448E ++:10963000403000180A06000070DF20BF60FF20E005 ++:109640002FEF00000000080C0B0FF07E000034FF2D ++:1096500000000000FF78FFFF9FFF00000000303097 ++:109660003F3F000000000000000078F93CFF0000D0 ++:10967000FFFF00000000000000000000F0F0D8FC38 ++:109680003020FFEF00FF00FF02BF42FF01FD01FDA0 ++:10969000C300FFFF00000000000F030300000000F4 ++:1096A00006060000FFFFFFFF0000FEFF00000000B5 ++:1096B00000000000F072FF3CB0BF000020BF009F20 ++:1096C0000000FFFF0000000000040307F04200005C ++:1096D0000000000000000078FFFF87E7000800049A ++:1096E00006F606F6080004000020000078603C0042 ++:1096F00000B4FFB400204000000000000000F0F0C3 ++:10970000C0E40020CFEF30F33CFF00BD40FD00FC83 ++:1097100000FC42007EFF00000000000FC0C00000FF ++:10972000000066668090FEFF3CFF00000000000025 ++:109730000000000000006672003C202F0000008640 ++:10974000009401A000000186006001F00400A586DD ++:1097500050F4A1B00085A58650F4A1B90005A586F6 ++:109760005AF4A1B80005A0865AF4A1B0008500867D ++:109770000A940180000000860AE001B800000000A1 ++:109780000086007400B000000086007500900000A4 ++:109790000086007400B00000008600B000000000E9 ++:1097A000A0865031A1B8000505860AF408B000056E ++:1097B0000086003008B0000500860A6104B8000089 ++:1097C000AA00BE140000008000000000000000009D ++:1097D0000000FFFF4040C3C3000A000C5C5CF0FFC8 ++:1097E000F0F0FF00FF7FFF7F3030BE82DFC3FFC39A ++:1097F000FF00BF1540C07FFF000000000000000018 ++:109800000000ACFFAC0F000000000000000000FFF3 ++:109810000F0FAA3C0A0C0505AFAF0000FFFF28A8F8 ++:10982000A828FAFFFAFF000A050F00000000000058 ++:1098300090067878FF5580008000FFFFFFFFFFFF54 ++:10984000FF55AA00BE140000000000000000000048 ++:1098500000000000FFFF0040C3C3A0AA303C5C5CD6 ++:10986000000F3C3CAAAAFFFF7F7F3030BE82DFC3DF ++:10987000D7C3FF00BA1000803FBF00000000000007 ++:1098800000000000ACF0AC00000000000000000090 ++:1098900000FF0F0FA0300000005500550011AAFF77 ++:1098A000A828A828FFFFFFFF0C0C0C0C00000000EC ++:1098B000900600007878AA0080800000FFFFFFE893 ++:1098C000FFCFFFCFFF5000507D7DF0FF0000000074 ++:1098D0000000000000007F700A0A00AAFFAA3C787E ++:1098E000553CFF0FFFFFFFF00000000000000000EC ++:1098F0001400143CFFFE00C200FF00FF0000000047 ++:109900000000000000000000000000000000100047 ++:1099100000000C7DCF7D7D287D2800000000FFFF2A ++:10992000000000000000BE00B40000343C34000021 ++:10993000000000000000000000000A0005500000C8 ++:109940000000553FFF3FFF1400147D7D303F0000B5 ++:1099500000000000000000002F200A0A282800AAAA ++:10996000F078553C000FFFFFBEBE00100001000064 ++:109970000000000C000CFF7C0040407F00FF000056 ++:1099800000000000000000000000000000000000D7 ++:10999000000000000C41CF41FFFF555500000000C2 ++:1099A000FFF000019C0000001E00140000043C04B5 ++:1099B00000000000000000000000000000000000A7 ++:1099C00000000000FFFFFFFF000021400002030035 ++:1099D000040004840400110800000408044011007D ++:1099E0001100040004080400110004081108040018 ++:1099F00003900308000041900482041003900408BF ++:109A000000900420040804A00000000002A085A02B ++:109A100004A020008410830004A020A0840004047B ++:109A2000911002000400041020081108820884002C ++:109A300004A0201021100400209011000090844008 ++:109A40000000049000000400110000000080048069 ++:109A50000400000000000000908000000100218050 ++:109A600020000000000000000000000000000000D6 ++:109A7000000084000000000000000100010040051B ++:109A800021000000A0000080200000000400000071 ++:109A900020000100050021002000000083002000BC ++:109AA0000080200000009100A100040002000500D9 ++:109AB00021008900080002002000A1002000900081 ++:109AC00010800000820000008200200000000010D2 ++:109AD0000020000000000000000000408020002066 ++:109AE0000000801000000001210080402100804023 ++:109AF00080200000000000000000000100200001A4 ++:109B000080110011000000000000000000C00000F3 ++:109B1000000080000020800000058001002000017E ++:109B2000000080008000800100010001800100042D ++:109B3000000100010004000080000000001000008F ++:109B40000200001080000000000000000200000081 ++:109B5000000000000041002100000021009004A04E ++:109B60000090821004200005000888100490A005D1 ++:109B700040C140000021004100100010004000A141 ++:109B80000020042000200020001000100010000021 ++:109B90000000000004100090041100A004200091B7 ++:109BA000C0040021202120210420002000200420C6 ++:109BB0000080040400040491002010110220000819 ++:109BC000001001210002020820000000900801009E ++:109BD000900500040000A040000800A002A0008240 ++:109BE00008108441410800A1009000A00808050267 ++:109BF00011000002090004001102898209A040C07E ++:109C0000408200400000114010000000410041006F ++:109C10000000000420100004208520002000200007 ++:109C200082100008040400C08004000800400900FD ++:109C300000C0402080200020042011000000098482 ++:109C400084C0000000A00200001021100910801044 ++:109C50000984118800800000219000C1C008C02143 ++:109C60008208000810081000C02084000010008244 ++:109C700090118400C005A040C110000920211040AF ++:109C8000C0000010C00884000089004100210000CD ++:109C900000000000008011000880910801050140CB ++:109CA00001402021C0410080001004800000C0213C ++:109CB000A005000204834080008000899040820358 ++:109CC0000008040510410010910882090000C0112D ++:109CD00002210041A10010000582880003820400D7 ++:109CE00041000500050003820509C100114005205F ++:109CF00000402100002004084100039020A0080338 ++:109D000020031002020202024110210221000390EE ++:109D100002C083000000A00104010001C14000C195 ++:109D200010042004800410900000090080A00000AE ++:109D3000904010C00020040008002000200005A072 ++:109D400020A0410010400300098208404100A1000A ++:109D5000100003001020100001000000044100006A ++:109D600000102000100084000000002040000000CF ++:109D70000000A000880000C0088082008400C000AD ++:109D800000C00090208000801080104100800010F2 ++:109D900000030000040000000520012000202080B6 ++:109DA000C0200080828004C00000C00310030203B2 ++:109DB0000000401100000080C100104000001100B0 ++:109DC00000001000840000008200100010800800D5 ++:109DD0000204000584000090050003C00004100088 ++:109DE000108240A02110414010C010404100038863 ++:109DF000C14041910988088408A0040020002090F7 ++:109E0000004009A00090100003C00000218410024F ++:109E100000080008008805A000000200008400007F ++:109E2000100211A04101A1A000A105C021000482DF ++:109E300005A0030021404100834000C0208402109F ++:109E4000000010104100000000C01000000002419E ++:109E500090004184030205000984A0108200028062 ++:109E6000850000100021400990054040C108C00352 ++:109E7000400820104004000591218500C100010028 ++:109E800089400490102008211010840000118800DF ++:109E90009020008000008200842100C0010510088D ++:109EA00000218821001000042010880400100810F0 ++:109EB0000008042000210408002140080021A10519 ++:109EC00010100003900584050005881001090003A7 ++:109ED00001C0040010000091002108000088032048 ++:109EE00000840888104000C00290410041108208A0 ++:109EF000090820090310098980A01182A00020848C ++:109F000082100040909000400240090120104184DE ++:109F100082024100A10005908505020800000200B0 ++:109F2000050410400040102100044004080510C042 ++:109F3000030410C000A0002000904100002020C0B9 ++:109F400011A0A0820201009020821040029010A077 ++:109F500009840200000000880084040000A00000C2 ++:109F600084000000020000800000000000000400E7 ++:109F70001180829100909000884020030000112001 ++:109F80000141021188034000C0000000821000005F ++:109F9000204140212000020084000802008000408F ++:109FA0000000008000000000C04000800180C088E8 ++:109FB000010000000103100000000000000000008C ++:109FC00001000009020000400000000000008400C1 ++:109FD000000010410100000000000000C00000046B ++:109FE0000285090811081140108005002000410079 ++:109FF00000030004880403200408094009082041E4 ++:10A0000000410040808900118083400002000991D6 ++:10A010000083911041800000828020800080418078 ++:10A020000000000000000400000008800080418063 ++:10A0300010808809800520201008038384A021084F ++:10A0400005A104000000840000000005201080200D ++:10A0500000081100000003000880C080008010008C ++:10A0600003008885058800C00020020889040004D8 ++:10A070000102C0010001A1000001C0008400000035 ++:10A0800000010000004002100000408389A001A0F0 ++:10A09000008800098408910800A088820010908838 ++:10A0A0000102000000040488024000A00310408464 ++:10A0B000A0840184210040000000030104A020C00E ++:10A0C0000508014000049040080000000001010163 ++:10A0D000C00000000088049000A0000408840884E8 ++:10A0E000012001C0110085054184410283019110C6 ++:10A0F00089410810A01010004010848208009000D0 ++:10A10000C000C089042090A0409182080001000096 ++:10A11000009001C01040C000044091A100A0018443 ++:10A120000110000000000102010000A00100010573 ++:10A130000104011100900100018200000100C0082B ++:10A14000208409C1210089C0110105C003C000009D ++:10A15000000400000100090101C000004191080055 ++:10A160008982A0A102029009028488C18889111005 ++:10A1700004804021098441898800038091858011F1 ++:10A1800008104100048388C10041800980841020A8 ++:10A190000005000003830083800000800320080086 ++:10A1A00008004003020000001000104110001010D1 ++:10A1B0002008080802102002080008840420100269 ++:10A1C0002180A0080805C121114089402000C00954 ++:10A1D00041000000002009008810208009001020A4 ++:10A1E0000509040004058380914000201008200424 ++:10A1F000000880A080A000901020200308080840DC ++:10A200008840004104882005A000A1000400080047 ++:10A2100000000080900000830080419080808003D7 ++:10A220000011A002800800050000000002000400E8 ++:10A2300080000010A01021208009881000904008A4 ++:10A2400090080505200485A08841801189410200FD ++:10A25000000010000000000004000020000485043D ++:10A26000800400028000058500C182419040832067 ++:10A270000241400910090884004101C100C0019059 ++:10A280002105414100040184C003030008000100CE ++:10A2900021000290C008880400410084080404845E ++:10A2A000400300008300100108000000A088888897 ++:10A2B00008080488A0890389C02040041189000986 ++:10A2C0000189059000C021031105100982884040D2 ++:10A2D00000829004010000000000A00000820290B3 ++:10A2E0000304C00400044082890804098520A004F6 ++:10A2F000A085A0A0200041908801C10882209085FF ++:10A300001000C0C082208488A001400885401084CD ++:10A310008800090283888488A00004001101C0001D ++:10A32000040088400140010100000000000000100E ++:10A33000008500010000910808852001C10000008F ++:10A340000110010101000184008300010008844024 ++:10A350001009A000C00401000000010001008500F8 ++:10A360004002880084080590051182011182832033 ++:10A3700041100583C100102010100210A0008005BC ++:10A380000005000880008021000200108080830505 ++:10A3900020002000408083800000000084008303B0 ++:10A3A00000001110000003800904030909000000E7 ++:10A3B0000080004000100000108082082010100073 ++:10A3C00003000589200805002091091003080300F7 ++:10A3D00080C18088000300004000080420000800BD ++:10A3E000820040100303C080A0032090031010805F ++:10A3F00000000081810041500000000000000000CA ++:10A40000210000130000005082410013C2000050E0 ++:10A4100006600013C200000000880000C2000000B7 ++:10A420001200001300000A000A00001300000A00D6 ++:10A4300000000A000013C20000000A500013C2000E ++:10A44000000000820021C200820000000013000012 ++:10A45000000000000013C200420000000021C20002 ++:10A46000000000000021000000000000008100004A ++:10A470000048FF1E1E1E4D007D0000A3A3A30C007C ++:10A480000F00000000000FCFFFFF000000000000E1 ++:10A4900028283C3C55550000000000003C3C0000D2 ++:10A4A000FFFF00000F0F00000F0FD7D70CCF287D44 ++:10A4B0005F5F000000000000000000000A0A008248 ++:10A4C0000002000214BE5F5F0500000070737C7F15 ++:10A4D00043576B7F00000000171717171C081C1C40 ++:10A4E000000000000000300004042C2C0003C0C356 ++:10A4F000553C553C001E1E1E410071000000A3008B ++:10A5000004000F0000000000C3C0C3C3000000002F ++:10A510000C3C0C3C00FF0F0F0000000000003C3C16 ++:10A520000000000000000F0F00000F0F14140CCFEC ++:10A53000287D0A0A00000000000000000000000062 ++:10A5400000820002282A14BE0A0A05003C0040438B ++:10A550004C4F02162A3E0000000017171717080874 ++:10A56000081C00000000000000000014283C4141CD ++:10A57000414155553C3CFB3800000000FFFF000006 ++:10A580000000FFFE5554B2B2FFB200000000343CA0 ++:10A590003414F0F5FFF5F0AA00003C3C3C3C3C3C98 ++:10A5A00000003C3C0000FF0000000000FFFF000036 ++:10A5B000000000B4000000000000000000000800DF ++:10A5C0000000000000000000410041000000000009 ++:10A5D0008010CCD0FA005000000000007D287D28BB ++:10A5E00000000000BEBE1414000000000000BE8287 ++:10A5F00000000000003C00AAD3100000000000A8EA ++:10A6000000000000FFBE5514B2B24D00B4FFB4000C ++:10A6100020282000F0A000A03C3C00003C3C3C3C3A ++:10A620003C3C00003C3C0000FF000000FFFFFFFF3F ++:10A630000000000000B4B4B40000000000000000FE ++:10A640000000000000001E140A00C0C0000008083E ++:10A65000F808C2DCC89E7800780000000000FAFA12 ++:10A660005050BE00BA00BEBE14140000000000002E ++:10A67000B2B2000000000C0C0A0AA5865071A0B00E ++:10A6800000050086006000B8000000860AE101B005 ++:10A690000000A0865075A1B00005A58650F4A1B0B9 ++:10A6A0000845A2C75174A0B4494502C701E101B4ED ++:10A6B0004140058600E001B000000000A08650F196 ++:10A6C000A1B00005A18650F5A1B00005A086507488 ++:10A6D000A0B0000500860CE000B00080A08650F01D ++:10A6E000A0B80085008600E108B000000086006088 ++:10A6F00000B000000086006100B0008000F000B0F3 ++:10A700003C3C0F55BEB2000000002AAA3C3CF0F0D1 ++:10A7100004F75457FA0A3F3F00000000BEFA14FA4B ++:10A7200000000000FF0F3A3AA8A8A0AA50C050C0ED ++:10A73000000050F0000000000000000000000000D9 ++:10A74000000001F1000000001010000000000000F7 ++:10A7500000003D0001000000000000C30202FFB441 ++:10A7600055B404043434000000000000000055001B ++:10A77000540004142C3C417D0000E040FFFF00A089 ++:10A7800000A00000000082B2000000002828FF00A6 ++:10A79000AAAA04F75457FA0A303034F520A0BE5064 ++:10A7A000145000000000F0003A3A0808000A55C3AF ++:10A7B0000000000010F00000000000000000000099 ++:10A7C000000000000101000055001010005003536C ++:10A7D0000000000001000100000000000000020273 ++:10A7E000AAB400B4003C003C0000000000000000DF ++:10A7F0001400140000102838407040700000FFFF63 ++:10A80000FCC00000283C2800A220202004F407F708 ++:10A810000000000008280828000000000043C3438F ++:10A82000AAF0AAF00F3C55FF3F30FAFA00000000F2 ++:10A83000F734E320101C3C3CAAFF3CF00000000071 ++:10A840000000040E0404000000007878FFAA000055 ++:10A8500000000000000000000000000C000C5D0083 ++:10A860000800FFAA00AA0000D3DF000000000000DB ++:10A870000000F0AA000055553C3CFFFFFCBCFFFF68 ++:10A88000FFFFAAAA00000A0F0A00820000000000D1 ++:10A8900000000000000008281C3C000000000040F0 ++:10A8A000C340AAF0AAF00F3C55003F300A0A00004E ++:10A8B00000000000000000003C3CAA003CF000004A ++:10A8C00000000000000A0000000000007878550039 ++:10A8D0000000000000000000000000000A0A000064 ++:10A8E00008000800FFAA00AA0000101C00000000D9 ++:10A8F000000000003C3C000055553C3C3C3C3C3CCE ++:10A90000FFD2FFFF210000C0100000002100050061 ++:10A910000500211004100000110011000090040037 ++:10A92000110020C00410880882039000C0108241EA ++:10A930008202A01111A01100000002A0030021C09A ++:10A9400011020300000004000000000004002100C8 ++:10A9500004C004002108030003101100210020009E ++:10A96000211011082000000002020200040004006F ++:10A970001100030440C00400210021000400410034 ++:10A980008400A00484090000A00002000000000070 ++:10A9900000000400900000000000A000A0000000E3 ++:10A9A0000000200004002080218041C009000980AF ++:10A9B000098809A04108A00000009000A100000043 ++:10A9C0002000000090000000200000000200900025 ++:10A9D00002000000000004009000040000000000DD ++:10A9E00004002000820000000000A102010300001A ++:10A9F00000000400048001000000000004002000AA ++:10AA00000000080004802088000000000000000012 ++:10AA100000000000008200000000000000000000B4 ++:10AA200000100000000000C080048009800100A127 ++:10AA30000010800980830000000000000000000179 ++:10AA4000000000000000800400C0000000000000C2 ++:10AA50000000000000C00000000000000000000036 ++:10AA600000000008000000000000000080008000DE ++:10AA700080000000800080000000800000000000D6 ++:10AA8000000000008000000300000005001100002D ++:10AA90000020001000000000000000210010001045 ++:10AAA00000210008000004102010401010C0081001 ++:10AAB0000010008940820440004100110021001074 ++:10AAC000000800110011A0110490000000110208FC ++:10AAD0000010000000000000000000080008000056 ++:10AAE00000088200000800080000000800032000A1 ++:10AAF000401010000010200020000000080000415D ++:10AB000000080041000840080004000000A0000008 ++:10AB10002190410200840010088200C0091000004A ++:10AB20000000050004C005C008A0090082088511C6 ++:10AB30008400000840029004A005A0090010000055 ++:10AB4000000010900000210000000400000000C080 ++:10AB500000C00000008400000000040000000000AD ++:10AB600000000000000800000000000000000000DD ++:10AB700000000900000041880000201100000000D2 ++:10AB8000000003082182100080002084C00100081A ++:10AB90008411C0108441004100051040C041C01123 ++:10ABA00082009021841000210005C011840511C18C ++:10ABB000041021210040028009A041A005C082416B ++:10ABC000000000110000C041C040C00001090000A9 ++:10ABD000840008008200100310008200840300003B ++:10ABE0008820C040A0100000841084218205C0216C ++:10ABF000C0218208C00088080000900009201000D1 ++:10AC0000824100038208C00082000800110810047D ++:10AC100009000000210041000200000003000000C4 ++:10AC20000000000000002100050004001100049055 ++:10AC300002000201A0020000C0001021202110909B ++:10AC400010900000030083010000000000000000DD ++:10AC50000000410010001000200000001100090059 ++:10AC6000090002000000022000000300100005009F ++:10AC700000000300090803100800050000A0C1053A ++:10AC8000020021008000C100050841000200C1014E ++:10AC9000820000000000880000100240040800004C ++:10ACA00040008811821108210200021110110000D9 ++:10ACB0008800010001202111000041202120051001 ++:10ACC00000040004000400001040001110000800FF ++:10ACD0000000000000100000000000000000200044 ++:10ACE00000000000000000000400C0090000000097 ++:10ACF000000000219000000890800000000000008B ++:10AD000004200000000004004000000000000000DB ++:10AD10000420200000100000000005C0000000001A ++:10AD2000031000000400000005C000080900001026 ++:10AD300004080300852088008001A120050020016F ++:10AD4000100182050000110005A0050000100000A0 ++:10AD500000002004000000000020410000840010DA ++:10AD60000000000000A000004100000010000000F2 ++:10AD70001000100010000000000000001100100082 ++:10AD8000080021009011000041A008881000000078 ++:10AD900090112001A1050005001004000440900856 ++:10ADA000C0109005C0020008000500088821C005F9 ++:10ADB00010211008880002850800040810211020C6 ++:10ADC0000120021005880000C04010098211000017 ++:10ADD0000010102011A10000000000408400840534 ++:10ADE0004000100310001021A000A0030020A021AB ++:10ADF0000005C003001084218400081184050000B0 ++:10AE0000000001000008410810001010010084003B ++:10AE1000002108100520108400400082000000A0DE ++:10AE200000100000100010101100030000000900C5 ++:10AE3000040003002184214004030904901141000F ++:10AE40000888900008820803050005C0210400005E ++:10AE500020000000400410880000000000001000E6 ++:10AE60000040000000000000000010001000090079 ++:10AE70001010050000000200004010000008030050 ++:10AE8000000800040200000010000091020200C04F ++:10AE9000031100040884000000000020000082402C ++:10AEA0000000000000008204000088000008040088 ++:10AEB00090412003100010009000919090801008A5 ++:10AEC000042000000821100000A08800880304115D ++:10AED0009020000020000000C000000000000000E2 ++:10AEE0000000A000000900030011A00300000004FE ++:10AEF0000020C00000000000000000000000000072 ++:10AF00000000000800000000201101000010008572 ++:10AF10000009004000008200004010000000000016 ++:10AF20000000000000000000000000000000000021 ++:10AF3000000000000000000000000000808003808E ++:10AF400080C1C1C0808020800082C10483808300D2 ++:10AF500000040341C0008080800203000000000064 ++:10AF600000000000000000000000000000000000E1 ++:10AF700000000000000000000000000000000000D1 ++:10AF80008300008083410000030000418988830022 ++:10AF90000300000303410000030000C1090000009A ++:10AFA00000000000000000000000000000000000A1 ++:10AFB000000000000000000000000000080008A0E1 ++:10AFC000C11008C108C10804014090088384091019 ++:10AFD0001182000401018382820482A10100000029 ++:10AFE0000000000000000000000000000000000061 ++:10AFF0000000000000000000000000000000000051 ++:10B000000082838200C0834190820184024182C019 ++:10B010000988858200010101000201A0C0C1000071 ++:10B020000000000000000000000000000000000020 ++:10B030000000000000000000000000000000000010 ++:10B0400082008408002102820202C10400008441BF ++:10B05000A1838383008303008382858300830104AB ++:10B0600000000000000000000000000000000000E0 ++:10B0700000000000000000000000000000000000D0 ++:10B080000000820088820083000082041182008216 ++:10B09000C004908383820083C10082000382008306 ++:10B0A000010200000000000000000000000000009D ++:10B0B0000000000000000000000000000000000090 ++:10B0C000000000000080002104880080C100001101 ++:10B0D0000983028320840083C100028904A000A0A8 ++:10B0E00008800000000000000000000000000000D8 ++:10B0F0000000000000000000000000000000000050 ++:10B10000000000000000008000830000000082803A ++:10B1100000808000108320A00083C100090082808D ++:10B12000008341000000000000000000000000005B ++:10B13000000000000000000000000000000000000F ++:10B14000000000000010000083A0C0C1000000004B ++:10B15000832120C100020080A00200000040008086 ++:10B16000844180000000000000000000000000009A ++:10B1700000000000000000000000000000000000CF ++:10B180000000000000000002000083C10000000079 ++:10B190000000802011A10040000083020000000098 ++:10B1A000008080808000000000000000000000009F ++:10B1B000000000000000000000000000000000008F ++:10B1C000000000000000000100C0A01005C1000048 ++:10B1D0000002051103C1000500C08383900000A197 ++:10B1E00000C082A1820000000000000000000000FA ++:10B1F000000000000000000000000000000000004F ++:10B2000000000000000000000001008283C1000077 ++:10B21000000000C0828990A1008300828383000027 ++:10B220000000000482A08200000000000000000076 ++:10B23000000000000000000000000000000000000E ++:10B2400000080000008200001111008241A1048367 ++:10B2500011080183A14110880482010101830000CB ++:10B26000C10101830101C083000000000000000053 ++:10B2700000000000000000000000000000000000CE ++:10B2800000000000000000000000838901820183AB ++:10B29000000004400110118304C083820101018376 ++:10B2A0000000400800040101A0C1000000000000EF ++:10B2B000000000000000000000000000000000008E ++:10B2C0000000000000000000000041821080822089 ++:10B2D00000A08280408302C080210489040302838D ++:10B2E0000000820341C04103808300000000000091 ++:10B2F000000000000000000000000000000000004E ++:10B3000000000000000000000000000002030480B4 ++:10B3100041020000008041009082008202900403FC ++:10B320000283000080800000210200C000000000B5 ++:10B33000000000000000000000000000000000000D ++:10B3400000000000000000000000000000000000FD ++:10B350000000124221820013C200124281600013D9 ++:10B36000C200124200000000000012420000000073 ++:10B3700000000000000000000000000000000000CD ++:10B3800000000000000000000000000000000000BD ++:10B39000000000001242000000000000124281483C ++:10B3A0000013C20012420000000000001242FFFF22 ++:10B3B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D ++:10B3C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10B3D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D ++:10B3E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D ++:10B3F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D ++:10B40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10B41000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10B42000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10B4300000D4CDD10C44407000E80A0600006059E9 ++:10B4400000000000000000000000000000000000FC ++:10B4500000000000000000000000000000000000EC ++:10B460000E5E01000000000000000000000000006F ++:10B4700000000000000000000000000000807A7062 ++:10B4800000000000000000000000000000000000BC ++:10B4900000000000000000000000000000000000AC ++:10B4A0000000AEDE00000000000000000000000010 ++:10B4B000000000000000000000000000000000008C ++:10B4C0007B7500000000000000000000000000008C ++:10B4D000000000000000000000000000000000006C ++:10B4E00000001E7BC002000000000000408C07002E ++:10B4F00000000000000030020000000000004003D7 ++:10B50000DE780000000000000000000000000000E5 ++:10B51000000000000000000000000000000000002B ++:10B5200000000000067BC000000000000000008C4E ++:10B5300007000000000000003000000000000000D4 ++:10B540000003DE6000000008110000000400040099 ++:10B550000090030004008300001004000410841015 ++:10B560008401110820080000000820C00004030026 ++:10B57000201004082000A0022020040008910000F0 ++:10B580000004210400000400200020000440800486 ++:10B590002004110020009100000020000409200078 ++:10B5A00080001100030111001100110000002100B2 ++:10B5B00000000400A0A0000000000400200080049F ++:10B5C0001100200484014000000000000000000081 ++:10B5D0000000400000000000080000000000000023 ++:10B5E0002000040400800000000000000000008033 ++:10B5F000000000000180010005804180010001047D ++:10B6000000000080A08000000000A1000000008079 ++:10B6100020800180000001002000A0000000000444 ++:10B6200000000800200000040000000020000400CA ++:10B63000000000000000042100000000A000020043 ++:10B64000048000000080044000900003008200009D ++:10B6500000000002000200000000000000000000E6 ++:10B66000000000000000000000000000004000009A ++:10B6700000010000000000000001000100090001BD ++:10B68000000100000010000000C0000000A08000C9 ++:10B690008000000000000011000400000000000015 ++:10B6A0000000000000010000000000000000000198 ++:10B6B000000000000000000000000000000000008A ++:10B6C0000000000000008000800100210008000050 ++:10B6D0000021000000000000000800000010000829 ++:10B6E0000000000000110000001000210021209047 ++:10B6F000002100020000000000110004000400848A ++:10B700000020002000080080000800000000000069 ++:10B710002010200000000000000400830000000052 ++:10B72000000000000000001020000008000082005F ++:10B7300004400000000000000010000000000000B5 ++:10B740000000040000210000020002200008008424 ++:10B75000050000A002002000110000840010000875 ++:10B7600000000410000041A0000200C00001000120 ++:10B770000885000811C080C005100340C0080420DF ++:10B78000040884040300002141C080000000000080 ++:10B7900000204120910000840000101020000008CB ++:10B7A0000004800000001010008200000010000063 ++:10B7B0000000030000000000000000008004000002 ++:10B7C0000090108200C000100000000000850003FF ++:10B7D00000100000000801000121002104100000F9 ++:10B7E0000000A00589050000000000008241A002C1 ++:10B7F00082020008A08882001000A02100C00580FD ++:10B8000011800380218800000090000004000000E7 ++:10B810000000008500800400A000C0400400C100BA ++:10B8200000000091200000000000002100008200C4 ++:10B83000C000C00008001000840000000000048068 ++:10B84000000000001121C0098400001100009004D4 ++:10B85000C100000000000000000020010200910073 ++:10B8600000000500108400000400090005008000AD ++:10B870000900110000000000109010002000850059 ++:10B880000000030010000000030005000500C101D6 ++:10B89000000020010000C1000001000000002000A5 ++:10B8A0001000100010001000050000000000100043 ++:10B8B000000000000000000041040000030003003D ++:10B8C0008000030011008200050005002000020036 ++:10B8D0000402080200000002000000030040100003 ++:10B8E000200000000021010000000000040084008E ++:10B8F0002000900000000000002100098400C0101A ++:10B9000020001000004001000000000000100000B6 ++:10B91000402000000120000004000008C005820053 ++:10B9200009200000000000000000040000000000EA ++:10B9300001400040900410000000000020000000C2 ++:10B9400000000241900020200408A00010008400A4 ++:10B9500003000080001000000000048400000000CC ++:10B96000000480840441104100000201040404002A ++:10B9700003040440850010C1108500010004030089 ++:10B98000C105001000C11000800810C000000000B8 ++:10B99000082000100000000000A0410080004101CC ++:10B9A00000000800000011000000040004820000F4 ++:10B9B00000004100108400C000A00200051100003A ++:10B9C00010000000008410000000000800000000CB ++:10B9D000000010C0024000000000001085100010A0 ++:10B9E000C0000080020000029002000001040180FB ++:10B9F00001000080014110009140C002901084833A ++:10BA0000080302C0100084200020108908090000EB ++:10BA100000000080840000C000000000000004005E ++:10BA2000000800000000000000000000010001000C ++:10BA3000000000000000000000000000C108000835 ++:10BA40009005001084000021000000008400100018 ++:10BA50001000000008001100000400000004410074 ++:10BA60000400200021400084410004C04040000048 ++:10BA70000420028400400290219002822004119050 ++:10BA8000210005A020002082000441A10404080038 ++:10BA90001091902090209010000000A000000090D5 ++:10BAA00004A041840404049004850801004080003F ++:10BAB000820000A0002040004140100400A010407F ++:10BAC00000000000002010A0100004004020002012 ++:10BAD0008010800002000210020000000000000040 ++:10BAE0000000000000008280000000000000848050 ++:10BAF00000000000000002800100884100112000C9 ++:10BB00000041C00000200404202000002010030099 ++:10BB1000840000040400201120A100400000000067 ++:10BB2000000000000000108000000040051000210F ++:10BB30000400050900000000000000800000000073 ++:10BB40000080000000000000000000000100010073 ++:10BB5000000004000405000002000521000591001A ++:10BB600091400040000009800200000009008900A7 ++:10BB7000890041000000090008000000400080002A ++:10BB8000890040000200090041004100008011804E ++:10BB9000C1000300C00309118000418900000000BA ++:10BBA0000000C100000080210040020400200321A9 ++:10BBB00000092005044002000000210008000000E8 ++:10BBC00000004000000000008000820000004000F3 ++:10BBD00000088041002089830091009110890001B4 ++:10BBE000C000C001000188202104018800A00100DC ++:10BBF000050003000100880001002000000089000A ++:10BC00004000A000010089000900000001000404B8 ++:10BC10008508C082000088018400080001910000AE ++:10BC2000000008001000000020004000010000009B ++:10BC300001000401010000010100C00091000100A9 ++:10BC40000000000000000000000082004000000032 ++:10BC50000100000102000001898300100010018929 ++:10BC60000800008800008200020020014000888255 ++:10BC70004190100111209000059040019004410175 ++:10BC800041A0200082058500000004010802040094 ++:10BC9000040090820101042001109008019001002D ++:10BCA0000000018200010090000100000008000077 ++:10BCB00000000900C0088800830100000100012085 ++:10BCC0000101100000000100010020002000100010 ++:10BCD000200001820000000400004100088491015E ++:10BCE000850000000000002080080009000400001A ++:10BCF00080C0A000912090800541C00008042180F0 ++:10BD00000908092180000089832100008204400085 ++:10BD10004003410405A0050540851080828041054F ++:10BD20001040000009804120040000200000008233 ++:10BD300000030002A0008980800589050000400002 ++:10BD40002180092088000400100005008000800088 ++:10BD500080008011088021002100040009004000BB ++:10BD600021219021020000000080048080000080DA ++:10BD70001100000000092009218580838080208037 ++:10BD800011000080008002000011800380800010FC ++:10BD900011400009009000A0A08400830902210541 ++:10BDA0000005A110000000001100200000000800A4 ++:10BDB0000000028003000040000209C004000008E7 ++:10BDC0000008000400A10000000000000000008046 ++:10BDD000000000808000020811022041894102C059 ++:10BDE0000005894080210008000800840088822026 ++:10BDF0002004828800A09021012100884083824095 ++:10BE0000010200829040000800A000204021822012 ++:10BE100000040082C08802099021A1A0A083000034 ++:10BE20000101000011010000A0C000020182080011 ++:10BE30000588009001080020008900A1010390A05E ++:10BE400000A100C100C0008200C0004000200040EE ++:10BE5000002000900084028801010001000003011D ++:10BE60000104840189058208000100000100000826 ++:10BE700008880810080008A0000300400000001017 ++:10BE800000A000400000000083208501100088A071 ++:10BE90000090008900010000020000044000A1A100 ++:10BEA00000908582008801000000004000880001A9 ++:10BEB0000000000401080000010001910090010051 ++:10BEC0000088009000000000000000000000000159 ++:10BED0000000000100000000004000000089000098 ++:10BEE000000000890090010001881111030010007A ++:10BEF00003808085008000000000008800910040E1 ++:10BF000000800005000200050000834109409111F6 ++:10BF1000800000000020002000008421408983214F ++:10BF2000100840804085099110000000000000903A ++:10BF300000020000030005000300200009110205B3 ++:10BF40004004038000000000000000000000000822 ++:10BF50000020000000030000000000000000008539 ++:10BF60000002000040900209110410000A000013B2 ++:10BF7000000000000000000081004160818100138A ++:10BF8000C200000082000013810041001200001373 ++:10BF90000000000000000081810041000042001309 ++:10BFA000C20042000000008181001100000000007A ++:10BFB00000818100810000000000C200000081417A ++:10BFC0000013C2000A0000810013C200000000003C ++:10BFD0000000000000000A000021C2004200000032 ++:10BFE0000081000081000000008181000050FFC33B ++:10BFF000FF430000000000000000000000000000FF ++:10C0000000000FFF663C0000000000000000060674 ++:10C010000F006600FF0000000000FF09FFF99F9F6E ++:10C02000BD24FCFC000300004F0D090918090000A5 ++:10C0300000000000000000003636FF0F0000000086 ++:10C04000FFF700340F0F0F0F00000000FF6699008C ++:10C0500000000000000000000000000000000000E0 ++:10C0600000000000E6FE260200004F0D0202020260 ++:10C07000FFC3FF00000000000000000000000000FF ++:10C08000000000000F00663C0000000000000000FF ++:10C0900006060F006600000000000000F600060023 ++:10C0A0000606BD240C0C00F300004200000018003E ++:10C0B000000000000000000000003636F000000024 ++:10C0C0000000FFC700046F2D6F2D0000000030300E ++:10C0D0003030000000000000000000000000000000 ++:10C0E000000000000000E6FE260200004200C3003F ++:10C0F0000202FFFFFFFFFFFFFFFFFFFFFFFFFFFF4A ++:10C10000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:10C11000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F ++:10C12000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F ++:10C13000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F ++:10C14000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ++:10C15000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF ++:10C16000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10C17000FFFFFFFF00705CFB0C4440F000180A0654 ++:10C1800000005014F4F4FFFF000000000000000065 ++:10C19000000000000000000000000000000000009F ++:10C1A000C090C0900000000066663C3C00000000AB ++:10C1B0000009F6FF0000000070007F003C3C66664E ++:10C1C00040C100C30000000000007C7F7C7FF000C5 ++:10C1D000000000000000006F80EF0000FFFF000083 ++:10C1E000000000F00FFF0000000000C1C3C100000C ++:10C1F0000000000000003C363C36420342C3333CA2 ++:10C20000FCFF0C060C0CF4F4F4F400000000000039 ++:10C210000000000000000000000024E730F30000F0 ++:10C2200000000000C39900000000000000000000B2 ++:10C230000000006F90FF0000000010001F00C33CD2 ++:10C24000A566404000000000000000001C101C100B ++:10C250002400240000000000006F80EF6464FDFDF6 ++:10C260000000000000F00FFF000000000040C3408D ++:10C27000000000000000000066366636420042C042 ++:10C28000333C030000060000000600E101900000BE ++:10C29000A0865070A0B00005A08650F4A1B900851A ++:10C2A000A08650F0A1B00005058600E001B900A00D ++:10C2B000A0865071A0B80005A0865094A88900857A ++:10C2C00000000AF0003000000000A08650E0A8B096 ++:10C2D0000005A0865070A0B000050006007401A003 ++:10C2E0000000008600E4003000000086006000B01E ++:10C2F0000000008600E109B00405008600E000B0FF ++:10C30000008000860A5100B0000000000000000814 ++:10C31000FFF72C00002C417D0000000000003F3F93 ++:10C3200014D70000000000000100AFA03030287DCD ++:10C33000000000000000FF3500000E0E0404FFFFA7 ++:10C3400028280000FF00FFFF0000000000000000A0 ++:10C35000B2FFB2FF0000000000000000000000007B ++:10C360000DFD0FFF0000000000003B3B000000003F ++:10C370001E1E0F3C0000000000F000F00000000056 ++:10C3800000000000000000003C3C00FF0000000036 ++:10C390000000FFFF83000083407040700000000039 ++:10C3A000030314D70000000000000100AFA03030EC ++:10C3B0002070207000000000003500000A0A000014 ++:10C3C00055FF000A0000FF00000000000000000010 ++:10C3D0000000004D004D00000000080808CB0000E0 ++:10C3E000000008F800F000000000C3033B3B000021 ++:10C3F00000001E1E0F3C0000000010F000F00000C6 ++:10C40000000000000000000000003C3C00FF0000B5 ++:10C410000000BEBE555580D082D7000820280000FD ++:10C42000000082AA8A8A000000000C00CFFF0000F2 ++:10C4300000007D7F7DFF000000000FFF0F0F5505FE ++:10C4400050004040707000003C3C0F0F00000000A6 ++:10C4500000000000000000000000000000000000DC ++:10C46000000000005050050F000000000000000018 ++:10C4700000000000C3C3C3C3000000000000008030 ++:10C480000000000000000000FFFFAAAA00058005D0 ++:10C49000000000004141000080D00000000BE0EBF4 ++:10C4A0000000000000280808000000000F030F3FF4 ++:10C4B0000000000055555555000000000FFF0F0FFC ++:10C4C000500050000000303000003C3C0F0F0000D6 ++:10C4D000000000000000000000000000000000005C ++:10C4E000000000000000D755000F00000000000011 ++:10C4F000000000000000C3C3C3C300000000000030 ++:10C5000000000000000000000000FFFEAAA90000DB ++:10C5100000004000000082000400000800900400B9 ++:10C5200000000000802021000010000000008000BA ++:10C53000409040000000040020000400040040007F ++:10C5400000000000000020000408A10000002004FA ++:10C550000000000040000000000011000400040082 ++:10C5600020002000040084008000800804000000F7 ++:10C57000000000000400000040000400040041002E ++:10C580000000000004000400000020002100000062 ++:10C590000000210000000000210000000000000059 ++:10C5A000040000000000088000000000900000006F ++:10C5B00020009000000000000000010001000100C8 ++:10C5C0000400400000002000200001800400000062 ++:10C5D00000800000000000000000000000000005D6 ++:10C5E0000000000000000100410004000480000081 ++:10C5F0000000040000000000000000000000000037 ++:10C600000400000000000000000000000000000026 ++:10C61000A00000000000000000000000000000007A ++:10C62000000000000000000000000000000000000A ++:10C6300000000000000000000001000000000000F9 ++:10C6400000000000000000000000000000010000E9 ++:10C6500000000000000000C000000000000000001A ++:10C6600000000000000000000000000000000000CA ++:10C6700000000000000000000000000000000000BA ++:10C6800000000000000000000000000000000000AA ++:10C690000000000000000000001100000000000089 ++:10C6A000000000000010000800000000000000086A ++:10C6B0000000001000080000000000020000000060 ++:10C6C0000000000000100008000000000021002011 ++:10C6D0000000000800000000000000000000000052 ++:10C6E000000000000000001000000000000000003A ++:10C6F000000000000000000000000000000000003A ++:10C700000000000000000008000000000000000021 ++:10C710000010000000000000000000C000008000C9 ++:10C720008000008504010301002000200085000135 ++:10C73000000100C00000000000000000098410009B ++:10C740008001040004000400830100000082004016 ++:10C750000001000000000000410000000000000097 ++:10C760001082000000000000000000000000050131 ++:10C7700000001000000000000000000000000000A9 ++:10C78000001000000000000010000000050005007F ++:10C790000000000000000000000000000003000096 ++:10C7A0002000202100021104840400800080001079 ++:10C7B0000020001084080008000084008203841117 ++:10C7C00010000440850091008300402000410003D8 ++:10C7D0000080002000000000C00000000000C00039 ++:10C7E000C00084000000000884000000C021000098 ++:10C7F0000002100011000000840000000000000092 ++:10C800000000000000030000000388008400000016 ++:10C810000000C0008800100000008400000000003C ++:10C8200000000500000004008900850004000800E5 ++:10C8300089000401100002000001000084011000C2 ++:10C8400009010300400000000000A00020002000BB ++:10C850002000000041000000200000001000000047 ++:10C86000100000000000100009000000000000009F ++:10C8700000000000000000000000000000000200B6 ++:10C880000000000004000000000002001000000092 ++:10C89000020020002000020000000900000000004B ++:10C8A0000000000000000000010020000400010062 ++:10C8B0000100080001200100010000200000200804 ++:10C8C0000000004000000000000000020400000022 ++:10C8D0000000000000000000000000000000000058 ++:10C8E000000000000000000000000009000000003F ++:10C8F0000000000000000000000000000000000038 ++:10C900000000000000000000000000000000000027 ++:10C910000000000000000011000000000000000006 ++:10C9200000000040000003012000C18420400004FA ++:10C93000C1108000042003000421001020200020EA ++:10C940004120410000000000102005000000100000 ++:10C950008000000000001000000080000000800146 ++:10C960008082000000820000000000000000000043 ++:10C9700010000000000000000000000000000000A7 ++:10C9800000000000000000000000000000000000A7 ++:10C990000000000100000000000000000000000096 ++:10C9A0000001800100800010004001214000118042 ++:10C9B0000091202108080188001001A0008001805A ++:10C9C000008800A184008400100004A10000000081 ++:10C9D0001000042184218800C000840004030400A6 ++:10C9E0000804202100C000000000842100408800CD ++:10C9F000C00000000000C00000000005C0000003EF ++:10CA00000000000000000000000000000000000026 ++:10CA100000000003100400000000002100000000DE ++:10CA2000C000C0042004000000840200000280C096 ++:10CA3000000104000020041088000500044103C028 ++:10CA400040102005850210000084040009404000C9 ++:10CA5000400020002004002000900088004000904A ++:10CA60000000200000000000000040000000004026 ++:10CA70000000410000400000000020000000001005 ++:10CA80000082000000000000000004000000200000 ++:10CA90001000100000000000000000022000002034 ++:10CAA0000000000020400000000000000100000025 ++:10CAB00040000020110000800180210000000110D2 ++:10CAC0000000008001A010800000000000000000B5 ++:10CAD0000100010000000100000000000000000053 ++:10CAE0000000000000000000004000000000000006 ++:10CAF0000000000000000000000000000000000036 ++:10CB00000000000000000000000000000000000025 ++:10CB10000000000000000000000000000000000015 ++:10CB200000000000200000000000000005000000E0 ++:10CB3000008011110009000209090008081080880E ++:10CB400000880005910200800082000000002000A3 ++:10CB500000801103800903A0050300000000850088 ++:10CB600000000983008000800983000000000000AD ++:10CB70000000000000000000000000000080418074 ++:10CB80008080008000000000000000000000000025 ++:10CB90000000000000000000000000000000000095 ++:10CBA00000000000020300000005090000820140AF ++:10CBB000000800C089010001A001010100000191ED ++:10CBC00010C1000902C191851010000802C0048440 ++:10CBD0000002000801A18291900500000000A00061 ++:10CBE000020000000182000400040188000000002F ++:10CBF00000000000000000000000000000000088AD ++:10CC0000C0400220000400000000000000000000FE ++:10CC10000000000000000000000000000000000014 ++:10CC20000000000000000100000000000100000002 ++:10CC30000000A0A000850189000000A00089010972 ++:10CC4000111100C1018282019108C08982C00000D7 ++:10CC50000100000000A000018982219121830000D1 ++:10CC60004100A000100001000000010001000000D0 ++:10CC700000000000000000000000000000000000B4 ++:10CC800003004000880021C00000000000000000F8 ++:10CC90000000000000000000000001000000010092 ++:10CCA0000000000000000000000000000002010081 ++:10CCB0000040000000000083021000000080008996 ++:10CCC00010048589088810800002888200A0808472 ++:10CCD00011002000030003020002C100A0A083890C ++:10CCE0000000C0004100C100090003000800090065 ++:10CCF0000000000000000000000000000000000034 ++:10CD00000000104185008300038000000000000047 ++:10CD100000000000000000000000410010000000C2 ++:10CD20001000000000000000000009000300038064 ++:10CD300009000000000003000000414104412009F7 ++:10CD400089830800100000808980020000000980AB ++:10CD5000A08000808080008000004110800209A037 ++:10CD6000110300800080000000000040800880095E ++:10CD70008011000000000000000000000000000022 ++:10CD80000000000000800080408000800000000063 ++:10CD90000000000000000000000000000000000093 ++:10CDA000210000000000000000000000000200055B ++:10CDB000090400050040880003000088000001010C ++:10CDC0000101898901004188A0A089820000A0C0DA ++:10CDD00082A0898200020840A040020000A10491C4 ++:10CDE000838901010004000400C000000001020169 ++:10CDF00088010201000000000000000000000000A7 ++:10CE00000000000000000040004082200088000078 ++:10CE10000000000000000000000000000000000012 ++:10CE20000000000000000000000000000000000101 ++:10CE3000000101000000900020008800A002404096 ++:10CE400010828801C000838485828901010091A13C ++:10CE50008903A000A1888402C000000002000389A9 ++:10CE600090210100030200000000000000200000EB ++:10CE700000100001000000000000000000000000A1 ++:10CE80000000000000000000024088004000022076 ++:10CE90000000000000000000000000000000000092 ++:10CEA0000000000100000000000000000000000081 ++:10CEB0000000002000000000000000000000000052 ++:10CEC00080808000002100008880108221400800BE ++:10CED0009111C110910040808000001100400000BD ++:10CEE0008383209102022000000200040011000050 ++:10CEF000000000840021000000000000000000008D ++:10CF00000000000000000000000080C180058000DB ++:10CF10000000000000000000000000000000000011 ++:10CF200000000000002000020000000000000000DF ++:10CF30000000000000050005000000600000C200C5 ++:10CF4000004206600013C20000000A500013C20035 ++:10CF500082480A600013C200000081810013C200F1 ++:10CF6000000000420013C2000A500000001300003D ++:10CF700000000000008181000000000000000000AF ++:10CF8000000000000000000000000000210000136D ++:10CF90000000000000000000000000000000000091 ++:10CFA0000000000000840000840000000000000079 ++:10CFB00000000000000000008100000000000000F0 ++:10CFC0000000000000000000556530CF0000001098 ++:10CFD0000000000030100C04000000000000000001 ++:10CFE0000000000055FF2D2DFF553C0F00000000F4 ++:10CFF0000000000000000000303000500000000081 ++:10D000000000000000000000000000000000000020 ++:10D010000000000000000000000000000000000010 ++:10D020000000000000000000000000000000000000 ++:10D030000000000000000000000000A008A80000A0 ++:10D0400000000000000000000000555500FF000037 ++:10D05000000000000000C0400301000000000000CC ++:10D0600000000000000000AA2D2D00553C0F00001C ++:10D070000000000000000000000030305000000000 ++:10D0800000000000000000000000000000000000A0 ++:10D090000000000000000000000000000000000090 ++:10D0A0000000000000000000000000000000000080 ++:10D0B00000000000000000000000000000A002A22C ++:10D0C0000000000000000000EF10FF003C3C3C3C72 ++:10D0D000EFFFFFFFA8BC283C960000000A0A0A0ADE ++:10D0E0000000000055514541FC0CAFAFF0FFFFAA16 ++:10D0F00000000000FFFFFA50FFFFC3C3000A003A20 ++:10D10000000000000000000000000000000000001F ++:10D11000000000000000000A000200000000000003 ++:10D120000000000000000000000000000000FFFF01 ++:10D13000FFFF0000000000000000FFFF0F0F0008CD ++:10D1400000FD0000000000000000FF00FF00C3C35E ++:10D15000C3C3FFFFFFFFFCFC3C3C009600000A0A33 ++:10D160000A0A0000000014100400FC0CA0A0F0004B ++:10D1700000AA0000000005AF0000FFFFC3C30000CD ++:10D18000003C000000000000000000000000000063 ++:10D190000000000000000000000A00020000000083 ++:10D1A000000000000000000000000000000000007F ++:10D1B000FEFEFFFF0000000000000000FFFF0F0F59 ++:10D1C0000008000800860064A8B0A005008600F5ED ++:10D1D00009920000000270F509100000000652B527 ++:10D1E000A90000050086006509B0848508860494BE ++:10D1F00008820010008600E00090000000860251C6 ++:10D2000000B000000000000000000000000000006E ++:10D2100000000000000000860080018000A00000E7 ++:10D2200000000000000000000000000000000000FE ++:10D2300000040800000000000000000000000000E2 ++:10D2400000100000000010002000C3C33C3C600040 ++:10D250000900FFFF0000F000AAAA0F0FFF007F8067 ++:10D26000FF00FF0FF00F3C0000005C555C5500EB29 ++:10D270000028407040700000000010F010F0000026 ++:10D28000000000000000000000000000000000009E ++:10D2900000000000000000007878FF00000FFFFF92 ++:10D2A000000000000000000000000000000000007E ++:10D2B000000000000000000000000000000000006E ++:10D2C000000000000000000000000000C3C33C3C60 ++:10D2D00060600909FFFF00000F00AAAA0F0FFF00FE ++:10D2E000FF00FF0000F0F00F003C00003C353C3533 ++:10D2F000002800280030003000000000100010005E ++:10D30000000000000000000000000000000000001D ++:10D3100000000000000000000000FF00FF00000C03 ++:10D32000FFFC000000000000000000000000000002 ++:10D3300000000000000000000000000000000000ED ++:10D34000000000000000000000003C3C3C3C550098 ++:10D3500055000000000000000000208020800F0F1A ++:10D36000000024008100FBFF393C22001100000076 ++:10D37000000000FF00A00500AF000000000050000A ++:10D380005FFFFFFFAAAA00000000000000000000ED ++:10D39000000000000000000000000000FFFFF0009F ++:10D3A00000FF05F500000000000000000000000084 ++:10D3B000000000000000000000000000000000006D ++:10D3C000000000000000000000000000BFFF3C3C27 ++:10D3D000550055000000000000000000288228824F ++:10D3E0000F0F0000002400810400393C00220011CE ++:10D3F00000000000000000A0050005000000000083 ++:10D40000550555F5FFFEAAA9000000000000000028 ++:10D4100000000000000000000000000000003FFFCE ++:10D42000300000FF0CFC00000000000000000000C5 ++:10D4300000000000000000000000000000000000EC ++:10D4400000000000000000000000000000000000DC ++:10D4500000000000000000000000000000000000CC ++:10D460000000210000000000000004000000000097 ++:10D4700000000000000000000000000800000000A4 ++:10D48000000021000000000000000000000000007B ++:10D49000000000000000000000000000000000008C ++:10D4A000000000002000200000000000000000003C ++:10D4B000000000000000C1010000000000000000AA ++:10D4C00000002000000000000000000000004000FC ++:10D4D000000000000000000000000000000000004C ++:10D4E00000000000C00000000000A00000000000DC ++:10D4F000000000000000A0000000000090000000FC ++:10D500000000000000000000000000000400000017 ++:10D51000000000000000000000000000000000000B ++:10D5200000000000000004000000000000000000F7 ++:10D5300000000000000000000210000000002000B9 ++:10D5400000000000000020000000000000000000BB ++:10D550000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFD9 ++:10D56000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB ++:10D57000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:10D58000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB ++:10D59000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B ++:10D5A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B ++:10D5B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B ++:10D5C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B ++:10D5D000FFFFFFFF00BCDC7F0C44408800C00A0650 ++:10D5E000000080A2000000000021000000000000F8 ++:10D5F000000000000000000000000010000000001B ++:10D600000000000000000000000000000003000017 ++:10D6100000000010000000000000001000000000EA ++:10D6200000000000000000000000000000000000FA ++:10D6300000000000001000000000000000100000CA ++:10D6400000000000000000000000000000000000DA ++:10D6500000000000001000000000000000100000AA ++:10D6600000000000000000000000000000000010AA ++:10D6700000000000000000000000000800000000A2 ++:10D680000082000000000000000000000000000018 ++:10D690000000410000000000000010000000000039 ++:10D6A0000000000000000000000000004100000039 ++:10D6B000000000000000000000000000000000006A ++:10D6C000000000000000000000000000000000005A ++:10D6D000000000000000000000000000000000004A ++:10D6E000000000000000000000000000000000003A ++:10D6F0000000000500000000000000000000842180 ++:10D700000000C00300000000000000000000000056 ++:10D7100000000000C00800000000000082000000BF ++:10D7200000000000000000000000004100000000B8 ++:10D7300000000000000000000010000000000000D9 ++:10D7400000000000000000000000000000000000D9 ++:10D7500000000000000000000000000000001000B9 ++:10D7600000000000000000000000000000000000B9 ++:10D77000000000000900110000001100000002007C ++:10D7800000000000000040901000000000000000B9 ++:10D790000000000000000000000000000000200069 ++:10D7A0000000000000000000000000000000000079 ++:10D7B0000000000000000000000000000000000069 ++:10D7C0000000000000000000000000000000000059 ++:10D7D0000000000000000000000000000000400009 ++:10D7E000000000000000000000000000FFFFFFFF3D ++:10D7F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39 ++:10D80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28 ++:10D81000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 ++:10D82000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 ++:10D83000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8 ++:10D84000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8 ++:10D85000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8 ++:10D86000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00D0F6 ++:10D8700049F10C44408800100A0600008020000096 ++:10D880000000000000000000000000000000000098 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000004100000037 ++:10D8B0000000000000000000000000000000000068 ++:10D8C0000000000000000000000000000000001048 ++:10D8D0000000000000000000000000000000000048 ++:10D8E00000000000000000000000000000A0000098 ++:10D8F0000000000000000000000000000000000028 ++:10D900000000000000000000000000000003001004 ++:10D91000000000038400000384218400C000002173 ++:10D92000C0000003C00800008400000000000000E8 ++:10D9300000000008000000210000000000080000B6 ++:10D9400000000003000000000000000000000000D4 ++:10D9500000000000000000000000000000000000C7 ++:10D9600000000000000000000000000000000003B4 ++:10D970000000000000000000002100000000000086 ++:10D980008400000000000000000000000000110002 ++:10D990000900090002000000000000000000000073 ++:10D9A000008840020000000000400000000000006D ++:10D9B0000000000000000000000000000000000067 ++:10D9C000000800000000000000000000000000004F ++:10D9D0000000000000000000000000000000000047 ++:10D9E0000000000000000000000000000000000037 ++:10D9F00000000000000000000010100009000000FE ++:10DA000000000020FFFFFFFFFFFFFFFFFFFFFFFF02 ++:10DA1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:10DA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:10DA3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10DA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:10DA5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10DA6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:10DA7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 ++:10DA8000FFFFFFFFFFFF002C12120C4440880070C4 ++:10DA90000A06000000C300000000000000000000B3 ++:10DAA0000000000000000000000000000000000076 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000000000000000000000000000000056 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000100000000000000000000000000000014 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000000000F5 ++:10DB300000000000000000000000000000000000E5 ++:10DB400000000000000000000000000000000000D5 ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB700000000000000000000000000000000000A5 ++:10DB8000000008000000000000000000000000008D ++:10DB900000000000000000000000FFFFFFFFFFFF8B ++:10DBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10DBB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10DBC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:10DBD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:10DBE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10DBF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:10DC0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 ++:10DC1000FFFFFFFFFFFFFFFFFFFFFFFF007C9DA057 ++:10DC20000C44408800E80A060000004100000000A3 ++:10DC300000000000000000000000000000000000E4 ++:10DC400000000000000000000000000000000000D4 ++:10DC500000000000000000000000000000000000C4 ++:10DC600000000000000000000000000000000000B4 ++:10DC700000000000000000000000000000000000A4 ++:10DC80000000000000000000000000000000400054 ++:10DC90000000000000020000000000000000000082 ++:10DCA0000000000000000000000000000000FFFF76 ++:10DCB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:10DCC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:10DCD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 ++:10DCE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:10DCF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10DD0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10DD1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10DD2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:10DD30000074185D0C44408800D80A06000080E397 ++:10DD400000000000000000000000000000000000D3 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000000000000000B3 ++:10DD700000000000000000000000000000000000A3 ++:10DD80000000000000000000000000000000000093 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000020000053 ++:10DDB0000000000000000000000000000000000063 ++:10DDC0000000000000000000000000000000000053 ++:10DDD0000000000000000000000000000000000043 ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000000000000000000000000012 ++:10DE10000000000000000000000000000000000002 ++:10DE200000000000000000000000000000000000F2 ++:10DE300000000200000000000000000000000000E0 ++:10DE400000000000000000000000000000000000D2 ++:10DE500000000000000000000000000000000000C2 ++:10DE600000000000000000000000000000000000B2 ++:10DE700000000000000000000000000000000000A2 ++:10DE80000000000000000000000000000000000092 ++:10DE90000000000000000000000000000000000082 ++:10DEA00000000000000000000090000000000000E2 ++:10DEB0000000010000000000000000000000000061 ++:10DEC000000000000000FFFFFFFFFFFFFFFFFFFF5C ++:10DED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 ++:10DEE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 ++:10DEF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 ++:10DF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 ++:10DF1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 ++:10DF2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 ++:10DF3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 ++:10DF4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 ++:10DF5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 ++:10DF6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 ++:10DF7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 ++:10DF8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 ++:10DF9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:10DFA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 ++:10DFB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 ++:10DFC000FFFFFFFFFFFFFFFFFFFF0000000000005B ++:10DFD0000000000000000000000000000000000041 ++:10DFE0000000000000000000000000000000000031 ++:10DFF0000000000000000000000000000000000021 ++:10E000000000000000000000000000000800000008 ++:10E0100048000000000000000000000000000000B8 ++:10E0200000000000000000000000000000000000F0 ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E0500000000000000000000000000000000000C0 ++:10E0600000000000000000000000000000000000B0 ++:10E0700000000000000000000000000000000000A0 ++:10E080000000000000000000000000000000000090 ++:10E090000000000000000000000000000000000080 ++:10E0A0000000000000000000000000000000000070 ++:10E0B0000000000000000000000000000000000060 ++:10E0C000000000000000000000000000000000F858 ++:10E0D000DEC50C85004004000400040004000400B8 ++:10E0E000040004000400CC26000000000000000032 ++:10E0F0000C44C00000C0CC2600000000000000005E ++:10E100000C44C0800000CC2600000000000000008D ++:10E110000C44C0800080CC260000000000000000FD ++:10E120000C44C08000A0CC260000000000000000CD ++:10E130000C44C0800060CC260000000000000000FD ++:10E140000C44C0800030CC2600000000000000001D ++:10E150000C44C08000B0CC2600000000000000008D ++:10E160000C44C0800008CC26000000000000000025 ++:10E170000C44C0800088CC26000000000000000095 ++:10E180000C44C08000C8CC26000000000000000045 ++:10E190000C44C08000A8CC26000000000000000055 ++:10E1A0000C44C0800098CC26000000000000000055 ++:10E1B0000C44C0800058CC26000000000000000085 ++:10E1C0000C44C02000A8CC26000000000000000085 ++:10E1D0000C44C0200068CC260000000000000000B5 ++:10E1E0000C44C0A000E8CC260000000000000000A5 ++:10E1F0000C44C0E00030CC2600000000000000000D ++:10E200000C44C0E000B0CC2600000000000000007C ++:10E210000C44C0E00070CC260000000000000000AC ++:10E220000C44C0E000F0CC2600000000000000001C ++:10E230000C44C0E00008CC260000000000000000F4 ++:10E240000C44C0E00088CC26000000000000000064 ++:10E250000C44C0E00048CC26000000000000000094 ++:10E260000C44C0E000C8CC26000000000000000004 ++:10E270000C44C0E00028CC26000000000000000094 ++:10E280000C44C0E000A8CC26000000000000000004 ++:10E290000C44C0E00068CC26000000000000000034 ++:10E2A0000C44C0E000E8CC260000000000000000A4 ++:10E2B0000C44C01000E8CC26000000000000000064 ++:10E2C0000C44C0900078CC26000000000000000044 ++:10E2D0000C44C03000E8CC26000000000000000024 ++:10E2E0000C44C07000A8CC26000000000000000014 ++:10E2F0000C44C0700068CC26000000000000000044 ++:10E300000C44C0880080CC26000000000000000003 ++:10E310000C44C0880040CC26000000000000000033 ++:10E320000C44C0880060CC26000000000000000003 ++:10E330000C44C08800E0CC26000000000000000073 ++:10E340000C44C08800D0CC26000000000000000073 ++:10E350000C44C0880030CC26000000000000000003 ++:10E360000C44C08800B0CC26000000000000000073 ++:10E370000C44C0880008CC2600000000000000000B ++:10E380000C44C0880088CC2600000000000000007B ++:10E390000C44C0880048CC260000000000000000AB ++:10E3A0000C44C08800C8CC2600000000000000001B ++:10E3B0000C44C0880028CC260000000000000000AB ++:10E3C0000C44C08800A8CC2600000000000000001B ++:10E3D0000C44C0880068CC2600000000000000004B ++:10E3E0000C44C08800E8CC260000000000000000BB ++:10E3F0000C44C0880018CC2600000000000000007B ++:10E400000C44C0880098CC260000000000000000EA ++:10E410000C44C0880058CC2600000000000000001A ++:10E420000C44C00000400C8500800A06000000413A ++:10E4300000000000000000000000000000000000DC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000000010200000102000000000000000003C ++:10E48000000000000000000000000000000000008C ++:10E49000000000000000000000000000000000007C ++:10E4A000000000000000000000000000000000006C ++:10E4B0000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF6A ++:10E4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:10E4D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10E4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10E4F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10E50000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10E51000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10E52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:10E53000FFFFFFFF0030976E0C44C08000400A06CA ++:10E54000000080200000000000000000000000002B ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000000000000000008B ++:10E59000000000000800000000000000080000006B ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000001000000000000000000000000000000B ++:10E6000000000000000000000000000000000010FA ++:10E6100000000010000001000000000000000100E8 ++:10E6200000000000000000000000000000000041A9 ++:10E63000000000200010000000100000000000009A ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E66000000000000000000000000000000000109A ++:10E67000000000000000000000000000000000009A ++:10E68000000000000000000000000000000000008A ++:10E69000000000000000000000000000000000007A ++:10E6A00000000000000000000084000000000000E6 ++:10E6B000001000000000000000A0000000000000AA ++:10E6C00000000000000000000000FFFFFFFFFFFF50 ++:10E6D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A ++:10E6E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A ++:10E6F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A ++:10E70000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19 ++:10E71000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09 ++:10E72000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9 ++:10E73000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9 ++:10E74000FFFFFFFFFFFFFFFFFFFFFFFF00F853FB8F ++:10E750000C44C08000E00A06000080610000000058 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000000000000099 ++:10E780000000000000000000000000000000000089 ++:10E7900000000000A000A000000000000000000039 ++:10E7A000A00000000000A000A000A00000000800E1 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000000039 ++:10E7E0000000000000000000000000000000000029 ++:10E7F0000000000000000000000000000000000019 ++:10E800000000008800000000000000000000000080 ++:10E8100000000000000000000000000000000000F8 ++:10E820000000000000A00000000000000000000048 ++:10E8300000000000000000000000000000000000D8 ++:10E84000001000A000000000000000000000000018 ++:10E8500000C00000000000000000000000000010E8 ++:10E860000000000000000000000000100000000098 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000008400000000000094 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E93000001000000010000000000000000000C0F7 ++:10E94000000000000000000000000000000000C007 ++:10E9500000000000000000000000001000000000A7 ++:10E9600000000000000000000000000000000000A7 ++:10E970000000000000000000000000000000000097 ++:10E980000000A041000000000000000000000000A6 ++:10E9900000000000A0000000A00400000020000013 ++:10E9A0000000000000000000000000000000000067 ++:10E9B0000000000000000000000000000000000057 ++:10E9C000000000000800000000000000000000003F ++:10E9D0000000000000000000000000000000000037 ++:10E9E000000000000000FFFFFFFFFFFFFFFFFFFF31 ++:10E9F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 ++:10EA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:10EA1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:10EA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10EA3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:10EA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10EA5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:10EA6000FFFFFFFFFFFFFFFF000C1F380C44C080BB ++:10EA700000700A06000000C3000000000000000053 ++:10EA800000000000000000900000000000000000F6 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000001000000000055 ++:10EAC0000010010000000000000000000000000035 ++:10EAD00000000000000000000088000000000000AE ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000050000000000000000000000000000 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB300000000000000000000000000008000000CD ++:10EB400000000080100000000000000040000000F5 ++:10EB50000000000040000000000000000000000075 ++:10EB600000000000000000000000000000000000A5 ++:10EB7000000000000000000000000000FFFFFFFF99 ++:10EB8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:10EB9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10EBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10EBB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:10EBC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:10EBD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10EBE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:10EBF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00A47F ++:10EC00004EE30C44C08000480A06000000410000AA ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC40000000000000000000000000000000004084 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC80000000000000000000000000000000000084 ++:10EC9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 ++:10ECA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:10ECB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:10ECC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 ++:10ECD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:10ECE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10ECF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 ++:10ED0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10ED1000FFFF00B852AB0C44C08000280A06000078 ++:10ED200000410000000000000000000000000000A2 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED7000000000000000000400000000000000008F ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA00000000000FFFFFFFFFFFFFFFFFFFFFFFF6F ++:10EDB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 ++:10EDC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 ++:10EDD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 ++:10EDE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:10EDF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10EE0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 ++:10EE1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:10EE2000FFFFFFFFFFFF009073720C44C08000687B ++:10EE30000A06000080200000000000000000000022 ++:10EE400000000000000000000000000000000000C2 ++:10EE500000000000000000000000000000000000B2 ++:10EE600000000000000000000000000000000000A2 ++:10EE70000000000000000000000000000000000092 ++:10EE80000000000000000000000000000080000002 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000000000022 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000400000000000000040000000000081 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF600000000000000000000000000000000000A1 ++:10EF70000000000000000000000000000000000091 ++:10EF80000000000000000000000000000000000081 ++:10EF90002020000000000000000000000000000031 ++:10EFA0000000000000000000000000000000000061 ++:10EFB000000000000000000000000000FFFFFFFF55 ++:10EFC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 ++:10EFD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 ++:10EFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 ++:10EFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 ++:10F00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:10F01000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10F02000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 ++:10F03000FFFFFFFFFFFFFFFFFFFFFFFFFFFF002CB2 ++:10F04000CEF40C44C08000D80A060000A86B000073 ++:10F05000000000000000000000200000010000008F ++:10F0600000000000000000000000000000000000A0 ++:10F070000000000000000000000000000000000090 ++:10F080000000000000000000000000000000000080 ++:10F09000000000200000010000000020000000002F ++:10F0A000000000200000000000000020000001001F ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D00000000000000000000040000000000200EE ++:10F0E0000000000000000000000000000000000020 ++:10F0F0000000000000000000000000000000000010 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000040000000000200000000000000AD ++:10F12000020000000000000000000040000000009D ++:10F1300002000000000000000000000000000000CD ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000900A6 ++:10F16000000000000000000000000000000000009F ++:10F17000000000000000000000000000000000008F ++:10F18000000000000000000000000000000000007F ++:10F1900000000000000000000900000000000080E6 ++:10F1A00001000000000000810100000000000000DC ++:10F1B0000900000000000000000000000000000046 ++:10F1C000000000000000000000000000000000003F ++:10F1D000000000000000000000000000000000002F ++:10F1E0000000000004000000000011000000040006 ++:10F1F0000000110011000400800011000000000058 ++:10F2000000000000040000001100000008000800D9 ++:10F2100000000000000004000400000000000000E6 ++:10F2200000000000000000000500000002000400D3 ++:10F2300000000000050004000300000002000800B8 ++:10F240000200000002000900200004002000040069 ++:10F25000030000002000000000000000000000008B ++:10F26000000000000000010000000000000000009D ++:10F27000010000000000000001002000000000006C ++:10F28000000000000000000000000000000001007D ++:10F29000010000000000000001000000000000006C ++:10F2A000000000000000000000000000000001005D ++:10F2B000000000000000000000000000000001004D ++:10F2C000000000000000010000000100010001003A ++:10F2D00000000000000001000000000000008000AD ++:10F2E00000000000000000000000000020002000DE ++:10F2F000000080008000000000000000000000000E ++:10F300000000000080000020000000000040040019 ++:10F31000801140000000000000C00000000000005C ++:10F3200000008011800480018000000000000000C7 ++:10F33000000000000000004100010000000000018A ++:10F3400080000001000100058001000000000000B5 ++:10F3500000010000000000C080000000000000006C ++:10F36000020000000000000000000000000001009A ++:10F37000010000004000200000000000000000002C ++:10F3800000008200001020000090000000000080BB ++:10F3900005212008011000000041000000000000CD ++:10F3A0000000000020822090020840100000084168 ++:10F3B000000090000021002100C09020900000007B ++:10F3C0000220040002040204028204020000002160 ++:10F3D000000082040000000000090400000000009A ++:10F3E000000000000000000000000000000000001D ++:10F3F00000008000000000000000000000A00000ED ++:10F4000000A0004080000000801000840000000088 ++:10F41000004000001004808400900020000080C0A4 ++:10F420008084801000C0000000020008000200007C ++:10F43000001000000020000000200010000000006C ++:10F440000002000000040002000200880004000422 ++:10F4500000040000000000C000080084000200005A ++:10F46000000000000000000000000000000000009C ++:10F47000000000002000000000000000000000006C ++:10F480000000000000802000000040000000840018 ++:10F490008400008000000180100000000080000057 ++:10F4A00004000400040000000000008000800080D0 ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000800080000000023A ++:10F4D00000000080000000000000008000000080AC ++:10F4E000000000000000080000000000000088008C ++:10F4F000200010000400040005040004800500043E ++:10F500004000200104000200A10205000301830065 ++:10F5100003000004054005880401040008000300FE ++:10F5200000000500030003200500A0010000C10148 ++:10F530000320100002001000210010010000400113 ++:10F540000221080000000801000041000000000046 ++:10F550000000000000000401102041A00000050090 ++:10F56000100000000000000001000000000000008A ++:10F5700003000100010001000100008000800482FE ++:10F58000008001000104C1008300208000000040D1 ++:10F5900004000000C080008500008508C100C10093 ++:10F5A000C000000000210800008010052104C021D7 ++:10F5B000100200808400C141C000821001100021AF ++:10F5C000010485840000C005082000210800000017 ++:10F5D000C000004100210000010800800000000080 ++:10F5E000000000000000000000000000000000100B ++:10F5F00000000000040040A0208420100310400000 ++:10F600000300031020044002C00420040010400244 ++:10F610000084208420C02000000041000400040079 ++:10F6200004000410000010000800000000000300A7 ++:10F6300041004110400240C000400020020008028A ++:10F6400000004040412008841010202000000800E5 ++:10F6500020000800418820001000000800880000F9 ++:10F66000001000100000000000000000000000007A ++:10F670000000000000000100010001000100000086 ++:10F680000100000000000180018040800180000036 ++:10F690000100000001000100010000000000010065 ++:10F6A0000100010001000000000001000000004016 ++:10F6B00000000000000001800000000000000000C9 ++:10F6C00000000000010000800000000000000000B9 ++:10F6D00000000000000000000000000000800000AA ++:10F6E000000000000000000000000000000000001A ++:10F6F00000C0000000000010040000000000000036 ++:10F700000001031100900210000240A000840000DC ++:10F71000408420C002842000418441100008000081 ++:10F7200008000800080008000000800085A1000112 ++:10F730008400411005C0C0000501000082110000D6 ++:10F740000584020000010001000400C021840000C3 ++:10F7500020000000080000000004000000102185C7 ++:10F7600021010084000000000001000000000041B1 ++:10F770000000000000000000000001000000000088 ++:10F7800000000002000200000100008001000005EE ++:10F79000000001000100A1000100000000900080B5 ++:10F7A00000000100110001101100000004410820B8 ++:10F7B00082200500000000214100000200000940F5 ++:10F7C0000000002110001040C002848008001000DA ++:10F7D000C0000100000008000800009000001000B8 ++:10F7E000C0080040000000000000002000000000F1 ++:10F7F00000000080000009000000008088008000F8 ++:10F8000040400908911100090010090991110908E7 ++:10F8100002C109099110400941020909402020094B ++:10F8200000050041000200000000000000C040038D ++:10F830004120414100000003800940110002C00343 ++:10F84000052090020040051110020004100800007D ++:10F8500080000400000000031002090803040005F2 ++:10F860000011110500040400000000000900000060 ++:10F8700000000000000800000000000000C08940F7 ++:10F88000C0848840019091010001400001019191E4 ++:10F89000C1010889010191019001010101010101EA ++:10F8A0000101000100010000000040040000000010 ++:10F8B00003010001030100000001840100000000B9 ++:10F8C00041014101C00100011100010100000001DE ++:10F8D0000000C00000000000400111010000010014 ++:10F8E0000401A00000010000000000000000000072 ++:10F8F00001000000000000900000000000000088EF ++:10F90000890085888901098990018388888985858E ++:10F91000080003888901858505000188000111011F ++:10F9200000000004104110000002A082000201004B ++:10F93000000000400108008201001000090440019D ++:10F940008390000000C001010108910188840991A1 ++:10F9500083C00800000002820201010001830082CE ++:10F9600001000100010801830100000000000110F6 ++:10F970000100100000000000000011000000000065 ++:10F98000000008008800901003910002418010825E ++:10F99000838900080880A102838910004180000249 ++:10F9A00083090000008080050000008000800008BE ++:10F9B0000300000040804080000003008040890078 ++:10F9C00000118300000402004020030005039000A2 ++:10F9D00011C08280C00010400980104002000288DF ++:10F9E0004080030811004000118240000000000028 ++:10F9F00005000900000000000000090000000000F0 ++:10FA00000000410000088082090800C002020010C6 ++:10FA10000921400302080011090940030390001165 ++:10FA20000589C083414000404000050000000200FD ++:10FA300040808080008020021010004010030009E8 ++:10FA40000080008011840220004110C10083091051 ++:10FA50000088000989040000000000808000830401 ++:10FA60004004400200034010000808088908001004 ++:10FA700000110810802000000000000000000000BD ++:10FA80000000000001000089C09109084089018937 ++:10FA900000000189C1410103C0A101C101030109A5 ++:10FAA00000090185A189011000010000100000A0DB ++:10FAB000000001A088820080010000000001020116 ++:10FAC0000010000800A00988008300080010A0832F ++:10FAD0000000001100008211C00200C000848204F6 ++:10FAE00009C100A100C1A0C1010300C0001182C171 ++:10FAF0000000000000008201000000000000000083 ++:10FB0000000000080000000083898589890089C001 ++:10FB10001102898382008888858989898900890200 ++:10FB2000018801830188010101C001A001000100D9 ++:10FB300001880103030000000080010000010101B1 ++:10FB4000010009880940880088900908880082011E ++:10FB50008800914008A04001888800A000000000B3 ++:10FB600000C00182010001910000010400040100B5 ++:10FB700000000000000000910000000000000000F4 ++:10FB8000000000000080000000008988051189083D ++:10FB9000C0008391829110001000839084110900AD ++:10FBA0002000038004111080214109802080020080 ++:10FBB00040000380408202080800008003000940E2 ++:10FBC000202120000388048011080900830000021E ++:10FBD0000221020003801109094000000000000812 ++:10FBE000000800000380040002034011030002101B ++:10FBF00002040800000000090040000000000000AE ++:10FC000000000000000000000000000000000013E1 ++:10FC1000C2000000124100066000420000420013D2 ++:10FC200060000000064100066000210041840006DB ++:10FC30006000000012000006C20082000000820086 ++:10FC400000060000000012410013600000000000E8 ++:10FC500000130000000081000006C2000A4281413A ++:10FC60000006C22000420000001360001242210082 ++:10FC70000013C200004241840013C2000042000091 ++:10FC80000000000000000000000000000000FFFF76 ++:10FC9000FFFF3C7C3C3E5C3C2424CC3C5666FD0291 ++:10FCA0006600FC036566DF206600FC036566F7FFFF ++:10FCB0000800FDFDFDFDBDBDBC3D000000000000D5 ++:10FCC0000C30000005A00000FC0C6F6F00003C3CF5 ++:10FCD000444400004488000000000090FFFF04003E ++:10FCE0000000000000000000000000000000000014 ++:10FCF0003C99C30FFFCFF0C0000000000C000C00C7 ++:10FD000000000000000000000000000000000000F3 ++:10FD1000FB0004003C3E3C3E3C3C24243C3C6666EC ++:10FD2000FF006600FF006666FF006600FF00666673 ++:10FD3000FFFF0000FDFDFDFD3C3C3C3C00000000E1 ++:10FD4000000003C0000005A00000FC0C6060000083 ++:10FD50003C3C88880000448800000060009004005B ++:10FD6000040000000000000000000000000000008F ++:10FD70000000C399C30FFFCFF0C0000000000000D7 ++:10FD8000240000000000000000000000000000004F ++:10FD90000000000000000000000000000000000063 ++:10FDA0000000000000000000000000000000000053 ++:10FDB0000000000000000000000000000000000043 ++:10FDC0000000000000000000000000000000000033 ++:10FDD0000000000000000000000000000000000023 ++:10FDE000000000000000000000000000C21002003F ++:10FDF00000218461000000000000000000000000FD ++:10FE000000000000000000000000000000000000F2 ++:10FE100000000000C0C0C0C0F0F0F0F000FF04FB24 ++:10FE200096660FF0F0F0D4F066690FF020DF00FF67 ++:10FE3000A6A6333300FF04FB00000000FFFF000014 ++:10FE4000000066660000000090600000505096962A ++:10FE5000303F0000F0F000000C300000906024F40F ++:10FE600042F23CFF1CFF0000000000000000000008 ++:10FE7000000000000000009600964B4B424200003C ++:10FE80000000009966FF0000000000000000000074 ++:10FE9000000000000000C0C0C0C0F8F8F4F800FF87 ++:10FEA00000FF96660FF0F0F0F0F066690FF000FFCB ++:10FEB00000FFA6A6333300FF00FF00000000FFFF95 ++:10FEC00000000000999900000000090600000A0ADD ++:10FED0009696303F00000F0F000003C00000090697 ++:10FEE00024F424F43C3C1C1C00000000000004002E ++:10FEF0000000000000000000C3960096424B424BF9 ++:10FF0000000000000000FFFF00000090090000005A ++:10FF10000000009009000000008600D10880001059 ++:10FF2000058600B401A20010058600B500A20010ED ++:10FF300005860074019204100086007401300000F0 ++:10FF4000100000F009104860000000C700E0013018 ++:10FF50005100080604750198486000C700E10030B0 ++:10FF600051000586007009B004000086006409F0A5 ++:10FF700004000886046008B200100586007009F8C5 ++:10FF800004000086026409B0040000000020001094 ++:10FF9000014000000020001001403000F0003D3C16 ++:10FFA0007C3CFF00FF00FFC3FFFFAAAEAEAA00002B ++:10FFB0000004000000000C000000000000003C3CB9 ++:10FFC00000000000F0F03C3CFF00000000000000DA ++:10FFD00055550000FFFFFFFF0030FFFF000002004B ++:10FFE00000000000FE3DC201FFFFF0F00000000035 ++:10FFF0000000000000000000FFFFFEFF0000000006 ++:020000040003F7 ++:100000003C3C3E3C0000000000000000004040007E ++:100010000002020000404000000202000000000058 ++:100020003C3C7D3CDF20FF00FFC3FFFFAEAAAEAA31 ++:1000300000000000000000000C00FFAA000000000B ++:100040003C3C00000000F0F03C3CFF0000000000E1 ++:10005000000055550000FFFFFDFF0030FEFE0000D0 ++:10006000000000C00080EA29D615FFFFF0F0000074 ++:1000700000008000000000000000000004000000FC ++:1000800000003C3C3E3E000000000000000040003C ++:1000900000000000000240000000000000023C3CA4 ++:1000A0003C3CFFFFFFFF000000000F1B0F0FA0A054 ++:1000B00000003C3F3D3E000000000000C3C30000C4 ++:1000C00000000000FF000000F0F00F0F0000000033 ++:1000D0000000000000000000000000000200FDFD24 ++:1000E0000000000000000000000000001E1E14BE02 ++:1000F00000000000FFFF7DFF000000000000000086 ++:1001000000000000000000000000000000000000EF ++:1001100000000000000000000000000000000000DF ++:100120007CBCFC3C04380000000000000F0F0F0FE7 ++:10013000A0A000003C3F3C3F000000000000C3C303 ++:10014000000000000000FF000000F0F00F0F0000B2 ++:10015000000000000000000000000000000002029B ++:10016000FDFD0000000000000000000000001E1E59 ++:1001700014BE00000000FFFF7DFF00000000000033 ++:10018000000000000000000000000000000000006F ++:100190000000000000000000080000000000000057 ++:1001A0000800000000000000210000000000000026 ++:1001B000000002000000000000000000000021001C ++:1001C000110000000000000004000000000000001A ++:1001D000000000000000000000000000000000001F ++:1001E000000084000900210000000000210021001F ++:1001F000000021001100110000002100000011008A ++:1002000021000400040004000000040084000440F5 ++:1002100011000400000000000000010000000000C8 ++:1002200000000100000000000000000000000000CD ++:1002300000000000000000000000000000000000BE ++:1002400000000000000000000000010000000000AD ++:10025000000000000000040000000000000000009A ++:10026000000000000200000000000000000000008C ++:10027000000000000000000000000000000000007E ++:10028000000000000000000000000000010040002D ++:10029000000000000000000000000000000000005E ++:1002A000000000008000040004008400040000003E ++:1002B00000000000000000000000800000000000BE ++:1002C0000400000000000000000000A0000000008A ++:1002D00000000000040000C0000002000000000058 ++:1002E0000040400008000010000940C0000000006D ++:1002F00000000300020000200000880180000001CF ++:1003000000008000800084000088000000000000E1 ++:10031000000000008000000000000000000000005D ++:100320000000000000000200010001004100010087 ++:1003300000000000000000000000000008000000B5 ++:10034000000001000000A000000000008400000088 ++:10035000001100000000011000000000011000006A ++:10036000001000800100010000C1009001000000A9 ++:10037000000000419000A10090910009211002109E ++:1003800000208200020004000900000000000000BC ++:1003900000000000000004008200000000000000D7 ++:1003A000000000000000000000000000000000004D ++:1003B0000000000000000000000000C00084802059 ++:1003C00000000000000400040000000000840000A1 ++:1003D00000000010000000000082000000000090FB ++:1003E0000010000000080040000080C100820020D2 ++:1003F000008400C0002000C00082008400A000A093 ++:10040000002080C000C000090082002000C000A1C0 ++:10041000008800010000801000000084000000003F ++:1004200000000000000000000000000000000000CC ++:10043000000000000000000000410000A0000000DB ++:1004400020800010000000C100800000000000219A ++:10045000C0000000000000000000000000000000DC ++:10046000A0100005C010908000800000040400115E ++:1004700000910405000200209011C041C00000005E ++:10048000004100101000A000A0C08420A080A000A7 ++:10049000A00200400004000520100009C041000037 ++:1004A00000000000800000000000000000000010BC ++:1004B0000000008220A000000088A08804208001A5 ++:1004C000000002209000800200028800840402A044 ++:1004D00003004188020000900004A10441040000D0 ++:1004E0000384038411A0118411000908104182853E ++:1004F000049104000541004000000982020000014F ++:1005000000900890411000A009000001210008009F ++:1005100000900420020000040400040484100082FF ++:1005200000000000000002000000000000000000C9 ++:1005300000800000000001000000000003000180B6 ++:100540000420000000802000048000802103098036 ++:100550000000000082001000000000804080008049 ++:1005600000000005001090100000000002800082D2 ++:100570000210012001050002008088000000C10077 ++:100580000020820088000010001000008840000356 ++:10059000010500000180000000800100858021002D ++:1005A000000000000000000000000000210000002A ++:1005B0000200000000C0112004002010200002846E ++:1005C0002010200020100000200040000000040047 ++:1005D0000810008240C0040041A00002090441004C ++:1005E0000090000000104188000004000500024057 ++:1005F00040400820020441C041400500092021A0DC ++:100600001120024021C011A0038800000002000850 ++:1006100000044004000000000088801004000484EE ++:100620000004208400400000900000008800A0002A ++:100630000000000000000000008001000100010334 ++:100640000120010001000100000001000000000085 ++:100650000103C01000000000012000000000008025 ++:10066000000000020000C002A00000210100900074 ++:100670000100010511400380000000808209000094 ++:100680000405A08904000000080000108800001183 ++:100690000880408089800000000082090409010070 ++:1006A0008500C0908900000000000000000000A04C ++:1006B00000000000000008C004000400000000006A ++:1006C00020842040004080C0000083A02020000043 ++:1006D000800008820000000000C0000003008004C9 ++:1006E0000202000041820000C140038480108901A1 ++:1006F00010844000108485008208020111834100AB ++:1007000000A0808408840088030208854108030053 ++:1007100000C0104000000010004041000000000434 ++:1007200040844084000084C00000000000000000FD ++:1007300000000000000000000100010001000000B6 ++:1007400000000100018000802000000008000189F5 ++:1007500000002000000010000010000084050000D0 ++:100760001080828082110000000002800003088057 ++:10077000024001210100C10002004080C0080002C7 ++:100780001003000004000009000000800010008039 ++:1007900000000000018000000080900000000000C8 ++:1007A00008800100010300000500000000000000B7 ++:1007B0000080000004000000008080800400808031 ++:1007C00000000010000940000000048400880000C0 ++:1007D0000000C0C0000580402040800588092140FD ++:1007E0000908004000400011000800C0808320205C ++:1007F0001082030589C080040211082005200840EA ++:1008000021114104410302000440204190080004EA ++:100810000009081003038440090004080000800058 ++:100820004180000011110009800209090000000048 ++:100830000000001000000000000000C008880184D3 ++:1008400010A000900001000101000000048200855A ++:100850000000000289838888088301090801890152 ++:100860008300010010000000000000000000408331 ++:100870000889001100088482840001C10140C10080 ++:100880008489A191018800019000A0010100090163 ++:100890000001000001010100840000000000009040 ++:1008A000C0400240009089010001080101010100DF ++:1008B000000000000008000000000000008808019F ++:1008C000C090880083C09100C1C100901101C00197 ++:1008D00085850000018883009000088801908201CE ++:1008E0008488C1888901000000080000010100001F ++:1008F00000000020000001A00801044090019100C8 ++:10090000089000028800838284010805109183C04A ++:100910001000C000080004008301C000090290A07C ++:1009200090000000400040880188000000A0010104 ++:1009300010000000000000000300000000000000A4 ++:100940008008C000800889901000400900008909D3 ++:1009500004048809000003A040080500008003800B ++:100960000802808085808911050011900008030825 ++:10097000000000400500030003000440000089104F ++:100980008300821100800020830802038083854158 ++:100990008300800000008000800010200500C1005E ++:1009A000A0000040000000000009020000000080DC ++:1009B000030900000000000011000000000000001A ++:1009C00040000080000000000080C01000090909FC ++:1009D0000000800800000909400002020005A04054 ++:1009E0004183000200880308089080000000020094 ++:1009F00003000000050900C10003000310110020DE ++:100A0000830341109105000811A0030805C00020D0 ++:100A10000000050304400040004008202084000539 ++:100A200000A00091000080000880008004041141B3 ++:100A300000098983000000000000000000000000A1 ++:100A400000000100000810008210008889A100A0A9 ++:100A500001A190008801A010C111010001419090F6 ++:100A600091010189008900080083C089820000008B ++:100A70000100A000000000900810000400410140A7 ++:100A800088A09008418883A09089008401C00091CB ++:100A90000041000800090000000000A0C00000089C ++:100AA00000A000408809008204A0838400020101A4 ++:100AB0000101000189890000000000000000000021 ++:100AC00000000000000090118882100089880188D1 ++:100AD00001100000008883C0C084A00008008200CC ++:100AE0008803880040408310011008001104019021 ++:100AF000018800000100000091C084008800880087 ++:100B00008301404088002000418585A008009008AE ++:100B100041A01104040010080000000000000010B3 ++:100B200082000441C00004908404A0020800020274 ++:100B300000020009000100010000000000000000A8 ++:100B400000000000000000008811C089400088807B ++:100B5000108004800000008008000000001189005F ++:100B6000800080400000000090914111834090007F ++:100B700003001000100011000000030002052041D6 ++:100B80004100831008110209000503A108008840F4 ++:100B900040000311844111418080000400000000E6 ++:100BA0000080800900C100048000800500008000F2 ++:100BB000800000800091002100090000000000007A ++:100BC0000000000000000000000000410010600074 ++:100BD000420000880006600000000041000660003E ++:100BE0000000000000136000000000000013C200BD ++:100BF000000011410006C200420000000000004257 ++:100C00000000000000840013600000000084001356 ++:100C1000600012600000001300008100004100131A ++:100C2000C200000082000013C20021000000001377 ++:100C3000C200000081810013C2000000000000001B ++:100C4000000000000000000000000000FFFFFFFFA8 ++:100C50000000000000FF00FF30CF30CF3C3C3C3CA8 ++:100C600028D728D700000000FF00C3C30F3FCFFFE5 ++:100C70003CFF3F3F2C20505F0000000000000000C0 ++:100C8000300C0000030C00FF00FF040000003C5586 ++:100C9000FF0F85758F7F00005005000006060000DD ++:100CA0000000000000040000000000555500000096 ++:100CB00000000000000000000000556530CF00007B ++:100CC00000000000000000000000000000007FFFA6 ++:100CD000FFFF0000000000FFFF0030CF30CF3C3CA2 ++:100CE000C3C328D728D7000000005FA063C300302B ++:100CF000C0F000C303030000505F000000000000CC ++:100D00000000C0030000C03055550F0F0000000068 ++:100D10003C55000F8A7A80700000A00A0000909075 ++:100D20000000000000000000000000002075752099 ++:100D3000000000000000000000000000555500FF0A ++:100D400000000000000000000000000000000000A3 ++:100D500000000000AFAF5050FF00FF00F3F30C0C99 ++:100D6000AAAA55AAC0C0FFFF55555555C6C65A5A1E ++:100D7000FB0BF808FFFF0000000000013333000008 ++:100D80000000330000000AA000003C3CAAAA7DFF3E ++:100D90000041FFFF00003C3C0000606000002814A0 ++:100DA00000000000ACA000000000FF3C003C01017E ++:100DB000ABAB0000000000000000EF10FF003C3C67 ++:100DC000AAAA0000000000000000000000000000CF ++:100DD000000000000000AFAF505000FFFF00F3F331 ++:100DE0000C0CAAAA55AA3F3F000055555556C6C639 ++:100DF0005A5AFB0BF8087D287D2800000001333388 ++:100E00000000000000330000055000003C33AAA59C ++:100E1000FFFF0082FFFE0001C3C3000009090000BC ++:100E20008241000000000C0000000000FF000000F4 ++:100E30000500AFAA0000000000000000FF00FF0056 ++:100E4000C3C39696000000000000000000000000F0 ++:100E5000000000000106009400800803C086C075F1 ++:100E600030B00803C084C055308042030080008148 ++:100E700008820010008600F008800000A5865274E9 ++:100E8000A9B04C65000000C7006104B051000584A2 ++:100E9000006508B080A0A58E00B508B8486000C7FE ++:100EA00000A1009051000086006408380000008610 ++:100EB000027109800000008600B10890008500865C ++:100EC00000F40192001000000090090000000000F2 ++:100ED000009009000000000000003CFF3C3C0000C6 ++:100EE0000000FFFBFFFBFFFFFFFF00F000F0FB082F ++:100EF000FEFE0000FFFFCFCFDFDF2F001F0000004E ++:100F00000000000000000000B1B1FFAA4FDF0F5F3A ++:100F10003A3A3F30FFFFFFFF08FFFF083DFFFDFFAC ++:100F20000004AAAE3C3D7D7C0000000000FF0000F4 ++:100F30000000000000000000FFFF90A07D3C773320 ++:100F400000000000FFFF0000000000200010014032 ++:100F50000000002000100140D020F0003CFF3C3C8D ++:100F600000000000FFFBFFFBFFFFFFFE00F000F0B2 ++:100F7000FB08020230303F3FCFCFDFDF2000100000 ++:100F800000000000000000000000B1B100555FFF4C ++:100F90001F7F3A3A3F30577FFFFF08080808C2001A ++:100FA0000200AAAE00043C3C7D7D0000000000FF72 ++:100FB00000000004000200100000FFFFA0A0550088 ++:100FC000550000000000FFFF00000040400000024C ++:100FD000020000404000000202000070AAAA0202C3 ++:100FE000010200000000656530300055C3C3333393 ++:100FF0003333B4F0FFBE1CBC1CBC0000000000007A ++:10100000000000000000000000000000005000147C ++:1010100000000000A0A0C3C33C3C3C3C20002000DA ++:10102000FF553C55000000008200A00000000000B9 ++:10103000554D5555000000000000000870505050FC ++:10104000FF00C33C00000000000000004000000062 ++:1010500000000002400000000000000200700000DC ++:10106000010100030000000065653030FFAAC3964F ++:1010700033333333B4F000141CBC1CBC000000003C ++:10108000008855DD00000000000000000000005056 ++:10109000001400000000A0A03C3CCC3C3C3C2000E4 ++:1010A000200000553C55000000000000A00000009A ++:1010B00000005555555500000000000000002000BC ++:1010C0000000AAAAAAAA0000000000000000000078 ++:1010D00000000000000000000000000021000000EF ++:1010E00000000000200000000000000000000000E0 ++:1010F00000000000000041000000000000000000AF ++:1011000004024000210020000090200000000000A8 ++:101110000000000041000000000000002100080065 ++:1011200084000800A00000008000A00088002010BB ++:1011300021000000040020001182000004001100C2 ++:101140000000040404002000080004002000044003 ++:10115000000000000000000000000000000000008F ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:101180000000090001000000000000000100000054 ++:10119000000000000000000000002000000000002F ++:1011A00000000500010005000000400010001100D3 ++:1011B00000800000000000000000000000000000AF ++:1011C0000000000000000000820000000000040099 ++:1011D000000000000000000000000000000000000F ++:1011E00000000000000000000000000000000000FF ++:1011F00000000000000000000000000000000000EF ++:10120000000000000000000000001000000080004E ++:1012100080000040000000000090000000900000EE ++:10122000004000008000020000400020000000415B ++:101230000008802100000000000000000000000005 ++:10124000000000000004000000000000000000009A ++:10125000000000000000000000000000000000008E ++:10126000000000000000000000000000000000007E ++:101270000000000000000000000000000008000066 ++:10128000000000000000000000000000000000005E ++:10129000041010000000000000000000000000002A ++:1012A0000011000000410400014100800000200006 ++:1012B00000A0008804C00000000000000000000042 ++:1012C0000000000000000000000000000000000816 ++:1012D00000000008200800000000000000000000DE ++:1012E00000000000000000000000000000000000FE ++:1012F000000011100900050000000082000000003D ++:1013000000000000000000000800000009000900C3 ++:101310000000002000000000000000000584000024 ++:101320001000020000C0000000008240849090A0E5 ++:10133000400211910410028208C041000000040024 ++:101340000000040000000000000000001000040085 ++:1013500000004100210021000000400000000000CA ++:101360000010000000050000000000000000000068 ++:1013700082030021000000000000000000000000C7 ++:1013800000000000000000104000001020050021B7 ++:1013900000008440A005004100002000C021004062 ++:1013A00000000003002100058221000021C121214D ++:1013B00011048590A0080090011082118200C003E2 ++:1013C000C0039000C00000000040000000000005C5 ++:1013D00008000000000008100000000000000000ED ++:1013E0000000000000000000000000000000008479 ++:1013F00000000000000000000000210000000000CC ++:101400000000000000040000004000001100800007 ++:10141000840009C0000000820004000000000000F9 ++:10142000000000042000000000C00400C0908841BB ++:1014300002C110001000022100080888000000828C ++:1014400000A0000000A0210000001000000000002B ++:1014500000000000040041000900410000000000FD ++:10146000000000000000000000000000000000007C ++:10147000000000000000000000000000000000006C ++:10148000A008000088000000000000000200001119 ++:10149000080002000003A00000000080000090008F ++:1014A0000000024100000003000984030041050020 ++:1014B00009C091040303C01101C00090C110C00015 ++:1014C0000004020000000000A000002182040000CF ++:1014D0000000000000102000840400000000000054 ++:1014E00000000000000000000000000000000000FC ++:1014F00002000000000000000000000000080200E0 ++:1015000000000200000000000200020002000000D3 ++:101510000000058805000000000000000000000039 ++:101520000900000000A0008400000002000000008C ++:1015300000010011804100008011040988838000AF ++:10154000030000000000004000400000000000C058 ++:10155000100000000010000040000000098205009B ++:101560000002400000000000000000000000000039 ++:1015700000000200000502098200000000210008AE ++:10158000000000000003002100008800000084002B ++:101590004004002020212000020800080003004031 ++:1015A0000000000020000020C00500050403041115 ++:1015B00020000002009004C01041400289C01108C0 ++:1015C00004210411C0008421C0029000A0218408DD ++:1015D0001010000000001000000000000400A00037 ++:1015E000901000000000000000000000000000005B ++:1015F00000000000000000000000040000000000E7 ++:1016000000000000009021400900020003000900D2 ++:1016100010400000040000001000000000002084C2 ++:1016200000100000000000000900000441000984CF ++:1016300000840000040000110001098980C100013C ++:101640002010001000000000110000040000000045 ++:1016500000080000000410100090040000000000CA ++:101660001100000000000000000000000000000069 ++:101670000000000000410000000000000400002005 ++:101680000020040000000000000000000000001026 ++:101690002005A00084000009044090000000001014 ++:1016A00000058810000000008805900388030000F2 ++:1016B0000000880800200109108410401008400232 ++:1016C000A040100384A0C000C04102000000004000 ++:1016D0000040000010041000104020008841000469 ++:1016E00020008805820000000000000000000000CB ++:1016F00000000000000000000000000000000000EA ++:1017000000000000000080000000000000008000D9 ++:1017100009000080800403000300002103418000D1 ++:101720000000800203000080000000000080000034 ++:1017300000000300008080C1830003000003034118 ++:101740008000000080020300000000000000000094 ++:101750000000000000000000000000000000000089 ++:101760000000000000000000000000000000000079 ++:101770000000000000000000000000000000000069 ++:101780000000000000000000820000000082000055 ++:10179000820000000010108401C0C182000001011D ++:1017A000828200C08283010000000000000000A0CF ++:1017B00000000000010000A082C183A0A1840001FC ++:1017C0000101828200848283010000000000000089 ++:1017D0000000000000000000000000000000000009 ++:1017E00000000000000000000000000000000000F9 ++:1017F00000000000000000000000000000000000E9 ++:1018000000000000000000000000000002000000D6 ++:1018100000000000050000018400888382830083AB ++:10182000C10082000582008200A000000000C0000C ++:10183000000000010000C1000001C001908385820A ++:101840000005C10082008582008200820000000045 ++:101850000000000000000000000000000000000088 ++:101860000000000000000000000000000000000078 ++:101870000000000000000000000000000000000068 ++:1018800000000000000000000000000000008000D8 ++:10189000000000000000040000410000028309A0D5 ++:1018A0000083C10000008480008000000000000070 ++:1018B0008000000000030000C1000003800340839B ++:1018C00002890083C10000000480008000800000C5 ++:1018D0000000000000000000000000000000000008 ++:1018E00000000000000000000000000000000000F8 ++:1018F00000000000000000000000000000000000E8 ++:1019000000000000000000000000000000000000D7 ++:1019100000000000000000000000000009C10011EC ++:10192000000083C1000000000000830000000000F0 ++:10193000000000000000000000000000008003C163 ++:10194000001100008302000000000000830000007E ++:101950000000000000000000000000000000000087 ++:101960000000000000000000000000000000000077 ++:101970000000000000000000000000000000000067 ++:101980000000000000000000000000000000000057 ++:10199000000000000000000000000000004000C146 ++:1019A0000082008283C10000000000C0838200002A ++:1019B000000000000000000000000000000000C067 ++:1019C00001C10082008283830000000000848382C2 ++:1019D0000000000000000000000000000000000007 ++:1019E00000000000000000000000000000000000F7 ++:1019F00000000000000000000000000000000000E7 ++:101A000000000000000000000000000000000000D6 ++:101A10000000000200000001000000000082A100A0 ++:101A20000000830001830183000082820000010026 ++:101A3000029000000000000000010000008201820E ++:101A40008300000083820001018300008282008203 ++:101A50000101C08300000000000000000000000041 ++:101A60000000000000000000000000000000000076 ++:101A70000000000000000000000000000000000066 ++:101A80000000000000000000000000000000000056 ++:101A9000000000000080000000020000000009803B ++:101AA00040000000021040834183000000800000DD ++:101AB000024180410000000000000003000000809F ++:101AC00004800200000002C0410302830000008085 ++:101AD000008002038083000000000000000000007E ++:101AE00000000000000000000000000000000000F6 ++:101AF00000000000000000000000000000000000E6 ++:101B000000000000000000000000000000000000D5 ++:101B100000000000000000000000000012000000B3 ++:101B20000000000012002150000660001242000078 ++:101B3000000000001242000000000000000000420F ++:101B400000000000000012428148001348001242C9 ++:101B50000000000000001242000000000000000031 ++:101B60000000000000000000000000000000000075 ++:101B70000000000000000000FFFFFFFFFFFFFFFF6D ++:101B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:101B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:101BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:101BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:101BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 ++:101BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 ++:101BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 ++:101BF000FFFFFFFFFFFFFFFFFFFF0040AA570C445E ++:101C0000C02000E80A060000605900000000000043 ++:101C100000000000000000000000000000000000C4 ++:101C20000000000000000000000000400000000074 ++:101C300000000000000000000000000000000000A4 ++:101C400000000000000000007B7500000040000064 ++:101C50000000000000000000000000000000000084 ++:101C6000000000000000000000007B710000000088 ++:101C70000000000000000000000000000000000064 ++:101C80000000000000000000000000000000000054 ++:101C90000000000000000000000000000000000044 ++:101CA0000000000000000000000000000000000034 ++:101CB000000000000000000006000000000000001E ++:101CC000300200000000000040031E780000000009 ++:101CD00000000000000000000000060000000000FE ++:101CE0000000300000000000000000031E60000043 ++:101CF00000000000000000000000000000000000E4 ++:101D000000000000000000000000000000000000D3 ++:101D10000000000000000000000000000000800043 ++:101D200000000000000000000000000000001000A3 ++:101D3000000000000000000000000000040002009D ++:101D400000000000004041000000210021000000D0 ++:101D5000040410000200000000A000002100400464 ++:101D60000482000021004000080000000000020082 ++:101D7000000000001100A0C00800200020000400A6 ++:101D800004000000040004002002200200002000E3 ++:101D90000000000000000000000000000000000043 ++:101DA00010000000000000000000000008002000FB ++:101DB0000100000000000000000000000000010021 ++:101DC0000000000000000080000000000000000093 ++:101DD00000000080010001000000000000008800F9 ++:101DE000008000008200000000000000A000000051 ++:101DF00001000000000000000900010000000000D8 ++:101E00000000000000000000000021802180000090 ++:101E100001000000000000000000000000000000C1 ++:101E20000000200000000000040000004100090044 ++:101E300000000000000000000200000000000000A0 ++:101E4000040000000000000000209000000080005E ++:101E5000840000C0000000000000000000008000BE ++:101E6000A00041008000000000000000002000846D ++:101E7000004000200000020000000000804100003F ++:101E8000801080000000040080200001000000009D ++:101E900080010002000000000000000000000000BF ++:101EA0000000000001000000000001000000000030 ++:101EB000820000000000000000000100000000009F ++:101EC000000001000000000000000080040000008D ++:101ED00004001100000000000000000000000000ED ++:101EE000400011110400400082000000002000802A ++:101EF0000010000000C100000121000090030890C4 ++:101F0000080002800200000021030280000400009B ++:101F10000009200200900000000000000000000006 ++:101F20000000000011000000090011001100000075 ++:101F300000000000200000000000200802880000CF ++:101F40000000000000840000000084002102210045 ++:101F5000101000A00204000000000011418200A146 ++:101F600000100040008400080982004000000000CA ++:101F700000900900004020020088C0A00008201145 ++:101F8000000800080000A1020021040800A00011C0 ++:101F9000000000A0804000400000000000000000A1 ++:101FA0000000000000000000000000000000000031 ++:101FB0008800000002000000000082000000A00075 ++:101FC0000000000000000000000090004000000041 ++:101FD00000000100000000800000000000840000FC ++:101FE000004000000080000500000009C0A00000C3 ++:101FF0000041000000410080000000000305008057 ++:1020000001200080008000090290002001808200F1 ++:102010008202100040000211A00000000000000039 ++:102020000000000000000000000000204000000050 ++:1020300000000000002000010090000040000400AB ++:10204000000100000000000000000000000020006F ++:102050000001800000001000204000000200820803 ++:10206000112190010000840004000820C10021001B ++:10207000840011200500050010011010030002016A ++:102080008300050000A0800000C100100490000043 ++:1020900020000900030003010000101000000000F0 ++:1020A000000000000000000000000000000001002F ++:1020B0000000000000000080882000200000C10017 ++:1020C00000000020000000000000002100000011BE ++:1020D0000000002040050000010000A10000830373 ++:1020E00003102004050490091011C000C1C1404133 ++:1020F000C003104104800000000084200011022170 ++:1021000001020221002000000200100200218900CB ++:1021100000009010C00020000402840000040000B1 ++:1021200000000000000000000000090000000000A6 ++:102130000000000009000900000009040921000056 ++:10214000400000080900804000000010112000003D ++:102150000004000000A0000004000040020800008D ++:10216000108820C0008821400084004002000084C4 ++:102170001002008840C002201090022140900440CC ++:10218000101010881000410008000004034003C034 ++:1021900000000408218804000200004003090084B4 ++:1021A000000000000000000000000000000000002F ++:1021B0000000000000000000000004000000A0403B ++:1021C0000000000000000000020984050200000574 ++:1021D000881100048200004000210100000001007D ++:1021E00000000100010000000080000000800100EC ++:1021F00000404180000501000109900001A001108C ++:10220000010000000010000000000100000000803C ++:102210009000000001800000010001000000044067 ++:1022200000000000000000000000000000000000AE ++:10223000000000000000040000000000002000007A ++:1022400000000000A10020000000040004000000C5 ++:102250000400840000001101002000A0908405000B ++:102260004010000000098040A0048010020000A07F ++:10227000000041880988091010084110910000826F ++:102280000001091004108310004000848440841170 ++:1022900004C1040400900010041100200800038809 ++:1022A00020200400000000000000000000000000EA ++:1022B0000000000000000009000000200000008075 ++:1022C0000009000500001041000000050000880022 ++:1022D0008200000008000000884000900200050015 ++:1022E00004000510000000200405040004000000A4 ++:1022F00000000000A0009000000089830003080592 ++:102300008805002008058808100590A00011030921 ++:102310000302031021410000C000012004802111AC ++:102320000000880001000000000000000000000024 ++:102330000000000000000000000000000000030397 ++:1023400000210503034000080010081100090003E4 ++:10235000000003041109A003000421402003C1036D ++:1023600000002103110800C00005899188080008B9 ++:10237000094010052041040382008800410020002C ++:102380008383C00002C140081041000520110220D3 ++:102390000083400802C000090805400509084105FE ++:1023A0001103008900020484000000000000000006 ++:1023B000000000000000000000000000000000001D ++:1023C00089010000200000008800000001000000DA ++:1023D000880984200000000441010201010001007D ++:1023E000880184002000000000000009208583C1CE ++:1023F000002100000100C101000021008300000055 ++:10240000010089834004910200880100020000015C ++:1024100000009083119001020040000121000000A3 ++:102420000001C101000500010020000000000000C3 ++:102430000000000000000000000000000188000013 ++:10244000010082012010A08985840800100010C1BD ++:102450000900C00020A0A000210009000890200071 ++:102460008300100809008888010000008409910396 ++:1024700089C1888891000800080088C0A0000284F3 ++:10248000028903C10090210009108390020084108A ++:102490000500400540030008020282C004A09088A5 ++:1024A00003A1050089000182010301010000000071 ++:1024B000000000000000000000000000000010000C ++:1024C0000000030009028880808983850000800065 ++:1024D00080098300000089000500830010001000BF ++:1024E00080028304C0800800850003090000C089C1 ++:1024F00090A011A0119011001100410008210811B5 ++:102500008900100890890800C00020098300880510 ++:102510008900050410C080400080804180808900CF ++:1025200010004105C0001000410040910309000067 ++:10253000000000000000000000000000000000009B ++:102540000000400000001000001003A1000308007C ++:102550000000098090000411001040C140032008D1 ++:1025600000910900800303101191108883830000FB ++:10257000A000210085002180020400914090C0103D ++:102580000008000800848003408090020005C18399 ++:10259000088500C02109108803808200008008009F ++:1025A000020220A003080308101000022009910372 ++:1025B000000000000000000000000000000000001B ++:1025C00000000000000040000008000000200001A2 ++:1025D000010800100084C040008800080084000149 ++:1025E000008300C00004880900A00021018590211B ++:1025F0000000048809900282A082010000C000103F ++:10260000880100C000840084824100040388108295 ++:102610008305010800C000880941009008C08204B9 ++:102620000304008301080089A108010100010101E0 ++:102630000901000000000000000000000000000090 ++:102640000000018800000100000083098800A0014B ++:1026500002020189008401010190010000000100D3 ++:1026600000080108000100000088000000040000CC ++:1026700000890000884010408801C02082419021DC ++:10268000822120C041C18800400110408540C00225 ++:102690009001034082A040021001082185A0A10002 ++:1026A00090010004000200400001011001880111A6 ++:1026B00000000020000000000000000000000000FA ++:1026C0000000000003801100020800000382800562 ++:1026D0000502898003820004414009800321091119 ++:1026E000081103800380402005030000000000085B ++:1026F000004000880000A120A021A00203808008E3 ++:1027000000080010008003C103112003A000839182 ++:10271000110082402080A14021048408919083040C ++:102720002140881020002184114105104180038040 ++:10273000041104040200000000000000000000007A ++:102740000000000000000684000660000000110088 ++:1027500000060000060000820013C20000002100F5 ++:10276000001300000000810000060000000021426C ++:1027700000136000000000000A500013C200008136 ++:1027800000000013C20000000042000660008282C8 ++:10279000000000130000414121810013600000008F ++:1027A000000000060000000000810013C20000507D ++:1027B00082000013C20000000000000000000000C2 ++:1027C0000000000000000000000F000000000000FA ++:1027D000444400000609000009090303000000004A ++:1027E000CC000000CC0000000660000F0505E2E20E ++:1027F0000000000000A60FCC0000FFFFFFFF00005C ++:1028000000000000000000000000DD4442429F9FE5 ++:10281000BD241482E3400609F0F600000001C7045D ++:1028200004043C3C0F0F000000002C2CC30300D01C ++:1028300000DB3F306666FF006666000000000000B7 ++:1028400000000000000000000000000F0F0F00005B ++:102850000000888800006090000009090303000060 ++:10286000000000CC000000CC00000990066FA0A082 ++:10287000424200000000F0A6F0CC0000FFFFFF7F06 ++:1028800000000000000000000080000044DDDBDBF1 ++:102890000606BD241482E340609000600000000042 ++:1028A00004040404FF006666000000000000FF0F3F ++:1028B000D0D0DBDBFF003636CF0C2727FFFFFFFF32 ++:1028C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 ++:1028D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 ++:1028E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8 ++:1028F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8 ++:10290000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 ++:10291000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 ++:10292000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 ++:10293000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00C0E5 ++:1029400074560C44C0A000180A060000304D000068 ++:102950000000000000000000000000000000000077 ++:1029600000000000F0F00000003300000505DBDB94 ++:102970001300000066660000282800009060000C2C ++:1029800000334242A0A080808181FFFF00FF000051 ++:10299000010000003CFF69666666F0F03CFFBCFF8A ++:1029A00000000000CFFFEFFF1D1D2222000C0C30A5 ++:1029B0000000000000420000F3F3427E99999999CB ++:1029C000FE00FFFF000040006666C0FC6666F0F097 ++:1029D00000000000000000000000000000000000F7 ++:1029E0000000000000000F0F000033000000A0A056 ++:1029F0003434ECFF000099990000414100000906C1 ++:102A00000CFF3300E2E2050580800000FEFF01FEBE ++:102A10000000C1000000C3006966A56633F03CFFFA ++:102A20007CFF00000000000020000C0C11113C3F56 ++:102A300003C0800000000000F0F03030427E000053 ++:102A400000000000000000000000E4E400FF24E7B4 ++:102A5000C0FC0000000000000000000000000000BA ++:102A60000000108E006401B04C6000C700A001A0FF ++:102A70005100108E026400B0486000C700610190F0 ++:102A8000510006C700600190550000860AF501B9A3 ++:102A900000A50000A18650F5A9B00005008600E160 ++:102AA000009800850586006408B9000006C700E1AB ++:102AB00000B05100018600750190048505860A6109 ++:102AC00000B000800086026508B00000088604702F ++:102AD00009B200100000000000000000000000002B ++:102AE000000000000000000000000000FF00FF00E8 ++:102AF000FFBEFFBE0000000008A85DFD0000000052 ++:102B000000800080000000000F3F0515000000005D ++:102B10000000000000000000000055FF2D2DFC0CFF ++:102B2000FC0C05AF05AF82820000FEFFFFFFFF0037 ++:102B30003C000F0F170F4141FDFF30003C00F550E6 ++:102B4000505000000000000000000000008A00005B ++:102B50000000000000000000000000000000000075 ++:102B60000000000000000000000000000000DF2066 ++:102B7000FF00FFBEFFBE0000000008A85DFD0000D2 ++:102B8000000000000000000000000F3F0F1F0000C9 ++:102B900000008000000000000000000100AA2D2DB0 ++:102BA000FC0C03F305AF05AF8292001034FF30FF39 ++:102BB000FC00FC000F0F0F0F4141FFFF00AA00AA0D ++:102BC000F5F5F5500008000000000000008A008ABA ++:102BD00000000000000000000000000000000000F5 ++:102BE00000000000000000000000000000000000E5 ++:102BF000000000003C393C3C00000000A353AC5CEA ++:102C0000FF00FF3C555555550000000000A0202056 ++:102C1000000000007FFF7FFF000000434343953F1B ++:102C200055FF000000008A828A820000000020D048 ++:102C30000000040CC341A5A50F0F00000000000018 ++:102C400001007878FF550000820000000000515D0F ++:102C50005555C33CC33CD7D72828000000000000CE ++:102C60000000000000000000000000000000000064 ++:102C70000000000000003C3C3C3C00000000AC5C5C ++:102C8000A353FF00FF3C155555550000000000A060 ++:102C90002020000000007FFF7FFF0000C100C1C1B5 ++:102CA00095C05500000000000A0000000000000070 ++:102CB000F0F00000143C0301AA5500FF00000000E2 ++:102CC000000000007878AA00008282000000000066 ++:102CD00055555555C33CC33CD7D7282800000000A4 ++:102CE00000000000000000000000000000080500D7 ++:102CF00040004000000000000300040000008000CD ++:102D0000800000000000000000000000000004003F ++:102D10000400040000000000000041040000000066 ++:102D20000000000041000000000020002000C00062 ++:102D300004000400210000000290000000000000D8 ++:102D400000010000044120000400110020002000C8 ++:102D50002000C000A0100800000090000800000043 ++:102D600000000000000000000000000000000080E3 ++:102D70000000000000000000000000000100000052 ++:102D80002000200000000000000000000000000003 ++:102D900000000000000000000000000000800000B3 ++:102DA0000000000000000000000000000000000023 ++:102DB00041000000000000000000010000000000D1 ++:102DC0000000002000009084000501008400000342 ++:102DD0000121010021000500000090001100010008 ++:102DE00000000000000000000000000000000000E3 ++:102DF0000000800000000000000000000000000053 ++:102E00000000000010008000000000001000000022 ++:102E100000000000000100000000000000000000B1 ++:102E200000C0000000000000200000008000000042 ++:102E30008000000000000090000000000000000082 ++:102E40000000000000010020000000000001000060 ++:102E5000000000000000000000000001000000026F ++:102E60000000000000000000000000000000000062 ++:102E70000000000010000000000000000000000042 ++:102E80000000000000000100100000000000010030 ++:102E90000000000000000020000000000002000010 ++:102EA0008400000000000000002001200000040059 ++:102EB00000000400000000000000001100000000FD ++:102EC00000000020900000040080001000000008B6 ++:102ED0000000000000008200000000000008000068 ++:102EE0000080002100000000000000000000000041 ++:102EF00000000000000020000000890000008000A9 ++:102F00008001000002000000031080100004200473 ++:102F10002004A084000005002004000440000001FB ++:102F200000009010000080A000400008A00800C031 ++:102F300011000000000800A00084008200A0001022 ++:102F400000820000000000000020002080010084BA ++:102F5000000000020041000000820000000000109C ++:102F60000001000000100000000000000000000050 ++:102F700000000000000000000100900002000000BE ++:102F80000800042088000241000082000405008936 ++:102F900001808380050308040005850000100111ED ++:102FA0000002000010100000404100030011031156 ++:102FB00000009008C00000000009841100210002F8 ++:102FC00000050041400084110000088500832004B2 ++:102FD0008400C000C0800090002100000008A01103 ++:102FE0000000C0028200002100000000000000007C ++:102FF00000000000000000000000001000820040FF ++:103000000810210021000000809000400000802175 ++:10301000C100800880008020000000408005090376 ++:103020000000000103000001000002840090800005 ++:10303000200000C000000408004002044000080016 ++:1030400002200900020003009082058808418200E6 ++:10305000840041C1C1210482C101009010001040D0 ++:1030600041002000200020000200000000000000BD ++:1030700000000000000000000000000000800000D0 ++:1030800000800180000000000009100000800000A6 ++:10309000048420002080200020000000008004A084 ++:1030A00000A000000020100000040000000000004C ++:1030B0000200011000410000020300000080010036 ++:1030C000002088800000002000000400000004842C ++:1030D00004002100000804A00100101010000000EE ++:1030E0000000000085001100010000400000000009 ++:1030F0000000000000000000000000000000800050 ++:10310000000000008400080100012100000082008E ++:10311000020404202005210100898905008800019E ++:103120000004100400C000C00000100200008082F3 ++:103130000010820104C0000000080009200508C03A ++:103140000000028210830000000240000084801012 ++:1031500002C0054085200240050804001000001050 ++:103160000810054010A000C00040000000C0000092 ++:103170000000000000000000000002210000000923 ++:10318000082090400009080001100020880300007A ++:10319000100404A08584C004C004C0040284082173 ++:1031A0000220000804000008000002218500000041 ++:1031B0000200000009028509000900100008A18230 ++:1031C00003208800012000400000040200050410D4 ++:1031D00008080900008002899180008003008400B3 ++:1031E0001085C0001090A000000000804041002128 ++:1031F00000000000000000000000000000000000CF ++:1032000000008000001000000001001000200400F9 ++:1032100000C000000200008203C041A08200002024 ++:103220000000009080011102009000000408850158 ++:103230000000090011000011C1840082020080A07A ++:1032400000C000A002000084028202C0000004C08E ++:103250000420200441110082209100001000104041 ++:1032600000001000410003001110028400A00300C0 ++:1032700020820000000000000000000000000000AC ++:10328000000000004000000000000010000000806E ++:10329000010000000000000000000000000003002A ++:1032A00000830000000002040000C00000000000D5 ++:1032B00004200000000000008288020000000000DE ++:1032C00010000000000000000000000000000000EE ++:1032D00082000180000000040000014000000100A5 ++:1032E000000000000000C00000000000000000001E ++:1032F00000000100000000000000000000000000CD ++:10330000000000000004901091030020400385009D ++:10331000890409040508000000401008890580049C ++:10332000211104080340000900110840A000118089 ++:103330008400050000C0C0800000C08010000311A0 ++:103340000004804011000000800011001000000304 ++:103350008003031041058311408941080000C0C16A ++:1033600080820804044040108041050404040300E6 ++:10337000020000004100000000000000000000000A ++:1033800000000000000000019001A000000000010A ++:103390009100C0000000880000000000000008014B ++:1033A000400001010000C0010000000001010240D6 ++:1033B000000483200000000004820800021001883D ++:1033C000898920890889000400001000000001009C ++:1033D0000001C0000101000008080903910000205D ++:1033E0002102C003011100040100C0000000000020 ++:1033F00001000000020000000000000000000000CA ++:1034000000000000000000000000000100000101B9 ++:1034100001008804890083009100820389090091DA ++:1034200000000004C00101010400840009C0C004C0 ++:10343000100008000500010800000040008440A0C2 ++:103440000000400040118201900120000400A00013 ++:10345000830182002108100221910200C189081114 ++:1034600083050200108401909089000209881000F1 ++:1034700082000100010900000108000000000000B6 ++:10348000000000000000000000000000090900002A ++:10349000030510000000A1008311104010840508EE ++:1034A0000303000000A1000209100810200088009A ++:1034B0004000A02111008200410000000000000037 ++:1034C00000000010800000880002002082008800B8 ++:1034D000C100830841204000C10503100205848417 ++:1034E0000885850585008800059009110280200067 ++:1034F00082419004204020404109108200000000D9 ++:10350000000000000000000000000000118000002A ++:1035100021804080030900C000009083098400914D ++:1035200040050008901000852088880804081111C3 ++:1035300000108440008980042188809000000008E9 ++:1035400000020510002011900004C1A000888080B6 ++:10355000408800880083008300041083A103024098 ++:10356000852121034105090980C080890540028920 ++:10357000000808C0111000410005200400200000D0 ++:103580000000000000000000000000000000000239 ++:10359000001000080082008800C00010888300101E ++:1035A000000801011001040400C1018489410001E7 ++:1035B0000001000182000010888282858489000059 ++:1035C00000400883099102200011A0832084008913 ++:1035D0004010010800C102050010008200848889A3 ++:1035E00000A110880888210200C004090402108983 ++:1035F0000104000501080020020000000100000194 ++:1036000000000000000000000000000000000000BA ++:103610000000000000010000019100010100911074 ++:10362000010000001001899001000120000000202D ++:10363000A0400400100104048489880020000020B8 ++:103640000000000000000000010884C18840400024 ++:1036500001820000002000000002910041000801EA ++:10366000022085100205080108C0834188008501F9 ++:10367000088401C001850001019083000000000062 ++:1036800088000000000000000000000000000000B2 ++:1036900000000000000040100000039110042140D1 ++:1036A0004080100308008021918003000800000082 ++:1036B0000400000900408002000080088020801182 ++:1036C00000000000050005000000090080208800BF ++:1036D0008800028000030080000800800309A00029 ++:1036E00040408000C09104038502048083838810D9 ++:1036F0008221408003000802114040008300110332 ++:103700000005200000000000000000000000000094 ++:1037100000000000008400426000000082000006FB ++:1037200000000000004200066000004282600006C7 ++:10373000600000000A504006C200004200840013EE ++:10374000C2000084000041000013600000000084FB ++:103750000013C2004250000000066000000012008A ++:1037600000130000008400840013C20082000000E7 ++:1037700000130000820012000013C20000000000CD ++:103780000013600041000000000000000000000085 ++:10379000000000000000F0F0F0F000000000000069 ++:1037A000300C00004444557D7DFF272700FF41BEBB ++:1037B00055EB5555AAAA00000000C3C0FFC0000089 ++:1037C0000000002800280000FFFFFFFF00C0A0400D ++:1037D0005555555590000000000000000000FF0FF7 ++:1037E000AF0A00A50030300CFFBEFFFE0F0F001423 ++:1037F000AAFF1E1E57FF55FF0F0F0000000000001C ++:10380000D700FF000010EFFF0000000000000000E4 ++:103810000000000000000000F0F0F0F000000000E8 ++:103820000000C0030000888800141455727200FF65 ++:10383000AA5514EB330F330F00000000D7C0FFC0B0 ++:10384000000000000028C0E800003CFFFFFF7010EF ++:1038500000C0287828780040101000000000000008 ++:10386000000F0A0AA5003CFCC003000000400F0F37 ++:10387000001400551E1E55FF55FF0F55003C00005B ++:103880000800D700D7000000FFFF00000000000084 ++:1038900000000000000000000000F3F3A200F0F0C0 ++:1038A00000002424000069000000FFFF3030FFFF0B ++:1038B0003F3082A0D7F50000FFFF05FA07F8FFFFB1 ++:1038C000FFFF0000000000AC00000000000000004E ++:1038D00000000000FF00FF000000000000000000EA ++:1038E0003300C0FF2481D15033000C0CFF00FF00D7 ++:1038F0005555054500010001FFCCFF4451A21020A1 ++:10390000D5758020000000000000000000000000CD ++:10391000000000000000000000000000FFFFA20007 ++:103920000F0F0000818100000069000030300000AE ++:1039300000003F30FF5FAA0A0000FFFF55BA7798EA ++:10394000FFFFEFFF0000000000A0000000000000EB ++:10395000000000000000FFF000F000000000000088 ++:103960000000003300C02481D15000333F0CFA0026 ++:10397000FF005555050500000005FF88FF00000009 ++:10398000000055550000000000004C5FC4F5000029 ++:103990000000000000000000000000000000009691 ++:1039A00000E400304860004700E00100510000964C ++:1039B0005265A090A005A5865074A19004000086D1 ++:1039C000026409F02480008600A5089800800000A9 ++:1039D000018600E109B8000500860CB508980005CD ++:1039E000A086006000B5496000C7006101905100E9 ++:1039F000008670E508B080000586002000A0000069 ++:103A00000886007109900000A58250E1A8B00085E9 ++:103A100000000000000000000000000000000000A6 ++:103A200000000000002855FFC3C3C3C3C3FF17171E ++:103A30000C0C0C0C30303030000000000A02FA028E ++:103A4000C3C35AFF00000000FA0AFA0A10D01FDFB1 ++:103A5000000000000000A0004000FF0FF00030F068 ++:103A60003FFF0000000000EB00EBF0F078F05000AA ++:103A70005500A0002000000200000000C3003F3FEE ++:103A80003F3F0000000000000004828282820000AC ++:103A90000000000000000000000000000000000026 ++:103AA0000000000000000F0F55FFC3C3C3C3003C5C ++:103AB0001717A6A6A6A630303030000000000A0274 ++:103AC0000A02C3C3A5FF00000000FF0FF00010D0E2 ++:103AD0001FDF00000000000000400000FF0FF000AA ++:103AE00000C00FCF0000000000EA00E0F0F0F0F0AE ++:103AF00050C055C00000000000030001FFF0C300EB ++:103B0000032B03030000000000000000828200007D ++:103B100000000000000000000000000000000000A5 ++:103B20000000000000000000000000000000000095 ++:103B3000F0F005F500000000E21DE21D00000000AD ++:103B400000AA00AA00000000FA82AAC2AAAAAAAA91 ++:103B50003C3C3C3C000005050404AAFFAAFFFF0012 ++:103B6000FF003C0FFF5500000000F000CC550000A6 ++:103B7000000000410C4D3C003C14C30075F50000F2 ++:103B80000000C3C30000000000000F00AA000000F6 ++:103B90000000000000000000000000000000000025 ++:103BA0000000000000000000000000000000000015 ++:103BB00000000F0F05F5000000001DE21DE20000EF ++:103BC000000000AA00AA00000000057D55BFF0F02B ++:103BD000FF0005F505F5000000000404AAFFAAFF98 ++:103BE0003CF0AAF03C0F005500000000F0FFCCAA0A ++:103BF00000000000000000003C283C3C0000F5F5FF ++:103C00000000000443430000000000000F00AA0071 ++:103C100000000000000000000000000000000000A4 ++:103C20000000000000000000000000000000000094 ++:103C30000000000000000000000000000000000084 ++:103C400000000000200000000082000000000000D2 ++:103C50000000000000004100000000000000000023 ++:103C6000002020000000040000000000020000000E ++:103C7000000000000000200020A000000000020062 ++:103C80000090050002001100400808000400050033 ++:103C900021000300030000002000000000000000DD ++:103CA0000000000000000000000000000000000014 ++:103CB0000000000000000000000002000000000002 ++:103CC00000000000000000000000000000000000F4 ++:103CD00000000000000000000000000000000000E4 ++:103CE00000000000000000000000200000000000B4 ++:103CF00000000000000000000000000000000000C4 ++:103D000000000000000000000000000000000000B3 ++:103D10000000000000000040000000000000000063 ++:103D20000000000000000000000000000000000093 ++:103D30000000000000000000000000000000000083 ++:103D40000000000000000000000000000000000073 ++:103D50000000000000000000000000000000000063 ++:103D60000000000000000000000000000000000053 ++:103D70000000000000000000000000000000000043 ++:103D80000000000000000000000000000000000033 ++:103D9000000000000000000000000400000000001F ++:103DA0000000000000000000000000000000000013 ++:103DB0000000000000000000000000000000000003 ++:103DC00000000000000000000000000000000000F3 ++:103DD00000100000000000000000000000110000C2 ++:103DE0000000000000000000000000004000000093 ++:103DF00000000002000000000000000000000005BC ++:103E000000000000000000000000000000000000B2 ++:103E10000000000000210000200000000010000051 ++:103E20000000000000000000000000000000000092 ++:103E3000000000000000000000000400040000007A ++:103E400040001100110002000900000021000000E4 ++:103E500002002100000000000000410000004000BE ++:103E60000000000000000000110000000008000831 ++:103E70002100000000000400000011000000090003 ++:103E80001000000005820000410000000500000055 ++:103E90000088000003000000000000000000030094 ++:103EA00000A0000000000000000000000000000072 ++:103EB00000000000020002000200040000000002F6 ++:103EC0000003C00090000000042088000002204091 ++:103ED000880004008400001100210000000000059B ++:103EE00000000000000300000041880000080008F6 ++:103EF000000300080000C0050010000000080003D7 ++:103F00008408C000040300000010A021901082115A ++:103F1000842190050021004184000041000500003B ++:103F2000C0000000000000000000000000000000D1 ++:103F300000000000090200000002008200000000F2 ++:103F40000000000000000000000000002100400010 ++:103F50000000000000000000000000000000000061 ++:103F60000000000000000000400009000000000008 ++:103F700000020000052000000000410021000000B8 ++:103F800020000300024000000000000002000000CA ++:103F90000000100002A0000000000000000003006C ++:103FA00000000000410000000000000000000000D0 ++:103FB00000000000000000000000000040000000C1 ++:103FC00000000000001000000000000000000209D6 ++:103FD00008000000080002000200020002000000C9 ++:103FE0000000001140000000000088000040900028 ++:103FF0000008001100400000000000030000000065 ++:1040000000000000000000209000200000100000D0 ++:10401000000000000800044000000008000508003F ++:104020000000000400042000000000000000000068 ++:104030000000000000000000000000000000000080 ++:104040000000000000000000000000000000000070 ++:104050000000000000000000000000000000000060 ++:104060000000000000000000000000000000000050 ++:104070000000000000080000000000000000000038 ++:10408000210000000000000000000000000005000A ++:1040900000000000000008004100000003000000D4 ++:1040A00005000010000000A000000000000000005B ++:1040B000000000000000000000000200901000005E ++:1040C00000210020900004110409020000200009D2 ++:1040D0002008020000002003040302212000002128 ++:1040E000000400000005000540100000000300006F ++:1040F000000000118808840800004000040000212E ++:10410000004000090221002100100000000000030F ++:10411000C008C0091000C040840090210021820026 ++:104120000005C01000008400102100000000000005 ++:10413000000000000000000000000000000000007F ++:10414000000000000000000000000010000000005F ++:10415000000000000000400000000000000000001F ++:104160000000000000880000004000100000000077 ++:104170000900000011000000000000000000000025 ++:1041800000002100000000000902400000000004BF ++:1041900020021100000000000000020008100000D2 ++:1041A000020000100010004000000000100000009D ++:1041B000000000000000000000000000000040209F ++:1041C00040004000402100000409000004000000FD ++:1041D0000000000000009009001100000200000033 ++:1041E000880300009003C000000000008800000069 ++:1041F00000000400040300000000000800040000A8 ++:1042000000000000020004000000000000000400A4 ++:104210000000000000000010040002000020024026 ++:10422000882000008200200300000000C00004007D ++:10423000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10424000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10425000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10426000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:10427000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:10428000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E ++:10429000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:1042A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E ++:1042B000FFFF00140F6C0C44C01000000A06000041 ++:1042C0006018000000000000000000000000000076 ++:1042D00000000900000000000200000000000000D3 ++:1042E00000000000200000000000000000000000AE ++:1042F00000000001000100010400000000000000B7 ++:1043000000000000000100008000210000002000EB ++:1043100011012020030000000304200509002000F3 ++:10432000040020000200020020001120030004828B ++:104330000400042008009100040004011100110091 ++:104340000400040100000000000000000000000064 ++:10435000000000000000000000000000000000005D ++:1043600000000000820000000000000000000000CB ++:104370000000000000040004000201000000000032 ++:104380000000001000000008000002000000000013 ++:104390000100002001800000400000800184000036 ++:1043A0000000010000000000C000010000800000CB ++:1043B000000000000180010010000000004000002B ++:1043C00000000000020400000000000000000000E7 ++:1043D000000000000000000000002001800000003C ++:1043E00000000000000000000000000000000000CD ++:1043F00000000000000000000000000000010000BC ++:1044000000000000000000C00000000000000000EC ++:10441000000000000000000000000000000000009C ++:10442000000000000020000100004100000000002A ++:1044300000000000000000000000000000000085F7 ++:1044400000000000000080000000000000000000EC ++:1044500000000000000000000000C0000104200077 ++:10446000000000000000000000000000000000004C ++:10447000000000000000000000000000000000201C ++:10448000000000000000000000000000000000002C ++:1044900000000000000000410000000000000020BB ++:1044A00090000000020000800220000000000000D8 ++:1044B00002000000000000000000000000000000FA ++:1044C00000040000000000002000000000000000C8 ++:1044D00000000000000009000000000003000200CE ++:1044E0000000000000002100110004012101A101D1 ++:1044F00002000400A10000000000020040000010C3 ++:104500000040000000000500000000000000000066 ++:1045100000908400000000908000800040000300B4 ++:1045200000084110000000850084410000000000E8 ++:1045300000040002000000022108008403000001C2 ++:104540000000400010820000000000200000000079 ++:10455000000000000000000000000000000000005B ++:104560000100000000000000000000418520002044 ++:1045700004200100000008000040000001000100CC ++:104580000005002000000000000000000000000006 ++:10459000000000000300000000000400040001000F ++:1045A000000000000005000000200011880000004D ++:1045B0000000008000030000008000000000900068 ++:1045C000900800000100000000000000A080000032 ++:1045D000000000000000000000000000000000904B ++:1045E000000000000000042000000000A0002040A7 ++:1045F00003A08000000000010300200088000340A9 ++:104600000000034000000000000003000000000064 ++:10461000000000000000A000000000008400040072 ++:104620000400030000009000050004014100210087 ++:104630000000C1000001900041A005000000100032 ++:10464000040000080020850810000090210041406F ++:10465000000000000000000000000000000000005A ++:10466000000090000000881001910000001105007A ++:104670000180840002210000000400008900210064 ++:104680000080000000802000000200000000000008 ++:1046900000000000000000002100000008000400ED ++:1046A000010000000000000004000800A12000003C ++:1046B00008000000400000040400A00000000811F1 ++:1046C000A0000000A0800821208084008200081142 ++:1046D00008000000000000000000000000000900C9 ++:1046E00000000900040000100000C00000000420C9 ++:1046F0000000000020002084A000410004000310FE ++:10470000040005004100210010000800040004001E ++:10471000410000000000100080080201000020009D ++:1047200004002120400020000000040000000004DC ++:104730000304852000000000000004200000200089 ++:10474000030020100000000002100000080010000C ++:104750000000000000000000000000000000000059 ++:104760000000000090000100008000000400000034 ++:10477000018000110211A1000300050000000100EA ++:1047800000000140000000000000004001000100A6 ++:104790000100000000000041000040000102000094 ++:1047A0000100010000800100010000000100000084 ++:1047B0000000000320000000000000000180000055 ++:1047C0000100A003900000000000000004000000B1 ++:1047D00000000000000000000000000000000000D9 ++:1047E00000001000000000008001000480010801AA ++:1047F0008801800184402182042000A00020200044 ++:10480000A1200088000010008300210003000000A8 ++:1048100008840000041000000900040000000000EB ++:1048200000000000008800044000000009000401AE ++:1048300005C00420099004200488050000008500BC ++:1048400011000000410008A01004030080000805CA ++:104850000000210000100000000000000000000027 ++:1048600000000000002100008800202004910404C2 ++:1048700005100920041005000000000000000000E1 ++:104880000100200000000000884002200000040019 ++:104890000000010000000100000000000000000016 ++:1048A0000000000000000000000001000000000007 ++:1048B000004000000180C000C1A00800000000000E ++:1048C00020000000000000000010000000000400B4 ++:1048D00000C0001000000000000000000000000008 ++:1048E000000000000000000000008385C08991A046 ++:1048F00009898080910000800000002020890880C4 ++:1049000000A10000090900050005008302090083D9 ++:104910000011400320400020000500C04021000499 ++:104920002040000321050211000321008500040935 ++:104930004000411000020000404000200000200024 ++:10494000200000000510000909200309000880204C ++:1049500041400008000000000000000000000000CE ++:10496000000000000000000000000000088321217A ++:10497000A111010588829184908800040410110916 ++:1049800090100008C00085010000000000400109EF ++:104990000008000001010101000000000000890082 ++:1049A00084010000000000010100000000009100EF ++:1049B0008901010001010001820001010001A00044 ++:1049C0008500010000000001A001010000000001BD ++:1049D0008200000100000000000000000000000054 ++:1049E00000000000000000000000000000000500C2 ++:1049F00084880301911021019100880083C188A05F ++:104A0000002111C084011001C001C000890204000E ++:104A1000A002089041100800A104020083C0000019 ++:104A20000000010021008500010000A0888801002D ++:104A3000010001C001010000A10100C1000482A029 ++:104A40004000C100C000C001020082C0C08908004F ++:104A500010000400A100820000000000000001001E ++:104A60000000000000000000000000000000000046 ++:104A700088090380820209A19008C1008000908902 ++:104A8000000020092180A1098040000983008303E0 ++:104A90008004098000A1838080094100410083C116 ++:104AA0000000020020000500A02011000000A0A1CD ++:104AB00009001000048010022102100311830085F8 ++:104AC00080040000080000008010210040C1208503 ++:104AD0002005880089001000890202000200000001 ++:104AE00020000000000000000000000000000000A6 ++:104AF0000000058580918089C0C0008080004080D2 ++:104B0000808080A0840009890021800000820985BE ++:104B10008085090000008000030020C100C1400919 ++:104B20000083000020400040004003C020090040F6 ++:104B30000021C04100100091004105032000000049 ++:104B400008800400000000001180000041200000E7 ++:104B500000044105080000800000418000000000C2 ++:104B60000000000000000000000000000000000045 ++:104B7000000000000103C0C0848589050020880072 ++:104B800083A0888288841190C109A040880000C158 ++:104B90000184208201000400A00011900108000897 ++:104BA000010200830000002100850041C1020100D4 ++:104BB000000000008300000100110089C189018804 ++:104BC000008400A040A000C000A0008400A000035A ++:104BD00000C00008010200A0000200200004000044 ++:104BE00000000000200000000000000000000000A5 ++:104BF00000000000000003848483A001C020909185 ++:104C000088900200888801C000200000008883A1ED ++:104C100000A0840002828588118208001008030029 ++:104C20000282C00005C000000120000001000190C8 ++:104C300000000140000000000000009100000000A2 ++:104C40008991C088C10090880000000000000088A1 ++:104C500000000020000001A0000000000000004053 ++:104C6000000000A0000100000000000000000000A3 ++:104C700000000000000000008385098991022000E7 ++:104C80008091800080008080092100800000210048 ++:104C90008902050585110080838084C120001100F0 ++:104CA0000309040509042080000008800002101098 ++:104CB00010802100409140030300210005104011A5 ++:104CC00020002083918020118280000000000000DD ++:104CD0000080030204A10921400000030009001024 ++:104CE000000000000005004100000000000000007E ++:104CF000000000000000000000000000004248002A ++:104D0000110021840006600000001182000660008E ++:104D10000000008100066000006012000006C20072 ++:104D20004150000000060000000000000A000006DC ++:104D30006000008282000013C2000088005000065C ++:104D40006000000021000006C20081008200000611 ++:104D50006000000082410006C200000082000013D3 ++:104D600060000A0000410006602000000000000012 ++:104D700000000000000000000000000042020606E3 ++:104D8000093D09090000000000000000FFFF0000CD ++:104D90003CC3FF000FFFF0000F0FF00F0909FFFFEA ++:104DA000000000000C03000005A00000000000004F ++:104DB0003030FFFFFF7FFF991E1E097E6F7EFFFFD1 ++:104DC000F6F63C00CFDFFFFF3CFF000000000000D4 ++:104DD0000000000000003C3C3838003C66660000E3 ++:104DE00000000000000000000000000000000000C3 ++:104DF00000000000000000000000000000000000B3 ++:104E00000606090909090000000000000000C3C3EC ++:104E10003C3C3CC3FF000FFFF0000F0FF00F0018E9 ++:104E20007E7E0000000030C0000005A000000000F1 ++:104E300000003030FFFFFF7F66001E1E09186F184C ++:104E400042DB42D200000F1F999930F000000000B1 ++:104E500000000000000000003C3C383E0000666698 ++:104E60000000000000000000000000000000000042 ++:104E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 ++:104E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 ++:104E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 ++:104EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 ++:104EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:104EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:104ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:104EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:104EF000FFFF00C84CFA0C44C01000180A0600005E ++:104F000090650000000000000000000000000000AC ++:104F100000002000FFFF6666000D00000000F0F0BA ++:104F200033333CC300FF00FF0FF0C03FC03FFFFF23 ++:104F300066001800909000006969000000330000CE ++:104F4000009600000000810000000000F066FF668F ++:104F5000009966FF42C342C304040000FFFFE6E677 ++:104F6000F0F0F0F000000000F0F00000003C003C29 ++:104F7000FFF7FF000000000024FCE7FC0000000039 ++:104F8000FBFBFFFF0000000000000000000000002D ++:104F9000000000000000FFFF0000000D0000000006 ++:104FA000F0F033333CC300FF00FF0FF0C03FC03FC1 ++:104FB000000099FF0018909000006969000033001C ++:104FC0000000960000000080111001000000006643 ++:104FD0000F6618187E7E42C342C304000000C3C39C ++:104FE000C0C0FCFCFCFC00000000F0F0000000FD74 ++:104FF00000FFF7F700000010000024C0E7C0000029 ++:105000000000FFFFFFFF00000000000000000000A4 ++:10501000000000000000058600B0009000000006BF ++:10502000009401000803C086C0F431B00803C082B8 ++:10503000C035301042030586007101904C60004776 ++:1050400000210000510000000186026001B0040050 ++:105050000086007109A800000086006408B2008084 ++:1050600000860C2101C0000000860061A19000159F ++:1050700000867065098000800006026109A00005B5 ++:105080000086006408B0000000000000000000007E ++:105090000000000000000000C300EB28010101F146 ++:1050A000F708FF00FF3CC33C000000008E828E8E9C ++:1050B000C6C601010F0FFF008782D282FFFF0000EA ++:1050C0000000FFFF3CC333F0000000000000008040 ++:1050D000A000000000000000000000000000AAFF87 ++:1050E000FFFFBCBCA0A040005050000000000FFF1C ++:1050F000FFFF000000000000000000000000004072 ++:10510000000000000000000000000000000000009F ++:1051100000000000000000000000C300CB080101F7 ++:105120000101FF00FF0000C3C33C00000000BEB24D ++:10513000BEBEC6C6FEFE0F0F00FFD2828782FFFFF3 ++:1051400000000001FFFE3CC333F00000000000003F ++:1051500000080082000000000000000000000000C5 ++:105160000A5F5F5FBCBCAAA0400070700000000036 ++:1051700001FFFFFF00000000000800000000000029 ++:10518000000000000000000000000000000000001F ++:105190000000000000000000000000002800F5F5FD ++:1051A000000000087F80FF00FFFE01FE07FA877AFB ++:1051B00055FF550000000000FFFFFFFFFFFAFFA0B2 ++:1051C000080A3EFF00000000AAAAF0F0000000005C ++:1051D00000005500AA0000000000FF00FF000000D2 ++:1051E000000000000000000000003C3CFFFF000049 ++:1051F0000000AAAAA8A0000000000F0F0F0F0000D7 ++:10520000000000101000000000000000000000007E ++:10521000000000000000000000000000000000008E ++:10522000F5F500000000FF000000000101FE07F896 ++:1052300057A8553C553C000000007FFFFFFFFA00D7 ++:10524000A000080A3EFF0000000069AA72F00000FA ++:10525000000000005500AA0000000000FF00FF0051 ++:10526000000000000000000000000000FFFFD7D792 ++:1052700000000000AAAAA8A0000000000D078F0FE0 ++:10528000000000000000000000000000000000001E ++:10529000000000000000020000000000000000000C ++:1052A00020002000200040000800800104010000D0 ++:1052B0000000000100000400000000000040004069 ++:1052C0000000000021000400040000C000002100D4 ++:1052D000000000000000000004000000030040A0E7 ++:1052E0004100200020000400202104000000A0054F ++:1052F00082000400210011002000030004000400CB ++:1053000004004000C00004001100110000008400EF ++:1053100091000000000000000100000000000000FB ++:105320000000090001000100000000000404010465 ++:105330000800000000040000000000000000000061 ++:105340000000000000040000000000000000000059 ++:1053500000000000000082000000000000000000CB ++:1053600000000000010001009000014000008400E6 ++:1053700002C00200010000000000830000000105DF ++:105380000000000091000500000004000000000083 ++:1053900020000400000000000000000000000000E9 ++:1053A000000000000000400000000000000040007D ++:1053B000400040000000000000000000000000006D ++:1053C00000000000000000000000000000000000DD ++:1053D0000000000000C0000000000000000000000D ++:1053E0000000000004000000000080000000000039 ++:1053F00000000000000000008000800000000000AD ++:10540000800000000000000000000000800000009C ++:10541000000000000000000000000000000000008C ++:10542000000000000000400001000000000000003B ++:105430000100010001000000000000004000000029 ++:10544000000000000000000000000000000000025A ++:10545000000000000021000000000000000000210A ++:105460000000000000000102000000000400000035 ++:105470000000000000000000000020000400000008 ++:105480000000100000410000000002000021200088 ++:10549000000000000000000000000000000000000C ++:1054A000000000000000000020002000C00020A13B ++:1054B000800404008000000020000000200009009B ++:1054C00040000000008400002100000000020020D5 ++:1054D0000000000000840000000000000000000048 ++:1054E00000840000000080A0000400000000000014 ++:1054F0000002080000000004008500000000000019 ++:1055000000001100000000A00002009000000484D0 ++:10551000000000C08000000000000000000000004B ++:105520000000000000000000000001000100210058 ++:10553000890420800500200000000100A000010077 ++:10554000000088000411C000004000001000100995 ++:10555000C091C009002000020011000000000000FE ++:105560000000020090000000040000800000200005 ++:105570000002840001000000008000049000000090 ++:105580008405C000000020000000000000001000A2 ++:10559000C103A040001004008810000000000000BB ++:1055A00000000000000000000000000000000000FB ++:1055B00000000002000000001101000100000000D6 ++:1055C00000A10200090002000000000000008008A5 ++:1055D00000000000100000C003004000000000A018 ++:1055E00021000800000041000000000000C0110080 ++:1055F000410020008200050000000500100082002C ++:10560000020020001000030005000000020020003E ++:105610002000C00040000500030000A002000000C0 ++:1056200000000000000000000000000000008800F2 ++:10563000000088009080000000400004024000004C ++:105640000000000400050000000000000000000051 ++:1056500002800000000000000000820084000000C2 ++:1056600000000000000000050000000000008400B1 ++:1056700000000000C10003008221000000000800BB ++:1056800020000000010000000000000000000400F5 ++:1056900009004111210003000800A00000001000D3 ++:1056A00000000000000000000000400000001100A9 ++:1056B000000080C00200800000110000890000008E ++:1056C00009000000210200000000040000844010D6 ++:1056D0000000000000020220002000000000000086 ++:1056E00000000020090000C004004100002041101B ++:1056F00000000040048241041090052003010004D2 ++:1057000000A1040004000482040021844000080079 ++:105710004102800088A085008040002120000420F4 ++:10572000100000000000000000000005000000095B ++:1057300000000000020000400440000400000400DB ++:1057400000000403A009908900020000010000008D ++:1057500000211003040000090191C000C0001000E6 ++:10576000840000000000000000000009000000802C ++:105770000021C00000000100002000210000000204 ++:105780000083000401000100010501210021000047 ++:10579000C0210000040004000405040000200100F2 ++:1057A00001210000000000000000000000000000D7 ++:1057B0000000008200010000000009010001030256 ++:1057C00000020010000000000000000000C02100E6 ++:1057D0000284000000000000000002410000000000 ++:1057E000000000C00000000000002100080041206F ++:1057F00000000501020011C00000021000011000AD ++:1058000000002000214000C00202009002100000B1 ++:1058100010000300050410884100008403011000FB ++:10582000088821C080000000000000000000000087 ++:1058300000000000000000020000040990200002A7 ++:10584000004000058440000000000000001000003F ++:1058500000000000400000000009840088020000F1 ++:105860000000820002000040000008000000080064 ++:1058700000800000A008004100000041080008402E ++:1058800010000000010010000041000000000000B6 ++:105890000000000000008480000084000005082053 ++:1058A0001000000300402000000000000000000085 ++:1058B0000000000000000000800000000510000053 ++:1058C000000300000000091082030900C00000006E ++:1058D00082030000C0800000000800080911008455 ++:1058E000000000000000000000C0000000000000F8 ++:1058F0000000098000000400088003090909411123 ++:105900004040000080004000000040C100090891B4 ++:105910001184004000400020004000838000C0103F ++:10592000104010884009021141840000000000006E ++:1059300000000000000000000000040082000000E1 ++:1059400000000001000020000000898900A0C09034 ++:10595000004089898888A09000840082A00000C04F ++:105960000004000000000000000000000000000033 ++:105970000000000000880088C00400080100C00189 ++:10598000890001010000040000000000A18888894E ++:1059900011A00040000100010000000102890884FC ++:1059A00009050004108940400510010800000000AE ++:1059B00000000090000000000000008803001000BC ++:1059C0008220030010018200028803859001008577 ++:1059D0000488414090008884008841850888080038 ++:1059E00002A008820000000000000000000000008B ++:1059F00000000000000088011000888808090901E3 ++:105A000011828800850488000000A0008201020045 ++:105A10008802890941A00000000000000001010087 ++:105A2000080089004100050185008800C1C0000010 ++:105A30000000000000004000000000000000C00363 ++:105A40008005008083218002000080808385801093 ++:105A50000003008003008040000000800340000538 ++:105A600000008000808000000000000000000000B6 ++:105A700000000000000000000040800080008088DE ++:105A8000200388808000890000000000000080035F ++:105A9000114040008202890500000000000000085B ++:105AA000404180009008830040400400C00089808D ++:105AB00000000000000000000000000000000000E6 ++:105AC000008000002090008300800000118000838F ++:105AD000000000800200C103000000800000C0033D ++:105AE0000400800020801000000000000000000082 ++:105AF0000000000000000000000000080004040492 ++:105B000000880000009100098404008000001180DA ++:105B10000080200900040089C1C1080000000000C5 ++:105B2000030000008010001011834089809080895C ++:105B3000408900000000000000000000000000009C ++:105B4000000020020008008400050004000000049A ++:105B50001005C09000904104898900000090828265 ++:105B600089890000848809849040000000000000BA ++:105B70000000000000000000000000000090080885 ++:105B80000010008900040040000510000002009091 ++:105B90000084002001020405C0A14088010000002B ++:105BA0000000010000C008A0000500890010A0400E ++:105BB000A0091188000000000000000000000000A3 ++:105BC0000000000002000582020000020588880033 ++:105BD00002010282018904889001908801C1840039 ++:105BE00040019088840108080200C0900000000075 ++:105BF000000000000000000000000000000008831A ++:105C0000882010000840A1090389A000C0020001FB ++:105C100000010000008811A08810A0000208020006 ++:105C2000400000000000090888114000A0A0020800 ++:105C30008805080010A0000000000000000000001F ++:105C4000000000000000802190808000008083859B ++:105C5000900080218080031000800021800003409C ++:105C60000000002180008002800080008080000011 ++:105C70000000000000000000000000000000000024 ++:105C80000082808080008000090341030404020038 ++:105C9000000300400000000009109111910209006A ++:105CA00080008000000000008311C088910000097E ++:105CB000004080208009000000000000000000007B ++:105CC00000000000000000000041001060004200E1 ++:105CD00081840006600000820000001360008200E2 ++:105CE000000000130000000000000013000000503E ++:105CF00000000000000000000000000000000000A4 ++:105D00000000418100136000420081810013C20045 ++:105D1000820000000000C2000A4841880013C2004F ++:105D20000000000000066000006081000013840095 ++:105D3000000081810013C20000000000000000008C ++:105D40000000000000000000000000FF0000000054 ++:105D500000FF000000FF0000FFFF0000FFFF000049 ++:105D600055550000FFFF00005555000000000000E1 ++:105D70000000000000000000000000000000000023 ++:105D80000000000000000000A03CAF3C00C03CFC54 ++:105D900000FF00FF0000000000000000080AFDFFF7 ++:105DA000505F303F00000000000000000055000F71 ++:105DB000000F00FF0000000000FF00FF00000000D7 ++:105DC00000000000000000000000000000FF0000D4 ++:105DD000000000FF000000FF0000000000000000C5 ++:105DE000000055550000000000005555000000005F ++:105DF00000000000000000000000000000000000A3 ++:105E000000000000000000000000503C5F3C00006B ++:105E1000FFFF05AF55FF0000000000000000080074 ++:105E2000FDF500FF00FF000000000000000000552D ++:105E3000000F000F0000000000000A5F287D000036 ++:105E40000000000000000000000000000000F0F072 ++:105E5000F0F03C3C00003C3C0000FFFF0000AAAA20 ++:105E60000000FFFF0000AAAA00000000FFFF40039F ++:105E700055FF0000000000000000000000000000CE ++:105E80000000000000000000000000000000000012 ++:105E9000FFC0BF807D7D0000000000000000AAAAB6 ++:105EA000FF00FF00FFF700343F303F3000000000EC ++:105EB000A0A03030AAFF3C00AFAFAFAFFFFC000C9A ++:105EC00000000000000000000000000000000000D2 ++:105ED000F0F0F0F03C3C00003C3C00000000000012 ++:105EE000AAAA000000000000AAAA0000FFFFFFFF0E ++:105EF000BFFCFA00000000000000000000000000ED ++:105F00000000000000000000000000000000000091 ++:105F10000000FFC0BF80FDFD808000000000000089 ++:105F2000AAAABFB01F10FFE30020FAFA0A0A000075 ++:105F30000000A0A03030AAFF3C00AFACA3A0FFFA45 ++:105F4000000A000000000000000000000000000047 ++:105F50000000A8865175A094494512DF21A441A4F0 ++:105F60006940A2C75180A084494002C701800084D3 ++:105F700041400086026100B0000000000000000007 ++:105F800000000000000000000000000000860094F7 ++:105F900009800005008600B401A0000000860060B2 ++:105FA000A8B0001500860094018000000086002142 ++:105FB00008B000050886049009820010008600944D ++:105FC0000180000000000010080000000000000038 ++:105FD000090000005FFFFFFFFFFFFFFFFF00FF0062 ++:105FE000FFC3FFFF000400040100000000040004E0 ++:105FF000000000003C553C0F0505AFAF000000005D ++:106000000000000000000000000000000000B4B428 ++:10601000FF00000DFFFD3C3C787899FF99FF0000E0 ++:10602000000000000000FF00BF010000FFFF00FFB4 ++:10603000000000000000FF00E8E80000FFFFBF8351 ++:10604000BC80088A5DDF0000000000000100000045 ++:106050000020000001005FFFFFFFDFFFFFFFDF20E8 ++:10606000FF00FFC3FFFF0000000001000000000070 ++:10607000000000000A003C0F3C5505AF05AF0000D2 ++:106080000000000000000000000000000000000010 ++:10609000FF00FF00000DFFFD3C3C7D2899009900AA ++:1060A0000000000000080000FF00BE0040007F3F2D ++:1060B00000FF000000000000FF00E8E835003500A8 ++:1060C000FF00FF000000FFFF004000000000000094 ++:1060D000004000000000020000000000FFBFFFFFC2 ++:1060E000000000000F0F0F27000300000000000059 ++:1060F000000000000000000003032B2BAAAA33CCF1 ++:10610000000000000000000000000000000000008F ++:106110000000FFF7282000FF05F50000000000FF49 ++:1061200000FF0000000000000000FFFF000000FF73 ++:1061300000FF0000000000000000FEAE5404505FAD ++:10614000F0FFFFFF000000FF505F000000000000B4 ++:106150000002000000000000000000000000FFFF3F ++:10616000FFFF000000000F0F0F0F000000000000F5 ++:106170002800000000301010000017173F3F555551 ++:1061800033CC000000000000000000000000000010 ++:1061900000000000FFF7282000FF0CFC00000000BA ++:1061A000085D8ADF00000000008200FFFFEA004077 ++:1061B000407F003F0000000000000000FEAE5404DD ++:1061C000000FA0AFE8FFE80000FF303FFFFFFFFF38 ++:1061D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:1061E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:1061F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10620000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10621000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10622000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10623000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10624000FFFFFFFFFFFFFFFFFFFFFFFFFFFF002438 ++:106250008C330C44C05000000A060000A8A90000BE ++:10626000000000008000000000000000100000009E ++:10627000000000000000000000000000000000001E ++:106280000000000000A0000000000000000000006E ++:10629000000000001100000080000000000000006D ++:1062A00000002000090040000200820020002000C1 ++:1062B0008500040000009000040004000400820037 ++:1062C000000040000040040000002000200000000A ++:1062D0000000000010002021040020002000110018 ++:1062E00000000000000002000000000000000000AC ++:1062F000000000000000000000000000000000009E ++:106300000000000300000021002100000000000048 ++:1063100000050000002000210000400000000000F7 ++:1063200000000000010000000000830004000100E4 ++:106330008300020083000000020001000100A100B0 ++:1063400004000000010090802000A00000009100E7 ++:106350002000000000000100008400009100010006 ++:106360000402000000000000000000000000000027 ++:106370000000008800C000000000000000000000D5 ++:1063800000040000000000000000000000004000C9 ++:1063900000000000000000000000000000000020DD ++:1063A000000000C000000000000000000000808825 ++:1063B00000000001000800008000020000048000CE ++:1063C000000000000000000000000001200020008C ++:1063D000000000000000000080010000000000003C ++:1063E00000408000000000000000000000000000ED ++:1063F00000000000C00000000000000000000000DD ++:1064000000000080000000200000000000000000EC ++:10641000000000000000000000000000000000007C ++:1064200000800000000000000000000000090000E3 ++:10643000200000080004008000000400010000802B ++:1064400020000000A000000000000000004001004B ++:10645000010000000400040000001008000000001B ++:10646000A000A0802000000000000000000000004C ++:106470000000000000000000000000A000040084F4 ++:106480008000000900010284020210000020004088 ++:10649000000000100010008800000040004004844C ++:1064A000000000A00088000000C0004000040410AC ++:1064B0000004000000000040000000C0000280A0B6 ++:1064C000000000200000009011100090000000402B ++:1064D00000A0000000400000000000841001201017 ++:1064E000800000900000000000000000000000009C ++:1064F000000000000000000000000000000000801C ++:1065000000001021A0C000400009910001000040DF ++:1065100004000000000082000040000000800091A4 ++:1065200000418204880200000000000088218800E9 ++:106530000100048000009040A0000005000500025A ++:106540000241000502000000C000820000000000BF ++:106550000000000000050200C04102001000A10878 ++:1065600003002005104010008441000000000000DE ++:106570000000000000000300000080000020002058 ++:1065800080000041000802880000000003004084F1 ++:106590000204000000000000000005004190028895 ++:1065A000C0000000020009210000000000010000FE ++:1065B000830020A0200000008505020105000500E1 ++:1065C00009011001000000002100C10002101000AC ++:1065D00003004100101010822100840010002000F0 ++:1065E0004090208821008000090082000000000007 ++:1065F000000000000005002182050000040000C129 ++:1066000088C10405004084800000000300002000D1 ++:106610000021010500000000000000100000000043 ++:106620000111030000218200008800410000840461 ++:10663000A00020410100010000000484A1400009E5 ++:106640000000C002C008C021000088002000031024 ++:106650000000100000000000000000002100902158 ++:106660000100010000410000204100000400000082 ++:1066700000000000090000000000090040000000C8 ++:1066800000000000020000C10040909000000240A5 ++:1066900000020084001100840000000000A000003F ++:1066A00002000200404100004000100210A0000063 ++:1066B0000020000003400240008821C00900804003 ++:1066C000008540084102820200C0089008200200B4 ++:1066D0004102080005880040000003042100030077 ++:1066E000C1000500410809000302400004901100A8 ++:1066F000000000000000000000000000400000005A ++:1067000000210003000300030040000009030040D3 ++:10671000840988008800002000000000004000007C ++:106720000005C000910001C0A0400100010001006F ++:10673000000000000011000000000000002188009F ++:106740002005A04001C000100385002100000000CA ++:10675000002100210000002090C000000000000087 ++:1067600082001009082000900040020090200202E0 ++:106770001009000000000000000000000000000000 ++:1067800000001100890400008000022000C0008485 ++:1067900000C0000000040084000421C00000008448 ++:1067A00000208000210000008084400002001021B1 ++:1067B0000000000005C021A04184001102882004CF ++:1067C0004104110500A1218480118040418400C052 ++:1067D0002084009000A00010000002080410200097 ++:1067E0001000100041A0410009081000218403009E ++:1067F00008000290000000100000000500000000EA ++:1068000000000000000020890000200901000000B5 ++:106810000021000500000000000002000000000050 ++:10682000C00010804020C005002020000100820030 ++:1068300001A0000000000000000084000040A14111 ++:10684000018000C100C00002000010100280820020 ++:1068500082000100C00084008200000000000000EF ++:10686000000000000000000000000080040900009B ++:106870000000000001000000000000000000000017 ++:106880000000000000004085401000410910088809 ++:10689000008003080891110005001000400000006E ++:1068A0000000000000001040000010000302080873 ++:1068B00080114008111100C005100020400509108A ++:1068C00009090040898000904083108288100840A8 ++:1068D00008880009840210020080000040000000C7 ++:1068E0000340000900084004091180092108021032 ++:1068F00008410009110803400000000000000000EA ++:10690000000000000000000000099041C0010141AA ++:106910000183A0028405010200008900010000003B ++:106920000000000000000000000004000000010062 ++:1069300000004000010000000000040140010000D0 ++:10694000000004000200A0080410C083A1A10302FB ++:1069500000048888000108050010000804100104E4 ++:10696000000401010001000001009001C0010001CC ++:106970000001030000010001000100000000000010 ++:106980000040000000000000000008009188410164 ++:1069900001C1020083004010840020A020000400F8 ++:1069A000C01000000000000000004000108801013D ++:1069B00041001000A011A10085000000C1008588E1 ++:1069C000C0011000410084C088048504A000092093 ++:1069D000880885918201A010890411000800C00078 ++:1069E0000800840000000000000101000100108286 ++:1069F0001000010003002184910103040000000045 ++:106A00000000000008000000000000008409108061 ++:106A100005214189800008008800900080108000D6 ++:106A200000008080000000000000000000009002D4 ++:106A300010050900400040C08811830800002000B4 ++:106A40000811080888000240030089098908C0402D ++:106A500040058840832008021000A1020941090076 ++:106A600010009100840009000000101009000500CA ++:106A7000118089080941A004C080210289410000D9 ++:106A8000000000000000000000000000000004C042 ++:106A900000088004081140C000088090089100039D ++:106AA000009000C10008000000000000800000030A ++:106AB00000050589110811840091008240030080BF ++:106AC0008202000241C08205021000020490109070 ++:106AD000A00800101008088304108002C10904886F ++:106AE00000008000000000000302000402092000F2 ++:106AF000040500C111A080A040040008200921C0A5 ++:106B00000000000000000000000000000000000085 ++:106B100000099040A00808400002C091A005214053 ++:106B200000C0000800859000000000000000820006 ++:106B300000820008011000C10008000500112011AA ++:106B40000080091000900084409101A0C001001154 ++:106B5000890882100404A10100410000C0C1401155 ++:106B6000888900900240880800400101000000016F ++:106B7000C10000A0002100850889010400A101894D ++:106B800002090000000000000000000000000000FA ++:106B9000000000089008C001404000010002000011 ++:106BA0000090109084889000080800000000000009 ++:106BB0000000010800000000000000880101010140 ++:106BC0000190008001A1010000000008859088A1CB ++:106BD000A0014040859088080010889011418908E4 ++:106BE0001000408200000000000100040190000439 ++:106BF0000000000001C00185000001008288C00380 ++:106C00001100030800000000000000000000000068 ++:106C10000000000004100889910211000020000902 ++:106C200000090000800400000000000000000000D7 ++:106C3000000000002080021002111100090841101C ++:106C4000102110800080400304090809110082050A ++:106C5000820800210900830088C004884009894017 ++:106C600090911010828000020004000800000900CA ++:106C70001002040200000200084004000800048220 ++:106C800004080209400000000000000000000000AD ++:106C900000000000000000000013C200000000001F ++:106CA0000013C20000000000000600000000000009 ++:106CB00000130000005000810000C20000500000DE ++:106CC000001300000000000000000006C2004200A7 ++:106CD00081000013C200000081000013C2000A00FE ++:106CE00081810013C200005000000000000000007D ++:106CF00000810013C2000A0000820013C2000A00D3 ++:106D000000410013C200000000000000000000006D ++:106D10000000000000000000B000B0000909000001 ++:106D200000000000000000010000000091C3EF3CE3 ++:106D30000000000000000000FFFFFF6F663066F3F8 ++:106D40007E187E18AA5A47E7000000000240FFFFA5 ++:106D50007F7E3C3CFF99FD0DF40400000000000024 ++:106D6000000036FF3600FF24DB00000000000000BA ++:106D700000000F6F0060BF83BF83FF3FFFFF7DBE3A ++:106D8000BD7E0F0F0F0FFF00FF800000000000000E ++:106D900000000000000000000000F00000000008FB ++:106DA000000800000000000000000000000081F367 ++:106DB0007E0C00000000000000003F3FFF6F66CF28 ++:106DC000660C6F6F0909A5AA424700000000400247 ++:106DD000FFFF6F663C3C6600FD0DF4040000000000 ++:106DE00000000000FFFF0000DF04DF0400000000DF ++:106DF000000000000F6F00603E023E02FFBFFFBFB9 ++:106E000041828142CF4E0C4EFF007F000000000007 ++:106E10000000000000000000000000000000000072 ++:106E20000000000000000000000000000000000062 ++:106E30000000000000000000000000000000000052 ++:106E40000000000000000000000000000000000042 ++:106E50000000000000000000000000000000C20868 ++:106E60000400001188610000000000000000000024 ++:106E70000000000000000000000000000000000012 ++:106E80000000000000000000000000000000000002 ++:106E90000000000000000000000000000000363C80 ++:106EA000FFFF34FF3CFF4040000000009000000066 ++:106EB00000000000000000000000000000007E7ED6 ++:106EC000FFFF000000FF66F066F01FBFE84D000006 ++:106ED00000000000000100893C3C00FFE7E424E4DE ++:106EE000000000000000000000FF64FD2020EFEF24 ++:106EF00000000000FFE7FFFF003C003C9918FF7E08 ++:106F000003FF03FF02C23EFE00FC03FF8081FEFF81 ++:106F10000000000000000000000000000000000071 ++:106F20000000FFFF04FF00FF000000000000000061 ++:106F30000000000000000000000000000000000051 ++:106F40007E7EFFFF900090FF3C003CFF080D17B2D3 ++:106F5000000001000000019989996666666624E4D4 ++:106F6000E7E4000000000000000000FF049D003086 ++:106F7000CFFF00000000FFE7FF0FC0FC427E0018BB ++:106F8000667E00FC03FF02C23EFE02FE02FE00011E ++:106F90007E7F0000001008000000000000000100DB ++:106FA00000000086008108800000008400F008B026 ++:106FB00000000086006000B000000086006100B0A4 ++:106FC000000000860C6408B8000000860C6000A970 ++:106FD00000A00000A086706100B00005008600B02F ++:106FE00001A0000005860AA001A900A00086009467 ++:106FF000018000000086006000B0008000860075FF ++:1070000000B0000001860074009800000086007542 ++:1070100000B000000000000000000100000000209F ++:107020000000000000800080000000000000000060 ++:10703000FFFFFFFBFFFFA3F03DFD3DFD0000000053 ++:1070400000000000000000000000005500000000EB ++:107050000000000000000000000088004400FE4026 ++:10706000FE40D77D7DD7FF00FF0060606F6FFE544C ++:10707000AE040A005F55000000001F9F3FBF0000E4 ++:1070800000000000000000000000C3C3FFFFFFFA83 ++:10709000FFFF0001000000400000000000000000B1 ++:1070A00000000000020000000000000C00000000D2 ++:1070B0000000FFFFFFFFF0A0F0A001C101C1000030 ++:1070C00000000000000000000000100000000000B0 ++:1070D00000008000000000000000000022001100FD ++:1070E000FF41BE0082282882EB41AA0090909F9F1A ++:1070F000FE54AE040A005F55000000001F1F1F1F52 ++:1071000000000000000000000000000043C37FFFFB ++:10711000FFFABEBE000100000000000000000002F7 ++:1071200000000000000000004100000000200020DE ++:10713000FFFF00000F0B0F0F0000000039FFC9FF19 ++:1071400000000000000000000000000003033F3FBB ++:107150000000000004040434000000000000F6FFFA ++:10716000F9FFACACACAC027F027FFAFA3CFA005FEC ++:1071700080DFFBFB0B0BC1FD003CFFFFFEFE0AFFA7 ++:10718000FCFF0000000000000000000000000FFFF6 ++:107190000FFF0000000055555514000000000000CE ++:1071A00000000000000000000000000000000000DF ++:1071B00000003E3E02000000000000000000390018 ++:1071C000C9000000000000000000000000000303F0 ++:1071D0003F3F0000000008080838000000000000E1 ++:1071E0009FFF6FFFACACACAC007D82FF50503C50B9 ++:1071F000005F80DFF8F80808013D003CFFEBFEEA85 ++:1072000000003F3F00000000000000000000000000 ++:107210000FFF0FFF0000000055555515020002003A ++:107220000000040000000000000004000000200036 ++:107230000000000000400000000000000400040006 ++:1072400000000000000000000000000000018000BD ++:107250008000002000000000000802000000100074 ++:1072600021008302A00004000400000409000000C3 ++:1072700004002100020008000300000000002100BB ++:107280000200110821080400800002000001200013 ++:1072900020000000000021042001020002880100FB ++:1072A00001000000010000000000000001000000DB ++:1072B00001000000000000000000000000000000CD ++:1072C00000000010000000000005000000000002A7 ++:1072D00010001000201100000000008000000000DD ++:1072E0000100000002000300010001000080C00056 ++:1072F000000001000000000000000000A0000000ED ++:107300000400020000800480A100040000000020AE ++:10731000010021002000A000828000080100000080 ++:1073200000000000000000008000000000000500D8 ++:10733000090000408400090000000001000800006E ++:107340000000800000820800004000001090000053 ++:10735000809080000000800000020000000000001B ++:1073600000C00001000000000004000000008000D8 ++:10737000800102000040841080C000000000000076 ++:1073800000000000000000000000000000000000FD ++:10739000000000000000000000410000001080001C ++:1073A0000088000000000000000002000000000053 ++:1073B00000000000008005000000000000200080A8 ++:1073C0000000000004000000041000800000010024 ++:1073D0000000400004410000041000800000001084 ++:1073E0000000000000080020001100A000000200C2 ++:1073F00020002004010000C00580102100000021B1 ++:107400000041A00000000000840000000000000017 ++:1074100000000000000000200000008800000000C4 ++:10742000200000200000000000000000800000009C ++:10743000000000000020001084A00400000280086A ++:10744000A0892041200200020000000300C000408B ++:1074500000C0002080000088008800022100400257 ++:107460001004004100008008849000012002000008 ++:1074700000010021040100840010008904100000B4 ++:1074800003400000000200C00388418480840000A3 ++:1074900000020000000000000000208820102100F1 ++:1074A00020004108A10000000000000000000200D0 ++:1074B0004000400000210000000005000100002104 ++:1074C0004082102000201000001000000008004141 ++:1074D00090000000008540050000000200004041CF ++:1074E000914101000008000010910340C002038098 ++:1074F0009000840400840404C000000082089010FE ++:1075000000119011A011A04190001000C0000220B5 ++:1075100090000000901010118400C0089102090032 ++:1075200082008302028040410000000000008000D1 ++:107530000000000004000000000000004000800087 ++:1075400005000484108480821000001000000020D8 ++:10755000000080A08001000800C0C0000988000071 ++:1075600009000000000000890000100000A0008257 ++:10757000808500000300000100840400004010101A ++:107580002110000000000000902100001000000009 ++:1075900021100000000002A10800001000000910E6 ++:1075A00000011000400020208200000000000000C8 ++:1075B0002000000000000100000088000000010021 ++:1075C000200000050105C1002000000002000000AD ++:1075D00000C1824102051010008500000500000076 ++:1075E0000000004100100000A00800001100000091 ++:1075F000000020200041840002040000014100A19D ++:1076000001A1028088038200880010C0000082006F ++:1076100020008400000300210108A00300090803E2 ++:107620000041000400000100C10021000000100022 ++:1076300000C00300004000022000208400080384F2 ++:10764000000404C000204020202020200410040258 ++:1076500020020402000040844102084040901010C3 ++:10766000000000880488400221100040000000084B ++:1076700020012020098803010800A12002200084A5 ++:1076800000401040031111004104110021101000AE ++:107690000304089000C004C0000009840082A00018 ++:1076A0001082050420A010041040410405020000CF ++:1076B000000000000010008000000102010000A096 ++:1076C00090000080401100404000C1800140100047 ++:1076D00001C0001001030000000000000100912122 ++:1076E00082050000000940410041000984090000B2 ++:1076F00000A1110805208809840884002040852104 ++:1077000000008200010090020011821100408400FC ++:107710000000A0001011C000000000000000820066 ++:107720002100C009A0A1112010800000A08900A0A4 ++:10773000000000010000001000C0200000000082D6 ++:10774000118400042002001000C10008051000C0D0 ++:1077500000100000091000848240028500019000A2 ++:10776000800004A00000202100C0041000000000E0 ++:107770000000118510844184A00508080004084019 ++:10778000809100000000000191110000008400C001 ++:10779000029000C0000000009001030010001001E2 ++:1077A00003000500201020104100211000000002FD ++:1077B00003100000000400000000000001000000B1 ++:1077C0000000000000808980000000100080004060 ++:1077D0000000201000050000100021C10104C004B9 ++:1077E000201040119010900090A0880084000800A4 ++:1077F0000221004004080100000021840080008074 ++:107800000080040400410000001008200000000077 ++:1078100000000000100010000040024010000010A6 ++:1078200003088400000083001100A0000000000095 ++:10783000084100009105804003830911890910A0C7 ++:10784000082000411085102009081041C0100008D0 ++:107850000990039000000880028000800880C10029 ++:107860008880080002A080030983400810000500FA ++:107870000000410000800011824104090009000558 ++:10788000002040201004208908C000051184000059 ++:107890000000090000000500000011000500C08084 ++:1078A0001000848020801100890010000800090366 ++:1078B00009200940101082218288001001900808D8 ++:1078C0004110C110002121830189830001894004F6 ++:1078D0008401C0080010009091C0000800C001821F ++:1078E0000810040800040310C0A000100010882035 ++:1078F00001840090000000000000050090000000DE ++:107900000001400101010000C0820184008200C02A ++:107910000000880000000000000088000000000057 ++:1079200089101084081000C0880009008800010038 ++:10793000880101000000000183004188092108211D ++:1079400000008484880010400801110888092190F3 ++:107950000800820011048301900189000900418818 ++:10796000000101000100009108001000C10810A1F1 ++:107970000101010000C0002000001000888900887B ++:1079800010010810048805A08400002100000002F6 ++:1079900000880800200009C0080000000100010064 ++:1079A00001000001C000000002C001000101000050 ++:1079B00001010900A101A1C0C100100904808521B5 ++:1079C00040090900C0000000A0009102880090401A ++:1079D0008800800803009000900800404000C0002C ++:1079E000034009404005050040410511A000020088 ++:1079F000000802101000108008000000000900209C ++:107A000000910040008020804080892009031100FF ++:107A1000008010008000200089001100020040005A ++:107A20000800400000030000000000801100200456 ++:107A300040002021020009042000892003828008E0 ++:107A40008888410040400020802000880888008409 ++:107A5000C191004010080088114108080000800012 ++:107A6000A180808000090011A008004040028091A0 ++:107A7000A085A003000400110040000800000400DD ++:107A80000000030010800203034009208010004022 ++:107A900005000040410900000000008000000009CE ++:107AA00000110082001000000011808800918010F9 ++:107AB000000440C000098011001111048008011168 ++:107AC0001088028501C00090088408400011001150 ++:107AD00088101003902100040009008305040008A9 ++:107AE0008840A084881002888802A1C10801010989 ++:107AF0008811A08488C10000840120018800000052 ++:107B000000000002011001900004008901090288B0 ++:107B10000001900082009000002000080084C0084E ++:107B200000C000C10009000200080000A08508880C ++:107B30008290000401A0021082A0000800049002BC ++:107B40008400008900000188908800C0880101102D ++:107B5000418441838300402084918440040040405C ++:107B600084001041A000C0888284C000820004000C ++:107B70008491088988001088849008019000C000D2 ++:107B80000000910940841000912000000140010193 ++:107B900001A082A01000A000080000010000000069 ++:107BA00000400004000000000000102088000800D1 ++:107BB00000080088008400010000008900C1000165 ++:107BC00000829103080808032080408420202010B0 ++:107BD00009800380410802114000808300000020DA ++:107BE00000808000801100008080808000040010F0 ++:107BF00000008020800400058080800080410040DB ++:107C000000000000038390001100880041100288EA ++:107C10000820100080008004000800000010000907 ++:107C200000080080000000040008000080008000C0 ++:107C3000000000800000000900200000008900848E ++:107C40000009008000000013C20082000000001341 ++:107C5000C200000000000013C2000000000000137A ++:107C60006000210000840013608000000000001309 ++:107C7000C200000000000013C2000000000000006D ++:107C800000000000000006000013C200828800000F ++:107C90000013C200000000000013000042000000BA ++:107CA0000013000000000000000000000000810040 ++:107CB000001300008200000000008400410000006A ++:107CC0000000840041600000F0B0404140410030BD ++:107CD00000000000010055550000E0F0EFFF00003B ++:107CE0000000000200000000000000000000000092 ++:107CF0000000555F55FF000000000F550F0F0000FA ++:107D000000000FFD0F3D0000505CFCFC0000000077 ++:107D1000330FF0333C0F3CFF00000000003C00003C ++:107D20000000000000000000000000004AFF4FFFBC ++:107D300000000000F555F5F500000000000070F0AF ++:107D400000000000AA3CAA0F000000400100010052 ++:107D50000000000000000100CCCC003010001F0F1C ++:107D60000000000000000000000000000000000013 ++:107D700000000000005F41AF000000003C553C3CAB ++:107D800000000000053F053F0000000C0C0C000047 ++:107D90000000CCF00FCC3C003CF000000000003CA8 ++:107DA00000280000000000000000000000000505A1 ++:107DB0000F0F00000000A0F0F5F50000000000002B ++:107DC00000F000000000003C000FFFFFAA00FFAA27 ++:107DD000FF000000000000000808FF0FFF007E42C7 ++:107DE000FCC0DFFFFFFFF00F0FF0000000000A0AE9 ++:107DF00000AA00000000FF3CFC30FCB8B830B2F331 ++:107E0000B2F300000000FF55FE540000FFFFFFFF2B ++:107E100000000000FCFFFCF0AAFFAA00FA507878EE ++:107E2000B2B28282000000000000000000000000EA ++:107E3000F8F8FF2F00000000000000000000000024 ++:107E4000FFFE5554F03C00C3DFFFFFFFFFFFA80813 ++:107E5000FFA8FF080C000000000000003F3F30308A ++:107E6000FCC0FCC0FFFFFFFF00FFFF0000000000A0 ++:107E70000A0A00AA00000000BE28FC300000000032 ++:107E8000B230B23000000000FE54FE540000FFFF8C ++:107E9000FEFF000000000C0F0C00F0F0F0F0FA50B4 ++:107EA0007878303000000000000050000000000032 ++:107EB0000000F8F8F82800000000000000000000B2 ++:107EC0000000FFBE5514F03C00C3FFFFFFFF00861B ++:107ED000006108900000008600F10880000008861C ++:107EE00000F008800000008600A1A08000850086C8 ++:107EF000002500900010A08650E1A09000050086AB ++:107F00000031009200800086006000B80080000010 ++:107F1000058652B0A38000050086007100B0000005 ++:107F20000086026100B000000086006000B0000022 ++:107F30000086006000B00080008600800190000094 ++:107F4000A0865070A8B80005A0865A70A8B0008519 ++:107F5000FFFFFFFF3D053D050F0F00003C7D0F4F6C ++:107F6000F700FF0000020000FF3A3A3A2C6DFFFFD5 ++:107F7000FFFF3C0000FF0FFF08002800000000008A ++:107F8000FFFFAB0005FF05FF00FF00000000000041 ++:107F90000000FB0BF808FF550F5500000000FFFF25 ++:107FA000FFFF2CBF936C000000000000000040F0B9 ++:107FB00000F000000000FFFFFFFFFF00AA004141AA ++:107FC0007D7D00000000F3F3F3F3000000000000EB ++:107FD0000100FFFFAAAA3C003E0A000000003C414D ++:107FE0000F4FFF00FF0000020000FF3A3A3A2C6DED ++:107FF0000041FFFF381001FF0DFF000028000001C5 ++:108000000001FFFFA80004FF45FF00FF0010000073 ++:1080100000000000FB0BF80800550F5500000000A1 ++:10802000FBFFF1FF083E36C9000000000000000021 ++:1080300000F000F000000000FFFD7F7DFF00FA501F ++:1080400000C33CFF00000000F1F0F1F3000000006D ++:108050000000010000400000BA92FFFF0040004114 ++:10806000AAAFFFFFD7FFD7D700002000C0C0000095 ++:10807000000055550028001805060000CFFF4414E5 ++:10808000000000000000702000001010000A000036 ++:108090000000000000000000000055553C3C0000BE ++:1080A00000000F8F0F0F5AA593360000000000004C ++:1080B0000000010000000000000000000000FF00C0 ++:1080C000FF0F0A0A5F5F00000000000000000000D0 ++:1080D0000000FFFFFFFF00000000AA82FFFF00403A ++:1080E0000000000F555FFFFFFFFF00002000C0C031 ++:1080F00000000C00C33C0028002805060000CFFF4C ++:108100000000000000000000F0A00020103000007F ++:1081100000000000000000000000000055550F0F97 ++:10812000000000000FDF0F0F5AA56CC9000000000F ++:10813000000000000000000000000000000000003F ++:10814000FF00FC0C0A0A5F5F000000000000000056 ++:10815000000000007FFFFFFF0000000000000000A3 ++:108160000800000000000000000000000000000007 ++:108170002100000400A0000010000000000000002A ++:108180000400000000000000000000C0000000002B ++:10819000000080000000000000000000000000A0BF ++:1081A00002000400800000400300100000004000B6 ++:1081B000030000002000000002000000000020403A ++:1081C000000004002000210004008802400041005B ++:1081D00000002000840020002000000000000000BB ++:1081E000000000000000000000000000000000008F ++:1081F00000000000008000000000010000000000FE ++:10820000000000000000000000000000000000006E ++:10821000000000000400000000000000000000005A ++:108220000000010000001000908088000100A00004 ++:108230000100000000000002000300000000A00098 ++:108240000080000000000000A00301002080010069 ++:108250000000000009001100010001000000000002 ++:108260000000000000000000000000000500000009 ++:10827000000000000000000005002100000000A038 ++:1082800000008000004000400000000000000020CE ++:1082900000A08000800000008082000000C000007C ++:1082A00000000000000500000011000000000000B8 ++:1082B00000000000000100A000000000000080009D ++:1082C000000000000000000000011000000020007D ++:1082D00000000000410000100000850000000000C8 ++:1082E000000000000000000000000000000000008E ++:1082F000000000000000000000000000000000007E ++:10830000000000030410008000800008002100002D ++:1083100000200000020002410000100000200000C8 ++:108320000000000000000090001100080010004153 ++:108330000041000000200008000000000000004193 ++:1083400020000000001100000000000800200010C4 ++:1083500001090008000000000009000004000020DE ++:10836000000000000000000000000000000000000D ++:108370008000040080008900002000000500040146 ++:1083800010A00000400080040240000100400010E6 ++:108390004010034004008084109000C000C000A082 ++:1083A0000000118240028082C085040811102082E2 ++:1083B00040204082410002850008001003028840EE ++:1083C000419000200302004005C000840008030122 ++:1083D00080001000411090401100024000C01100C8 ++:1083E00010400000880000000000000040400041F4 ++:1083F00000102000011020000200002000400005B5 ++:10840000000801210000050004C183210040008014 ++:1084100000008300004040024010C141001188214B ++:1084200000030000400089000410414000000010DB ++:108430004100400500008441894084800000C0055F ++:1084400002A084400000004108A182030000C08017 ++:108450008440040390210000112110200100C0007D ++:108460009000100800000000110000000000000053 ++:1084700000000000000000000000004100000000BB ++:1084800004001100A00100000200040002008900A5 ++:108490000801000141001101000002854140000077 ++:1084A00009000000000000004001000041010082BE ++:1084B00021000004211011100200C0000200000081 ++:1084C000030000000810000040A003042100000089 ++:1084D0002100090010101000090084008200000033 ++:1084E0000008081003400000000000000000000029 ++:1084F00000000000020000008800C00000C0001062 ++:1085000000000000000011080000000089030100C5 ++:10851000020001100020882100020041010810A182 ++:1085200084050011841000000009014000000010C3 ++:108530000040000000A1004100030009414101008A ++:108540000000004108410000040300000885840089 ++:108550000041C010881008050041002110050541A8 ++:1085600000108490C1001080000000000000000096 ++:108570000000000000000900A0000010200400001E ++:10858000000200000589000000008400402009046A ++:10859000800002100810000004C009400000210003 ++:1085A000414041404104098400008020002100C076 ++:1085B0008088110010102040912000900902824113 ++:1085C0000500092021C00800040000020502000087 ++:1085D0000500004008000382210091400502A1022D ++:1085E00010C0051041042088118400080408001000 ++:1085F0000410000504000010040805110011019189 ++:10860000880984C184000408842100050500004114 ++:1086100000800211050001C08800002102024041D3 ++:1086200004100480040088008800000002088240D2 ++:10863000820240210000010041800200002100412F ++:1086400003828400840082210021C1210000820075 ++:10865000000010410040A010002110090200820417 ++:1086600010809000000004112011C02100000000C3 ++:108670000000000000000000000002004000200098 ++:108680004001200004400088008402102000910175 ++:1086900004008040114009000010000000A09184F7 ++:1086A0000010100141C10000040009C0000010C00A ++:1086B000210000C082A0004090100020024108006C ++:1086C000001100A005820084400000A002A0090063 ++:1086D00080C002A082820484401000A020042110E7 ++:1086E00003000008020000C04110211040040000F7 ++:1086F0000000000000000000000000000000010376 ++:108700000110C02001210005A0200000000300008E ++:1087100004020000040000908221002100100209E0 ++:1087200004000000C120C0400208C0110000000089 ++:1087300082050021000303410000114100410002B5 ++:10874000090000408800C00900000100000000008E ++:1087500000002003C121200000000110880000005B ++:10876000840000211090001000051003C08011004B ++:1087700000000000000000000000000000000000F9 ++:1087800008800980048009800000911141090900D6 ++:108790000000000020000000098310000005000315 ++:1087A0002085118503C020801008000400400009C6 ++:1087B00000000040901140C0008808038040401035 ++:1087C00009110000800041000000000000000000CE ++:1087D0000000830000090805202040050005054031 ++:1087E00080834080000002802000108982C18900BF ++:1087F0001004000000000000000000000000000065 ++:1088000000000190052090C0018400008901010151 ++:1088100000000000200000000000058301400088E7 ++:108820000040910220400010001000C100880008A4 ++:1088300000C0000000A1848801C0009100018200F6 ++:1088400000000000000082000000000000000000A6 ++:1088500000000000200020010100010120891041DA ++:108860000089881001040088008801909082040823 ++:10887000C0C0000000000000000000000000000078 ++:1088800000000000100108000800848982008900AF ++:1088900089C08300410009212000090388A1C00488 ++:1088A000C10341888201C005094011C000000010C9 ++:1088B0000000000000000401C020A1109004A000EE ++:1088C000040002008400400004A0100083C04100A6 ++:1088D000900090049000020085004000850108018E ++:1088E000820221858511000001A00182010005009E ++:1088F000C188880811090000000000000000000085 ++:1089000000000000000000080005000080A04000FA ++:10891000C0008580A00008110940000303831108EE ++:108920000000890203000810912082854184000024 ++:1089300000800021000000000002000210009105EC ++:10894000100011002000A00009094000C0058800A7 ++:1089500002001000090010000000410000418920C1 ++:1089600000402000219083890000088005851000C8 ++:108970000240880084890983000000000000000094 ++:108980000000000000000000000800080208008845 ++:1089900011110009009189830000000021808000EE ++:1089A00009104109030409034020800000A11005BB ++:1089B00003098005000220080000100080800000EC ++:1089C0008000400900080009054000000000048004 ++:1089D00000000000000000000000034100022089A8 ++:1089E00010032008802003100541004000040821E6 ++:1089F0000003400800800089208000000000000083 ++:108A00000000000000000000000090409020008264 ++:108A100008100100000000A08983A0080084010262 ++:108A20002010000090018200020100008888088464 ++:108A300085104100040108010100000001C082020C ++:108A4000A0C020A000000091009001910020000033 ++:108A500000840090000000000000C00001900008A9 ++:108A60000011010201080482908988020005008833 ++:108A70008308024101A1041004110102000000005A ++:108A80000000000000000000000000000821C08875 ++:108A90002000C08800010001000100881111880039 ++:108AA000840141A085C0A103A000C0408410020041 ++:108AB000820140840084050005000200000083104C ++:108AC00004011000900200080001000000A083C013 ++:108AD00008848801C0A000010001000000400121BD ++:108AE0000040000001A0098440908201A08201089A ++:108AF0000109000001000185898390010410000034 ++:108B00000000000000000000000000000000000362 ++:108B100000008000800000110020004000801083D1 ++:108B2000C011A1090800834002C005108000880917 ++:108B300021040908058003800800080040000000A7 ++:108B40009080004100404100000300200008000028 ++:108B500003101008020311000040004000040080D0 ++:108B600009020585051020001091A0A10841088088 ++:108B700003004004001140000985858480030080C3 ++:108B800000000000000000000000000000000000E5 ++:108B900000000013C20021000000000810000000C7 ++:108BA00000000013C200425000000013000000004B ++:108BB0000000001300000000000040130000060049 ++:108BC000000081000013C2000A0000810000C20002 ++:108BD0000A0000000000C200426000000013000014 ++:108BE000000000810000C200420011000013C2001A ++:108BF000004821000013C200008411820013C2004B ++:108C000041600000000000000000000000000000C3 ++:108C1000000000000000FBFFFFFF00000000F3FF6A ++:108C2000C3FF00000282000000000609F0F644883D ++:108C3000B910968E170F7E2481DB00098181FF2DEC ++:108C4000002D0000FFFFC3C3000000000000000073 ++:108C5000000000004E4EFF4E00000000000000002B ++:108C600000000000FF4E004E66006600000000009D ++:108C700000020000FFFFFFFF660FE7CFFFFF0000CD ++:108C80003C003C000000000000000000000000006C ++:108C90000000000000000000FFFFFFFF00000000D8 ++:108CA000FFFFFFFF3C0080000000000060900060BC ++:108CB0004488B91096B2D4F081DB7E24000900000C ++:108CC000FF2D002D00000000C3C3000000000000C5 ++:108CD0000000064697D74E4E004E000000000000F0 ++:108CE000000000000000FF4E004E7F1976106666FF ++:108CF000260000020000003C4242660F240C99004E ++:108D000099007E427E42FFFFFFFFFFFFFFFFFFFF54 ++:108D1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 ++:108D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 ++:108D3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 ++:108D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:108D5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:108D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:108D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:108D8000FFFFFFFFFFFFFFFF0008C2470C44C0309A ++:108D900000180A06000070DF00000000000000005C ++:108DA00000000000000000000000000000000000C3 ++:108DB000FF9FFF9F3C3C1C3C000000000C0C22224B ++:108DC0004747A0A0BD18422469966699000002009A ++:108DD000DD44BB22000000000000FCFCFCFFFF00A3 ++:108DE000FFFFE4F0C3FF00F00FFF00000000FFFFF3 ++:108DF000FFFF00000000202020380EFE0EFE999993 ++:108E0000FFFFF4FFFFFFF0F00FFF00000000FFFF87 ++:108E1000FFFF24BDBD240E0FFEFF00000000000078 ++:108E20000000000000000000000000000000000042 ++:108E30000000FFFFFFFF3C3C3C3C000000002E2EEA ++:108E40001111424205053C0081189966699600009F ++:108E5000000044DD22BB000000000000F0F0F0FF45 ++:108E60009900FF996672003C3636363600000000E5 ++:108E7000FBFB38FB000000000000001802F202F2C9 ++:108E80009090F6F6040F0F0F060000F000000000AF ++:108E9000FF9F009FBD2424BD0E0CFEFC00000000BF ++:108EA000000000000000000000000000A0865081CB ++:108EB000A0A800050006006008090000A186502156 ++:108EC000A090486500C7006000B0510000860C21EA ++:108ED00000B800800086002100B00000000000867D ++:108EE0000C6109A0008500860A6408B000000886AD ++:108EF000007000B000000086006000B000800086B6 ++:108F0000007400B000000086006001B0001005860B ++:108F1000007101B90080008602B401A000000000C9 ++:108F20000000000000000000000000000000F069E8 ++:108F3000F0AAFEFFFEFF0000000055AAFF00F0F0BF ++:108F4000F8F4555F555FD7D7EEBF00000000A0A032 ++:108F5000BCBC0FFF5F5F0C3F0C3F00000000000037 ++:108F6000FCFCEB280000000000000000555FFFFF44 ++:108F70000000C240000000000000000000000000EF ++:108F8000000000008200AAAA00003C3C044500004A ++:108F90000000000000000100EA40EA408E8E82BE20 ++:108FA00000000000000000000000000000000000C1 ++:108FB000F0AAF0AAFFFFFCFF000000000000000084 ++:108FC00000002814555D55DFD7D7EFFB00000000E7 ++:108FD00050007C3C00F050500C3F0C3F0000000063 ++:108FE0000000C0C0EB280000010000000000000FDE ++:108FF000FFFF00000000000014000000000000005F ++:109000000000000000008080AAAA0000FE3C0CCFF7 ++:10901000088A0000000000000100FF00FF000C0CA7 ++:10902000003C000000000000000000000000000004 ++:109030000000FECA3E0A0F5A3C3C000000000F0B25 ++:10904000040B0000000053C35FFFBEBEFCC0101045 ++:109050000000FFFFFFFF8A80DFD500000100000055 ++:1090600000000000000000003000200000000000B0 ++:109070000FAFFF3F00000000280055FF0000000078 ++:109080002A0FAAFF000000002DFFFFFF0000FC0CCC ++:109090001F5F1F5FF0FFF3F30000000055AAF0F020 ++:1090A0008ADF005500000000000000000000000002 ++:1090B00000000000FECA3E0A0F0F3C3C000000000A ++:1090C0000004040B0000000050005C3C8282FCC0E5 ++:1090D00038102800495D4155202A757F00000000A6 ++:1090E00000000000000000003420300020000000DC ++:1090F000000000003CFF000000002D0500AA000059 ++:109100000000AA008A000000000005FFFFFF000029 ++:10911000AAAA1F1F1F5FF0F0F3F30000000055AA7A ++:1091200055AA085D00550000000000000000000086 ++:109130000000000000010000200000000401000801 ++:109140002108210300000000000020900000009092 ++:1091500000400001C001112000100220912084A0D5 ++:10916000800080204000000020002000004082405D ++:1091700011100040110040004000804010001040DD ++:10918000020020000200200000000000210020005A ++:10919000100110002100A040110000000300000099 ++:1091A00000000440840004000000000000000000F3 ++:1091B000000000000000001000000100000001405D ++:1091C0000080008000880000000000000000000017 ++:1091D00000000080882041200080008001802080E5 ++:1091E0000500040004800100000000000000008071 ++:1091F0000280000000800000000001091080C1050D ++:109200000180010000002100C000000002000000F9 ++:109210008200010801000400048000000000040036 ++:109220008800000001801100A10000000000000083 ++:10923000000000000000000000000000000000002E ++:10924000800000000000000400000000800000001A ++:1092500000000000004080000000000000C000008E ++:109260000005000000000000000100C00000000038 ++:1092700000000010000000000001000000C080019C ++:109280008009880500080000000000000000800040 ++:1092900002080001000100000000000100000000C1 ++:1092A0000040000000000041000900010000000033 ++:1092B00000000000000000000000000000000000AE ++:1092C00000002000000000000080000000000200FC ++:1092D00000000000000000800200000000110041BA ++:1092E0000021008400110000000000020000004185 ++:1092F0000010002100000020000000080000000015 ++:10930000024002C00990008000000005000000003B ++:109310000211018090400040000000100008880801 ++:10932000000004800010000088A000A000200000C1 ++:109330000000000000000000000004000000000029 ++:109340008201110000000409040104010403050066 ++:10935000000000100000000811400000408400845C ++:10936000802000414084C10200201084008500005C ++:1093700011C000A009C04110000209820040A140B4 ++:10938000111080A000402121000200400040000098 ++:109390000000804000888085909005400000008893 ++:1093A000000002900501004011000010021190829F ++:1093B0000000000000000000000504000408000098 ++:1093C0000010210400100000018401040104018444 ++:1093D00002009005904000000003C0C10440C0009E ++:1093E00000090280C0C0831040214083054104046D ++:1093F00000000005C0210041C00800008800820074 ++:1094000040A100210400C009A0A000A1004000006C ++:10941000100000000200000020081000A008080052 ++:109420000010100891001008C0050221C04011086A ++:10943000100000000000000000000000000000001C ++:10944000000000A000880010000000004021002063 ++:1094500002040940040811000405028400A0000071 ++:1094600040090084020080A0908341201120042044 ++:10947000008500000084000010824008098200403E ++:1094800004001009030803218200852010A00300B6 ++:1094900000C021000800000100C01000000805C045 ++:1094A0000300000405080082000005008802100087 ++:1094B000C1080304000000000000000000000000DC ++:1094C00000000000000040000000000000100184C7 ++:1094D0000080858000900080001100A00010000036 ++:1094E000000001A0880020000205204000800080CC ++:1094F0001180844000000000840000002100000072 ++:1095000000800121019000800040110040A1000571 ++:109510008200000000210000104082000010008046 ++:1095200000000000000000108410000810090490E2 ++:109530008821108900800000000000000000000069 ++:109540000000000000000200000000002000801069 ++:10955000008580088001020808004084094003104B ++:10956000000000100084802080C082100011008460 ++:109570000300C01100840000002000200201A003AD ++:109580000040C04011909008100110851004842004 ++:10959000410003404100034005400982050021408D ++:1095A0001000038200C00902038200020000830849 ++:1095B000000008848310400800000008000000003C ++:1095C000000000000000000300100010000801105F ++:1095D00020080004201104040111001001200003E0 ++:1095E00000000040A0800805402102104105000253 ++:1095F00000000040040802030000000000200008F2 ++:10960000414004C102A1820008800002014000C064 ++:1096100005800011880000000080000000000000AC ++:109620000008011000050000000800000000100004 ++:1096300002A1A020C000104008900000000000001F ++:1096400000000000000000000000000020000000FA ++:1096500002000404000800000011109000C0008403 ++:1096600000000040008400100308008200108010F9 ++:109670002008829010000010000000000388008481 ++:1096800000088284098882A011108211000000095C ++:1096900080404010218240840300418410A0418218 ++:1096A000200008C1410903000302908203088240A0 ++:1096B00000040200100005918290054100000000A6 ++:1096C00000000000000000000000000090000141C8 ++:1096D0000000900001004080400040200100000098 ++:1096E0000000000000800000000004830000100063 ++:1096F0001000001004000000000000000000004006 ++:1097000000080041200300410300C0004110000098 ++:10971000888804A0119000002110C01084108800D7 ++:109720000000882100400088C00000C12000000027 ++:1097300010000010101000000020040000200000A5 ++:109740000000000000000000000000000000021106 ++:109750000009400308081103004021082040104080 ++:1097600080881040041180C000034082000008047B ++:10977000000909052005A0802085824100A1008004 ++:109780000011800510900390200880112109851197 ++:1097900021038810A0091110100000000200080029 ++:1097A000402088111120024090050520040011403E ++:1097B0004005001004104108110008808580090050 ++:1097C0000000000000000000000000000000000099 ++:1097D0009101080100000001000188000000000163 ++:1097E00000081085009000900882C0000011004021 ++:1097F0000100080000000000880840C00391000834 ++:1098000000000004849101110089018384880120F3 ++:1098100091888901C10002000101019040040020EB ++:109820000100010008000100000085A18400004043 ++:109830000041C0018400000000010840A010C08465 ++:109840000004000000000000000000000000000014 ++:1098500000000000000001880088019000A10102C2 ++:10986000000001010090080008900800211020C0AD ++:1098700084021090104040A041A011009000000010 ++:1098800008080000030103C0212185000400000432 ++:10989000A0C00241A1008502A18308894100901067 ++:1098A00088012000A00101A0040085C0C00009C0FB ++:1098B000210008C000010502C0400304051091000A ++:1098C0004190854100000000000000000000000001 ++:1098D000000000004010200002001180080040033A ++:1098E00005C103091108100089088900800588084E ++:1098F0000809A0808009838000A109059100050066 ++:109900002000A1820000900240C188858805914016 ++:1099100040028900A111A003C0808505A11110009B ++:10992000000010212020091008000920C09103091F ++:109930000500050941A00802A08021918880A0901F ++:1099400004008500881000000000000000000000F6 ++:10995000000000000000109100030340410383A0B9 ++:1099600011084008892108098009009008C0118069 ++:1099700080800000A080028803880005028803110F ++:109980000090080005000000082000A1000302214B ++:10999000400900110890214008910420112089C03D ++:1099A0000009000880A000880282000520820805C6 ++:1099B000200880040388044008210090401010858E ++:1099C00000A02084A10900030000000000000000A6 ++:1099D000000000000000000001020088000891085B ++:1099E0000502009101901040001084840884408991 ++:1099F000000282908810400200050011008302835B ++:109A000001C08810018220400000000900C0081039 ++:109A10000290000840914003009100A001410041E4 ++:109A20000589004088C1088408080110000201C0AF ++:109A300000210088821190840220002000C10109C9 ++:109A400008080009C004100240A100000000000046 ++:109A500000000000000000000000041010908401CD ++:109A6000400001000084010001009110C1000801C4 ++:109A7000880091201001080190081040100000009B ++:109A80001008084108011000909000004085020075 ++:109A900020012002820182008800099083882182AF ++:109AA000200088C00101000101010082C010214096 ++:109AB000000090A09141C0112101091004894109C1 ++:109AC0009100C088208502408201C008000000008B ++:109AD0000000000000000000000000008080000383 ++:109AE00000028000030041A141002000088088118D ++:109AF0004002080020049010900208002102200873 ++:109B00002011020000088041800500000000208331 ++:109B10008408030200008903201109112003C08971 ++:109B2000408509008000100809080821008008000D ++:109B300005400308210003820810C1202080110283 ++:109B400004414009800000908004004100000000B2 ++:109B500000000000000000000000000000002100E4 ++:109B60000013C200000000000013C2000600000045 ++:109B70000013C200000000000006000042000000C8 ++:109B80000013C200000000840013C2002100000086 ++:109B900000000000C2000A000600001300000600DA ++:109BA00000410013C20041000000000000000060FE ++:109BB00000810000C200000000000013C20082000B ++:109BC000000000000000000021000013C20000009F ++:109BD0000000000000000000000000000000000085 ++:109BE00000000000153FD5FF141400100C5F0F5D3E ++:109BF0007DBF7D3DFFFFFFFF7DDDD7DD0000000065 ++:109C0000557FAA8033C3C9C3000000001E1E1E1E5C ++:109C1000000000FF5F5F0C3F0FFF0C0FFCFF0D3DCE ++:109C2000073FAAFF0F0FFFFFFFFF50000000283C77 ++:109C3000283CAAAAAAAA000F777F35355555050FEB ++:109C4000040E000F555F05000C00000000000030FE ++:109C5000CFCF000000000000000000000000000066 ++:109C6000000000000000002AC0EA000000000C5FB5 ++:109C70000FFD05550555FFFFFF7F41111411000031 ++:109C80000000057EFF813C3C6B6B000000001E1E47 ++:109C90001E1E000000FF0F0F000F0C3F000FF0FF13 ++:109CA0000D3D373F00550F0FDFFFFFFF00000000A5 ++:109CB000280020288A8000000C0F777F303F00FFAB ++:109CC000000A040E0000555555503C3000000000BD ++:109CD00041710C0C000000000000000000000000BA ++:109CE00000000000FFFF0804FC3CFC3CD7D7070045 ++:109CF000D540C00004FB55BE00000000FFFFFAAADB ++:109D000005000000DFFFFFFF50505050820082002E ++:109D10000000F1F100007D7D3C3C002800822F2FE7 ++:109D20002F2F3CFF00F3BEBEBFB03A3F3A300000D9 ++:109D30000000000082000F0AFFFFFFFE00FEAAFFE6 ++:109D4000EBEBFFFFBEBA555501010404050000000E ++:109D50000000000000000000000000000000000003 ++:109D600000000000000008040804FD3CBC3CFFFFAC ++:109D70000800D540C00003FCFF0000010000FFFF09 ++:109D8000F00000000000FFFFFFFF555500008300BA ++:109D9000830000000353000055555550507850D2B1 ++:109DA0002B2B2B283CFE00F214141F103A3F3A30A4 ++:109DB00000000000000000000F0CFFFFFFFC00FC93 ++:109DC000FFFFEBEBFFFF1410555500413434F50055 ++:109DD000000000000000E80000000000000000009B ++:109DE00000000000000000000086006109B80000CB ++:109DF000A5865A60A0B00085018600610898000021 ++:109E000000860C6000B0008001860260003800000F ++:109E10000086028408A80000000000860C6000B0E4 ++:109E2000000000860C6101A0008000860AFCA0B83A ++:109E300000000086006000B800800186006408B061 ++:109E400080050586006008B000050086006000B04F ++:109E50000000008600E109B90005000000000000D4 ++:109E600000000000008000000000DFFFFFFF5C5FDB ++:109E7000FCFF000000003D7DC2821E001EFF0000AE ++:109E8000FFFFFFEFFFEF00F100FDC300EB283C3CBC ++:109E9000FA05FCC0FCC07DBF824000000000000845 ++:109EA000C0F0FCFC7D28FAFA00000000E8E8FF3C66 ++:109EB000A0A0C300000000000100FFFF828200009C ++:109EC0005DFDFFFF141450503FFF5F5F08081C1C2E ++:109ED000D7D7FFFFFFFE5554F20202020000000038 ++:109EE000000000000000000000000000FFFFFFFF76 ++:109EF000FFFFFFFF00000000195DEEAAEBFFEB0083 ++:109F00000080FF7FFF2CFFEFF1FFFDFFFF3CEB2800 ++:109F10003C3C05FAFFFF00000555FAFA000000007E ++:109F2000000840F07CFC7D28505004000000E8E868 ++:109F3000C30000000000000000005100FFFF82AAE3 ++:109F400000005D5DFFFF003C00F00F0F5F5F0A0047 ++:109F50005F00CFFFCFFFFFFA555000000000000068 ++:109F600000000000000000000000000000000000F1 ++:109F70000000000000000000000000000000AF052D ++:109F8000AFAFFF000000DCDC6C6C8ECF4DCF00006B ++:109F9000000000002828EB28E8E8FFFF1E1E000054 ++:109FA000FFFF3FFF000F7DDFFFFFAAF3000000006F ++:109FB00000000000BFF36FF300000A00FF8FFFFFF7 ++:109FC000000000000055147DB2B2B2B2140C140CA3 ++:109FD0000000000000FF55550A0A0A0A00003C0F65 ++:109FE0000000000000000000400000000000000031 ++:109FF0000000000000000000000000000000000061 ++:10A00000870587AFFF0000009C9C33338E0C4D0CFE ++:10A010000000000040018001EB28E8E800001E1E5F ++:10A020000000FFFFFFFF003F7DDFFFFFFFF3282859 ++:10A03000280000000000DFF3EFF300000000FFDF66 ++:10A04000FFFF000000000055147DFFFF000000002E ++:10A050003C3C000000000F0F0F0F08080800000034 ++:10A060003C5500000000000000000000000000005F ++:10A070000000000000000000020000880000000056 ++:10A0800000000000000000002100000000000000AF ++:10A090000000050000A000000400210021000000D5 ++:10A0A00021000000000000200091110000000000CD ++:10A0B000A000C00209000002001000000000001013 ++:10A0C00000208408000000040002000000000004DA ++:10A0D0000400040020100002000000000000210025 ++:10A0E0000404210000000000000000000000000047 ++:10A0F0000000000000000000000000000000000060 ++:10A10000000000000000000000000000000000004F ++:10A110000000000000000000000000000000000837 ++:10A120000000000000008800000000100000000097 ++:10A130000000050011800000008088800000000001 ++:10A1400090800080108000000080008000000000EF ++:10A15000008401000000008000800000000000007A ++:10A1600000000180900000000000000000000000DE ++:10A1700000000000000000000000000000000000DF ++:10A1800000000000000000000000000000000000CF ++:10A1900000000000000000000000000000000000BF ++:10A1A000000000000000004000C0000100000000AE ++:10A1B0000082000000010008000000C00000000054 ++:10A1C000000000028084000900000001000000007F ++:10A1D00000008000002000080000000000110000C6 ++:10A1E00000000082000000080000000000000000E5 ++:10A1F000000000000000000000000000000000005F ++:10A20000000000000000000000000000000000004E ++:10A21000000000000000000000000000000000003E ++:10A2200000000000000000100000000000400000DE ++:10A23000000000000000000400C100110000000048 ++:10A240000000000000A00421008400000040000085 ++:10A25000000000080800009100800000001000824B ++:10A26000000000210041002100C1000000000000AA ++:10A2700000000000000000000000020000000000DC ++:10A2800000000000020000000000000009100000B3 ++:10A290001100020021000010210000000400000055 ++:10A2A000020004C0000000000000000000000204E2 ++:10A2B00002838400040000040200808308900320CD ++:10A2C00011000000008441840001A08400A020014E ++:10A2D0000085411000820382800400A1000009C0B3 ++:10A2E000008400A0119040C0001111110000000076 ++:10A2F0000000000000000000000000000003000556 ++:10A3000000000000000300000005881000000408A1 ++:10A31000A00800419005000900030041002100024F ++:10A320000021000384410010C0000021000000054E ++:10A33000C1850102100000080083004140080509A2 ++:10A34000A0800010104100410000A0042100000086 ++:10A3500085408840024000088221208900021010B8 ++:10A3600082218210884090410505400410040000BD ++:10A3700000000000000000000000000000000000DD ++:10A380000082009000200088000000000000000013 ++:10A390000000000000000000000040820082090070 ++:10A3A0000300000020200800000000000000000062 ++:10A3B00000000000009000000088088200000000FB ++:10A3C000000000000901400000000000030003003D ++:10A3D0001100004000010000000008000091900002 ++:10A3E000001000A00300210800004100000120012E ++:10A3F000000000000000000000000000000000005D ++:10A400000000000000000000000800000000001034 ++:10A4100000000000000000009000000000000000AC ++:10A4200090210011000000000020002100400011D8 ++:10A430000000000000009003200000080103040059 ++:10A4400000000011001190020009001188038840EB ++:10A450000000A0098841001088000008830900203E ++:10A460001000109100000011A0100000004000201A ++:10A4700001080000000000000000000000000000D3 ++:10A4800000000000000000000000000000000000CC ++:10A49000000000000000000000880000000009200B ++:10A4A0000000000000000084000000000000000028 ++:10A4B0000000000041000000000190C0000004A165 ++:10A4C0002040000010C0004000A0850010001003D4 ++:10A4D00000A01010039000A083A0000800088001D5 ++:10A4E0002040408400C0000000A0800000024041E5 ++:10A4F000800002400000000000000000000000009A ++:10A50000000000000000400800000020004100089A ++:10A51000A003000388039011A011900390219011D3 ++:10A520000408041002104002001104080000040591 ++:10A530000421040500000021000900101003C010D0 ++:10A540000210A11004118400024004410221000005 ++:10A550000410400005009000A0400211A0890005F1 ++:10A56000081001001103C003000982080200001056 ++:10A57000C0102008C008000000000000000000001B ++:10A5800000000000000000000000000000000000CB ++:10A5900000000000000000000000000000000000BB ++:10A5A00000000000000011880000000000000020F2 ++:10A5B0000000001000000000000011400282218213 ++:10A5C000091000A0000002000000001000840082BA ++:10A5D000001008100010004000100010410210840C ++:10A5E0000010008400850000000000200084008826 ++:10A5F00000840810008410830000000000000000A8 ++:10A60000000000000000000000000008900088002A ++:10A6100000118840880000000000000000000000D9 ++:10A62000900900000011000000000000000500007B ++:10A630000020000000400000000090000090880012 ++:10A640009003040488098804000000000000000949 ++:10A65000000000000141004000000000044100A093 ++:10A6600090418802A00200200000C0000083820305 ++:10A670000000000003A0041005040000000000001A ++:10A6800000000000000000000000000000000000CA ++:10A6900000000000000000000000000000000000BA ++:10A6A00000000000000000000000000000000000AA ++:10A6B0000000000000000000000000000000830017 ++:10A6C000008083C1000003000041C0890300030033 ++:10A6D000000303410000030080C11000000083005C ++:10A6E0000080834100000300004190848300030048 ++:10A6F000000303410000030080C1200000000000AF ++:10A700000000000000000000000000000000000049 ++:10A710000000000000000000000000000000000039 ++:10A720000000000000000000000000000000000029 ++:10A730000000000000000000000000000000008297 ++:10A74000838200C083410082014088C182C001042D ++:10A750000982000101010090019010C101000082F6 ++:10A76000838200C083C10082012088A183C08382CC ++:10A770000984000101010090019010C10000000057 ++:10A7800000000000000000000000000000000000C9 ++:10A7900000000000000000000000000000000000B9 ++:10A7A00000000000000000000000000000000000A9 ++:10A7B0000000000000000000000000000000000099 ++:10A7C00082009082008300008210A1820082C0205B ++:10A7D000098383820083C1008200038200830120F9 ++:10A7E0008200888200830000821041820082C020A3 ++:10A7F000098385820011C1018200038200830190D8 ++:10A800000000000000000000000000000000000048 ++:10A810000000000000000000000000000000000038 ++:10A820000000000000000000000000000000000028 ++:10A830000000000000000000000000000000000018 ++:10A840000000000000800083000000800280008083 ++:10A850008080908310830083C10040008280008349 ++:10A860004180000000800083000000808280008022 ++:10A870008080908341830083C108400082800083F0 ++:10A880004100000000000000000000000000000087 ++:10A8900000000000000000000000000000000000B8 ++:10A8A00000000000000000000000000000000000A8 ++:10A8B0000000000000000000000000000000000098 ++:10A8C000000000000002000083C1000000000080C2 ++:10A8D000801020C1002100008302000000000080E1 ++:10A8E000830080000002400083C10000000000805F ++:10A8F000801002C1001100008302000000000080EF ++:10A9000083000000000000000000000000000000C4 ++:10A910000000000000000000000000000000000037 ++:10A920000000000000000000000000000000000027 ++:10A930000000000000000000000000000000000017 ++:10A940000000000000000001008283C10000000040 ++:10A95000001082A101C100820082838300000000F8 ++:10A9600000C0828202000001008283C1000000005A ++:10A97000001082C1A0C10082008283830000000019 ++:10A9800000048282000000000000000000000000BF ++:10A9900000000000000000000000000000000000B7 ++:10A9A00000000000000000000000000000000000A7 ++:10A9B0000000000000000000000000000000000097 ++:10A9C00000000000000000008301018201890000F6 ++:10A9D000104000820583C089838201010183000049 ++:10A9E0008282000001018288838901820183000044 ++:10A9F00010200082A083108883820101018300005F ++:10AA0000828200880101C0080000000000000000F0 ++:10AA10000000000000000000000000000000000036 ++:10AA20000000000000000000000000000000000026 ++:10AA30000000000000000000000000000000000016 ++:10AA40000000000000000000000002031080410828 ++:10AA50000000800041804082001002C00403028395 ++:10AA60000000008000000208002002030480410270 ++:10AA7000000080000280C182800302C004030283C0 ++:10AA8000000000800000024100C000000000000043 ++:10AA900000000000000000000000000000000000B6 ++:10AAA00000000000000000000000000000000000A6 ++:10AAB0000000000000000000000000000000000096 ++:10AAC0000000000000000000000000000000000086 ++:10AAD00000001242000000000000124281480013F2 ++:10AAE000C2001242000000000000124200000000FC ++:10AAF00000001242000000000000124281480013D2 ++:10AB0000C20012420000000000001242FFFFFFFFDF ++:10AB1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10AB2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:10AB3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 ++:10AB4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 ++:10AB5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 ++:10AB6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 ++:10AB7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5 ++:10AB8000FFFFFFFFFFFFFFFFFFFFFFFFFFFF005C77 ++:10AB9000D1510C44C07000E80A0600000881000092 ++:10ABA00000000000000000000000000000000000A5 ++:10ABB0000000000000000000000000000000000095 ++:10ABC0000000000000000000000000000000000085 ++:10ABD0000000000000000000000000000000000075 ++:10ABE000AEDE0000000000000000000000000000D9 ++:10ABF00000000000000000000000000000007B7565 ++:10AC0000AEDE0000000000000000000000000000B8 ++:10AC100000000000000000000000000000007B7544 ++:10AC20000000000000000000000000000000000024 ++:10AC30000000000000000000000000000000000014 ++:10AC40000000000000000000000000000000000004 ++:10AC500000000000000000000000000000000000F4 ++:10AC60000000067BC000000000000000008C070010 ++:10AC700000000000000030000000000000000003A1 ++:10AC8000DE60067BC000000000000000008C0700B2 ++:10AC90000000000000003000000000000000000381 ++:10ACA000DE60000000000000000000000000000066 ++:10ACB0000000040080000400000000010001000109 ++:10ACC00080010000000000002000000000000000E3 ++:10ACD000000000000000000083000000000000A150 ++:10ACE00000000000000000000000000000A00008BC ++:10ACF00000000000A000840020008409000810016A ++:10AD000080000000000000000000000084008400BB ++:10AD10000400800004002100000004002000200046 ++:10AD200020000008000000000000000000000000FB ++:10AD300000000000010020000100000000200020B1 ++:10AD40000020202000000021000000000000000082 ++:10AD500000000000000000000000020000000000F1 ++:10AD600000080000000000000000000000000000DB ++:10AD7000008000000000050005210100108800800F ++:10AD8000014002000000000000100000000021004F ++:10AD9000210001001000000000000000A1000100DF ++:10ADA00001000100000000000000000000000000A1 ++:10ADB0000000000000000000000000000000000093 ++:10ADC0000000000000000000000000000000000083 ++:10ADD00000000000000000000000000000000084EF ++:10ADE00000820090008200C0000000000008000007 ++:10ADF00000000000000000000000000000000082D1 ++:10AE000000000008000000000000000000C000007A ++:10AE100000000000000180000000000000000004AD ++:10AE20000082000000000008000000000000000098 ++:10AE30000000000000000000000000000000000012 ++:10AE40000000000000000000000000000000000002 ++:10AE500000000000000000000000000000000000F2 ++:10AE60000000000000000000000000410000008021 ++:10AE700000000000000000000000000000000008CA ++:10AE800000410000008000000000001000000000F1 ++:10AE9000000000000000000804000021001000086D ++:10AEA0000000000000000000009000000000000012 ++:10AEB000000000000000000000000400000084000A ++:10AEC000000000000000800000000300A00002005D ++:10AED000C100000102000900020000000290090008 ++:10AEE000008840000000040009A00000000009855F ++:10AEF000890840C000908040001000000020102011 ++:10AF000080010001008203414140808400A0831041 ++:10AF10000085000000C000081108000800C002A061 ++:10AF200010400000210003C0000000840000000069 ++:10AF30000000000000000000000000000100000010 ++:10AF400005000000000000002000000000002100BB ++:10AF5000010020000040010000000100000001038A ++:10AF600000050000014100000005824100000008CA ++:10AF70000020108811089041200000030005009077 ++:10AF80000180042000208241A0880080100000057C ++:10AF9000400000209000000000410000C08500003B ++:10AFA000010001A100000041000084000003000036 ++:10AFB0000000000000000000000000000000000091 ++:10AFC0002000200020000000000000000000000021 ++:10AFD000000000000000050000000000000002006A ++:10AFE0004000100000000400020005000200000004 ++:10AFF0000000040041000000800009002000A000C3 ++:10B0000000002100030004009000830080840800F9 ++:10B01000000804004100000110014100000084000C ++:10B020000500000010100200090010000088000058 ++:10B0300000000000000000000000000000004000D0 ++:10B0400000000100050001000000000000000020D9 ++:10B050000010040000000020000000200000000597 ++:10B06000004001040503040000410121002001000B ++:10B0700000000009010088090400204100000100CF ++:10B08000030000000005000201091100040504008E ++:10B090000100008501000000000201080000000816 ++:10B0A000200000210011000300210000000000002A ++:10B0B0000020000000000000000000000000000070 ++:10B0C000000000000000000000000001200000005F ++:10B0D0000001800000000001000980000000020162 ++:10B0E0001000100004A00084008800400000000050 ++:10B0F000004000000084C1840508104000000000EA ++:10B100001110410004000421042004200582008461 ++:10B1100004200902408800A11003901100C0000023 ++:10B120008082008200C0108402A0108441000000D0 ++:10B130000000828400000000000000000000000009 ++:10B1400000000000000000000000000000040100FA ++:10B150000000000420000008C00400041000880063 ++:10B1600001080500000000000000000800000000C9 ++:10B1700000000080004000101000008001800008E6 ++:10B180000021C02100008900C18801808980000061 ++:10B190000000018000100110000801A005400021FE ++:10B1A0000021202104000000C008011088050000D3 ++:10B1B00000109000111000000000000000000000CE ++:10B1C000000000000000400000004000400020009F ++:10B1D000000800002000040000000000000900003A ++:10B1E000000040000000024002081010008202022D ++:10B1F000042020000020000040840584000800A0F6 ++:10B20000002009880088008404020010001004A0B7 ++:10B210000000004011840511090100042008000409 ++:10B22000042004C000080284058420104108090499 ++:10B2300000880090042011200000000000000000A1 ++:10B24000000000000008000200030420902000001D ++:10B250000100040004200120000000000000400460 ++:10B26000040300000000040000000180002004101E ++:10B2700000A1000004410021000001000000008046 ++:10B2800000000000040000000411000000000000A5 ++:10B29000000000000080000082A0002000000004E8 ++:10B2A00000000000000000000010042188030000DE ++:10B2B000000000000000000000000000000000008E ++:10B2C00000000000000000000000838084890591D8 ++:10B2D0000080030380090011000000030009000042 ++:10B2E00000211180000000001000201005114020F6 ++:10B2F00021400800210010000300000020218004EC ++:10B30000032103082040030540410541032000219B ++:10B31000880200082100000040208008C00340206F ++:10B32000911021114100000000000500050000807F ++:10B3300000000300040400092103000000000000D5 ++:10B3400000000000000000000000000089200585CA ++:10B35000008800C0A101108982A000A000010001A6 ++:10B360000000000000822088000801900001010018 ++:10B3700000010000000000000100000000002100AA ++:10B3800004010000010041018400000100000100EF ++:10B39000A002419000910000040001008400A0017F ++:10B3A000000002010100000000000000000001A0F8 ++:10B3B000000800900040A00008010000000000000C ++:10B3C000000000000000000000000000000020005D ++:10B3D00091008800850908000500A00091A1C00027 ++:10B3E00002000200030190001010A10008054000B7 ++:10B3F0008500410009900200A100850041C00000C5 ++:10B400000001010001000082040011214020900091 ++:10B4100008008904000020080101C090C18808C00C ++:10B420000088002100A101090102002100030001A0 ++:10B430000201A00490012002040084C02101030045 ++:10B4400000000000000000000000000000000000FC ++:10B4500080084100800083898005C1000000030945 ++:10B4600011000000000003052140A08085038585B0 ++:10B4700000408800050005000809100088001080C1 ++:10B48000000002201000050000808200A0020811C8 ++:10B49000050303004000400080C01140400010043C ++:10B4A000C0000500030520080340208020C040881C ++:10B4B000114080050080002100C141000200901071 ++:10B4C000200000000000000000000000000000005C ++:10B4D0000000008000800089000300008080800957 ++:10B4E00000030000004100898003000800000808F4 ++:10B4F00000C10340000000C010400008008800A008 ++:10B500000021008010110020000205884040000248 ++:10B5100008C10305024000042009008500402120E5 ++:10B520000040A08220054090058210038002411156 ++:10B530000320801000050021000200404040000070 ++:10B540000589000500000000000000000000000068 ++:10B5500000000000000890208203002100881002F3 ++:10B5600002A100A10000000100A1200100A1829021 ++:10B5700083918803012100840084010900400003B5 ++:10B5800000840090008001080020009100C0018824 ++:10B590000082018588410108C00220210089002025 ++:10B5A0000102008883028890011000211103040029 ++:10B5B00000010101A0010001A0000001A001019112 ++:10B5C0000082008500410000000000000000000033 ++:10B5D00000000000000004102000020008000188A4 ++:10B5E0001100A00090A001890100010100A011112B ++:10B5F0008308910189101020880120000202A021F7 ++:10B600004000820010840080040288108200000044 ++:10B61000010101030000002003101121080020098E ++:10B620008200090084004100039009412140A001EB ++:10B6300000A000000103010085A120008300C004D8 ++:10B64000011100A101000040000000000000000006 ++:10B6500000000000000000008091800080110000C8 ++:10B66000038084001111000003A0410002210000AA ++:10B67000888802089121088080C100400004800071 ++:10B6800000A0001100008080008080808080000089 ++:10B690000000100305C01141208009828510402060 ++:10B6A000830889200520C121100003000490108325 ++:10B6B000110821000909028808009008A000100064 ++:10B6C000208009900940200941000000000000008E ++:10B6D0000000000000000000000000000013C20095 ++:10B6E000820000000013C200820000000000C200BF ++:10B6F000000000000000000000000000000000004A ++:10B700004100000000000000000000008200001363 ++:10B710000000005000000000C20021000081001362 ++:10B72000C20011008200401300000042000000131C ++:10B73000C200000000000081C20000600000008123 ++:10B740000000000000810000C200000000000000B6 ++:10B7500000000000000000000000000000000000E9 ++:10B7600099000000F000000099000000000F0000A8 ++:10B77000F00000003E3E3E7CFFFF7E240000000003 ++:10B78000FF7E99180000000090996F6E0000000085 ++:10B7900000008000000066006600FFFF7F6F3F3FF3 ++:10B7A0003030FE986E0824240000000800000000DD ++:10B7B0000000000000003C3C00BF6F0F6F2F000036 ++:10B7C0000003818181C3FFFF0000BD813C000000B8 ++:10B7D0000000000000000000000000000000000069 ++:10B7E000000099000000F000000099000000000F28 ++:10B7F0000000F0000000024040407E2400000000F5 ++:10B800000000667E001800000000D0DD2F2A000036 ++:10B8100000000000000000006600E680FFFF3F0F10 ++:10B82000FF0FF000FE986E080000400000080000C6 ++:10B8300000000000000000000C0C00EF6E0A6E2AF1 ++:10B8400009000903838183C3001E001EBD813C00E3 ++:10B8500000000000000000000000000000000000E8 ++:10B8600000000000000000000000000000000000D8 ++:10B8700000000000000000000000000000000000C8 ++:10B8800000000000000000000000000000000000B8 ++:10B8900000000000000000000000000000000000A8 ++:10B8A0000000000000000000000000000000000098 ++:10B8B0000000C208040000118861000000000000C0 ++:10B8C0000000000000000000000000000000000078 ++:10B8D0000000000000000000000000000000000068 ++:10B8E0000000000F000F000000000000000F00002B ++:10B8F0000000000000C300000000000000007070A5 ++:10B9000070F09F099F9FFFFFFFFF000000005CA3F6 ++:10B91000CA3500000C042C2CFCFFFCFF800000004A ++:10B9200098181000F0F0F0F03C3C3C3C78787878C7 ++:10B930000000000000000000000000000000000007 ++:10B94000F4F4FCFD000000000000000000FF00FF18 ++:10B9500033660F66000000000000000000000000D9 ++:10B9600000000000000F000F0000F0F00000000FCA ++:10B970000000F0F0000000C300003C3C00000000AC ++:10B98000303030F09F098B8BF6FFFFFF0000000086 ++:10B990005CA3CA35000008082C2CFCFFFCFF8100CA ++:10B9A000000099981810C33C3CC369966996787852 ++:10B9B00078783C3C3C3D00000000000000000000A6 ++:10B9C0000000F4F4F4F50000000000000000F0F0C6 ++:10B9D000FFFFCC66F06600000000000000000000E1 ++:10B9E0000000000000000086C04130A04903C0C72D ++:10B9F000C08030804903C0C7C06030B043030086B8 ++:10BA0000006000B000000086006000B0008000868A ++:10BA1000006000B8000000000086022101B80000AC ++:10BA20000086506000B00005008600940080000091 ++:10BA30000086006101F8040005860A6100B900A0D3 ++:10BA4000A0865061A8B000850086006100B00000AB ++:10BA50000086007400B0000000000000000000003C ++:10BA600000000000000000003C3FAAAF35553555EE ++:10BA7000000000000000000000000000FF00FF00C8 ++:10BA8000FCBD8103CFCF0C0C4341555F01833DBF0B ++:10BA9000FCB800000CAC5CFC0000FF0000000000E3 ++:10BAA000000000000000E7FFDBFFF3F3FF005CFC99 ++:10BAB000ACFC74008B7400FF00FFF3F3FF00CFEFCA ++:10BAC0000F2F0000000000000000000057F70000EA ++:10BAD0000000000000000000000000000000000066 ++:10BAE000000000000000000000003C30AAA0300070 ++:10BAF0003FFF000800080C00000000000000FF00ED ++:10BB0000FF00FFFFC3C3FF00FF00FDBEAAA001832B ++:10BB10003DBFB83000000CAC5CFC0000FF000A0A1E ++:10BB20003050000000000000BDFF7EFF3030FF00FD ++:10BB30005C0CAC0CFF74748B69690F0F3030FF0024 ++:10BB4000CFEF0F2F00000000000000000000F7F70B ++:10BB5000000000000000000001FF00FF00000000E6 ++:10BB6000000000000000000000000000FF000000D6 ++:10BB700000003C3C01000100000002000000000049 ++:10BB8000FFFFFFFF33663333E72424E700000000A4 ++:10BB90003CC3C33C00000000555555550000000053 ++:10BBA00000000000000000000000EEBBFFFFF0AA54 ++:10BBB000F0AA3C3C555500000000F0F0FFFF0000EB ++:10BBC0000000000000000000000000000000000075 ++:10BBD0000800FFFFFFFF0000000000004000000021 ++:10BBE0000000000000000000000000000000FF88CE ++:10BBF00088880F003F3C00000000000002000000A9 ++:10BC000000007FFFFFFF66CC3333DB1818DB00003A ++:10BC10000000A5A5A5A50000000003FCF30C000092 ++:10BC2000000000000000000000000000DD77FFFFC2 ++:10BC3000F03CF03C0F0F0F0F00000000F000FFF091 ++:10BC400000000000000000000000000000000000F4 ++:10BC500000000800EFFF4FFF0000000000000000A0 ++:10BC60000000000000008001000000000000000053 ++:10BC700000000000000000000000000000000000C4 ++:10BC80000020000000000000800000000000000014 ++:10BC90000000000020000000000000000001000083 ++:10BCA00000000090000800000000000020000000DC ++:10BCB0000000210000A000000000000000001100B2 ++:10BCC00000000000000000000400000004A02000AC ++:10BCD00000010000000180000001000000000000E1 ++:10BCE0000000000000000000021000000000000042 ++:10BCF0000000000000000000000000000000000044 ++:10BD000000000080000000000000020000000000B1 ++:10BD1000000000000000010000000000000000081A ++:10BD20000000000000000000000000000000010012 ++:10BD30000000000000000000000000000000000003 ++:10BD400000000000000000000000010000000000F2 ++:10BD500000000008000000081000000800000010AB ++:10BD60004000000000000000000000000000000093 ++:10BD700000000000000000000000000000000000C3 ++:10BD800000000000000000000000000000000000B3 ++:10BD900000000000000000000000000000000000A3 ++:10BDA0000000000000C000000000000000000000D3 ++:10BDB0000000000000000000000000000000000083 ++:10BDC0000000000000000000000000010000000072 ++:10BDD0000000000000000000000000000000000063 ++:10BDE0000000000000000000000000000000000053 ++:10BDF0000000000000000000000000000000000043 ++:10BE00000000000000000000000000000000000032 ++:10BE100000000000000000000021000000210000E0 ++:10BE2000000000000008000000000000000000000A ++:10BE300000030000000000000000001100000000EE ++:10BE400000000000000000210005000000080000C4 ++:10BE5000001100110010000000030000000000109D ++:10BE600000000000001000000000000000000000C2 ++:10BE700000000000000000002000000000000000A2 ++:10BE800003000200000000000000000000000000AD ++:10BE90004100000000848200200000000001020038 ++:10BEA000000000C000820000000000A0008400101C ++:10BEB00000A00000A01002000000000005840000A7 ++:10BEC00000840000000000000000000000A100C08D ++:10BED000040800000000000000080000000000C08E ++:10BEE00000820000001000002000000000000000A0 ++:10BEF0000000000000000000000001000000000041 ++:10BF00000010000001000000001000000000000010 ++:10BF100000000000000000001100010000410004CA ++:10BF20000100000800000040002100000010002176 ++:10BF30000000000000212100010300030000840331 ++:10BF40008400002100030000000800080000000237 ++:10BF500000080180000000080003000082000000CB ++:10BF6000004100000000000000008500000000000B ++:10BF700000000000000000000000000000000000C1 ++:10BF800000000000040000000001000000000300A9 ++:10BF9000030000000000000000000000000000009E ++:10BFA0000000000000000900000000000000000088 ++:10BFB0000000000000000400000009000000000074 ++:10BFC00005001000000000000000000084000000D8 ++:10BFD000000003002000000010000000002000000E ++:10BFE0000000030000000500000000002000000029 ++:10BFF000000000000000000000000000000000023F ++:10C000000000000000000100000000080000000027 ++:10C010000000000000000000000000000000000020 ++:10C020000000000000000000000000000000000010 ++:10C0300000000000000000000000000300000000FD ++:10C0400000000000000000000000000000002100CF ++:10C05000000000000000010000000000000200805D ++:10C0600000000000000000020000000000000100CD ++:10C0700000000000000000000000000000000000C0 ++:10C080000000040080208000040000000400040080 ++:10C0900000A00082002000000010000080010000CD ++:10C0A0000000000000000000000800000000800008 ++:10C0B00000000010000000000000000002A00000CE ++:10C0C000000003000000000000000000000000105D ++:10C0D0000200000000000001000000001008000045 ++:10C0E00041000000000041004100000000C0058246 ++:10C0F0002000000000000000000000000000000020 ++:10C100000000000001100480042101210000011141 ++:10C11000890300000000008000000011002102409F ++:10C1200000000000000300050000000800000040BF ++:10C130001021000000000008004100000011C103B0 ++:10C14000000804210000000588050010C000000060 ++:10C15000C010010384100000C02000210000100066 ++:10C160000000001110000000000000100000C010CE ++:10C17000100001000000000000000000110000009D ++:10C180000000000000000000000000000088000027 ++:10C190000002408200880020009000200010000073 ++:10C1A000042000000008001000000000008210843D ++:10C1B00000080010000000000000040000840010CF ++:10C1C0002008020000080010008400000040110058 ++:10C1D0000000090003840000004000000000008807 ++:10C1E0000084000000104000000041000220008296 ++:10C1F0000004030802A0000000000000000000008E ++:10C20000000000000000000000000000000000002E ++:10C21000000000000000000000800000008000001E ++:10C22000000000000000000000000000000000000E ++:10C2300001000080000000000000840000000000F9 ++:10C2400000000100001000000000000000000000DD ++:10C2500000000000000000000000000000000000DE ++:10C2600000000000000000000000000000000000CE ++:10C27000000000000000010000000000000000803D ++:10C280000000000000008000082189052103004112 ++:10C29000008000800800008000000000880000008E ++:10C2A0000200000020800580001080021020211074 ++:10C2B000000000000000100000000000000000006E ++:10C2C000000000000000000000000000000000006E ++:10C2D00000000000910011000000080000000000B4 ++:10C2E00003000000000000000000114000110010D9 ++:10C2F00010110000000040000000000000000000DD ++:10C30000001000000000000010000101A1009100D9 ++:10C310000000000482849100000200902008059033 ++:10C3200000A00190402000040104000182000101EE ++:10C3300000010000000000000100000000000000FB ++:10C3400000000000000000000000000000000000ED ++:10C3500000000000880091000000000000000000C4 ++:10C3600000000000000000000000000000000000CD ++:10C3700000010100000000000100000001000000B9 ++:10C3800000A000080000000000000000020000A063 ++:10C39000000020C1200084000040008890010800B7 ++:10C3A000200000C0080090001120200001000020A3 ++:10C3B000000000000000000001000000000000007C ++:10C3C00000000000000040001001040040100000C8 ++:10C3D000000000000000000000000000000101005B ++:10C3E00000000082000000000100000001000000C9 ++:10C3F000000000000000000000000000000102003A ++:10C400000000008000080800000000000000910308 ++:10C4100005800021C1898003800000800000001099 ++:10C420000000000000002000000085000500100052 ++:10C43000400002401100000005000500410000001E ++:10C4400000000000000000000005800580008080E2 ++:10C45000000000000000000000000000000000419B ++:10C460001000020003802040400011002100100055 ++:10C470000500210003000000000000000000000390 ++:10C48000000000000000110000000000000000009B ++:10C49000000500830982C041000000000000000088 ++:10C4A0000000000000000000002000C1809100A1F9 ++:10C4B00003A00040000903850003000300080003F7 ++:10C4C000000000000000000000000000000000006C ++:10C4D00000000000000000000000000000001180CB ++:10C4E0008080004100214120000500000000008004 ++:10C4F0000000081000080008050800000000000007 ++:10C50000000000000000000000000000000000002B ++:10C51000000000A0000401038920000890848288A4 ++:10C520000090000820C000900000009084102010AF ++:10C5300000040010000000210103000000000000C2 ++:10C5400000000000000000000000000000000000EB ++:10C5500000000000000000000000000000000000DB ++:10C560000088C082000000000001A001000000005F ++:10C5700000202000000100000000000100400090A9 ++:10C580000082000000000000000000000000000029 ++:10C59000000000009005208300002020202088005B ++:10C5A0004000088808012000900000820020004020 ++:10C5B000000000C0010001010101000000000000B6 ++:10C5C000000000000000000000000000000020004B ++:10C5D0002000A0000020000000000000000000007B ++:10C5E000009000000000002000000001000000009A ++:10C5F000000000000000000000010000000000A09A ++:10C60000000000000000000000000000000000002A ++:10C61000000000000000058280C10303C100008506 ++:10C620000000000000000040000000000080001139 ++:10C630000003000800800900051009202100000007 ++:10C6400000080041000000000000000000000000A1 ++:10C6500080038000000000000000000000000000D7 ++:10C6600000000000000000000000001100020000B7 ++:10C670000000001100000000000000100003000096 ++:10C6800000000000000000000000000000000000AA ++:10C69000000000000000000000000013C200420083 ++:10C6A000000000130000000000000013000000481C ++:10C6B000000000000000000000000000C2000A416D ++:10C6C000000000000000000000000000000000006A ++:10C6D000000000420000C200000000000000000056 ++:10C6E000000011000013C240000012840013C200B9 ++:10C6F00000840000001300000000000000000000A3 ++:10C70000000000600000C2000042000000000000C5 ++:10C710000000000000000000000000000000000019 ++:10C7200000400000000000000000000000000000C9 ++:10C7300000000000000081C0BDFC08FF20FFF000E9 ++:10C74000FC3C000000000F3F3FFF00000000000025 ++:10C7500000000000000000000000000000000000D9 ++:10C7600000000000000000000000000000000000C9 ++:10C7700000FF3FFF0000000000000000000000007C ++:10C78000FFFFFFFF000000000000000000000000AD ++:10C790000000000000000000000000000000101079 ++:10C7A0000000004000000000000000000000000049 ++:10C7B000000000000000000003423F7E0808202027 ++:10C7C00000003C3C00000000000C0C0F00000000CA ++:10C7D0000000000000000000000000000000000059 ++:10C7E0000000000000000000000000000000000049 ++:10C7F000000000283FCF0000000000000000000003 ++:10C8000000007FFFFFFF00000000000000000000AC ++:10C810000000000000000000000000000000000018 ++:10C820000800000000000000000000000000000000 ++:10C83000000000000000000000007D7D2828BEBE32 ++:10C84000BFB0AAAAF0F000000000FFFFFAA00000AD ++:10C8500000000000000000000000000000000000D8 ++:10C8600000000000000000000000000000000000C8 ++:10C8700000000000FFFCFF0A000000000F0014147D ++:10C880003838103828282828000000000000000050 ++:10C890000000000000000000000000000000000098 ++:10C8A0000000080080800000000000000000000080 ++:10C8B0000000000000000000000000007D287D282E ++:10C8C00014141F10EB28F33000000000FAA0000041 ++:10C8D0000000000000000000000000000000000058 ++:10C8E0000000000000000000000000000000000048 ++:10C8F000000000000000FCFC0A0A000000000F001D ++:10C90000141438101010F000F000000000000000B7 ++:10C910000000000000000000000000000000000017 ++:10C920000000008600B108800000008600C1008081 ++:10C93000000000860081008000000086006000B0DA ++:10C9400000000086006008B0000000000000000049 ++:10C95000000000000000000000000000008650649D ++:10C9600008B0000000000000000000000086006128 ++:10C97000A93000050086006509B080850086006149 ++:10C98000003000000000000000000000008600648D ++:10C9900008B08005000000900900000000000000C1 ++:10C9A000010000007DBEFF3C55555555FFFFFFFFC0 ++:10C9B0002000F7FF00500000000000000000000011 ++:10C9C0003C0CDFDF00000000EB82147D0000000063 ++:10C9D00000000000000000000000000000000F0048 ++:10C9E0000F05000000000000000000000000000033 ++:10C9F0000000AAAAFF0000000000000000000000E4 ++:10CA0000000000FF00000000000000000000000027 ++:10CA1000000000A800A80000002000100140000055 ++:10CA20000020000000004182C3005D555155FF5DAC ++:10CA3000FFDF0000FFFF000000000008000800000A ++:10CA400000000C0C7D7D00000000147DEB820000D6 ++:10CA500000000000000000000000000000000000D6 ++:10CA600000000000000000000000000000000000C6 ++:10CA700000000000000000000000000000000000B6 ++:10CA80000000000000FF00000000000000000000A7 ++:10CA90000000000000A800A80040400000020200C2 ++:10CAA0000000000000000200000000006969FFFFB4 ++:10CAB000AAC3AA3CC5C5C5C50000100001000100FD ++:10CAC000D7827D2876C373C30000000000000000F9 ++:10CAD0000000000000000000000000000000000056 ++:10CAE00000000000000015B51FBF0000000000009E ++:10CAF0000000000000000000000000000000000036 ++:10CB00000000000000000000000000000000000025 ++:10CB100000000000000000000000400000000000D5 ++:10CB20000002000000000000000000000000696931 ++:10CB30000000AAFFAA0035353535000010000000BE ++:10CB4000000087D22D78393933330000000000000F ++:10CB500000000000000000000000000000000000D5 ++:10CB6000000000000000000010B01ABA0000000031 ++:10CB700000000000000000000000000000000000B5 ++:10CB800000000000000000000000000000000000A5 ++:10CB90000000000000000000000000000000000095 ++:10CBA0000000000000000000000000000000000085 ++:10CBB0000000000000000000000000000000000075 ++:10CBC0000000000000000000000000000000000065 ++:10CBD0000000000000000000000000000000000055 ++:10CBE0000000000000000000000000000000000045 ++:10CBF0000000000000000000000000000000000035 ++:10CC0000000000000000000000000000000800001C ++:10CC10000000000000000000000041002000FFFFB5 ++:10CC2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14 ++:10CC3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04 ++:10CC4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4 ++:10CC5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4 ++:10CC6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 ++:10CC7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4 ++:10CC8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 ++:10CC9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 ++:10CCA00000D883750C44C08800C00A0600008020AC ++:10CCB0000000000000000000000000000000000074 ++:10CCC0000000000000000000000000000000000064 ++:10CCD0000000000000000000000000000000001044 ++:10CCE0000000000000100010000000000000000024 ++:10CCF0000000000000000000000000000000000034 ++:10CD000000100000000000210010000000000000E2 ++:10CD10000000000000000002000000000000000011 ++:10CD200000110000000000030010000000000000DF ++:10CD300000000000000000000000000000000000F3 ++:10CD400000000000000000000000000000000000E3 ++:10CD500000000000000000000000000000000000D3 ++:10CD6000001000000000000000840000000000002F ++:10CD70000000000000000082000000080000000029 ++:10CD800000000000000000000000000000000000A3 ++:10CD90000000000000000000058200000500000007 ++:10CDA0000000000000000000000000000000000083 ++:10CDB0000000000000000000000000000000000073 ++:10CDC0000021002100000000000000000000000021 ++:10CDD0000000000000210000000000050008000025 ++:10CDE0000000000800000000000800000000000033 ++:10CDF0000000000000000000000300100000000020 ++:10CE00000000000000000000000000100000000012 ++:10CE1000000000000000000000000000000800000A ++:10CE200000000000000000000000000000000005FD ++:10CE3000000800080000FFFFFFFFFFFFFFFFFFFFEC ++:10CE4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:10CE5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10CE6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10CE7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:10CE8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:10CE9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:10CEA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:10CEB000FFFFFFFFFFFFFFFF00FCFEC10C44C08827 ++:10CEC00000100A06000080200000000000000000A2 ++:10CED00000000000000000100000000000820000C0 ++:10CEE0000000000000000000000000000000000042 ++:10CEF0000000000000000000000000000000000032 ++:10CF00000000000000000000000000000000000021 ++:10CF10000000000000000000000000000000000011 ++:10CF20000000000000000000000000000000000001 ++:10CF300000000000000000000000000000000000F1 ++:10CF400000000000000000000000004100000000A0 ++:10CF500000000003000000000000000000000000CE ++:10CF600000000000000000000005000000000000BC ++:10CF70000000000000080008000800000005000094 ++:10CF8000000500000000000000000000000000009C ++:10CF90000000000000000008000000210000000068 ++:10CFA0000008000000000000000000210000000058 ++:10CFB0000010000000080000002000000008000829 ++:10CFC0000008000000000000000000000000000059 ++:10CFD0000000000000000000000000000000000051 ++:10CFE0000010001000000000000000000000000021 ++:10CFF0000000000000080000000000000000000029 ++:10D000000000000000000000000000000000000020 ++:10D010000000000000000000000000000000000010 ++:10D0200000000000000200000000040000000400F6 ++:10D0300000000000004000000000000000000000B0 ++:10D040000000000000000000000000000000FFFFE2 ++:10D05000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ++:10D06000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10D07000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10D08000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 ++:10D09000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 ++:10D0A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 ++:10D0B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 ++:10D0C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 ++:10D0D00000CC1ECD0C44C08800700A06000000C3BE ++:10D0E0000000000000000000000000000000000040 ++:10D0F000010000000000002000000000000000000F ++:10D10000000000000000000000000000000000001F ++:10D11000000000000000000000000000000000000F ++:10D1200000000000000000000000000000000000FF ++:10D1300000000000000000000000000000000000EF ++:10D1400000000000000000000000000000000000DF ++:10D1500000000000000000000000000000000000CF ++:10D1600000000000000000000000000000000000BF ++:10D1700000000800000000000000000000000000A7 ++:10D18000000000000000000000000000000000009F ++:10D19000000000000000000000000000000000008F ++:10D1A000000000000500000000000000000000007A ++:10D1B000000000000300000000000000000000006C ++:10D1C000000000000000000000000000000000005F ++:10D1D000000000000000000000000000000000004F ++:10D1E00000000000FFFFFFFFFFFFFFFFFFFFFFFF4B ++:10D1F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:10D20000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:10D21000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E ++:10D22000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E ++:10D23000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE ++:10D24000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE ++:10D25000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE ++:10D26000FFFFFFFFFFFF004C448D0C44C08800D837 ++:10D270000A060000E9600000000000000000000055 ++:10D28000000000000000000000200000010000007D ++:10D29000000000000000000000000000000000008E ++:10D2A000000000000000000000000000000000007E ++:10D2B000000000000000000000000020000000004E ++:10D2C000000000000000000000000020000000003E ++:10D2D000000000000000000000000000000000004E ++:10D2E000000000000000000000000000000000003E ++:10D2F000000000000000000000000000000000002E ++:10D3000000000000000000000040000000000200DB ++:10D31000000000000000000000000000000000000D ++:10D3200000000000000000000000000000000000FD ++:10D3300000000000000000000000000000000000ED ++:10D3400002000000000000000000000000000000DB ++:10D3500002000000000000000000000000000000CB ++:10D3600000000000000000000000000000000000BD ++:10D3700000000000000000000000000000000000AD ++:10D380000000000000000000000000000000090094 ++:10D39000000000000000000000000000000000008D ++:10D3A000000000000000000000000000000000007D ++:10D3B000000000000000000000000000000000006D ++:10D3C000010000000000000000000000000000005C ++:10D3D000010000000000000000000000000000004C ++:10D3E000000000000000000000000000000000003D ++:10D3F000000000000000000000000000FFFFFFFF31 ++:10D40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10D41000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C ++:10D42000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C ++:10D43000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC ++:10D44000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC ++:10D45000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC ++:10D46000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC ++:10D47000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC ++:10D48000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC ++:10D49000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C ++:10D4A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C ++:10D4B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C ++:10D4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:10D4D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:10D4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10D4F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10D50000000000000000000000000000000000001B ++:10D51000000000000000000000000000000000000B ++:10D5200000000000000000000000000000000000FB ++:10D5300000000000000000000000000000000000EB ++:10D5400000000000000000000000000000000000DB ++:10D5500000000000000000000000000000000000CB ++:10D5600000000000000000000000000000000000BB ++:10D5700000000000000000000000000000000000AB ++:10D58000000000000000000000000000000000009B ++:10D59000000000000000000000000000000000008B ++:10D5A000000000000000000000000000000000007B ++:10D5B000000000000000000000000000000000006B ++:10D5C000000000000000000000000000000000005B ++:10D5D000000000000000000000000000000000004B ++:10D5E000000000000000000000000000000000003B ++:10D5F000000000000000000000000000000000002B ++:10D60000000000000000000000000000000000001A ++:10D61000000000000000000000000000000000000A ++:10D6200000000000000000000000000000000000FA ++:10D6300000000000000000000000000000000000EA ++:10D6400000000000000000000000000000000000DA ++:10D6500000000000000000000000000000000000CA ++:10D6600000000000000000000000000000000000BA ++:10D6700000000000000000000000000000000000AA ++:10D68000000000000000000000000000000000009A ++:10D69000000000000000000000000000000000008A ++:10D6A000000000000000000000000000000000007A ++:10D6B000000000000000000000000000000000006A ++:10D6C000000000000000000000000000000000005A ++:10D6D000000000000000000000000000000000004A ++:10D6E000000000000000000000000000000000003A ++:10D6F000000000000000000000000000000000002A ++:10D700000000000000000000000000000000000019 ++:10D710000000000000000000000000000000000009 ++:10D7200000000000000000000000000000000000F9 ++:10D7300000000000000000000000000000000000E9 ++:10D7400000000000000000000000000000000000D9 ++:10D7500000000000000000000000000000000000C9 ++:10D7600000000000000000000000000000000000B9 ++:10D7700000000000000000000000000000000000A9 ++:10D780000000000000000000000000000000000099 ++:10D790000000000000000000000000000000000089 ++:10D7A0000000000000000000000000000000000079 ++:10D7B0000000000000000000000000000000000069 ++:10D7C0000000000000000000000000000000000059 ++:10D7D0000000000000000000000000000000000049 ++:10D7E0000000000000000000000000000000000039 ++:10D7F0000000000000000000000000000000000029 ++:10D800000000000000000000000000000000000018 ++:10D810000000000000000000000000000000000008 ++:10D8200000000000000000000000000000000000F8 ++:10D8300000000000000000000000000000000000E8 ++:10D8400000000000000000000000000000000000D8 ++:10D8500000000000000000000000000000000000C8 ++:10D8600000000000000000000000000000000000B8 ++:10D8700000000000000000000000000000000000A8 ++:10D880000000000000000000000000000000000098 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000000000000078 ++:10D8B0000000000000000000000000000000000068 ++:10D8C0000000000000000000000000000000000058 ++:10D8D0000000000000000000000000000000000048 ++:10D8E0000000000000000000000000000000000038 ++:10D8F0000000000000000000000000000000000028 ++:10D900000000000000000000000000000000000017 ++:10D910000000000000000000000000000000000007 ++:10D9200000000000000000000000000000000000F7 ++:10D9300000000000000000000000000000000000E7 ++:10D9400000000000000000000000000000000000D7 ++:10D9500000000000000000000000000000000000C7 ++:10D9600000000000000000000000000000000000B7 ++:10D9700000000000000000000000000000000000A7 ++:10D980000000000000000000000000000000000097 ++:10D990000000000000000000000000000000000087 ++:10D9A0000000000000000000000000000000000077 ++:10D9B0000000000000000000000000000000000067 ++:10D9C0000000000000000000000000000000000057 ++:10D9D0000000000000000000000000000000000047 ++:10D9E0000000000000000000000000000000000037 ++:10D9F0000000000000000000000000000000000027 ++:10DA00000000000000000000000000000000000016 ++:10DA10000000000000000000000000000000000006 ++:10DA200000000000000000000000000000000000F6 ++:10DA300000000000000000000000000000000000E6 ++:10DA400000000000000000000000000000000000D6 ++:10DA500000000000000000000000000000000000C6 ++:10DA600000000000000000000000000000000000B6 ++:10DA700000000000000000000000000000000000A6 ++:10DA80000000000000000000000000000000000096 ++:10DA90000000000000000000000000000000000086 ++:10DAA0000000000000000000000000000000000076 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000000000000000000000000000000056 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000000000000000000000000000000000015 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000000000F5 ++:10DB300000000000000000000000000000000000E5 ++:10DB400000000000000000000000000000000000D5 ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB700000000000000000000000000000000000A5 ++:10DB80000000000000000000000000000000000095 ++:10DB90000000000000000000000000000000000085 ++:10DBA0000000000000000000000000000000000075 ++:10DBB0000000000000000000000000000000000065 ++:10DBC0000000000000000000000000000000000055 ++:10DBD0000000000000000000000000000000000045 ++:10DBE0000000000000000000000000000000000035 ++:10DBF0000000000000000000000000000000000025 ++:10DC00000000000000000000000000000000000014 ++:10DC10000000000000000000000000000000000004 ++:10DC200000000000000000000000000000000000F4 ++:10DC300000000000000000000000000000000000E4 ++:10DC400000000000000000000000000000000000D4 ++:10DC500000000000000000000000000000000000C4 ++:10DC600000000000000000000000000000000000B4 ++:10DC700000000000000000000000000000000000A4 ++:10DC80000000000000000000000000000000000094 ++:10DC90000000000000000000000000000000000084 ++:10DCA0000000000000000000000000000000000074 ++:10DCB0000000000000000000000000000000000064 ++:10DCC0000000000000000000000000000000000054 ++:10DCD0000000000000000000000000000000000044 ++:10DCE0000000000000000000000000000000000034 ++:10DCF0000000000000000000000000000000000024 ++:10DD00000000000000000000000000000000000013 ++:10DD10000000000000000000000000000000000003 ++:10DD200000000000000000000000000000000000F3 ++:10DD300000000000000000000000000000000000E3 ++:10DD400000000000000000000000000000000000D3 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000000000000000B3 ++:10DD700000000000000000000000000000000000A3 ++:10DD80000000000000000000000000000000000093 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000000000073 ++:10DDB0000000000000000000000000000000000063 ++:10DDC0000000000000000000000000000000000053 ++:10DDD0000000000000000000000000000000000043 ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000000000000000000000000012 ++:10DE10000000000000000000000000000000000002 ++:10DE200000000000000000000000000000000000F2 ++:10DE300000000000000000000000000000000000E2 ++:10DE400000000000000000000000000000000000D2 ++:10DE500000000000000000000000000000000000C2 ++:10DE600000000000000000000000000000000000B2 ++:10DE700000000000000000000000000000000000A2 ++:10DE80000000000000000000000000000000000092 ++:10DE90000000000000000000000000000000000082 ++:10DEA0000000000000000000000000000000000072 ++:10DEB0000000000000000000000000000000000062 ++:10DEC0000000000000000000000000000000000052 ++:10DED0000000000000000000000000000000000042 ++:10DEE0000000000000000000000000000000000032 ++:10DEF0000000000000000000000000000000000022 ++:10DF00000000000000000000000000000000000011 ++:10DF10000000000000000000000000000000000001 ++:10DF200000000000000000000000000000000000F1 ++:10DF300000000000000000000000000000000000E1 ++:10DF400000000000000000000000000000000000D1 ++:10DF500000000000000000000000000000000000C1 ++:10DF600000000000000000000000000000000000B1 ++:10DF700000000000000000000000000000000000A1 ++:10DF80000000000000000000000000000000000091 ++:10DF90000000000000000000000000000000000081 ++:10DFA0000000000000000000000000000000000071 ++:10DFB0000000000000000000000000000000000061 ++:10DFC0000000000000000000000000000000000051 ++:10DFD0000000000000000000000000000000000041 ++:10DFE0000000000000000000000000000000000031 ++:10DFF0000000000000000000000000000000000021 ++:10E000000000000000000000000000000000000010 ++:10E010000000000000000000000000000000000000 ++:10E0200000000000000000000000000000000000F0 ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E0500000000000000000000000000000000000C0 ++:10E0600000000000000000000000000000000000B0 ++:10E0700000000000000000000000000000000000A0 ++:10E080000000000000000000000000000000000090 ++:10E090000000000000000000000000000000000080 ++:10E0A0000000000000000000000000000000000070 ++:10E0B0000000000000000000000000000000000060 ++:10E0C0000000000000000000000000000000000050 ++:10E0D0000000000000000000000000000000000040 ++:10E0E0000000000000000000000000000000000030 ++:10E0F0000000000000000000000000000000000020 ++:10E10000000000000000000000000000000000000F ++:10E1100000000000000000000000000000000000FF ++:10E1200000000000000000000000000000000000EF ++:10E1300000000000000000000000000000000000DF ++:10E1400000000000000000000000000000000000CF ++:10E1500000000000000000000000000000000000BF ++:10E1600000000000000000000000000000000000AF ++:10E17000000000000000000000000000000000009F ++:10E18000000000000000000000000000000000008F ++:10E19000000000000000000000000000000000007F ++:10E1A000000000000000000000000000000000006F ++:10E1B000000000000000000000000000000000005F ++:10E1C000000000000000000000000000000000004F ++:10E1D000000000000000000000000000000000003F ++:10E1E000000000000000000000000000000000002F ++:10E1F000000000000000000000000000000000001F ++:10E20000000000000000000000000000000000000E ++:10E2100000000000000000000000000000000000FE ++:10E2200000000000000000000000000000000000EE ++:10E2300000000000000000000000000000000000DE ++:10E2400000000000000000000000000000000000CE ++:10E2500000000000000000000000000000000000BE ++:10E2600000000000000000000000000000000000AE ++:10E27000000000000000000000000000000000009E ++:10E28000000000000000000000000000000000008E ++:10E29000000000000000000000000000000000007E ++:10E2A000000000000000000000000000000000006E ++:10E2B000000000000000000000000000000000005E ++:10E2C000000000000000000000000000000000004E ++:10E2D000000000000000000000000000000000003E ++:10E2E000000000000000000000000000000000002E ++:10E2F000000000000000000000000000000000001E ++:10E30000000000000000000000000000000000000D ++:10E3100000000000000000000000000000000000FD ++:10E3200000000000000000000000000000000000ED ++:10E3300000000000000000000000000000000000DD ++:10E3400000000000000000000000000000000000CD ++:10E3500000000000000000000000000000000000BD ++:10E3600000000000000000000000000000000000AD ++:10E37000000000000000000000000000000000009D ++:10E38000000000000000000000000000000000008D ++:10E39000000000000000000000000000000000007D ++:10E3A000000000000000000000000000000000006D ++:10E3B000000000000000000000000000000000005D ++:10E3C000000000000000000000000000000000004D ++:10E3D000000000000000000000000000000000003D ++:10E3E000000000000000000000000000000000002D ++:10E3F000000000000000000000000000000000001D ++:10E40000000000000000000000000000000000000C ++:10E4100000000000000000000000000000000000FC ++:10E4200000000000000000000000000000000000EC ++:10E4300000000000000000000000000000000000DC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000000000000000000000000000000000009C ++:10E48000000000000000000000000000000000008C ++:10E49000000000000000000000000000000000007C ++:10E4A000000000000000000000000000000000006C ++:10E4B000000000000000000000000000000000005C ++:10E4C000000000000000000000000000000000004C ++:10E4D000000000000000000000000000000000003C ++:10E4E000000000000000000000000000000000002C ++:10E4F000000000000000000000000000000000001C ++:10E50000000000000000000000000000000000000B ++:10E5100000000000000000000000000000000000FB ++:10E5200000000000000000000000000000000000EB ++:10E5300000000000000000000000000000000000DB ++:10E5400000000000000000000000000000000000CB ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000000000000000008B ++:10E59000000000000000000000000000000000007B ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000000000000000000000000000000000001B ++:10E60000000000000000000000000000000000000A ++:10E6100000000000000000000000000000000000FA ++:10E6200000000000000000000000000000000000EA ++:10E6300000000000000000000000000000000000DA ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E6600000000000000000000000000000000000AA ++:10E67000000000000000000000000000000000009A ++:10E68000000000000000000000000000000000008A ++:10E69000000000000000000000000000000000007A ++:10E6A000000000000000000000000000000000006A ++:10E6B000000000000000000000000000000000005A ++:10E6C000000000000000000000000000000000004A ++:10E6D000000000000000000000000000000000003A ++:10E6E000000000000000000000000000000000002A ++:10E6F000000000000000000000000000000000001A ++:10E700000000000000000000000000000000000009 ++:10E7100000000000000000000000000000000000F9 ++:10E7200000000000000000000000000000000000E9 ++:10E7300000000000000000000000000000000000D9 ++:10E7400000000000000000000000000000000000C9 ++:10E7500000000000000000000000000000000000B9 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000000000000099 ++:10E780000000000000000000000000000000000089 ++:10E790000000000000000000000000000000000079 ++:10E7A0000000000000000000000000000000000069 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000000039 ++:10E7E0000000000000000000000000000000000029 ++:10E7F0000000000000000000000000000000000019 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000000000000000000000000000F8 ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000000000000000000000000000000D8 ++:10E8400000000000000000000000000000000000C8 ++:10E8500000000000000000000000000000000000B8 ++:10E8600000000000000000000000000000000000A8 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000000000000000000018 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000000000000000000000000000000D7 ++:10E9400000000000000000000000000000000000C7 ++:10E9500000000000000000000000000000000000B7 ++:10E9600000000000000000000000000000000000A7 ++:10E970000000000000000000000000000000000097 ++:10E980000000000000000000000000000000000087 ++:10E990000000000000000000000000000000000077 ++:10E9A0000000000000000000000000000000000067 ++:10E9B0000000000000000000000000000000000057 ++:10E9C0000000000000000000000000000000000047 ++:10E9D0000000000000000000000000000000000037 ++:10E9E0000000000000000000000000000000000027 ++:10E9F0000000000000000000000000000000000017 ++:10EA00000000000000000000000000000000000006 ++:10EA100000000000000000000000000000000000F6 ++:10EA200000000000000000000000000000000000E6 ++:10EA300000000000000000000000000000000000D6 ++:10EA400000000000000000000000000000000000C6 ++:10EA500000000000000000000000000000000000B6 ++:10EA600000000000000000000000000000000000A6 ++:10EA70000000000000000000000000000000000096 ++:10EA80000000000000000000000000000000000086 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000000000000000056 ++:10EAC0000000000000000000000000000000000046 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB300000000000000000000000000000000000D5 ++:10EB400000000000000000000000000000000000C5 ++:10EB500000000000000000000000000000000000B5 ++:10EB600000000000000000000000000000000000A5 ++:10EB70000000000000000000000000000000000095 ++:10EB80000000000000000000000000000000000085 ++:10EB90000000000000000000000000000000000075 ++:10EBA0000000000000000000000000000000000065 ++:10EBB0000000000000000000000000000000000055 ++:10EBC0000000000000000000000000000000000045 ++:10EBD0000000000000000000000000000000000035 ++:10EBE0000000000000000000000000000000000025 ++:10EBF0000000000000000000000000000000000015 ++:10EC00000000000000000000000000000000000004 ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC80000000000000000000000000000000000084 ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000000000000000000000000000000064 ++:10ECB0000000000000000000000000000000000054 ++:10ECC0000000000000000000000000000000000044 ++:10ECD0000000000000000000000000000000000034 ++:10ECE0000000000000000000000000000000000024 ++:10ECF0000000000000000000000000000000000014 ++:10ED00000000000000000000000000000000000003 ++:10ED100000000000000000000000000000000000F3 ++:10ED200000000000000000000000000000000000E3 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA0000000000000000000000000000000000063 ++:10EDB0000000000000000000000000000000000053 ++:10EDC0000000000000000000000000000000000043 ++:10EDD0000000000000000000000000000000000033 ++:10EDE0000000000000000000000000000000000023 ++:10EDF0000000000000000000000000000000000013 ++:10EE00000000000000000000000000000000000002 ++:10EE100000000000000000000000000000000000F2 ++:10EE200000000000000000000000000000000000E2 ++:10EE300000000000000000000000000000000000D2 ++:10EE400000000000000000000000000000000000C2 ++:10EE500000000000000000000000000000000000B2 ++:10EE600000000000000000000000000000000000A2 ++:10EE70000000000000000000000000000000000092 ++:10EE80000000000000000000000000000000000082 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000000000022 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000000000000000000000000000000001 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF600000000000000000000000000000000000A1 ++:10EF70000000000000000000000000000000000091 ++:10EF80000000000000000000000000000000000081 ++:10EF90000000000000000000000000000000000071 ++:10EFA0000000000000000000000000000000000061 ++:10EFB0000000000000000000000000000000000051 ++:10EFC0000000000000000000000000000000000041 ++:10EFD0000000000000000000000000000000000031 ++:10EFE0000000000000000000000000000000000021 ++:10EFF0000000000000000000000000000000000011 ++:10F000000000000000000000000000000000000000 ++:10F0100000000000000000000000000000000000F0 ++:10F0200000000000000000000000000000000000E0 ++:10F0300000000000000000000000000000000000D0 ++:10F0400000000000000000000000000000000000C0 ++:10F0500000000000000000000000000000000000B0 ++:10F0600000000000000000000000000000000000A0 ++:10F070000000000000000000000000000000000090 ++:10F080000000000000000000000000000000000080 ++:10F090000000000000000000000000000000000070 ++:10F0A0000000000000000000000000000000000060 ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D0000000000000000000000000000000000030 ++:10F0E0000000000000000000000000000000000020 ++:10F0F0000000000000000000000000000000000010 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000000AF ++:10F16000000000000000000000000000000000009F ++:10F17000000000000000000000000000000000008F ++:10F18000000000000000000000000000000000007F ++:10F19000000000000000000000000000000000006F ++:10F1A000000000000000000000000000000000005F ++:10F1B000000000000000000000000000000000004F ++:10F1C000000000000000000000000000000000003F ++:10F1D000000000000000000000000000000000002F ++:10F1E000000000000000000000000000000000001F ++:10F1F000000000000000000000000000000000000F ++:10F2000000000000000000000000000000000000FE ++:10F2100000000000000000000000000000000000EE ++:10F2200000000000000000000000000000000000DE ++:10F2300000000000000000000000000000000000CE ++:10F2400000000000000000000000000000000000BE ++:10F2500000000000000000000000000000000000AE ++:10F26000000000000000000000000000000000009E ++:10F27000000000000000000000000000000000008E ++:10F28000000000000000000000000000000000007E ++:10F29000000000000000000000000000000000006E ++:10F2A000000000000000000000000000000000005E ++:10F2B000000000000000000000000000000000004E ++:10F2C000000000000000000000000000000000003E ++:10F2D000000000000000000000000000000000002E ++:10F2E000000000000000000000000000000000001E ++:10F2F000000000000000000000000000000000000E ++:10F3000000000000000000000000000000000000FD ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000000000000CD ++:10F3400000000000000000000000000000000000BD ++:10F3500000000000000000000000000000000000AD ++:10F36000000000000000000000000000000000009D ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000000000004D ++:10F3C000000000000000000000000000000000003D ++:10F3D000000000000000000000000000000000002D ++:10F3E000000000000000000000000000000000001D ++:10F3F000000000000000000000000000000000000D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F4400000000000000000000000000000000000BC ++:10F4500000000000000000000000000000000000AC ++:10F46000000000000000000000000000000000009C ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000000000000000003C ++:10F4D000000000000000000000000000000000002C ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000000000000000EB ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000000000000000000000000000007B ++:10F59000000000000000000000000000000000006B ++:10F5A000000000000000000000000000000000005B ++:10F5B000000000000000000000000000000000004B ++:10F5C000000000000000000000000000000000003B ++:10F5D000000000000000000000000000000000002B ++:10F5E000000000000000000000000000000000001B ++:10F5F000000000000000000000000000000000000B ++:10F6000000000000000000000000000000000000FA ++:10F6100000000000000000000000000000000000EA ++:10F6200000000000000000000000000000000000DA ++:10F6300000000000000000000000000000000000CA ++:10F6400000000000000000000000000000000000BA ++:10F6500000000000000000000000000000000000AA ++:10F66000000000000000000000000000000000009A ++:10F67000000000000000000000000000000000008A ++:10F68000000000000000000000000000000000007A ++:10F69000000000000000000000000000000000006A ++:10F6A000000000000000000000000000000000005A ++:10F6B000000000000000000000000000000000004A ++:10F6C000000000000000000000000000000000003A ++:10F6D000000000000000000000000000000000002A ++:10F6E000000000000000000000000000000000001A ++:10F6F000000000000000000000000000000000000A ++:10F7000000000000000000000000000000000000F9 ++:10F7100000000000000000000000000000000000E9 ++:10F7200000000000000000000000000000000000D9 ++:10F7300000000000000000000000000000000000C9 ++:10F7400000000000000000000000000000000000B9 ++:10F7500000000000000000000000000000000000A9 ++:10F760000000000000000000000000000000000099 ++:10F770000000000000000000000000000000000089 ++:10F780000000000000000000000000000000000079 ++:10F790000000000000000000000000000000000069 ++:10F7A0000000000000000000000000000000000059 ++:10F7B0000000000000000000000000000000000049 ++:10F7C0000000000000000000000000000000000039 ++:10F7D0000000000000000000000000000000000029 ++:10F7E0000000000000000000000000000000000019 ++:10F7F0000000000000000000000000000000000009 ++:10F8000000000000000000000000000000000000F8 ++:10F8100000000000000000000000000000000000E8 ++:10F8200000000000000000000000000000000000D8 ++:10F8300000000000000000000000000000000000C8 ++:10F8400000000000000000000000000000000000B8 ++:10F8500000000000000000000000000000000000A8 ++:10F860000000000000000000000000000000000098 ++:10F870000000000000000000000000000000000088 ++:10F880000000000000000000000000000000000078 ++:10F890000000000000000000000000000000000068 ++:10F8A0000000000000000000000000000000000058 ++:10F8B0000000000000000000000000000000000048 ++:10F8C0000000000000000000000000000000000038 ++:10F8D0000000000000000000000000000000000028 ++:10F8E0000000000000000000000000000000000018 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000000000000000F7 ++:10F9100000000000000000000000000000000000E7 ++:10F9200000000000000000000000000000000000D7 ++:10F9300000000000000000000000000000000000C7 ++:10F9400000000000000000000000000000000000B7 ++:10F9500000000000000000000000000000000000A7 ++:10F960000000000000000000000000000000000097 ++:10F970000000000000000000000000000000000087 ++:10F980000000000000000000000000000000000077 ++:10F990000000000000000000000000000000000067 ++:10F9A0000000000000000000000000000000000057 ++:10F9B0000000000000000000000000000000000047 ++:10F9C0000000000000000000000000000000000037 ++:10F9D0000000000000000000000000000000000027 ++:10F9E0000000000000000000000000000000000017 ++:10F9F0000000000000000000000000000000000007 ++:10FA000000000000000000000000000000000000F6 ++:10FA100000000000000000000000000000000000E6 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000000000000000000C6 ++:10FA400000000000000000000000000000000000B6 ++:10FA500000000000000000000000000000000000A6 ++:10FA60000000000000000000000000000000000096 ++:10FA70000000000000000000000000000000000086 ++:10FA80000000000000000000000000000000000076 ++:10FA90000000000000000000000000000000000066 ++:10FAA0000000000000000000000000000000000056 ++:10FAB0000000000000000000000000000000000046 ++:10FAC0000000000000000000000000000000000036 ++:10FAD0000000000000000000000000000000000026 ++:10FAE0000000000000000000000000000000000016 ++:10FAF0000000000000000000000000000000000006 ++:10FB000000000000000000000000000000000000F5 ++:10FB100000000000000000000000000000000000E5 ++:10FB200000000000000000000000000000000000D5 ++:10FB300000000000000000000000000000000000C5 ++:10FB400000000000000000000000000000000000B5 ++:10FB500000000000000000000000000000000000A5 ++:10FB60000000000000000000000000000000000095 ++:10FB70000000000000000000000000000000000085 ++:10FB80000000000000000000000000000000000075 ++:10FB90000000000000000000000000000000000065 ++:10FBA0000000000000000000000000000000000055 ++:10FBB0000000000000000000000000000000000045 ++:10FBC0000000000000000000000000000000000035 ++:10FBD0000000000000000000000000000000000025 ++:10FBE0000000000000000000000000000000000015 ++:10FBF0000000000000000000000000000000000005 ++:10FC000000000000000000000000000000000000F4 ++:10FC100000000000000000000000000000000000E4 ++:10FC200000000000000000000000000000000000D4 ++:10FC300000000000000000000000000000000000C4 ++:10FC400000000000000000000000000000000000B4 ++:10FC500000000000000000000000000000000000A4 ++:10FC60000000000000000000000000000000000094 ++:10FC70000000000000000000000000000000000084 ++:10FC80000000000000000000000000000000000074 ++:10FC90000000000000000000000000000000000064 ++:10FCA0000000000000000000000000000000000054 ++:10FCB0000000000000000000000000000000000044 ++:10FCC0000000000000000000000000000000000034 ++:10FCD0000000000000000000000000000000000024 ++:10FCE0000000000000000000000000000000000014 ++:10FCF0000000000000000000000000000000000004 ++:10FD000000000000000000000000000000000000F3 ++:10FD100000000000000000000000000000000000E3 ++:10FD200000000000000000000000000000000000D3 ++:10FD300000000000000000000000000000000000C3 ++:10FD400000000000000000000000000000000000B3 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000000000000000000000000000000000093 ++:10FD70000000000000000000000000000000000083 ++:10FD80000000000000000000000000000000000073 ++:10FD90000000000000000000000000000000000063 ++:10FDA0000000000000000000000000000000000053 ++:10FDB0000000000000000000000000000000000043 ++:10FDC0000000000000000000000000000000000033 ++:10FDD0000000000000000000000000000000000023 ++:10FDE0000000000000000000000000000000000013 ++:10FDF0000000000000000000000000000000000003 ++:10FE000000000000000000000000000000000000F2 ++:10FE100000000000000000000000000000000000E2 ++:10FE200000000000000000000000000000000000D2 ++:10FE300000000000000000000000000000000000C2 ++:10FE400000000000000000000000000000000000B2 ++:10FE500000000000000000000000000000000000A2 ++:10FE60000000000000000000000000000000000092 ++:10FE70000000000000000000000000000000000082 ++:10FE80000000000000000000000000000000000072 ++:10FE90000000000000000000000000000000000062 ++:10FEA0000000000000000000000000000000000052 ++:10FEB0000000000000000000000000000000000042 ++:10FEC0000000000000000000000000000000000032 ++:10FED0000000000000000000000000000000000022 ++:10FEE0000000000000000000000000000000000012 ++:10FEF0000000000000000000000000000000000002 ++:10FF000000000000000000000000000000000000F1 ++:10FF100000000000000000000000000000000000E1 ++:10FF200000000000000000000000000000000000D1 ++:10FF300000000000000000000000000000000000C1 ++:10FF400000000000000000000000000000000000B1 ++:10FF500000000000000000000000000000000000A1 ++:10FF60000000000000000000000000000000000091 ++:10FF70000000000000000000000000000000000081 ++:10FF80000000000000000000000000000000000071 ++:10FF90000000000000000000000000000000000061 ++:10FFA0000000000000000000000000000000000051 ++:10FFB0000000000000000000000000000000000041 ++:10FFC0000000000000000000000000000000000031 ++:10FFD0000000000000000000000000000000000021 ++:10FFE0000000000000000000000000000000000011 ++:10FFF0000000000000000000000000000000000001 ++:020000040004F6 ++:1000000000000000000000000000000000000000F0 ++:1000100000000000000000000000000000000000E0 ++:1000200000000000000000000000000000000000D0 ++:1000300000000000000000000000000000000000C0 ++:1000400000000000000000000000000000000000B0 ++:1000500000000000000000000000000000000000A0 ++:100060000000000000000000000000000000000090 ++:100070000000000000000000000000000000000080 ++:100080000000000000000000000000000000000070 ++:100090000000000000000000000000000000000060 ++:1000A0000000000000000000000000000000000050 ++:1000B0000000000000000000000000000000000040 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000000000000000000000000000020 ++:1000E0000000000000000000000000000000000010 ++:1000F0000000000000000000000000000000000000 ++:1001000000000000000000000000000000000000EF ++:1001100000000000000000000000000000000000DF ++:1001200000000000000000000000000000000000CF ++:1001300000000000000000000000000000000000BF ++:1001400000000000000000000000000000000000AF ++:10015000000000000000000000000000000000009F ++:10016000000000000000000000000000000000008F ++:10017000000000000000000000000000000000007F ++:10018000000000000000000000000000000000006F ++:10019000000000000000000000000000000000005F ++:1001A000000000000000000000000000000000004F ++:1001B000000000000000000000000000000000003F ++:1001C000000000000000000000000000000000002F ++:1001D000000000000000000000000000000000001F ++:1001E000000000000000000000000000000000000F ++:1001F00000000000000000000000000000000000FF ++:1002000000000000000000000000000000000000EE ++:1002100000000000000000000000000000000000DE ++:1002200000000000000000000000000000000000CE ++:1002300000000000000000000000000000000000BE ++:1002400000000000000000000000000000000000AE ++:10025000000000000000000000000000000000009E ++:10026000000000000000000000000000000000008E ++:10027000000000000000000000000000000000007E ++:10028000000000000000000000000000000000006E ++:10029000000000000000000000000000000000005E ++:1002A000000000000000000000000000000000004E ++:1002B000000000000000000000000000000000003E ++:1002C000000000000000000000000000000000002E ++:1002D000000000000000000000000000000000001E ++:1002E000000000000000000000000000000000000E ++:1002F00000000000000000000000000000000000FE ++:1003000000000000000000000000000000000000ED ++:1003100000000000000000000000000000000000DD ++:1003200000000000000000000000000000000000CD ++:1003300000000000000000000000000000000000BD ++:1003400000000000000000000000000000000000AD ++:10035000000000000000000000000000000000009D ++:10036000000000000000000000000000000000008D ++:10037000000000000000000000000000000000007D ++:10038000000000000000000000000000000000006D ++:10039000000000000000000000000000000000005D ++:1003A000000000000000000000000000000000004D ++:1003B000000000000000000000000000000000003D ++:1003C000000000000000000000000000000000002D ++:1003D000000000000000000000000000000000001D ++:1003E000000000000000000000000000000000000D ++:1003F00000000000000000000000000000000000FD ++:1004000000000000000000000000000000000000EC ++:1004100000000000000000000000000000000000DC ++:1004200000000000000000000000000000000000CC ++:1004300000000000000000000000000000000000BC ++:1004400000000000000000000000000000000000AC ++:10045000000000000000000000000000000000009C ++:10046000000000000000000000000000000000008C ++:10047000000000000000000000000000000000007C ++:10048000000000000000000000000000000000006C ++:10049000000000000000000000000000000000005C ++:1004A000000000000000000000000000000000004C ++:1004B000000000000000000000000000000000003C ++:1004C000000000000000000000000000000000002C ++:1004D000000000000000000000000000000000001C ++:1004E000000000000000000000000000000000000C ++:1004F00000000000000000000000000000000000FC ++:1005000000000000000000000000000000000000EB ++:1005100000000000000000000000000000000000DB ++:1005200000000000000000000000000000000000CB ++:1005300000000000000000000000000000000000BB ++:1005400000000000000000000000000000000000AB ++:10055000000000000000000000000000000000009B ++:10056000000000000000000000000000000000008B ++:10057000000000000000000000000000000000007B ++:10058000000000000000000000000000000000006B ++:10059000000000000000000000000000000000005B ++:1005A000000000000000000000000000000000004B ++:1005B000000000000000000000000000000000003B ++:1005C000000000000000000000000000000000002B ++:1005D000000000000000000000000000000000001B ++:1005E000000000000000000000000000000000000B ++:1005F00000000000000000000000000000000000FB ++:1006000000000000000000000000000000000000EA ++:1006100000000000000000000000000000000000DA ++:1006200000000000000000000000000000000000CA ++:1006300000000000000000000000000000000000BA ++:1006400000000000000000000000000000000000AA ++:10065000000000000000000000000000000000009A ++:10066000000000000000000000000000000000008A ++:10067000000000000000000000000000000000007A ++:10068000000000000000000000000000000000006A ++:10069000000000000000000000000000000000005A ++:1006A000000000000000000000000000000000004A ++:1006B000000000000000000000000000000000003A ++:1006C000000000000000000000000000000000002A ++:1006D000000000000000000000000000000000001A ++:1006E000000000000000000000000000000000000A ++:1006F00000000000000000000000000000000000FA ++:1007000000000000000000000000000000000000E9 ++:1007100000000000000000000000000000000000D9 ++:1007200000000000000000000000000000000000C9 ++:1007300000000000000000000000000000000000B9 ++:1007400000000000000000000000000000000000A9 ++:100750000000000000000000000000000000000099 ++:100760000000000000000000000000000000000089 ++:100770000000000000000000000000000000000079 ++:100780000000000000000000000000000000000069 ++:100790000000000000000000000000000000000059 ++:1007A0000000000000000000000000000000000049 ++:1007B0000000000000000000000000000000000039 ++:1007C0000000000000000000000000000000000029 ++:1007D0000000000000000000000000000000000019 ++:1007E0000000000000000000000000000000000009 ++:1007F00000000000000000000000000000000000F9 ++:1008000000000000000000000000000000000000E8 ++:1008100000000000000000000000000000000000D8 ++:1008200000000000000000000000000000000000C8 ++:1008300000000000000000000000000000000000B8 ++:1008400000000000000000000000000000000000A8 ++:100850000000000000000000000000000000000098 ++:100860000000000000000000000000000000000088 ++:100870000000000000000000000000000000000078 ++:100880000000000000000000000000000000000068 ++:100890000000000000000000000000000000000058 ++:1008A0000000000000000000000000000000000048 ++:1008B0000000000000000000000000000000000038 ++:1008C0000000000000000000000000000000000028 ++:1008D0000000000000000000000000000000000018 ++:1008E0000000000000000000000000000000000008 ++:1008F00000000000000000000000000000000000F8 ++:1009000000000000000000000000000000000000E7 ++:1009100000000000000000000000000000000000D7 ++:1009200000000000000000000000000000000000C7 ++:1009300000000000000000000000000000000000B7 ++:1009400000000000000000000000000000000000A7 ++:100950000000000000000000000000000000000097 ++:100960000000000000000000000000000000000087 ++:100970000000000000000000000000000000000077 ++:100980000000000000000000000000000000000067 ++:100990000000000000000000000000000000000057 ++:1009A0000000000000000000000000000000000047 ++:1009B0000000000000000000000000000000000037 ++:1009C0000000000000000000000000000000000027 ++:1009D0000000000000000000000000000000000017 ++:1009E0000000000000000000000000000000000007 ++:1009F00000000000000000000000000000000000F7 ++:100A000000000000000000000000000000000000E6 ++:100A100000000000000000000000000000000000D6 ++:100A200000000000000000000000000000000000C6 ++:100A300000000000000000000000000000000000B6 ++:100A400000000000000000000000000000000000A6 ++:100A50000000000000000000000000000000000096 ++:100A60000000000000000000000000000000000086 ++:100A70000000000000000000000000000000000076 ++:100A80000000000000000000000000000000000066 ++:100A90000000000000000000000000000000000056 ++:100AA0000000000000000000000000000000000046 ++:100AB0000000000000000000000000000000000036 ++:100AC0000000000000000000000000000000000026 ++:100AD0000000000000000000000000000000000016 ++:100AE0000000000000000000000000000000000006 ++:100AF00000000000000000000000000000000000F6 ++:100B000000000000000000000000000000000000E5 ++:100B100000000000000000000000000000000000D5 ++:100B200000000000000000000000000000000000C5 ++:100B300000000000000000000000000000000000B5 ++:100B400000000000000000000000000000000000A5 ++:100B50000000000000000000000000000000000095 ++:100B60000000000000000000000000000000000085 ++:100B70000000000000000000000000000000000075 ++:100B80000000000000000000000000000000000065 ++:100B90000000000000000000000000000000000055 ++:100BA0000000000000000000000000000000000045 ++:100BB0000000000000000000000000000000000035 ++:100BC0000000000000000000000000000000000025 ++:100BD0000000000000000000000000000000000015 ++:100BE0000000000000000000000000000000000005 ++:100BF00000000000000000000000000000000000F5 ++:100C000000000000000000000000000000000000E4 ++:100C100000000000000000000000000000000000D4 ++:100C200000000000000000000000000000000000C4 ++:100C300000000000000000000000000000000000B4 ++:100C400000000000000000000000000000000000A4 ++:100C50000000000000000000000000000000000094 ++:100C60000000000000000000000000000000000084 ++:100C70000000000000000000000000000000000074 ++:100C80000000000000000000000000000000000064 ++:100C90000000000000000000000000000000000054 ++:100CA0000000000000000000000000000000000044 ++:100CB0000000000000000000000000000000000034 ++:100CC0000000000000000000000000000000000024 ++:100CD0000000000000000000000000000000000014 ++:100CE0000000000000000000000000000000000004 ++:100CF00000000000000000000000000000000000F4 ++:100D000000000000000000000000000000000000E3 ++:100D100000000000000000000000000000000000D3 ++:100D200000000000000000000000000000000000C3 ++:100D300000000000000000000000000000000000B3 ++:100D400000000000000000000000000000000000A3 ++:100D50000000000000000000000000000000000093 ++:100D60000000000000000000000000000000000083 ++:100D70000000000000000000000000000000000073 ++:100D80000000000000000000000000000000000063 ++:100D90000000000000000000000000000000000053 ++:100DA0000000000000000000000000000000000043 ++:100DB0000000000000000000000000000000000033 ++:100DC0000000000000000000000000000000000023 ++:100DD0000000000000000000000000000000000013 ++:100DE0000000000000000000000000000000000003 ++:100DF00000000000000000000000000000000000F3 ++:100E000000000000000000000000000000000000E2 ++:100E100000000000000000000000000000000000D2 ++:100E200000000000000000000000000000000000C2 ++:100E300000000000000000000000000000000000B2 ++:100E400000000000000000000000000000000000A2 ++:100E50000000000000000000000000000000000092 ++:100E60000000000000000000000000000000000082 ++:100E70000000000000000000000000000000000072 ++:100E80000000000000000000000000000000000062 ++:100E90000000000000000000000000000000000052 ++:100EA0000000000000000000000000000000000042 ++:100EB0000000000000000000000000000000000032 ++:100EC0000000000000000000000000000000000022 ++:100ED0000000000000000000000000000000000012 ++:100EE0000000000000000000000000000000000002 ++:100EF00000000000000000000000000000000000F2 ++:100F000000000000000000000000000000000000E1 ++:100F100000000000000000000000000000000000D1 ++:100F200000000000000000000000000000000000C1 ++:100F300000000000000000000000000000000000B1 ++:100F400000000000000000000000000000000000A1 ++:100F50000000000000000000000000000000000091 ++:100F60000000000000000000000000000000000081 ++:100F70000000000000000000000000000000000071 ++:100F80000000000000000000000000000000000061 ++:100F90000000000000000000000000000000000051 ++:100FA0000000000000000000000000000000000041 ++:100FB0000000000000000000000000000000000031 ++:100FC0000000000000000000000000000000000021 ++:100FD0000000000000000000000000000000000011 ++:100FE0000000000000000000000000000000000001 ++:100FF00000000000000000000000000000000000F1 ++:1010000000000000000000000000000000000000E0 ++:1010100000000000000000000000000000000000D0 ++:1010200000000000000000000000000000000000C0 ++:1010300000000000000000000000000000000000B0 ++:1010400000000000000000000000000000000000A0 ++:101050000000000000000000000000000000000090 ++:101060000000000000000000000000000000000080 ++:101070000000000000000000000000000000000070 ++:101080000000000000000000000000000000000060 ++:101090000000000000000000000000000000000050 ++:1010A0000000000000000000000000000000000040 ++:1010B0000000000000000000000000000000000030 ++:1010C0000000000000000000000000000000000020 ++:1010D0000000000000000000000000000000000010 ++:1010E0000000000000000000000000000000000000 ++:1010F00000000000000000000000000000000000F0 ++:1011000000000000000000000000000000000000DF ++:1011100000000000000000000000000000000000CF ++:1011200000000000000000000000000000000000BF ++:1011300000000000000000000000000000000000AF ++:10114000000000000000000000000000000000009F ++:10115000000000000000000000000000000000008F ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:10118000000000000000000000000000000000005F ++:10119000000000000000000000000000000000004F ++:1011A000000000000000000000000000000000003F ++:1011B000000000000000000000000000000000002F ++:1011C000000000000000000000000000000000001F ++:1011D000000000000000000000000000000000000F ++:1011E00000000000000000000000000000000000FF ++:1011F00000000000000000000000000000000000EF ++:1012000000000000000000000000000000000000DE ++:1012100000000000000000000000000000000000CE ++:1012200000000000000000000000000000000000BE ++:1012300000000000000000000000000000000000AE ++:10124000000000000000000000000000000000009E ++:10125000000000000000000000000000000000008E ++:10126000000000000000000000000000000000007E ++:10127000000000000000000000000000000000006E ++:10128000000000000000000000000000000000005E ++:10129000000000000000000000000000000000004E ++:1012A000000000000000000000000000000000003E ++:1012B000000000000000000000000000000000002E ++:1012C000000000000000000000000000000000001E ++:1012D000000000000000000000000000000000000E ++:1012E00000000000000000000000000000000000FE ++:1012F00000000000000000000000000000000000EE ++:1013000000000000000000000000000000000000DD ++:1013100000000000000000000000000000000000CD ++:1013200000000000000000000000000000000000BD ++:1013300000000000000000000000000000000000AD ++:10134000000000000000000000000000000000009D ++:10135000000000000000000000000000000000008D ++:10136000000000000000000000000000000000007D ++:10137000000000000000000000000000000000006D ++:10138000000000000000000000000000000000005D ++:10139000000000000000000000000000000000004D ++:1013A000000000000000000000000000000000003D ++:1013B000000000000000000000000000000000002D ++:1013C000000000000000000000000000000000001D ++:1013D000000000000000000000000000000000000D ++:1013E00000000000000000000000000000000000FD ++:1013F00000000000000000000000000000000000ED ++:1014000000000000000000000000000000000000DC ++:1014100000000000000000000000000000000000CC ++:1014200000000000000000000000000000000000BC ++:1014300000000000000000000000000000000000AC ++:10144000000000000000000000000000000000009C ++:10145000000000000000000000000000000000008C ++:10146000000000000000000000000000000000007C ++:10147000000000000000000000000000000000006C ++:10148000000000000000000000000000000000005C ++:10149000000000000000000000000000000000004C ++:1014A000000000000000000000000000000000003C ++:1014B000000000000000000000000000000000002C ++:1014C000000000000000000000000000000000001C ++:1014D000000000000000000000000000000000000C ++:1014E00000000000000000000000000000000000FC ++:1014F00000000000000000000000000000000000EC ++:1015000000000000000000000000000000000000DB ++:1015100000000000000000000000000000000000CB ++:1015200000000000000000000000000000000000BB ++:1015300000000000000000000000000000000000AB ++:10154000000000000000000000000000000000009B ++:10155000000000000000000000000000000000008B ++:10156000000000000000000000000000000000007B ++:10157000000000000000000000000000000000006B ++:10158000000000000000000000000000000000005B ++:10159000000000000000000000000000000000004B ++:1015A000000000000000000000000000000000003B ++:1015B000000000000000000000000000000000002B ++:1015C000000000000000000000000000000000001B ++:1015D000000000000000000000000000000000000B ++:1015E00000000000000000000000000000000000FB ++:1015F00000000000000000000000000000000000EB ++:1016000000000000000000000000000000000000DA ++:1016100000000000000000000000000000000000CA ++:1016200000000000000000000000000000000000BA ++:1016300000000000000000000000000000000000AA ++:10164000000000000000000000000000000000009A ++:10165000000000000000000000000000000000008A ++:10166000000000000000000000000000000000007A ++:10167000000000000000000000000000000000006A ++:10168000000000000000000000000000000000005A ++:10169000000000000000000000000000000000004A ++:1016A000000000000000000000000000000000003A ++:1016B000000000000000000000000000000000002A ++:1016C000000000000000000000000000000000001A ++:1016D000000000000000000000000000000000000A ++:1016E00000000000000000000000000000000000FA ++:1016F00000000000000000000000000000000000EA ++:1017000000000000000000000000000000000000D9 ++:1017100000000000000000000000000000000000C9 ++:1017200000000000000000000000000000000000B9 ++:1017300000000000000000000000000000000000A9 ++:101740000000000000000000000000000000000099 ++:101750000000000000000000000000000000000089 ++:101760000000000000000000000000000000000079 ++:101770000000000000000000000000000000000069 ++:101780000000000000000000000000000000000059 ++:101790000000000000000000000000000000000049 ++:1017A0000000000000000000000000000000000039 ++:1017B0000000000000000000000000000000000029 ++:1017C0000000000000000000000000000000000019 ++:1017D0000000000000000000000000000000000009 ++:1017E00000000000000000000000000000000000F9 ++:1017F00000000000000000000000000000000000E9 ++:1018000000000000000000000000000000000000D8 ++:1018100000000000000000000000000000000000C8 ++:1018200000000000000000000000000000000000B8 ++:1018300000000000000000000000000000000000A8 ++:101840000000000000000000000000000000000098 ++:101850000000000000000000000000000000000088 ++:101860000000000000000000000000000000000078 ++:101870000000000000000000000000000000000068 ++:101880000000000000000000000000000000000058 ++:101890000000000000000000000000000000000048 ++:1018A0000000000000000000000000000000000038 ++:1018B0000000000000000000000000000000000028 ++:1018C0000000000000000000000000000000000018 ++:1018D0000000000000000000000000000000000008 ++:1018E00000000000000000000000000000000000F8 ++:1018F00000000000000000000000000000000000E8 ++:1019000000000000000000000000000000000000D7 ++:1019100000000000000000000000000000000000C7 ++:1019200000000000000000000000000000000000B7 ++:1019300000000000000000000000000000000000A7 ++:101940000000000000000000000000000000000097 ++:101950000000000000000000000000000000000087 ++:101960000000000000000000000000000000000077 ++:101970000000000000000000000000000000000067 ++:101980000000000000000000000000000000000057 ++:101990000000000000000000000000000000000047 ++:1019A0000000000000000000000000000000000037 ++:1019B0000000000000000000000000000000000027 ++:1019C0000000000000000000000000000000000017 ++:1019D0000000000000000000000000000000000007 ++:1019E00000000000000000000000000000000000F7 ++:1019F00000000000000000000000000000000000E7 ++:101A000000000000000000000000000000000000D6 ++:101A100000000000000000000000000000000000C6 ++:101A200000000000000000000000000000000000B6 ++:101A300000000000000000000000000000000000A6 ++:101A40000000000000000000000000000000000096 ++:101A50000000000000000000000000000000000086 ++:101A60000000000000000000000000000000000076 ++:101A70000000000000000000000000000000000066 ++:101A80000000000000000000000000000000000056 ++:101A90000000000000000000000000000000000046 ++:101AA0000000000000000000000000000000000036 ++:101AB0000000000000000000000000000000000026 ++:101AC0000000000000000000000000000000000016 ++:101AD0000000000000000000000000000000000006 ++:101AE00000000000000000000000000000000000F6 ++:101AF00000000000000000000000000000000000E6 ++:101B000000000000000000000000000000000000D5 ++:101B100000000000000000000000000000000000C5 ++:101B200000000000000000000000000000000000B5 ++:101B300000000000000000000000000000000000A5 ++:101B40000000000000000000000000000000000095 ++:101B50000000000000000000000000000000000085 ++:101B60000000000000000000000000000000000075 ++:101B70000000000000000000000000000000000065 ++:101B80000000000000000000000000000000000055 ++:101B90000000000000000000000000000000000045 ++:101BA0000000000000000000000000000000000035 ++:101BB0000000000000000000000000000000000025 ++:101BC0000000000000000000000000000000000015 ++:101BD0000000000000000000000000000000000005 ++:101BE00000000000000000000000000000000000F5 ++:101BF00000000000000000000000000000000000E5 ++:101C000000000000000000000000000000000000D4 ++:101C100000000000000000000000000000000000C4 ++:101C200000000000000000000000000000000000B4 ++:101C300000000000000000000000000000000000A4 ++:101C40000000000000000000000000000000000094 ++:101C50000000000000000000000000000000000084 ++:101C60000000000000000000000000000000000074 ++:101C70000000000000000000000000000000000064 ++:101C80000000000000000000000000000000000054 ++:101C90000000000000000000000000000000000044 ++:101CA0000000000000000000000000000000000034 ++:101CB0000000000000000000000000000000000024 ++:101CC0000000000000000000000000000000000014 ++:101CD0000000000000000000000000000000000004 ++:101CE00000000000000000000000000000000000F4 ++:101CF00000000000000000000000000000000000E4 ++:101D000000000000000000000000000000000000D3 ++:101D100000000000000000000000000000000000C3 ++:101D200000000000000000000000000000000000B3 ++:101D300000000000000000000000000000000000A3 ++:101D40000000000000000000000000000000000093 ++:101D50000000000000000000000000000000000083 ++:101D60000000000000000000000000000000000073 ++:101D70000000000000000000000000000000000063 ++:101D80000000000000000000000000000000000053 ++:101D90000000000000000000000000000000000043 ++:101DA0000000000000000000000000000000000033 ++:101DB0000000000000000000000000000000000023 ++:101DC0000000000000000000000000000000000013 ++:101DD0000000000000000000000000000000000003 ++:101DE00000000000000000000000000000000000F3 ++:101DF00000000000000000000000000000000000E3 ++:101E000000000000000000000000000000000000D2 ++:101E100000000000000000000000000000000000C2 ++:101E200000000000000000000000000000000000B2 ++:101E300000000000000000000000000000000000A2 ++:101E40000000000000000000000000000000000092 ++:101E50000000000000000000000000000000000082 ++:101E60000000000000000000000000000000000072 ++:101E70000000000000000000000000000000000062 ++:101E80000000000000000000000000000000000052 ++:101E90000000000000000000000000000000000042 ++:101EA0000000000000000000000000000000000032 ++:101EB0000000000000000000000000000000000022 ++:101EC0000000000000000000000000000000000012 ++:101ED0000000000000000000000000000000000002 ++:101EE00000000000000000000000000000000000F2 ++:101EF00000000000000000000000000000000000E2 ++:101F000000000000000000000000000000000000D1 ++:101F100000000000000000000000000000000000C1 ++:101F200000000000000000000000000000000000B1 ++:101F300000000000000000000000000000000000A1 ++:101F40000000000000000000000000000000000091 ++:101F50000000000000000000000000000000000081 ++:101F60000000000000000000000000000000000071 ++:101F70000000000000000000000000000000000061 ++:101F80000000000000000000000000000000000051 ++:101F90000000000000000000000000000000000041 ++:101FA0000000000000000000000000000000000031 ++:101FB0000000000000000000000000000000000021 ++:101FC0000000000000000000000000000000000011 ++:101FD0000000000000000000000000000000000001 ++:101FE00000000000000000000000000000000000F1 ++:101FF00000000000000000000000000000000000E1 ++:1020000000000000000000000000000000000000D0 ++:1020100000000000000000000000000000000000C0 ++:1020200000000000000000000000000000000000B0 ++:1020300000000000000000000000000000000000A0 ++:102040000000000000000000000000000000000090 ++:102050000000000000000000000000000000000080 ++:102060000000000000000000000000000000000070 ++:102070000000000000000000000000000000000060 ++:102080000000000000000000000000000000000050 ++:102090000000000000000000000000000000000040 ++:1020A0000000000000000000000000000000000030 ++:1020B0000000000000000000000000000000000020 ++:1020C0000000000000000000000000000000000010 ++:1020D0000000000000000000000000000000000000 ++:1020E00000000000000000000000000000000000F0 ++:1020F00000000000000000000000000000000000E0 ++:1021000000000000000000000000000000000000CF ++:1021100000000000000000000000000000000000BF ++:1021200000000000000000000000000000000000AF ++:10213000000000000000000000000000000000009F ++:10214000000000000000000000000000000000008F ++:10215000000000000000000000000000000000007F ++:10216000000000000000000000000000000000006F ++:10217000000000000000000000000000000000005F ++:10218000000000000000000000000000000000004F ++:10219000000000000000000000000000000000003F ++:1021A000000000000000000000000000000000002F ++:1021B000000000000000000000000000000000001F ++:1021C000000000000000000000000000000000000F ++:1021D00000000000000000000000000000000000FF ++:1021E00000000000000000000000000000000000EF ++:1021F00000000000000000000000000000000000DF ++:1022000000000000000000000000000000000000CE ++:1022100000000000000000000000000000000000BE ++:1022200000000000000000000000000000000000AE ++:10223000000000000000000000000000000000009E ++:10224000000000000000000000000000000000008E ++:10225000000000000000000000000000000000007E ++:10226000000000000000000000000000000000006E ++:10227000000000000000000000000000000000005E ++:10228000000000000000000000000000000000004E ++:10229000000000000000000000000000000000003E ++:1022A000000000000000000000000000000000002E ++:1022B000000000000000000000000000000000001E ++:1022C000000000000000000000000000000000000E ++:1022D00000000000000000000000000000000000FE ++:1022E00000000000000000000000000000000000EE ++:1022F00000000000000000000000000000000000DE ++:1023000000000000000000000000000000000000CD ++:1023100000000000000000000000000000000000BD ++:1023200000000000000000000000000000000000AD ++:10233000000000000000000000000000000000009D ++:10234000000000000000000000000000000000008D ++:10235000000000000000000000000000000000007D ++:10236000000000000000000000000000000000006D ++:10237000000000000000000000000000000000005D ++:10238000000000000000000000000000000000004D ++:10239000000000000000000000000000000000003D ++:1023A000000000000000000000000000000000002D ++:1023B000000000000000000000000000000000001D ++:1023C000000000000000000000000000000000000D ++:1023D00000000000000000000000000000000000FD ++:1023E00000000000000000000000000000000000ED ++:1023F00000000000000000000000000000000000DD ++:1024000000000000000000000000000000000000CC ++:1024100000000000000000000000000000000000BC ++:1024200000000000000000000000000000000000AC ++:10243000000000000000000000000000000000009C ++:10244000000000000000000000000000000000008C ++:10245000000000000000000000000000000000007C ++:10246000000000000000000000000000000000006C ++:10247000000000000000000000000000000000005C ++:10248000000000000000000000000000000000004C ++:10249000000000000000000000000000000000003C ++:1024A000000000000000000000000000000000002C ++:1024B000000000000000000000000000000000001C ++:1024C000000000000000000000000000000000000C ++:1024D00000000000000000000000000000000000FC ++:1024E00000000000000000000000000000000000EC ++:1024F00000000000000000000000000000000000DC ++:1025000000000000000000000000000000000000CB ++:1025100000000000000000000000000000000000BB ++:1025200000000000000000000000000000000000AB ++:10253000000000000000000000000000000000009B ++:10254000000000000000000000000000000000008B ++:10255000000000000000000000000000000000007B ++:10256000000000000000000000000000000000006B ++:10257000000000000000000000000000000000005B ++:10258000000000000000000000000000000000004B ++:10259000000000000000000000000000000000003B ++:1025A000000000000000000000000000000000002B ++:1025B000000000000000000000000000000000001B ++:1025C000000000000000000000000000000000000B ++:1025D00000000000000000000000000000000000FB ++:1025E00000000000000000000000000000000000EB ++:1025F00000000000000000000000000000000000DB ++:1026000000000000000000000000000000000000CA ++:1026100000000000000000000000000000000000BA ++:1026200000000000000000000000000000000000AA ++:10263000000000000000000000000000000000009A ++:10264000000000000000000000000000000000008A ++:10265000000000000000000000000000000000007A ++:10266000000000000000000000000000000000006A ++:10267000000000000000000000000000000000005A ++:10268000000000000000000000000000000000004A ++:10269000000000000000000000000000000000003A ++:1026A000000000000000000000000000000000002A ++:1026B000000000000000000000000000000000001A ++:1026C000000000000000000000000000000000000A ++:1026D00000000000000000000000000000000000FA ++:1026E00000000000000000000000000000000000EA ++:1026F00000000000000000000000000000000000DA ++:1027000000000000000000000000000000000000C9 ++:1027100000000000000000000000000000000000B9 ++:1027200000000000000000000000000000000000A9 ++:102730000000000000000000000000000000000099 ++:102740000000000000000000000000000000000089 ++:102750000000000000000000000000000000000079 ++:102760000000000000000000000000000000000069 ++:102770000000000000000000000000000000000059 ++:102780000000000000000000000000000000000049 ++:102790000000000000000000000000000000000039 ++:1027A0000000000000000000000000000000000029 ++:1027B0000000000000000000000000000000000019 ++:1027C0000000000000000000000000000000000009 ++:1027D00000000000000000000000000000000000F9 ++:1027E00000000000000000000000000000000000E9 ++:1027F00000000000000000000000000000000000D9 ++:1028000000000000000000000000000000000000C8 ++:1028100000000000000000000000000000000000B8 ++:1028200000000000000000000000000000000000A8 ++:102830000000000000000000000000000000000098 ++:102840000000000000000000000000000000000088 ++:102850000000000000000000000000000000000078 ++:102860000000000000000000000000000000000068 ++:102870000000000000000000000000000000000058 ++:102880000000000000000000000000000000000048 ++:102890000000000000000000000000000000000038 ++:1028A0000000000000000000000000000000000028 ++:1028B0000000000000000000000000000000000018 ++:1028C0000000000000000000000000000000000008 ++:1028D00000000000000000000000000000000000F8 ++:1028E00000000000000000000000000000000000E8 ++:1028F00000000000000000000000000000000000D8 ++:1029000000000000000000000000000000000000C7 ++:1029100000000000000000000000000000000000B7 ++:1029200000000000000000000000000000000000A7 ++:102930000000000000000000000000000000000097 ++:102940000000000000000000000000000000000087 ++:102950000000000000000000000000000000000077 ++:102960000000000000000000000000000000000067 ++:102970000000000000000000000000000000000057 ++:102980000000000000000000000000000000000047 ++:102990000000000000000000000000000000000037 ++:1029A0000000000000000000000000000000000027 ++:1029B0000000000000000000000000000000000017 ++:1029C0000000000000000000000000000000000007 ++:1029D00000000000000000000000000000000000F7 ++:1029E00000000000000000000000000000000000E7 ++:1029F00000000000000000000000000000000000D7 ++:102A000000000000000000000000000000000000C6 ++:102A100000000000000000000000000000000000B6 ++:102A200000000000000000000000000000000000A6 ++:102A30000000000000000000000000000000000096 ++:102A40000000000000000000000000000000000086 ++:102A50000000000000000000000000000000000076 ++:102A60000000000000000000000000000000000066 ++:102A70000000000000000000000000000000000056 ++:102A80000000000000000000000000000000000046 ++:102A90000000000000000000000000000000000036 ++:102AA0000000000000000000000000000000000026 ++:102AB0000000000000000000000000000000000016 ++:102AC0000000000000000000000000000000000006 ++:102AD00000000000000000000000000000000000F6 ++:102AE00000000000000000000000000000000000E6 ++:102AF00000000000000000000000000000000000D6 ++:102B000000000000000000000000000000000000C5 ++:102B100000000000000000000000000000000000B5 ++:102B200000000000000000000000000000000000A5 ++:102B30000000000000000000000000000000000095 ++:102B40000000000000000000000000000000000085 ++:102B50000000000000000000000000000000000075 ++:102B60000000000000000000000000000000000065 ++:102B70000000000000000000000000000000000055 ++:102B80000000000000000000000000000000000045 ++:102B90000000000000000000000000000000000035 ++:102BA0000000000000000000000000000000000025 ++:102BB0000000000000000000000000000000000015 ++:102BC0000000000000000000000000000000000005 ++:102BD00000000000000000000000000000000000F5 ++:102BE00000000000000000000000000000000000E5 ++:102BF00000000000000000000000000000000000D5 ++:102C000000000000000000000000000000000000C4 ++:102C100000000000000000000000000000000000B4 ++:102C200000000000000000000000000000000000A4 ++:102C30000000000000000000000000000000000094 ++:102C40000000000000000000000000000000000084 ++:102C50000000000000000000000000000000000074 ++:102C60000000000000000000000000000000000064 ++:102C70000000000000000000000000000000000054 ++:102C80000000000000000000000000000000000044 ++:102C90000000000000000000000000000000000034 ++:102CA0000000000000000000000000000000000024 ++:102CB0000000000000000000000000000000000014 ++:102CC0000000000000000000000000000000000004 ++:102CD00000000000000000000000000000000000F4 ++:102CE00000000000000000000000000000000000E4 ++:102CF00000000000000000000000000000000000D4 ++:102D000000000000000000000000000000000000C3 ++:102D100000000000000000000000000000000000B3 ++:102D200000000000000000000000000000000000A3 ++:102D30000000000000000000000000000000000093 ++:102D40000000000000000000000000000000000083 ++:102D50000000000000000000000000000000000073 ++:102D60000000000000000000000000000000000063 ++:102D70000000000000000000000000000000000053 ++:102D80000000000000000000000000000000000043 ++:102D90000000000000000000000000000000000033 ++:102DA0000000000000000000000000000000000023 ++:102DB0000000000000000000000000000000000013 ++:102DC0000000000000000000000000000000000003 ++:102DD00000000000000000000000000000000000F3 ++:102DE00000000000000000000000000000000000E3 ++:102DF00000000000000000000000000000000000D3 ++:102E000000000000000000000000000000000000C2 ++:102E100000000000000000000000000000000000B2 ++:102E200000000000000000000000000000000000A2 ++:102E30000000000000000000000000000000000092 ++:102E40000000000000000000000000000000000082 ++:102E50000000000000000000000000000000000072 ++:102E60000000000000000000000000000000000062 ++:102E70000000000000000000000000000000000052 ++:102E80000000000000000000000000000000000042 ++:102E90000000000000000000000000000000000032 ++:102EA0000000000000000000000000000000000022 ++:102EB0000000000000000000000000000000000012 ++:102EC0000000000000000000000000000000000002 ++:102ED00000000000000000000000000000000000F2 ++:102EE00000000000000000000000000000000000E2 ++:102EF00000000000000000000000000000000000D2 ++:102F000000000000000000000000000000000000C1 ++:102F100000000000000000000000000000000000B1 ++:102F200000000000000000000000000000000000A1 ++:102F30000000000000000000000000000000000091 ++:102F40000000000000000000000000000000000081 ++:102F50000000000000000000000000000000000071 ++:102F60000000000000000000000000000000000061 ++:102F70000000000000000000000000000000000051 ++:102F80000000000000000000000000000000000041 ++:102F90000000000000000000000000000000000031 ++:102FA0000000000000000000000000000000000021 ++:102FB0000000000000000000000000000000000011 ++:102FC0000000000000000000000000000000000001 ++:102FD00000000000000000000000000000000000F1 ++:102FE00000000000000000000000000000000000E1 ++:102FF00000000000000000000000000000000000D1 ++:1030000000000000000000000000000000000000C0 ++:1030100000000000000000000000000000000000B0 ++:1030200000000000000000000000000000000000A0 ++:103030000000000000000000000000000000000090 ++:103040000000000000000000000000000000000080 ++:103050000000000000000000000000000000000070 ++:103060000000000000000000000000000000000060 ++:103070000000000000000000000000000000000050 ++:103080000000000000000000000000000000000040 ++:103090000000000000000000000000000000000030 ++:1030A0000000000000000000000000000000000020 ++:1030B0000000000000000000000000000000000010 ++:1030C0000000000000000000000000000000000000 ++:1030D00000000000000000000000000000000000F0 ++:1030E00000000000000000000000000000000000E0 ++:1030F00000000000000000000000000000000000D0 ++:1031000000000000000000000000000000000000BF ++:1031100000000000000000000000000000000000AF ++:10312000000000000000000000000000000000009F ++:10313000000000000000000000000000000000008F ++:10314000000000000000000000000000000000007F ++:10315000000000000000000000000000000000006F ++:10316000000000000000000000000000000000005F ++:10317000000000000000000000000000000000004F ++:10318000000000000000000000000000000000003F ++:10319000000000000000000000000000000000002F ++:1031A000000000000000000000000000000000001F ++:1031B000000000000000000000000000000000000F ++:1031C00000000000000000000000000000000000FF ++:1031D00000000000000000000000000000000000EF ++:1031E00000000000000000000000000000000000DF ++:1031F00000000000000000000000000000000000CF ++:1032000000000000000000000000000000000000BE ++:1032100000000000000000000000000000000000AE ++:10322000000000000000000000000000000000009E ++:10323000000000000000000000000000000000008E ++:10324000000000000000000000000000000000007E ++:10325000000000000000000000000000000000006E ++:10326000000000000000000000000000000000005E ++:10327000000000000000000000000000000000004E ++:10328000000000000000000000000000000000003E ++:10329000000000000000000000000000000000002E ++:1032A000000000000000000000000000000000001E ++:1032B000000000000000000000000000000000000E ++:1032C00000000000000000000000000000000000FE ++:1032D00000000000000000000000000000000000EE ++:1032E00000000000000000000000000000000000DE ++:1032F00000000000000000000000000000000000CE ++:1033000000000000000000000000000000000000BD ++:1033100000000000000000000000000000000000AD ++:10332000000000000000000000000000000000009D ++:10333000000000000000000000000000000000008D ++:10334000000000000000000000000000000000007D ++:10335000000000000000000000000000000000006D ++:10336000000000000000000000000000000000005D ++:10337000000000000000000000000000000000004D ++:10338000000000000000000000000000000000003D ++:10339000000000000000000000000000000000002D ++:1033A000000000000000000000000000000000001D ++:1033B000000000000000000000000000000000000D ++:1033C00000000000000000000000000000000000FD ++:1033D00000000000000000000000000000000000ED ++:1033E00000000000000000000000000000000000DD ++:1033F00000000000000000000000000000000000CD ++:1034000000000000000000000000000000000000BC ++:1034100000000000000000000000000000000000AC ++:10342000000000000000000000000000000000009C ++:10343000000000000000000000000000000000008C ++:10344000000000000000000000000000000000007C ++:10345000000000000000000000000000000000006C ++:10346000000000000000000000000000000000005C ++:10347000000000000000000000000000000000004C ++:10348000000000000000000000000000000000003C ++:10349000000000000000000000000000000000002C ++:1034A000000000000000000000000000000000001C ++:1034B000000000000000000000000000000000000C ++:1034C00000000000000000000000000000000000FC ++:1034D00000000000000000000000000000000000EC ++:1034E00000000000000000000000000000000000DC ++:1034F00000000000000000000000000000000000CC ++:1035000000000000000000000000000000000000BB ++:1035100000000000000000000000000000000000AB ++:10352000000000000000000000000000000000009B ++:10353000000000000000000000000000000000008B ++:10354000000000000000000000000000000000007B ++:10355000000000000000000000000000000000006B ++:10356000000000000000000000000000000000005B ++:10357000000000000000000000000000000000004B ++:10358000000000000000000000000000000000003B ++:10359000000000000000000000000000000000002B ++:1035A000000000000000000000000000000000001B ++:1035B000000000000000000000000000000000000B ++:1035C00000000000000000000000000000000000FB ++:1035D00000000000000000000000000000000000EB ++:1035E00000000000000000000000000000000000DB ++:1035F00000000000000000000000000000000000CB ++:1036000000000000000000000000000000000000BA ++:1036100000000000000000000000000000000000AA ++:10362000000000000000000000000000000000009A ++:10363000000000000000000000000000000000008A ++:10364000000000000000000000000000000000007A ++:10365000000000000000000000000000000000006A ++:10366000000000000000000000000000000000005A ++:10367000000000000000000000000000000000004A ++:10368000000000000000000000000000000000003A ++:10369000000000000000000000000000000000002A ++:1036A000000000000000000000000000000000001A ++:1036B000000000000000000000000000000000000A ++:1036C00000000000000000000000000000000000FA ++:1036D00000000000000000000000000000000000EA ++:1036E00000000000000000000000000000000000DA ++:1036F00000000000000000000000000000000000CA ++:1037000000000000000000000000000000000000B9 ++:1037100000000000000000000000000000000000A9 ++:103720000000000000000000000000000000000099 ++:103730000000000000000000000000000000000089 ++:103740000000000000000000000000000000000079 ++:103750000000000000000000000000000000000069 ++:103760000000000000000000000000000000000059 ++:103770000000000000000000000000000000000049 ++:103780000000000000000000000000000000000039 ++:103790000000000000000000000000000000000029 ++:1037A0000000000000000000000000000000000019 ++:1037B0000000000000000000000000000000000009 ++:1037C00000000000000000000000000000000000F9 ++:1037D00000000000000000000000000000000000E9 ++:1037E00000000000000000000000000000000000D9 ++:1037F00000000000000000000000000000000000C9 ++:1038000000000000000000000000000000000000B8 ++:1038100000000000000000000000000000000000A8 ++:103820000000000000000000000000000000000098 ++:103830000000000000000000000000000000000088 ++:103840000000000000000000000000000000000078 ++:103850000000000000000000000000000000000068 ++:103860000000000000000000000000000000000058 ++:103870000000000000000000000000000000000048 ++:103880000000000000000000000000000000000038 ++:103890000000000000000000000000000000000028 ++:1038A0000000000000000000000000000000000018 ++:1038B0000000000000000000000000000000000008 ++:1038C00000000000000000000000000000000000F8 ++:1038D00000000000000000000000000000000000E8 ++:1038E00000000000000000000000000000000000D8 ++:1038F00000000000000000000000000000000000C8 ++:1039000000000000000000000000000000000000B7 ++:1039100000000000000000000000000000000000A7 ++:103920000000000000000000000000000000000097 ++:103930000000000000000000000000000000000087 ++:103940000000000000000000000000000000000077 ++:103950000000000000000000000000000000000067 ++:103960000000000000000000000000000000000057 ++:103970000000000000000000000000000000000047 ++:103980000000000000000000000000000000000037 ++:103990000000000000000000000000000000000027 ++:1039A0000000000000000000000000000000000017 ++:1039B0000000000000000000000000000000000007 ++:1039C00000000000000000000000000000000000F7 ++:1039D00000000000000000000000000000000000E7 ++:1039E00000000000000000000000000000000000D7 ++:1039F00000000000000000000000000000000000C7 ++:103A000000000000000000000000000000000000B6 ++:103A100000000000000000000000000000000000A6 ++:103A20000000000000000000000000000000000096 ++:103A30000000000000000000000000000000000086 ++:103A40000000000000000000000000000000000076 ++:103A50000000000000000000000000000000000066 ++:103A60000000000000000000000000000000000056 ++:103A70000000000000000000000000000000000046 ++:103A80000000000000000000000000000000000036 ++:103A90000000000000000000000000000000000026 ++:103AA0000000000000000000000000000000000016 ++:103AB0000000000000000000000000000000000006 ++:103AC00000000000000000000000000000000000F6 ++:103AD00000000000000000000000000000000000E6 ++:103AE00000000000000000000000000000000000D6 ++:103AF00000000000000000000000000000000000C6 ++:103B000000000000000000000000000000000000B5 ++:103B100000000000000000000000000000000000A5 ++:103B20000000000000000000000000000000000095 ++:103B30000000000000000000000000000000000085 ++:103B40000000000000000000000000000000000075 ++:103B50000000000000000000000000000000000065 ++:103B60000000000000000000000000000000000055 ++:103B70000000000000000000000000000000000045 ++:103B80000000000000000000000000000000000035 ++:103B90000000000000000000000000000000000025 ++:103BA0000000000000000000000000000000000015 ++:103BB0000000000000000000000000000000000005 ++:103BC00000000000000000000000000000000000F5 ++:103BD00000000000000000000000000000000000E5 ++:103BE00000000000000000000000000000000000D5 ++:103BF00000000000000000000000000000000000C5 ++:103C000000000000000000000000000000000000B4 ++:103C100000000000000000000000000000000000A4 ++:103C20000000000000000000000000000000000094 ++:103C30000000000000000000000000000000000084 ++:103C40000000000000000000000000000000000074 ++:103C50000000000000000000000000000000000064 ++:103C60000000000000000000000000000000000054 ++:103C70000000000000000000000000000000000044 ++:103C80000000000000000000000000000000000034 ++:103C90000000000000000000000000000000000024 ++:103CA0000000000000000000000000000000000014 ++:103CB0000000000000000000000000000000000004 ++:103CC00000000000000000000000000000000000F4 ++:103CD00000000000000000000000000000000000E4 ++:103CE00000000000000000000000000000000000D4 ++:103CF00000000000000000000000000000000000C4 ++:103D000000000000000000000000000000000000B3 ++:103D100000000000000000000000000000000000A3 ++:103D20000000000000000000000000000000000093 ++:103D30000000000000000000000000000000000083 ++:103D40000000000000000000000000000000000073 ++:103D50000000000000000000000000000000000063 ++:103D60000000000000000000000000000000000053 ++:103D70000000000000000000000000000000000043 ++:103D80000000000000000000000000000000000033 ++:103D90000000000000000000000000000000000023 ++:103DA0000000000000000000000000000000000013 ++:103DB0000000000000000000000000000000000003 ++:103DC00000000000000000000000000000000000F3 ++:103DD00000000000000000000000000000000000E3 ++:103DE00000000000000000000000000000000000D3 ++:103DF00000000000000000000000000000000000C3 ++:103E000000000000000000000000000000000000B2 ++:103E100000000000000000000000000000000000A2 ++:103E20000000000000000000000000000000000092 ++:103E30000000000000000000000000000000000082 ++:103E40000000000000000000000000000000000072 ++:103E50000000000000000000000000000000000062 ++:103E60000000000000000000000000000000000052 ++:103E70000000000000000000000000000000000042 ++:103E80000000000000000000000000000000000032 ++:103E90000000000000000000000000000000000022 ++:103EA0000000000000000000000000000000000012 ++:103EB0000000000000000000000000000000000002 ++:103EC00000000000000000000000000000000000F2 ++:103ED00000000000000000000000000000000000E2 ++:103EE00000000000000000000000000000000000D2 ++:103EF00000000000000000000000000000000000C2 ++:103F000000000000000000000000000000000000B1 ++:103F100000000000000000000000000000000000A1 ++:103F20000000000000000000000000000000000091 ++:103F30000000000000000000000000000000000081 ++:103F40000000000000000000000000000000000071 ++:103F50000000000000000000000000000000000061 ++:103F60000000000000000000000000000000000051 ++:103F70000000000000000000000000000000000041 ++:103F80000000000000000000000000000000000031 ++:103F90000000000000000000000000000000000021 ++:103FA0000000000000000000000000000000000011 ++:103FB0000000000000000000000000000000000001 ++:103FC00000000000000000000000000000000000F1 ++:103FD00000000000000000000000000000000000E1 ++:103FE00000000000000000000000000000000000D1 ++:103FF00000000000000000000000000000000000C1 ++:1040000000000000000000000000000000000000B0 ++:1040100000000000000000000000000000000000A0 ++:104020000000000000000000000000000000000090 ++:104030000000000000000000000000000000000080 ++:104040000000000000000000000000000000000070 ++:104050000000000000000000000000000000000060 ++:104060000000000000000000000000000000000050 ++:104070000000000000000000000000000000000040 ++:104080000000000000000000000000000000000030 ++:104090000000000000000000000000000000000020 ++:1040A0000000000000000000000000000000000010 ++:1040B0000000000000000000000000000000000000 ++:1040C00000000000000000000000000000000000F0 ++:1040D00000000000000000000000000000000000E0 ++:1040E00000000000000000000000000000000000D0 ++:1040F00000000000000000000000000000000000C0 ++:1041000000000000000000000000000000000000AF ++:10411000000000000000000000000000000000009F ++:10412000000000000000000000000000000000008F ++:10413000000000000000000000000000000000007F ++:10414000000000000000000000000000000000006F ++:10415000000000000000000000000000000000005F ++:10416000000000000000000000000000000000004F ++:10417000000000000000000000000000000000003F ++:10418000000000000000000000000000000000002F ++:10419000000000000000000000000000000000001F ++:1041A000000000000000000000000000000000000F ++:1041B00000000000000000000000000000000000FF ++:1041C00000000000000000000000000000000000EF ++:1041D00000000000000000000000000000000000DF ++:1041E00000000000000000000000000000000000CF ++:1041F00000000000000000000000000000000000BF ++:1042000000000000000000000000000000000000AE ++:10421000000000000000000000000000000000009E ++:10422000000000000000000000000000000000008E ++:10423000000000000000000000000000000000007E ++:10424000000000000000000000000000000000006E ++:10425000000000000000000000000000000000005E ++:10426000000000000000000000000000000000004E ++:10427000000000000000000000000000000000003E ++:10428000000000000000000000000000000000002E ++:10429000000000000000000000000000000000001E ++:1042A000000000000000000000000000000000000E ++:1042B00000000000000000000000000000000000FE ++:1042C00000000000000000000000000000000000EE ++:1042D00000000000000000000000000000000000DE ++:1042E00000000000000000000000000000000000CE ++:1042F00000000000000000000000000000000000BE ++:1043000000000000000000000000000000000000AD ++:10431000000000000000000000000000000000009D ++:10432000000000000000000000000000000000008D ++:10433000000000000000000000000000000000007D ++:10434000000000000000000000000000000000006D ++:10435000000000000000000000000000000000005D ++:10436000000000000000000000000000000000004D ++:10437000000000000000000000000000000000003D ++:10438000000000000000000000000000000000002D ++:10439000000000000000000000000000000000001D ++:1043A000000000000000000000000000000000000D ++:1043B00000000000000000000000000000000000FD ++:1043C00000000000000000000000000000000000ED ++:1043D00000000000000000000000000000000000DD ++:1043E00000000000000000000000000000000000CD ++:1043F00000000000000000000000000000000000BD ++:1044000000000000000000000000000000000000AC ++:10441000000000000000000000000000000000009C ++:10442000000000000000000000000000000000008C ++:10443000000000000000000000000000000000007C ++:10444000000000000000000000000000000000006C ++:10445000000000000000000000000000000000005C ++:10446000000000000000000000000000000000004C ++:10447000000000000000000000000000000000003C ++:10448000000000000000000000000000000000002C ++:10449000000000000000000000000000000000001C ++:1044A000000000000000000000000000000000000C ++:1044B00000000000000000000000000000000000FC ++:1044C00000000000000000000000000000000000EC ++:1044D00000000000000000000000000000000000DC ++:1044E00000000000000000000000000000000000CC ++:1044F00000000000000000000000000000000000BC ++:1045000000000000000000000000000000000000AB ++:10451000000000000000000000000000000000009B ++:10452000000000000000000000000000000000008B ++:10453000000000000000000000000000000000007B ++:10454000000000000000000000000000000000006B ++:10455000000000000000000000000000000000005B ++:10456000000000000000000000000000000000004B ++:10457000000000000000000000000000000000003B ++:10458000000000000000000000000000000000002B ++:10459000000000000000000000000000000000001B ++:1045A000000000000000000000000000000000000B ++:1045B00000000000000000000000000000000000FB ++:1045C00000000000000000000000000000000000EB ++:1045D00000000000000000000000000000000000DB ++:1045E00000000000000000000000000000000000CB ++:1045F00000000000000000000000000000000000BB ++:1046000000000000000000000000000000000000AA ++:10461000000000000000000000000000000000009A ++:10462000000000000000000000000000000000008A ++:10463000000000000000000000000000000000007A ++:10464000000000000000000000000000000000006A ++:10465000000000000000000000000000000000005A ++:10466000000000000000000000000000000000004A ++:10467000000000000000000000000000000000003A ++:10468000000000000000000000000000000000002A ++:10469000000000000000000000000000000000001A ++:1046A000000000000000000000000000000000000A ++:1046B00000000000000000000000000000000000FA ++:1046C00000000000000000000000000000000000EA ++:1046D00000000000000000000000000000000000DA ++:1046E00000000000000000000000000000000000CA ++:1046F00000000000000000000000000000000000BA ++:1047000000000000000000000000000000000000A9 ++:104710000000000000000000000000000000000099 ++:104720000000000000000000000000000000000089 ++:104730000000000000000000000000000000000079 ++:104740000000000000000000000000000000000069 ++:104750000000000000000000000000000000000059 ++:104760000000000000000000000000000000000049 ++:104770000000000000000000000000000000000039 ++:104780000000000000000000000000000000000029 ++:104790000000000000000000000000000000000019 ++:1047A0000000000000000000000000000000000009 ++:1047B00000000000000000000000000000000000F9 ++:1047C00000000000000000000000000000000000E9 ++:1047D00000000000000000000000000000000000D9 ++:1047E00000000000000000000000000000000000C9 ++:1047F00000000000000000000000000000000000B9 ++:1048000000000000000000000000000000000000A8 ++:104810000000000000000000000000000000000098 ++:104820000000000000000000000000000000000088 ++:104830000000000000000000000000000000000078 ++:104840000000000000000000000000000000000068 ++:104850000000000000000000000000000000000058 ++:104860000000000000000000000000000000000048 ++:104870000000000000000000000000000000000038 ++:104880000000000000000000000000000000000028 ++:104890000000000000000000000000000000000018 ++:1048A0000000000000000000000000000000000008 ++:1048B00000000000000000000000000000000000F8 ++:1048C00000000000000000000000000000000000E8 ++:1048D00000000000000000000000000000000000D8 ++:1048E00000000000000000000000000000000000C8 ++:1048F00000000000000000000000000000000000B8 ++:1049000000000000000000000000000000000000A7 ++:104910000000000000000000000000000000000097 ++:104920000000000000000000000000000000000087 ++:104930000000000000000000000000000000000077 ++:104940000000000000000000000000000000000067 ++:104950000000000000000000000000000000000057 ++:104960000000000000000000000000000000000047 ++:104970000000000000000000000000000000000037 ++:104980000000000000000000000000000000000027 ++:104990000000000000000000000000000000000017 ++:1049A0000000000000000000000000000000000007 ++:1049B00000000000000000000000000000000000F7 ++:1049C00000000000000000000000000000000000E7 ++:1049D00000000000000000000000000000000000D7 ++:1049E00000000000000000000000000000000000C7 ++:1049F00000000000000000000000000000000000B7 ++:104A000000000000000000000000000000000000A6 ++:104A10000000000000000000000000000000000096 ++:104A20000000000000000000000000000000000086 ++:104A30000000000000000000000000000000000076 ++:104A40000000000000000000000000000000000066 ++:104A50000000000000000000000000000000000056 ++:104A60000000000000000000000000000000000046 ++:104A70000000000000000000000000000000000036 ++:104A80000000000000000000000000000000000026 ++:104A90000000000000000000000000000000000016 ++:104AA0000000000000000000000000000000000006 ++:104AB00000000000000000000000000000000000F6 ++:104AC00000000000000000000000000000000000E6 ++:104AD00000000000000000000000000000000000D6 ++:104AE00000000000000000000000000000000000C6 ++:104AF00000000000000000000000000000000000B6 ++:104B000000000000000000000000000000000000A5 ++:104B10000000000000000000000000000000000095 ++:104B20000000000000000000000000000000000085 ++:104B30000000000000000000000000000000000075 ++:104B40000000000000000000000000000000000065 ++:104B50000000000000000000000000000000000055 ++:104B60000000000000000000000000000000000045 ++:104B70000000000000000000000000000000000035 ++:104B80000000000000000000000000000000000025 ++:104B90000000000000000000000000000000000015 ++:104BA0000000000000000000000000000000000005 ++:104BB00000000000000000000000000000000000F5 ++:104BC00000000000000000000000000000000000E5 ++:104BD00000000000000000000000000000000000D5 ++:104BE00000000000000000000000000000000000C5 ++:104BF00000000000000000000000000000000000B5 ++:104C000000000000000000000000000000000000A4 ++:104C10000000000000000000000000000000000094 ++:104C20000000000000000000000000000000000084 ++:104C30000000000000000000000000000000000074 ++:104C40000000000000000000000000000000000064 ++:104C50000000000000000000000000000000000054 ++:104C60000000000000000000000000000000000044 ++:104C70000000000000000000000000000000000034 ++:104C80000000000000000000000000000000000024 ++:104C90000000000000000000000000000000000014 ++:104CA0000000000000000000000000000000000004 ++:104CB00000000000000000000000000000000000F4 ++:104CC00000000000000000000000000000000000E4 ++:104CD00000000000000000000000000000000000D4 ++:104CE00000000000000000000000000000000000C4 ++:104CF00000000000000000000000000000000000B4 ++:104D000000000000000000000000000000000000A3 ++:104D10000000000000000000000000000000000093 ++:104D20000000000000000000000000000000000083 ++:104D30000000000000000000000000000000000073 ++:104D40000000000000000000000000000000000063 ++:104D50000000000000000000000000000000000053 ++:104D60000000000000000000000000000000000043 ++:104D70000000000000000000000000000000000033 ++:104D80000000000000000000000000000000000023 ++:104D90000000000000000000000000000000000013 ++:104DA0000000000000000000000000000000000003 ++:104DB00000000000000000000000000000000000F3 ++:104DC00000000000000000000000000000000000E3 ++:104DD00000000000000000000000000000000000D3 ++:104DE00000000000000000000000000000000000C3 ++:104DF00000000000000000000000000000000000B3 ++:104E000000000000000000000000000000000000A2 ++:104E10000000000000000000000000000000000092 ++:104E20000000000000000000000000000000000082 ++:104E30000000000000000000000000000000000072 ++:104E40000000000000000000000000000000000062 ++:104E50000000000000000000000000000000000052 ++:104E60000000000000000000000000000000000042 ++:104E70000000000000000000000000000000000032 ++:104E80000000000000000000000000000000000022 ++:104E90000000000000000000000000000000000012 ++:104EA0000000000000000000000000000000000002 ++:104EB00000000000000000000000000000000000F2 ++:104EC00000000000000000000000000000000000E2 ++:104ED00000000000000000000000000000000000D2 ++:104EE00000000000000000000000000000000000C2 ++:104EF00000000000000000000000000000000000B2 ++:104F000000000000000000000000000000000000A1 ++:104F10000000000000000000000000000000000091 ++:104F20000000000000000000000000000000000081 ++:104F30000000000000000000000000000000000071 ++:104F40000000000000000000000000000000000061 ++:104F50000000000000000000000000000000000051 ++:104F60000000000000000000000000000000000041 ++:104F70000000000000000000000000000000000031 ++:104F80000000000000000000000000000000000021 ++:104F90000000000000000000000000000000000011 ++:104FA0000000000000000000000000000000000001 ++:104FB00000000000000000000000000000000000F1 ++:104FC00000000000000000000000000000000000E1 ++:104FD00000000000000000000000000000000000D1 ++:104FE00000000000000000000000000000000000C1 ++:104FF00000000000000000000000000000000000B1 ++:1050000000000000000000000000000000000000A0 ++:105010000000000000000000000000000000000090 ++:105020000000000000000000000000000000000080 ++:105030000000000000000000000000000000000070 ++:105040000000000000000000000000000000000060 ++:105050000000000000000000000000000000000050 ++:105060000000000000000000000000000000000040 ++:105070000000000000000000000000000000000030 ++:105080000000000000000000000000000000000020 ++:105090000000000000000000000000000000000010 ++:1050A0000000000000000000000000000000000000 ++:1050B00000000000000000000000000000000000F0 ++:1050C00000000000000000000000000000000000E0 ++:1050D00000000000000000000000000000000000D0 ++:1050E00000000000000000000000000000000000C0 ++:1050F00000000000000000000000000000000000B0 ++:10510000000000000000000000000000000000009F ++:10511000000000000000000000000000000000008F ++:10512000000000000000000000000000000000007F ++:10513000000000000000000000000000000000006F ++:10514000000000000000000000000000000000005F ++:10515000000000000000000000000000000000004F ++:10516000000000000000000000000000000000003F ++:10517000000000000000000000000000000000002F ++:10518000000000000000000000000000000000001F ++:10519000000000000000000000000000000000000F ++:1051A00000000000000000000000000000000000FF ++:1051B00000000000000000000000000000000000EF ++:1051C00000000000000000000000000000000000DF ++:1051D00000000000000000000000000000000000CF ++:1051E00000000000000000000000000000000000BF ++:1051F00000000000000000000000000000000000AF ++:10520000000000000000000000000000000000009E ++:10521000000000000000000000000000000000008E ++:10522000000000000000000000000000000000007E ++:10523000000000000000000000000000000000006E ++:10524000000000000000000000000000000000005E ++:10525000000000000000000000000000000000004E ++:10526000000000000000000000000000000000003E ++:10527000000000000000000000000000000000002E ++:10528000000000000000000000000000000000001E ++:10529000000000000000000000000000000000000E ++:1052A00000000000000000000000000000000000FE ++:1052B00000000000000000000000000000000000EE ++:1052C00000000000000000000000000000000000DE ++:1052D00000000000000000000000000000000000CE ++:1052E00000000000000000000000000000000000BE ++:1052F00000000000000000000000000000000000AE ++:10530000000000000000000000000000000000009D ++:10531000000000000000000000000000000000008D ++:10532000000000000000000000000000000000007D ++:10533000000000000000000000000000000000006D ++:10534000000000000000000000000000000000005D ++:10535000000000000000000000000000000000004D ++:10536000000000000000000000000000000000003D ++:10537000000000000000000000000000000000002D ++:10538000000000000000000000000000000000001D ++:10539000000000000000000000000000000000000D ++:1053A00000000000000000000000000000000000FD ++:1053B00000000000000000000000000000000000ED ++:1053C00000000000000000000000000000000000DD ++:1053D00000000000000000000000000000000000CD ++:1053E00000000000000000000000000000000000BD ++:1053F00000000000000000000000000000000000AD ++:10540000000000000000000000000000000000009C ++:10541000000000000000000000000000000000008C ++:10542000000000000000000000000000000000007C ++:10543000000000000000000000000000000000006C ++:10544000000000000000000000000000000000005C ++:10545000000000000000000000000000000000004C ++:10546000000000000000000000000000000000003C ++:10547000000000000000000000000000000000002C ++:10548000000000000000000000000000000000001C ++:10549000000000000000000000000000000000000C ++:1054A00000000000000000000000000000000000FC ++:1054B00000000000000000000000000000000000EC ++:1054C00000000000000000000000000000000000DC ++:1054D00000000000000000000000000000000000CC ++:1054E00000000000000000000000000000000000BC ++:1054F00000000000000000000000000000000000AC ++:10550000000000000000000000000000000000009B ++:10551000000000000000000000000000000000008B ++:10552000000000000000000000000000000000007B ++:10553000000000000000000000000000000000006B ++:10554000000000000000000000000000000000005B ++:10555000000000000000000000000000000000004B ++:10556000000000000000000000000000000000003B ++:10557000000000000000000000000000000000002B ++:10558000000000000000000000000000000000001B ++:10559000000000000000000000000000000000000B ++:1055A00000000000000000000000000000000000FB ++:1055B00000000000000000000000000000000000EB ++:1055C00000000000000000000000000000000000DB ++:1055D00000000000000000000000000000000000CB ++:1055E00000000000000000000000000000000000BB ++:1055F00000000000000000000000000000000000AB ++:10560000000000000000000000000000000000009A ++:10561000000000000000000000000000000000008A ++:10562000000000000000000000000000000000007A ++:10563000000000000000000000000000000000006A ++:10564000000000000000000000000000000000005A ++:10565000000000000000000000000000000000004A ++:10566000000000000000000000000000000000003A ++:10567000000000000000000000000000000000002A ++:10568000000000000000000000000000000000001A ++:10569000000000000000000000000000000000000A ++:1056A00000000000000000000000000000000000FA ++:1056B00000000000000000000000000000000000EA ++:1056C00000000000000000000000000000000000DA ++:1056D00000000000000000000000000000000000CA ++:1056E00000000000000000000000000000000000BA ++:1056F00000000000000000000000000000000000AA ++:105700000000000000000000000000000000000099 ++:105710000000000000000000000000000000000089 ++:105720000000000000000000000000000000000079 ++:105730000000000000000000000000000000000069 ++:105740000000000000000000000000000000000059 ++:105750000000000000000000000000000000000049 ++:105760000000000000000000000000000000000039 ++:105770000000000000000000000000000000000029 ++:105780000000000000000000000000000000000019 ++:105790000000000000000000000000000000000009 ++:1057A00000000000000000000000000000000000F9 ++:1057B00000000000000000000000000000000000E9 ++:1057C00000000000000000000000000000000000D9 ++:1057D00000000000000000000000000000000000C9 ++:1057E00000000000000000000000000000000000B9 ++:1057F00000000000000000000000000000000000A9 ++:105800000000000000000000000000000000000098 ++:105810000000000000000000000000000000000088 ++:105820000000000000000000000000000000000078 ++:105830000000000000000000000000000000000068 ++:105840000000000000000000000000000000000058 ++:105850000000000000000000000000000000000048 ++:105860000000000000000000000000000000000038 ++:105870000000000000000000000000000000000028 ++:105880000000000000000000000000000000000018 ++:105890000000000000000000000000000000000008 ++:1058A00000000000000000000000000000000000F8 ++:1058B00000000000000000000000000000000000E8 ++:1058C00000000000000000000000000000000000D8 ++:1058D00000000000000000000000000000000000C8 ++:1058E00000000000000000000000000000000000B8 ++:1058F00000000000000000000000000000000000A8 ++:105900000000000000000000000000000000000097 ++:105910000000000000000000000000000000000087 ++:105920000000000000000000000000000000000077 ++:105930000000000000000000000000000000000067 ++:105940000000000000000000000000000000000057 ++:105950000000000000000000000000000000000047 ++:105960000000000000000000000000000000000037 ++:105970000000000000000000000000000000000027 ++:105980000000000000000000000000000000000017 ++:105990000000000000000000000000000000000007 ++:1059A00000000000000000000000000000000000F7 ++:1059B00000000000000000000000000000000000E7 ++:1059C00000000000000000000000000000000000D7 ++:1059D00000000000000000000000000000000000C7 ++:1059E00000000000000000000000000000000000B7 ++:1059F00000000000000000000000000000000000A7 ++:105A00000000000000000000000000000000000096 ++:105A10000000000000000000000000000000000086 ++:105A20000000000000000000000000000000000076 ++:105A30000000000000000000000000000000000066 ++:105A40000000000000000000000000000000000056 ++:105A50000000000000000000000000000000000046 ++:105A60000000000000000000000000000000000036 ++:105A70000000000000000000000000000000000026 ++:105A80000000000000000000000000000000000016 ++:105A90000000000000000000000000000000000006 ++:105AA00000000000000000000000000000000000F6 ++:105AB00000000000000000000000000000000000E6 ++:105AC00000000000000000000000000000000000D6 ++:105AD00000000000000000000000000000000000C6 ++:105AE00000000000000000000000000000000000B6 ++:105AF00000000000000000000000000000000000A6 ++:105B00000000000000000000000000000000000095 ++:105B10000000000000000000000000000000000085 ++:105B20000000000000000000000000000000000075 ++:105B30000000000000000000000000000000000065 ++:105B40000000000000000000000000000000000055 ++:105B50000000000000000000000000000000000045 ++:105B60000000000000000000000000000000000035 ++:105B70000000000000000000000000000000000025 ++:105B80000000000000000000000000000000000015 ++:105B90000000000000000000000000000000000005 ++:105BA00000000000000000000000000000000000F5 ++:105BB00000000000000000000000000000000000E5 ++:105BC00000000000000000000000000000000000D5 ++:105BD00000000000000000000000000000000000C5 ++:105BE00000000000000000000000000000000000B5 ++:105BF00000000000000000000000000000000000A5 ++:105C00000000000000000000000000000000000094 ++:105C10000000000000000000000000000000000084 ++:105C20000000000000000000000000000000000074 ++:105C30000000000000000000000000000000000064 ++:105C40000000000000000000000000000000000054 ++:105C50000000000000000000000000000000000044 ++:105C60000000000000000000000000000000000034 ++:105C70000000000000000000000000000000000024 ++:105C80000000000000000000000000000000000014 ++:105C90000000000000000000000000000000000004 ++:105CA00000000000000000000000000000000000F4 ++:105CB00000000000000000000000000000000000E4 ++:105CC00000000000000000000000000000000000D4 ++:105CD00000000000000000000000000000000000C4 ++:105CE00000000000000000000000000000000000B4 ++:105CF00000000000000000000000000000000000A4 ++:105D00000000000000000000000000000000000093 ++:105D10000000000000000000000000000000000083 ++:105D20000000000000000000000000000000000073 ++:105D30000000000000000000000000000000000063 ++:105D40000000000000000000000000000000000053 ++:105D50000000000000000000000000000000000043 ++:105D60000000000000000000000000000000000033 ++:105D70000000000000000000000000000000000023 ++:105D80000000000000000000000000000000000013 ++:105D90000000000000000000000000000000000003 ++:105DA00000000000000000000000000000000000F3 ++:105DB00000000000000000000000000000000000E3 ++:105DC00000000000000000000000000000000000D3 ++:105DD00000000000000000000000000000000000C3 ++:105DE00000000000000000000000000000000000B3 ++:105DF00000000000000000000000000000000000A3 ++:105E00000000000000000000000000000000000092 ++:105E10000000000000000000000000000000000082 ++:105E2000000000000000000000000000000050B072 ++:105E3000C308080027989C5000C308000027B89C9E ++:105E400050804300000834001C3080C1060000115F ++:105E50000C000090C004003F3FA0443020C0CF0F92 ++:105E60000B042C080090000108000324804000016E ++:105E7000C0000920102000304002080100008430DA ++:105E8000F3034002333FD010509003010234041456 ++:105E9000A44000020D0105310400001000C0000301 ++:105EA0001000EC300000C00E01000C00007002C0B9 ++:105EB000010302240C3000C10A00000B1040003026 ++:105EC000400208033024C43080C30A00000B0CC019 ++:105ED0009010C3040000110C0000900001040003A6 ++:105EE0002480408000C00009201008F0A0820B0C24 ++:105EF0002526100850A3C2C00009030CF000B0C052 ++:105F0000000C09318C000010C2040000110C684024 ++:105F10004000C0000420008C90000201010003102A ++:105F200040003042020804021008F012830B0C25D6 ++:105F30002B100850A3C2400009030C40B00200C05F ++:105F4000020410000C9000C2000C09310CE0B002F9 ++:105F500000C0022305008430000140040300002437 ++:105F6000400002C000092010400030400208040830 ++:105F7000000C90000281000F30B8C050A1038100D6 ++:105F8000352A8C009030C0800E000B0CC09010C3DE ++:105F9000040000218C500010C10000000910800096 ++:105FA00030010104002310200030400208040210D8 ++:105FB00008F080820B0C1523100850A3C24800097A ++:105FC000030C40B00200C0020410000C9000C2009C ++:105FD0000C09310CE0B00200C00223010084300043 ++:105FE00000400403000024400002C00009201040CB ++:105FF00000304002080408000C90000281003F308D ++:10600000B8C05023038100352A8C0C001000010019 ++:106010001B00240C3032000D0135268C00007082EC ++:106020008F0935060C000070C200000300D4185020 ++:1060300093000000000000000000000000000000CD ++:106040000000000000000000000000000000000050 ++:106050000000000000000000000000000000000040 ++:106060000000000000000000000000000000000030 ++:106070000000000000000000000000000000000020 ++:106080000000000000000000000000000000000010 ++:106090000000000000000000000000000000000000 ++:1060A00000000000000000000000000000000000F0 ++:1060B00000000000000000000000000000000000E0 ++:1060C00000000000000000000000000000000000D0 ++:1060D00000000000000000000000000000000000C0 ++:1060E00000000000000000000000000000000000B0 ++:1060F00000000000000000000000000000000000A0 ++:10610000000000000000000000000000000000008F ++:10611000000000000000000000000000000000007F ++:10612000000000000000000000000000000000006F ++:10613000000000000000000000000000000000005F ++:10614000000000000000000000000000000000004F ++:10615000000000000000000000000000000000003F ++:10616000000000000000000000000000000000002F ++:10617000000000000000000000000000000000001F ++:10618000000000000000000000000000000000000F ++:1061900000000000000000000000000000000000FF ++:1061A00000000000000000000000000000000000EF ++:1061B00000000000000000000000000000000000DF ++:1061C00000000000000000000000000000000000CF ++:1061D00000000000000000000000000000000000BF ++:1061E00000000000000000000000000000000000AF ++:1061F000000000000000000000000000000000009F ++:10620000000000000000000000000000000000008E ++:10621000000000000000000000000000000000007E ++:10622000000000000000000000000000000000006E ++:10623000000000000000000000000000000000005E ++:10624000000000000000000000000000000000004E ++:10625000000000000000000000000000000000003E ++:10626000000000000000000000000000000000002E ++:10627000000000000000000000000000000000001E ++:10628000000000000000000000000000000000000E ++:1062900000000000000000000000000000000000FE ++:1062A000000000000000000000000000000050009E ++:1062B00000000000000000000000000000000000DE ++:1062C00000000000000000000000000000000000CE ++:1062D00000000000000000000000000000000000BE ++:1062E00000000000000000000000000000000000AE ++:1062F000000000000000000000000000000000009E ++:10630000000000000000000000000000000000008D ++:10631000000000000000000000000000000000007D ++:10632000000000000000000000000000000000006D ++:10633000000000000000000000000000000000005D ++:10634000000000000000000000000000000000004D ++:10635000000000000000000000000000000000003D ++:10636000000000000000000000000000000000002D ++:10637000000000000000000000000000000000001D ++:10638000000000000000000000000000000000000D ++:1063900000000000000000000000000000000000FD ++:1063A00000000000000000000000000000000000ED ++:1063B00000000000000000000000000000000000DD ++:1063C00000000000000000000000000000000000CD ++:1063D00000000000000000000000000000000000BD ++:1063E00000000000000000000000000000000000AD ++:1063F000000000000000000000000000000000009D ++:10640000000000000000000000000000000000008C ++:10641000000000000000000000000000000000007C ++:10642000000000000000000000000000000000006C ++:10643000000000000000000000000000000000005C ++:10644000000000000000000000000000000000004C ++:10645000000000000000000000000000000000003C ++:10646000000000000000000000000000000000002C ++:10647000000000000000000000000000000000001C ++:10648000000000000000000000000000000000000C ++:1064900000000000000000000000000000000000FC ++:1064A00000000000000000000000000000000000EC ++:1064B00000000000000000000000000000000000DC ++:1064C00000000000000000000000000000000000CC ++:1064D00000000000000000000000000000000000BC ++:1064E00000000000000000000000000000000000AC ++:1064F000000000000000000000000000000000009C ++:10650000000000000000000000000000000000008B ++:10651000000000000000000000000000000000007B ++:10652000000000000000000000000000000000006B ++:10653000000000000000000000000000000000005B ++:10654000000000000000000000000000000000004B ++:10655000000000000000000000000000000000003B ++:10656000000000000000000000000000000000002B ++:10657000000000000000000000000000000000001B ++:10658000000000000000000000000000000000000B ++:1065900000000000000000000000000000000000FB ++:1065A00000000000000000000000000000000000EB ++:1065B00000000000000000000000000000000000DB ++:1065C00000000000000000000000000000000000CB ++:1065D00000000000000000000000000000000000BB ++:1065E00000000000000000000000000000000000AB ++:1065F000000000000000000000000000000000009B ++:10660000000000000000000000000000000000008A ++:10661000000000000000000000000000000000007A ++:10662000000000000000000000000000000000006A ++:10663000000000000000000000000000000000005A ++:10664000000000000000000000000000000000004A ++:10665000000000000000000000000000000000003A ++:10666000000000000000000000000000000000002A ++:10667000000000000000000000000000000000001A ++:10668000000000000000000000000000000000000A ++:1066900000000000000000000000000000000000FA ++:1066A00000000000000000000000000000000000EA ++:1066B00000000000000000000000000000000000DA ++:1066C00000000000000000000000000000000000CA ++:1066D00000000000000000000000000000000000BA ++:1066E00000000000000000000000000000000000AA ++:1066F000000000000000000000000000000000009A ++:106700000000000000000000000000000000000089 ++:106710000000000000000000000000000000000079 ++:106720000000000000000000000000000000000069 ++:106730000000000000000000000000000000000059 ++:106740000000000000000000000000000000000049 ++:106750000000000000000000000000000000000039 ++:106760000000000000000000000000000000000029 ++:106770000000000000000000000000000000000019 ++:106780000000000000000000000000000000000009 ++:1067900000000000000000000000000000000000F9 ++:1067A00000000000000000000000000000000000E9 ++:1067B00000000000000000000000000000000000D9 ++:1067C00000000000000000000000000000000000C9 ++:1067D00000000000000000000000000000000000B9 ++:1067E00000000000000000000000000000000000A9 ++:1067F0000000000000000000000000000000000099 ++:106800000000000000000000000000000000000088 ++:106810000000000000000000000000000000000078 ++:106820000000000000000000000000000000000068 ++:106830000000000000000000000000000000000058 ++:106840000000000000000000000000000000000048 ++:106850000000000000000000000000000000000038 ++:106860000000000000000000000000000000000028 ++:106870000000000000000000000000000000000018 ++:106880000000000000000000000000000000000008 ++:1068900000000000000000000000000000000000F8 ++:1068A00000000000000000000000000000000000E8 ++:1068B00000000000000000000000000000000000D8 ++:1068C00000000000000000000000000000000000C8 ++:1068D00000000000000000000000000000000000B8 ++:1068E00000000000000000000000000000000000A8 ++:1068F0000000000000000000000000000000000098 ++:106900000000000000000000000000000000000087 ++:106910000000000000000000000000000000000077 ++:106920000000000000000000000000000000000067 ++:106930000000000000000000000000000000000057 ++:106940000000000000000000000000000000000047 ++:106950000000000000000000000000000000000037 ++:106960000000000000000000000000000000000027 ++:106970000000000000000000000000000000000017 ++:106980000000000000000000000000000000000007 ++:1069900000000000000000000000000000000000F7 ++:1069A00000000000000000000000000000000000E7 ++:1069B00000000000000000000000000000000000D7 ++:1069C00000000000000000000000000000000000C7 ++:1069D00000000000000000000000000000000000B7 ++:1069E00000000000000000000000000000000000A7 ++:1069F0000000000000000000000000000000000097 ++:106A00000000000000000000000000000000000086 ++:106A10000000000000000000000000000000000076 ++:106A20000000000000000000000000000000000066 ++:106A30000000000000000000000000000000000056 ++:106A40000000000000000000000000000000000046 ++:106A50000000000000000000000000000000000036 ++:106A60000000000000000000000000000000000026 ++:106A70000000000000000000000000000000000016 ++:106A80000000000000000000000000000000000006 ++:106A900000000000000000000000000000000000F6 ++:106AA00000000000000000000000000000000000E6 ++:106AB00000000000000000000000000000000000D6 ++:106AC00000000000000000000000000000000000C6 ++:106AD00000000000000000000000000000000000B6 ++:106AE00000000000000000000000000000000000A6 ++:106AF0000000000000000000000000000000000096 ++:106B00000000000000000000000000000000000085 ++:106B10000000000000000000000000000000000075 ++:106B20000000000000000000000000000000000065 ++:106B30000000000000000000000000000000000055 ++:106B40000000000000000000000000000000000045 ++:106B50000000000000000000000000000000000035 ++:106B60000000000000000000000000000000000025 ++:106B70000000000000000000000000000000000015 ++:106B80000000000000000000000000000000000005 ++:106B900000000000000000000000000000000000F5 ++:106BA00000000000000000000000000000000000E5 ++:106BB00000000000000000000000000000000000D5 ++:106BC00000000000000000000000000000000000C5 ++:106BD00000000000000000000000000000000000B5 ++:106BE00000000000000000000000000000000000A5 ++:106BF0000000000000000000000000000000000095 ++:106C00000000000000000000000000000000000084 ++:106C10000000000000000000000000000000000074 ++:106C20000000000000000000000000000000000064 ++:106C30000000000000000000000000000000000054 ++:106C40000000000000000000000000000000000044 ++:106C50000000000000000000000000000000000034 ++:106C60000000000000000000000000000000000024 ++:106C70000000000000000000000000000000000014 ++:106C80000000000000000000000000000000000004 ++:106C900000000000000000000000000000000000F4 ++:106CA00000000000000000000000000000000000E4 ++:106CB00000000000000000000000000000000000D4 ++:106CC00000000000000000000000000000000000C4 ++:106CD00000000000000000000000000000000000B4 ++:106CE00000000000000000000000000000000000A4 ++:106CF0000000000000000000000000000000000094 ++:106D00000000000000000000000000000000000083 ++:106D10000000000000000000000000000000000073 ++:106D20000000000000000000000000000000000063 ++:106D30000000000000000000000000000000000053 ++:106D40000000000000000000000000000000000043 ++:106D50000000000000000000000000000000000033 ++:106D60000000000000000000000000000000000023 ++:106D70000000000000000000000000000000000013 ++:106D80000000000000000000000000000000000003 ++:106D900000000000000000000000000000000000F3 ++:106DA00000000000000000000000000000000000E3 ++:106DB00000000000000000000000000000000000D3 ++:106DC00000000000000000000000000000000000C3 ++:106DD00000000000000000000000000000000000B3 ++:106DE00000000000000000000000000000000000A3 ++:106DF0000000000000000000000000000000000093 ++:106E00000000000000000000000000000000000082 ++:106E10000000000000000000000000000000000072 ++:106E20000000000000000000000000000000000062 ++:106E30000000000000000000000000000000000052 ++:106E40000000000000000000000000000000000042 ++:106E50000000000000000000000000000000000032 ++:106E60000000000000000000000000000000000022 ++:106E70000000000000000000000000000000000012 ++:106E80000000000000000000000000000000000002 ++:106E900000000000000000000000000000000000F2 ++:106EA00000000000000000000000000000000000E2 ++:106EB00000000000000000000000000000000000D2 ++:106EC00000000000000000000000000000000000C2 ++:106ED00000000000000000000000000000000000B2 ++:106EE00000000000000000000000000000000000A2 ++:106EF0000000000000000000000000000000000092 ++:106F00000000000000000000000000000000000081 ++:106F10000000000000000000000000000000000071 ++:106F20000000000000000000000000000000000061 ++:106F30000000000000000000000000000000000051 ++:106F40000000000000000000000000000000000041 ++:106F50000000000000000000000000000000000031 ++:106F60000000000000000000000000000000000021 ++:106F70000000000000000000000000000000000011 ++:106F80000000000000000000000000000000000001 ++:106F900000000000000000000000000000000000F1 ++:106FA00000000000000000000000000000000000E1 ++:106FB00000000000000000000000000000000000D1 ++:106FC00000000000000000000000000000000000C1 ++:106FD00000000000000000000000000000000000B1 ++:106FE00000000000000000000000000000000000A1 ++:106FF0000000000000000000000000000000000091 ++:107000000000000000000000000000000000000080 ++:107010000000000000000000000000000000000070 ++:107020000000000000000000000000000000000060 ++:107030000000000000000000000000000000000050 ++:107040000000000000000000000000000000000040 ++:107050000000000000000000000000000000000030 ++:107060000000000000000000000000000000000020 ++:107070000000000000000000000000000000000010 ++:107080000000000000000000000000000000000000 ++:1070900000000000000000000000000000000000F0 ++:1070A00000000000000000000000000000000000E0 ++:1070B00000000000000000000000000000000000D0 ++:1070C00000000000000000000000000000000000C0 ++:1070D00000000000000000000000000000000000B0 ++:1070E00000000000000000000000000000000000A0 ++:1070F0000000000000000000000000000000000090 ++:10710000000000000000000000000000000000007F ++:10711000000000000000000000000000000000006F ++:10712000000000000000000000000000000000005F ++:10713000000000000000000000000000000000004F ++:10714000000000000000000000000000000000003F ++:10715000000000000000000000000000000000002F ++:10716000000000000000000000000000000000001F ++:10717000000000000000000000000000000000000F ++:1071800000000000000000000000000000000000FF ++:1071900000000000000000000000000000000000EF ++:1071A00000000000000000000000000000000000DF ++:1071B00000000000000000000000000000000000CF ++:1071C00000000000000000000000000000000000BF ++:1071D00000000000000000000000000000000000AF ++:1071E000000000000000000000000000000000009F ++:1071F000000000000000000000000000000000008F ++:10720000000000000000000000000000000000007E ++:10721000000000000000000000000000000000006E ++:10722000000000000000000000000000000000005E ++:10723000000000000000000000000000000000004E ++:10724000000000000000000000000000000000003E ++:10725000000000000000000000000000000000002E ++:10726000000000000000000000000000000000001E ++:10727000000000000000000000000000000000000E ++:1072800000000000000000000000000000000000FE ++:1072900000000000000000000000000000000000EE ++:1072A00000000000000000000000000000000000DE ++:1072B00000000000000000000000000000000000CE ++:1072C00000000000000000000000000000000000BE ++:1072D00000000000000000000000000000000000AE ++:1072E000000000000000000000000000000000009E ++:1072F000000000000000000000000000000000008E ++:10730000000000000000000000000000000000007D ++:10731000000000000000000000000000000000006D ++:10732000000000000000000000000000000000005D ++:10733000000000000000000000000000000000004D ++:10734000000000000000000000000000000000003D ++:10735000000000000000000000000000000000002D ++:10736000000000000000000000000000000000001D ++:10737000000000000000000000000000000000000D ++:1073800000000000000000000000000000000000FD ++:1073900000000000000000000000000000000000ED ++:1073A00000000000000000000000000000000000DD ++:1073B00000000000000000000000000000000000CD ++:1073C00000000000000000000000000000000000BD ++:1073D00000000000000000000000000000000000AD ++:1073E000000000000000000000000000000000009D ++:1073F000000000000000000000000000000000008D ++:10740000000000000000000000000000000000007C ++:10741000000000000000000000000000000000006C ++:10742000000000000000000000000000000000005C ++:10743000000000000000000000000000000000004C ++:10744000000000000000000000000000000000003C ++:10745000000000000000000000000000000000002C ++:10746000000000000000000000000000000000001C ++:10747000000000000000000000000000000000000C ++:1074800000000000000000000000000000000000FC ++:1074900000000000000000000000000000000000EC ++:1074A00000000000000000000000000000000000DC ++:1074B00000000000000000000000000000000000CC ++:1074C00000000000000000000000000000000000BC ++:1074D00000000000000000000000000000000000AC ++:1074E000000000000000000000000000000000009C ++:1074F000000000000000000000000000000000008C ++:10750000000000000000000000000000000000007B ++:10751000000000000000000000000000000000006B ++:10752000000000000000000000000000000000005B ++:10753000000000000000000000000000000000004B ++:10754000000000000000000000000000000000003B ++:10755000000000000000000000000000000000002B ++:10756000000000000000000000000000000000001B ++:10757000000000000000000000000000000000000B ++:1075800000000000000000000000000000000000FB ++:1075900000000000000000000000000000000000EB ++:1075A00000000000000000000000000000000000DB ++:1075B00000000000000000000000000000000000CB ++:1075C00000000000000000000000000000000000BB ++:1075D00000000000000000000000000000000000AB ++:1075E000000000000000000000000000000000009B ++:1075F000000000000000000000000000000000008B ++:10760000000000000000000000000000000000007A ++:10761000000000000000000000000000000000006A ++:10762000000000000000000000000000000000005A ++:10763000000000000000000000000000000000004A ++:10764000000000000000000000000000000000003A ++:10765000000000000000000000000000000000002A ++:10766000000000000000000000000000000000001A ++:10767000000000000000000000000000000000000A ++:1076800000000000000000000000000000000000FA ++:1076900000000000000000000000000000000000EA ++:1076A00000000000000000000000000000000000DA ++:1076B00000000000000000000000000000000000CA ++:1076C00000000000000000000000000000000000BA ++:1076D00000000000000000000000000000000000AA ++:1076E000000000000000000000000000000000009A ++:1076F000000000000000000000000000000000008A ++:107700000000000000000000000000000000000079 ++:107710000000000000000000000000000000000069 ++:107720000000000000000000000000000000000059 ++:107730000000000000000000000000000000000049 ++:107740000000000000000000000000000000000039 ++:107750000000000000000000000000000000000029 ++:107760000000000000000000000000000000000019 ++:107770000000000000000000000000000000000009 ++:1077800000000000000000000000000000000000F9 ++:1077900000000000000000000000000000000000E9 ++:1077A00000000000000000000000000000000000D9 ++:1077B00000000000000000000000000000000000C9 ++:1077C00000000000000000000000000000000000B9 ++:1077D00000000000000000000000000000000000A9 ++:1077E0000000000000000000000000000000000099 ++:1077F0000000000000000000000000000000000089 ++:107800000000000000000000000000000000000078 ++:107810000000000000000000000000000000000068 ++:107820000000000000000000000000000000000058 ++:107830000000000000000000000000000000000048 ++:107840000000000000000000000000000000000038 ++:107850000000000000000000000000000000000028 ++:107860000000000000000000000000000000000018 ++:107870000000000000000000000000000000000008 ++:1078800000000000000000000000000000000000F8 ++:1078900000000000000000000000000000000000E8 ++:1078A00000000000000000000000000000000000D8 ++:1078B00000000000000000000000000000000000C8 ++:1078C00000000000000000000000000000000000B8 ++:1078D00000000000000000000000000000000000A8 ++:1078E0000000000000000000000000000000000098 ++:1078F0000000000000000000000000000000000088 ++:107900000000000000000000000000000000000077 ++:107910000000000000000000000000000000000067 ++:107920000000000000000000000000000000000057 ++:107930000000000000000000000000000000000047 ++:107940000000000000000000000000000000000037 ++:107950000000000000000000000000000000000027 ++:107960000000000000000000000000000000000017 ++:107970000000000000000000000000000000000007 ++:1079800000000000000000000000000000000000F7 ++:1079900000000000000000000000000000000000E7 ++:1079A00000000000000000000000000000000000D7 ++:1079B00000000000000000000000000000000000C7 ++:1079C00000000000000000000000000000000000B7 ++:1079D00000000000000000000000000000000000A7 ++:1079E0000000000000000000000000000000000097 ++:1079F0000000000000000000000000000000000087 ++:107A00000000000000000000000000000000000076 ++:107A10000000000000000000000000000000000066 ++:107A20000000000000000000000000000000000056 ++:107A30000000000000000000000000000000000046 ++:107A40000000000000000000000000000000000036 ++:107A50000000000000000000000000000000000026 ++:107A60000000000000000000000000000000000016 ++:107A70000000000000000000000000000000000006 ++:107A800000000000000000000000000000000000F6 ++:107A900000000000000000000000000000000000E6 ++:107AA00000000000000000000000000000000000D6 ++:107AB00000000000000000000000000000000000C6 ++:107AC00000000000000000000000000000000000B6 ++:107AD00000000000000000000000000000000000A6 ++:107AE0000000000000000000000000000000000096 ++:107AF0000000000000000000000000000000000086 ++:107B00000000000000000000000000000000000075 ++:107B10000000000000000000000000000000000065 ++:107B20000000000000000000000000000000000055 ++:107B30000000000000000000000000000000000045 ++:107B40000000000000000000000000000000000035 ++:107B50000000000000000000000000000000000025 ++:107B60000000000000000000000000000000000015 ++:107B70000000000000000000000000000000000005 ++:107B800000000000000000000000000000000000F5 ++:107B900000000000000000000000000000000000E5 ++:107BA00000000000000000000000000000000000D5 ++:107BB00000000000000000000000000000000000C5 ++:107BC00000000000000000000000000000000000B5 ++:107BD00000000000000000000000000000000000A5 ++:107BE0000000000000000000000000000000000095 ++:107BF0000000000000000000000000000000000085 ++:107C00000000000000000000000000000000000074 ++:107C10000000000000000000000000000000000064 ++:107C20000000000000000000000000000000000054 ++:107C30000000000000000000000000000000000044 ++:107C40000000000000000000000000000000000034 ++:107C50000000000000000000000000000000000024 ++:107C60000000000000000000000000000000000014 ++:107C70000000000000000000000000000000000004 ++:107C800000000000000000000000000000000000F4 ++:107C900000000000000000000000000000000000E4 ++:107CA00000000000000000000000000000000000D4 ++:107CB00000000000000000000000000000000000C4 ++:107CC00000000000000000000000000000000000B4 ++:107CD00000000000000000000000000000000000A4 ++:107CE0000000000000000000000000000000000094 ++:107CF0000000000000000000000000000000000084 ++:107D00000000000000000000000000000000000073 ++:107D10000000000000000000000000000000000063 ++:107D20000000000000000000000000000000000053 ++:107D30000000000000000000000000000000000043 ++:107D40000000000000000000000000000000000033 ++:107D50000000000000000000000000000000000023 ++:107D60000000000000000000000000000000000013 ++:107D70000000000000000000000000000000000003 ++:107D800000000000000000000000000000000000F3 ++:107D900000000000000000000000000000000000E3 ++:107DA00000000000000000000000000000000000D3 ++:107DB00000000000000000000000000000000000C3 ++:107DC00000000000000000000000000000000000B3 ++:107DD00000000000000000000000000000000000A3 ++:107DE0000000000000000000000000000000000093 ++:107DF0000000000000000000000000000000000083 ++:107E00000000000000000000000000000000000072 ++:107E10000000000000000000000000000000000062 ++:107E20000000000000000000000000000000000052 ++:107E30000000000000000000000000000000000042 ++:107E40000000000000000000000000000000000032 ++:107E50000000000000000000000000000000000022 ++:107E60000000000000000000000000000000000012 ++:107E70000000000000000000000000000000000002 ++:107E800000000000000000000000000000000000F2 ++:107E900000000000000000000000000000000000E2 ++:107EA00000000000000000000000000000000000D2 ++:107EB00000000000000000000000000000000000C2 ++:107EC00000000000000000000000000000000000B2 ++:107ED00000000000000000000000000000000000A2 ++:107EE0000000000000000000000000000000000092 ++:107EF0000000000000000000000000000000000082 ++:107F00000000000000000000000000000000000071 ++:107F10000000000000000000000000000000000061 ++:107F20000000000000000000000000000000000051 ++:107F30000000000000000000000000000000000041 ++:107F40000000000000000000000000000000000031 ++:107F50000000000000000000000000000000000021 ++:107F60000000000000000000000000000000000011 ++:107F70000000000000000000000000000000000001 ++:107F800000000000000000000000000000000000F1 ++:107F900000000000000000000000000000000000E1 ++:107FA00000000000000000000000000000000000D1 ++:107FB00000000000000000000000000000000000C1 ++:107FC00000000000000000000000000000000000B1 ++:107FD00000000000000000000000000000000000A1 ++:107FE0000000000000000000000000000000000091 ++:107FF0000000000000000000000000000000000081 ++:108000000000000000000000000000000000000070 ++:108010000000000000000000000000000000000060 ++:108020000000000000000000000000000000000050 ++:108030000000000000000000000000000000000040 ++:108040000000000000000000000000000000000030 ++:108050000000000000000000000000000000000020 ++:108060000000000000000000000000000000000010 ++:108070000000000000000000000000000000000000 ++:1080800000000000000000000000000000000000F0 ++:1080900000000000000000000000000000000000E0 ++:1080A00000000000000000000000000000000000D0 ++:1080B00000000000000000000000000000000000C0 ++:1080C00000000000000000000000000000000000B0 ++:1080D00000000000000000000000000000000000A0 ++:1080E0000000000000000000000000000000000090 ++:1080F0000000000000000000000000000000000080 ++:10810000000000000000000000000000000000006F ++:10811000000000000000000000000000000000005F ++:10812000000000000000000000000000000000004F ++:10813000000000000000000000000000000000003F ++:10814000000000000000000000000000000000002F ++:10815000000000000000000000000000000000001F ++:10816000000000000000000000000000000000000F ++:1081700000000000000000000000000000000000FF ++:1081800000000000000000000000000000000000EF ++:1081900000000000000000000000000000000000DF ++:1081A00000000000000000000000000000000000CF ++:1081B00000000000000000000000000000000000BF ++:1081C00000000000000000000000000000000000AF ++:1081D000000000000000000000000000000000009F ++:1081E000000000000000000000000000000000008F ++:1081F000000000000000000000000000000000007F ++:10820000000000000000000000000000000000006E ++:10821000000000000000000000000000000000005E ++:10822000000000000000000000000000000000004E ++:10823000000000000000000000000000000000003E ++:10824000000000000000000000000000000000002E ++:10825000000000000000000000000000000000001E ++:10826000000000000000000000000000000000000E ++:1082700000000000000000000000000000000000FE ++:1082800000000000000000000000000000000000EE ++:1082900000000000000000000000000000000000DE ++:1082A00000000000000000000000000000000000CE ++:1082B00000000000000000000000000000000000BE ++:1082C00000000000000000000000000000000000AE ++:1082D000000000000000000000000000000000009E ++:1082E000000000000000000000000000000000008E ++:1082F000000000000000000000000000000000007E ++:10830000000000000000000000000000000000006D ++:10831000000000000000000000000000000000005D ++:10832000000000000000000000000000000000004D ++:10833000000000000000000000000000000000003D ++:10834000000000000000000000000000000000002D ++:10835000000000000000000000000000000000001D ++:10836000000000000000000000000000000000000D ++:1083700000000000000000000000000000000000FD ++:1083800000000000000000000000000000000000ED ++:1083900000000000000000000000000000000000DD ++:1083A00000000000000000000000000000000000CD ++:1083B00000000000000000000000000000000000BD ++:1083C00000000000000000000000000000000000AD ++:1083D000000000000000000000000000000000009D ++:1083E000000000000000000000000000000000008D ++:1083F000000000000000000000000000000000007D ++:10840000000000000000000000000000000000006C ++:10841000000000000000000000000000000000005C ++:10842000000000000000000000000000000000004C ++:10843000000000000000000000000000000000003C ++:10844000000000000000000000000000000000002C ++:10845000000000000000000000000000000000001C ++:10846000000000000000000000000000000000000C ++:1084700000000000000000000000000000000000FC ++:1084800000000000000000000000000000000000EC ++:1084900000000000000000000000000000000000DC ++:1084A00000000000000000000000000000000000CC ++:1084B00000000000000000000000000000000000BC ++:1084C00000000000000000000000000000000000AC ++:1084D000000000000000000000000000000000009C ++:1084E000000000000000000000000000000000008C ++:1084F000000000000000000000000000000000007C ++:10850000000000000000000000000000000000006B ++:10851000000000000000000000000000000000005B ++:10852000000000000000000000000000000000004B ++:10853000000000000000000000000000000000003B ++:10854000000000000000000000000000000000002B ++:10855000000000000000000000000000000000001B ++:10856000000000000000000000000000000000000B ++:1085700000000000000000000000000000000000FB ++:1085800000000000000000000000000000000000EB ++:1085900000000000000000000000000000000000DB ++:1085A00000000000000000000000000000000000CB ++:1085B00000000000000000000000000000000000BB ++:1085C00000000000000000000000000000000000AB ++:1085D000000000000000000000000000000000009B ++:1085E000000000000000000000000000000000008B ++:1085F000000000000000000000000000000000007B ++:10860000000000000000000000000000000000006A ++:10861000000000000000000000000000000000005A ++:10862000000000000000000000000000000000004A ++:10863000000000000000000000000000000000003A ++:10864000000000000000000000000000000000002A ++:10865000000000000000000000000000000000001A ++:10866000000000000000000000000000000000000A ++:1086700000000000000000000000000000000000FA ++:1086800000000000000000000000000000000000EA ++:1086900000000000000000000000000000000000DA ++:1086A00000000000000000000000000000000000CA ++:1086B00000000000000000000000000000000000BA ++:1086C00000000000000000000000000000000000AA ++:1086D000000000000000000000000000000000009A ++:1086E000000000000000000000000000000000008A ++:1086F000000000000000000000000000000000007A ++:108700000000000000000000000000000000000069 ++:108710000000000000000000000000000000000059 ++:108720000000000000000000000000000000000049 ++:108730000000000000000000000000000000000039 ++:108740000000000000000000000000000000000029 ++:108750000000000000000000000000000000000019 ++:108760000000000000000000000000000000000009 ++:1087700000000000000000000000000000000000F9 ++:1087800000000000000000000000000000000000E9 ++:1087900000000000000000000000000000000000D9 ++:1087A00000000000000000000000000000000000C9 ++:1087B00000000000000000000000000000000000B9 ++:1087C00000000000000000000000000000000000A9 ++:1087D0000000000000000000000000000000000099 ++:1087E0000000000000000000000000000000000089 ++:1087F0000000000000000000000000000000000079 ++:108800000000000000000000000000000000000068 ++:108810000000000000000000000000000000000058 ++:108820000000000000000000000000000000000048 ++:108830000000000000000000000000000000000038 ++:108840000000000000000000000000000000000028 ++:108850000000000000000000000000000000000018 ++:108860000000000000000000000000000000000008 ++:1088700000000000000000000000000000000000F8 ++:1088800000000000000000000000000000000000E8 ++:1088900000000000000000000000000000000000D8 ++:1088A00000000000000000000000000000000000C8 ++:1088B00000000000000000000000000000000000B8 ++:1088C00000000000000000000000000000000000A8 ++:1088D0000000000000000000000000000000000098 ++:1088E0000000000000000000000000000000000088 ++:1088F0000000000000000000000000000000000078 ++:108900000000000000000000000000000000000067 ++:108910000000000000000000000000000000000057 ++:108920000000000000000000000000000000000047 ++:108930000000000000000000000000000000000037 ++:108940000000000000000000000000000000000027 ++:108950000000000000000000000000000000000017 ++:108960000000000000000000000000000000000007 ++:1089700000000000000000000000000000000000F7 ++:1089800000000000000000000000000000000000E7 ++:1089900000000000000000000000000000000000D7 ++:1089A00000000000000000000000000000000000C7 ++:1089B00000000000000000000000000000000000B7 ++:1089C00000000000000000000000000000000000A7 ++:1089D0000000000000000000000000000000000097 ++:1089E0000000000000000000000000000000000087 ++:1089F0000000000000000000000000000000000077 ++:108A00000000000000000000000000000000000066 ++:108A10000000000000000000000000000000000056 ++:108A20000000000000000000000000000000000046 ++:108A30000000000000000000000000000000000036 ++:108A40000000000000000000000000000000000026 ++:108A50000000000000000000000000000000000016 ++:108A60000000000000000000000000000000000006 ++:108A700000000000000000000000000000000000F6 ++:108A800000000000000000000000000000000000E6 ++:108A900000000000000000000000000000000000D6 ++:108AA00000000000000000000000000000000000C6 ++:108AB00000000000000000000000000000000000B6 ++:108AC00000000000000000000000000000000000A6 ++:108AD0000000000000000000000000000000000096 ++:108AE0000000000000000000000000000000000086 ++:108AF0000000000000000000000000000000000076 ++:108B00000000000000000000000000000000000065 ++:108B10000000000000000000000000000000000055 ++:108B20000000000000000000000000000000000045 ++:108B30000000000000000000000000000000000035 ++:108B40000000000000000000000000000000000025 ++:108B50000000000000000000000000000000000015 ++:108B60000000000000000000000000000000000005 ++:108B700000000000000000000000000000000000F5 ++:108B800000000000000000000000000000000000E5 ++:108B900000000000000000000000000000000000D5 ++:108BA00000000000000000000000000000000000C5 ++:108BB00000000000000000000000000000000000B5 ++:108BC00000000000000000000000000000000000A5 ++:108BD0000000000000000000000000000000000095 ++:108BE000000050B0C308080027989C5000C308003C ++:108BF0000027B89C50804300000834001C3080C11E ++:108C0000060000110C000090C004003F3FA044305B ++:108C100020C0CF0F0B042C08009000010800032493 ++:108C200080400001C00009201020003040020801EF ++:108C300000008430F3034002333FD0105090030112 ++:108C400002340414A44000020D0105310400001098 ++:108C500000C000031000EC300000C00E01000C004A ++:108C6000007002C0010302240C3000C10A00000B96 ++:108C700010400030400208033024C43080C30A0092 ++:108C8000000B0CC09010C3040000110C00009000F9 ++:108C9000010400032480408000C00009201008F077 ++:108CA000A0820B0C2526100850A3C2C00009030C9B ++:108CB000F000B0C0000C09318C000010C2040000AC ++:108CC000110C68404000C0000420008C900002019C ++:108CD0000100031040003042020804021008F012A4 ++:108CE000830B0C252B100850A3C2400009030C4035 ++:108CF000B00200C0020410000C9000C2000C093148 ++:108D00000CE0B00200C002230500843000014004E2 ++:108D100003000024400002C0000920104000304041 ++:108D200002080408000C90000281000F30B8C05007 ++:108D3000A1038100352A8C009030C0800E000B0CFE ++:108D4000C09010C3040000218C500010C10000002E ++:108D5000091080003001010400231020003040027F ++:108D60000804021008F080820B0C1523100850A391 ++:108D7000C2480009030C40B00200C0020410000CFD ++:108D80009000C2000C09310CE0B00200C0022301C7 ++:108D90000084300000400403000024400002C000B2 ++:108DA0000920104000304002080408000C90000226 ++:108DB00081003F30B8C05023038100352A8C0C005D ++:108DC000100001001B00240C3032000D0135268CF0 ++:108DD000000070828F0935060C000070C20000038D ++:108DE00000D41850930000000000000000000000B4 ++:108DF0000000000000000000000000000000000073 ++:108E00000000000000000000000000000000000062 ++:108E10000000000000000000000000000000000052 ++:108E20000000000000000000000000000000000042 ++:108E30000000000000000000000000000000000032 ++:108E40000000000000000000000000000000000022 ++:108E50000000000000000000000000000000000012 ++:108E60000000000000000000000000000000000002 ++:108E700000000000000000000000000000000000F2 ++:108E800000000000000000000000000000000000E2 ++:108E900000000000000000000000000000000000D2 ++:108EA00000000000000000000000000000000000C2 ++:108EB00000000000000000000000000000000000B2 ++:108EC00000000000000000000000000000000000A2 ++:108ED0000000000000000000000000000000000092 ++:108EE0000000000000000000000000000000000082 ++:108EF0000000000000000000000000000000000072 ++:108F00000000000000000000000000000000000061 ++:108F10000000000000000000000000000000000051 ++:108F20000000000000000000000000000000000041 ++:108F30000000000000000000000000000000000031 ++:108F40000000000000000000000000000000000021 ++:108F50000000000000000000000000000000000011 ++:108F60000000000000000000000000000000000001 ++:108F700000000000000000000000000000000000F1 ++:108F800000000000000000000000000000000000E1 ++:108F900000000000000000000000000000000000D1 ++:108FA00000000000000000000000000000000000C1 ++:108FB00000000000000000000000000000000000B1 ++:108FC00000000000000000000000000000000000A1 ++:108FD0000000000000000000000000000000000091 ++:108FE0000000000000000000000000000000000081 ++:108FF0000000000000000000000000000000000071 ++:109000000000000000000000000000000000000060 ++:109010000000000000000000000000000000000050 ++:109020000000000000000000000000000000000040 ++:109030000000000000000000000000000000000030 ++:109040000000000000000000000000000000000020 ++:109050000000000000000000000000000000000010 ++:1090600000005000000000000000000000000000B0 ++:1090700000000000000000000000000000000000F0 ++:1090800000000000000000000000000000000000E0 ++:1090900000000000000000000000000000000000D0 ++:1090A00000000000000000000000000000000000C0 ++:1090B00000000000000000000000000000000000B0 ++:1090C00000000000000000000000000000000000A0 ++:1090D0000000000000000000000000000000000090 ++:1090E0000000000000000000000000000000000080 ++:1090F0000000000000000000000000000000000070 ++:10910000000000000000000000000000000000005F ++:10911000000000000000000000000000000000004F ++:10912000000000000000000000000000000000003F ++:10913000000000000000000000000000000000002F ++:10914000000000000000000000000000000000001F ++:10915000000000000000000000000000000000000F ++:1091600000000000000000000000000000000000FF ++:1091700000000000000000000000000000000000EF ++:1091800000000000000000000000000000000000DF ++:1091900000000000000000000000000000000000CF ++:1091A00000000000000000000000000000000000BF ++:1091B00000000000000000000000000000000000AF ++:1091C000000000000000000000000000000000009F ++:1091D000000000000000000000000000000000008F ++:1091E000000000000000000000000000000000007F ++:1091F000000000000000000000000000000000006F ++:10920000000000000000000000000000000000005E ++:10921000000000000000000000000000000000004E ++:10922000000000000000000000000000000000003E ++:10923000000000000000000000000000000000002E ++:10924000000000000000000000000000000000001E ++:10925000000000000000000000000000000000000E ++:1092600000000000000000000000000000000000FE ++:1092700000000000000000000000000000000000EE ++:1092800000000000000000000000000000000000DE ++:1092900000000000000000000000000000000000CE ++:1092A00000000000000000000000000000000000BE ++:1092B00000000000000000000000000000000000AE ++:1092C000000000000000000000000000000000009E ++:1092D000000000000000000000000000000000008E ++:1092E000000000000000000000000000000000007E ++:1092F000000000000000000000000000000000006E ++:10930000000000000000000000000000000000005D ++:10931000000000000000000000000000000000004D ++:10932000000000000000000000000000000000003D ++:10933000000000000000000000000000000000002D ++:10934000000000000000000000000000000000001D ++:10935000000000000000000000000000000000000D ++:1093600000000000000000000000000000000000FD ++:1093700000000000000000000000000000000000ED ++:1093800000000000000000000000000000000000DD ++:1093900000000000000000000000000000000000CD ++:1093A00000000000000000000000000000000000BD ++:1093B00000000000000000000000000000000000AD ++:1093C000000000000000000000000000000000009D ++:1093D000000000000000000000000000000000008D ++:1093E000000000000000000000000000000000007D ++:1093F000000000000000000000000000000000006D ++:10940000000000000000000000000000000000005C ++:10941000000000000000000000000000000000004C ++:10942000000000000000000000000000000000003C ++:10943000000000000000000000000000000000002C ++:10944000000000000000000000000000000000001C ++:10945000000000000000000000000000000000000C ++:1094600000000000000000000000000000000000FC ++:1094700000000000000000000000000000000000EC ++:1094800000000000000000000000000000000000DC ++:1094900000000000000000000000000000000000CC ++:1094A00000000000000000000000000000000000BC ++:1094B00000000000000000000000000000000000AC ++:1094C000000000000000000000000000000000009C ++:1094D000000000000000000000000000000000008C ++:1094E000000000000000000000000000000000007C ++:1094F000000000000000000000000000000000006C ++:10950000000000000000000000000000000000005B ++:10951000000000000000000000000000000000004B ++:10952000000000000000000000000000000000003B ++:10953000000000000000000000000000000000002B ++:10954000000000000000000000000000000000001B ++:10955000000000000000000000000000000000000B ++:1095600000000000000000000000000000000000FB ++:1095700000000000000000000000000000000000EB ++:1095800000000000000000000000000000000000DB ++:1095900000000000000000000000000000000000CB ++:1095A00000000000000000000000000000000000BB ++:1095B00000000000000000000000000000000000AB ++:1095C000000000000000000000000000000000009B ++:1095D000000000000000000000000000000000008B ++:1095E000000000000000000000000000000000007B ++:1095F000000000000000000000000000000000006B ++:10960000000000000000000000000000000000005A ++:10961000000000000000000000000000000000004A ++:10962000000000000000000000000000000000003A ++:10963000000000000000000000000000000000002A ++:10964000000000000000000000000000000000001A ++:10965000000000000000000000000000000000000A ++:1096600000000000000000000000000000000000FA ++:1096700000000000000000000000000000000000EA ++:1096800000000000000000000000000000000000DA ++:1096900000000000000000000000000000000000CA ++:1096A00000000000000000000000000000000000BA ++:1096B00000000000000000000000000000000000AA ++:1096C000000000000000000000000000000000009A ++:1096D000000000000000000000000000000000008A ++:1096E000000000000000000000000000000000007A ++:1096F000000000000000000000000000000000006A ++:109700000000000000000000000000000000000059 ++:109710000000000000000000000000000000000049 ++:109720000000000000000000000000000000000039 ++:109730000000000000000000000000000000000029 ++:109740000000000000000000000000000000000019 ++:109750000000000000000000000000000000000009 ++:1097600000000000000000000000000000000000F9 ++:1097700000000000000000000000000000000000E9 ++:1097800000000000000000000000000000000000D9 ++:1097900000000000000000000000000000000000C9 ++:1097A00000000000000000000000000000000000B9 ++:1097B00000000000000000000000000000000000A9 ++:1097C0000000000000000000000000000000000099 ++:1097D0000000000000000000000000000000000089 ++:1097E0000000000000000000000000000000000079 ++:1097F0000000000000000000000000000000000069 ++:109800000000000000000000000000000000000058 ++:109810000000000000000000000000000000000048 ++:109820000000000000000000000000000000000038 ++:109830000000000000000000000000000000000028 ++:109840000000000000000000000000000000000018 ++:109850000000000000000000000000000000000008 ++:1098600000000000000000000000000000000000F8 ++:1098700000000000000000000000000000000000E8 ++:1098800000000000000000000000000000000000D8 ++:1098900000000000000000000000000000000000C8 ++:1098A00000000000000000000000000000000000B8 ++:1098B00000000000000000000000000000000000A8 ++:1098C0000000000000000000000000000000000098 ++:1098D0000000000000000000000000000000000088 ++:1098E0000000000000000000000000000000000078 ++:1098F0000000000000000000000000000000000068 ++:109900000000000000000000000000000000000057 ++:109910000000000000000000000000000000000047 ++:109920000000000000000000000000000000000037 ++:109930000000000000000000000000000000000027 ++:109940000000000000000000000000000000000017 ++:109950000000000000000000000000000000000007 ++:1099600000000000000000000000000000000000F7 ++:1099700000000000000000000000000000000000E7 ++:1099800000000000000000000000000000000000D7 ++:1099900000000000000000000000000000000000C7 ++:1099A00000000000000000000000000000000000B7 ++:1099B00000000000000000000000000000000000A7 ++:1099C0000000000000000000000000000000000097 ++:1099D0000000000000000000000000000000000087 ++:1099E0000000000000000000000000000000000077 ++:1099F0000000000000000000000000000000000067 ++:109A00000000000000000000000000000000000056 ++:109A10000000000000000000000000000000000046 ++:109A20000000000000000000000000000000000036 ++:109A30000000000000000000000000000000000026 ++:109A40000000000000000000000000000000000016 ++:109A50000000000000000000000000000000000006 ++:109A600000000000000000000000000000000000F6 ++:109A700000000000000000000000000000000000E6 ++:109A800000000000000000000000000000000000D6 ++:109A900000000000000000000000000000000000C6 ++:109AA00000000000000000000000000000000000B6 ++:109AB00000000000000000000000000000000000A6 ++:109AC0000000000000000000000000000000000096 ++:109AD0000000000000000000000000000000000086 ++:109AE0000000000000000000000000000000000076 ++:109AF0000000000000000000000000000000000066 ++:109B00000000000000000000000000000000000055 ++:109B10000000000000000000000000000000000045 ++:109B20000000000000000000000000000000000035 ++:109B30000000000000000000000000000000000025 ++:109B40000000000000000000000000000000000015 ++:109B50000000000000000000000000000000000005 ++:109B600000000000000000000000000000000000F5 ++:109B700000000000000000000000000000000000E5 ++:109B800000000000000000000000000000000000D5 ++:109B900000000000000000000000000000000000C5 ++:109BA00000000000000000000000000000000000B5 ++:109BB00000000000000000000000000000000000A5 ++:109BC0000000000000000000000000000000000095 ++:109BD0000000000000000000000000000000000085 ++:109BE0000000000000000000000000000000000075 ++:109BF0000000000000000000000000000000000065 ++:109C00000000000000000000000000000000000054 ++:109C10000000000000000000000000000000000044 ++:109C20000000000000000000000000000000000034 ++:109C30000000000000000000000000000000000024 ++:109C40000000000000000000000000000000000014 ++:109C50000000000000000000000000000000000004 ++:109C600000000000000000000000000000000000F4 ++:109C700000000000000000000000000000000000E4 ++:109C800000000000000000000000000000000000D4 ++:109C900000000000000000000000000000000000C4 ++:109CA00000000000000000000000000000000000B4 ++:109CB00000000000000000000000000000000000A4 ++:109CC0000000000000000000000000000000000094 ++:109CD0000000000000000000000000000000000084 ++:109CE0000000000000000000000000000000000074 ++:109CF0000000000000000000000000000000000064 ++:109D00000000000000000000000000000000000053 ++:109D10000000000000000000000000000000000043 ++:109D20000000000000000000000000000000000033 ++:109D30000000000000000000000000000000000023 ++:109D40000000000000000000000000000000000013 ++:109D50000000000000000000000000000000000003 ++:109D600000000000000000000000000000000000F3 ++:109D700000000000000000000000000000000000E3 ++:109D800000000000000000000000000000000000D3 ++:109D900000000000000000000000000000000000C3 ++:109DA00000000000000000000000000000000000B3 ++:109DB00000000000000000000000000000000000A3 ++:109DC0000000000000000000000000000000000093 ++:109DD0000000000000000000000000000000000083 ++:109DE0000000000000000000000000000000000073 ++:109DF0000000000000000000000000000000000063 ++:109E00000000000000000000000000000000000052 ++:109E10000000000000000000000000000000000042 ++:109E20000000000000000000000000000000000032 ++:109E30000000000000000000000000000000000022 ++:109E40000000000000000000000000000000000012 ++:109E50000000000000000000000000000000000002 ++:109E600000000000000000000000000000000000F2 ++:109E700000000000000000000000000000000000E2 ++:109E800000000000000000000000000000000000D2 ++:109E900000000000000000000000000000000000C2 ++:109EA00000000000000000000000000000000000B2 ++:109EB00000000000000000000000000000000000A2 ++:109EC0000000000000000000000000000000000092 ++:109ED0000000000000000000000000000000000082 ++:109EE0000000000000000000000000000000000072 ++:109EF0000000000000000000000000000000000062 ++:109F00000000000000000000000000000000000051 ++:109F10000000000000000000000000000000000041 ++:109F20000000000000000000000000000000000031 ++:109F30000000000000000000000000000000000021 ++:109F40000000000000000000000000000000000011 ++:109F50000000000000000000000000000000000001 ++:109F600000000000000000000000000000000000F1 ++:109F700000000000000000000000000000000000E1 ++:109F800000000000000000000000000000000000D1 ++:109F900000000000000000000000000000000000C1 ++:109FA00000000000000000000000000000000000B1 ++:109FB00000000000000000000000000000000000A1 ++:109FC0000000000000000000000000000000000091 ++:109FD0000000000000000000000000000000000081 ++:109FE0000000000000000000000000000000000071 ++:109FF0000000000000000000000000000000000061 ++:10A000000000000000000000000000000000000050 ++:10A010000000000000000000000000000000000040 ++:10A020000000000000000000000000000000000030 ++:10A030000000000000000000000000000000000020 ++:10A040000000000000000000000000000000000010 ++:10A050000000000000000000000000000000000000 ++:10A0600000000000000000000000000000000000F0 ++:10A0700000000000000000000000000000000000E0 ++:10A0800000000000000000000000000000000000D0 ++:10A0900000000000000000000000000000000000C0 ++:10A0A00000000000000000000000000000000000B0 ++:10A0B00000000000000000000000000000000000A0 ++:10A0C0000000000000000000000000000000000090 ++:10A0D0000000000000000000000000000000000080 ++:10A0E0000000000000000000000000000000000070 ++:10A0F0000000000000000000000000000000000060 ++:10A10000000000000000000000000000000000004F ++:10A11000000000000000000000000000000000003F ++:10A12000000000000000000000000000000000002F ++:10A13000000000000000000000000000000000001F ++:10A14000000000000000000000000000000000000F ++:10A1500000000000000000000000000000000000FF ++:10A1600000000000000000000000000000000000EF ++:10A1700000000000000000000000000000000000DF ++:10A1800000000000000000000000000000000000CF ++:10A1900000000000000000000000000000000000BF ++:10A1A00000000000000000000000000000000000AF ++:10A1B000000000000000000000000000000000009F ++:10A1C000000000000000000000000000000000008F ++:10A1D000000000000000000000000000000000007F ++:10A1E000000000000000000000000000000000006F ++:10A1F000000000000000000000000000000000005F ++:10A20000000000000000000000000000000000004E ++:10A21000000000000000000000000000000000003E ++:10A22000000000000000000000000000000000002E ++:10A23000000000000000000000000000000000001E ++:10A24000000000000000000000000000000000000E ++:10A2500000000000000000000000000000000000FE ++:10A2600000000000000000000000000000000000EE ++:10A2700000000000000000000000000000000000DE ++:10A2800000000000000000000000000000000000CE ++:10A2900000000000000000000000000000000000BE ++:10A2A00000000000000000000000000000000000AE ++:10A2B000000000000000000000000000000000009E ++:10A2C000000000000000000000000000000000008E ++:10A2D000000000000000000000000000000000007E ++:10A2E000000000000000000000000000000000006E ++:10A2F000000000000000000000000000000000005E ++:10A30000000000000000000000000000000000004D ++:10A31000000000000000000000000000000000003D ++:10A32000000000000000000000000000000000002D ++:10A33000000000000000000000000000000000001D ++:10A34000000000000000000000000000000000000D ++:10A3500000000000000000000000000000000000FD ++:10A3600000000000000000000000000000000000ED ++:10A3700000000000000000000000000000000000DD ++:10A3800000000000000000000000000000000000CD ++:10A3900000000000000000000000000000000000BD ++:10A3A00000000000000000000000000000000000AD ++:10A3B000000000000000000000000000000000009D ++:10A3C000000000000000000000000000000000008D ++:10A3D000000000000000000000000000000000007D ++:10A3E000000000000000000000000000000000006D ++:10A3F000000000000000000000000000000000005D ++:10A40000000000000000000000000000000000004C ++:10A41000000000000000000000000000000000003C ++:10A42000000000000000000000000000000000002C ++:10A43000000000000000000000000000000000001C ++:10A44000000000000000000000000000000000000C ++:10A4500000000000000000000000000000000000FC ++:10A4600000000000000000000000000000000000EC ++:10A4700000000000000000000000000000000000DC ++:10A4800000000000000000000000000000000000CC ++:10A4900000000000000000000000000000000000BC ++:10A4A00000000000000000000000000000000000AC ++:10A4B000000000000000000000000000000000009C ++:10A4C000000000000000000000000000000000008C ++:10A4D000000000000000000000000000000000007C ++:10A4E000000000000000000000000000000000006C ++:10A4F000000000000000000000000000000000005C ++:10A50000000000000000000000000000000000004B ++:10A51000000000000000000000000000000000003B ++:10A52000000000000000000000000000000000002B ++:10A53000000000000000000000000000000000001B ++:10A54000000000000000000000000000000000000B ++:10A5500000000000000000000000000000000000FB ++:10A5600000000000000000000000000000000000EB ++:10A5700000000000000000000000000000000000DB ++:10A5800000000000000000000000000000000000CB ++:10A5900000000000000000000000000000000000BB ++:10A5A00000000000000000000000000000000000AB ++:10A5B000000000000000000000000000000000009B ++:10A5C000000000000000000000000000000000008B ++:10A5D000000000000000000000000000000000007B ++:10A5E000000000000000000000000000000000006B ++:10A5F000000000000000000000000000000000005B ++:10A60000000000000000000000000000000000004A ++:10A61000000000000000000000000000000000003A ++:10A62000000000000000000000000000000000002A ++:10A63000000000000000000000000000000000001A ++:10A64000000000000000000000000000000000000A ++:10A6500000000000000000000000000000000000FA ++:10A6600000000000000000000000000000000000EA ++:10A6700000000000000000000000000000000000DA ++:10A6800000000000000000000000000000000000CA ++:10A6900000000000000000000000000000000000BA ++:10A6A00000000000000000000000000000000000AA ++:10A6B000000000000000000000000000000000009A ++:10A6C000000000000000000000000000000000008A ++:10A6D000000000000000000000000000000000007A ++:10A6E000000000000000000000000000000000006A ++:10A6F000000000000000000000000000000000005A ++:10A700000000000000000000000000000000000049 ++:10A710000000000000000000000000000000000039 ++:10A720000000000000000000000000000000000029 ++:10A730000000000000000000000000000000000019 ++:10A740000000000000000000000000000000000009 ++:10A7500000000000000000000000000000000000F9 ++:10A7600000000000000000000000000000000000E9 ++:10A7700000000000000000000000000000000000D9 ++:10A7800000000000000000000000000000000000C9 ++:10A7900000000000000000000000000000000000B9 ++:10A7A00000000000000000000000000000000000A9 ++:10A7B0000000000000000000000000000000000099 ++:10A7C0000000000000000000000000000000000089 ++:10A7D0000000000000000000000000000000000079 ++:10A7E0000000000000000000000000000000000069 ++:10A7F0000000000000000000000000000000000059 ++:10A800000000000000000000000000000000000048 ++:10A810000000000000000000000000000000000038 ++:10A820000000000000000000000000000000000028 ++:10A830000000000000000000000000000000000018 ++:10A840000000000000000000000000000000000008 ++:10A8500000000000000000000000000000000000F8 ++:10A8600000000000000000000000000000000000E8 ++:10A8700000000000000000000000000000000000D8 ++:10A8800000000000000000000000000000000000C8 ++:10A8900000000000000000000000000000000000B8 ++:10A8A00000000000000000000000000000000000A8 ++:10A8B0000000000000000000000000000000000098 ++:10A8C0000000000000000000000000000000000088 ++:10A8D0000000000000000000000000000000000078 ++:10A8E0000000000000000000000000000000000068 ++:10A8F0000000000000000000000000000000000058 ++:10A900000000000000000000000000000000000047 ++:10A910000000000000000000000000000000000037 ++:10A920000000000000000000000000000000000027 ++:10A930000000000000000000000000000000000017 ++:10A940000000000000000000000000000000000007 ++:10A9500000000000000000000000000000000000F7 ++:10A9600000000000000000000000000000000000E7 ++:10A9700000000000000000000000000000000000D7 ++:10A9800000000000000000000000000000000000C7 ++:10A9900000000000000000000000000000000000B7 ++:10A9A00000000000000000000000000000000000A7 ++:10A9B0000000000000000000000000000000000097 ++:10A9C0000000000000000000000000000000000087 ++:10A9D0000000000000000000000000000000000077 ++:10A9E0000000000000000000000000000000000067 ++:10A9F0000000000000000000000000000000000057 ++:10AA00000000000000000000000000000000000046 ++:10AA10000000000000000000000000000000000036 ++:10AA20000000000000000000000000000000000026 ++:10AA30000000000000000000000000000000000016 ++:10AA40000000000000000000000000000000000006 ++:10AA500000000000000000000000000000000000F6 ++:10AA600000000000000000000000000000000000E6 ++:10AA700000000000000000000000000000000000D6 ++:10AA800000000000000000000000000000000000C6 ++:10AA900000000000000000000000000000000000B6 ++:10AAA00000000000000000000000000000000000A6 ++:10AAB0000000000000000000000000000000000096 ++:10AAC0000000000000000000000000000000000086 ++:10AAD0000000000000000000000000000000000076 ++:10AAE0000000000000000000000000000000000066 ++:10AAF0000000000000000000000000000000000056 ++:10AB00000000000000000000000000000000000045 ++:10AB10000000000000000000000000000000000035 ++:10AB20000000000000000000000000000000000025 ++:10AB30000000000000000000000000000000000015 ++:10AB40000000000000000000000000000000000005 ++:10AB500000000000000000000000000000000000F5 ++:10AB600000000000000000000000000000000000E5 ++:10AB700000000000000000000000000000000000D5 ++:10AB800000000000000000000000000000000000C5 ++:10AB900000000000000000000000000000000000B5 ++:10ABA00000000000000000000000000000000000A5 ++:10ABB0000000000000000000000000000000000095 ++:10ABC0000000000000000000000000000000000085 ++:10ABD0000000000000000000000000000000000075 ++:10ABE0000000000000000000000000000000000065 ++:10ABF0000000000000000000000000000000000055 ++:10AC00000000000000000000000000000000000044 ++:10AC10000000000000000000000000000000000034 ++:10AC20000000000000000000000000000000000024 ++:10AC30000000000000000000000000000000000014 ++:10AC40000000000000000000000000000000000004 ++:10AC500000000000000000000000000000000000F4 ++:10AC600000000000000000000000000000000000E4 ++:10AC700000000000000000000000000000000000D4 ++:10AC800000000000000000000000000000000000C4 ++:10AC900000000000000000000000000000000000B4 ++:10ACA00000000000000000000000000000000000A4 ++:10ACB0000000000000000000000000000000000094 ++:10ACC0000000000000000000000000000000000084 ++:10ACD0000000000000000000000000000000000074 ++:10ACE0000000000000000000000000000000000064 ++:10ACF0000000000000000000000000000000000054 ++:10AD00000000000000000000000000000000000043 ++:10AD10000000000000000000000000000000000033 ++:10AD20000000000000000000000000000000000023 ++:10AD30000000000000000000000000000000000013 ++:10AD40000000000000000000000000000000000003 ++:10AD500000000000000000000000000000000000F3 ++:10AD600000000000000000000000000000000000E3 ++:10AD700000000000000000000000000000000000D3 ++:10AD800000000000000000000000000000000000C3 ++:10AD900000000000000000000000000000000000B3 ++:10ADA00000000000000000000000000000000000A3 ++:10ADB0000000000000000000000000000000000093 ++:10ADC0000000000000000000000000000000000083 ++:10ADD0000000000000000000000000000000000073 ++:10ADE0000000000000000000000000000000000063 ++:10ADF0000000000000000000000000000000000053 ++:10AE00000000000000000000000000000000000042 ++:10AE10000000000000000000000000000000000032 ++:10AE20000000000000000000000000000000000022 ++:10AE30000000000000000000000000000000000012 ++:10AE40000000000000000000000000000000000002 ++:10AE500000000000000000000000000000000000F2 ++:10AE600000000000000000000000000000000000E2 ++:10AE700000000000000000000000000000000000D2 ++:10AE800000000000000000000000000000000000C2 ++:10AE900000000000000000000000000000000000B2 ++:10AEA00000000000000000000000000000000000A2 ++:10AEB0000000000000000000000000000000000092 ++:10AEC0000000000000000000000000000000000082 ++:10AED0000000000000000000000000000000000072 ++:10AEE0000000000000000000000000000000000062 ++:10AEF0000000000000000000000000000000000052 ++:10AF00000000000000000000000000000000000041 ++:10AF10000000000000000000000000000000000031 ++:10AF20000000000000000000000000000000000021 ++:10AF30000000000000000000000000000000000011 ++:10AF40000000000000000000000000000000000001 ++:10AF500000000000000000000000000000000000F1 ++:10AF600000000000000000000000000000000000E1 ++:10AF700000000000000000000000000000000000D1 ++:10AF800000000000000000000000000000000000C1 ++:10AF900000000000000000000000000000000000B1 ++:10AFA00000000000000000000000000000000000A1 ++:10AFB0000000000000000000000000000000000091 ++:10AFC0000000000000000000000000000000000081 ++:10AFD0000000000000000000000000000000000071 ++:10AFE0000000000000000000000000000000000061 ++:10AFF0000000000000000000000000000000000051 ++:10B000000000000000000000000000000000000040 ++:10B010000000000000000000000000000000000030 ++:10B020000000000000000000000000000000000020 ++:10B030000000000000000000000000000000000010 ++:10B040000000000000000000000000000000000000 ++:10B0500000000000000000000000000000000000F0 ++:10B0600000000000000000000000000000000000E0 ++:10B0700000000000000000000000000000000000D0 ++:10B0800000000000000000000000000000000000C0 ++:10B0900000000000000000000000000000000000B0 ++:10B0A00000000000000000000000000000000000A0 ++:10B0B0000000000000000000000000000000000090 ++:10B0C0000000000000000000000000000000000080 ++:10B0D0000000000000000000000000000000000070 ++:10B0E0000000000000000000000000000000000060 ++:10B0F0000000000000000000000000000000000050 ++:10B10000000000000000000000000000000000003F ++:10B11000000000000000000000000000000000002F ++:10B12000000000000000000000000000000000001F ++:10B13000000000000000000000000000000000000F ++:10B1400000000000000000000000000000000000FF ++:10B1500000000000000000000000000000000000EF ++:10B1600000000000000000000000000000000000DF ++:10B1700000000000000000000000000000000000CF ++:10B1800000000000000000000000000000000000BF ++:10B1900000000000000000000000000000000000AF ++:10B1A000000000000000000000000000000000009F ++:10B1B000000000000000000000000000000000008F ++:10B1C000000000000000000000000000000000007F ++:10B1D000000000000000000000000000000000006F ++:10B1E000000000000000000000000000000000005F ++:10B1F000000000000000000000000000000000004F ++:10B20000000000000000000000000000000000003E ++:10B21000000000000000000000000000000000002E ++:10B22000000000000000000000000000000000001E ++:10B23000000000000000000000000000000000000E ++:10B2400000000000000000000000000000000000FE ++:10B2500000000000000000000000000000000000EE ++:10B2600000000000000000000000000000000000DE ++:10B2700000000000000000000000000000000000CE ++:10B2800000000000000000000000000000000000BE ++:10B2900000000000000000000000000000000000AE ++:10B2A000000000000000000000000000000000009E ++:10B2B000000000000000000000000000000000008E ++:10B2C000000000000000000000000000000000007E ++:10B2D000000000000000000000000000000000006E ++:10B2E000000000000000000000000000000000005E ++:10B2F000000000000000000000000000000000004E ++:10B30000000000000000000000000000000000003D ++:10B31000000000000000000000000000000000002D ++:10B32000000000000000000000000000000000001D ++:10B33000000000000000000000000000000000000D ++:10B3400000000000000000000000000000000000FD ++:10B3500000000000000000000000000000000000ED ++:10B3600000000000000000000000000000000000DD ++:10B3700000000000000000000000000000000000CD ++:10B3800000000000000000000000000000000000BD ++:10B3900000000000000000000000000000000000AD ++:10B3A000000000000000000000000000000000009D ++:10B3B000000000000000000000000000000000008D ++:10B3C000000000000000000000000000000000007D ++:10B3D000000000000000000000000000000000006D ++:10B3E000000000000000000000000000000000005D ++:10B3F000000000000000000000000000000000004D ++:10B40000000000000000000000000000000000003C ++:10B41000000000000000000000000000000000002C ++:10B42000000000000000000000000000000000001C ++:10B43000000000000000000000000000000000000C ++:10B4400000000000000000000000000000000000FC ++:10B4500000000000000000000000000000000000EC ++:10B4600000000000000000000000000000000000DC ++:10B4700000000000000000000000000000000000CC ++:10B4800000000000000000000000000000000000BC ++:10B4900000000000000000000000000000000000AC ++:10B4A000000000000000000000000000000000009C ++:10B4B000000000000000000000000000000000008C ++:10B4C000000000000000000000000000000000007C ++:10B4D000000000000000000000000000000000006C ++:10B4E000000000000000000000000000000000005C ++:10B4F000000000000000000000000000000000004C ++:10B50000000000000000000000000000000000003B ++:10B51000000000000000000000000000000000002B ++:10B52000000000000000000000000000000000001B ++:10B53000000000000000000000000000000000000B ++:10B5400000000000000000000000000000000000FB ++:10B5500000000000000000000000000000000000EB ++:10B5600000000000000000000000000000000000DB ++:10B5700000000000000000000000000000000000CB ++:10B5800000000000000000000000000000000000BB ++:10B5900000000000000000000000000000000000AB ++:10B5A000000000000000000000000000000000009B ++:10B5B000000000000000000000000000000000008B ++:10B5C000000000000000000000000000000000007B ++:10B5D000000000000000000000000000000000006B ++:10B5E000000000000000000000000000000000005B ++:10B5F000000000000000000000000000000000004B ++:10B60000000000000000000000000000000000003A ++:10B61000000000000000000000000000000000002A ++:10B62000000000000000000000000000000000001A ++:10B63000000000000000000000000000000000000A ++:10B6400000000000000000000000000000000000FA ++:10B6500000000000000000000000000000000000EA ++:10B6600000000000000000000000000000000000DA ++:10B6700000000000000000000000000000000000CA ++:10B6800000000000000000000000000000000000BA ++:10B6900000000000000000000000000000000000AA ++:10B6A000000000000000000000000000000000009A ++:10B6B000000000000000000000000000000000008A ++:10B6C000000000000000000000000000000000007A ++:10B6D000000000000000000000000000000000006A ++:10B6E000000000000000000000000000000000005A ++:10B6F000000000000000000000000000000000004A ++:10B700000000000000000000000000000000000039 ++:10B710000000000000000000000000000000000029 ++:10B720000000000000000000000000000000000019 ++:10B730000000000000000000000000000000000009 ++:10B7400000000000000000000000000000000000F9 ++:10B7500000000000000000000000000000000000E9 ++:10B7600000000000000000000000000000000000D9 ++:10B7700000000000000000000000000000000000C9 ++:10B7800000000000000000000000000000000000B9 ++:10B7900000000000000000000000000000000000A9 ++:10B7A0000000000000000000000000000000000099 ++:10B7B0000000000000000000000000000000000089 ++:10B7C0000000000000000000000000000000000079 ++:10B7D0000000000000000000000000000000000069 ++:10B7E0000000000000000000000000000000000059 ++:10B7F0000000000000000000000000000000000049 ++:10B800000000000000000000000000000000000038 ++:10B810000000000000000000000000000000000028 ++:10B820000000000000000000000000000000000018 ++:10B830000000000000000000000000000000000008 ++:10B8400000000000000000000000000000000000F8 ++:10B8500000000000000000000000000000000000E8 ++:10B8600000000000000000000000000000000000D8 ++:10B8700000000000000000000000000000000000C8 ++:10B8800000000000000000000000000000000000B8 ++:10B8900000000000000000000000000000000000A8 ++:10B8A0000000000000000000000000000000000098 ++:10B8B0000000000000000000000000000000000088 ++:10B8C0000000000000000000000000000000000078 ++:10B8D0000000000000000000000000000000000068 ++:10B8E0000000000000000000000000000000000058 ++:10B8F0000000000000000000000000000000000048 ++:10B900000000000000000000000000000000000037 ++:10B910000000000000000000000000000000000027 ++:10B920000000000000000000000000000000000017 ++:10B930000000000000000000000000000000000007 ++:10B9400000000000000000000000000000000000F7 ++:10B9500000000000000000000000000000000000E7 ++:10B9600000000000000000000000000000000000D7 ++:10B9700000000000000000000000000000000000C7 ++:10B9800000000000000000000000000000000000B7 ++:10B990000000000000004140C7001040088801403E ++:10B9A0000180040052884820228488180000480042 ++:10B9B000B22002880800000800200D0000000200EC ++:10B9C0000800200080000002004800C00080000045 ++:10B9D0000200080020008000000200080020108003 ++:10B9E00009110254005001420235C0000008002035 ++:10B9F0000080000002000800200080000002000813 ++:10BA0000002010014402080A002821A240881222C6 ++:10BA10002C80B000C202080B20246000B4C20208CF ++:10BA20000931017403000D0000000200080020002D ++:10BA300080000002000800200080000002000800D2 ++:10BA40002000800000020008002010C04402080A04 ++:10BA5000002821A2808912020008300013803700DC ++:10BA600000000800200080000002000800204004C0 ++:10BA7000021504210050411300031104444803003F ++:10BA80000080000002000800200080000002000882 ++:10BA90000020090002010804108400918080020047 ++:10BAA0004A882808A28400010000083000C0004D28 ++:10BAB00000D30000002050045604005400D8016058 ++:10BAC00007821D0466B0508142054D002144500399 ++:10BAD0008092FE0300020008002092FE77022804F4 ++:10BAE000202800A0848882244A083000C000000377 ++:10BAF000000C801020C2004D00030048030010809D ++:10BB00000100023400D080400235D000000800203F ++:10BB100000800000020008002000800000020008F1 ++:10BB2000002010404402080A002821A2B089120215 ++:10BB30000CC004600D00000002000800200080001E ++:10BB40000002000800201080011520560098C00D4A ++:10BB50002C00000200080020008000000200080005 ++:10BB60002000800000020008002010804502080A22 ++:10BB7000002821A2608912020C0030000D00000094 ++:10BB80000200080020008000000200080020108051 ++:10BB900002050006400300008000000200080020AB ++:10BBA0000080000002000800200080000002000861 ++:10BBB00000200D00000002000800200080000002AC ++:10BBC0000008002000800000020008002000800023 ++:10BBD00000020008002040010019D40000002000ED ++:10BBE0008000000200080020008000000200080021 ++:10BBF000200080000002000800200D00000002006C ++:10BC000008002000800000020008002000800000E2 ++:10BC100002000800200080000002000800201080C0 ++:10BC200001150054C0030C00800000020008002031 ++:10BC300000800000020008002000800000020008D0 ++:10BC4000002010504402080A002821A290891222E4 ++:10BC50002420300042424C00DE0000002000800022 ++:10BC60000002000800204005880D2026E000E0408A ++:10BC700005880D2426F0010600800000020008005F ++:10BC80002000800000020008002010404702080A3F ++:10BC9000002821A2408912020CC004600D0000009F ++:10BCA000020008002000800000020008002003407D ++:10BCB00000152026085001628202152026D8048033 ++:10BCC00011608B09FE804203000080000002000822 ++:10BCD00000200D000000020008002000800000028B ++:10BCE0000008002000800000020008002000800002 ++:10BCF00000020008002010C0081D2074A8D0C11345 ++:10BD0000000B192C64C003090D000000020008009C ++:10BD10002000800000020008002010C04402080A31 ++:10BD2000002821A2708812020CC004600D000000DF ++:10BD3000020008002000800000020008002010849B ++:10BD40008819085680D84113008B19F4404303002A ++:10BD500000800000020008002000800000020008AF ++:10BD6000002010804502080A002821A270891202D2 ++:10BD70000C0030000D0000000200080020008000D0 ++:10BD80000002000800200D00000002000800200052 ++:10BD9000800000020008002000800000020008006F ++:10BDA000200080000002000800200D0000000200BA ++:10BDB0000800200080000002000800200080000031 ++:10BDC000020008002000800000020008002040015E ++:10BDD0000408004660030000800000020008002004 ++:10BDE000008000000200080020008000000200081F ++:10BDF000002010C04502080A002821A21089120262 ++:10BE00000CC004600F1E8011D200000020008000D2 ++:10BE100000020008002000000000000000000000F8 ++:10BE20000000000000000000000000000000000012 ++:10BE30000000000000000000000000000000000002 ++:10BE400000000000000000000000000000000000F2 ++:10BE500000000000000000000000000000000000E2 ++:10BE600000000000000000000000000000000000D2 ++:10BE700000000000000000000000000000000000C2 ++:10BE800000000000000000000000000000000000B2 ++:10BE900000000000000000000000000000000000A2 ++:10BEA0000000000000000000000000000000000092 ++:10BEB0000000000000000000000000000000000082 ++:10BEC0000000000000000000000000000000000072 ++:10BED0000000000000000000000000000000000062 ++:10BEE0000000000000000000000000000000000052 ++:10BEF0000000000000000000000000000000000042 ++:10BF00000000000000000000000000000000000031 ++:10BF10000000000000000000000000000000000021 ++:10BF20000000000000000000000000000000000011 ++:10BF30000000000000000000000000000000000001 ++:10BF400000000000000000000000000000000000F1 ++:10BF500000000000000000000000000000000000E1 ++:10BF600000000000000000000000000000000000D1 ++:10BF700000000000000000000000000000000000C1 ++:10BF800000000000000000000000000000000000B1 ++:10BF900000000000000000000000000000000000A1 ++:10BFA0000000000000000000000000000000000091 ++:10BFB0000000000000000000000000000000000081 ++:10BFC0000000000000000000000000000000000071 ++:10BFD0000000000000000000000000000000000061 ++:10BFE0000000000000000000000000000000000051 ++:10BFF0000000000000000000000000000000000041 ++:10C000000000000000000000000000000000000030 ++:10C010000000000000000000000000000000000020 ++:10C020000000000000000000000000000000000010 ++:10C030000000000000000000000000000000000000 ++:10C0400000000000000000000000000000000000F0 ++:10C0500000000000000000000000000000000000E0 ++:10C0600000000000000000000000000000000000D0 ++:10C0700000000000000000000000000000000000C0 ++:10C0800000000000000000000000000000000000B0 ++:10C0900000000000000000000000000000000000A0 ++:10C0A0000000000000000000000000000000000090 ++:10C0B0000000000000000000000000000000000080 ++:10C0C0000000000000000000000000000000000070 ++:10C0D0000000000000000000000000000000000060 ++:10C0E0000000000000000000000000000000000050 ++:10C0F0000000000000000000000000000000000040 ++:10C10000000000000000000000000000000000002F ++:10C11000000000000000000000000000000000001F ++:10C12000000000000000000000000000000000000F ++:10C1300000000000000000000000000000000000FF ++:10C1400000000000000000000000000000000000EF ++:10C1500000000000000000000000000000000000DF ++:10C1600000000000000000000000000000000000CF ++:10C1700000000000000000000000000000000000BF ++:10C1800000000000000000000000000000000000AF ++:10C19000000000000000000000000000000000009F ++:10C1A000000000000000000000000000000000008F ++:10C1B000000000000000000000000000000000007F ++:10C1C000000000000000000000000000000000006F ++:10C1D000000000000000000000000000000000005F ++:10C1E000000000000000000000000000000000004F ++:10C1F000000000000000000000000000000000003F ++:10C20000000000000000000000000000000000002E ++:10C21000000000000000000000000000000000001E ++:10C22000000000000000000000000000000000000E ++:10C2300000000000000000000000000000000000FE ++:10C2400000000000000000000000000000000000EE ++:10C2500000000000000000000000000000000000DE ++:10C2600000000000000000000000000000000000CE ++:10C2700000000000000000000000000000000000BE ++:10C2800000000000000000000000000000000000AE ++:10C29000000000000000000000000000000000009E ++:10C2A000000000000000000000000000000000008E ++:10C2B000000000000000000000000000000000007E ++:10C2C000000000000000000000000000000000006E ++:10C2D000000000000000000000000000000000005E ++:10C2E000000000000000000000000000000000004E ++:10C2F000000000000000000000000000000000003E ++:10C30000000000000000000000000000000000002D ++:10C31000000000000000000000000000000000001D ++:10C32000000000000000000000000000000000000D ++:10C3300000000000000000000000000000000000FD ++:10C3400000000000000000000000000000000000ED ++:10C3500000000000000000000000000000000000DD ++:10C3600000000000000000000000000000000000CD ++:10C3700000000000000000000000000000000000BD ++:10C3800000000000000000000000000000000000AD ++:10C39000000000000000000000000000000000009D ++:10C3A000000000000000000000000000000000008D ++:10C3B000000000000000000000000000000000007D ++:10C3C000000000000000000000000000000000006D ++:10C3D000000000000000000000000000000000005D ++:10C3E000000000000000000000000000000000004D ++:10C3F000000000000000000000000000000000003D ++:10C40000000000000000000000000000000000002C ++:10C41000000000000000000000000000000000001C ++:10C42000000000000000000000000000000000000C ++:10C4300000000000000000000000000000000000FC ++:10C4400000000000000000000000000000000000EC ++:10C4500000000000000000000000000000000000DC ++:10C4600000000000000000000000000000000000CC ++:10C4700000000000000000000000000000000000BC ++:10C4800000000000000000000000000000000000AC ++:10C49000000000000000000000000000000000009C ++:10C4A000000000000000000000000000000000008C ++:10C4B000000000000000000000000000000000007C ++:10C4C000000000000000000000000000000000006C ++:10C4D000000000000000000000000000000000005C ++:10C4E000000000000000000000000000000000004C ++:10C4F000000000000000000000000000000000003C ++:10C50000000000000000000000000000000000002B ++:10C51000000000000000000000000000000000001B ++:10C52000000000000000000000000000000000000B ++:10C5300000000000000000000000000000000000FB ++:10C5400000000000000000000000000000000000EB ++:10C5500000000000000000000000000000000000DB ++:10C5600000000000000000000000000000000000CB ++:10C5700000000000000000000000000000000000BB ++:10C5800000000000000000000000000000000000AB ++:10C59000000000000000000000000000000000009B ++:10C5A000000000000000000000000000000000008B ++:10C5B000000000000000000000000000000000007B ++:10C5C000000000000000000000000000000000006B ++:10C5D000000000000000000000000000000000005B ++:10C5E000000000000000000000000000000000004B ++:10C5F000000000000000000000000000000000003B ++:10C60000000000000000000000000000000000002A ++:10C61000000000000000000000000000000000001A ++:10C62000000000000000000000000000000000000A ++:10C6300000000000000000000000000000000000FA ++:10C6400000000000000000000000000000000000EA ++:10C6500000000000000000000000000000000000DA ++:10C6600000000000000000000000000000000000CA ++:10C6700000000000000000000000000000000000BA ++:10C6800000000000000000000000000000000000AA ++:10C69000000000000000000000000000000000009A ++:10C6A000000000000000000000000000000000008A ++:10C6B000000000000000000000000000000000007A ++:10C6C000000000000000000000000000000000006A ++:10C6D000000000000000000000000000000000005A ++:10C6E000000000000000000000000000000000004A ++:10C6F000000000000000000000000000000000003A ++:10C700000000000000000000000000000000000029 ++:10C710000000000000000000000000000000000019 ++:10C720000000000000000000000000000000000009 ++:10C7300000000000000000000000000000000000F9 ++:10C7400000000000000000000000000000000000E9 ++:10C7500000000000000000000000000000000000D9 ++:10C7600000000000000000000000000000000000C9 ++:10C7700000000000000000000000000000000000B9 ++:10C7800000000000000000000000000000000000A9 ++:10C790000000000000000000000000000000000099 ++:10C7A0000000000000000000000000000000000089 ++:10C7B0000000000000000000000000000000000079 ++:10C7C0000000000000000000000000000000000069 ++:10C7D0000000000000000000000000000000000059 ++:10C7E0000000000000000000000000000000000049 ++:10C7F0000000000000000000000000000000000039 ++:10C800000000000000000000000000000000000028 ++:10C810000000000000000000000000000000000018 ++:10C820000000000000000000000000000000000008 ++:10C8300000000000000000000000000000000000F8 ++:10C8400000000000000000000000000000000000E8 ++:10C8500000000000000000000000000000000000D8 ++:10C8600000000000000000000000000000000000C8 ++:10C8700000000000000000000000000000000000B8 ++:10C8800000000000000000000000000000000000A8 ++:10C890000000000000000000000000000000000098 ++:10C8A0000000000000000000000000000000000088 ++:10C8B0000000000000000000000000000000000078 ++:10C8C0000000000000000000000000000000000068 ++:10C8D0000000000000000000000000000000000058 ++:10C8E0000000000000000000000000000000000048 ++:10C8F0000000000000000000000000000000000038 ++:10C900000000000000000000000000000000000027 ++:10C910000000000000000000000000000000000017 ++:10C920000000000000000000000000000000000007 ++:10C9300000000000000000000000000000000000F7 ++:10C9400000000000000000000000000000000000E7 ++:10C9500000000000000000000000000000000000D7 ++:10C9600000000000000000000000000000000000C7 ++:10C9700000000000000000000000000000000000B7 ++:10C9800000000000000000000000000000000000A7 ++:10C990000000000000000000000000000000000097 ++:10C9A0000000000000000000000000000000000087 ++:10C9B0000000000000000000000000000000000077 ++:10C9C0000000000000000000000000000000000067 ++:10C9D0000000000000000000000000000000000057 ++:10C9E0000000000000000000000000000000000047 ++:10C9F0000000000000000000000000000000000037 ++:10CA00000000000000000000000000000000000026 ++:10CA10000000000000000000000000000000000016 ++:10CA20000000000000000000000000000000000006 ++:10CA300000000000000000000000000000000000F6 ++:10CA400000000000000000000000000000000000E6 ++:10CA500000000000000000000000000000000000D6 ++:10CA600000000000000000000000000000000000C6 ++:10CA700000000000000000000000000000000000B6 ++:10CA800000000000000000000000000000000000A6 ++:10CA90000000000000000000000000000000000096 ++:10CAA0000000000000000000000000000000000086 ++:10CAB0000000000000000000000000000000000076 ++:10CAC0000000000000000000000000000000000066 ++:10CAD0000000000000000000000000000000000056 ++:10CAE0000000000000000000000000000000000046 ++:10CAF0000000000000000000000000000000000036 ++:10CB00000000000000000000000000000000000025 ++:10CB10000000000000000000000000000000000015 ++:10CB20000000000000000000000000000000000005 ++:10CB300000000000000000000000000000000000F5 ++:10CB400000000000000000000000000000000000E5 ++:10CB500000000000000000000000000000000000D5 ++:10CB600000000000000000000000000000000000C5 ++:10CB700000000000000000000000000000000000B5 ++:10CB800000000000000000000000000000000000A5 ++:10CB90000000000000000000000000000000000095 ++:10CBA0000000000000000000000000000000000085 ++:10CBB0000000000000000000000000000000000075 ++:10CBC0000000000000000000000000000000000065 ++:10CBD0000000000000000000000000000000000055 ++:10CBE0000000000000000000000000000000000045 ++:10CBF0000000000000000000000000000000000035 ++:10CC00000000000000000000000000000000000024 ++:10CC10000000000000000000000000000000000014 ++:10CC20000000000000000000000000000000000004 ++:10CC300000000000000000000000000000000000F4 ++:10CC400000000000000000000000000000000000E4 ++:10CC500000000000000000000000000000000000D4 ++:10CC600000000000000000000000000000000000C4 ++:10CC700000000000000000000000000000000000B4 ++:10CC800000000000000000000000000000000000A4 ++:10CC90000000000000000000000000000000000094 ++:10CCA0000000000000000000000000000000000084 ++:10CCB0000000000000000000000000000000000074 ++:10CCC0000000000000000000000000000000000064 ++:10CCD0000000000000000000000000000000000054 ++:10CCE0000000000000000000000000000000000044 ++:10CCF0000000000000000000000000000000000034 ++:10CD00000000000000000000000000000000000023 ++:10CD10000000000000000000000000000000000013 ++:10CD20000000000000000000000000000000000003 ++:10CD300000000000000000000000000000000000F3 ++:10CD400000000000000000000000000000000000E3 ++:10CD500000000000000000000000000000000000D3 ++:10CD600000000000000000000000000000000000C3 ++:10CD700000000000000000000000000000000000B3 ++:10CD800000000000000000000000000000000000A3 ++:10CD90000000000000000000000000000000000093 ++:10CDA0000000000000000000000000000000000083 ++:10CDB0000000000000000000000000000000000073 ++:10CDC0000000000000000000000000000000000063 ++:10CDD0000000000000000000000000000000000053 ++:10CDE0000000000000000000000000000000000043 ++:10CDF0000000000000000000000000000000000033 ++:10CE00000000000000000000000000000000000022 ++:10CE10000000000000000000000000000000000012 ++:10CE20000000000000000000000000000000000002 ++:10CE300000000000000000000000000000000000F2 ++:10CE400000000000000000000000000000000000E2 ++:10CE500000000000000000000000000000000000D2 ++:10CE600000000000000000000000000000000000C2 ++:10CE700000000000000000000000000000000000B2 ++:10CE800000000000000000000000000000000000A2 ++:10CE90000000000000000000000000000000000092 ++:10CEA0000000000000000000000000000000000082 ++:10CEB0000000000000000000000000000000000072 ++:10CEC0000000000000000000000000000000000062 ++:10CED0000000000000000000000000000000000052 ++:10CEE0000000000000000000000000000000000042 ++:10CEF0000000000000000000000000000000000032 ++:10CF00000000000000000000000000000000000021 ++:10CF10000000000000000000000000000000000011 ++:10CF20000000000000000000000000000000000001 ++:10CF300000000000000000000000000000000000F1 ++:10CF400000000000000000000000000000000000E1 ++:10CF500000000000000000000000000000000000D1 ++:10CF600000000000000000000000000000000000C1 ++:10CF700000000000000000000000000000000000B1 ++:10CF800000000000000000000000000000000000A1 ++:10CF90000000000000000000000000000000000091 ++:10CFA0000000000000000000000000000000000081 ++:10CFB0000000000000000000000000000000000071 ++:10CFC0000000000000000000000000000000000061 ++:10CFD0000000000000000000000000000000000051 ++:10CFE0000000000000000000000000000000000041 ++:10CFF0000000000000000000000000000000000031 ++:10D000000000000000000000000000000000000020 ++:10D010000000000000000000000000000000000010 ++:10D020000000000000000000000000000000000000 ++:10D0300000000000000000000000000000000000F0 ++:10D0400000000000000000000000000000000000E0 ++:10D0500000000000000000000000000000000000D0 ++:10D0600000000000000000000000000000000000C0 ++:10D0700000000000000000000000000000000000B0 ++:10D0800000000000000000000000000000000000A0 ++:10D090000000000000000000000000000000000090 ++:10D0A0000000000000000000000000000000000080 ++:10D0B0000000000000000000000000000000000070 ++:10D0C0000000000000000000000000000000000060 ++:10D0D0000000000000000000000000000000000050 ++:10D0E0000000000000000000000000000000000040 ++:10D0F0000000000000000000000000000000000030 ++:10D10000000000000000000000000000000000001F ++:10D11000000000000000000000000000000000000F ++:10D1200000000000000000000000000000000000FF ++:10D1300000000000000000000000000000000000EF ++:10D1400000000000000000000000000000000000DF ++:10D1500000000000000000000000000000000000CF ++:10D1600000000000000000000000000000000000BF ++:10D1700000000000000000000000000000000000AF ++:10D18000000000000000000000000000000000009F ++:10D19000000000000000000000000000000000008F ++:10D1A000000000000000000000000000000000007F ++:10D1B000000000000000000000000000000000006F ++:10D1C000000000000000000000000000000000005F ++:10D1D000000000000000000000000000000000004F ++:10D1E000000000000000000000000000000000003F ++:10D1F000000000000000000000000000000000002F ++:10D20000000000000000000000000000000000001E ++:10D21000000000000000000000000000000000000E ++:10D2200000000000000000000000000000000000FE ++:10D2300000000000000000000000000000000000EE ++:10D2400000000000000000000000000000000000DE ++:10D2500000000000000000000000000000000000CE ++:10D2600000000000000000000000000000000000BE ++:10D2700000000000000000000000000000000000AE ++:10D28000000000000000000000000000000000009E ++:10D29000000000000000000000000000000000008E ++:10D2A000000000000000000000000000000000007E ++:10D2B000000000000000000000000000000000006E ++:10D2C000000000000000000000000000000000005E ++:10D2D000000000000000000000000000000000004E ++:10D2E000000000000000000000000000000000003E ++:10D2F000000000000000000000000000000000002E ++:10D30000000000000000000000000000000000001D ++:10D31000000000000000000000000000000000000D ++:10D3200000000000000000000000000000000000FD ++:10D3300000000000000000000000000000000000ED ++:10D3400000000000000000000000000000000000DD ++:10D3500000000000000000000000000000000000CD ++:10D3600000000000000000000000000000000000BD ++:10D3700000000000000000000000000000000000AD ++:10D38000000000000000000000000000000000009D ++:10D39000000000000000000000000000000000008D ++:10D3A000000000000000000000000000000000007D ++:10D3B000000000000000000000000000000000006D ++:10D3C000000000000000000000000000000000005D ++:10D3D000000000000000000000000000000000004D ++:10D3E000000000000000000000000000000000003D ++:10D3F000000000000000000000000000000000002D ++:10D40000000000000000000000000000000000001C ++:10D41000000000000000000000000000000000000C ++:10D4200000000000000000000000000000000000FC ++:10D4300000000000000000000000000000000000EC ++:10D4400000000000000000000000000000000000DC ++:10D4500000000000000000000000000000000000CC ++:10D4600000000000000000000000000000000000BC ++:10D4700000000000000000000000000000000000AC ++:10D48000000000000000000000000000000000009C ++:10D49000000000000000000000000000000000008C ++:10D4A000000000000000000000000000000000007C ++:10D4B000000000000000000000000000000000006C ++:10D4C000000000000000000000000000000000005C ++:10D4D000000000000000000000000000000000004C ++:10D4E000000000000000000000000000000000003C ++:10D4F000000000000000000000000000000000002C ++:10D50000000050B0C308080027989C5000C30800D2 ++:10D510000027B89C50804300000834001C3080C1B4 ++:10D52000060000110C000090C004003F3FA04430F2 ++:10D5300020C0CF0F0B042C0800900001080003242A ++:10D5400080400001C0000920102000304002080186 ++:10D5500000008430F3034002333FD01050900301A9 ++:10D5600002340414A44000020D010531040000102F ++:10D5700000C000031000EC300000C00E01000C00E1 ++:10D58000007002C0010302240C3000C10A00000B2D ++:10D5900010400030400208033024C43080C30A0029 ++:10D5A000000B0CC09010C3040000110C0000900090 ++:10D5B000010400032480408000C00009201008F00E ++:10D5C000A0820B0C2526100850A3C2C00009030C32 ++:10D5D000F000B0C0000C09318C000010C204000043 ++:10D5E000110C68404000C0000420008C9000020133 ++:10D5F0000100031040003042020804021008F0123B ++:10D60000830B0C252B100850A3C2400009030C40CB ++:10D61000B00200C0020410000C9000C2000C0931DE ++:10D620000CE0B00200C00223050084300001400479 ++:10D6300003000024400002C00009201040003040D8 ++:10D6400002080408000C90000281000F30B8C0509E ++:10D65000A1038100352A8C009030C0800E000B0C95 ++:10D66000C09010C3040000218C500010C1000000C5 ++:10D670000910800030010104002310200030400216 ++:10D680000804021008F080820B0C1523100850A328 ++:10D69000C2480009030C40B00200C0020410000C94 ++:10D6A0009000C2000C09310CE0B00200C00223015E ++:10D6B0000084300000400403000024400002C00049 ++:10D6C0000920104000304002080408000C900002BD ++:10D6D00081003F30B8C05023038100352A8C0C00F4 ++:10D6E000100001001B00240C3032000D0135268C87 ++:10D6F000000070828F0935060C000070C200000324 ++:10D7000000D418509300000000000000000000004A ++:10D710000000000000000000000000000000000009 ++:10D7200000000000000000000000000000000000F9 ++:10D7300000000000000000000000000000000000E9 ++:10D7400000000000000000000000000000000000D9 ++:10D7500000000000000000000000000000000000C9 ++:10D7600000000000000000000000000000000000B9 ++:10D7700000000000000000000000000000000000A9 ++:10D780000000000000000000000000000000000099 ++:10D790000000000000000000000000000000000089 ++:10D7A0000000000000000000000000000000000079 ++:10D7B0000000000000000000000000000000000069 ++:10D7C0000000000000000000000000000000000059 ++:10D7D0000000000000000000000000000000000049 ++:10D7E0000000000000000000000000000000000039 ++:10D7F0000000000000000000000000000000000029 ++:10D800000000000000000000000000000000000018 ++:10D810000000000000000000000000000000000008 ++:10D8200000000000000000000000000000000000F8 ++:10D8300000000000000000000000000000000000E8 ++:10D8400000000000000000000000000000000000D8 ++:10D8500000000000000000000000000000000000C8 ++:10D8600000000000000000000000000000000000B8 ++:10D8700000000000000000000000000000000000A8 ++:10D880000000000000000000000000000000000098 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000000000000078 ++:10D8B0000000000000000000000000000000000068 ++:10D8C0000000000000000000000000000000000058 ++:10D8D0000000000000000000000000000000000048 ++:10D8E0000000000000000000000000000000000038 ++:10D8F0000000000000000000000000000000000028 ++:10D900000000000000000000000000000000000017 ++:10D910000000000000000000000000000000000007 ++:10D9200000000000000000000000000000000000F7 ++:10D9300000000000000000000000000000000000E7 ++:10D9400000000000000000000000000000000000D7 ++:10D9500000000000000000000000000000000000C7 ++:10D9600000000000000000000000000000000000B7 ++:10D9700000000000000000000000000000000000A7 ++:10D980000000500000000000000000000000000047 ++:10D990000000000000000000000000000000000087 ++:10D9A0000000000000000000000000000000000077 ++:10D9B0000000000000000000000000000000000067 ++:10D9C0000000000000000000000000000000000057 ++:10D9D0000000000000000000000000000000000047 ++:10D9E0000000000000000000000000000000000037 ++:10D9F0000000000000000000000000000000000027 ++:10DA00000000000000000000000000000000000016 ++:10DA10000000000000000000000000000000000006 ++:10DA200000000000000000000000000000000000F6 ++:10DA300000000000000000000000000000000000E6 ++:10DA400000000000000000000000000000000000D6 ++:10DA500000000000000000000000000000000000C6 ++:10DA600000000000000000000000000000000000B6 ++:10DA700000000000000000000000000000000000A6 ++:10DA80000000000000000000000000000000000096 ++:10DA90000000000000000000000000000000000086 ++:10DAA0000000000000000000000000000000000076 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000000000000000000000000000000056 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000000000000000000000000000000000015 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000000000F5 ++:10DB300000000000000000000000000000000000E5 ++:10DB400000000000000000000000000000000000D5 ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB700000000000000000000000000000000000A5 ++:10DB80000000000000000000000000000000000095 ++:10DB90000000000000000000000000000000000085 ++:10DBA0000000000000000000000000000000000075 ++:10DBB0000000000000000000000000000000000065 ++:10DBC0000000000000000000000000000000000055 ++:10DBD0000000000000000000000000000000000045 ++:10DBE0000000000000000000000000000000000035 ++:10DBF0000000000000000000000000000000000025 ++:10DC00000000000000000000000000000000000014 ++:10DC10000000000000000000000000000000000004 ++:10DC200000000000000000000000000000000000F4 ++:10DC300000000000000000000000000000000000E4 ++:10DC400000000000000000000000000000000000D4 ++:10DC500000000000000000000000000000000000C4 ++:10DC600000000000000000000000000000000000B4 ++:10DC700000000000000000000000000000000000A4 ++:10DC80000000000000000000000000000000000094 ++:10DC90000000000000000000000000000000000084 ++:10DCA0000000000000000000000000000000000074 ++:10DCB0000000000000000000000000000000000064 ++:10DCC0000000000000000000000000000000000054 ++:10DCD0000000000000000000000000000000000044 ++:10DCE0000000000000000000000000000000000034 ++:10DCF0000000000000000000000000000000000024 ++:10DD00000000000000000000000000000000000013 ++:10DD10000000000000000000000000000000000003 ++:10DD200000000000000000000000000000000000F3 ++:10DD300000000000000000000000000000000000E3 ++:10DD400000000000000000000000000000000000D3 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000000000000000B3 ++:10DD700000000000000000000000000000000000A3 ++:10DD80000000000000000000000000000000000093 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000000000073 ++:10DDB0000000000000000000000000000000000063 ++:10DDC0000000000000000000000000000000000053 ++:10DDD0000000000000000000000000000000000043 ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000000000000000000000000012 ++:10DE10000000000000000000000000000000000002 ++:10DE200000000000000050B0C308080027989C5074 ++:10DE300000C308000027B89C50804300000834004D ++:10DE40001C3080C1060000110C000090C004003F8F ++:10DE50003FA0443020C0CF0F0B042C0800900001DD ++:10DE60000800032480400001C00009201020003079 ++:10DE70004002080100008430F3034002333FD01019 ++:10DE80005090030102340414A44000020D01053136 ++:10DE90000400001000C000031000EC300000C00EB1 ++:10DEA00001000C00007002C0010302240C3000C10C ++:10DEB0000A00000B10400030400208033024C43038 ++:10DEC00080C30A00000B0CC09010C3040000110CAA ++:10DED00000009000010400032480408000C000097D ++:10DEE000201008F0A0820B0C2526100850A3C2C0F9 ++:10DEF0000009030CF000B0C0000C09318C000010C8 ++:10DF0000C2040000110C68404000C0000420008CD6 ++:10DF10009000020101000310400030420208040298 ++:10DF20001008F012830B0C252B100850A3C24000E0 ++:10DF300009030C40B00200C0020410000C9000C2A3 ++:10DF4000000C09310CE0B00200C00223050084304F ++:10DF50000001400403000024400002C0000920101A ++:10DF60004000304002080408000C90000281000FBD ++:10DF700030B8C050A1038100352A8C009030C08099 ++:10DF80000E000B0CC09010C3040000218C50001038 ++:10DF9000C10000000910800030010104002310209E ++:10DFA000003040020804021008F080820B0C152398 ++:10DFB000100850A3C2480009030C40B00200C00280 ++:10DFC0000410000C9000C2000C09310CE0B00200FB ++:10DFD000C0022301008430000040040300002440FC ++:10DFE0000002C00009201040003040020804080070 ++:10DFF0000C90000281003F30B8C0502303810035EF ++:10E000002A8C0C00100001001B00240C3032000D83 ++:10E010000135268C000070828F0935060C000070D7 ++:10E02000C200000300D4185093000000000000005C ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E0500000000000000000000000000000000000C0 ++:10E0600000000000000000000000000000000000B0 ++:10E0700000000000000000000000000000000000A0 ++:10E080000000000000000000000000000000000090 ++:10E090000000000000000000000000000000000080 ++:10E0A0000000000000000000000000000000000070 ++:10E0B0000000000000000000000000000000000060 ++:10E0C0000000000000000000000000000000000050 ++:10E0D0000000000000000000000000000000000040 ++:10E0E0000000000000000000000000000000000030 ++:10E0F0000000000000000000000000000000000020 ++:10E10000000000000000000000000000000000000F ++:10E1100000000000000000000000000000000000FF ++:10E1200000000000000000000000000000000000EF ++:10E1300000000000000000000000000000000000DF ++:10E1400000000000000000000000000000000000CF ++:10E1500000000000000000000000000000000000BF ++:10E1600000000000000000000000000000000000AF ++:10E17000000000000000000000000000000000009F ++:10E18000000000000000000000000000000000008F ++:10E19000000000000000000000000000000000007F ++:10E1A000000000000000000000000000000000006F ++:10E1B000000000000000000000000000000000005F ++:10E1C000000000000000000000000000000000004F ++:10E1D000000000000000000000000000000000003F ++:10E1E000000000000000000000000000000000002F ++:10E1F000000000000000000000000000000000001F ++:10E20000000000000000000000000000000000000E ++:10E2100000000000000000000000000000000000FE ++:10E2200000000000000000000000000000000000EE ++:10E2300000000000000000000000000000000000DE ++:10E2400000000000000000000000000000000000CE ++:10E2500000000000000000000000000000000000BE ++:10E2600000000000000000000000000000000000AE ++:10E27000000000000000000000000000000000009E ++:10E28000000000000000000000000000000000008E ++:10E29000000000000000000000000000000000007E ++:10E2A000000000000000500000000000000000001E ++:10E2B000000000000000000000000000000000005E ++:10E2C000000000000000000000000000000000004E ++:10E2D000000000000000000000000000000000003E ++:10E2E000000000000000000000000000000000002E ++:10E2F000000000000000000000000000000000001E ++:10E30000000000000000000000000000000000000D ++:10E3100000000000000000000000000000000000FD ++:10E3200000000000000000000000000000000000ED ++:10E3300000000000000000000000000000000000DD ++:10E3400000000000000000000000000000000000CD ++:10E3500000000000000000000000000000000000BD ++:10E3600000000000000000000000000000000000AD ++:10E37000000000000000000000000000000000009D ++:10E38000000000000000000000000000000000008D ++:10E39000000000000000000000000000000000007D ++:10E3A000000000000000000000000000000000006D ++:10E3B000000000000000000000000000000000005D ++:10E3C000000000000000000000000000000000004D ++:10E3D000000000000000000000000000000000003D ++:10E3E000000000000000000000000000000000002D ++:10E3F000000000000000000000000000000000001D ++:10E40000000000000000000000000000000000000C ++:10E4100000000000000000000000000000000000FC ++:10E4200000000000000000000000000000000000EC ++:10E4300000000000000000000000000000000000DC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000000000000000000000000000000000009C ++:10E48000000000000000000000000000000000008C ++:10E49000000000000000000000000000000000007C ++:10E4A000000000000000000000000000000000006C ++:10E4B000000000000000000000000000000000005C ++:10E4C000000000000000000000000000000000004C ++:10E4D000000000000000000000000000000000003C ++:10E4E000000000000000000000000000000000002C ++:10E4F000000000000000000000000000000000001C ++:10E50000000000000000000000000000000000000B ++:10E5100000000000000000000000000000000000FB ++:10E5200000000000000000000000000000000000EB ++:10E5300000000000000000000000000000000000DB ++:10E5400000000000000000000000000000000000CB ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000000000000000008B ++:10E59000000000000000000000000000000000007B ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000000000000000000000000000000000001B ++:10E60000000000000000000000000000000000000A ++:10E6100000000000000000000000000000000000FA ++:10E6200000000000000000000000000000000000EA ++:10E6300000000000000000000000000000000000DA ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E6600000000000000000000000000000000000AA ++:10E67000000000000000000000000000000000009A ++:10E68000000000000000000000000000000000008A ++:10E69000000000000000000000000000000000007A ++:10E6A000000000000000000000000000000000006A ++:10E6B000000000000000000000000000000000005A ++:10E6C000000000000000000000000000000000004A ++:10E6D000000000000000000000000000000000003A ++:10E6E000000000000000000000000000000000002A ++:10E6F000000000000000000000000000000000001A ++:10E700000000000000000000000000000000000009 ++:10E7100000000000000000000000000000000000F9 ++:10E7200000000000000000000000000000000000E9 ++:10E7300000000000000000000000000000000000D9 ++:10E7400000000000000000000000000000000000C9 ++:10E7500000000000000000000000000000000000B9 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000000000000099 ++:10E780000000000000000000000000000000000089 ++:10E790000000000000000000000000000000000079 ++:10E7A0000000000000000000000000000000000069 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000000039 ++:10E7E0000000000000000000000000000000000029 ++:10E7F0000000000000000000000000000000000019 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000000000000000000000000000F8 ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000000000000000000000000000000D8 ++:10E8400000000000000000000000000000000000C8 ++:10E8500000000000000000000000000000000000B8 ++:10E8600000000000000000000000000000000000A8 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000000000000000000018 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000000000000000000000000000000D7 ++:10E9400000000000000000000000000000000000C7 ++:10E9500000000000000000000000000000000000B7 ++:10E9600000000000000000000000000000000000A7 ++:10E970000000000000000000000000000000000097 ++:10E980000000000000000000000000000000000087 ++:10E990000000000000000000000000000000000077 ++:10E9A0000000000000000000000000000000000067 ++:10E9B0000000000000000000000000000000000057 ++:10E9C0000000000000000000000000000000000047 ++:10E9D0000000000000000000000000000000000037 ++:10E9E0000000000000000000000000000000000027 ++:10E9F0000000000000000000000000000000000017 ++:10EA00000000000000000000000000000000000006 ++:10EA100000000000000000000000000000000000F6 ++:10EA200000000000000000000000000000000000E6 ++:10EA300000000000000000000000000000000000D6 ++:10EA400000000000000000000000000000000000C6 ++:10EA500000000000000000000000000000000000B6 ++:10EA600000000000000000000000000000000000A6 ++:10EA70000000000000000000000000000000000096 ++:10EA80000000000000000000000000000000000086 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000000000000000056 ++:10EAC0000000000000000000000000000000000046 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB300000000000000000000000000000000000D5 ++:10EB400000000000000000000000000000000000C5 ++:10EB500000000000000000000000000000000000B5 ++:10EB600000000000000000000000000000000000A5 ++:10EB70000000000000000000000000000000000095 ++:10EB80000000000000000000000000000000000085 ++:10EB90000000000000000000000000000000000075 ++:10EBA0000000000000000000000000000000000065 ++:10EBB0000000000000000000000000000000000055 ++:10EBC0000000000000000000000000000000000045 ++:10EBD0000000000000000000000000000000000035 ++:10EBE0000000000000000000000000000000000025 ++:10EBF0000000000000000000000000000000000015 ++:10EC00000000000000000000000000000000000004 ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC80000000000000000000000000000000000084 ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000000000000000000000000000000064 ++:10ECB0000000000000000000000000000000000054 ++:10ECC0000000000000000000000000000000000044 ++:10ECD0000000000000000000000000000000000034 ++:10ECE0000000000000000000000000000000000024 ++:10ECF0000000000000000000000000000000000014 ++:10ED00000000000000000000000000000000000003 ++:10ED100000000000000000000000000000000000F3 ++:10ED200000000000000000000000000000000000E3 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA0000000000000000000000000000000000063 ++:10EDB0000000000000000000000000000000000053 ++:10EDC0000000000000000000000000000000000043 ++:10EDD0000000000000000000000000000000000033 ++:10EDE0000000000000000000000000000000000023 ++:10EDF0000000000000000000000000000000000013 ++:10EE00000000000000000000000000000000000002 ++:10EE100000000000000000000000000000000000F2 ++:10EE200000000000000000000000000000000000E2 ++:10EE300000000000000000000000000000000000D2 ++:10EE400000000000000000000000000000000000C2 ++:10EE500000000000000000000000000000000000B2 ++:10EE600000000000000000000000000000000000A2 ++:10EE70000000000000000000000000000000000092 ++:10EE80000000000000000000000000000000000082 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000000000022 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000000000000000000000000000000001 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF600000000000000000000000000000000000A1 ++:10EF70000000000000000000000000000000000091 ++:10EF80000000000000000000000000000000000081 ++:10EF90000000000000000000000000000000000071 ++:10EFA0000000000000000000000000000000000061 ++:10EFB0000000000000000000000000000000000051 ++:10EFC0000000000000000000000000000000000041 ++:10EFD0000000000000000000000000000000000031 ++:10EFE0000000000000000000000000000000000021 ++:10EFF0000000000000000000000000000000000011 ++:10F000000000000000000000000000000000000000 ++:10F0100000000000000000000000000000000000F0 ++:10F0200000000000000000000000000000000000E0 ++:10F0300000000000000000000000000000000000D0 ++:10F0400000000000000000000000000000000000C0 ++:10F0500000000000000000000000000000000000B0 ++:10F0600000000000000000000000000000000000A0 ++:10F070000000000000000000000000000000000090 ++:10F080000000000000000000000000000000000080 ++:10F090000000000000000000000000000000000070 ++:10F0A0000000000000000000000000000000000060 ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D0000000000000000000000000000000000030 ++:10F0E0000000000000000000000000000000000020 ++:10F0F0000000000000000000000000000000000010 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000000AF ++:10F16000000000000000000000000000000000009F ++:10F17000000000000000000000000000000000008F ++:10F18000000000000000000000000000000000007F ++:10F19000000000000000000000000000000000006F ++:10F1A000000000000000000000000000000000005F ++:10F1B000000000000000000000000000000000004F ++:10F1C000000000000000000000000000000000003F ++:10F1D000000000000000000000000000000000002F ++:10F1E000000000000000000000000000000000001F ++:10F1F000000000000000000000000000000000000F ++:10F2000000000000000000000000000000000000FE ++:10F2100000000000000000000000000000000000EE ++:10F2200000000000000000000000000000000000DE ++:10F2300000000000000000000000000000000000CE ++:10F2400000000000000000000000000000000000BE ++:10F2500000000000000000000000000000000000AE ++:10F26000000000000000000000000000000000009E ++:10F27000000000000000000000000000000000008E ++:10F28000000000000000000000000000000000007E ++:10F29000000000000000000000000000000000006E ++:10F2A000000000000000000000000000000000005E ++:10F2B000000000000000000000000000000000004E ++:10F2C000000000000000000000000000000000003E ++:10F2D000000000000000000000000000000000002E ++:10F2E000000000000000000000000000000000001E ++:10F2F000000000000000000000000000000000000E ++:10F3000000000000000000000000000000000000FD ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000000000000CD ++:10F3400000000000000000000000000000000000BD ++:10F3500000000000000000000000000000000000AD ++:10F36000000000000000000000000000000000009D ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000000000004D ++:10F3C000000000000000000000000000000000003D ++:10F3D000000000000000000000000000000000002D ++:10F3E000000000000000000000000000000000001D ++:10F3F000000000000000000000000000000000000D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F4400000000000000000000000000000000000BC ++:10F4500000000000000000000000000000000000AC ++:10F46000000000000000000000000000000000009C ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000000000000000003C ++:10F4D000000000000000000000000000000000002C ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000000000000000EB ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000000000000000000000000000007B ++:10F59000000000000000000000000000000000006B ++:10F5A000000000000000000000000000000000005B ++:10F5B000000000000000000000000000000000004B ++:10F5C000000000000000000000000000000000003B ++:10F5D000000000000000000000000000000000002B ++:10F5E000000000000000000000000000000000001B ++:10F5F000000000000000000000000000000000000B ++:10F6000000000000000000000000000000000000FA ++:10F6100000000000000000000000000000000000EA ++:10F6200000000000000000000000000000000000DA ++:10F6300000000000000000000000000000000000CA ++:10F6400000000000000000000000000000000000BA ++:10F6500000000000000000000000000000000000AA ++:10F66000000000000000000000000000000000009A ++:10F67000000000000000000000000000000000008A ++:10F68000000000000000000000000000000000007A ++:10F69000000000000000000000000000000000006A ++:10F6A000000000000000000000000000000000005A ++:10F6B000000000000000000000000000000000004A ++:10F6C000000000000000000000000000000000003A ++:10F6D000000000000000000000000000000000002A ++:10F6E000000000000000000000000000000000001A ++:10F6F000000000000000000000000000000000000A ++:10F7000000000000000000000000000000000000F9 ++:10F7100000000000000000000000000000000000E9 ++:10F7200000000000000000000000000000000000D9 ++:10F7300000000000000000000000000000000000C9 ++:10F7400000000000000000000000000000000000B9 ++:10F7500000000000000000000000000000000000A9 ++:10F760000000000000000000000000000000000099 ++:10F770000000000000000000000000000000000089 ++:10F780000000000000000000000000000000000079 ++:10F790000000000000000000000000000000000069 ++:10F7A0000000000000000000000000000000000059 ++:10F7B0000000000000000000000000000000000049 ++:10F7C0000000000000000000000000000000000039 ++:10F7D0000000000000000000000000000000000029 ++:10F7E0000000000000000000000000000000000019 ++:10F7F0000000000000000000000000000000000009 ++:10F8000000000000000000000000000000000000F8 ++:10F8100000000000000000000000000000000000E8 ++:10F8200000000000000000000000000000000000D8 ++:10F8300000000000000000000000000000000000C8 ++:10F8400000000000000000000000000000000000B8 ++:10F8500000000000000000000000000000000000A8 ++:10F860000000000000000000000000000000000098 ++:10F870000000000000000000000000000000000088 ++:10F880000000000000000000000000000000000078 ++:10F890000000000000000000000000000000000068 ++:10F8A0000000000000000000000000000000000058 ++:10F8B0000000000000000000000000000000000048 ++:10F8C0000000000000000000000000000000000038 ++:10F8D0000000000000000000000000000000000028 ++:10F8E0000000000000000000000000000000000018 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000000000000000F7 ++:10F9100000000000000000000000000000000000E7 ++:10F9200000000000000000000000000000000000D7 ++:10F9300000000000000000000000000000000000C7 ++:10F9400000000000000000000000000000000000B7 ++:10F9500000000000000000000000000000000000A7 ++:10F960000000000000000000000000000000000097 ++:10F970000000000000000000000000000000000087 ++:10F980000000000000000000000000000000000077 ++:10F990000180000000880060E0800000002400D0AA ++:10F9A00000000000000000000180000000880060EE ++:10F9B0000180000000880060018000000088006075 ++:10F9C00000000000000000000180000000880060CE ++:10F9D0000180000000880060E0800000002400D06A ++:10F9E0000000000000000000000000000000000017 ++:10F9F0000000000000000000000000000000000007 ++:10FA000000000000000000000000000000000000F6 ++:10FA10000180000000880060018000000088006014 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000000000000000000C6 ++:10FA400000000000000000000000000000000000B6 ++:10FA500001800000008800600180000000880060D4 ++:10FA60000000000000000000000000000000000096 ++:10FA70000000000000000000000000000000000086 ++:10FA80000000000000000000000000000000000076 ++:10FA90000000000000000000000000000000000066 ++:10FAA0000000000000000000000000000000000056 ++:10FAB000E0800000002400D0E0800000002400D09E ++:10FAC0000180000000880060018000000088006064 ++:10FAD0000180000000880060E0800000002400D069 ++:10FAE0000000000000000000000000000000000016 ++:10FAF0000180000000880060018000000088006034 ++:10FB00000180000000880060E0800000002400D038 ++:10FB10000180000000880060018000000088006013 ++:10FB2000E0800000002400D0018000000088006018 ++:10FB300000000000000000000000000000000000C5 ++:10FB400000000000000000000000000000000000B5 ++:10FB500000000000000000000000000000000000A5 ++:10FB60000000000000000000000000000000000095 ++:10FB70000000000000000000000000000000000085 ++:10FB80000180000000880060E0800000002400D0B8 ++:10FB90000180000000880060018000000088006093 ++:10FBA0000000000000000000000000000000000055 ++:10FBB0000000000000000000000000000000000045 ++:10FBC0000000000000000000000000000000000035 ++:10FBD000E0800000002400D0018000000088006068 ++:10FBE000E0800000002400D0018000000088006058 ++:10FBF00000000000000000020110000100000000F1 ++:10FC000000000000000000000000000000000000F4 ++:10FC100000000000000000000000000000000000E4 ++:10FC2000E0800000002400D0018000000088006017 ++:10FC3000E0800000002400D0018000000088006007 ++:10FC400000000000000000000000000000000000B4 ++:10FC500000000000000000000000000000000000A4 ++:10FC60000000000000000000000000000000000094 ++:10FC70000000000000000000000000000000000084 ++:10FC800001800000008800600180000000880060A2 ++:10FC90000180000000880060E0800000002400D0A7 ++:10FCA0000180000000880060E0800000002400D097 ++:10FCB0000180000000880060018000000088006072 ++:10FCC0000000000000000000000000000000000034 ++:10FCD0000000000000000000000000000000000024 ++:10FCE0000000000000000000000000000000000014 ++:10FCF0000180000000880060018000000088006032 ++:10FD0000E180000000880060E18000000088006061 ++:10FD1000E180000000880060E18000000088006051 ++:10FD2000E180000000880060E18000000088006041 ++:10FD3000E180000000880060E18000000088006031 ++:10FD400000000000000000000000000000000000B3 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000000000000000000000000000000000093 ++:10FD70000000000000000000000000000000000083 ++:10FD80000000000000000000000000000000000073 ++:10FD90000000000000000000000000000000000063 ++:10FDA000E0800000002400D0018000000088006096 ++:10FDB0000180000000880060018000000088006071 ++:10FDC0000000000000000000000000000000000033 ++:10FDD0000000000000000000000000000000000023 ++:10FDE0000000000000000000000000000000000013 ++:10FDF000E0800000002400D0018000000088006046 ++:10FE00000180000000880060000000000000000089 ++:10FE100000000000000000000000000000000000E2 ++:10FE200000000000000000000000000000000000D2 ++:10FE300000000000000000000000000000000000C2 ++:10FE40000000000000000000E0800000002400D05E ++:10FE500000000000000000000000000000000000A2 ++:10FE60000000000000000000000000000000000092 ++:10FE7000E180000000880060E180000000880060F0 ++:10FE80000180000000880060000000000000000009 ++:10FE90000180000000880060018000000088006090 ++:10FEA0000000000000000000000000000000000052 ++:10FEB0000000000000000000000000000000000042 ++:10FEC0000000000000000000000000000000000032 ++:10FED00001800000008800600000000000000000B9 ++:10FEE0000000000000000000000000000000000012 ++:10FEF0000180000000880060000000000000000099 ++:10FF000000000000000000000000000000000000F1 ++:10FF100000000000000000000000000000000000E1 ++:10FF200000000000000000000000000000000000D1 ++:10FF300000000000000000000000000000000000C1 ++:10FF400000000000000000000000000000000000B1 ++:10FF5000E0800000002400D0E0800000002400D0F9 ++:10FF60000180000000880060E0800000002400D0D4 ++:10FF70000000000000000000000000000000000081 ++:10FF80000000000000000000000000000000000071 ++:10FF90000000000000000000000000000000000061 ++:10FFA000018000000088006001800000008800607F ++:10FFB000E0800000002400D00000000000000000ED ++:10FFC0000000000000000000000000000000000031 ++:10FFD000E0800000002400D00000000000000000CD ++:10FFE000E0800000002400D0018000000088006054 ++:10FFF0000180000000880060000000000000000098 ++:020000040005F5 ++:1000000000000000000000000000000000000000F0 ++:1000100000000000000000000000000000000000E0 ++:1000200000000000000000000000000000000000D0 ++:1000300000000000000000000000000000000000C0 ++:1000400000000000000000000000000000000000B0 ++:1000500000000000000000000000000000000000A0 ++:100060000000000000000000000000000000000090 ++:10007000E0800000002400D00180000000880060C3 ++:100080000000003044B90C44002000E80C850080DA ++:100090000A0600000041AE9E0000000000000000C3 ++:1000A0000000000000000000000000000000000050 ++:1000B000000000007975AE9E000000000000000006 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000079750000000000000000000032 ++:1000E0000000000000000000000000000000000010 ++:1000F0000000000000000000000000000000000000 ++:1001000000000000000000000000000000000000EF ++:100110000000000000000000FFFFFFFFFFFFFFFFE7 ++:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F ++:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F ++:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10019000FFFFFFFFFFFFFFFFFFFF00BC8B8F0C4443 ++:1001A000802000E80A0600000041AE9E000000002A ++:1001B000000000000000000000000000000000003F ++:1001C00000000000000000007975AE9E00000000F5 ++:1001D000000000000000000000000000000000001F ++:1001E000000000000000000079750000AE9E0000D5 ++:1001F00000000000000000000000000000000000FF ++:10020000000000000000000000007975AE9E0000B4 ++:1002100000000000000000000000000000000000DE ++:10022000000000000000000000007975FFFFFFFFE4 ++:10023000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE ++:10024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE ++:10025000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE ++:10026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10027000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10029000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:1002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00E478 ++:1002B00099310C44402000E80A0600000041AE1EBF ++:1002C000010000000000000000000000000000002D ++:1002D0000000000000000000000000807875AE1EE5 ++:1002E000010000000000000000000000000000000D ++:1002F0000000000000000000000000007975000010 ++:10030000AE9E0000000000000000000000000000A1 ++:100310000000000000000000000000000080787570 ++:10032000AE9E000000000000000000000000000081 ++:1003300000000000000000000000000000007975CF ++:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD ++:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD ++:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D ++:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D ++:10039000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D ++:1003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D ++:1003B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D ++:1003C000FFFF00FCCA620C44407000E80A0600000F ++:1003D00000410000000000000000000000000000DC ++:1003E000000000000000000000000000000000000D ++:1003F00000000E1E010000000000000000000000D0 ++:10040000000000000000000000000000000000806C ++:1004100078700000000000000000000000000000F4 ++:1004200000000000000000000000000000000000CC ++:1004300000000000AEDE0000000000000000000030 ++:1004400000000000000000000000000000000000AC ++:1004500000007B75FFFFFFFFFFFFFFFFFFFFFFFFB8 ++:10046000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C ++:10047000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C ++:10048000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C ++:10049000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:1004A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:1004B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:1004C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:1004D000FFFFFFFFFFFF0068C4A20C44C02000E83C ++:1004E0000A060000004100000000000000000000BB ++:1004F00000000000000000000000000000000000FC ++:1005000000000000000000000000000000000000EB ++:1005100000000000000000000000000000000000DB ++:1005200000000000797500000000000000000000DD ++:1005300000000000000000000000000000000000BB ++:1005400000000000000079710000000000000000C1 ++:10055000000000000000000000000000000000009B ++:100560000000000000000000FFFFFFFFFFFFFFFF93 ++:10057000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B ++:10058000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B ++:10059000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B ++:1005A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B ++:1005B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B ++:1005C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B ++:1005D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B ++:1005E000FFFFFFFFFFFFFFFFFFFF0070D9AD0C858E ++:1005F00000500C8500C004000400040004000C85B9 ++:1006000000500C8500A00C8700FF0C8300810C407B ++:100610000024DD610C8500B0040004000400040027 ++:1006200004000400040004000400040004000400AA ++:0406300004000400BE ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1161.202.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1161.202.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1161.202.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1161.202.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,20590 @@ ++# ++# $Id: FPGA_1161.201.hex 11553 2017-06-07 14:32:38Z dima $ ++# ++:020000040000FA ++:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:100010005599AA660C8500E004008C85C0018C828D ++:10002000BC008C8691778C43200008C90C8700F3B4 ++:100030000C83008104000400040004000400040098 ++:100040000400040004000400040004000400040090 ++:10005000040004000400CC813C138C8110812C84AA ++:1000600000004C8000F88C87FFFFCC8400A0CC827D ++:100070000020CC8080004C8600004C8100004C8524 ++:1000800000004C8300004C870000CC85D847CC434F ++:1000900000000000040004000C44000000000C8577 ++:1000A00000800A06000080610000000000000000DF ++:1000B0000000000000000000000000000000000040 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000000000000000000000000000020 ++:1000E0000000000000000000000040900000409070 ++:1000F0000000000000000000000000000000000000 ++:1001000000000000000000000000000000000000EF ++:1001100000000000000000000000000000000000DF ++:1001200000000000000000000000000000000000CF ++:1001300000000000000000000000000000000000BF ++:1001400000000000000000000000000000000000AF ++:10015000000000000000000000000000000000009F ++:10016000000000000000000000000000004000004F ++:10017000004000000000000000000000000000003F ++:10018000000000000000000000000000000000006F ++:10019000000000000000000000000000000000005F ++:1001A000000000000000000000000000000000004F ++:1001B000000000000000000000000000000000003F ++:1001C000000000000000000000000000000000002F ++:1001D000000000000000000000000000000000001F ++:1001E00000000000000000000000000000000020EF ++:1001F00000000020000000000000000000000000DF ++:1002000000000000000000000000000000000000EE ++:1002100000000000000000000000000000000000DE ++:1002200000000000000000000000000000000000CE ++:100230000000000000002500000000000000000099 ++:1002400000000000000000000000000000000000AE ++:10025000000000000000000000000000000000009E ++:10026000200000000000000004000000000000006A ++:10027000000000000000000000000000000000007E ++:100280000000000000D0800000000000000000001E ++:10029000000000000000000000000000000000005E ++:1002A000000000000000000000000000000000004E ++:1002B0000000050000000000000000000000000039 ++:1002C000000000000000000000000000000004002A ++:1002D000000004000000000000000000000000001A ++:1002E000000000000000000000000000000004000A ++:1002F00000000000040000000000000000000000FA ++:1003000000000000000000000000000000000000ED ++:1003100000000000000000000000000000000000DD ++:1003200000000000000000000000000000000000CD ++:1003300000000000000000000000000000000000BD ++:1003400000000000000000000000000000000000AD ++:10035000000000000000000000000000000000009D ++:10036000000000000000000000000000000000008D ++:10037000000000000000000000000000000000007D ++:10038000000000000000000000000000000000006D ++:10039000000000000000000000000000000000005D ++:1003A000000000000000000000000000000000004D ++:1003B0000000000000E48EEC0C8500400400040006 ++:1003C000040004000400040004000400CC26000023 ++:1003D0000000000000000C44008000A0CC260000BB ++:1003E0000000000000000C4400800060CC260000EB ++:1003F0000000000000000C4400800008CC26000033 ++:100400000000000000000C4400800088CC260000A2 ++:100410000000000000000C44008000C8CC26000052 ++:100420000000000000000C44008000A8CC26000062 ++:100430000000000000000C4400800098CC26000062 ++:100440000000000000000C4400800058CC26000092 ++:100450000000000000000C44002000A8CC26000092 ++:100460000000000000000C4400200068CC260000C2 ++:100470000000000000000C4400E00030CC2600002A ++:100480000000000000000C4400E000B0CC2600009A ++:100490000000000000000C4400E00070CC260000CA ++:1004A0000000000000000C4400E000F0CC2600003A ++:1004B0000000000000000C4400E00008CC26000012 ++:1004C0000000000000000C4400E00088CC26000082 ++:1004D0000000000000000C4400E00048CC260000B2 ++:1004E0000000000000000C4400E000C8CC26000022 ++:1004F0000000000000000C4400E00028CC260000B2 ++:100500000000000000000C4400E000A8CC26000021 ++:100510000000000000000C4400E00068CC26000051 ++:100520000000000000000C4400E000E8CC260000C1 ++:100530000000000000000C44001000E8CC26000081 ++:100540000000000000000C4400700040CC260000B9 ++:100550000000000000000C4400700030CC260000B9 ++:100560000000000000000C44007000B0CC26000029 ++:100570000000000000000C4400700070CC26000059 ++:100580000000000000000C44007000F0CC260000C9 ++:100590000000000000000C4400700008CC260000A1 ++:1005A0000000000000000C4400700088CC26000011 ++:1005B0000000000000000C4400700048CC26000041 ++:1005C0000000000000000C44007000C8CC260000B1 ++:1005D0000000000000000C4400700028CC26000041 ++:1005E0000000000000000C44007000A8CC260000B1 ++:1005F0000000000000000C4400700068CC260000E1 ++:100600000000000000000C44007000E8CC26000050 ++:100610000000000000000C4400700018CC26000010 ++:100620000000000000000C4400F000E8CC260000B0 ++:100630000000000000000C4400880040CC260000B0 ++:100640000000000000000C4400880060CC26000080 ++:100650000000000000000C44008800E0CC260000F0 ++:100660000000000000000C4400880010CC260000B0 ++:100670000000000000000C44008800D0CC260000E0 ++:100680000000000000000C4400880030CC26000070 ++:100690000000000000000C44008800B0CC260000E0 ++:1006A0000000000000000C4400880008CC26000078 ++:1006B0000000000000000C4400880088CC260000E8 ++:1006C0000000000000000C4400880048CC26000018 ++:1006D0000000000000000C44008800C8CC26000088 ++:1006E0000000000000000C4400880028CC26000018 ++:1006F0000000000000000C44008800A8CC26000088 ++:100700000000000000000C4400880018CC26000007 ++:100710000000000000000C4400880098CC26000077 ++:100720000000000000000C4400880058CC260000A7 ++:100730000000000000000C44008000400C85008098 ++:100740000A060000802000000000000000000000F9 ++:100750000000000000000000000000000088000011 ++:100760000000000000000000000000000000000089 ++:100770000000000000000000000000000000000079 ++:100780000000000000000000000000000000000069 ++:100790000000000000000000000000000000000059 ++:1007A0000000000000000400000000000000020043 ++:1007B0000000000000000000000000000000000039 ++:1007C0000000000000000000000000000000000029 ++:1007D00000000000000000100000000000000040C9 ++:1007E00000000000000000400000000000000000C9 ++:1007F00000000000000000100000000000000000E9 ++:1008000000000000000000000000000000000000E8 ++:1008100000000000000000000010000000000000C8 ++:1008200000000000000000000000000000000000C8 ++:100830000100000000000000002000000000000097 ++:1008400000000000000000000000000000000000A8 ++:100850000000000000000000000000000000000098 ++:100860000000000000000000000000000000000088 ++:10087000000000000000000009000000000000006F ++:100880000000000000000000000000000000000068 ++:100890000000000000000000000000000000000058 ++:1008A0000000000000000000000000000000000048 ++:1008B0000000000000000000000000000000000038 ++:1008C000000000000000000000000000FFFFFFFF2C ++:1008D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28 ++:1008E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 ++:1008F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 ++:10090000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 ++:10091000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 ++:10092000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 ++:10093000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 ++:10094000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00ECC9 ++:10095000DE880C44008000E00A06000040510000E0 ++:100960000000000000000000000000000000000087 ++:100970000000000000000000000000000000000077 ++:100980000000000000000000000000000000000067 ++:100990000000000000000000000000000000000057 ++:1009A0000000000000000000000000000000000047 ++:1009B0000000000000000000000000000000000037 ++:1009C00000000000000000000000840000000000A3 ++:1009D0000000000000000000000000000000000017 ++:1009E0000000000000000000000000000000000007 ++:1009F00000000000000000000000000000000000F7 ++:100A000000000000000000000000000000000000E6 ++:100A100000000000000000000000000000000000D6 ++:100A200000000000000000000000000000000000C6 ++:100A300000000000000000000500000000000000B1 ++:100A40000000000000000000050000000000008819 ++:100A50000000000000000000000000000000000096 ++:100A60000000000000000000000000000000000086 ++:100A70000000000000000000000000000000000076 ++:100A80000000000000000000000000000000000066 ++:100A90000000000000000000000000000000000056 ++:100AA000000000000000000000000000000900003D ++:100AB0000000000000000000000000000000000036 ++:100AC000820000000000000000090000000000009B ++:100AD0000000000000000000000000000000000016 ++:100AE0000000000000000000000000000000000006 ++:100AF00000000000000000000000000000000000F6 ++:100B000000000000000000000000000000000000E5 ++:100B100000000000000000000000000000000000D5 ++:100B200000000000000000000000000000000000C5 ++:100B300000000000090000000000000000000000AC ++:100B40000000000010000000100000000000000085 ++:100B50000000000000000000000000000000000095 ++:100B60000000000000000000000000000000000085 ++:100B70000000000000000000000000000000000075 ++:100B80000000000000000000000000000000000065 ++:100B90000000000000000000000000000000000055 ++:100BA0000000000000000000000000000000000045 ++:100BB0000000000000000000000000000000000035 ++:100BC00000000000000090000020880000000000ED ++:100BD0000000000000000000000000000000000015 ++:100BE0000000000000000000000000000000000005 ++:100BF00000000000000000000000000000000000F5 ++:100C000000000000000000000000000000000000E4 ++:100C100000000000000000000000000000000000D4 ++:100C200000000000000000000000000000000000C4 ++:100C300000000000000000000000000000000000B4 ++:100C400000000000000000000000000000000000A4 ++:100C50000000000020000000000000000000000074 ++:100C60000000000000000000000000000000000084 ++:100C70000000000000000000000000000000000074 ++:100C80000000000000000000000000000000000064 ++:100C90000000000000000000000000000000000054 ++:100CA0000000000000000000000000000000000044 ++:100CB0000000000000000000000000000000000034 ++:100CC0000000000000000000000000000000000024 ++:100CD0000000000000000100000000000000000013 ++:100CE0000000000000000000000000000000000004 ++:100CF00000000000000000000000000000000000F4 ++:100D000000000000000000000000000000000000E3 ++:100D100000000000000000000000000000000000D3 ++:100D200000000000000000000000000000000000C3 ++:100D300000000000000000000000000000000000B3 ++:100D400000000000000000000000000000000000A3 ++:100D50000000000000A001000000000000C0000032 ++:100D60000000000000000000000000000000000083 ++:100D70000000000000000000000000000000000073 ++:100D80000000000000000000000000000000000063 ++:100D90000000000000000000000000000000000053 ++:100DA0000000000000000000000000000000000043 ++:100DB0000000000000000000000000000000000033 ++:100DC0000000000000000000000000000000000023 ++:100DD000000000000000000008000000000000808B ++:100DE0000000000000000000000000000000000003 ++:100DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:100E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:100E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:100E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:100E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:100E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:100E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:100E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:100E7000FFFF0094DA5A0C44008000480A06000084 ++:100E80000041000000000000000000000000000021 ++:100E90000000000000000000000000000000000052 ++:100EA0000000000000000000000000000000000042 ++:100EB0000000000000000000000000000000000032 ++:100EC00000000040000000000000000000000000E2 ++:100ED0000000000000000000000000000000000012 ++:100EE0000000000000000000000000000000000002 ++:100EF00000000000000000000000000000000000F2 ++:100F000000000000FFFFFFFFFFFFFFFFFFFFFFFFED ++:100F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 ++:100F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 ++:100F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 ++:100F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 ++:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 ++:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 ++:100F8000FFFFFFFFFFFF009C16A90C440080002814 ++:100F90000A06000000410000000000000000000000 ++:100FA0000000000000000000000000000000000041 ++:100FB0000000000000000000000000000000000031 ++:100FC0000000000000000000000000000000000021 ++:100FD0000000000000000000000000000000000011 ++:100FE0000000000000000000000000000000000001 ++:100FF00000000000000000000000000000000000F1 ++:101000000000000000000060000000000000000080 ++:101010000000000000000000FFFFFFFFFFFFFFFFD8 ++:10102000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10103000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10104000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 ++:10105000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 ++:10106000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 ++:10107000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 ++:10108000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 ++:10109000FFFFFFFFFFFFFFFFFFFF007844650C44E9 ++:1010A000008000680A0600008020000000000000A8 ++:1010B0000000000000000000000000000000000030 ++:1010C0000000000000000000000000000000000020 ++:1010D0000000000000000000000000000000000010 ++:1010E0000000000000000000000000000000000000 ++:1010F00000000000000000000000000000000000F0 ++:1011000000000000000000000000000000000000DF ++:10111000000000000000000000800000000000004F ++:1011200000000000000000000000000000000000BF ++:1011300000000000000000000000000000000000AF ++:10114000000000000000000000000000000000009F ++:10115000000000000000000000000000000000008F ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:10118000000000000000000000000000000000005F ++:10119000000000000002000000000000000000004D ++:1011A0000000000000000000000000008C000000B3 ++:1011B000000000000000000000000000000000002F ++:1011C000000000000000000000000000000000001F ++:1011D000000000000000000000000000000000000F ++:1011E00000000000000000000000000000000000FF ++:1011F00000000000000000000000000000000000EF ++:1012000000000000000000000000000000000000DE ++:1012100000000000000000000000000008200000A6 ++:1012200000000000000000000000000000000000BE ++:10123000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE ++:10124000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE ++:10125000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10126000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10127000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10128000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10129000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:1012A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:1012B000FFFF0050F1CA0C44008000D80A0600006D ++:1012C000A86B00000000000000000000000000000B ++:1012D000000000000000000000000000000000000E ++:1012E00000000000000000000000000000000000FE ++:1012F00000000000000000000000000000000000EE ++:1013000000000000000000000000000000000000DD ++:1013100000000000000000000000000000000000CD ++:10132000000000000000000000000100000000209C ++:1013300000000100000000000000000000000000AC ++:10134000000000000000000000000000000000009D ++:10135000000000000000000000000000000000008D ++:10136000000000000000000000000000000000007D ++:10137000000000000000000000000000000000006D ++:10138000000000000000000000000000000000005D ++:10139000000000000000000000000000000000004D ++:1013A00000000000000000400000000000000040BD ++:1013B000000000000000000000000000000000002D ++:1013C000000000000000000000000000000000001D ++:1013D000000000000000000000000000000000000D ++:1013E00000000000000000000000000000000000FD ++:1013F00000000000000000000000000000000000ED ++:1014000000000000000000000000000000000000DC ++:1014100000000000000000000000000000000000CC ++:1014200000000000000000000000001008000000A4 ++:1014300000000001090000000000000000000000A2 ++:10144000000000000000000000000000000000009C ++:101450000000000000000200000000000000030087 ++:10146000000000000000000000000000000000007C ++:101470000000000000000400000003000000040061 ++:10148000000000000000000000000000020000005A ++:10149000000000000000000000000000000000004C ++:1014A000000000000000000000000000000000003C ++:1014B000000000000000000000000000000000002C ++:1014C000000000000000000000000000000000001C ++:1014D000000000000000000000000000000000000C ++:1014E00000000000000000000000000000000000FC ++:1014F00000000000000000000000000000000000EC ++:10150000000000000000000000000080000000005B ++:1015100000000000000000000000000000000000CB ++:1015200000000000000000000000000000000000BB ++:1015300000000000000000000000000000000000AB ++:10154000000000000000000000000000000000009B ++:1015500000000400000000000000008900040000FA ++:101560000001002000000000030120010000000035 ++:10157000000000000000000000000020000000004B ++:1015800000002000000000000010800000C00000EB ++:10159000000000000000000000000000000000004B ++:1015A00008000000000004000020002000200000CF ++:1015B000000000000001000000000000000000002A ++:1015C00021000000001000000000000000000000EA ++:1015D0000000002101000020000000000004028043 ++:1015E0000000000400800000000002040120000050 ++:1015F0000000000002000000000000000080000069 ++:1016000000000000010000000000008020000080B9 ++:1016100000000000000000100000000000000000BA ++:101620000000010000000000010000800080008038 ++:10163000000000000000002000000000000000008A ++:10164000000000000000008000000000000000001A ++:1016500000900000009000000000009000000000DA ++:101660000002000000C000A0000000000000000018 ++:101670000000000000000010000400200000000036 ++:10168000000000000000000000000000000000005A ++:10169000000000000000000000000000000000004A ++:1016A000000000000010000000000000000000002A ++:1016B0000002100800000000000000000000000010 ++:1016C000000000000000000000000000000000001A ++:1016D000000000000000000000000000000000000A ++:1016E000000000800000000000000000000000007A ++:1016F00000000000000000000000000000000000EA ++:1017000000000000000000000000000000000000D9 ++:1017100000000000000000000000000000000000C9 ++:101720000000000000000080000000000000000039 ++:1017300000000080018000000000000000000000A8 ++:101740000000000000000000000000000000000099 ++:1017500000000000008500010001000400000000FE ++:101760000300410000000000000000040000000031 ++:101770000000000000000000000000000000000069 ++:101780000000000000C00000000000A08000000079 ++:101790000001800100000000400000000000000087 ++:1017A000000000000000000005002100000003010F ++:1017B0000000000000000000000000000000000029 ++:1017C0000000000000000000000000000000000019 ++:1017D000000000000000A00400040004008200419A ++:1017E0000000000010000000000000000880000061 ++:1017F00000000000000000008200840000000000E3 ++:1018000000000000000000000000000000000400D4 ++:10181000000000202002000000000900000000007D ++:101820000000000000001000000000000000100098 ++:1018300000040000000000000000000000000000A4 ++:101840000000000000000000000000000000000098 ++:10185000000000000000000000000000000004A0E4 ++:101860000000000000000000000040000000000434 ++:101870000000000420000000000000000000000044 ++:1018800000000000009000010400000009000000BA ++:101890000000000000000020000000000000000028 ++:1018A0000000000000000000000008840810040090 ++:1018B000040000A00000000200000000100000A0D2 ++:1018C0002020000000000000000000000088000050 ++:1018D0000000000000000000000000000000000008 ++:1018E00001000000000000000000000001000000F6 ++:1018F00000000000000001000000000000000000E7 ++:1019000000000000000000000004000000000000D3 ++:101910000000000000000000008000000000000047 ++:1019200000000000880000000000000001000180AD ++:101930000100010000000000008000000000000025 ++:101940008400008000000000820000000000000011 ++:101950000000000000000000000000000000000087 ++:101960000000000000000000000000200000000156 ++:101970000000800000840084080080040000000053 ++:10198000000000C000000000000000000000000097 ++:101990000000000080008001800000A00000000026 ++:1019A0000000000000A000002100000000A00000D6 ++:1019B0001010000000A000024000090000C0000854 ++:1019C0001000000200008000000100C18000000043 ++:1019D0000000000000000000000000000000000007 ++:1019E0000000000000000000000000000080000077 ++:1019F000000200000400000000000000048000005D ++:101A000000000800000000000000000000000000CE ++:101A1000000000000000040040400800000000003A ++:101A200000000000000000000000000000000000B6 ++:101A300000000080000000000080010000000000A5 ++:101A400000910000008000000400842000200400B9 ++:101A50000000000000000000000000000000000086 ++:101A60008003210900000000800008000000000041 ++:101A700091100009000409080000000000000000A7 ++:101A80000000000000000000000000000000000056 ++:101A9000000004000000000080830991004141899A ++:101AA00000000000000000000000808304000080AF ++:101AB00000808083A08000800000000320000000E0 ++:101AC00000400000020000000000000000800080D4 ++:101AD0000080000000000000000000000000000086 ++:101AE0000000C001010182000000C000010082006E ++:101AF0000000910100000000010100000000000052 ++:101B000000000000000000000000000000000000D5 ++:101B100000000000000000000000908385840009A0 ++:101B20000111000000000000000000008883009008 ++:101B3000889000088883919088900000000101003F ++:101B40000000000100000000000000000000101074 ++:101B50000408000800000000000000000000000071 ++:101B6000000000000000010000C0010100000000B2 ++:101B700000000101000001C001010101008200001C ++:101B80000000010000000000000000000000000054 ++:101B90000000000001000100018201019101828822 ++:101BA0008910C18200000000000000000000000158 ++:101BB0000184000001894001918404008301001028 ++:101BC00000C000080100000000000000000000014B ++:101BD000A00008000808000000000000000000004D ++:101BE0000000000000040000410000000309400064 ++:101BF0000900090009210000418004020309048052 ++:101C000009001100090000000000000000000000B1 ++:101C10000000000000110200410021800303911127 ++:101C20000080899140880000000000000000000052 ++:101C300000114100000003110011C10000008311D8 ++:101C4000008000000080030000000000000200008F ++:101C500000400000800080800900000000000000BB ++:101C6000090000000000000000000000000900035F ++:101C70000000000000000080094100050009400349 ++:101C800000020041090400090000000000000000FB ++:101C900000000000000080000000000000000000C4 ++:101CA00002828091899191830080000000000000F1 ++:101CB0000000020000099100800302008009110069 ++:101CC0008083000009400000800300000000020043 ++:101CD0000080008000000080008000000000000004 ++:101CE00000000000000000000000000000000001F3 ++:101CF0000201000000000000008800010001000156 ++:101D000041010001000101009001000000000000FD ++:101D100000000000000000002000000000000000A3 ++:101D200000000189901091A08991008000000000BE ++:101D30000000000001000001A10090010190C0031B ++:101D400005049083880000010000080100000000E5 ++:101D5000010000880010A0A0820800080000000018 ++:101D60000000000000000000000000000188018267 ++:101D700000000001000000A10082000101A0018517 ++:101D800001830101000000A000000000000000002D ++:101D90000000000000000000000000000000000043 ++:101DA00000000000C18911018201918800800000BB ++:101DB0000000000000008300900008000000830085 ++:101DC0009004C000C088010000000001000001086C ++:101DD00001020000000010100800100000100000B8 ++:101DE0000000000000000000000000000000038070 ++:101DF000048000000003000000C000820041098050 ++:101E00002191094111210000008200020000000020 ++:101E100000000000000000000000000000000000C2 ++:101E200000000000000802898441110291800080B6 ++:101E300000000040000000008300800080000000DF ++:101E400083008000800000000300000000100000FC ++:101E500003802080000002000010800080000080CD ++:101E60000000000000000000000000000000000072 ++:101E700000880013D000828800410042C200008226 ++:101E8000000000132000000000000013C2008100C9 ++:101E900000000000000000000000000BC100000076 ++:101EA000000000004820004200000083C1000084C0 ++:101EB00000000000000000000000000000420000E0 ++:101EC000000000000042000000000000004210007E ++:101ED0000000000000224800000000000013000085 ++:101EE00000000000000000000000000000000000F2 ++:101EF0000000FF000000FF000000000000000000E4 ++:101F0000000000FB0004C102414100000000FF0C82 ++:101F1000FF30000000000000000000000000000092 ++:101F20000000000000000000000091089900C0308F ++:101F3000C3FF00000000000000000000FFFF0000E1 ++:101F40000F0F0000FFFF00000F0F0000FFFF000059 ++:101F50000F0F0000E7E78100000000000000000014 ++:101F60000000000000000000000000000000000071 ++:101F700000000000FF000000FF0000000000000063 ++:101F80000000000000FF0000C3004242000000000B ++:101F9000FF0CFF3000000000000000000000000007 ++:101FA00000000000000000000000000099009900FF ++:101FB000C030FFFF00000000000000000000000033 ++:101FC00000000F0F0000000000000F0F00000000D5 ++:101FD00000000F0F0000E7E7810000000000000094 ++:101FE00000000000000000000000000000000000F1 ++:101FF00000000000000000000000000000000000E1 ++:1020000000000000000000000000000000000000D0 ++:1020100000000000000000000000000000000000C0 ++:10202000000000000000000000000001044000006B ++:1020300000000000000000000000000000000000A0 ++:102040000000000000000000000000000000000090 ++:102050000000000000000000000000000000000080 ++:102060000000000000000000000000000000000070 ++:102070000000000000000000000000FFFFFF0F0F45 ++:10208000000000008181CFFF0000002099000F00B8 ++:102090000000000099003FFF000000000000000069 ++:1020A000000000000000000000000000000003002D ++:1020B0005600CC00FFFFFFBD000000000000666678 ++:1020C00066660000FFFF0000F0F00000FFFF000068 ++:1020D000F0F000003C3CFFFF0000000000000000AA ++:1020E00000000000000000000000000000000000F0 ++:1020F00000000000000000000000000000FFFFFFE3 ++:102100000F0F000000008181FFFF00000000990018 ++:10211000F000000000009900FFFF00000000000038 ++:1021200000000000000000000000000000000000AF ++:1021300003006600F000FFFFFFFF0000000000004A ++:1021400066666666000000000000F0F00000000017 ++:102150000000F0F000003C3CFFFFFFFF000000002B ++:10216000000000000000000000000000000000006F ++:10217000000000000000000000000000C0C7C07D9B ++:1021800030B04103008600640090000000860260C9 ++:1021900000B200100086006000B0000000000000E7 ++:1021A000000000000086006108B00005000000008B ++:1021B0000000000000840440008900850000000049 ++:1021C00000000000084002C1018000B44940024103 ++:1021D000018000044940A2C7016108B4414008865B ++:1021E0000071009000000086008000800000000068 ++:1021F0000080010000000000000009000000000055 ++:1022000000000000000000000000FFFF00000000D0 ++:1022100000000000000000000000000000000000BE ++:1022200000000000000000000000000000000000AE ++:102230000000000000000010000000F000F00000AE ++:10224000000000000000000000000000000000008E ++:102250000202030000000000000000000000000077 ++:1022600000000000FFFF0000000000000000000070 ++:10227000000000200000000000000020000001001D ++:10228000000000000000000000000000FFFF000050 ++:10229000000000000000000000000000000000003E ++:1022A000000000000000000000000000000000002E ++:1022B00000000000000000000000000000F030C03E ++:1022C000000000000000000000000A0A0F000000EB ++:1022D0000000020203000F003C00000000000000AC ++:1022E000000000000000FFFF0000000000A00C0044 ++:1022F000000000000000000002000040000000009C ++:1023000002000000000000000000000000000000CB ++:1023100000000000000000000000000000000000BD ++:1023200000000000000000000000000000000000AD ++:1023300000000000000000000000CB080B0B00F0C4 ++:1023400040B00000000000000000000000C000C31A ++:1023500000000000000000003000500000000000FD ++:10236000000000000000000000000000000000006D ++:10237000000000004000000000000000000000001D ++:10238000000000000000000000000000000000004D ++:10239000000000000000000000000000000000003D ++:1023A000000000000000000000000000000000002D ++:1023B000000000000000000000000000CB083C000E ++:1023C00000F000F00000000000000000000000C06D ++:1023D00000000000000000F000AA300050000000E3 ++:1023E00000000000000000000000000000000200EB ++:1023F00002000500000000000000000000000000D6 ++:1024000000000000000008000000000000000200C2 ++:102410000200000003000000400000002100000056 ++:102420000000000011000000040000000000000097 ++:10243000000000000000000000000000000002009A ++:102440000000000004000000000000000000000088 ++:10245000000000000000000000000000000021005B ++:10246000000000000000210000000000000000004B ++:10247000000000000000000000000000000000005C ++:102480000000000000000010010000000000000932 ++:10249000000000000000000000000100000000003B ++:1024A000000000000000000000000100000000002B ++:1024B000000000000000000000000000000000001C ++:1024C000000000000000000000C00000000000004C ++:1024D00000000000000000000000000000000000FC ++:1024E00000000000000000000000000000000000EC ++:1024F00000000000000000000000000000000000DC ++:1025000000000000000000000080000100018005C4 ++:102510000009000000010004800400010001000027 ++:102520002101000000010001000000000001000086 ++:102530000000000000000000040000000000000097 ++:10254000002000000000000000000040000000002B ++:10255000000000000000000000000000000000007B ++:10256000002000000000000000000000000000004B ++:10257000000000000000000000000000000000005B ++:102580000000000000000000000000000204002025 ++:1025900008C000200000000400800280002000022B ++:1025A00000000004020000040004002000000004F9 ++:1025B00000000000000000000021010000000000F9 ++:1025C000000000800000000000000000008000000B ++:1025D00000000000000000000000000000000000FB ++:1025E000000000800000000000000000000000006B ++:1025F00000000000000000000000000000000000DB ++:102600000000000000000000000000000000008248 ++:1026100005400040000000880040004000C000006D ++:1026200000000000004003000004009000020000D1 ++:102630000000000000000000000000840000000016 ++:102640000000000000000000000000A000040000E6 ++:10265000000000000000000000000000000000007A ++:1026600000000040004000000000000000000000EA ++:10267000000000000000000000000000000000005A ++:10268000000000000000000000000000000000004A ++:1026900000000090000000050000000040802000C5 ++:1026A00082000000C00000800000008000000000E8 ++:1026B00000000000000000000000C000000000005A ++:1026C0000000000000000003000000000000008483 ++:1026D0000000000010050041000000000000C000E4 ++:1026E00000000000000000000000000000000000EA ++:1026F0000000000000008400000000000000000056 ++:102700000000000000000000820000000000000047 ++:1027100000000000410010019041100108840040B9 ++:10272000100000008000008802000000100000007F ++:1027300000018000009000200000000010100084C4 ++:1027400000840800000000820004000000900800DF ++:102750000005000000000000000000000000000074 ++:1027600000000000000000008000000010000300D6 ++:102770000300000000040000002000000000000032 ++:102780000000000000000000000000000000000049 ++:102790000000000000000000002008840808082154 ++:1027A00000800000A0004000000002000000840043 ++:1027B00082000204400000000880C0001000108069 ++:1027C00000000000A00010000000108000000000C9 ++:1027D0000000008200000000000000000000000077 ++:1027E00000000000000000000000400000000000A9 ++:1027F00000000000100000800000008000000000C9 ++:1028000000000000000000000000000000000000C8 ++:10281000000000000000004000A1000041841020E2 ++:102820001040000021A0000021000002080000204C ++:1028300000000004092040000000000440000000E7 ++:10284000000000000500000000000000000000C0C3 ++:102850000000000000000000000000000000000474 ++:1028600000000002000000002000400004002100E1 ++:102870008002800080020200C000000040000220B0 ++:1028800041210001030100210000000000000000C0 ++:1028900000000000000000000080000400000005AF ++:1028A00011001000001000004000000000000400B3 ++:1028B000C080000000850080010000000080010051 ++:1028C00000000000000000210000000000030000E4 ++:1028D000002100000021002100000009000000008C ++:1028E000008000000000C0000000010301000100A2 ++:1028F00000002080200020A000000900000001004E ++:1029000000800082C002C00200820000820000003D ++:102910001000000000000000100088C0411080007E ++:102920000040004041A0000000000000884000007E ++:1029300000C0000000000090000110000001200015 ++:1029400040030000000000840000000000000000C0 ++:102950000020000000000000009000000040000087 ++:10296000008400400000020000000000000005009C ++:1029700040000000002000000500000000114000A1 ++:1029800005204000000000200020000000000000A2 ++:1029900000000000000000000000000009000080AE ++:1029A0000800108884000000C00000000000408083 ++:1029B000000000000000C000000000201000002007 ++:1029C000010001A0840000008440100000001000FD ++:1029D000000000A10000C000000000000000000096 ++:1029E00000000000000000000000000000000000E7 ++:1029F00000000100000000800000000000000090C6 ++:102A000091000080010000000080008000000000B4 ++:102A1000000000000000000000000000000003892A ++:102A20002089042105900505090240110341008019 ++:102A30000580088000000000000000000011110364 ++:102A400000090002031100008000200000000000C7 ++:102A50000000000000000000000000000000000076 ++:102A60000000000000000000000000000000000066 ++:102A70008000000089090000000300004009008078 ++:102A80000003801000000000008300000903030021 ++:102A90000000000000000000000000000000000036 ++:102AA000098289A100090110010101000000010152 ++:102AB0000088890801C000C000000000000000007C ++:102AC0008901000100010100000040000100000038 ++:102AD000000000008800000000000000000000006E ++:102AE00000000000000000000000000000000000E6 ++:102AF0000000900084009101000000C1A0C0A1C1AD ++:102B000000080001080100000000000502C0A0024A ++:102B100000000000000000000000000000000000B5 ++:102B20000000400000C0898383098300C00008843E ++:102B300083000040000000000102001000000000BF ++:102B40000000000000000082000000000000000003 ++:102B50000000000000000000000100000000010073 ++:102B60000001000000000000000000000000000064 ++:102B7000000000000100A0A0880105000801A001DC ++:102B8000C0000182080009008800830004000200E0 ++:102B90000200C10000000000000000000000000072 ++:102BA0000000000009000080210389050500820063 ++:102BB00000408910000804000500030000800000A8 ++:102BC0000000000000000000000000000000000005 ++:102BD00000000000000000000000001005000500DB ++:102BE00021000509000002000000000000000000B4 ++:102BF00000000000000010000000800903008008B1 ++:102C000000030000038080008800800083008005AE ++:102C100000000000030000000000000000000900A8 ++:102C20000000000000000309020911098080000073 ++:102C30000002400941C10080008002800080000045 ++:102C4000000900008000030021000009910300003A ++:102C50000000000000800000000000000080000074 ++:102C60000000000000000000000000000000000064 ++:102C700000000000000000000000000008218003A8 ++:102C8000000000800240808300000080101000835C ++:102C90000080000080000003000000000000000031 ++:102CA0000000000000000000019001108589C08232 ++:102CB00010020084000301110008A01001080008A0 ++:102CC000000000000000820001000100000111016D ++:102CD000000000C000C0008200000000000000886A ++:102CE00000000000000000000000000000000000E4 ++:102CF00000000000000000000000000000A000092B ++:102D0000880590C0A090010188090400001000010E ++:102D10000089000402A00802000100000000000079 ++:102D20000000000000000000000083918885400042 ++:102D300010080091019100000090021004000401AD ++:102D4000040000000000000000010000000000007E ++:102D50000000000000000000000000000000000073 ++:102D60000000000000010000000000000000000062 ++:102D70000000000000000000000000000101011040 ++:102D800000000090C189A10008010090010101002C ++:102D90000000008803000208C000A0C0000000007E ++:102DA00000000000000000000000000089A11103E5 ++:102DB0009010000008822010001100000000001098 ++:102DC00000100000000000100000001000000000D3 ++:102DD00000000000000000000000000000000000F3 ++:102DE00000000000000000030003000000000000DD ++:102DF00000000000000000000000000000000302CE ++:102E0000088004000980034009008021008003112C ++:102E1000080000000080030000858500008000009D ++:102E200000000000000000000000000000000000A2 ++:102E30000010480082410000001010000041000016 ++:102E40000022020000000000000BD0000041000042 ++:102E500000830200424800000083000000000000E0 ++:102E60000010C100000000000000C100420000008E ++:102E700000000000D0000000000000000000000082 ++:102E800000000013C20000000000001310004260A8 ++:102E900000000022020000000000001300000000FB ++:102EA0000000000000000000000000000000000022 ++:102EB000000AFF5F00FF00FF550055FF00AF50FF05 ++:102EC000000000000000000000000000F0F0F0F042 ++:102ED00000000000000000000000000000000000F2 ++:102EE00000000000000000000000000000000000E2 ++:102EF00000000000000000000000000000000000D2 ++:102F000000000080BFBF000000FF000000FF0000C5 ++:102F100000FF000000FF000000FF00000F0F000096 ++:102F2000FFFF0000000000000000000000000000A3 ++:102F300000000000FFFF08DF08DF550055FF00FF1D ++:102F400000FF000000000000000000000000F0F0A2 ++:102F5000F0F000000000AAAA55AA0000000000003E ++:102F60000000000000000000000000000000000061 ++:102F70000000000000000000000000000000000051 ++:102F80000000000000003F3F000000FF000000FFC5 ++:102F9000000000FF000000FF000000FF00000F0F16 ++:102FA0000000000000000000000000000000000021 ++:102FB00000000000FF00FF00FFFF00413A3C3C3CE6 ++:102FC000FFFF00000000000000F000AAC3C3C3C35D ++:102FD000555555550000000000000000000000009D ++:102FE00000000000000000000000000000000000E1 ++:102FF00015F05500000000000000C3C3C3C300006B ++:10300000000000000000F0F0F0F03C3C0000F0F0A8 ++:103010000000FFFF0000FF000000F0F00000F0F0F3 ++:1030200000005555FFFF00000000000000000000F8 ++:10303000000000000000FF003F30FFBE00003A3CEF ++:103040003C3CFBFB0808000000000FFF55FFC3C31A ++:10305000C3C355555555DF209A9A00000000000063 ++:103060000000000000000000000000000000000060 ++:10307000000015005500000000000000C3C3C3C3DA ++:103080000000000000000000F0F0F0F03C3C000008 ++:10309000F0F0000000000000FF000000F0F0000071 ++:1030A000F0F000005555FFFF000000000000000098 ++:1030B00000000000000000000086006008B0000072 ++:1030C0000006006008B000000086004108B0001053 ++:1030D0000086006108B000000086046100B20000B4 ++:1030E0000086006100900000008600E10890000565 ++:1030F00000000200000000000000000000000800C6 ++:1031000000000000000000000000118601F00084B3 ++:103110004940A2C75180A8844940A2470160008469 ++:10312000494002C7018000844140000000000000C7 ++:1031300000000000000000000000FCFCFFF05C55F7 ++:10314000F0FF000000000F170F0FBAAAEAAA82B220 ++:10315000AAAA00000000000000000000000000001B ++:103160000000000000000000A00000000000FFFFC1 ++:10317000000000000000000000000000000000004F ++:10318000000000000000000000000000000000003F ++:103190000A00000000000000020200000000000021 ++:1031A0000000000000000008000000000000000017 ++:1031B000000000000000008001000000C0C000F01E ++:1031C0003C35000F000000000F170F0F8AAA2AAA33 ++:1031D00000300000000000000000000000000000BF ++:1031E00000000000000000000F00A0000000000030 ++:1031F000FFFF0000000000000000000000000000D1 ++:1032000000000000000000000000000000000000BE ++:1032100000000000000000000A00000000000000A4 ++:103220000000FFFF0F0F000000080800080000006A ++:103230000000000000000000002000000000F03C42 ++:10324000F0F03C55555500000000FCFC505FF7FFC6 ++:10325000200000000000000000000000000000004E ++:10326000000000000000000000000000000000005E ++:10327000000000000000000000000000000000004E ++:10328000000000000000000000000000000000003E ++:10329000000000000000000000020000000000002C ++:1032A00000000000C08070B000000000000020009E ++:1032B000000000000000000000000000000002000C ++:1032C000F03C3C3C3C553C3C000000000C0C505F8A ++:1032D000F7FF2000000000000000000000000000D8 ++:1032E00000000000000000000000000000000000DE ++:1032F00000000000000000000000000000000000CE ++:1033000000000000000000000000000000000000BD ++:1033100000000000000005000000000200000100A5 ++:10332000010000000000004070B005000000000037 ++:10333000200000000000000000004000000000002D ++:10334000000004000000000009200400000011003B ++:103350001100040000008300110000880400000038 ++:10336000000000000000000000000000000000005D ++:103370000000040000000000000000000000000049 ++:10338000000000000000000000000000000000003D ++:10339000000000000000000000000000000000002D ++:1033A000000000000000000000000000000000001D ++:1033B000000000000000000000000000000000000D ++:1033C0000000000020000000000088000000000055 ++:1033D0000400000000000000080090000000000051 ++:1033E00000000000000000000000000000000000DD ++:1033F00000000000000008000000000000000000C5 ++:10340000000000000080000000000000000000003C ++:1034100000000000000000000000000000000000AC ++:10342000000000000000000000000000000000009C ++:10343000000000000000000000000000000000008C ++:1034400000000000000000000000000080000000FC ++:103450000000008880000000000000000010000054 ++:103460000000000000C0000000000000000000009C ++:1034700000100000000000000000000000400000FC ++:103480000001000400040000000000000000000033 ++:10349000020000000000000000000000000000002A ++:1034A000000000000000000000000000000000001C ++:1034B000000000000000000000000000000000000C ++:1034C0000000000000000000004100410020100842 ++:1034D0000021001000411010000000000000004119 ++:1034E00000000000000000000000000000000000DC ++:1034F000000000900010001000000000000000A17B ++:1035000000000010008000800000000000000000AB ++:103510000000000000080008000800000000000093 ++:10352000000000000000000000000000000000009B ++:103530000008000000000000000000000000000083 ++:103540000000000000000000000000820000008871 ++:1035500000880000000000000020090000000000BA ++:103560000082004000000000000000000000000099 ++:103570000000000000000200000000000000000049 ++:10358000000000000000000000000000000000003B ++:10359000000000100000000000000000000000001B ++:1035A000000000000000000000000000000000001B ++:1035B00000000000000021000000000000000000EA ++:1035C00000000000000000000000000000030003F5 ++:1035D000002084211000A0100810101008200020E6 ++:1035E00000000010000000000002000000000000C9 ++:1035F00000000000100000000000000000000000BB ++:1036000000000000000000000000000000000000BA ++:10361000000000000000000000000000C0000000EA ++:103620000000000000008400000900090000000004 ++:10363000000000000000000000000000000000008A ++:10364000000000000000000000000000000020005A ++:1036500010000090038405009000900002004100DB ++:1036600005A04000A18200000300A100410041002C ++:1036700041000300410005000000200000000000A0 ++:103680000000000100000000000000010800000030 ++:10369000000000000000000000000000000020000A ++:1036A000000000000000000000000000000000001A ++:1036B000000000880000000000000000000005007D ++:1036C00000000000000000000000000000000000FA ++:1036D0000208A00082000800000008000441080061 ++:1036E0000041A000010002000000000004000000F2 ++:1036F000C0000000C00000000000820000000000C8 ++:103700000041000000100020000000000020000028 ++:1037100000000000000000000000000000000000A9 ++:103720000000000000000000000000000000000099 ++:103730000000000000000000000000000000000089 ++:103740000000000000000000000000000000000079 ++:10375000000010001090000005880040058841001E ++:103760004100118803882188000009001000000032 ++:1037700021080000110040001000000005001000AA ++:1037800010001100030010000000000010000000F5 ++:103790000008000000000000000000000000000021 ++:1037A0000000000000000000000000000000000019 ++:1037B0000000000000000000000000000000000009 ++:1037C00000000000000000000000000000000000F9 ++:1037D00000000000902100000020022002200000D4 ++:1037E000004100200221C000101110000220000042 ++:1037F00000000004002100000100000000000000A3 ++:1038000000000000000000000000000000000000B8 ++:1038100000000080000088000000000000000000A0 ++:103820000000000000000000000000210000000077 ++:103830000000902090000200000000200200000024 ++:10384000A0000000000000000000000000000000D8 ++:1038500000000000C0001004090080010340108433 ++:1038600010002000084102000000000041A0008874 ++:1038700090108000C14110040500838803011040AE ++:10388000000080048001020041004101100400009A ++:103890000000000000000000000000000000000028 ++:1038A0000000000000000000100000000000000008 ++:1038B00000000000004000000000000000000200C6 ++:1038C00000000000000000000000000000000000F8 ++:1038D0000000000000000000040900004010040087 ++:1038E0008200880001001002004100008400842052 ++:1038F0000000080020212008000900000821080815 ++:103900000000880004881002040900000002000082 ++:10391000000000000000A000000000000000000007 ++:10392000080000000000000000000000000000008F ++:103930000000000000000000C00000110000A00016 ++:103940000000000000000000000000000000000077 ++:103950000000000000000000000080008500001151 ++:1039600083C180000380000283C1830003000083C1 ++:1039700003414000830000C1030080008300808970 ++:1039800083C18000030000828382830000000083E3 ++:1039900003204000830000C103000000000000007D ++:1039A0000000000000000000000000000000000017 ++:1039B0000000000000000000000000000000000007 ++:1039C00000000000000000000000000000000000F7 ++:1039D00000000000000000000000000082828282DF ++:1039E00088828340828201C0048905C005A0A1822B ++:1039F00000830501038283C004C101000882838221 ++:103A0000A0C083C182820102024105C005A00282DA ++:103A100000830300038283C004C101000000000092 ++:103A20000000000000000000000000000000000096 ++:103A30000000000000000000000000000000000086 ++:103A40000000000000000000000000000000000076 ++:103A500000000000000000000000000000008200E4 ++:103A600008820083C082828211820082C190088312 ++:103A700083820083C10083A085820083014082008D ++:103A8000848200830883828205820082C140088389 ++:103A900083820083100083A08582008301400000A0 ++:103AA0000000000000000000000000000000000016 ++:103AB0000000000000000000000000000000000006 ++:103AC00000000000000000000000000000000000F6 ++:103AD00000000000000000000000000000000000E6 ++:103AE00000008080008388800080848000808309BB ++:103AF000828304C10083C100028502C1008341802A ++:103B0000000000800083C1C00080048000808380AA ++:103B1000828304C100839100028502C10083418039 ++:103B20000000000000000000000000000000000095 ++:103B30000000000000000000000000000000000085 ++:103B40000000000000000000000000000000000075 ++:103B50000000000000000000000000000000000065 ++:103B600000000002000083A182C10000080083C0A1 ++:103B700040C1004100008302000000200080C0A17D ++:103B80008000000200008302408800000000838261 ++:103B90000908004100008302000000200000C0026C ++:103BA0000000000000000000000000000000000015 ++:103BB0000000000000000000000000000000000005 ++:103BC00000000000000000000000000000000000F5 ++:103BD00000000000000000000000000000000000E5 ++:103BE000000000000001008283A183040000018224 ++:103BF000830901C10082008283830400008300C026 ++:103C000083A18200000100848383010400000082FC ++:103C10008309A0080082008283830200008300845D ++:103C2000838300000000000000000000000000008E ++:103C30000000000000000000000000000000000084 ++:103C40000000000000000000000000000000000074 ++:103C50000000000000000000000000000000000064 ++:103C60000000000000008309000889C10883830860 ++:103C700000838282A0888383010101830000C00346 ++:103C800001030100A0C18383004005C0088383A015 ++:103C90000101A0839003838301010183000010824E ++:103CA00001030101A0C100000000000000000000AD ++:103CB0000000000000000000000000000000000004 ++:103CC00000000000000000000000000000000000F4 ++:103CD00000000000000000000000000000000000E4 ++:103CE0000000000000000000028309802182009093 ++:103CF000020011831184000402C04103028300000A ++:103D0000C1104104210400C00283418002C180A08F ++:103D10000200400384A000C002C0410302830000EF ++:103D2000C1890420022000C0000000000000000043 ++:103D30000000000000000000000000000000000083 ++:103D40000000000000000000000000000000000073 ++:103D50000000000000000000000000000000000063 ++:103D60000000000000000000000000000000000053 ++:103D700012422148000B020012428148000B02004F ++:103D8000124200000000000012420000000000008B ++:103D900012422148000B010012428148000B020030 ++:103DA000124200000000000012420000000000006B ++:103DB0000000000000000000000000000000000003 ++:103DC00000000000000000000000000000000000F3 ++:103DD00000000000000000000000000000000000E3 ++:103DE000000000000000000000000000FFFFFFFFD7 ++:103DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3 ++:103E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:103E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:103E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:103E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:103E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 ++:103E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 ++:103E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00E878 ++:103E700064CC0C44002000E80A060000C832AEDE24 ++:103E80000000000000000000000000000000000032 ++:103E90000000000000000000000000007B75AEDEA6 ++:103EA0000000000000000000000000000000000012 ++:103EB0000000000000000000000000007B75000012 ++:103EC00000000000000000000000000000000000F2 ++:103ED00000000000000000000000000000000000E2 ++:103EE00000000000000000000000000000000000D2 ++:103EF00000000000000000000000000000000000C2 ++:103F00000678C000000000000000008C07000000E0 ++:103F100000000000300000000000000000031E60F0 ++:103F20000678C000000000000000008C07000000C0 ++:103F300000000000300000000000000000031E60D0 ++:103F40000000000000000000000000000000000071 ++:103F50000000000000000000000000000000000061 ++:103F60000000000000000000000000000000000051 ++:103F70000000000000000000000000000000000041 ++:103F80000000000080100090882000004000000029 ++:103F900000000000000091000301000000C00200CA ++:103FA00020C1840004000420040000000000800000 ++:103FB0000090000000000000000000000000000071 ++:103FC00004000000000000000000000000000000ED ++:103FD00000000000000000000000000000000010D1 ++:103FE00000000000000000000000000000000000D1 ++:103FF00000000000000000000000000000000000C1 ++:10400000000000000000080000000980100001000E ++:104010000000000000000000400000080000000058 ++:1040200000000002210001000180010008000000E2 ++:10403000040000000000000000000000000000007C ++:104040000000000000C000000000000000000000B0 ++:104050000000000000000000000000000000000060 ++:1040600000800000000000000000000000000000D0 ++:104070000000000000000000000000000000000040 ++:10408000000000000000000000000000002000A070 ++:104090000020000180010004400100000001000038 ++:1040A000000000000000000400010082000800047D ++:1040B00000000400000000200000000400040000D4 ++:1040C000000020000000004000000004100000007C ++:1040D00020000000000000000000000000000000C0 ++:1040E0000000000000000000000000000000400090 ++:1040F00000000000000000000000000000000000C0 ++:10410000000000000000020000000021002100204B ++:10411000A00000A100200220000001020000000415 ++:1041200000000000000000000080002000000000EF ++:1041300000000000010000000080000000800080FE ++:10414000000000000100000000800000008004006A ++:10415000000001000000000000000000000000005E ++:10416000000000000000000000000000000000004F ++:10417000000000000000000000000000000000003F ++:1041800000000000000000000100000100012121EA ++:10419000110240012001000120000001404003A164 ++:1041A00000A00020002011000020000100000040BD ++:1041B00000090008009000000083000000000000DB ++:1041C000800100000000000000000000000000006E ++:1041D00000000000000000000000000000200000BF ++:1041E000001000000000000080002100000000001E ++:1041F000000021000000000000000000000000009E ++:10420000000000000000000000000000000884081A ++:1042100084888280C02010048408102100020100DC ++:10422000C0088200008000800000C0850020C0001F ++:104230000080C0A00080000000000002000000001C ++:104240001000040800000000000000000000000052 ++:1042500000000000000000000000000000000080DE ++:1042600000000080000000000000080000000000C6 ++:1042700082000000000000000000000000000000BC ++:1042800000000000000000000000000000000540E9 ++:104290000000050111001190410004001000100001 ++:1042A000050020004000110400000001A1200000D2 ++:1042B0000088000000000201000000000000000172 ++:1042C00080012000200005000000100000200000F8 ++:1042D0008804C000C100410041002100000000002E ++:1042E00000018021800100010000000080004000EA ++:1042F00000000000000005000000000000000000B9 ++:1043000000000000000000000000000000000000AD ++:1043100000008810000404000000100000000305E5 ++:1043200001000000000001400091000000204089D1 ++:10433000000000000000000000020000002000005B ++:10434000000420040100050000000000000000003F ++:1043500000000980090004000000000000000000C7 ++:1043600000000004048208040004000000000200B1 ++:10437000000000000000000000000000000000003D ++:10438000000000000000000000000000000000002D ++:1043900000008002C100801100040382800110052A ++:1043A0002000800580000200100900000020218804 ++:1043B000218820C0000003000088000000000000E9 ++:1043C000000800000000040021010000400100007E ++:1043D000000000001000080010001000050440005C ++:1043E00000000420000000880010211000000000E0 ++:1043F000111021000000000000000000000000007B ++:1044000000000000000000000000000000000000AC ++:104410000000000004800400048290A10004400811 ++:1044200084881021108240001100A1A000000080AB ++:1044300000000000C100C000C0001000000010001B ++:10444000840084800000000001001008C0110108F1 ++:1044500000000000000000000100000000000080DB ++:1044600001000000018000000000008000800000CA ++:10447000A00090800000000000000000000000008C ++:10448000000000000000000000000000000000002C ++:10449000000000000000000400041090009000A044 ++:1044A000100400000902110402040200C1020020ED ++:1044B0000900092002200440030041004140008817 ++:1044C00000200082000420000040008204880000D8 ++:1044D000000000908000000040001000002000015B ++:1044E000200221014000C000802180218020802105 ++:1044F0000000000180019001800000900001800117 ++:1045000000000000000000000000000000000000AB ++:104510000000000000000000000000800000040017 ++:10452000000005040011008000000080042110A19B ++:10453000008000000080A080A18000008200008038 ++:1045400000000000000000800100000000000000EA ++:10455000000004000000042000001141004100851B ++:10456000002083A184400100094120A020842080F4 ++:1045700008840000000420100804042090000410A7 ++:104580002010000000000000C0000000000000003B ++:1045900000000000000000000000C183040302804E ++:1045A00002404021084184089102C102040900052B ++:1045B00000080388418404020405038040008280CF ++:1045C00041802000050011000200000000000000F2 ++:1045D00000000000000000000300000000030000D5 ++:1045E00088000000400010201100000080831104AA ++:1045F0004000410083820409092111918080050057 ++:10460000800000000000000000000000000000002A ++:10461000000000000000000000000000918305047D ++:10462000000809A000011100820040009101010072 ++:1046300000000001910904C1000400119008C1C0EC ++:10464000418401080000000000000000000000009C ++:104650000000000000000000000001000000000158 ++:10466000880011000000C1008501000090009083C7 ++:10467000850205C0011089830091008301C18882F1 ++:104680000184C004000000000000000000000000E1 ++:104690000000000000000000000000000000089082 ++:1046A00004A1089000830188000000880001080030 ++:1046B00005A01010410140A0C1C010411000080227 ++:1046C000A104C1020800A1000190890010000002AD ++:1046D00000010020000100000000000000000000B8 ++:1046E000C000820190888300C00010911000C08536 ++:1046F000C1018301C090831101018900A0089101CB ++:104700000001000000000090000000000000000018 ++:104710000100000000040002000000000000000092 ++:104720008009008280C000C1210008091000020930 ++:104730008200C080800503410400A00284050404B7 ++:10474000898040001084040041002000C141822182 ++:104750000080000300800003000000000000000053 ++:10476000000000000003800083000000800880003B ++:104770008083092020210080830208098402898027 ++:1047800089090009000000000090000000000000FE ++:104790000000020000000000000000000000000017 ++:1047A000000010888308A180888308C1031141821A ++:1047B0008321210800030409100302020891051057 ++:1047C000051000890240A1110020000200412104CF ++:1047D0008084000003000400800000020004030243 ++:1047E0000003008080400080000089838840000032 ++:1047F0000880808082040080030289830202808412 ++:104800009189A180000000008000000000000000ED ++:104810000000000000000000000000000000000098 ++:1048200000000000850882C1110890830005018402 ++:104830000008C101010000000000A10189408810AA ++:10484000A11009050008C1C104A090090004008559 ++:1048500000C082880400000001000400C0010001C3 ++:104860000101A0010080089000C0000891838389A5 ++:104870000090010808C090A010C0C11091830101F0 ++:1048800088C0A1058982000000009000000000009F ++:104890000000000000000000000000000000000018 ++:1048A000000000000000830509028208C082004069 ++:1048B0000090001000000111010901000108010130 ++:1048C0000004000000A0010501000001000201A099 ++:1048D0000001000001880000008800000000008244 ++:1048E0000000000500000080019101080000001098 ++:1048F00083098411850188088391C182A000A004E6 ++:1049000082058801828988A082000400900000004E ++:104910000000000000000000000000000000000097 ++:1049200000000000000000008303A1004000808020 ++:1049300000800040009100411008044010114180A7 ++:10494000050302110910110009C010211002058091 ++:1049500040000403040410800000008000000000F8 ++:104960000080000000100000008003880400004068 ++:104970000080838802C0C010008083A004800902E8 ++:1049800002008002800900A1808080000000800079 ++:104990000000000000000000000000000000000017 ++:1049A000000000000000000000000000000B2000DC ++:1049B000816000000022480011410000000B44000B ++:1049C000000000000042020081000041000BD00006 ++:1049D00000002100000BC100425000000083D00005 ++:1049E0008148000000830200124200000000000B1A ++:1049F000C2000A000000000BD00041480000000B7C ++:104A0000D00082880000001002001100060082130E ++:104A10000200000000000000000000000000000094 ++:104A20000000000000000000000000000F0F0F66F3 ++:104A30002D2D3C3C000000007E42CFCFFF66990048 ++:104A40003C0F2D2DFF6C0F6CF0F00000F0F0C0005B ++:104A5000C000C00000F030060000000F00000000A1 ++:104A60000000000000000000000000000000FF0047 ++:104A700000003C3C0000F0F0FF005A5A5A5AC33C78 ++:104A80000F0F00FF3C3C00000000F000F0000000B1 ++:104A90000000000000000000000000000000000016 ++:104AA000000000000000000000000000000066663A ++:104AB0000F662D2D0F0F000000007E420C0C1E1EF5 ++:104AC0001E1E3C0F2D2DF06C006CF0F80008F0F06D ++:104AD00050003232020200003006003C6600000046 ++:104AE00000000000000000000000000000000000C6 ++:104AF000FF0000003C3C00000F0FFF005A5A5A5ABA ++:104B0000C33C0F0FFF003C3C00000000D020D02031 ++:104B10000000000000000000000000000000000095 ++:104B20000000000000000000000000000000000085 ++:104B30000000000000000000000000000000000075 ++:104B40000000000000000000000000000000000065 ++:104B50000000000000000000000000000000000055 ++:104B600000000000000000000000000000218000A4 ++:104B70000000000000000000000000000000000035 ++:104B80000000000000000000000000000000000025 ++:104B90000000000000000000000000000000000015 ++:104BA0000000000000000000000000000000000005 ++:104BB00000003C3C663C00000000BDBD90F6424257 ++:104BC0007E7E30303F3FFCFC7E7EF6F6303F18188C ++:104BD00018180000000004C40303000000000C0CBF ++:104BE0000000000000000000000000000000FFFFC7 ++:104BF000FFFF0000000066660000FFFFFF00FF00EF ++:104C000099999999FFFF66993C3C0F0F40BF0000AE ++:104C10002000DF0000000000000000000000000095 ++:104C20000000000000000000000000000000000084 ++:104C3000000000006666663C00000000242490F638 ++:104C400030F330F3606F606F0C0C18180606303FBD ++:104C5000781818180000000004C4000000000000CC ++:104C60006060000F00000000000000000000000075 ++:104C7000000000000000000066660000000000FF69 ++:104C800000FF66666666000066993C3CF0F000FF37 ++:104C900000000000FF000000000000000000000015 ++:104CA0000000000000000000000000000000000004 ++:104CB00000000000000005805A01A00900050086E0 ++:104CC000026100B000800186026100B900A5A086E3 ++:104CD0000C6100B00000008E006500B0000000868E ++:104CE000026101880005A0865060A8B0000500861A ++:104CF000006108B008400000A24751F00804494094 ++:104D00001286016108B40840120021904004004856 ++:104D1000008400000090000000A000C001B0000569 ++:104D2000000000000000000000000000090000007A ++:104D30000000001000000000010040000000020020 ++:104D400000000000FF7FFF7F000000000000000067 ++:104D5000000000003A303030000000000000C0C009 ++:104D6000000000003CFFFDFF00000000000000000C ++:104D70000000000000000000000000000000000033 ++:104D800000003CFFF3C0BF0E2F0800000000280009 ++:104D90000800030CD7FFAA00A0A0FF5F005F00007F ++:104DA00000000000000000000000000000200000E3 ++:104DB00001000000000000000000000000000001F1 ++:104DC0000000000000000040004000000000000063 ++:104DD00000000000000030303030000000000131E1 ++:104DE0000131000000003CFFFDFF0000000000005A ++:104DF00000000000000000000000000000000000B3 ++:104E000014000500003CF3C03F0C0F0000A0002878 ++:104E100000000800030CD7FFAA00A0A0FFFF00A01D ++:104E20000000000000000000000000000040000042 ++:104E30000000020000000000000000000000000070 ++:104E40000100010000000000000000000000000060 ++:104E50000000AAAA0003AAAA3C003C00C0C0C0D41B ++:104E60000000C3000000000014D700FF0000000095 ++:104E70000000000000000000000000000000000032 ++:104E8000000000000000000000000F4F00010202BF ++:104E900002000A00280042424380FFFAFFFF000F91 ++:104EA0000000000000000000000000000000000002 ++:104EB00000000000000000000000000000022000D0 ++:104EC00000080000000000000000000000000000DA ++:104ED00000000100ABAA0000AAAA3C503C00C0C0E0 ++:104EE000C0C00C410C410000000014D700FF0000BE ++:104EF00000000000000000000000000000000000B2 ++:104F000000000000000A0808000000004FFF010F29 ++:104F10000000020000000000C0C0C300FFFFFFFF50 ++:104F20000F000F0F00000000000000000000000054 ++:104F30000000000000000000000000000000000071 ++:104F40000084000404000000000000200020200075 ++:104F500000002100000204200000000040000000CA ++:104F6000000000000400000000010000002080009C ++:104F70000000000000000400800000000400200089 ++:104F8000000000001100040000000000000000000C ++:104F90000000000000000000000000000000000011 ++:104FA0000000000000000001000000000000000000 ++:104FB00000000000000000000000000000000000F1 ++:104FC00000008200008000000000000000800080DF ++:104FD0000000000000000080209000000021000080 ++:104FE0000000000000000000000000200000008021 ++:104FF00020000000000000008500200000000000EC ++:10500000010000C0000000000000000000000000DF ++:105010000000000000000000000000000000000090 ++:105020000000000000000000004000000000000040 ++:105030000000000000000000000000000000000070 ++:10504000000000000000000100000000000000005F ++:1050500000400000000000010089009000000000F6 ++:1050600000000000000000000004000100900000AB ++:10507000000000000000000000000003000000002D ++:105080002000000000800000000000000000000080 ++:10509000000100000001000000000000000000000E ++:1050A00000000000000000000400000200000000FA ++:1050B00000000000000000000000000000000000F0 ++:1050C000000000000000000000100021401100005E ++:1050D00000000000000800000004000400100000B0 ++:1050E00000000000400000000000008002200200DC ++:1050F000001100000010000000100000002000104F ++:10510000000001000000008000000000000000001E ++:10511000000000200000002000000002000000004D ++:1051200000020000000000000000000000800000FD ++:10513000000000000000000000000000000000006F ++:105140000000000000000000410000840000021088 ++:10515000020010000004041090002084A0208000B1 ++:105160008410080000A000000000002000000000E3 ++:1051700000200010090000000000000000000000F6 ++:105180000000000000000000000000008000008817 ++:105190000020008400840000000000008000000067 ++:1051A00000200010002000000500080000000000A2 ++:1051B00020000000000000000000000000000000CF ++:1051C0000000000000000000000000090000C00016 ++:1051D00001000105000088111140032185050380AD ++:1051E00002004110112010008400A00000A1C000A6 ++:1051F000A021888000800008100800000000000046 ++:10520000100000000000000000000000000040004E ++:10521000000000808400C0208240C0009000200078 ++:1052200000001080008000801000100001000000CD ++:1052300000000100000000008400000000000000E9 ++:1052400000000000000000000000000000000085D9 ++:1052500000000000000000100000008800000900AD ++:1052600002820000000080200020002000000020BA ++:10527000008380000000000000000000000010001B ++:1052800000000000009002000490054000001100A2 ++:1052900000000000000102902020410000200000DA ++:1052A000000400000020000000000000000000904A ++:1052B00000000000000000000000000000000000EE ++:1052C00000020000000000000000000000000000DC ++:1052D0000010840000000011000000000000000029 ++:1052E00000100111004000000480008000800000D8 ++:1052F00000801020200000000010000000000000CE ++:10530000000000000000000000000100000000009C ++:1053100000009000900088080000018000000080DC ++:10532000001100800000008000000000000000006C ++:10533000000000000000000000000000000000006D ++:10534000000000000000000000000000000000005D ++:10535000000020008000820110000000000021A059 ++:1053600000000004000180000084800800000200AA ++:1053700009000000000000200000000000011000F3 ++:1053800000000000000004A000000001000009006F ++:10539000000000000000000010858000C001208394 ++:1053A00041890000030000001001000000004120BE ++:1053B000050800C00000020000000000030000001B ++:1053C00000040000000000000000000000000000D9 ++:1053D00000000000110010000520884010000005AA ++:1053E00000030400048000400210002140008420DB ++:1053F0000200000000008203A088000000000020DE ++:1054000084210000000000000100000000040000F2 ++:10541000000000000041000000009108200021046D ++:1054200085040004000084008400840800008400D7 ++:10543000008000800000000001000000000000006B ++:1054400000000080000000000000000000000000DC ++:1054500000000000400000841040000800400200EE ++:1054600000000088000000004000020420C000840A ++:105470002090A000000841000020029000000820B9 ++:1054800000000020000000000001848500000000F2 ++:1054900000000004000011000000110000848000E2 ++:1054A00002820200200000002002099010900000FB ++:1054B00000C00000000000001000104000000000CC ++:1054C000000000008020000000000000000000003C ++:1054D00000000000000001000000C100000000808A ++:1054E00010001005001000000000011101800100F3 ++:1054F000000001002000008000000080000000008B ++:105500000080000000800000000000040304000090 ++:10551000000000000080000000000000000000000B ++:1055200020000000000001000000018000001000C9 ++:10553000000000000000000000000000000000006B ++:1055400000000000000020800000000000000000BB ++:105550000000000000000000041002022105900578 ++:1055600000800080200000000000C19011000000B9 ++:1055700091911184410909410000000000000000E0 ++:105580008080910002000000000000000000000088 ++:105590000040094000411010000000000000000021 ++:1055A000000080000980410000004010050000005C ++:1055B000410000008000030000000000A100410045 ++:1055C00000000000200000000000000000000000BB ++:1055D00000000000000000000000000100010100C8 ++:1055E0001101000400A0010000880820842100901F ++:1055F000000889828511018301010000000000007C ++:105600000000888291A001820000000000000000DC ++:105610000000000001000001010100000000000086 ++:105620000000000040A085020020002001000100D1 ++:105630000000010000000400000000000000020063 ++:105640000100000000000100000000000000000058 ++:10565000000000000000000000000000000000004A ++:1056600000840000A0018200C0884000080002C041 ++:10567000820090C1880183C01088C1C1000000046D ++:1056800000A000008801A0008888C0C100000000C0 ++:1056900000000000040002888900410100000000B1 ++:1056A00001000000010088000000020003900200D9 ++:1056B0000500A10003028301A000918882850800F3 ++:1056C000050205A0830100000000000001000000A9 ++:1056D00000000000000000000000000000000000CA ++:1056E0000000008000210020000000808000800475 ++:1056F00085800000800989024180809183890000B3 ++:1057000000800002001180020000808080C0000044 ++:105710000000000000108000C000A10090090000FF ++:105720000000080003000300034111118300C105BC ++:10573000090288008500A08540020200208084853F ++:105740008000118089848910000000000000090099 ++:105750000000000000000000000000000000000049 ++:10576000004000822104C088808000000380808087 ++:105770000080000888000080038980850089C1833B ++:105780000000040004008000000000000080808011 ++:1057900000000000400000800040004000090808B0 ++:1057A0000000000000000000800080000080908069 ++:1057B00000800040000220050005008000000080FD ++:1057C00000800080008000808080000000000000D9 ++:1057D00000000000000000000000000000000000C9 ++:1057E00000000089004100854182A08400C000A023 ++:1057F000884000028209852000080108909100A1DC ++:1058000089830000010000000400008800A082A03D ++:1058100088820000000000000088000000000001F5 ++:10582000080000000000000000000400022000103A ++:10583000058420100001000101008800000200A082 ++:10584000000400020088000400A08882000000001C ++:105850000000C00000000000000000000000000088 ++:105860000000000000000000000000008401C0886B ++:10587000C00040008300C000040004021101119127 ++:10588000910189C000A001100000010088898800F2 ++:1058900090008888000000A000000000008900003F ++:1058A000010100000000000000C100000000848928 ++:1058B00010914001042002050201820102029001C0 ++:1058C00088A09000C08201110100000100040000C6 ++:1058D00000000000000000000000000000000000C8 ++:1058E0000000000000000000000000000011800522 ++:1058F000008080008000831104000900218089035A ++:105900008585894190802000400004002000000827 ++:1059100080008000808000000000000000004083C4 ++:1059200040400221080000000000001000030000B9 ++:1059300080A08041800280008082802000050000DD ++:105940008011804100418080034004000521030054 ++:105950000000000000000000000000000000000047 ++:1059600000000000000000000000000B48000000E4 ++:10597000000000220000000000000080480000003D ++:1059800000000083C10021000000000BC2000000E5 ++:1059900000000008C200000000000010C20000006B ++:1059A0000000008302000A0000000000000BD0008D ++:1059B00000000000000BD0000000000000102000DC ++:1059C0000000000000100000008200000010020033 ++:1059D00000000000008048000000000000000000FF ++:1059E00000000000000000000000000000000804AB ++:1059F000DFEF00000000000000003F3F3CFFF0F040 ++:105A0000F0F00008AAA2424201C20000FF0000001C ++:105A10000000000000000000000000000000000086 ++:105A200000000F0F0F0000CF00CF000000000000AB ++:105A30000000000000000000000000000000000066 ++:105A4000FFFFFFFF00000000000000000055F3F31F ++:105A50000000000000000000000000000000000046 ++:105A60000000000000000000000000000000000036 ++:105A70000000FFFF000000000000000030303C008C ++:105A8000F0F0F0F00000AAAA414100C30020FF207E ++:105A90000000000000000000000000000000000006 ++:105AA000000000000F0F0F3C00CF30FF000000008F ++:105AB00000000000000000000000000000000000E6 ++:105AC00000005FDF55D70000000000000000005517 ++:105AD000FFFF0000000000000000000000000000C8 ++:105AE0000000000000000000000000000000BA8A72 ++:105AF000AAAA00000000000000000000000000FF53 ++:105B000000FF0F0F0F0F20000000424200000000B6 ++:105B10000000000000000000000000000000000085 ++:105B2000000000000000F0F082F0FA00FF05000025 ++:105B300000000000F0FF000A000000005500F5F032 ++:105B40000000FFFF3C3C3C3C00000000507C507CCF ++:105B50000000000000FF000F000000000000FFFF39 ++:105B60000000000000000000000000000000000035 ++:105B7000BA8AAAAA0000000000000000000000008D ++:105B800000FF00FF0F0F0F0F000000004242C3C3D1 ++:105B90000000000000000000000000000000000005 ++:105BA0000000000000000000F0F082F0FA00FA00AF ++:105BB000000000000000F0F00000000000007D3C4C ++:105BC000FDFC0000FFFF3C343C3800000000FFFFFC ++:105BD000507C0000000000FF0000000000000000FA ++:105BE000FFFF0000000000000000000000000000B7 ++:105BF00000000086006008B80000008600210080D8 ++:105C00000000058600600880000000860001080290 ++:105C1000001000860071A8B0000500860000080092 ++:105C2000000500860070A89000050086006000A0B6 ++:105C3000000000000086007100B00010A086503007 ++:105C4000A09000850086006108B00080000600205A ++:105C500000A0000005060061001000000086006042 ++:105C600000B0000000000000000000000000000084 ++:105C700000000000000000005C5C553CF0E8F0F023 ++:105C800010DF00FFFF0000FF50503C0000F700084D ++:105C9000424201C200000000000000000000F708BE ++:105CA000C2C201C200000000FFFF000000000000AF ++:105CB00000000000000000000000000000007F0065 ++:105CC0001F0007070107D3FFD3D300000000C1AABC ++:105CD000C300000010000000000000FF24240000AA ++:105CE00000000000000000000000000000000000B4 ++:105CF000000000000000000000005C5C553CF0E883 ++:105D0000F0F010DF00FFFB0044FF0000000000FF88 ++:105D10000000414100C3000000000000000000003E ++:105D2000FF00010100C300000000FFFF00000000B1 ++:105D30000000000000000000000000000000000063 ++:105D40000D0004000107010150FF50500000000049 ++:105D5000C100C300000000000000000000FF0000C0 ++:105D60000000000000000000000000000000000033 ++:105D70000000000000000000000000000000000023 ++:105D80003CFF3C000F3C0F0F03000300505000008D ++:105D9000005A5F5F0F001B000000000000000000C1 ++:105DA00000000FFF000000000000000000000000E5 ++:105DB0000000000030FF00CF0000000000000000E5 ++:105DC000000030F0FCFFC3EBEBFF00000000757536 ++:105DD000303000000000C0F0417100000000003CC5 ++:105DE000F5F50000000000000000000000000000C9 ++:105DF00000000000000000000000000000000000A3 ++:105E000000003CFF3C000F0F0F0F8C8C80803C008B ++:105E10000000005A5F5F0F000F000000000000004C ++:105E200000000FF00FFF00FF04FB00000000000067 ++:105E300000000000000000CF00CF000000000000C4 ++:105E4000000000000030F0FC008282C3000000006F ++:105E500075FF30FF000000001414417100000000C5 ++:105E6000003C0505000000000000000000000000EC ++:105E70000000000000000000000000000200000020 ++:105E800000002000000020000000000000000000D2 ++:105E900000000020000000000000000000000000E2 ++:105EA00003000000000004000000400000000000AB ++:105EB00000000000000000000000000000000000E2 ++:105EC00000000000000000000000000000000000D2 ++:105ED00000000000000000000000000000000000C2 ++:105EE00000000000000000000000000000000000B2 ++:105EF00000000000000000000000000000000000A2 ++:105F000000000000000000000000904000000000C1 ++:105F10000000000000000000000000000000000081 ++:105F20000000000000000000000000000000000071 ++:105F30000000000000000000000000000020000041 ++:105F40000000000000000000000000000000000051 ++:105F50000000000000000000000000000000000041 ++:105F60000000000000000000000000000000000031 ++:105F70000000000000000000000000000000000021 ++:105F80000000000000000000000000000000000011 ++:105F90000000000000000000000000000000000001 ++:105FA000000000820000000000000000000000006F ++:105FB00000000000000000000000000000000000E1 ++:105FC00000000000000000000000000000000000D1 ++:105FD00000000000000000000000000000000000C1 ++:105FE00000000000000000000000000000000000B1 ++:105FF00000000000000000000000000000000000A1 ++:10600000000000110000000000210000001100212C ++:1060100000200041004100080008000300000011BA ++:10602000000900000011000000000000000000094D ++:106030000020000000000000000000000000000040 ++:106040000000000000000000000000000000000050 ++:106050000000000000000000000000000000000040 ++:106060000000000000000000000000000000000030 ++:106070000000000000000000000000000000000020 ++:106080000000000000000000000000000000100000 ++:1060900004880000000004000400008800000000E4 ++:1060A000004002020000000000001000000000009C ++:1060B00000000000004000000000000000000000A0 ++:1060C00000000000000000000000000000000000D0 ++:1060D00000000000000000000000050002000000B9 ++:1060E000000000000000000000000000210000008F ++:1060F00000000000000000000000000000000000A0 ++:106100000000000000000000001000004021C0005E ++:1061100000001000100510400000000000090808F1 ++:106120000011A0200200000000000000000000009C ++:10613000000000000000000000000000000000005F ++:10614000000000000000000000000000000000024D ++:10615000000000000000000000000000002084009B ++:106160000000C000880000004000000000000000A7 ++:10617000000000000000000000000000000000001F ++:1061800000000000000000000040001000A000001F ++:1061900000000000200000000000000000000000DF ++:1061A000000000000082212010000000000000001C ++:1061B00000000000000000000000000000000000DF ++:1061C00000000000000000000000000000000000CF ++:1061D000000000001000000010000000000000900F ++:1061E00000000000000000000000000000000000AF ++:1061F000000000000000000000000000000000009F ++:1062000000000000000000000000040088002000E2 ++:1062100008009000000402040009000000000000D3 ++:106220009002000400000000002108000000A00807 ++:106230000800000000000000020000000000000054 ++:10624000900000000000A00000000000000000001E ++:10625000000000000000000000000000000000003E ++:10626000000400000000000000000000000000002A ++:10627000000000000000000000000000000000001E ++:10628000000000000000000000000000000000000E ++:1062900000000000000000001000000000000000EE ++:1062A00000000000000000000000000000000000EE ++:1062B00000000000000000000000000000000000DE ++:1062C00000000000000000000000000000000000CE ++:1062D00000000000000000000000000000000000BE ++:1062E00000000000000000000000000000000000AE ++:1062F000000000000000000000000000000000009E ++:106300000000000000000000000000000000100875 ++:106310000000000000000000000000030003000077 ++:10632000002002000409001100210011880000086B ++:106330000000000000090000000000210000000033 ++:10634000000000000000000000000000000300004A ++:1063500000000000100000000003002100110000F8 ++:10636000000000000000020000000000000000002B ++:106370000000000000008400000000000000000099 ++:10638000000000000000000000000000000000000D ++:106390000000100000000000000000000010008459 ++:1063A000000000000000000000000000009000005D ++:1063B0000000004000000008000000000000000095 ++:1063C000000000000090000000000000000000003D ++:1063D00000000000000000000000000000000200BB ++:1063E0000900000000200000000000000000000084 ++:1063F000410000000000000000000000000000005C ++:10640000000000000000000000000000000000008C ++:106410000000000002108440840004118411020076 ++:106420000810000882000021000010000000C000D9 ++:106430002004A00500000000000000000000004053 ++:10644000C000C009000800000000000000000000BB ++:1064500004000000040000001000000000000040E4 ++:10646000A04002000000000000000000000000004A ++:10647000000000000000000000000000000000001C ++:106480008800000000000000000000000000000084 ++:1064900000000000FFFFFFFFFFFFFFFFFFFFFFFF08 ++:1064A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC ++:1064B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC ++:1064C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC ++:1064D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC ++:1064E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC ++:1064F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC ++:10650000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B ++:10651000FFFFFFFFFFFF00A8BE430C440010000078 ++:106520000A0600006018000000000400044040005B ++:1065300000000400000404000000200080000800A7 ++:1065400080001100000000000000000004000000B6 ++:106550000000000000000401000000000000000036 ++:1065600000000000200000C000000000000000004B ++:10657000000000000000000000000000000000001B ++:10658000000000000000000000000000000000000B ++:1065900000000000000000000000000000000000FB ++:1065A000000000000000000000000000000000806B ++:1065B0000100000001000080000000000100040054 ++:1065C00005000800000000100000000000000000AE ++:1065D00000000000000000000004000000000000B7 ++:1065E000000000000000010000C0000000000000EA ++:1065F000000000000000000000000000000000009B ++:10660000000000000000000000000000000000008A ++:10661000000000000000000000000000000000007A ++:10662000000000000000000000000000000000006A ++:10663000000000014001000900010000000080206E ++:106640000000000000000001202080000000000089 ++:106650000000000000000000000400000000000036 ++:106660000000000100000000802100C000C0000008 ++:106670000000000200010000000000000001000115 ++:1066800000001100000000000000000020000000D9 ++:1066900000000000000000000000000000000000FA ++:1066A00000000000000000000000000000410000A9 ++:1066B000000800080420012000A0000800000000DD ++:1066C0000288000002000000000401101000000019 ++:1066D0000003000000100000040000800000000023 ++:1066E000004100000004000000000484008000005D ++:1066F0000000000000800002000000000000000414 ++:106700000004000000000000000000000000010381 ++:106710000000000000000000000000000000000079 ++:1067200000000000000000000000000000000090D9 ++:1067300000000011009100C00000000400000000F3 ++:1067400000000000850880090001048309020000A0 ++:1067500000000301000800880000000000040000A1 ++:1067600000008000058400C00004000000840000D8 ++:106770000000000080000020000000000800002051 ++:106780000400000000000000000000000000000005 ++:1067900000002100000000000010000000000000C8 ++:1067A00000000000000000000000000000000000E9 ++:1067B00000000000004000200000000000800000F9 ++:1067C000000000218400208020200020852000007F ++:1067D0000000000000020000000000000000008037 ++:1067E0000000000004000000002100800000000004 ++:1067F0000000000000000800008000000000010010 ++:106800000080010000000000000000000000000007 ++:1068100010000000000000000000008000000000E8 ++:106820000000000000000000000000000000000068 ++:1068300000000000800010008000020104008800B9 ++:106840008000050000000200200002008000090016 ++:1068500005010000030000000400410000000401E5 ++:106860000000804041009001050000000000009001 ++:106870000000000000000000000010000800000000 ++:1068800000000000210004200000410000840000FE ++:106890000000000080000000000000000000000078 ++:1068A00000010001000000200000000000000000C6 ++:1068B0000000000000114004000440052104010014 ++:1068C000090004008840A009041082009100020021 ++:1068D00084000010080000201000830000410041E7 ++:1068E0000140C000208000000840001100040000AA ++:1068F000000000000000000000000000C000400098 ++:10690000A0009000080000000021840000000000AA ++:1069100084000000000020008200820000000000CF ++:10692000000000040004000000000000000000005F ++:10693000000000000000110010000200050010001F ++:106940000000800000000582100002000884088416 ++:1069500011010801828408000000100008041000E2 ++:10696000000021000440004000100088004010009A ++:106970000000410000000000028800000000000448 ++:106980000800000021000300210004000000410075 ++:1069900005A00400030005004100044009000900AF ++:1069A00000000000000000000000000000000000E7 ++:1069B00000000000000000000000000000000400D3 ++:1069C00001000000100000000000000000000000B6 ++:1069D000000000040120051000000000000000007D ++:1069E000010000000000C1800000000000000080E5 ++:1069F0000000000000000000004001000000000056 ++:106A000000800000000000000009000001000000FC ++:106A10000000000001000011000000000100000063 ++:106A20000000000000000000000000000000000066 ++:106A300000000000000000000000080009000388BA ++:106A4000110004000004840004000082900005107E ++:106A500005830800002000410085050000000000BB ++:106A600000000800008490004104000000000000C5 ++:106A7000000400010000101002010000001041009D ++:106A80000500410000000090102005009000040067 ++:106A90000000030041A005A000C00300000400A006 ++:106AA0000000000000000090000000000000000056 ++:106AB00000000000000000000000000002000000D4 ++:106AC0001009020089102080030421000041404188 ++:106AD000C02110409110888010A0022000410000C9 ++:106AE000C000A0081040000010009040841000007A ++:106AF0000000820000400000008000040000000050 ++:106B00000000000000000000000001800000040000 ++:106B100000000008040000000000000000000080E9 ++:106B2000C00000008200A000000000008200000001 ++:106B300000000000000000000000000000004140D4 ++:106B400080112011101008840080002040A0000057 ++:106B50000000880000000888840902401105000038 ++:106B6000000000000000410080008500410000801E ++:106B700000001100008000A1000900210021000098 ++:106B800083910591800203111180000080000300B1 ++:106B90000203808008800000820300004080000023 ++:106BA000820300004080000091030904414109096B ++:106BB00000000000000000000000000000000000D5 ++:106BC0000101200000010000008200400089000552 ++:106BD000000004001100000002828203008300C054 ++:106BE00000000000000000000000C0009000000055 ++:106BF0000082080290000008028200850004000064 ++:106C000000009183000808A001C0018200A082A0BA ++:106C1000000005052020919000028903A0A00990A2 ++:106C200000C089A1C0C0099000A0910185010101A7 ++:106C30000101000000000000000000000000000052 ++:106C400000004000901009004100A040C0880940A9 ++:106C500003010000000008A00101C0038588042191 ++:106C6000830000000090000100000800840005403F ++:106C700091890800080002A0820000000182000043 ++:106C8000000100000000008500C1000000000000BD ++:106C90000004000090002001828803C19001A084BC ++:106CA000C088C1A090000284C0880302000008844C ++:106CB000A0018301000000000000000000000000AF ++:106CC00000000000890011808504C00000800921B7 ++:106CD00085858310090009009100052010830800B4 ++:106CE00000C189000000000000210002044089006A ++:106CF0000582091180000000800080002100418091 ++:106D000000002109000000000003008900022100AA ++:106D100000000500210080048041008003208003E2 ++:106D200000000080030080020000008003000000DB ++:106D30008000804189050000000000000000000084 ++:106D40000000000000001111000241029104030341 ++:106D50008208401021030080008020800000080489 ++:106D60002108008991C0000000002100800000116E ++:106D70000004004000090000800000800080030043 ++:106D800000000000800000000840001102092005FA ++:106D90000000801100030003000000800000C00319 ++:106DA000000000800000C003000000000000C0835D ++:106DB00040800000058911830000000000000000F1 ++:106DC00000000000000000000000002100A01020D2 ++:106DD0004100020002012001000800100184A0907F ++:106DE0000100A000048520830000000000000400D2 ++:106DF000004000880005020800C008840002A08846 ++:106E00000100880000008200000000010000010174 ++:106E10000300000008010000A001C0048890C0C069 ++:106E200089030090C09082C089A1020202A08282E0 ++:106E300089C1018800C001890191000000000000A3 ++:106E40000000000000000000000000000001000041 ++:106E50000102000501A0010101400000000800003E ++:106E60000010838402108200000201000002010071 ++:106E7000010083A08901040041100191000000007D ++:106E8000004001200100000000000000000400900C ++:106E9000000000000084008400000000900120C079 ++:106EA000020190029191A000C00190A00389C090BE ++:106EB000820190A001010182010001000000000098 ++:106EC000000000000000000000000000020441413A ++:106ED00010104000049005040240208000000009CA ++:106EE000001000808982111100101100030002803F ++:106EF000410010008308044000000880098310004E ++:106F00000200098009800405212121000000088079 ++:106F1000110041001100008000210020000000103D ++:106F200080000021890003100000002180000389F7 ++:106F3000008000218000091140800900110000003C ++:106F40000000000000000000000000000000000041 ++:106F500000800000000000000013D00006000000C8 ++:106F60000013C20000000060000BC2000A00008491 ++:106F70000013C200000000600013C2000000000007 ++:106F80000013C200060000000007C1000A820000D2 ++:106F900000000013C200824800000013D0000081EE ++:106FA00000000004C2000000000000040000060011 ++:106FB000000000048100000000840007E0001100D0 ++:106FC00000000000000000000000000000000000C1 ++:106FD0006C6C6C6C272727276666666600200000AD ++:106FE0000000000000000000FFE73C24EF2CCB086D ++:106FF0000FFF8181000000008100240004000000D8 ++:1070000000FC000C0000000003FF03000000000073 ++:1070100000003F7E0000FD9DF4940000000000FF92 ++:10702000660F3C3C3C3C66660000FFFF0000666665 ++:107030000000FFFF000066660000FBFF0400996689 ++:10704000999900000000000000000000000000000E ++:107050000000FFF00F00FF3CC300303F0CFC00209D ++:1070600000C00000000000000000FFFF0000FF0063 ++:10707000FF000F008181000000008100240000005B ++:10708000000000FC000C00000000FFFF00000000FA ++:1070900000000000034200006D0D640400000000C9 ++:1070A000000066663C3C3C3C666600000000000058 ++:1070B000666600000000000066660000FFFF00003A ++:1070C000FF006666000000000000000000000000F5 ++:1070D00000000000FFFFFFFFFFFFFFFFFFFFFFFFBC ++:1070E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 ++:1070F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 ++:10710000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F ++:10711000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10712000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F ++:10713000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F ++:10714000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F ++:10715000FFFFFFFFFFFF002C79740C4400100018A4 ++:107160000A06000094C6900090000081008183838D ++:10717000C3C3FFFF00000000000020DF00FF60F934 ++:1071800024BD3030FFFF00000000000000000000C0 ++:10719000000000E0E7070000000000000000C0C0A1 ++:1071A00000FFF1F170700000C042FC7E00000000A2 ++:1071B000000000000024003C000066660000FFFFA5 ++:1071C000000066660000FFFF00006666FFFF00002B ++:1071D000665AF0D4FFFF000000000000000000002D ++:1071E00000000000000000009000908100810889EC ++:1071F000E3E3C3C3F6F600600000000020DF0000F8 ++:1072000000FF00FF2020EFEF000000000000000062 ++:107210000000000000E0E7070000000000000000A0 ++:1072200000FF00FF707070700000000000000000A0 ++:107230000000000000004224C33C0000666600001D ++:107240000000000066660000000000006666FFFFA8 ++:10725000FFFF6666F0F0FFFF000000000000000086 ++:1072600000000000000000000000018602600090A5 ++:107270000080A0865070A8B900A5008600F1A8B0D3 ++:1072800000850086007500B000000886006500B02B ++:107290000000058600E508B00000008600E100B0AF ++:1072A00000000086006100B00000000000860CF1C4 ++:1072B000A8B80005008600E100B20080A2C6519087 ++:1072C0000884494002C7018000844940A2C7018068 ++:1072D000008441400006047C00B200000000000071 ++:1072E000000000000000000000000000000000009E ++:1072F0000500050000000000000000000000000084 ++:107300000000400000505000005500000000000048 ++:1073100000000000FFF03CAAFF00FFA300000000F7 ++:10732000FBD3FBD3000000000000000000000000C1 ++:107330000000000000000000000000000000080045 ++:107340000C00000E0000100014000000020A0000F3 ++:1073500000000000000000000000FFFFFFFF000031 ++:10736000000000000000000000000000000000001D ++:1073700000000500F5F00000000000000000000023 ++:1073800000000000000000505000000000AA0000B3 ++:1073900000000000000000F03CAAFFFFFFA3000077 ++:1073A0000000FBFBD3D30000000000000000000041 ++:1073B00000000000000000000000000000000000CD ++:1073C00000000000000000000000000000000000BD ++:1073D0002C0000000000050400000000FFFFDFFF9C ++:1073E000000000000000000000000000000000009D ++:1073F00000000000053D003C0202FF028A9ECBDF38 ++:107400000000000055FF55FF008A8A003404000088 ++:10741000000000000000000000000000FFF0FFF08E ++:10742000410014000FFF5C5C0A00A0000000000097 ++:10743000000000300C00000000000A00A000000066 ++:107440000000C00040000004000010000000000028 ++:1074500004000020000000040000000000000FFFF6 ++:107460000F0000000000000000000000000000000D ++:10747000000000000000050500000202FD00081CDD ++:10748000495D0000000055FF55FF008080000000AE ++:107490003404000000000000000000000000FFEBCA ++:1074A000FF414100140000F05C5C0A00A0000000F5 ++:1074B0000000000000300C00000000000A00A000E6 ++:1074C0000000000000000000040400005000000064 ++:1074D0000400040000A00000000C000000000000F8 ++:1074E0000F0F0F000000000000000000000000006F ++:1074F00000000000020002000210040882001000D8 ++:10750000000400008000110021048000000004003D ++:1075100000002120210000002100020300000000E3 ++:107520000000002000000000000000000000040037 ++:1075300000000488000000000000000000000000BF ++:107540000000000000040000000000000004000033 ++:107550000000000004000000000000000000000027 ++:107560000000000000820000000000000000000099 ++:107570000000000000000000000000000080400249 ++:1075800001000004000020000000000020000000B6 ++:10759000000000000080000000000000004000002B ++:1075A00000000000000000000000000000000000DB ++:1075B00000000000000000C000000000000000000B ++:1075C00000000000000000800000000000000080BB ++:1075D00000000000000000000000000000000000AB ++:1075E000000000000000000000000000000000009B ++:1075F000000000000000000080000001000000000A ++:1076000000000000004080002100400000400020F9 ++:107610000000000002000000000000000001000067 ++:107620000020000000000001000000000000000039 ++:10763000000000000002000000C000000000000286 ++:107640000000000000000000000100000000000039 ++:10765000000800000000000000000001000100011F ++:107660000003000000000000000000000000000017 ++:1076700000000000000000000000084100080000B9 ++:10768000021000100021009002100221000800A149 ++:107690000000002100000100001000000000002098 ++:1076A000002100A1040000020004000900210000E4 ++:1076B00000000000000000000010000000000000BA ++:1076C000000000000000000000000020000500098C ++:1076D00000210080000000000000001000040020D5 ++:1076E000002000200000000000000000000000005A ++:1076F00000000000000000000000000200100084F4 ++:107700000000002000C10000000100A000020008ED ++:1077100003000000008400050000828440A00000F7 ++:107720000004800000A000000020084000100000BD ++:10773000000000A000A000A0000000000000002049 ++:1077400000200000001000000000002000000000E9 ++:1077500000000000040000C0800000000000800065 ++:107760000000000400000000000100000000000014 ++:107770000000000000000000000000000000848005 ++:107780001000404000800002040000080011A080AA ++:10779000089010000000000000820000112084000A ++:1077A000C0118280040000000000008001900021D0 ++:1077B0000000100000050021000000110000000082 ++:1077C0000000020010000000200500000080000002 ++:1077D00000000000000001000000040000000000A4 ++:1077E00020000021008000000000000200000000D6 ++:1077F0000000000000000000000000000000000089 ++:1078000090000500830000001000210000010488A2 ++:1078100041C0200041000220414000000000100053 ++:1078200002001000020010000000038400000000AD ++:10783000000100000000C0000088410002000000BC ++:1078400000000000080000004100400000000000AF ++:107850000000000000000000000008000000000020 ++:107860000000030100000000800100000000000093 ++:107870000000000000000000000000000000000008 ++:1078800010000800A00004000000000000008808AC ++:10789000010090098500000008800000C000000081 ++:1078A000000500000000C000000000008200880009 ++:1078B000000000081000000003000040000000006D ++:1078C00000000000000000000000000000000003B5 ++:1078D00000000000000000000000000000000000A8 ++:1078E0000000000000400000000010200000000028 ++:1078F0000000000000000000000000000000000088 ++:107900000000000000000202080040000400040023 ++:1079100000C010008001A010030090400000000093 ++:107920002100419108000400100000009084000133 ++:1079300080200988000210200000808400000000E0 ++:1079400000000020000000000000001000100200F5 ++:107950000000000000000020000000008000001077 ++:1079600010000000092100000400000400100000C5 ++:1079700000000000000041000000000000000000C6 ++:107980000000000000000020C00200024000A00033 ++:1079900010000000000008042100002120830809D5 ++:1079A00000000020000200000000000000000405AC ++:1079B000004004000000C08001001000200500000D ++:1079C00000000000840000C01010840000100010AF ++:1079D000840000000000000000000000000004001F ++:1079E00000800000000084900000010000830083FC ++:1079F000C0000000000000000000000000000000C7 ++:107A00000000000000000000008400209001882099 ++:107A10000000418208000088111080400290800917 ++:107A200005000040108408001084410083004000DD ++:107A300000C0838400820000008400100010040154 ++:107A400000C01100008400C10000101000101000E0 ++:107A5000100040004100000005000000000002008E ++:107A600009000000000000200000000002000000EB ++:107A70000000000000020000009000000000000074 ++:107A800000000000000000000000000000000520D1 ++:107A9000048000000000000008110009209100008F ++:107AA00040840000820000000000000088001000F8 ++:107AB000014100001000000000000000C0000000B4 ++:107AC000034000000000000000040000000000006F ++:107AD00000000000000000000000000000000000A6 ++:107AE000000000000000000000800000880000404E ++:107AF0000000000000000080000000000000000006 ++:107B0000000000000000000000000000400800101D ++:107B10008005032002050505210209408303204159 ++:107B2000030509090005000540410021001100205E ++:107B30008420004002850390110811C14003090808 ++:107B400041100210000000000000000400000000CE ++:107B5000000000000000000000000000000009001C ++:107B600000004100020000000000800000000583CA ++:107B70008041828910110000000000000000000018 ++:107B800000000000000000000000000000000100F4 ++:107B900000012000010101011100010000000801A5 ++:107BA00085010001010090000400010000000001B7 ++:107BB000C000040100000089C005000500080001A4 ++:107BC0008800010000000000000000000004000028 ++:107BD00000000000000000000000000002000000A3 ++:107BE00000008800000000000000000040000000CD ++:107BF0000483400011890191000000000000000092 ++:107C00000000000000000000000000000000000074 ++:107C10000000000088008200C001C0C0C0032041F5 ++:107C20008300890291A182C1400084010300830086 ++:107C30000100012101400100410084828801C10846 ++:107C400000000082010000000000000000000004AD ++:107C5000000000000000000000000000000000A084 ++:107C600000000100000000000001000101008988FF ++:107C700083900500414089019191000001000000BE ++:107C800000000000000000000000000000000000F4 ++:107C900000C041000200850085000308200085C067 ++:107CA00000914003C18010A1888983000040A0207A ++:107CB0008300100008100883090291048880C02105 ++:107CC000A082200020804003054100000000000049 ++:107CD00000000000000000000000000000000000A4 ++:107CE0000800000011000900100041030202020018 ++:107CF000858091800804C180890290914100200014 ++:107D0000050000000000000000000000400000002E ++:107D1000000000004021002000200090100500918C ++:107D2000049083030589000900C0C04003000000DF ++:107D30000080008010820009410940090908808400 ++:107D40004120058804100020020285400000000048 ++:107D50000000000000000000000000000000000023 ++:107D600000000000800000040020214000A000115D ++:107D7000000021008089048400859189C089000069 ++:107D800000000000000000000000000000000000F3 ++:107D90000000000000000100000100010089000255 ++:107DA000000900110509000300000085830901C0D6 ++:107DB00000840040002001080008008203A0009019 ++:107DC0000811C089004000400003000911090000AB ++:107DD00000000000000000000000000000000000A3 ++:107DE000000000000000400000A000890091000396 ++:107DF00000010000010084890088C085898991897B ++:107E00000000000000000000000000000000000072 ++:107E100000000000000000000021000100010088B7 ++:107E20008241C001820110A041038502A100C1105E ++:107E3000009001000000000200020141000100006A ++:107E4000834004A0C10100C001020004010101003F ++:107E50000000000000000000000000000000000022 ++:107E6000000000000001000000000002000000010E ++:107E70000000829188018201888883854191830175 ++:107E8000C1C0000000000000000000000000000071 ++:107E9000000000000000000000000011000400408D ++:107EA0000080C01041100420910089091003400394 ++:107EB000C0800383400021050380088011C020108A ++:107EC0004000A00311080810108010001190094014 ++:107ED0001000000000000000000000000000000092 ++:107EE0000000000000000008000000000000004149 ++:107EF000000200008091800900208080898285C076 ++:107F000009210900000000410041000000000000BC ++:107F10000000000000000000000000000A00001344 ++:107F20000000006000000022D000004100500081ED ++:107F3000C2000041000000800100060000000013A4 ++:107F4000C2000000210000130100820000000013A5 ++:107F5000C20042000000000000001200000000000B ++:107F6000000000000000000000138100000000007D ++:107F7000000B440000502100000B00000000000036 ++:107F80000080010000000000000000000000000070 ++:107F900000000000000000000000000000000000E1 ++:107FA0000000FFFFFFFF5F7F5F7F0000FFFF000417 ++:107FB000FFFB283C2236A0C3A000000000000CCF2D ++:107FC0007D7D3FFFFFFF14001400004100FF3CFFD8 ++:107FD000171708500A5000000000000000000000C1 ++:107FE0000000000000000000000000000000000091 ++:107FF00000000000303001030000000000003C3CA5 ++:1080000000000000AA28AA280000000000000000CC ++:108010000000000000000000000000000000000060 ++:1080200000000000FDFFFFFF003C0F3F00410F3F3D ++:108030000014FFEB283C283CA0C3A0000000000077 ++:108040000CCF41413FFFFFFF14001430004000FF00 ++:1080500000C317170850085000000000000000007F ++:108060000000000000000000000000000000000010 ++:1080700000000000000000000103000000000000FC ++:108080003C3C20A00A0A2A28AA2800000000000080 ++:1080900000000000000000000000000000000000E0 ++:1080A00000000F000F00F0F80028555510108CCC80 ++:1080B0008CCC55AAFDFE0F0F0F070303030300002E ++:1080C000003CFFFFFFFF575557D7FFAAFF80003D39 ++:1080D000FFFF00C0828EFFB455B400000000000016 ++:1080E0000000000000000000000000000000000090 ++:1080F0000055005500000000FF0AFF0A00000000C4 ++:1081000000000000FEFEFFFFFFFFFFFF0000000079 ++:10811000FAFEFAFE0000000000000000000000006F ++:1081200000000000FCFC0C0C002800285555140031 ++:1081300080C080C055AA00000F0F0F0F000000FF85 ++:108140003C000000BFBEBFFF7F7D7FFFFFAAFF0096 ++:10815000003D003D00C08282AAB400B400000000CF ++:10816000000000000000000000000000000000000F ++:1081700000000055005500000000FF3CFF0000001B ++:10818000000020000000FEFEFFAAFFFFFFFE00002F ++:108190000000FFFFFFFF00000000000000000000E3 ++:1081A000000000000000000600E1018000000086E1 ++:1081B000006100B2008000860A6508B800000086F1 ++:1081C0007C60009000A000860CF1A8B800850086B5 ++:1081D000004101A8000000860A71A8B8000500004F ++:1081E000000000000000000000000000000000008F ++:1081F000008600E100B000000086006008980005DD ++:10820000000200A00380000000820AB0008000800D ++:1082100000000000000000800000000000000000DE ++:10822000000000000000000000000000FFFF000050 ++:10823000FFFAFC3C55005F00FFDFFFFFFFFFAA696C ++:108240000000000001010115000000003DFFFDFFDE ++:10825000555FAAA000000000000000000000000020 ++:10826000000000000000000000000000000000000E ++:1082700000000000000000000000000000000000FE ++:108280000008DF20DFDFFFFF000000BE00FA000073 ++:1082900000000000000000000000000000000000DE ++:1082A0000000000000000900000000000000FFFFC7 ++:1082B0000000FFFAF00055007D00FFFFFFFFFFFF09 ++:1082C000BE7D0000000000000000000000003D0036 ++:1082D000FD005555AAAA00800000000000008000A3 ++:1082E000000000000000000000000000000000008E ++:1082F000000000000000000000000000000000007E ++:1083000000000000FF002020FFFF000000BA00AEC8 ++:10831000020028AA00000000000000000000000089 ++:10832000000000000000002000000100000000002C ++:10833000AAAA55AA000000000000000000000000EA ++:10834000555500040000000055550CCF00000000FA ++:1083500000000000AA55FF0000FF04FB0000000021 ++:10836000000000000000000000000000000000000D ++:1083700000000000000000000000000000000000FD ++:1083800000000000000000000000AAAA55AAFFFF9C ++:10839000FFFF00C000C0000000000000000000005F ++:1083A000000000000000004000000000020000008B ++:1083B0000000555500FF0000000004000000000010 ++:1083C0000000000000000000000000000CCF0000D2 ++:1083D000000000000000A25DFF0000FF00FF0000A1 ++:1083E000000000000000000000000000000000008D ++:1083F000000000000000000000000000000000007D ++:10840000000000000000000000000000555500FFC3 ++:10841000FEFEBEBE4000C0000000000000000000E4 ++:10842000000000000000000000000000000000004C ++:10843000000000000000000000000000000000003C ++:1084400000000000008000000C800000000080C2DE ++:108450000000220542009313444000105908188080 ++:10846000881A92CC07004A3000000000000000008B ++:1084700000000000000000000000000008000000F4 ++:1084800000000000000000000000000000000000EC ++:1084900000000000000000000000000000000000DC ++:1084A00000000000000000000000000000000000CC ++:1084B00000000400040020A00400000003002101CB ++:1084C0000000800000000000C0000000210000004B ++:1084D0000000000000000200020020000300000075 ++:1084E00000201000000000000000820000000000DA ++:1084F000000000C0000000000000000011000000AB ++:10850000000000000000000000000000000000006B ++:10851000000000000000000000000000000000005B ++:10852000000000000000000000000000000000004B ++:108530000000000001000000000083009000000027 ++:1085400000100000080000000000030020000000F0 ++:10855000000000000000000000000000000000001B ++:1085600000000000000000000000000020000000EB ++:108570000000A000008000000000000000000000DB ++:1085800000000000000000000000000000000000EB ++:1085900000000000000000000000000000000000DB ++:1085A00000000000000000000000000000000000CB ++:1085B00000000000000000000001002103C1800055 ++:1085C000A1010020000000008001A1010011800530 ++:1085D000800000000000000000000000000000001B ++:1085E00000000000100000000001000000018000F9 ++:1085F00080000482040000C00000000000000000B1 ++:10860000000000000000000000000000000000006A ++:108610000000000100010004000040000000000014 ++:10862000000000000000000000000000000000004A ++:10863000000000000000000000000020008482080C ++:10864000020002040000900082004002104000027C ++:1086500010884041902000000000900000000020A1 ++:1086600000000000000900000000002000000020C1 ++:10867000200004100310010000800000000004002E ++:1086800000000000000000000000000000000000EA ++:108690000000001100040004008000000000000041 ++:1086A00000000000000000000000000000000000CA ++:1086B0000000000000000000000000000084050829 ++:1086C00009000000000000010008000100100484FF ++:1086D00002004100000005104108000000000020D9 ++:1086E000000000400000000200000000000009003F ++:1086F000800000000000000000000000000000A05A ++:108700000000000000000000000000000000000069 ++:108710000000000000000000000000000004000451 ++:108720000004000000000000000000000000000045 ++:1087300000000000000000000000000004118400A0 ++:108740001000881088090000001000A1001082802D ++:1087500010000103000000009021000884000000C8 ++:10876000C0000000C02100210000000000080041FE ++:108770000000100800090000004000400000000058 ++:1087800000000000000010000000000000000000D9 ++:108790000011000000001000000000000000008038 ++:1087A0000080008000008200000000000000000047 ++:1087B00000000000000000000000000000001000A9 ++:1087C0000500092091C0210003000810900010004E ++:1087D0004100410820001001C001A1042100210036 ++:1087E00000000000000000A00000020000000000E7 ++:1087F0000000004000000510000000000000000024 ++:108800000002000000000000000005002100200020 ++:108810004000400040004000000000000000000058 ++:108820000000000000880090000000000000000030 ++:108830000000000000000000000000000000000038 ++:1088400000000005828004000009C00082001100C1 ++:10885000000010008491850000080304408000009F ++:10886000C00000110800C00020001000080008002F ++:108870008809000000000000000000000000000067 ++:1088800000000880002108410800000010000800D6 ++:1088900000000100010009000900000000000800BC ++:1088A0000000000082000000000000000000000046 ++:1088B00000000000000000000000000000000000B8 ++:1088C000000002000000020010001082210090024F ++:1088D0000884C10340408488830204001002109081 ++:1088E00004024140418800200088009000040920D3 ++:1088F000092000000300000180000310100009009F ++:10890000000000000900020000020900000004A0AD ++:10891000000005000000000003000000000041000E ++:10892000080400A000000500000000001000000086 ++:108930000000000000000000000000000000000037 ++:108940000000000000000000000000008440000063 ++:108950000800000808100100020002C0C1210080C8 ++:10896000000001001000820010A0100084030080AD ++:1089700010C0A0C040110000000420000000000052 ++:108980000000004000000000000000800000000027 ++:10899000010000000000100000000000A000000026 ++:1089A0000000008000030000000000000021000023 ++:1089B00000000000000000000000000000000000B7 ++:1089C0000000000000000200419008820340020005 ++:1089D000100121C141A140C08800058520400284CA ++:1089E000024000840500059005400004410000009D ++:1089F00000000002000420080020000000008000A9 ++:108A00004000000400010000002003820000030079 ++:108A1000000000A000000000000000200000000096 ++:108A200000000300410000000000000000000004FE ++:108A300000000000000000400000000000000000F6 ++:108A400000000000000000000000A0000000A000E6 ++:108A50000841104084041040010008100008018003 ++:108A6000C0118590C00000400000104000000800C8 ++:108A70008800C000C080C080C01102C0000010008B ++:108A80004000010040000002000000800021A00022 ++:108A90001000100008000000080000000420000082 ++:108AA00000000400000000000000000000000000C2 ++:108AB00000800000A0000000000000000000000096 ++:108AC000000000000000000000004080000009805D ++:108AD00003800088058910214109400820110210F7 ++:108AE000412020859091210208410803080200409E ++:108AF000101103058009050520400000000040001A ++:108B00000000000000110000000000000083400091 ++:108B100080890000820310004180000000030040B3 ++:108B200000000000000000000000030040400004BE ++:108B300000200002000000000000000000002100F2 ++:108B4000000000000000000000000000018810107C ++:108B5000040800108883C1090141010801010100D6 ++:108B60000001010101898484018801A10000A001A4 ++:108B700000010100C10182010101010100000000AA ++:108B800001000000000000000000000000000011D3 ++:108B900005A010C100888901A1A0C19000C00001FA ++:108BA0000000000000008800000000000100C1017A ++:108BB00000000001000000000000000000000000B4 ++:108BC00000000000000000000000000000000200A3 ++:108BD000C1008900110001000089000100A1050009 ++:108BE000038203848301C0004002890191A1010036 ++:108BF000A0898990C0C1850082088589C1010000D3 ++:108C0000000000000001010000000002010000005F ++:108C10001001C000000089009001A084C088C1C07C ++:108C20000000014000000100000000010000000001 ++:108C300001000084010100000000000000000000AD ++:108C400000000000000000C0000000000000000064 ++:108C5000114008008800100010041188080211401B ++:108C600090009011A18483090000090089058320E8 ++:108C7000080009038808888391000800A191400931 ++:108C800000040000000000031000000000000300CA ++:108C90000000800800000000030080400000808089 ++:108CA0000380000008000000030000000004000032 ++:108CB000000240000400202000000000000000002E ++:108CC0000000110000000000000000000000000093 ++:108CD0000000000480111089008209800091088939 ++:108CE0000440001000C003890884040980A0100219 ++:108CF00010C1891000910388890810080002004003 ++:108D000041820080000010000080800041000011BE ++:108D1000000300800000009000008003000000803D ++:108D20004000C003000000000040000300030003F7 ++:108D300000030003000200040020050500000000FD ++:108D40000000000000000000000000000000000023 ++:108D50000000000000C0080141A104880008A041F3 ++:108D60000305040100A0000300A00382824090914B ++:108D700000C10088820800A001A18802000800024A ++:108D800000C10188000800400104008802000000C2 ++:108D90000000C00100C000C00490008888C10082AB ++:108DA000909005048901000000000000000100010E ++:108DB00000010001000100000000000100000000AF ++:108DC00000000000000000000000000000000000A3 ++:108DD00000000000000008A0888410001000C002FD ++:108DE0008505A0010501000300A1000100C08388E2 ++:108DF0000590040003C1A003A0890301C1A00102E2 ++:108E00000102010101C02020888400000000000050 ++:108E10000000000000000080C10491008201C090A9 ++:108E20000100A004C00190C001000000000000008B ++:108E30000000000000100000000200090000000017 ++:108E40000000000000000000000000000000000022 ++:108E50000000000000000000801180110008800068 ++:108E600010004108094040100811109109081080B5 ++:108E700083004080080040C184210489402188008B ++:108E80000310200202022080008080000000000009 ++:108E90000000000000000000008003100900002115 ++:108EA000008003000000002180800300000000001B ++:108EB0000000000000000000000004000284030322 ++:108EC00000000000000000000000000000000000A2 ++:108ED0000000000000000000000021000013C2009C ++:108EE00000000084000BC200000021810013C1803B ++:108EF000000012600083C200000081004083000077 ++:108F0000124211820183C100810000000013C200DF ++:108F100000500000000720000000000000000013C7 ++:108F2000000000000000001300000000000000002E ++:108F30000000000000000000E0000042000000000F ++:108F4000C20000000000000000000000000000005F ++:108F500000004100000000000000000000000000D0 ++:108F6000A505A5053F0F7F4FFF00FF003EFEFE3E1B ++:108F7000BDBDBD2DFF000F66F6F63F301400820028 ++:108F800004082010F0F06F630000000000000000F3 ++:108F90000000000000000000FF0000000000FF00D3 ++:108FA00000000F0F0000FFFF000066660000FFFFDB ++:108FB0000000FF00000000000000000000000000B2 ++:108FC0000000000000080000000000000000000099 ++:108FD0000000000000000000000000000000000091 ++:108FE00000003C0CC3033000704000000F0F02C2B1 ++:108FF000C202BDBD2D2D3C3C4E4E06063F30001436 ++:10900000008202014080FFFF666600040404000045 ++:1090100000000000000000000000FF000000000051 ++:10902000FF0000000F0F0000000000006666000057 ++:1090300000000000FF000000000000000000000031 ++:109040009000000000000008000000000000000088 ++:109050000008000000000000000000000000000008 ++:109060000000000000000000000000000000000000 ++:1090700000000000000000000000000000000000F0 ++:1090800000000000000000000000000000000000E0 ++:1090900000000000000000000000000000000000D0 ++:1090A00000000000000000000000000000000000C0 ++:1090B000000000000000000000000000000000218F ++:1090C0008000000000000000000000000000000020 ++:1090D000000000000410000000000000000000007C ++:1090E00000000000000021FF2103427E427E663C1A ++:1090F000663C667EF6FE5A5A20DBC3C0C0C0000044 ++:109100000FF00011002280401020F0F0F0FF181F37 ++:109110003C3F000000000000000000FF00FF0000D6 ++:109120003C3C00000000F0F00000FFFF000066661D ++:109130000000FFFF000000FFFFFF0F0F0000000016 ++:109140000000000000080000000000000000000017 ++:10915000000000000000000000000000000000000F ++:1091600000000000000000002BFF2B0FC0FCC3FF1D ++:10917000F0F00F0F667EF6FE666600FF8303800048 ++:1091800000000FF01100220001020804B0B0B0FF8F ++:1091900018FF3CFF000000000000000000FF00FF7F ++:1091A00000003C3C00000000F0F000000000000067 ++:1091B000666600000000000000FFFFFF0F0F0000C8 ++:1091C0000000000000000008000040004000000017 ++:1091D000000000000000000000000000000000008F ++:1091E00000000000000000860090098000800084DC ++:1091F000707500B0008000060C6501380010A5A64F ++:109200000044A9804C600086002001C0140008863C ++:1092100000640188000000860031A8900005A08647 ++:10922000016008B44940000002C701800084494041 ++:1092300002C701800084494002410100000441400E ++:1092400000005000000000050000001000000000B9 ++:1092500000000000000000000000000809000000FD ++:109260000000000000000000FF00CB0841C37DFFAC ++:10927000FFFFFFFF4D4D4D4D00000000000200823A ++:1092800030FF30FF0C0CFFFFFF0F3C3C0CFF0CFFCE ++:10929000000000000055F3F7FF00AAAA0010FFDF4E ++:1092A000000000000000000000000000008003003B ++:1092B00000000000000000000000000000000000AE ++:1092C000000000000000000000000000000000009E ++:1092D000000000000000000000000000002000006E ++:1092E00001000000000000000000FF00CB080000AB ++:1092F000FFFFBFBFBEFF417D417D000000000002B7 ++:10930000008230FFC3000008F3FB3C3C3C3C0CFFF8 ++:1093100000F3000000005555F7F7FF00AAAA00105F ++:10932000FFDF0000000000000000000000000080DF ++:1093300000000000001000100800080000000000FD ++:10934000000000000000000000000000000000001D ++:10935000000000000000000000000000000000000D ++:10936000000002000000000000000000FFEF1404F5 ++:1093700030FF00CF03C0FFFF00000000000000002E ++:10938000F359F355FFDFA08000FA04FE000000004F ++:1093900000FFAFAF000000000CFF0CFF000000005A ++:1093A00000000000000000000000000000000000BD ++:1093B000020000000000000000000000200000008B ++:1093C000000000000000000000000000000000009D ++:1093D000000000000000000000000000000000008D ++:1093E0000000000000000000000000000000FBEB97 ++:1093F000100000CF00CF03C0AAAA000000000000A8 ++:1094000000000C0C0C00FFDFA08000FA04FE00003E ++:10941000000000FF00FF000000000CAE0CFF000089 ++:10942000000000000000000000000000000000003C ++:1094300000000200101000000010001000002000CA ++:10944000000000000000000000000000000000001C ++:10945000000000000000000000000000000000000C ++:1094600000000000000000000000000000000000FC ++:10947000042084000400110002000408020182009C ++:10948000410000A002101100000040001000040084 ++:1094900000000300000003100000020000000004B0 ++:1094A0001100000011000000000005000000002075 ++:1094B000004000000000000000000000000000006C ++:1094C000000000000000000000000000000000009C ++:1094D000000000000000000000000000000000008C ++:1094E000000000000000000000000000000000007C ++:1094F0000000880010000000020004000080010845 ++:1095000041002000000000002000C0000100010018 ++:1095100000000000000000000080000000000000CB ++:1095200000000000880000000000000000000000B3 ++:109530000000000000000000000000000800000023 ++:10954000000000000000000000000000000000001B ++:10955000000000000000000000000000000000000B ++:1095600000000000000000000000000000000000FB ++:10957000000000000000000000008000000000006B ++:109580000000000000010000020100000000004097 ++:109590000000800000020001000000000000000048 ++:1095A00000000000110100000000000000000000A9 ++:1095B0000020040000C000000000000000000002C5 ++:1095C0000000000200030005000000000000000091 ++:1095D0000000000020080000000000000000000063 ++:1095E000000000000000000000000000000000007B ++:1095F0000000000000008821004120210221040019 ++:1096000000000000C0000004001191040010820856 ++:109610000091002110000080004000210021001175 ++:10962000000000000010004000000041A0100000F9 ++:1096300000000080000000C000000040002000008A ++:1096400000800000008000C00084000000000008CE ++:109650000000000000000180000000000000000089 ++:1096600000000000000000000000000000000000FA ++:1096700000000000000000000005041000040000CD ++:109680000010414000840010008400840010000499 ++:1096900000000002002003401184008400000090BC ++:1096A00000000000000804050240044004080440D3 ++:1096B00000000002800000A000002004200420918F ++:1096C000000102000000000000000000200008006F ++:1096D0000000000000000002000000000000000088 ++:1096E000000000000000000000200000000000005A ++:1096F0000000000000000000000090848205028548 ++:1097000008101000000040031009841000111021FF ++:10971000108010094091408000850000101000105A ++:10972000C002C0210020C0020190011000000040D2 ++:1097300000400000020040000000000001800180A5 ++:10974000910400040000000000000200000000007E ++:1097500000000000000010000000000000000400F5 ++:109760000000000000000000000000800000000079 ++:1097700000000000000000000000000010001000C9 ++:109780001000050009000500110002011000410051 ++:10979000020020A0040090001001209010000000A2 ++:1097A000100141012100000000001000090002002A ++:1097B0000300000000021082900241020000050434 ++:1097C0000004000410040000050100008390A000C4 ++:1097D00005000000000000000001000084012001DD ++:1097E0008008000480010000004000080000000024 ++:1097F0000000000000000000000000000000A005C4 ++:10980000C00008008205A0008809A0419102C003A1 ++:10981000C0000841080501004041A002A0408404A6 ++:1098200002000008100800000000102100000005E0 ++:1098300001001000C00002800804048000800000C5 ++:10984000C080C0A10089108082001040C0050200C5 ++:10985000210002401000A0000000000200000540AE ++:10986000010410800080020400000000008000005D ++:1098700000000000000000000000000000000000E8 ++:10988000000240850010090800000500000040406B ++:1098900003100082020404000008C04021009085EB ++:1098A000418820004100000000001000000005C1B8 ++:1098B000004005A108400040200040000091100138 ++:1098C00000001102100000002090000000000800BD ++:1098D0000800090004002100000000000000000052 ++:1098E000000000000200200004000088000000903A ++:1098F0000000000000000000000000000000000068 ++:1099000000009009820800080010400000051000C7 ++:10991000A1890000A01104C001004080218000093D ++:1099200010084002110040028800000000020041BF ++:1099300010020080000400051080052001000020B6 ++:1099400000200080008000090000001100000000DD ++:109950000000000000000100000400000000000002 ++:109960000000000000009000010000000002000064 ++:1099700000000000000000000000000000000000E7 ++:109980000000000002C00300030020A1210000C06D ++:1099900005000285009041A0088804212108910457 ++:1099A000008841840901000011080801100002002C ++:1099B0000000080000100000004085000400039033 ++:1099C0004000050000000020089005880008000005 ++:1099D00010020500410010000200000041000000DC ++:1099E00000000000000000000000210020008000B6 ++:1099F00000210020800000000000000000000000A6 ++:109A0000000000000000000000000800090210092A ++:109A1000A000C0008820C0210203C00002A0C091A5 ++:109A2000109100008440A002840002800140880060 ++:109A3000050000400200A000A0001000044000004B ++:109A400010210121000000000080080088090000AA ++:109A50008200C0800040C000000000400000840080 ++:109A600084000000A0008400C0000000000001008D ++:109A7000040000880080400000000000000000009A ++:109A80000000000000000000090309094108410925 ++:109A900020038000110020102103A10921021109D7 ++:109AA000808500858809000903004000050020002A ++:109AB0000020100800080040008203090082000511 ++:109AC00000000811890000000000000300001009D8 ++:109AD00000000003000009000000828300004080B5 ++:109AE000000002000000090005000009000208094A ++:109AF0000810088300092040020000000000000058 ++:109B000000000000000000000000200184000000B0 ++:109B100001000101C000000091018901090001015B ++:109B200000018804A084418200C0010004000000FC ++:109B3000010090018401000000000440400900C0C1 ++:109B4000000200000100C1000000000000C1A010E0 ++:109B5000A00100A000010000000000008905C0C0B5 ++:109B6000A1900000010010000000010000000800AA ++:109B7000010000000009040411A100000000000021 ++:109B8000000000000000000000000000040090C081 ++:109B9000A0010100080082000908850004009190DE ++:109BA000C0010201000004C18891840991000301F1 ++:109BB000840004894101040305A18290000000880B ++:109BC00000010010830002C008882100000000018D ++:109BD000A00010900300C000C0000200118290009D ++:109BE000C084408803020100010000100000000052 ++:109BF000008200000000C0010400A000000000007E ++:109C000000000000000000000000000000008900CB ++:109C100009000541090091000000C0009002910078 ++:109C200008801041A1090203020290A19120C00006 ++:109C30004008850000C1A0108840C1058290001135 ++:109C400000C100020080100080008091030000002D ++:109C50000002000400808304004180000000838231 ++:109C6000800000008080838011002000418000057A ++:109C70004000108041001000004000000000000083 ++:109C800000000000000000000000000000000000D4 ++:109C9000404000050909408000100000009009853F ++:109CA00011880005008480A103880011400400048D ++:109CB00000A000842188000303A000040988058017 ++:109CC00004000080C00041000000000000900083FC ++:109CD00000000000008084C0800305000080008434 ++:109CE0000083008000808080C0030040001000409E ++:109CF0000041108000050010100811058085000942 ++:109D00000309000000000000000000000000000047 ++:109D1000000001410041004191A0000900A0004065 ++:109D2000910900890085008890820008000902904E ++:109D3000000040A10090018440A1010400000084C3 ++:109D4000C188000840100282C0880010002000086E ++:109D5000000500000410A090020388010004001018 ++:109D6000008400410204C09040408901000500A029 ++:109D7000008302A000100009000900890000404192 ++:109D8000040401A00000000000000000000000002A ++:109D90000000000001C00111008500020000000168 ++:109DA0000001000801100088010100A011018902D2 ++:109DB000A0000009828984908800C00883918401F2 ++:109DC00010010940854010040800080001000190BE ++:109DD0000000010000001100A1020201A090090092 ++:109DE000A010400010C0C101C0004001900000025E ++:109DF000000000000000000001100000010004014C ++:109E00004040A00002C00000000000000000000070 ++:109E10000000000000000908410404C00800001010 ++:109E20000010001000000880100920212100830389 ++:109E300040410005408580C0008880000000A0826D ++:109E400040088540C080A08005004100020003104A ++:109E5000080020002000000003100900802100807D ++:109E600083090005840080800303000080218000B6 ++:109E70000000000400040000110010090811110086 ++:109E80000040808000000080000000000000000012 ++:109E9000000000000000000000840000C20000007C ++:109EA000000000810100000000000081810000002E ++:109EB00082000013440081000000000002008100C5 ++:109EC000410080838100210000840083C2000000E3 ++:109ED00000000013C2000000000000000013020098 ++:109EE0000000000000000000006000000013C1003E ++:109EF000060000000013E000000000000000C200A7 ++:109F0000820000000013000000410000000000007B ++:109F1000000000000000000000000101BFBF2A7F18 ++:109F20002A7F00000000417D7D7D550017003D0027 ++:109F30000500D700FFFF003C0C3F0000000036C9C1 ++:109F4000C1F7C3FF4D4D0CFF0CFFFFFFABBF00007F ++:109F500000000000FFFF000000FF0000000000FF05 ++:109F6000000000FF00000F0F000000FF0000FFFFD7 ++:109F700000005555000000003535C5C5033FC0FC45 ++:109F8000F0FF000F00000000FFFFFFEF00000000E7 ++:109F90000000000000000000000000000041BEFFC3 ++:109FA00000FF00FF00000000417D41410000030070 ++:109FB00001000500D70028FF003C0C3F0000000016 ++:109FC000936C40D3003C4D4D0CFF0CFF000001157D ++:109FD0000000000000202F2F000000FF0000000004 ++:109FE00000FF000000FF00000F0F000000FF000056 ++:109FF0000000000055550000000005F5F505003C87 ++:10A00000C3FF000FF0FF0000000000000000000090 ++:10A010000000000000000000000000000000B2B2DC ++:10A02000FF00FFBFC080BEBE4141AAAAAAAAF0F0AD ++:10A030003C3C003C00ACFFF3FFFFFFFEFFFA0000DA ++:10A0400000002EAF2EAF3C3CFFF03F3E0302AEA21D ++:10A05000EF2000000000FF00FF003C3C000000007B ++:10A06000F0F00000FFFF0000FFFF0000AAAA0000C0 ++:10A07000AAAA00000000FFFF00000000FA50FA50FA ++:10A08000FCFFFDFD3C3C2C3C5FFF5F5F00000000DF ++:10A0900000000000000000000000000000000000C0 ++:10A0A000B2B2B2B27F3F4000BEBE4141FF00FFC32B ++:10A0B000F0333CC3000000A0FFFFFFFFFFAEFFAA8C ++:10A0C000000000002EAF2EAFFFAAFFAA3F3C030006 ++:10A0D000FF00FF0000000000FF00FF003C3C00000C ++:10A0E0000000F0F000000000000000000000AAAA3C ++:10A0F0000000AAAA0000FFFFFFFF00000000BE143E ++:10A10000BE14FFFFFFFF3C3C7C3CFFFFFFFF000055 ++:10A11000000000000000000000000000000000003F ++:10A12000000000860A7400B000000086046100B0E0 ++:10A13000000000860A7100900000058650C001A052 ++:10A140000080A0865060A8B9008500820C6009904C ++:10A1500004050086707400B00000118601F00084D0 ++:10A1600049400000A2C75190A084494502C7016040 ++:10A1700000B44940A2C701800884414000860060C5 ++:10A1800008B800850086027008B0000000860A81C9 ++:10A19000008000000000000000000000000000003F ++:10A1A00000000000000000004100FF00000000006F ++:10A1B0005D5DDDFD000000003C3CFFFFFF5AFFA598 ++:10A1C0002D872D87000030006FFFF9FFA0A0D7FF7B ++:10A1D0003C00FFC3000000000F0F0F0F0000000045 ++:10A1E0000000200000000000000800000000C3FF85 ++:10A1F00003CF10D01FDF00000000000000000000AF ++:10A2000000000DF2FF0000000000FFFFFFFB000058 ++:10A210000800000000000000000000000000000036 ++:10A22000000000000000000000004000FF000000EF ++:10A2300000005D5D5D7D000000009C3C7FFF005ADA ++:10A2400000A5872D872D00030000F9FF6FFFA0A058 ++:10A2500000280000FFFF400000003F0F0F0F00002C ++:10A2600000000000200000000000000801000100C4 ++:10A2700041D741D710D01FDF00000C0001000100C2 ++:10A28000000000000DF237F800000000FFFFFFFFA4 ++:10A29000000008000000000A0000000000000000AC ++:10A2A0000000000000000000000000000055005504 ++:10A2B00000000000030FF5FF00000000283C2C2CDC ++:10A2C000F0F0F0F000FF00FF00000000FEBFBFFE56 ++:10A2D000000000005F575D55000000000000000016 ++:10A2E000000000000300000000000000000000006B ++:10A2F0000000000000001144BBEE00000000300030 ++:10A30000000000000000000000000000000000004D ++:10A310000000000A00001000100000000000000013 ++:10A3200000000000000000000000000000000C5DC4 ++:10A330000C5D00000000000F5F5F00000000283C83 ++:10A340002C2CFF3CC3000505AFAF00000000FD7FD3 ++:10A350007FFD000000000D010D0100010000000064 ++:10A3600000000000000000000000000000140000D9 ++:10A370000050000000000000BBEE1144000000A0EF ++:10A3800000000000000000000000000000000000CD ++:10A3900000000000000000000000000000000000BD ++:10A3A00000000000000000000000000040008800E5 ++:10A3B0000400044004000200020010000400040035 ++:10A3C0008400840040004000A102110000A01100A0 ++:10A3D00020000000800040002002000888004000AB ++:10A3E00021008004000080000008800400001000AC ++:10A3F00000000000800000000000000000000000DD ++:10A40000000000000000000000000000000000004C ++:10A410000000000000000000000000000400000038 ++:10A42000000000000000000000000000000001002B ++:10A430001100000000800000000001000100000089 ++:10A44000000020002000010001004080A00000006A ++:10A450000000000000042000010004800080400093 ++:10A460000100A00010800000040082800480000031 ++:10A470000100000004004000000000000400000093 ++:10A4800000000000000000000000000000000000CC ++:10A4900000000000000000000000000000000100BB ++:10A4A00000000000000000000000000000000000AC ++:10A4B0000000800980890001000100000000000107 ++:10A4C00000018000000000012000800080000000EA ++:10A4D0000000000100040001000000000000040072 ++:10A4E000000000000082800000000000000000006A ++:10A4F00000C000000000000000210000200100005A ++:10A500000008000000010000000100000000000041 ++:10A510000001000000000000000000000001000237 ++:10A52000000000000000000000000000000000002B ++:10A53000000000001088100804080020000000102F ++:10A540000020820420000011904000000400100050 ++:10A5500020110000902090808220201100008208AD ++:10A5600001000000000000001000000000000000DA ++:10A57000040000C000000000002100882000000846 ++:10A580000000000000000008000000400000000083 ++:10A5900000000004000000000000000000000004B3 ++:10A5A000008000000000000000000000000000002B ++:10A5B000000000004002058503011010000883C060 ++:10A5C0000084000080C0088982008000C000040070 ++:10A5D000000505400840400400A0100800C00585A3 ++:10A5E000004010C10008001000200010000000848E ++:10A5F0000084001000000000050040C0008400003E ++:10A60000009080C0800000000000004000080000B2 ++:10A6100000880000030000000000000000000001AE ++:10A620000001000100010000000000000000000027 ++:10A6300000000000000091898410820810210010A1 ++:10A64000044104000002200982042100202111009D ++:10A6500085050088088010410285001001801000E7 ++:10A66000820284C1000800C100030040000084048D ++:10A67000840484048440000084000000850082007B ++:10A68000000000000200020082000000888082803A ++:10A6900000000000A00000000000A00090000000EA ++:10A6A000001000100020001000000000000000005A ++:10A6B000000000000000000021000008050002006A ++:10A6C00083001000C0008200020005000300A0000B ++:10A6D00000001000020010000590030010000300AD ++:10A6E0008000100000000000000041A000000241B6 ++:10A6F000100003000300100400000200000010001E ++:10A7000000004000400000000000000000000000C9 ++:10A71000080200000000000000000002000000002D ++:10A7200000010000000080000001000000000000A7 ++:10A730000000000000000000000000040090040081 ++:10A74000000040030100110003000100822100000D ++:10A750002000000000001011400010041000200430 ++:10A76000020040008204000500009000C0040020A8 ++:10A77000C184002000000000038000000300880066 ++:10A78000830000000140111010000000004108404B ++:10A790000004A0000003000000000003000000000F ++:10A7A0000000022000000000200000040000000063 ++:10A7B000000000000000000000000000100408A0DD ++:10A7C0009000050810821000028221000585830098 ++:10A7D00000A0A1A08584908503884003000141402A ++:10A7E000412010100300101000A005080000000216 ++:10A7F0001084104004000020102010050000020109 ++:10A8000010000202C100C101034002884101100092 ++:10A810001090100000000000050000210940090010 ++:10A8200000000000211080008801800080010000ED ++:10A83000000000000000000000000000000085A1F2 ++:10A840009100110084030021A0001000A005042045 ++:10A85000041100052000020005088211098410047B ++:10A860000080000010090003840000000085000043 ++:10A870000080014091C001001000000900840080A8 ++:10A88000010884000000040940401000014100401C ++:10A8900000000000000000000000A0000008008090 ++:10A8A0001000A0210000C0A1040009200800202001 ++:10A8B0000000000000000000000000000000000098 ++:10A8C00011008901000490041088A1020000000218 ++:10A8D000028820008200020120C02020020810848B ++:10A8E0000001209021011000020041002085020893 ++:10A8F000100010041040100410001084040882009E ++:10A90000000009001000080000844100104000040D ++:10A9100008404000210009400300020000000090B0 ++:10A9200000000000002000040008800000218001D9 ++:10A930008020000000000000001000000000000067 ++:10A9400000000000100884804180110040000000D9 ++:10A950000080900901090440012001400080048525 ++:10A960000100002000000020000010000004000290 ++:10A97000908000002000008000800000C000A1C086 ++:10A98000202100000840C00010008400884011C051 ++:10A99000000000800100100000000800000000001E ++:10A9A0000200880000000080008000801000028407 ++:10A9B000401008C00000000000000000000000007F ++:10A9C00000000000110300040541030483038320F9 ++:10A9D00009050541000500C10289021020038041DC ++:10A9E00084200390008009A020411090402180081D ++:10A9F00005110310200000000000400000800080CE ++:10AA0000A00010800000848204C12040400840055E ++:10AA100002041005058841050011400003092000CB ++:10AA200080002000100020039100C12111050905BC ++:10AA30004141000041110000000000000000000042 ++:10AA40000000000000000001400021000100110191 ++:10AA5000400101000000008890840020008801412E ++:10AA6000088884A00108C00285850111000409003E ++:10AA7000400000010000010010000000010000087B ++:10AA80000010020400080000850503C000110089C1 ++:10AA900003A104A100080041000120000100010001 ++:10AAA00001004000010000000101C100830001001D ++:10AAB000010100040000010100000000000000008E ++:10AAC00000000000000000000000008201050000FE ++:10AAD000C0108808082105010221A000C0049010C0 ++:10AAE000C100880200000505C000400890004191A7 ++:10AAF000C000828403050800C00091000901110113 ++:10AB00000800010005100808000088001105081061 ++:10AB1000118890010282400084C0090000820385F0 ++:10AB2000C0000200C1000800090082019100A18854 ++:10AB300020900104004009A1010100000000000074 ++:10AB4000000000000000000000000000400005853B ++:10AB500011004180090290C003400010050005204B ++:10AB60000583110580A0401183408802C100410384 ++:10AB700010050400100040111100020020004010D8 ++:10AB8000200385090200050090840000000590055F ++:10AB9000A0411004801109800511858091000400F6 ++:10ABA000109000000000080080009000002091003C ++:10ABB0008980808509004180898310400000000061 ++:10ABC0000000000000000000000000000309000574 ++:10ABD00021A08890054111890241820302104002A0 ++:10ABE000C10980408284000302830241000004A066 ++:10ABF0000009020505C0001100849088008500044A ++:10AC00002140000500910002204100900080054095 ++:10AC100080919184408805200008000500402004B0 ++:10AC2000000000C140C0000000C1008500400002DB ++:10AC3000000921899185119140110005C140000052 ++:10AC400000000000000000000000000000000140C3 ++:10AC5000008901119182A0200004001010C101049C ++:10AC600008018482400482080410418400880004A2 ++:10AC7000C011204104A1001100A100A0890500021B ++:10AC8000000200A00003000800202004000900804A ++:10AC900000050411A084C111000520C082C0000578 ++:10ACA000018800A00084894100000004008400A104 ++:10ACB000008300C100A19183000901000000080188 ++:10ACC0000000000000000000000000000000000084 ++:10ACD00000080003000000000108000501080083CF ++:10ACE0008240888209008820A10291028800100811 ++:10ACF00041094104900140880105010100000088DC ++:10AD000000000100010001400001040010000210D9 ++:10AD10000080C12111830901C08885C04000A001C5 ++:10AD2000020201010001000000A00000000100017A ++:10AD3000004082018885200184880190010504007B ++:10AD40000100000000000000000000000000000002 ++:10AD5000000000802008414121000384104002854A ++:10AD600041A040840989C041110003100509410830 ++:10AD70000480098320101008110003400504040218 ++:10AD8000090011051002080508000002004080407B ++:10AD9000808000800382208582100380A000100242 ++:10ADA00004108280400304410303200000020010CD ++:10ADB00000100080800380C080218080038004090F ++:10ADC000030540000000000000000000000000003B ++:10ADD0000000000000810013C200065000000013B4 ++:10ADE000C200064100000081C200110000000013F3 ++:10ADF000C200816000810013C200110012000083B4 ++:10AE0000100000000000000044000050000000138B ++:10AE1000C2000000000000000013C200410000005A ++:10AE2000000000008200000000000000215000002F ++:10AE30000000C100000000000083C100218100006B ++:10AE40000013C200004100000000000000000000EC ++:10AE50000000000000007F1F7F1FFFFFFF7F00003A ++:10AE60000000000000000F7E0F18FCFFFC00699638 ++:10AE7000CA5C00000008FF7000700F000F000303A1 ++:10AE8000FD64EF6FE66FFEFC0E0CFF6F6666000060 ++:10AE90000000FF3F3F0F0000FFBD00013CC396963E ++:10AEA000E67FEF7653DBC35A96C3963CFF7E3C2485 ++:10AEB000000000006F0690F9000000004200400210 ++:10AEC000000066660F0F0F0F00000000000000007A ++:10AED000000000000000000070107010FFFFFFFF76 ++:10AEE00000000000000000000F7E0F180CFF0C0097 ++:10AEF000699635A300000000FF400040FFF00F00FE ++:10AF00000000FD640F0F0F00FEFC0E0CFF69020233 ++:10AF1000000000000F0C0C000000FF3C0000C33CD0 ++:10AF2000969680198910C33C333C69C3693C7E3CCA ++:10AF300024000000000090F96F06000000004200AD ++:10AF400042003000CCCC3C5A3C3C000000000000E9 ++:10AF500000000000000000000000000000000000F1 ++:10AF60000000C20804000011886100000000000019 ++:10AF700000000000000000000000000000000000D1 ++:10AF800000000000000000000000000000000000C1 ++:10AF900000000000000000000000000000000000B1 ++:10AFA00000000000000000000000000000000000A1 ++:10AFB0000000000000000000000000000000000091 ++:10AFC0000000000000000000000000000000000081 ++:10AFD00000000000000000000000000036363C3C8D ++:10AFE0006666666600000000000000000CFC0CFCB9 ++:10AFF00060F960F9A69540626666FFFF7EF07EF01C ++:10B000006EF7F76E00000000FEF0FFF00000000099 ++:10B01000F0FFFCFF000000003C7EFCFE0000CF09BA ++:10B020000F890606006630F3F3F396696969663C9A ++:10B03000663C74F674F600000000606000000808CA ++:10B04000FCFCFF9FFF9F24FFE7FFFCFCFCFA0000D5 ++:10B05000000000000000000000000000000006F6F4 ++:10B0600000FFF000F0FF00000000000000000C0CEA ++:10B07000FCFC009966FF596AE6F766663CFF7EF0C5 ++:10B080007EF008919108020000006E006F00000041 ++:10B09000000066007E3C0000000000000000000090 ++:10B0A00030F6F07F9F9F99FF3030F3309696966987 ++:10B0B000003CFF3C60746074000000000000000071 ++:10B0C0000808FCFCFFFFFFFF2400E7C30C0C0C0A80 ++:10B0D0000000000000000000000000000000000070 ++:10B0E00000860AFCA038000005860A6100B900A0AD ++:10B0F0000086007100B00000A5865A20A8B800158F ++:10B100000086005400A000000886006001980080BE ++:10B110000086006008B80085008600800080000579 ++:10B12000000008860271009000800086006000B870 ++:10B1300000800086006000B800000086006008B053 ++:10B140000000008204B00000000008000070083019 ++:10B1500000000000000000000000000000000000EF ++:10B160000000000000000F0F287D00000000FCFC24 ++:10B17000FCFCA0AA28AA000000000000505040FFDC ++:10B180000000000000017C1000000000000000FF33 ++:10B1900004FB000000000C0000000000000008009C ++:10B1A0000000000057565A5A3C003F0FFEFFB0F017 ++:10B1B000D782D7D700000000FFFFFFFF000000008C ++:10B1C0000FFF5F5F0802080A414203C00000F0F071 ++:10B1D0003C3C0000000000000000000000000000F7 ++:10B1E0000000000000000000287D287D0000000015 ++:10B1F0000CFC5CFCFAFFBEFF415500553CC35050AF ++:10B20000C2FF000000C000C1FD34000000000000CB ++:10B2100000FF0CF300000000000000000080008030 ++:10B2200008000000000097565AAA3D053C00FEF0B9 ++:10B23000B000D782D2D2000000007FFFFFFF0000E5 ++:10B24000000000F050500802020000000000000062 ++:10B25000F0F03C3C00000000000000000000000096 ++:10B2600000000000000000000000000000000000DE ++:10B2700000003D7D3D7DF0F0EB286DB27DA253FFD7 ++:10B2800000FF14141F1FF000F000FFFFFFFF00007D ++:10B290000000003C5FFD00000000040C0D0F0000EA ++:10B2A0000000000000000000FEAAFEAABFBEBDBC58 ++:10B2B000BEA2BEB60F7D0F410000000014D7D7D745 ++:10B2C000000000002BD4FFFF000000000039000048 ++:10B2D0000000FF0000FF0000000000000000000070 ++:10B2E000000000000000000000000000000000005E ++:10B2F00000000000156D1545F0F028EB1CE35DA281 ++:10B300000053000000000F0FF000F101555F7D7F3A ++:10B3100000000000003F5FFD0000000000040C0D75 ++:10B32000030000001400000000007E007EA0BEBEEE ++:10B33000BCBCBCA8BCA80F7D0F410000000014D706 ++:10B340001414000000002BD4000000000000003C9A ++:10B3500000000000FF0000FF0000000000000000EF ++:10B3600000000000000000000000000021001100AB ++:10B37000200011002000000004002008040020002C ++:10B38000201000000010400000000000110011001B ++:10B39000000420042104000000A0000400040204B2 ++:10B3A000000400000004840421000040000020008C ++:10B3B00084002001110000020000002000000000B5 ++:10B3C0000008000000000000000000000000000075 ++:10B3D000000000000000000000200000000000004D ++:10B3E00000000000008200000000000000000000DB ++:10B3F000A00090000000000000000000000000001D ++:10B400000000000000000400000004000000000034 ++:10B41000A00000800080A080000000000080A080CC ++:10B420000080008000000080048082000000000096 ++:10B430000100020001200000008000000000000068 ++:10B44000000000800000000000000000000000007C ++:10B45000000000000000000000000080000000006C ++:10B4600000000000000000000000000000000000DC ++:10B4700000000000000000000000000000000000CC ++:10B48000000000010001000000000000002000009A ++:10B4900000000000000000000000000000000000AC ++:10B4A000000000000000000000010001000000C0DA ++:10B4B00000000004000000A00000000000000000E8 ++:10B4C000000000200000002000000000000000003C ++:10B4D000000000000000000000000000000000016B ++:10B4E000000000000000000100000000000000005B ++:10B4F0000000000000000010000000080010000024 ++:10B50000000000000020002000000020901000003B ++:10B510000000000000000021000000000008A01052 ++:10B52000000000000000002000000040002000009B ++:10B5300000800000008000000000001100000000FA ++:10B5400000080000008000000090000000000000E3 ++:10B5500000000000000000000000000000000000EB ++:10B5600000200000000000000010000000000000AB ++:10B5700000000000000885048002000003000000B5 ++:10B580004100000000001100000100000000100058 ++:10B59000000000000000000000000000100020007B ++:10B5A0000501000000A010000010000008C000000D ++:10B5B000040400000000030003000000110000006C ++:10B5C00082009184000080210000002000042120DE ++:10B5D000410400200000030010000582100000005C ++:10B5E00005A00000000000000000000000000000B6 ++:10B5F000000000000000C0802080108082008200D7 ++:10B600008800840084218209A00084201000841016 ++:10B6100085008400C00010001003C02100108200CB ++:10B620000100002000030000C041840082000821C6 ++:10B63000C021C1910000C000900000000809100066 ++:10B64000100003004000000010888200008000808D ++:10B65000C080008084808400100010001000000072 ++:10B6600000000000000000000000000000000000DA ++:10B670000000000000000000000005000040000085 ++:10B68000100002000900100240001000030000003A ++:10B690000200000000000000008802040400100006 ++:10B6A00000000282208202001040000010004101D0 ++:10B6B0000200090082840000090041001000A0017E ++:10B6C00000904104020421040000000841400000F1 ++:10B6D0000000040020000400000000000000000042 ++:10B6E000000000000000000000000000000000005A ++:10B6F0000000000000000000000000210009000020 ++:10B7000082000000000000000000000000000000B7 ++:10B710000000000000001000000000000000010018 ++:10B7200000000000000020000000000000000000F9 ++:10B730000004000000002000000000211021002172 ++:10B74000040400000080018000A0000000800000D0 ++:10B75000C000000001001100010000000000000016 ++:10B7600000000000000000000000000000000000D9 ++:10B770000000000000000000000010001001410067 ++:10B7800000001000008210000000210000000001F5 ++:10B790000000000000000000410000000000100058 ++:10B7A00005400000000000048001100010000500AA ++:10B7B0000000030002A084002100000009088201AB ++:10B7C00000000201210002088041418911000400AB ++:10B7D0000800030000014100030000000000030016 ++:10B7E0000500200000000001000100010000000031 ++:10B7F000000000000000000000000000032101081C ++:10B80000000082218421822084210021A008880058 ++:10B81000842000214000C00010038202402100006B ++:10B82000002110800000000500832040000000205F ++:10B830008400C000000800210508A00800C000091D ++:10B840000304844101041000018002400440000010 ++:10B8500001008420020000048200C00000030000F8 ++:10B860008200000001000000C004C004C004000009 ++:10B8700000000000000000000000000000000200C6 ++:10B8800000A0090040030390418210000310004013 ++:10B890000500414011402004000000000488000021 ++:10B8A0000000000402000040008211401040090026 ++:10B8B000000000000200020002C04100030000007E ++:10B8C000050004900040410021844184028440101E ++:10B8D000410041001040040003004100030010003B ++:10B8E00003000400102005000000002000200000DC ++:10B8F0000000000000400000000000000000000008 ++:10B9000000000000000001820000000000000000B4 ++:10B910000000000000000000000000000000200007 ++:10B92000000000000000000000000000000088117E ++:10B930000000000000000100000000000000000006 ++:10B9400000000000C00000800000100000000003A4 ++:10B95000010000000000820083000000C000000021 ++:10B960000000000000000000000000000000008057 ++:10B9700000000000000000000000000000000000C7 ++:10B98000000000030004000940090000000000005E ++:10B9900000000000800089000000200080000000FE ++:10B9A00040000000000040000000080300094003C0 ++:10B9B00000008003000900200000000380098900C6 ++:10B9C000000000004005400911110908030880200B ++:10B9D00000090004052000202141020200098041E5 ++:10B9E0002010410200000000000000004020002163 ++:10B9F000050320000000000000000000000004001B ++:10BA00000000000010010000000001000000000024 ++:10BA1000000000000000020002000000000004001E ++:10BA2000000001000000000001000000010102010F ++:10BA3000010000000401000100010000A00120013C ++:10BA4000210000000000010082000001010101014D ++:10BA50004000000000000001A0010100000000C043 ++:10BA600010A0010500C00000000000000000C1019E ++:10BA7000A000A00001000000000000000000000085 ++:10BA80000000000000000000009001000001000024 ++:10BA9000000000000000820084000888040000000C ++:10BAA0000100000001000000000000000100000093 ++:10BAB0000000012001010000000001000101000060 ++:10BAC00021C088000501000008002188032184C1ED ++:10BAD0000400020091000308020004000400C009F1 ++:10BAE000C001A0A00401C04100000100010001004C ++:10BAF00005008484210105410100000000040000CC ++:10BB000000000000000000080500050021090240B7 ++:10BB10000000000000000000000080008080800025 ++:10BB200003004100040005020000000000000900BD ++:10BB300000000000210003090000000021000309AB ++:10BB40000005C0008000032000008440A08085A183 ++:10BB50008589000900100500209000090000000000 ++:10BB600000A020030500052102C0000010002000F5 ++:10BB70002000A00085008221A0A00200000000009B ++:10BB800000000000000000000080402000050008C8 ++:10BB9000C1110000000000000000008000800000D3 ++:10BBA000808000880091000900840000008000006F ++:10BBB00000800000008020838083000000020920B4 ++:10BBC000000340C0008000090003000020080002BC ++:10BBD000008410C002C10020040302C0040400C19C ++:10BBE000002003040302802089C0C08500000000FB ++:10BBF0000000000040A000A12010A0800000000074 ++:10BC00000000000000000000000000000100000033 ++:10BC1000000190010000000000000000000200C0D0 ++:10BC200000208820000900410002004000A0000818 ++:10BC300000040202000000080004020500000001E8 ++:10BC400001A1000101210004000100050000012103 ++:10BC500000840004A1210004000100200005002050 ++:10BC6000000800C1011001A188C1A185894100001F ++:10BC7000000000000000018900C0018303040000EF ++:10BC800000000000000000000000000000000100B3 ++:10BC900001010001000000000000000000000000A1 ++:10BCA00000002000208800000000000100000000CB ++:10BCB00000400000000001880140000000000188F1 ++:10BCC0000190010100000388038808000220004061 ++:10BCD000912090009101414008010200C000200421 ++:10BCE000020188008400A04085028501410104888A ++:10BCF00000000003000100000103048200000300B3 ++:10BD00000000000000000000000000000000000033 ++:10BD100020002005092102000000000000000000B2 ++:10BD200000050000000080800000000300100000FB ++:10BD30000000002000000000038004000303000056 ++:10BD4000038004002020000083850400801180808F ++:10BD5000000008A0102040084080802080020000E1 ++:10BD60008000000380008000000089000540090277 ++:10BD7000418000000020001000002083A12100006D ++:10BD8000890000000000000000000000000000002A ++:10BD9000000000820000C20000000000000000005F ++:10BDA0000000000000810000000000000000000012 ++:10BDB000000000420008C100000000880022C1000D ++:10BDC000000000820000C100000000820013C100DA ++:10BDD0000000000000000081C20000000000000020 ++:10BDE000E00006000000001300000A6000000013DD ++:10BDF000C200060000000000C200000000000013A6 ++:10BE0000C20006000000000000000000000000006A ++:10BE100000004100FFFFFFFF3000000000000000B5 ++:10BE20000000000000000000000000000000000012 ++:10BE3000000000000000000000000000000000F012 ++:10BE400000005500000000F000000F00000000009E ++:10BE5000000000C300000E0E0000000003030000FD ++:10BE600000007FFFFFFF0000000000C33CFF0A3E10 ++:10BE7000A0BC0300FFFF000000000000000000283D ++:10BE800000000000000000000000000000000000B2 ++:10BE9000000000000000BEBEF0FF300030000000D7 ++:10BEA0000000000000000000000000000000000092 ++:10BEB0000000BEBC3CBC0000000000000000000010 ++:10BEC00000F000005500000000F000000F0000002E ++:10BED00000FF000000C30000000F0000010001008F ++:10BEE000000000007FFFFFFF00000000171717177A ++:10BEF000003C003C030003000000000000000000C4 ++:10BF0000000000000001000100000000000000002F ++:10BF10000008000000000000FF55787800040000D1 ++:10BF20000000000000000000000000000000000011 ++:10BF3000000000000FFF0FBF00000000555500007B ++:10BF40000F000000000000000F00000000000000D3 ++:10BF5000000000000F0F00000000FCFCFCF8FF3C9C ++:10BF6000FF3A000005015555550004A004000000EB ++:10BF70000000FFC33C00F0F0FF00000000000000E4 ++:10BF80005000000050000000800000000000000091 ++:10BF900000000000041000000000AA0078780000F3 ++:10BFA0000000000000000000000000000000000091 ++:10BFB0000000000000000FFF0F8F0000000055552B ++:10BFC00000000F000000FF0000000F000000FF0055 ++:10BFD0000000FF000000000000000000F0F0F0F89A ++:10BFE000FF00FF00000004005555550000A10100AE ++:10BFF00000000000FAD27850B4B4BE140000000073 ++:10C0000000000000000000000000800000000000B0 ++:10C0100000000000000000000000000000000A0412 ++:10C02000080000000000000000000000008600E0A2 ++:10C03000008000000086006000B00080008600756F ++:10C0400000B00803C0C7C07530B04903C0C7C07492 ++:10C0500030B04903C0C7C0F43080430300000186FC ++:10C06000006008B0000000865260A8B0008500861D ++:10C0700000210090000000860021089000000000D0 ++:10C08000001008000000008600F108800000000099 ++:10C0900000000000000000000000000000000000A0 ++:10C0A0000000000000000000000000000000F3F3AA ++:10C0B000F3F3A0A028A000000000FFFFFFFF000096 ++:10C0C0000000000008000000000000000000000068 ++:10C0D0000000FF00FF00A566665A00000000000097 ++:10C0E000DFFFFFFFFFFFFFFF00C382823CC3C33CB3 ++:10C0F000753030300505FFFFFFFF3C7800FFD5FFAE ++:10C100000000000000000000000000003C3C7C7CBF ++:10C11000000000800100000000000008080000008E ++:10C12000000000000000000000000000000000000F ++:10C13000F3F3F3F30000280000000000F0F3000325 ++:10C14000000000000000080000000000000000A047 ++:10C1500000000000FF00FF00A566665A00002020D6 ++:10C160000000FFFFFFFFBE5FFFFF00C380803CC3F6 ++:10C170003CC3307530301405FFFFFFFF000000FFA7 ++:10C1800015FF00000000000000003C003C000A0F0A ++:10C190005A5F0000002000000000000000000000C6 ++:10C1A000010000000000000000000000000000008E ++:10C1B000000000000000F000F60000000000000099 ++:10C1C000000000000000000000000000000000006F ++:10C1D000000000000000000000000000000000005F ++:10C1E000000000000000000003C3C3C30000000003 ++:10C1F0001000000000000000417D00FF810082006F ++:10C200000905000000000000000000000000000020 ++:10C210003CFF3FFF000000000000020000000000A3 ++:10C22000000000000000000000000000000000000E ++:10C2300000000000000000000000060000000000F8 ++:10C2400000000000000000000000000000000000EE ++:10C2500000000000000000000000000000000000DE ++:10C260000000500000000000000003C2C3C3000033 ++:10C27000000000000000000000004D4D0F0F820084 ++:10C28000820009050000000000000000000000001E ++:10C29000000000C30FCF40000000000000000000BD ++:10C2A0000000000000002100200011000000040038 ++:10C2B000200020000000000020000000000000001E ++:10C2C000000004000004200011000400200004000D ++:10C2D000200004000000009020000000000020006A ++:10C2E000000000000000000000000000000000004E ++:10C2F0000000210004000000000000000088000091 ++:10C30000000000000000000000000000000000002D ++:10C31000000000000000000000000000000000001D ++:10C3200000000000000000000000C000000000004D ++:10C330000000000000002000A0000000000000003D ++:10C3400000000000000000000000000000000000ED ++:10C35000000000000000000090000000200000002D ++:10C360000000000000009000000000000400000039 ++:10C37000900000000000000000000000000000002D ++:10C3800000000000000000000000000000000000AD ++:10C39000000000000000000000000000000000009D ++:10C3A00000000000000000000000FFFFFFFFFFFF93 ++:10C3B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10C3C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D ++:10C3D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D ++:10C3E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D ++:10C3F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D ++:10C40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10C41000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10C42000FFFFFFFFFFFFFFFFFFFFFFFF0054B41CF4 ++:10C430000C44007000C00A060000405100000000DB ++:10C4400000000000000000000000000000000000EC ++:10C450000010001000100010001000100003000079 ++:10C4600000000000000000000000000000000021AB ++:10C47000004100080011001100110011000000002F ++:10C4800000000000000000000000000000000000AC ++:10C49000000000000000000000000000000000009C ++:10C4A000000000000000000000000000000000008C ++:10C4B000000000000000000000000000000000007C ++:10C4C00000000000410005000000410041000000A4 ++:10C4D000050000004100000041000400410041004F ++:10C4E00010004100410000001000000009000000A1 ++:10C4F00010000000050000000000410041000000A5 ++:10C50000000000C005002100000000001100000034 ++:10C5100000000000000000000000000000004100DA ++:10C52000000000000000000000000000000000000B ++:10C5300000000000000000000000000000000000FB ++:10C5400000100000000000001000000010000000BB ++:10C55000000000001000100000000000C0000000FB ++:10C5600000000000000000000000000000000000CB ++:10C57000000000000000C0008200000088000000F1 ++:10C580000000100000000200C000C0008200C000D7 ++:10C59000C00000001000C0200000100000000000DB ++:10C5A000000000000000000000000000000010007B ++:10C5B00000000000840000000000000000000000F7 ++:10C5C00000000000000000004000000010004100DA ++:10C5D0002000020005002000200000000000009064 ++:10C5E0000000200000000000020000000000200009 ++:10C5F00020020000000000002000030000001000E6 ++:10C600004120000000000000210010000000000098 ++:10C61000000020000000009000900000009000004A ++:10C620000000000000000002000000000000000008 ++:10C6300005000000000000000000000000000000F5 ++:10C6400000000000000000000000000000000000EA ++:10C6500000000000000000000000000000000000DA ++:10C66000C00000000000C000000020000009000021 ++:10C67000000000000000200000000000000000009A ++:10C680004004400800000011000084000000C000C9 ++:10C690001000000002110000000000000000200453 ++:10C6A000000000000000000000000000000000008A ++:10C6B000000000000000000000000000000000007A ++:10C6C000000000000000000000000000000000006A ++:10C6D000000000000000000000000000000000005A ++:10C6E000000000000000000000000000000000004A ++:10C6F0000000000000000000100000000500000025 ++:10C700000000000000000000000000001000000019 ++:10C710000002000000000000000000000000000017 ++:10C720000000000000000000000000000000000009 ++:10C7300000000000000000000000000000000000F9 ++:10C7400000000000000000000000C0001000C00059 ++:10C750000000000000210000000010100000000098 ++:10C760000000100000001000100000000008000091 ++:10C7700010000000000000000000000000000000A9 ++:10C7800000200000820000210000100000000000D6 ++:10C790008403080010000800080084000000C000A6 ++:10C7A00002000000000000088400000000000000FB ++:10C7B0000000000000000000000000000000000079 ++:10C7C000000000000000C000000011000000000098 ++:10C7D0000000000040000000000000000000000811 ++:10C7E0000000000000000000000000000000000049 ++:10C7F0000000000000000000200000000000000019 ++:10C800000000000000002000040000000000000004 ++:10C8100000000040100000000000000000000000C8 ++:10C8200000004100000000000000000000000000C7 ++:10C8300002000000000010000000000000000000E6 ++:10C8400000000000000000000000000000000000E8 ++:10C8500000000000000000000000000010000000C8 ++:10C860000002000000000000000000001000200096 ++:10C87000000000000000100088000000C000040458 ++:10C880000000044000030003000300030000000058 ++:10C8900000000000200000000000000090000000E8 ++:10C8A0000000000004000000000000000040002024 ++:10C8B0000000000000000000000000000000000078 ++:10C8C0000000000000000000000000000000FFFF6A ++:10C8D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:10C8E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 ++:10C8F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48 ++:10C90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 ++:10C91000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 ++:10C92000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17 ++:10C93000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 ++:10C94000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 ++:10C9500000500F080C4400F000000A0600006018A8 ++:10C96000000004000000410000000000000000087A ++:10C9700004000000000000000000000000000000B3 ++:10C98000000000000000034000008020000000A024 ++:10C99000040000000000800008000000000000000B ++:10C9A00000400000000180010405000000000000BC ++:10C9B0000000000100000001000000000000000075 ++:10C9C0000020000000000000000000000000000047 ++:10C9D0000000000000000000000000000000000057 ++:10C9E0000000000000000000000000000000000047 ++:10C9F0000000000000000000000000000000000037 ++:10CA0000000000000000A000008000000480000082 ++:10CA10000000000000000000020001000000000013 ++:10CA2000000000000000000202400084000000003E ++:10CA300000000000002000000010000000000000C6 ++:10CA400000000000000000000000000000000000E6 ++:10CA500000000000000000000000000000000000D6 ++:10CA600000000000000000000000000000000000C6 ++:10CA700000000008000000000002000000000000AC ++:10CA800000010000000000000000000000000000A5 ++:10CA90000000000000000000000000000000000096 ++:10CAA0000000000000800000000000000000000006 ++:10CAB0000000000000000000000000000000000076 ++:10CAC0000000000000000000000000000000000066 ++:10CAD0000000000000000000000000000000000056 ++:10CAE0000000000000000000000000000000000046 ++:10CAF0000000000000000000001000000010000016 ++:10CB000000000020001000000000000000000000F5 ++:10CB10000000000000000000000800000008000005 ++:10CB20000000000000030000000000000000000002 ++:10CB300000000000000000000000000000000000F5 ++:10CB400000000000000000000000000000000000E5 ++:10CB500000000000000000000000000000000000D5 ++:10CB60000000000000000000210000C0000000A044 ++:10CB70000000000010900004000000000000000011 ++:10CB800000000000000000000000000100000000A4 ++:10CB90000000000000000000000000000200000093 ++:10CBA00000000800800080400000000000A003009A ++:10CBB000000800002100000021000000000000002B ++:10CBC00009001088000000000000000000020000C2 ++:10CBD0000000000000000000000000000000000055 ++:10CBE0000000000000000000000000000000000045 ++:10CBF00000000000000000000080000000000000B5 ++:10CC000000000000000000000000000000400000E4 ++:10CC10000000000000000000000000000000010013 ++:10CC200000000000010002410200000000000000BE ++:10CC300000000000000000000000000000000000F4 ++:10CC40000000000000000000000000000000008064 ++:10CC500000000000000000000000000000000000D4 ++:10CC60000000000000000000000000000000410083 ++:10CC70001000000080009000000010000000000084 ++:10CC8000000009000000000000001001000000008A ++:10CC90000000000000000000000000000000040090 ++:10CCA0000000000000000200000000000000000082 ++:10CCB00000000000800000000000000000000000F4 ++:10CCC0000000090008000800000000000300000048 ++:10CCD0000000000010000000000000000000000044 ++:10CCE00000000000000000000000000000008400C0 ++:10CCF00000000000000004001100C000000004005B ++:10CD00000000000090000000000000000020000073 ++:10CD10000000000000000000000000000000000013 ++:10CD20000000000000030000000000000000000000 ++:10CD300000000000000020000000000000000000D3 ++:10CD400000000200040001000109000000000000D2 ++:10CD500000000009000000000000000000000000CA ++:10CD600000000000000000000000000000000000C3 ++:10CD700000004100100000C000040000000400009A ++:10CD8000000000002100040000000300000000007B ++:10CD90000000100000001000000000000000004132 ++:10CDA0000000000000000000000000000001020080 ++:10CDB000000000004108000000000000A0A00004E6 ++:10CDC000000010000400000002A0050000000000A8 ++:10CDD0000488004000000000000200000000000085 ++:10CDE0000000000000000000000000000000000043 ++:10CDF0000000000000000000000000800000008033 ++:10CE00000000000000000000010000000000000021 ++:10CE10000000000000000000000000000000000012 ++:10CE2000008400000000000000000000000000403E ++:10CE300001000040000000000000000000001100A0 ++:10CE40000080000000000100000001000000000060 ++:10CE500000000100008000000000008000000000D1 ++:10CE600000000000000000000000000000000000C2 ++:10CE70000000000010004100100041A0030041002C ++:10CE80004100000800000000050000000000000054 ++:10CE900000208000000000000400040000000000EA ++:10CEA000000400000002000000000000000002007A ++:10CEB00000000004000000000000000080000001ED ++:10CEC000C0A080408004A0200020000000A000003E ++:10CED00008C0000000020002000000020000000084 ++:10CEE00000000000410000000000000041000000C0 ++:10CEF0000000000000000000000000000000000032 ++:10CF000000002000840084000000C0000000000039 ++:10CF100082000080200000000000000001000000EE ++:10CF20000000000000000000000000000000000001 ++:10CF30000000000040000000000000000040204011 ++:10CF4000002005000800088005C000000020004007 ++:10CF500000000100000000000080000000800000D0 ++:10CF600000000000000000000000000000000000C1 ++:10CF700000000000000000000000000000000000B1 ++:10CF80008202000221A000820000000002000000D6 ++:10CF900000000000090000000000800041000000C7 ++:10CFA000000080004000000080000000050010002C ++:10CFB00000008000030000000000000000000000EE ++:10CFC000000000C0108280C10041008310008580F5 ++:10CFD00000808083000000800000008300A000002B ++:10CFE0000000000000000000000000000000000041 ++:10CFF0000000000000000000000000000000000031 ++:10D00000000009C002020311000800000200A00095 ++:10D01000000000000200A0000000000082000000EC ++:10D0200000000000040001000000900084000100E6 ++:10D0300001000000C000000000000000000000002F ++:10D04000000090000083012090100091008389A0CF ++:10D05000C090008488838800889000000009000345 ++:10D06000000200C0000000000000000000000000FE ++:10D0700000000000000000000000000000000000B0 ++:10D08000000000008801A08405880801000000005D ++:10D090000000000008008400C0000088000020009C ++:10D0A0004000048200000000000000A004002000F6 ++:10D0B0000000840040002000020082000000820086 ++:10D0C000A000049089008900A000200020009000AA ++:10D0D0000000A1008385000100849100830000000E ++:10D0E000000000000100000000000000000000003F ++:10D0F0000000000000A000000000000000A00000F0 ++:10D100000000000000000940020020918909000091 ++:10D110000000000000008000800000000082000588 ++:10D12000800080008080000000000000002180005E ++:10D1300080000000800000000000800080210000CE ++:10D140000900110080000300100980118000801088 ++:10D150008000000089008385001100000900830021 ++:10D1600000000000000003000000000000000000BC ++:10D1700004000000000000000000000000000000AB ++:10D18000000000000000000020090011000089914B ++:10D19000000000000000000000000080008000008F ++:10D1A000008000004180000000000080210000801D ++:10D1B0000082002103A000830080000005000080A1 ++:10D1C0000000000000000000000021000000C1007D ++:10D1D00003008091000000004083020000099100DC ++:10D1E0008083000080400000000300000000000079 ++:10D1F000000000000000000000000000000000002F ++:10D200000000000000000000000001C000A082003B ++:10D210008809000400A0009000000004000800102D ++:10D2200000C000040084008402C00090004000A000 ++:10D230000040000300400004000500020082018855 ++:10D240000882000000000000000000004000000014 ++:10D250008500010010890008008201410190C0C1D1 ++:10D26000A10090830000080182000001000000007E ++:10D2700000000000000000000000000000000000AE ++:10D2800000000000000000000000000088C105034D ++:10D29000A00105000000000000000000C000080020 ++:10D2A00000000004888882008400C0040000880018 ++:10D2B000020040000000000000000090000100009B ++:10D2C00000000002000000000001000000208301B7 ++:10D2D0002010840090C083204090010090C0010184 ++:10D2E000C090000000C001400000000000000000ED ++:10D2F000000000000000000000000000000000002E ++:10D30000000000000000000000000000000091404C ++:10D3100009200021110000000000000000000002B0 ++:10D32000800000000000002000008000008000005D ++:10D330008000000000000003000000000000000367 ++:10D340000000000000800000000200110011000039 ++:10D350008809808091000000830000801100808097 ++:10D360000303008000000080038000000002020030 ++:10D3700000000000000000000000000000000000AD ++:10D38000000000000000000000000000000000009D ++:10D3900000000013C20000000000001300000000A5 ++:10D3A00000000013C200000000000013000042480B ++:10D3B0000000001344000000000000000000000016 ++:10D3C0000000000000002100000000000000E0005C ++:10D3D000000000000207E000005000000081810012 ++:10D3E00000000000008100000600000000000000B6 ++:10D3F000000000000000000000000000000000002D ++:10D40000000000000000000000000000000000001C ++:10D410000000BD817E4266663333000000000000DC ++:10D4200000000000000000000000000000000000FC ++:10D430000000000000000000000000000000F333C6 ++:10D44000CC0F000000000000000000000000000001 ++:10D4500000000000FFFF0F0F000000000F0F000092 ++:10D460003C3C0000FFFF00000F0F00003C3C0000B0 ++:10D470000F0F00000000000000000000000000008E ++:10D48000000000000000000000000000000000009C ++:10D4900000000000FFC33C0066663333000000005C ++:10D4A000000000000000000000000000000000007C ++:10D4B000000000000000000000000000000000006C ++:10D4C0000F0F0FF00000000000000000000000003F ++:10D4D000000000000000FFFF0F0F000000000F0F12 ++:10D4E00000003C3C0000000000000F0F00003C3C2E ++:10D4F00000000F0F0000000000000000000000000E ++:10D500000000000000000000000000000000FFFF1D ++:10D51000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10D52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10D53000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:10D54000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB ++:10D55000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB ++:10D56000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB ++:10D57000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:10D58000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB ++:10D5900000085EBC0C4400F000180A06000090E78A ++:10D5A0000000000000000000FBFFF9FFFFFFFBFF91 ++:10D5B000000000000000000000000000000000006B ++:10D5C000000000000000000000000000000000005B ++:10D5D000000000000000000000000000000000004B ++:10D5E000000000000000FFFFC3C3BEFE41013C3C41 ++:10D5F0003C3C00006666000000FF0000FFFF0000EA ++:10D6000000FF000000FFFFFF00000000000000001E ++:10D61000000000000000000000000000000000000A ++:10D6200000000000000000000000FFFFFDFF000000 ++:10D6300002000000000000000000000000000000E8 ++:10D6400000000000000000000000000000000000DA ++:10D6500000000000000000000000000000000000CA ++:10D660000000000000000000060600006066FF9950 ++:10D670003C3C3C3C00006666000000FF00000000EF ++:10D68000000000FF000000FFFFFFFFFF00000000A0 ++:10D69000000000000000000000000000000000008A ++:10D6A0000000000000000000000000000086029161 ++:10D6B00008800000008600E100900000008600E184 ++:10D6C000008000050086006100B000000086002098 ++:10D6D00008B000050086006000B900000086006008 ++:10D6E00000B0000000000086006000B00010A1A0A3 ++:10D6F0005080A8B00845A249018100A449400245D4 ++:10D7000001810004494002C7016000B441400000AB ++:10D710000000000000000000000009000000000000 ++:10D7200000000800000000000000000000000008E9 ++:10D7300000000000000000000000002000200000A9 ++:10D7400000003D3D3C3C03050F0FF700F200C0C058 ++:10D75000C0C0D2825000000000004DBE4DB200009B ++:10D760000000005500100000000000000000000054 ++:10D7700082800080000000003C3CFF0000000000B0 ++:10D78000AA00AA000F0F0C0C00000000000000000F ++:10D790000000000000000000000000200000010068 ++:10D7A0000000000000000100000000000000000078 ++:10D7B000000800000000010100000000000000005F ++:10D7C000FF0000000505AAFF00050F0FF700F70096 ++:10D7D000C300C30000000000000000007D8E7D82B9 ++:10D7E0000000000000000000000000000000000039 ++:10D7F0000000828000800000000000000000002087 ++:10D800000028AA00AA0000000C0C00000000000084 ++:10D8100000000000000000000000004000000000C8 ++:10D8200002000040000000000000000000000000B6 ++:10D8300000000000000000000000000000000000E8 ++:10D8400000000000000005FF05FF000000000000D0 ++:10D8500000000000000000000000000000002B2B72 ++:10D86000E8E8000000000000FFEB000000000000FE ++:10D87000FA92FA00FF3F3F3FFFFFFFFF3C003030CE ++:10D88000003C0055A0A0AAAA00FF5555FFFFFDFCD3 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000000000000078 ++:10D8B000000000000030000000000C00000000002C ++:10D8C00000000000000000003D3D3D3D0000000064 ++:10D8D0000000050000000000000000000000000043 ++:10D8E0001717D4D4000000000C09FFEB0000000063 ++:10D8F0000000156D15FFFFFF3FFF7FFFFFFF3C009E ++:10D900003030003C0055A0A0000000000000FFFFE8 ++:10D91000FFFF000000000000000000000000000009 ++:10D9200000000000000000000000000000000400F3 ++:10D9300000000000040000000000000000000000E3 ++:10D940000000000000004000200020002000040033 ++:10D9500000000000040011000000110000010000A0 ++:10D96000000000000000800100018001800000C074 ++:10D97000040000000000040004000000000000009B ++:10D980000000000000000000000400000000000093 ++:10D990000000000000000000000000000000000087 ++:10D9A0000000000000000000000000000000000077 ++:10D9B0000000000000000000000000000000000067 ++:10D9C0000000000000000000000001000100010054 ++:10D9D000000000000000000000000000000000083F ++:10D9E00000000000000000004002000220042000AF ++:10D9F0000000000000000000000000000000000027 ++:10DA00000000000000000000000000800000000096 ++:10DA10000000000000000000000000000000000006 ++:10DA200000000000000000000000000000000000F6 ++:10DA300000000000000000000000000000000000E6 ++:10DA400000000000000000000000000000000000D6 ++:10DA500000000000000000000000000000000000C6 ++:10DA600000000000000000000000000000000000B6 ++:10DA7000000000C0000000000000000000000000E6 ++:10DA80000000000000000000000000000000000096 ++:10DA90000000000000000000000000000000000086 ++:10DAA0000000000000000000000000010000000075 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000001000000000000000100000000036 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000200000000000000100000000024 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000000000000000000000000000010000005 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000100000E5 ++:10DB30000000000000000000000000000084000061 ++:10DB40000000800000C0800000040002008200008D ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB70004000000000000000000080002000800045 ++:10DB8000000000000000000000020000000404206B ++:10DB90000000000000000000000000000000000085 ++:10DBA0000000000000000000000000000000000075 ++:10DBB000000000000000000000000000C0000000A5 ++:10DBC000C000000040000000040000800080000051 ++:10DBD00084000000000010000000000000000000B1 ++:10DBE0000000000000000000000000000000000035 ++:10DBF0000000010000000000000000002000010003 ++:10DC000020050000000000000000008000000080EF ++:10DC10000180000000030000000000000000000080 ++:10DC200000001000000000000000000000000000E4 ++:10DC3000000000000000000000000500000041009E ++:10DC40000000200009002000200005000000002046 ++:10DC50000000900000001000000000000000000024 ++:10DC60000000000000000000002000000000000094 ++:10DC70000000000010001000100000000000000074 ++:10DC8000000000002000000000000004110000005F ++:10DC9000050000000000000000000000000000007F ++:10DCA0004100000000000000000000000000000033 ++:10DCB0000000000000000000000000000000000064 ++:10DCC0000000000001000000010001000000000051 ++:10DCD00000800000200000000000000000000000A4 ++:10DCE00000000000000000000000008000000000B4 ++:10DCF0000000000000000000000000000000000024 ++:10DD00000000000000000100000200000080000090 ++:10DD10000000000000000000000000000000000003 ++:10DD200000000000000000000000000000000000F3 ++:10DD300000000000000000000000000000000000E3 ++:10DD4000000000004100400040010001C00003004D ++:10DD5000040003040300000800000000800100002C ++:10DD600000000900000000000000000000000000AA ++:10DD70000000000000001000000000000000000093 ++:10DD8000000000010000830000004101000584A1A3 ++:10DD9000000000010000040100000000000000007D ++:10DDA0000000000000000000000000000000000073 ++:10DDB0000000000000000000000000000000000063 ++:10DDC000000000000000000001000104C004212147 ++:10DDD00000000100008000008480820000004040BC ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000100000042100000004008455 ++:10DE100005200000000800000140C00000000000D4 ++:10DE20000000C00000000000100000000000000022 ++:10DE300000000000000000000000000000000000E2 ++:10DE40000000020041840084050020002000200022 ++:10DE50002000100005000000050400000000000282 ++:10DE60000040000000000000000000000000000072 ++:10DE70008000000000000000000010000000000012 ++:10DE80000000000000000000090000000000000089 ++:10DE9000109000200002000004040004002000A0F4 ++:10DEA0000000000010000020000000000000000042 ++:10DEB0000000000000000000000000000000000062 ++:10DEC0000000000000000000000000000100010050 ++:10DED00001000100010000000000008000000000BF ++:10DEE0000080008000000000000000000000000032 ++:10DEF0000000100000000000000000000000000012 ++:10DF00000000000000000000000000000000000011 ++:10DF10000000000000800080000000800080000001 ++:10DF2000000000000000000000000000000084006D ++:10DF300000000000000000000000000000000000E1 ++:10DF400000000000000000000000000000000000D1 ++:10DF5000000000400000400509C19140401000054C ++:10DF6000004002050040000000000000000000002A ++:10DF700000008000200000000000000000001100F0 ++:10DF80000000000009000000031100090010030058 ++:10DF900008038009050541411100800021000905A1 ++:10DFA0000000000000000000000000000000000071 ++:10DFB0000000000000000000000000000000000061 ++:10DFC0000000000000000000000000000000000051 ++:10DFD0000000000000010000C10301044101012113 ++:10DFE0000001A0010000000100000000000000008E ++:10DFF000000000008400000000000000000000009D ++:10E000000100000000000100000001008801000183 ++:10E0100000000101040100000000010020000000D8 ++:10E0200001000000000000000000000000000000EF ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E050000000000000010000000102000540030173 ++:10E0600005C00000000000000000000000000000EB ++:10E070000000010101008988829100000000000079 ++:10E08000000000000000010001010000000000008D ++:10E090000100010100000008010101010000000071 ++:10E0A00000C001000000004000C0000000000000AF ++:10E0B000000000000000000000000000010000005F ++:10E0C000000200000000000000000000000000004E ++:10E0D0000000000000000003000000204102A080BA ++:10E0E0002002A080000000020002004100000000A9 ++:10E0F00000000000110241008980A1910000000091 ++:10E1000000000000000000002100030900000000E2 ++:10E1100003002100030905000080212003090000FD ++:10E120000000000009000000008000410000000025 ++:10E1300000000000000000000000000000000200DD ++:10E1400000000000000000000000000000000000CF ++:10E15000000000000000000000020200000000209B ++:10E1600080C10910C0898500000021000300000063 ++:10E170000000000000000002001121008083000068 ++:10E1800000000000000000020011210980030000CF ++:10E190000300000209100083000000820205400312 ++:10E1A00000000080000980830000000000000000E3 ++:10E1B000000000000000000000000000000000005F ++:10E1C000000000000000000000000000000000004F ++:10E1D0000000000000000000A0000000010000009E ++:10E1E0000003C00403030504400200C000C001A0F6 ++:10E1F0000000000000000000000100000100208974 ++:10E2000000000000000000000001000101012001E9 ++:10E2100000000140000101410083009000030090D4 ++:10E220000391002000020083900300000000000022 ++:10E2300000000000000000000000000000000000DE ++:10E2400000000000000000000000000000000000CE ++:10E25000000000000000000000000040010000007D ++:10E26000000005A1030405010100010001000000F8 ++:10E270000000000000000000000082918489C001BD ++:10E28000888800000000000000000000000100017C ++:10E290000000000000A0008400010000018800C10F ++:10E2A0000101000000900000000000000088010053 ++:10E2B000010000000000000000000000000000005D ++:10E2C000000000000000000000000000000000004E ++:10E2D000000000000000000000000000008020009E ++:10E2E0000002000083020841C00209000300200070 ++:10E2F0000200020000000000000000008091008980 ++:10E30000800280800000000000000000000000117A ++:10E310000021000000000000000500100000038044 ++:10E3200005410220000000000000000000002180E4 ++:10E3300004002000000000000000000000000000B9 ++:10E3400000000000000000000000000000000000CD ++:10E3500000000000000000000000000000000000BD ++:10E360000000C2000A0000000013C200000000000C ++:10E370000000E00000600000000000000000060057 ++:10E380000007000000000000000000000000000086 ++:10E39000000001000000000000000007E0000A008B ++:10E3A00000000007E000000000880004E00000001A ++:10E3B00000880000C2000000000000000000000013 ++:10E3C000000000000000000000000000000000004D ++:10E3D000000000000000000000000000000000003D ++:10E3E00000FF00000F0F00003C3C0000E0F0EFFFDA ++:10E3F000FFFAFFFB0000000000000000000000002A ++:10E4000000000000FFFF000000000000000000000E ++:10E41000000000007D7E3FFC0000000000000505BC ++:10E42000AFFA0505AFFA555555AA00000000AAAA93 ++:10E4300055AA00FF00FF00000000000000000000DF ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E46000000000FF00000F0F0000AA55050010007B ++:10E470001F0FFFFAFFFB000000000000000000007B ++:10E48000000000000000F0F03C3C00000000000034 ++:10E490000000000000007D7D3CFF00000000000047 ++:10E4A000050505500505055000000F0F0000000090 ++:10E4B000555500FF50500000000000000000000013 ++:10E4C000000000000000000000000000000000004C ++:10E4D000000000000000000000000000000000003C ++:10E4E000000000000000F0F00000FFFFAF3FAA3086 ++:10E4F0002D7D7D7DF0F0D0F00000000000000000D8 ++:10E50000000000000000000080000000000000008B ++:10E510000000000000000000FFFFFFFF00000FF000 ++:10E520000FF050FAAA008EB23C00C33CFF00C3C3F8 ++:10E53000C3C30000FFFF0000000000000000000057 ++:10E5400000000000000000000000000000000000CB ++:10E5500000000000000000000000000000000000BB ++:10E560000000000000000000F0F000000000AF3FDD ++:10E57000AA3078282828F0F0F0F000000000000011 ++:10E58000000000000000000000000000000000008B ++:10E590000000000000000000000055AA55550000D2 ++:10E5A000FFFF0000FA50AA008EB23C00AAAA0000A9 ++:10E5B000C3C3C3C30000FFFF000000000000000051 ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E0000000000000000000A8005400A002001578 ++:10E5F0000886009108800000A5865260A0B0000542 ++:10E600000000000000000000000200A003890000DC ++:10E6100000000000000000000000000000020010E8 ++:10E6200000000086C07130104903C0C7C07130902F ++:10E6300041030086026C00B20400000000040800E0 ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E6600000000000000000000000000000000000AA ++:10E670000000000000A00000100000000000FFFFEC ++:10E68000FFFB0000000000000000D8F0D7FFFFFFF4 ++:10E69000000000000000000000000000000000007A ++:10E6A0000000000000000000C3003C00000000006B ++:10E6B000000088440000000000000000000000008E ++:10E6C000000000000000000000000000000000004A ++:10E6D00000000000000000800100000000000000B9 ++:10E6E000000000000000000000000000000000002A ++:10E6F000000000000000000000001000000000000A ++:10E70000FFFFFFFF0000000000000000F0F0280005 ++:10E71000FFFF0000000000000000000000000000FB ++:10E7200000000000000000000000000000000000E9 ++:10E7300000008844000000000000004000000000CD ++:10E7400000000000000000000000000000000000C9 ++:10E750000000000000000000002000000000000099 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000003000000069 ++:10E780000000000000000000000000000000000089 ++:10E790000000AAAA55AA0000000000000000000026 ++:10E7A0000000000000000000000000000000000069 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000020037 ++:10E7E0000000000000000000000000000000000029 ++:10E7F00000000000000000000028000000000000F1 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000555500FF00000000000000004F ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000000000000000000000000000000D8 ++:10E8400000000000000000000000000000000000C8 ++:10E850000000000000000000000040000000000078 ++:10E8600000000000000000000000000000000000A8 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000021000000000067 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D00000000000000000000000004000000000F8 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000000000000000000018 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000000000000000000000000000000D7 ++:10E9400000000000000000000000000000000000C7 ++:10E950000000000000000000000000000080000037 ++:10E9600000000000000000000000000000000004A3 ++:10E97000AB220C85004004000400040004000400E5 ++:10E98000040004000400CC26000000000000000089 ++:10E990000C44008800F0CC260000000000000000BD ++:10E9A0000C44008800C00C8500800A06000080200E ++:10E9B000000000000008000000000000000000004F ++:10E9C0000000000000000000000000000000000047 ++:10E9D0000000000000000000000000000000000037 ++:10E9E0000000000000000000000000000000000027 ++:10E9F0000000000000000000000000000000000017 ++:10EA00000000000000000000000000000000000006 ++:10EA100000000000000000000000000000000000F6 ++:10EA200000000000000000000000000000000000E6 ++:10EA300000000000000000000000000000000000D6 ++:10EA400000000000000000000000000000000000C6 ++:10EA500000000000000000000000000000000000B6 ++:10EA600000000000000000000000000000000000A6 ++:10EA70000000000000000000000000000000000096 ++:10EA80000000020000000000000000000000000084 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000000000000000056 ++:10EAC000C000000000000000000000000000000086 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB3000000000000000FFFFFFFFFFFFFFFFFFFFDF ++:10EB4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5 ++:10EB5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5 ++:10EB6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 ++:10EB7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5 ++:10EB8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:10EB9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10EBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10EBB000FFFFFFFFFFFFFFFF00DCBD450C440088A7 ++:10EBC00000900A06000000C30000000000000000E2 ++:10EBD0000000000000000000000000000200000033 ++:10EBE0000000000000000000000000000021000004 ++:10EBF00000000000002000000000000000000000F5 ++:10EC00000000000000000000000000000003000001 ++:10EC10000000840000000000000000000000000070 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000090000000000000000004 ++:10EC80000000000000000000000000001000000074 ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000000000000000000000000000000064 ++:10ECB0000000000000000000000000000000000054 ++:10ECC000000000000000000000000000FFFFFFFF48 ++:10ECD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:10ECE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10ECF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 ++:10ED0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10ED1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:10ED2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3 ++:10ED3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3 ++:10ED4000FFFFFFFFFFFFFFFFFFFFFFFFFFFF008C45 ++:10ED50002A4E0C44008800700A06000000410000A2 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA0000000000000000000000000000000000063 ++:10EDB0000000000000000000000000000000000053 ++:10EDC000000000000000000000000000000000043F ++:10EDD0000000000000000000000000000000000033 ++:10EDE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:10EDF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10EE0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 ++:10EE1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:10EE2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:10EE3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10EE4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10EE5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:10EE6000FFFF00F422F60C44008800680A06000048 ++:10EE700000C30000000000000000000000000000CF ++:10EE80000000000000000000000000000000000082 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000010000012 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000000000000000000000000000000001 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF6000000000000002000000000000000000009F ++:10EF7000000000000000FFFFFFFFFFFFFFFFFFFF9B ++:10EF8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:10EF9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 ++:10EFA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 ++:10EFB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 ++:10EFC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 ++:10EFD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 ++:10EFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 ++:10EFF000FFFFFFFFFFFFFFFF00EC6D7E0C4400886A ++:10F0000000D80A06000040D3000000000000000005 ++:10F0100000000000000000000000000000000000F0 ++:10F0200000000000000000000000000000000000E0 ++:10F0300000000000000000000000000000000000D0 ++:10F0400000000000000000000000000000000000C0 ++:10F0500000000000000000000000000000000000B0 ++:10F0600000000000000000000000000000000000A0 ++:10F07000000000000000000001000000000000008F ++:10F080000000000000000000000000000000000080 ++:10F090000000000000000000000000000000000070 ++:10F0A0000000000000000000000000000000000060 ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D0000000000000000000000000000000000030 ++:10F0E0000000000000000000000000000000000020 ++:10F0F00000000000004000000000000000000000D0 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000000AF ++:10F16000000000000000000000000000000000009F ++:10F170000000000000000000001008000000000077 ++:10F180000000000000000000000000000000FFFF81 ++:10F19000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10F1A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F ++:10F1B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F ++:10F1C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F ++:10F1D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:10F1E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F ++:10F1F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F ++:10F20000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E ++:10F21000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE ++:10F22000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE ++:10F23000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE ++:10F24000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE ++:10F25000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE ++:10F26000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE ++:10F27000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10F28000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10F29000FFFF000000000000000000000000000070 ++:10F2A000000000000000000000000000000000005E ++:10F2B000000000000000000000000000000000004E ++:10F2C000000000000000000000000000000000003E ++:10F2D0000000000008000092400000000000000054 ++:10F2E000000000000000000000000000000000001E ++:10F2F000000000000000000000000000000000000E ++:10F3000000000000000000000000000000000000FD ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000000000000CD ++:10F3400000000000000000000000000000000000BD ++:10F350000000000000000440000100000000000068 ++:10F36000000000000000000000000000000000009D ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000000000004D ++:10F3C000000000000000000000000000000000003D ++:10F3D00000000000000000001020000410200000C9 ++:10F3E000000000000000000000000000000000001D ++:10F3F000000000000000000000000000000000000D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F440000000000000000000000000000000A1001B ++:10F4500000850000000000000000000000000081A6 ++:10F460008181A181A18581000000000000000000D1 ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C0000000000000000000000003000000000039 ++:10F4D000000000000000000000000000000000002C ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000020000000000E9 ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000000000000000000000000000007B ++:10F590000000000000000000000000000000003C2F ++:10F5A0003FA90C850040040004000400040004008E ++:10F5B000040004000400CC2600000000000000004D ++:10F5C0000C4480800090CC26000000000000000069 ++:10F5D0000C4480800030CC260000000000000000B9 ++:10F5E0000C4480800008CC260000000000000000D1 ++:10F5F0000C4480800088CC26000000000000000041 ++:10F600000C4480800048CC26000000000000000070 ++:10F610000C44808000C8CC260000000000000000E0 ++:10F620000C44808000A8CC260000000000000000F0 ++:10F630000C4480800098CC260000000000000000F0 ++:10F640000C4480800058CC26000000000000000020 ++:10F650000C44804000E8CC260000000000000000C0 ++:10F660000C44802000A8CC26000000000000000010 ++:10F670000C4480200068CC26000000000000000040 ++:10F680000C4480A000E8CC26000000000000000030 ++:10F690000C4480E00030CC26000000000000000098 ++:10F6A0000C4480E000B0CC26000000000000000008 ++:10F6B0000C4480E00070CC26000000000000000038 ++:10F6C0000C4480E000F0CC260000000000000000A8 ++:10F6D0000C4480E00008CC26000000000000000080 ++:10F6E0000C4480E00088CC260000000000000000F0 ++:10F6F0000C4480E00048CC26000000000000000020 ++:10F700000C4480E000C8CC2600000000000000008F ++:10F710000C4480E00028CC2600000000000000001F ++:10F720000C4480E000A8CC2600000000000000008F ++:10F730000C4480E00068CC260000000000000000BF ++:10F740000C4480E000E8CC2600000000000000002F ++:10F750000C44801000E8CC260000000000000000EF ++:10F760000C4480900078CC260000000000000000CF ++:10F770000C44807000A8CC260000000000000000AF ++:10F780000C4480700068CC260000000000000000DF ++:10F790000C4480F000E8CC260000000000000000CF ++:10F7A0000C4480880040CC260000000000000000CF ++:10F7B0000C44808800E0CC2600000000000000001F ++:10F7C0000C44808800D0CC2600000000000000001F ++:10F7D0000C4480880030CC260000000000000000AF ++:10F7E0000C44808800B0CC2600000000000000001F ++:10F7F0000C4480880008CC260000000000000000B7 ++:10F800000C4480880088CC26000000000000000026 ++:10F810000C4480880048CC26000000000000000056 ++:10F820000C44808800C8CC260000000000000000C6 ++:10F830000C4480880028CC26000000000000000056 ++:10F840000C44808800A8CC260000000000000000C6 ++:10F850000C4480880068CC260000000000000000F6 ++:10F860000C4480880018CC26000000000000000036 ++:10F870000C4480880098CC260000000000000000A6 ++:10F880000C4480880058CC260000000000000000D6 ++:10F890000C44808000400C8500800A060000401067 ++:10F8A00000000000000080000000000000000200D6 ++:10F8B00000000000008800000000000000000000C0 ++:10F8C0000000000000000000000000000000000038 ++:10F8D0000000000000000000000000000000000028 ++:10F8E00000004100000000000000000000000000D7 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000100000000000E7 ++:10F9100008000000000000000010000000000000CF ++:10F9200000000010000000000210000000000008AD ++:10F930000110001002000000001000000000000094 ++:10F940000010002100000000001000000000000076 ++:10F950000010001000000000002100000010000056 ++:10F960000021000000100000000000100000000056 ++:10F970000000001000210000000000000000001046 ++:10F98000000000210040A000000000410000000035 ++:10F990000000004100000000000000800000004066 ++:10F9A0000000001000000000000000000000000047 ++:10F9B000000000000000000000C000000000000087 ++:10F9C0000000000000000000000000000000000037 ++:10F9D0000000000000C00000000000000000000067 ++:10F9E00000000000000000000000000000A0000077 ++:10F9F00000000000004000000000000000000000C7 ++:10FA000000000000001000C0000000000000000026 ++:10FA10000000000000A00000000000000000000046 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000000000000000000C6 ++:10FA400000000000000000000000000000000000B6 ++:10FA500000000000000000000000000000000000A6 ++:10FA60000000000000000000000000000000000096 ++:10FA70000000000000000000000000000000000086 ++:10FA800000008800000000000000000000000000EE ++:10FA90000000000000000000000000000000000066 ++:10FAA0000000000000000000000000000000000056 ++:10FAB0000000000000000000000000000000000046 ++:10FAC0000000000000000000000000000000000036 ++:10FAD0000000000000000000000000000000000026 ++:10FAE0000000000000000000000000000000000016 ++:10FAF0000000000000000000000000000000000006 ++:10FB000000000000000000000000050000000000F0 ++:10FB100000000000000000000000000000000000E5 ++:10FB200000100000000000000000000000000000C5 ++:10FB300000000000000000000000000000000000C5 ++:10FB400000000000000000000000000000000000B5 ++:10FB500000000000000000000000000000000000A5 ++:10FB60000000000000000000000000000000000095 ++:10FB70000000000000000000000000000000000085 ++:10FB80000000000000000800080008000000080055 ++:10FB90000000000000000000000000020000000063 ++:10FBA0000000000000000000000000000000000055 ++:10FBB000000000000000000000000000090000A09C ++:10FBC0000000000000000010000003000010000012 ++:10FBD000030000000000030000000000030000001C ++:10FBE0000000000000000000000003100000000002 ++:10FBF00000000300000000000300000000001000EF ++:10FC000000000000000005000000000000000000EF ++:10FC100000000000030000000000000002100000CF ++:10FC20000088000000000000000000000000FFFF4E ++:10FC3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 ++:10FC4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4 ++:10FC5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 ++:10FC6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 ++:10FC7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 ++:10FC8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 ++:10FC9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:10FCA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:10FCB00000788FF60C44808000500A06000000C3D4 ++:10FCC0000000000000000000000000000000000034 ++:10FCD0000000000000000000000000C00000000064 ++:10FCE0000000000000000000000000000000000014 ++:10FCF0000000000000000000000000000000000004 ++:10FD000000000000000000000000000000000000F3 ++:10FD10000084030000000000000004000000000058 ++:10FD200000000000020000000000000000000000D1 ++:10FD300000000000000000000010000000000000B3 ++:10FD400000000010000000000000000000000000A3 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000000000000000000000000000000000093 ++:10FD70000000000000000000000000000000000083 ++:10FD80000000000000000000000000000000000073 ++:10FD900000000000000000000000A00000000000C3 ++:10FDA00000000000000008000000080000008400BF ++:10FDB00082410800000000008200000000000000F6 ++:10FDC00000000000FFFFFFFFFFFFFFFFFFFFFFFF3F ++:10FDD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:10FDE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10FDF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10FE0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:10FE1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:10FE2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10FE3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10FE4000FFFFFFFFFFFF002C08030C44808000B081 ++:10FE50000A060000802000000000000000000000F2 ++:10FE60000000000000000000000000000000000092 ++:10FE70000000000000000000000000000000000082 ++:10FE80000000000000000000000000000000000072 ++:10FE900000000000000000800000000000000000E2 ++:10FEA0000000000000000000000000000000000052 ++:10FEB0000000000000000000000000000000000042 ++:10FEC0000000000000000000000000000000000032 ++:10FED00000000000000000000000000000000040E2 ++:10FEE000000000000000008800000000000000008A ++:10FEF0000000000000000000000000000000000002 ++:10FF000000000000000000000000000000000000F1 ++:10FF100000000000000000000000000000000000E1 ++:10FF200000000000000000000000000000000000D1 ++:10FF3000000000000000000000C000000000000001 ++:10FF400000000000000000000000000000000000B1 ++:10FF500000000000000000000000000000000000A1 ++:10FF60000000000000000000000000000000000091 ++:10FF70000000000000000000000000000000000081 ++:10FF80000000000000000000000000000000000071 ++:10FF90000000000000000000000000000000000061 ++:10FFA0000000000000000000000000000000000051 ++:10FFB0000000000021000000000000000000000020 ++:10FFC000000000000000000000000000020000002F ++:10FFD000000000000000000000000000FFFFFFFF25 ++:10FFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 ++:10FFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 ++:020000040001F9 ++:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 ++:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ++:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00248A ++:10006000C1900C44808000280A0600000041000076 ++:100070000000000000000000000A00000000000076 ++:100080000000000000000000000000000000000070 ++:100090000000000000000000000000000000000060 ++:1000A0000000000000000000000000000000000050 ++:1000B0000000000000000000000000000000000040 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000000000000000000000000000020 ++:1000E0000000000000000000000000000000000010 ++:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ++:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF ++:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F ++:10017000FFFF00E4B7440C44808000680A060000DA ++:10018000802000000000000000000000000000804F ++:10019000000000000000000000000000000000005F ++:1001A000000000000000000000000000000000004F ++:1001B000000000000000000000000000000000003F ++:1001C000000000000000000000000000000000002F ++:1001D000000000000000000000000000000000001F ++:1001E000000000000000000000000000000000000F ++:1001F00000000000000000000000000000000000FF ++:1002000000000000000000000000000200000000EC ++:1002100000000002000000000000000000000000DC ++:1002200000000000000000000000000000000000CE ++:1002300000000000000000000000000000000000BE ++:1002400000000000000000000000000000000000AE ++:10025000000000000000000000000000000000009E ++:10026000000000000000000000000000000000008E ++:10027000000000000000400000000000000000003E ++:10028000000000000000000000000000000000006E ++:1002900000002040000000000000000000000000FE ++:1002A000000000000000000000000000000000004E ++:1002B000000000000000000000000000000000003E ++:1002C000000000000000000000000000000000002E ++:1002D000000000000000000000000000000000001E ++:1002E000000000000000000000000000000000000E ++:1002F00000000000000000000000000000000000FE ++:100300000000000000000000FFFFFFFFFFFFFFFFF5 ++:10031000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED ++:10032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD ++:10033000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD ++:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD ++:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD ++:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D ++:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10038000FFFFFFFFFFFFFFFFFFFF00087FB70C44E9 ++:10039000808000D80A06000060DB0000000000003A ++:1003A000010000000000000001000000000000004B ++:1003B000000000000000000000000000000000003D ++:1003C000000000000000000000000000000000002D ++:1003D000000000000000000000000000000000001D ++:1003E000000000000000000000000000000000000D ++:1003F00000000000000000200000010000000000DC ++:1004000000000000000000000000000000000020CC ++:10041000000000000000000000000000004000009C ++:10042000000000000040000000000000000000008C ++:1004300000000000000000000000000000000000BC ++:1004400000000000000000000000000000000000AC ++:10045000000000000000000000000000000000009C ++:10046000000000000000000000000000000000008C ++:10047000000000000000004000000000020000003A ++:10048000000000000000000000000000000000006C ++:10049000000000000200000000000000000000005A ++:1004A000001008000000000010100800000000000C ++:1004B000000000000000000000000000000000003C ++:1004C000000000000000000000000000000000002C ++:1004D000000000000000000000000000000000001C ++:1004E000000000000000000000000000000000000C ++:1004F00000000000000000000000000009000000F3 ++:1005000000000000000000000000000000000000EB ++:10051000000000800100000000000000000000005A ++:1005200004000200000000001100040004000400A8 ++:10053000040000000000200004000400002000006F ++:100540000000110000000000030000000300040090 ++:10055000000000000000040009000000000011007D ++:100560000000000004000000000000002000000067 ++:100570000800080000000000040000000200000065 ++:10058000000000000000000000000000000000006B ++:1005900002000000000000000000008400000000D5 ++:1005A000000000000000000000000000000000004B ++:1005B000000000000000000001000000000000003A ++:1005C000000000000000000000000000000000002B ++:1005D000000000000000000000000000000000001B ++:1005E000000000C000000100000000000000010049 ++:1005F00000000000000000000000000000000000FB ++:1006000000000000000000000000000000000000EA ++:1006100000000000000000000000000000000000DA ++:100620000000000011000000000000C0800100C0B8 ++:1006300000000000000004000000000000000000B6 ++:1006400000000000000000000000030000000000A7 ++:100650000000000000000000000000210800000071 ++:100660000000008800C000000000000080000000C2 ++:1006700080000000000000000000000000000000FA ++:10068000001000000000000040000000000000001A ++:100690000010000000000240024000000040000086 ++:1006A00000000000001000000000000000412004D5 ++:1006B000000002008210004101000010000900004B ++:1006C000004000000010000000000000901000003A ++:1006D00000000000004100000000004100A00000F8 ++:1006E000000000100010004000000000000020107A ++:1006F0000000200000210010000000210010000078 ++:1007000000400200001000100200910000000041B3 ++:10071000000000800020001004A10100004100A0A2 ++:1007200000000041001000400002000000880004AA ++:10073000000000000090000000C000000000000267 ++:100740000000000000000000000000A000400000C9 ++:100750000000000000C00084000000000000000055 ++:10076000004000840000004000000300000400007E ++:100770000000000000900000000200100084004013 ++:100780000001088800880020002000A000A00000D0 ++:100790000000000000880000000100000000009040 ++:1007A00000000000008400000000000000000000C5 ++:1007B00000800000000000000000000000000000B9 ++:1007C0000000000000000000000000000000000029 ++:1007D0000000080000000000000000000000000011 ++:1007E0000000000000000000000000000000000009 ++:1007F00000000000000000000000100000000000E9 ++:1008000000000008000000000000000000000000E0 ++:100810000000000000000000000000400000000098 ++:1008200000000004000000000000000000000000C4 ++:10083000000005A000000000800100100000100072 ++:100840000000040000000000100000010000000093 ++:10085000000080A021C09000210085C0100003008E ++:100860000000000010001000030041840040000060 ++:100870008004050004040300C100101020A0000043 ++:10088000C00203004100000020000300200005001A ++:10089000000003840000000109080000840000003B ++:1008A00000000010100400040004000441050000D2 ++:1008B000904100410000004100214002C0210000A1 ++:1008C00000000005090000000000A000002010004A ++:1008D0000000000020000041202100002000000056 ++:1008E000000000000000C00000000800C000000080 ++:1008F0000000208000008580000004001000A1009E ++:100900008400118500008200000001000000C10089 ++:1009100000000000000000030040008500002100EE ++:1009200000000011000000A100800080A08000A055 ++:100930004100002009004100008803A005000400D8 ++:1009400040000900118400100000030000100004A2 ++:100950000300080000000400100020001010030035 ++:100960000000008403100320410003000020410028 ++:10097000000009001004200005401000008403005E ++:1009800004000588040000000400100021840020F9 ++:1009900041200500100003000200020010000020AA ++:1009A000104011C0800000000000000000000000A6 ++:1009B00003400000000000000000001100000000E3 ++:1009C0000000000000000000000000000000000027 ++:1009D0000080000001000000010000000100000094 ++:1009E0000000000000000000008000000000000087 ++:1009F00000000000000000000000000000000000F7 ++:100A000000000100000001000000010000000005DE ++:100A100000000000000000000000010001000000D4 ++:100A200000000000000008000000000000000000BE ++:100A3000000000000084000010001084000000008E ++:100A40000000001003000084001000C0050000003A ++:100A5000008480840500080000004100050000A01B ++:100A600000008010050000100000042041008001FB ++:100A70004100850100000000008400840300100094 ++:100A800000A0000000000000038400000310030029 ++:100A900020A003A02000000041A04110410000114F ++:100AA0000284089080000001000180000000000026 ++:100AB00000000000000200058200C000C01000001D ++:100AC00000000021844100410000000000000000FF ++:100AD00000000000200000001100000000000000E5 ++:100AE00000000000040000000010000001808400ED ++:100AF00004040000202000000005000084008400A1 ++:100B000000000021820082000000820000008200BC ++:100B100000000100C0001100004110000002C041AF ++:100B20004040110001000400000400042000A00067 ++:100B300000001000000000000000000000000000A5 ++:100B4000000000000000000000800800110000000C ++:100B50000000000000000000000000000000000095 ++:100B600008050004401140100000000000000000D3 ++:100B700002058902104108100080080500091010C4 ++:100B8000084008058009888440090000400005806D ++:100B90000000020920090011084140808500100072 ++:100BA000410080C000840211002080030409040079 ++:100BB00000808003080900008000000000000000A1 ++:100BC0000000000000000000000000088900C09044 ++:100BD0000090000000000000000000000000000085 ++:100BE0000000890100000100000100000000000079 ++:100BF00000000183C1880291010200000009021176 ++:100C0000A0C0000908410885091000020008C110B1 ++:100C100002A000080100010100010001050409848F ++:100C2000010201C00483A08401A1000308C10401E2 ++:100C30000002000882010101820082000000000021 ++:100C400000000000000000C00000000008000800D4 ++:100C5000904090C000000000000000010000010072 ++:100C600000000001000001C00101010100000000BE ++:100C7000000000008200090809400311000009007B ++:100C80001010100109A01000C0C01101038208005B ++:100C90008800110005C00000008201040100040169 ++:100CA0008400410000820000000000010182000178 ++:100CB0000100000401C1000001000000010100006A ++:100CC0000000000000090000008000020004801005 ++:100CD0000000000000820000000000000040000052 ++:100CE00041000000110904000880050209200000ED ++:100CF0000000000000000202410005400920000041 ++:100D00001104090090400900890489808502098442 ++:100D10000409400090000384090002000511090045 ++:100D20008920040085004180000400000040098003 ++:100D30000002410000000389000041000000030997 ++:100D400000000000000000000000000000000000A3 ++:100D50000080800008808080000000000900800082 ++:100D60000000000000000000044000400008402097 ++:100D70000000000000000000020800820890A002AD ++:100D80000000020980C0208820910340001100C0AB ++:100D900020820000808090800080020200111009F3 ++:100DA00020100010004080840040000080800480FB ++:100DB000898080000000C009008300000000400915 ++:100DC00000830000000000000000000000000000A0 ++:100DD00000000010C00408848888000000000000A3 ++:100DE0008200000800000000C000000000A0000118 ++:100DF00001010000000000008800000382C1888516 ++:100E00008904000000A010C14185A188010384C0AD ++:100E10004084018800A01008A08488880001000098 ++:100E2000000001000000A0A1048400A10008400807 ++:100E300083100282080400C008C100830000000083 ++:100E4000010108890000000000000000010001000D ++:100E500001000100840188001000C01000000000A3 ++:100E6000000000000000000000000000000000047E ++:100E7000010000000000000000000000058588025D ++:100E80008200A008000084018883C001081085C189 ++:100E900088080801A00884008800C00108880100B3 ++:100EA00000030001000084098402A000A0C0010228 ++:100EB0000288010003008588A182A0000400018847 ++:100EC00001C000000000000000000000000003005E ++:100ED00040004000200080028000800000000000F0 ++:100EE00000000000000000000008000400004000B6 ++:100EF00040020811400000000000000000000282D3 ++:100F00008809021008000000880391410840888089 ++:100F1000C040918282034000801080090008800058 ++:100F20000200092008401000808300410002008078 ++:100F300040000200400040008380040000000000E8 ++:100F4000038004800000000000000000C2000000D8 ++:100F500000420000C20000004160000BC2200000FF ++:100F600000000022D0000041004200066020000086 ++:100F700000420006D00000000000000B000000004E ++:100F80001242000BD000000000001242000BD00003 ++:100F900006001242000BD00006601200000B440055 ++:100FA000000000420000D00000000000000000002F ++:100FB0000A4800840013D000005000820013D000C3 ++:100FC000000000840042D00083A000000000000068 ++:100FD0000000000000000000000000000000000011 ++:100FE0000000000000000000000000000000000001 ++:100FF0000000FFFFFFFFFFF3FFF70000000000000D ++:101000000000DFFFFFFFDBFFDFFF0000FFFF7FFFD0 ++:10101000FFFFFFFFFFDFFFFFDFDFFFDF000000005C ++:1010200000000000FFFFFFFFFFFFFFFF00000000C8 ++:10103000FFFF00F6FFFF3C7C00000000FF00000007 ++:10104000FF000000FF000000FF00000000000000A3 ++:101050000000000000080004000000000000000084 ++:101060000000000000000000000000000000000080 ++:1010700000000000DFFFFFFFFFFFFFFF0000000098 ++:1010800000000000FFFFFFFFFFFFFFFF0000FFFF6A ++:10109000FFFFFFFF76FFFFFFFFFFFFFFFFFF0000E7 ++:1010A000000000000000BFFFFFFFFFFFF8FF00008F ++:1010B0000000FFFF0076FFFF3C7C00000000FF0007 ++:1010C0000000FF000000FF000000FF000000FFFF25 ++:1010D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 ++:1010E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:1010F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10110000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF ++:10111000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10112000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:10113000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:10114000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:1011500000944F4A0C44804000180A06000070DFDB ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:10118000000000006666000000C026E6464646767F ++:1011900000000000000000000018E0F84646467617 ++:1011A0000000D3D3D3FF00903CB4909090F6060695 ++:1011B00006F600000000FF00666699F9DBFB1010E0 ++:1011C00010F700000000E6E60000BC3CFFFF000056 ++:1011D000FFFF000000FF0000F0F0000000FF000033 ++:1011E000F0F000000000000000000000000000001F ++:1011F00000000000000000000000000000000000EF ++:10120000000000000000F6F6F0F000FF00FF424290 ++:10121000427E000000000000000000FF00FF42428C ++:10122000427E00000000002CF0F0F0F0B0B0B0F210 ++:10123000262626E6000000000F0F3C3C0060002040 ++:10124000F0F0F0F000000000E6E70000BC3CFFFF1B ++:101250000000FFFF000000FF0000F0F0000000FFB2 ++:101260000000F0F00000000000000005080000048D ++:1012700008000000008600A40190000500860061BF ++:1012800008B000050086006400300000008600758C ++:10129000009000000086006100B00000008600B4ED ++:1012A000019000000000008600B401980000008654 ++:1012B00000B401900000008600A009900010010019 ++:1012C0000014000000000086006000B0008001866D ++:1012D000007D00B00803C0C7C07C30304903C0C7E0 ++:1012E000C07C3090490300000000000000000000B6 ++:1012F000000000000000EBA8A8A80D0D0DFF0000E5 ++:10130000000000000000000000003C3C0000000065 ++:1013100000000A0A0A0A0000000000000000F7D7D7 ++:101320002000000CC3CF0000FA0A0A0AD3D3D3FF6F ++:10133000BE828282101010BFFA0A0A0A4141417D22 ++:1013400000000000000000000A0A0A0AFFFFFFFF79 ++:1013500000000000CBDF0A5F3C3C3000FFEBFCF8F4 ++:1013600000000000FFFF000000000000000000007F ++:101370000000000000000000AAAAAAAA0F0F0F0F89 ++:101380000000000000000000000000003C3C0000E5 ++:10139000000000000A0A0A0A000000000000000025 ++:1013A000F555A0000008D7DF0000EA2A2A2A00002D ++:1013B000002CAEA2A2A23C3C3C3CEA2A2A2A45458B ++:1013C000457500000000000000000F0B0F0A55F5E6 ++:1013D0005555004100410A5F0A5F3C3C3800FFFF61 ++:1013E000FCFC00000000FFFF000000000000000007 ++:1013F000000000000000000000000000FFFF8383E9 ++:1014000083830000000000000000000000000000D6 ++:1014100000000000000000000000000000000000CC ++:101420000000FDFFFFFFFFFFFFEF0000FFFDFFFFDC ++:10143000EFEFFFFFFF7FFFFFFFDFFFD7FFFFFFFDA6 ++:10144000FFFFFFFF0000000000000000AFAFAAAAEE ++:101450007D7D7D7D0000FFFF00000000FFFFFFFF9E ++:10146000000000000000000000000000000000007C ++:101470000000000000000000000000000000FEFE70 ++:1014800000838383000000000000000000000000D3 ++:10149000000000000000000000000000000000004C ++:1014A00000000000FFFFFFFFFFEFFFEF0000FFFF66 ++:1014B000FFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:1014C000FFFFFF7FFF3F0000000000000000AFAF04 ++:1014D000AFAE7DFD7DFD0100FEFE00000000FFFFC0 ++:1014E000FCFC000000000000000000000000040000 ++:1014F0008400100004000400000003000300040046 ++:1015000004000400040004001100000000000400B6 ++:101510000000210004000400110004000400000089 ++:101520001100110004000000000040001000000045 ++:1015300000000200020002000000A100040082007E ++:10154000000011000000800000000000000080008A ++:1015500000000000040004000801110000008200E7 ++:101560000000000000000000000002000000000079 ++:10157000000040000100000000000000000000002A ++:10158000000000000000000000000000000000005B ++:10159000000000000000000000000000000001004A ++:1015A0000000000000000000000000000100010039 ++:1015B00000C00000000000000000000020009000BB ++:1015C00020000000A0000000040000000000000057 ++:1015D00020000000000000100000010200000000D8 ++:1015E00010000000000000000000000000000000EB ++:1015F00000100000004000018020002000A0000535 ++:101600000021000000000001000400000010112073 ++:10161000000000000800000000100000008800002A ++:101620000000000000000000000000100011002079 ++:10163000808800C00000000000C002000020802060 ++:101640000020800100A00020000000000000001029 ++:101650000000002000012091024100210009000447 ++:1016600002011041800040A0000000900001000134 ++:10167000000000010021A0901010088000800010E0 ++:1016800000A00004000000000004008000200021F1 ++:101690000000002100000120000090100021002126 ++:1016A0000020042000009040000000100000000412 ++:1016B000001020200000000000200021002002A0D7 ++:1016C000208000A0202000100000000000108210E8 ++:1016D0000221001002400020012001200020009083 ++:1016E0000090010801044010010400410010002096 ++:1016F00090200021002000C00002001100A0000482 ++:1017000000A00020001100C00005009103400084EB ++:10171000000200100002000000020000008800101B ++:10172000009100000010000000000000008800840C ++:10173000000400010005000000000000000000900F ++:10174000001000000000000200C0000000A000A087 ++:1017500000008088008400C00010001000410010CC ++:10176000000000A0004082210000000800A000212D ++:10177000002000C000010084000000800090840070 ++:10178000008082000080002000000084C0020080F1 ++:101790000021000000211000C000C080C000000037 ++:1017A000000900020010000000001000000082216B ++:1017B000C0000080000400C0000084210009104027 ++:1017C000040520410000000584050000C0008200DF ++:1017D000002182000400C01100008200C00000C08F ++:1017E00000008200820082804120C0090080400009 ++:1017F000000290000000002000000000C1021082E2 ++:10180000A18400001001039041001000410040003D ++:101810002000200010200000C1000900200010104E ++:101820000001020005000000004041000002108895 ++:10183000802010C105000201051100000084040091 ++:10184000098410A010C010040300100000C0411053 ++:101850000000100000C085004100C10002C003006C ++:10186000050080A0000040030005800000004190BA ++:10187000000804000382058205828001000510A192 ++:101880008800041000000004081000090100000096 ++:10189000010000030100008000001005C0000000EE ++:1018A00008000004000000050000000500000080A2 ++:1018B000002120A10004000001020020000000001F ++:1018C000830000000000A00082900041A000000002 ++:1018D000000000410141000004000000041001006C ++:1018E0001000002110000041018800C04000A0004D ++:1018F000002100A10000820000100000100800007C ++:10190000090241002040031000204140050305006A ++:101910000300020080C1200002004010030200000A ++:101920001020000002840300408400002004051001 ++:1019300000000000110000000000200020840000D2 ++:101940004100040003400402050021000000058856 ++:1019500000C0048800A0414000002002020210C024 ++:1019600000000202034041080000008810021090AD ++:10197000008403020984C00200C0000000000500CA ++:101980000000008004090180200000910000000494 ++:10199000000088050100042001000400010000107F ++:1019A000000000000000012100000100000001898A ++:1019B00000000000000000000041100001000100D4 ++:1019C0000000102101000040050084008400A005F3 ++:1019D00090419000A100002110000400A10000052A ++:1019E000A000820001000080840040000200C0804E ++:1019F000000300001000C000100200000000000002 ++:101A000000000001800000C002018801042190A1B3 ++:101A100080A0000003100204412080A000A00090DC ++:101A200000010082038200100001410000020090CA ++:101A300000041000020000A00200850180010005E2 ++:101A400000040000021009100010821000C0418242 ++:101A5000000041110900108410100084000004A04F ++:101A6000418404C000000082000041098800008415 ++:101A7000002100080000101003918400000041853F ++:101A80000010800100021003880001022020018460 ++:101A9000202004050000840000C0009020000010F9 ++:101AA000C041002000000010C0410002000000C141 ++:101AB0000021008000000000000000050404202038 ++:101AC00000A08880000000009000000020000000BE ++:101AD0000005001084040000080000000010000051 ++:101AE000030010410121000000210810008841007E ++:101AF0001000108200850000010000082000001185 ++:101B000000040000100804808080408000008340B2 ++:101B1000410920400808850409400902090900001C ++:101B2000000011000080000080000900000000009B ++:101B30000000000000000000000021000000000084 ++:101B4000080005000000008000000580858000007E ++:101B50008920000900112009000000808500008014 ++:101B600088828509C09108418991214000848008BC ++:101B70000303082105004008090302100541090478 ++:101B8000109102400885100800820204000400A0A1 ++:101B90008840008500400008850001000001010127 ++:101BA0000008A004A0000008000090000000000051 ++:101BB0000000000000000000000004000100000020 ++:101BC0000000A10000000000000000408810C008D4 ++:101BD0000008080100010001010000C08208404027 ++:101BE00000400808C005C10588080483018400047A ++:101BF00082A1890100010000000100011001010122 ++:101C00000000098800A10011200001000800410027 ++:101C1000039088004040890040090800C000080087 ++:101C20004100C00004100001044000000100002039 ++:101C3000010000000000000000010100010001009F ++:101C400000000490A0000490020000008800400002 ++:101C5000080040040108008801910100C00009004B ++:101C6000900291C00801048405014104400820C08D ++:101C7000C0080240C000C01102218300018201009F ++:101C8000018401018204A09008891088400083002B ++:101C90000800038000004000A10020098800040023 ++:101CA00083038900000900800011008008004000C3 ++:101CB00004000300000000000000000340000800D2 ++:101CC00040000004850003028008800900000041F4 ++:101CD000000080000009200005000502090000093D ++:101CE000A00000002000C12002008503090400407C ++:101CF0000088008300884000408490048305110020 ++:101D00004100080003050000004000828000000838 ++:101D1000001180C0000003080004080900800310BF ++:101D200000840011A1A100000000008000800000DC ++:101D30000000000000800000000000000000000023 ++:101D400000800080008000801000408000000000C3 ++:101D5000008080000500808002081004034041409C ++:101D600000800080008080002089800491850488A4 ++:101D7000034010081140880904800921101108034C ++:101D800002C000C0048283830300004021840489D0 ++:101D900000212005408520900041008320410088DB ++:101DA00001C1001000A0830900C0A00404841040F9 ++:101DB00000880090009000820000000000000200F7 ++:101DC000000400080010008800040184010290A0B3 ++:101DD00000000040C0824102408800010100000074 ++:101DE00090000008C0C0908488040140C084108422 ++:101DF00088890101A1000100020001900003010097 ++:101E00008503A109000300034109010808A083100C ++:101E1000908882854001820004000340858940202B ++:101E2000C101019001C1008901408505A0C0830066 ++:101E3000C0A00000000000010000000000910000B0 ++:101E4000000000000000000000000102000000008F ++:101E500000A00000840104004000C040000001A078 ++:101E600000010100840102010801C00884A18883E7 ++:101E7000A0004188840384A0A0000411010801850A ++:101E8000000000A000040001000100000908A08873 ++:101E90001000C000808380110008000089030282C6 ++:101EA0004040A11003000421118209008308028030 ++:101EB000400009000000001100400000000000C0C8 ++:101EC0000000000000000011000000000383040572 ++:101ED00011030800000080108000800000800400D2 ++:101EE0000804404020008003000980210080840213 ++:101EF00085844004882083024080110088C10380CB ++:101F00000408000011000000001100210000020878 ++:101F100011808400892000000013C20042000000EC ++:101F20000042480000000042000BD0004148000081 ++:101F30000013C20000004100000602000000820001 ++:101F400000136000008100000013C20000000000C8 ++:101F500000104800000000001200000BC20000004A ++:101F600000840080D00000001200000B000006007A ++:101F70001242000BD0004141000000424800828123 ++:101F8000000000134800810000000000D00000485D ++:101F9000000000104800210000000000101F101F6A ++:101FA000000CFFFC01FD01FD4F41414105045010B3 ++:101FB0000900030000000000000000000000000015 ++:101FC0000000000000000000000000000000000011 ++:101FD000E1E1F0C30000000000000000000000008C ++:101FE0000000FFFFBFFFF3FFFFFF00000000000045 ++:101FF0000000FEFFFFFFBFAFFFFF04070707511000 ++:102000005DDF3CFF7D7DAAFFF0FF000000000000C7 ++:10201000F3FF0D0D0C0F000FF0FF00000000101F6C ++:10202000101F0000FFFF00FF00FF4F414141000073 ++:10203000551405000C000000000000000000000026 ++:102040000000000000000000000000000000000090 ++:102050000000E1E1F0C3000000000000000000000B ++:1020600000000000FFFFFFFFF7FFFFFF0000000080 ++:1020700000000000FFFFFFFFFFFFFFFF0404070455 ++:1020800051105DDF3C0028280055000F00000000C3 ++:102090005155F3FF010100030055AAFF00000000A5 ++:1020A000FFFFFFFFFFC0FF00FF00FF0000D000F0B8 ++:1020B00005005000000000000000000000000000CB ++:1020C000F0008282000000000000AAAA00000000C8 ++:1020D000A0B4A0B400000000000000000000000058 ++:1020E000000000000000F414FFFFFFCBCBCB00008A ++:1020F000000000000000F3C33000F8D0D0D0FABEDA ++:10210000501400000000AA3CAAAAACACAA3CFA0AEF ++:10211000FE3EF30059AAA220A22000000000000009 ++:1021200000003C3C80823F00FF00FF50AF000020D9 ++:10213000000001004000000000000000000000005E ++:10214000000000008282000000000000AAAA000037 ++:102150000000A0B4A0B400000000010101010000D3 ++:102160000000000000000000E0000000340000005B ++:102170000000000000000505FBEB1000FCC0C0C023 ++:102180000000000000000000AA3C3C3CACACAA3CB3 ++:10219000FA0A0434C0006AAAA2A2202000000000AB ++:1021A0000082026100B80010008600010880000073 ++:1021B0000586007500B00000088600B00890000099 ++:1021C00000860260013000A00086006009B004159E ++:1021D000008600600090008508865061A8B0000568 ++:1021E0000000008600A0019000050186007500B087 ++:1021F0000000008600A001900000018600B401905C ++:1022000000000086706000B8000005865A60A0B922 ++:1022100000A500860A6000B90010008670010080E9 ++:102220000000C3FFFF0FFFF141413C3C3C3C40003C ++:102230007FFF00000000081C495D3C3E3C3E00FF63 ++:102240003C3C00000000FCFF555500000000000071 ++:102250000000000000000004AAFF00000000FFFFD3 ++:102260000000000078F050F000EB04EF00000000E8 ++:10227000000000003CB400A00005AAAFF8D0D0D008 ++:102280005151515D000000000000000000000000FE ++:102290000404000000000000EBEFFFFF3C3C3F3C6B ++:1022A00040007FFFC3FFF000414141413CFC3C0C3A ++:1022B00040007FFF00000000081C495DFFFF000A8E ++:1022C00050FF7C7C0000000000FF000000000000C8 ++:1022D00000000000000000000000AAFF0000000055 ++:1022E00030B0000000007878505000C30CCF0000E0 ++:1022F000000000000000F0F0F0F00001BEBFFCC0E4 ++:10230000C0C04141417D000200000000000000000B ++:10231000000004040000000000000BEB0FFF3C3C39 ++:10232000303C40007FFF100000000000000FFF0065 ++:10233000FF3030FF00FF000000000530053FBEFF0A ++:10234000BE55F1F1FDFD000000000000000000009E ++:10235000000000000000000000000000000000007D ++:1023600000005F5F5F5F0000FFFFFFFFFFFFFFFFF9 ++:102370000000000000000000FFFFFFEFFFFFFF3F35 ++:10238000FFFFFFFFFFFFFFFF0001FFFE3C3C3C3C67 ++:102390000000000000043C380000000000000000C5 ++:1023A000FFFF00003C3C3C3C00001000000000002F ++:1023B000FF00CF0000CF00FF000000000530053F08 ++:1023C00014FF1455C1C1CDCD000000000000000075 ++:1023D00000000000000000000000000000000000FD ++:1023E000000000005FDFDFDF0000FFEFFFFFFFF80E ++:1023F000FFFF0000000000000000FFFFFFFFFFFFE5 ++:10240000FF7FFFFDFFFFBFAFFFFF0001FFFE1C1CB2 ++:102410001C140000000000043C3800000000000014 ++:102420000000AFFFA0003C3C0CFC11000490200019 ++:10243000202004881100040021C011400000040085 ++:1024400000000400040005001190040000000400D6 ++:10245000042000000000112011000400000004000E ++:102460000200040004000300040000000400000057 ++:10247000040004001100110004001000030000001B ++:102480000000000004000400020003100400030028 ++:1024900000000000040020000400040020000000F0 ++:1024A000110011000000040000C000000000000046 ++:1024B0000000A0000000000000000000000000007C ++:1024C000000000000200000000000000000000000A ++:1024D000000000000000000082000000000000007A ++:1024E00000000000000000000000000000C000002C ++:1024F0000000000000000200A00000000100040035 ++:1025000000000000000000000000000004001000B7 ++:10251000000000000000000000000000004100007A ++:10252000000000000000000000000000080000841F ++:10253000040000C0000000A0000000200000000017 ++:10254000008800020040040004000004000000882D ++:102550000000000100A00000001011200010000089 ++:102560000000000100C00000002100040021004024 ++:1025700000000020000000C000000000000010006B ++:102580000088002000880000008880000000000013 ++:102590000000002004000008000000000088002067 ++:1025A000000000000000111000000000000000000A ++:1025B00000000010A000024100200021A0800010B7 ++:1025C00000000021008000000000002000A000208A ++:1025D000001000410002000000000090A0C1002097 ++:1025E00000009000000200210020821000900008EE ++:1025F000000000100041001000000000000800036F ++:1026000001110000002100108211000008000011DB ++:1026100000000010024102100010004100210020C3 ++:10262000000800000020004100410041004100205E ++:102630000211001000A0214000C00088008400C0EA ++:1026400000001000000000A0001040C00090000238 ++:10265000008800900010001000A000400000000062 ++:10266000000000000000000000400002008803009D ++:1026700005900000408802820304008800100000DA ++:102680000010001000900810004021C0000200005F ++:102690000088082011000582000400A000900002BC ++:1026A0008001C000009000908084000000000002C3 ++:1026B00080C00085820000040200020082008410B5 ++:1026C000001000000000A0008205C0020000000011 ++:1026D000020000100041000000000008100010007F ++:1026E0000000100000000000040000800000000056 ++:1026F000000084000000400002108200041000006E ++:1027000040000020104002000800000010000000FF ++:1027100000008800000900000000000300411021B3 ++:102720000203202011050402000040000200000006 ++:10273000000020030004080000000800050111004B ++:10274000800005008500000000000000000000007F ++:1027500000902000100000001000000100000000A8 ++:102760000000100100C10000000005840000090005 ++:10277000110003011000000000A0000000900020E4 ++:10278000058400001000C10208A00020C0008000E5 ++:10279000000009080020910005000300100110004E ++:1027A0000500109010000000410000000000000033 ++:1027B000000000001088100810008811910900081E ++:1027C000C005080082111041000000000010000543 ++:1027D00020090010100020000000880000100020D8 ++:1027E00000000800080400080000001000100004A9 ++:1027F0000000100000200041000008000000082137 ++:102800000000000000008800108900000020090579 ++:1028100002400800080500C1100000000000001080 ++:1028200000008811022110030000000000000411C4 ++:102830009020100000000000000041904182400004 ++:102840004100008409A000A01000400000C0041056 ++:10285000000004100402400280C140C003880088C8 ++:10286000038800A0098410828088000040840090C2 ++:10287000080010880400000085880000008400A083 ++:102880004102008400000300028221A000A0008415 ++:1028900020020004020010100810000008000910B7 ++:1028A0008500880000C083002110000000004188DE ++:1028B0000091028810C0100100019020040000095E ++:1028C0008900880000000000000900000000A00945 ++:1028D000C0C0840200000020C0001004000090006E ++:1028E00000208400080000000009400010000000E3 ++:1028F00090110821000000001000200500000011C8 ++:1029000002008411000000000000C000020040002E ++:102910009000100010000000A0000000080900084E ++:102920008800400010020410081000000010400051 ++:102930000000C010C1000000001082201005091026 ++:1029400041100300108400001090800040A021007E ++:1029500000C000C000C1000080C0808809000010D5 ++:102960000000000011010084008441100008008272 ++:1029700003C000830810000005C0410000400000B3 ++:1029800010000084000003004188021000A0408471 ++:102990000000000000C005101010200041011001CF ++:1029A000108400082100050010884100051005C0B2 ++:1029B000108403820500054000A00088000010A0DC ++:1029C00000000809C0100240C000820020008300FF ++:1029D00000008400A0409040000008410410000066 ++:1029E0000041000008211008044000000000000021 ++:1029F00000000000001000000000000008110800A6 ++:102A0000000000000820000000000041000000114C ++:102A10000541000000000000200400001000100428 ++:102A20008404C0210200C000020000000400000075 ++:102A3000C00000002000C000C000002010200020C6 ++:102A4000002000008300008883C1800003800041D3 ++:102A5000C182038083000083034190008380800251 ++:102A600003008000A000001183C18000038080C1AA ++:102A700003830380830000830341C00083000002BE ++:102A8000030000000000830000C183C180800300B8 ++:102A90000002838803000300008303414080830019 ++:102AA00080C1030000008300008883C18080410052 ++:102AB0000002839003000400008303104080800024 ++:102AC000008503000082838208C183C182A00104C3 ++:102AD000029121C00110118200830101838283C011 ++:102AE00010830100828282828882834008820110E2 ++:102AF000100921C0010211820083010183828388B1 ++:102B00004083010000000082838204C183C182A04F ++:102B10000182408903C101A0A18200830101020258 ++:102B20008382A0C101000082838290C183C182A000 ++:102B30000082A041054101A09082008301010302AF ++:102B400082A0A00401008200088200834182A0824A ++:102B500041820000C182408382830083C1008320C0 ++:102B60000982008301C0820090820083C182828238 ++:102B700085820082C190088382830083C100832004 ++:102B800091830083012000008200888200834182BB ++:102B9000A08209820004C102408382820083C100B6 ++:102BA00004108483000501028200208200830382D6 ++:102BB000A0820582000441A00983838200839100E2 ++:102BC00020418482000901A00000808000831080E1 ++:102BD0000080048000008380208309880083C10076 ++:102BE000020984C000834109000000800083C08086 ++:102BF0000080028000808300408340C10083C108C0 ++:102C0000020904C1008341850000000000800083A8 ++:102C100041808080048000008300898303840083D6 ++:102C2000C10085C0039000034109000000800083BB ++:102C3000C080808004800000830090832090008307 ++:102C40001000200203820083100000050080A0C154 ++:102C500088C1000000804021C0A180C00000910216 ++:102C6000000000110000830200000003008083C107 ++:102C7000C04100000000830320C10011000083C197 ++:102C8000000000110000830280000000000200002C ++:102C900083C1114100000080890291C1000400003D ++:102CA000830200000010000083A180000003008068 ++:102CB00080C184C100000000830203C1000800003D ++:102CC000830200000020000083858000000000C017 ++:102CD00082C1832100000040828905A102C00084D6 ++:102CE000828300000002008483830000000000C093 ++:102CF00082C1832100000082838201C100820082A0 ++:102D000083C10000000400848283020000000001EF ++:102D1000008283C10091000000C0820982C100824C ++:102D200000828383000000C1008283A18200A00092 ++:102D300000C082C182030000008283C100C1008301 ++:102D40000082838300000005008283048200020960 ++:102D5000018289210482A18201038482C002C1828E ++:102D6000010101830000838301080101C003029176 ++:102D700001828303908383400183918310218388A0 ++:102D8000018301830000C18201010101C00800002C ++:102D90008389018221A1888204A000832182A0C0AE ++:102DA000838300010183000082040102010184C1C8 ++:102DB000020500828340088383A00183088302C048 ++:102DC000838201010183000082050102010102C129 ++:102DD00083830280410200A020800283110380854A ++:102DE000C18802030283000040A00411020800C150 ++:102DF000830302804188008802004083408880C0AD ++:102E0000020804834183000082C0044102080005D7 ++:102E100000000203208041020084040008839083A4 ++:102E2000000502C0410302830000090802082102D4 ++:102E300000C083834080412180C00200408311880C ++:102E400000040282080302830000411002032102F1 ++:102E500000C0000000000000124211480008D0002D ++:102E6000125081480004D00012420000000000000F ++:102E70001242000000000000124221480004D0006D ++:102E8000124221480004D00012420000000000005D ++:102E9000124200000000000000001242114800131E ++:102EA000440012428148000B020012420000000060 ++:102EB0000000124200000000000012422148000BF6 ++:102EC000480012428148000B4800124200000000F6 ++:102ED00000001242FFFFFFFFFFFFFFFFFFFFFFFFAA ++:102EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:102EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:102F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 ++:102F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 ++:102F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 ++:102F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 ++:102F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:102F5000FFFFFFFFFFFF0014C6670C44802000E85E ++:102F60000A0600006059AEDE00000000000000000C ++:102F70000000000000000000000000000000000051 ++:102F8000000000007B75AEDE0000000000000000C5 ++:102F90000000000000000000000000000000000031 ++:102FA000000000007B750000AEDE000000000000A5 ++:102FB0000000000000000000000000000000000011 ++:102FC0000000000000007B75AEDE00000000000085 ++:102FD00000000000000000000000000000000000F1 ++:102FE0000000000000007B750678C00000000000B3 ++:102FF0000000008C0700000000000000300000000E ++:103000000000000000031E600678C0000000000001 ++:103010000000008C070000000000000030000000ED ++:103020000000000000031E6000000678C0000000E1 ++:1030300000000000008C07000000000000003000CD ++:1030400000000000000000031E600678C0000000C1 ++:1030500000000000008C07000000000000003000AD ++:1030600000000000000000031E6000000240040099 ++:1030700000001100110004104000020002001100C5 ++:1030800004000000040004000820000011002100DA ++:103090001100001020200208201002008408840083 ++:1030A00004000200020004A004200000000004004C ++:1030B000040000000800040005200420040004109F ++:1030C00004000208004008000440840800000020BA ++:1030D0000400000000000310051020100000001084 ++:1030E000210000400000000100000000000000007E ++:1030F0000000000000000000008000000000000050 ++:10310000200000000000000000000080000000001F ++:103110000000000000000100000001000000088025 ++:1031200008002000100000000000200000C0000087 ++:10313000A00000000000010004000000208000004A ++:1031400000008800008000000000008002000040B5 ++:1031500000800000000000008280000000001000DD ++:10316000000000000000820082400000000000001B ++:1031700000000000000100000008410900020040BA ++:103180000004000100010000000000000001000038 ++:1031900000000000214000000400000000000400C6 ++:1031A000100880000000001000000000000100C0B6 ++:1031B00000008040000000400003000000C000400C ++:1031C0000000000000000004C100000000410020D9 ++:1031D00080010001000100A1000000820000000049 ++:1031E0000001000900000000000000018001000053 ++:1031F000002100000000002002000010204000110B ++:103200000411008000409004001090030041004031 ++:1032100000000000000000C10020000800000003C2 ++:10322000010001801011C00000080008000800081B ++:1032300000004000028000000280008400080009B5 ++:103240000208000388000000008040030409008297 ++:103250002090040400400004004000210021880365 ++:10326000000900100084A0080410000002200420BF ++:10327000000802C00020008800C000000000808418 ++:103280000004008800A000100002000005020004F5 ++:103290000088098500A12082000000200004402051 ++:1032A000002000048084800100C0008500000083AD ++:1032B00000110000208880100004008200840011AA ++:1032C00000048020000000020090800000088008B8 ++:1032D00002A0000000000000000200000002031035 ++:1032E0000902000010A140900020000808C088A03A ++:1032F0000000110084030000000300084000A0103B ++:1033000020080090000000000000001100210010C3 ++:103310000003004000040004110000000080004190 ++:103320000080008040A10800401000210020001013 ++:10333000882000040000880840001080C0418200FE ++:1033400088040084081000091089C00910100000CA ++:103350004000101190000041820510000000C000E4 ++:1033600084110000000291041100004100080000D7 ++:10337000040000080041020002000900080080006B ++:1033800010200000000000000500100003040800E9 ++:10339000000000000400000010004190020108003D ++:1033A00000001008000800002100210002000000B9 ++:1033B0000300050000880000000000001000050068 ++:1033C00000100002034010401100400002844141FF ++:1033D00009000000800804014100000000000811FD ++:1033E0001002210010000200001010001040000028 ++:1033F00009901001840104000811102082090800BE ++:103400000400008000000000C000201188000008B7 ++:103410000000A010000901000009001100000804CC ++:10342000000000000000C000100508008200010933 ++:10343000C000000000110000000008100000901003 ++:103440008200008000A010830089A02005080011E0 ++:103450008208900420050480030800001010C010AA ++:103460000040820404000000C1000880881088A089 ++:103470000000000008200320110041200021050069 ++:10348000100404102140000241108040100300038A ++:10349000000189C020008004001100A00005800008 ++:1034A0008082111000100090101009A088C0210027 ++:1034B00082C041C1A110111000A000008390040936 ++:1034C000214082104000800000A084C080020021C2 ++:1034D0000008400402C008102100210200404004FE ++:1034E0002088802002880200211010041020100182 ++:1034F00004000521030000C000001020040088849F ++:1035000000410088410000088811008304008820E1 ++:10351000002000202000010820908804A0008420C2 ++:103520000400044100888890A003888500000921D8 ++:103530000005031182100841000004000000204132 ++:10354000000400802110000502000000200040104F ++:1035500000020080A00089000000100300000000AD ++:1035600000080000028001000141008084A1008069 ++:1035700010200005A0A00000A0000000C0800040B6 ++:1035800000C000200810009083004182004000C06D ++:10359000020400840000008420900084008408203D ++:1035A00000840400008410C01020001000000010EF ++:1035B00000000308008500080020410003200000EF ++:1035C00000400084218400400010008400100800A6 ++:1035D00000C000C008101000100120004110410080 ++:1035E00000004183002021090000100400824000F7 ++:1035F00000C00920094000848840080190011000A3 ++:10360000000004000800080010002000A01108912C ++:103610000000010000000000000011000000900008 ++:1036200002800000080000000000008000900400FC ++:10363000000000200000000404001091A000088099 ++:10364000000008A082040409109004401003024006 ++:103650001103000000200008840800080005004055 ++:1036600000000000884008830410000000000000F3 ++:10367000000288410890008000000880002002209D ++:10368000080002100240A0A0411000C1408800883C ++:1036900041084005A00402024141081108104108F8 ++:1036A00009101011830909100000030503090041E6 ++:1036B000080588C0808409912104000000000000F2 ++:1036C00000000000000040800200000008008300AD ++:1036D0001000400003002100000008000800858061 ++:1036E0004080888000202141020480050080800005 ++:1036F000040000000080C1A084408009900302A063 ++:103700001120800301C18283214101080082040845 ++:10371000002101C1C101410101000101010040017D ++:103720001100000101001001000000000101000172 ++:1037300000090100908210400040000200000000DB ++:103740000000000000008800028401A000A000002A ++:103750000900000001000100000000000100000459 ++:10376000C084018882C0C00111009000C0000082A6 ++:10377000A0880188000402880809080582C0A10306 ++:1037800008858203A00403018383A10940108200FD ++:103790001000A00905C141911184A09003C0000050 ++:1037A0000190010001000182001000880101000267 ++:1037B0000982012101000000010201200000002017 ++:1037C0000800004000000000000004010000108418 ++:1037D00008000300010083880000000000000100D1 ++:1037E00010008410A08889A10520A0C005034140D5 ++:1037F000010001000100010082110805041101020D ++:103800001000C0A0894183859103028220A02180FD ++:103810004002800089088820914084008241058808 ++:103820000000100008000900108011801010090825 ++:103830000280418005200905110008000288090066 ++:1038400011000400100010210000004000100000D2 ++:1038500080A1910010032000C009090000000400AD ++:103860000320211080800800031188830480C08217 ++:103870004090080010001000090020C08503058258 ++:1038800003000008000090A083840380000521A0AD ++:1038900002080004808841084088038040202002FC ++:1038A000034080000008084140101011041008096E ++:1038B000C1412010041010200420101100080841FC ++:1038C00011830000030000800000000000808000E1 ++:1038D0001000008000400004054000840011091120 ++:1038E000211080000008008080400003410008098A ++:1038F0000489030580000080000000809080800023 ++:103900008080008003A104210480418301020040E3 ++:10391000A085200400C04005829100090004000831 ++:1039200001A1900104100082010521050100010898 ++:1039300000C1830901010100004190000082A0C084 ++:103940008301008390000100001008000000900433 ++:1039500010108302001090890088008282A000006D ++:1039600000000101840000400408088890118202D0 ++:103970000090018409A1A09008C000000882A01056 ++:10398000881084848488829011C0C184901184003E ++:103990000883A10190A0830391418300C008010224 ++:1039A000890510014010010000900000010001880D ++:1039B000004000000000014000400900000001A09C ++:1039C000018401010100000000000001000000006E ++:1039D000001000000800000082900200088400002F ++:1039E0000000000100000001004005A18300100854 ++:1039F0008200110120011004000808840400000165 ++:103A0000C00189008400881091201088840010C1B2 ++:103A10008000910310210300900940880804910060 ++:103A20000240408211048080090008080909100042 ++:103A300009004040000040001000108308042000EE ++:103A40000300058211400400000000080008000087 ++:103A5000000000000000800000008090000300844F ++:103A600000000000004000080003000990910410CD ++:103A70008000C0208508022090C0000000040011D2 ++:103A80000009411185219021808083118380832149 ++:103A9000C18300000013C2000A0021000013C2000D ++:103AA000000000000008C200000000000013100029 ++:103AB0000000000000424400428200840008D00060 ++:103AC000420041000013C200000000000004020098 ++:103AD0004200000000000000480000000000000854 ++:103AE00048008200000000004400418800000008F7 ++:103AF000D00000810000000BC200004100000080E7 ++:103B0000C200000000000013480082840000004250 ++:103B100000000082BD24BD249FFF06FFFFFF7F3F02 ++:103B2000FFFFFFFFFF0066666F6F0909CFFF0C0004 ++:103B3000666F66667EFF4200FF00EF08FFFFFFFE34 ++:103B4000FF3FFF7FBD3C0900F000FE7E000000004B ++:103B50000000000000000000000000000000000065 ++:103B600000000404FF04000000006F097E7EFF0FC8 ++:103B7000FF0F00000000FFFFFFFFFFFFFF0F00002F ++:103B8000000000000000000000000000000000F045 ++:103B9000FF0F050518189F9F9F9F9F990699FFFF8C ++:103BA0007F3FFFFFFF0C0F0FFFFFFF99FF99FFFF04 ++:103BB000000066606666FFFF0000FF00EF08FFFF81 ++:103BC000FFFFFFFFFFFF3C3C0900F0007E7E00008E ++:103BD00000000000000000000000000000000000E5 ++:103BE0000000000004040404000000006F0918181D ++:103BF000F000F00042002400FF6EFF0CFFFFFF0FFB ++:103C00000000000000000000000090000000000024 ++:103C100004D0DB0B05051818FFFFFFFFFFFFFFFFB8 ++:103C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 ++:103C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 ++:103C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 ++:103C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:103C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:103C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 ++:103C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:103C9000FFFFFFFFFFFFFFFFFFFF0018D9630C448A ++:103CA00080A000180A060000304D30303F3F1F183A ++:103CB0007F7E7EFFFEFFFFFFFFFFE360EF6F3D09AA ++:103CC0003DFF6662666E0009FFFF00FF00FF000116 ++:103CD000FEFF4F4F4FFF1C1C1C7C0000000024FF08 ++:103CE000FFFF00000000F0F40024000000000000CE ++:103CF000000000000000000000240024000000007C ++:103D000000FF427E000000003C3CFFFF3034FFFF1C ++:103D10006666FFFF000000000000000000000000D9 ++:103D20007E7081849FFF2000000000FF06F606F6EB ++:103D300018187E7E7EFFFEFF3C7EFFFF60606F6F87 ++:103D40003C003CFF6662666E0000FFF660F900FF13 ++:103D50000001FEFF000000B01818187E08000000E7 ++:103D600024FFF4FF000000000024002400000000F5 ++:103D7000000000000000000000000024F0F400003B ++:103D800000006666427E00000000663C00FF0024E2 ++:103D9000FFFF6466FFFF000000004000266603008E ++:103DA00003007E7E81811C3C83C3000000000086EE ++:103DB00070B0009800000082000109B00000008689 ++:103DC000007100B80000008600E008B00000008626 ++:103DD000006108B00000000000740030000005849D ++:103DE000004109B90000000600610830000500002C ++:103DF000A0865060A8B00085A0865060A8B8008555 ++:103E000000000000080900A50186006108B9001043 ++:103E1000008600E108B000000086007008900000F5 ++:103E2000A00650810890486000C7006100B05100B2 ++:103E30007D7F282F00C33CFF0200800003033F3F2B ++:103E4000F5A0F5A0551E551E000000003C17FF17F9 ++:103E500000000000000500000000F0F000FF00007E ++:103E600000000000CFCFAFAF0000000000FF000057 ++:103E70000000AAAAAAAAFFFFFFFFFF0000FF557DCE ++:103E80005F7F00000000000000003C000B0F0C30C2 ++:103E90005555FCC0ABBF000000000FFF0FFF3C3CBE ++:103EA0001E1E0000000000000000AAFFAAFF14C3AD ++:103EB00003007D7D28280ACB3EFF00000000003C67 ++:103EC000003C28282828001E001E000000000017C3 ++:103ED000C31700000000000000000000F0F000FF29 ++:103EE0000000000000000C0C05050000000000FFB1 ++:103EF00000000000A0A0A0A040403330F0F00F0F61 ++:103F0000003C0F3F00000000000000003C001F0FBD ++:103F1000FC3F5555FCC0A8808A0AAAAA0FFF0FFFD4 ++:103F20000F0F1E1EFB04000004005155AAA8AA2270 ++:103F300014000300FF3C003CFC05FCF5000041417F ++:103F4000553C0FFF00000000417D3F3F0000000096 ++:103F50000000000000000000000000000000F0F081 ++:103F60000F0F000040008000000000000000000073 ++:103F70000F0F00000000FFFFFFFF00000F0F000009 ++:103F800000000C0C03030000000000000000FFFF15 ++:103F9000FFFF5555545700000000FFFFFFFFD7FFFC ++:103FA000DFFF0000000000F000000000EBEBFFFF6F ++:103FB000BA30D4C00028F0FFF0FFFC05FCF510007B ++:103FC0000000553C0F0000000000417D030300008D ++:103FD00000000000000000000000000000000000E1 ++:103FE000F0F00F0F000000000000000000000000D3 ++:103FF00000000F0F00000000FFBAFFBA00000F0F13 ++:1040000000000000000000000000000000000000B0 ++:10401000FEFCBE3C5457555500000000B0F00000B7 ++:10402000D7FFDFFF000000000070008000F0FFFFFE ++:10403000BA30BA301400032B02000200000000C0A6 ++:10404000200404000200000000000000820020881C ++:1040500080880001210000900000040000009120F1 ++:10406000050000088410040808000200030004048E ++:10407000820000002002110800400020840141005D ++:10408000040004200420A0018811A0000440212085 ++:10409000840000A100004000009000000402021013 ++:1040A000000002840300030084C0000000A00000A0 ++:1040B0002108000021022108000500000000000086 ++:1040C000000002800000000000000000000004006A ++:1040D00000002000A00420000000000000000000FC ++:1040E0000480000000000300C10011001100100056 ++:1040F0000080110000000080008000C08480024029 ++:104100000000000005808580094003A009001080A0 ++:1041100010800800002000000100000000000000E6 ++:104120000100000000000000000020000000000965 ++:10413000000082C0000000000400C0888004000469 ++:10414000000402040000000004010001002000003F ++:1041500000000000210000A0000000000008000096 ++:1041600000000000004000000000000000000040CF ++:1041700085000020000200010800000000C00001CE ++:1041800011400000800100000040000120010000FB ++:1041900080000001009080A10000000100848000E8 ++:1041A000040202000008001000000020200000842B ++:1041B00080048000000180000000800080004080BA ++:1041C00000900084108000000000014000209080DA ++:1041D000041100000000000000200008000800900A ++:1041E00000200000020800800000000800110021EB ++:1041F00000A10200100000A10004A11100000000B5 ++:104200000004209090400204000000110010C12022 ++:1042100000032021004000001010000004100000E6 ++:104220000821031001058200008000000421910094 ++:1042300000090202024100200400A0000400040062 ++:1042400000000000892009000008020000020000B0 ++:1042500000A000011000800000C0000008A0004085 ++:1042600000C020A080008400004080A080908000DA ++:104270000084804000C00084000000400000002056 ++:104280000000002002040005008880410040080270 ++:1042900082044040040080904110020204050002A4 ++:1042A0008008038200C00040000200C021A000205E ++:1042B00020A000C005000010020200000082008261 ++:1042C0000000100508001000201000800100001000 ++:1042D000001000402004100002210805000801021F ++:1042E00000000004011020100541008004050411A5 ++:1042F0000405001002880810000900008240020036 ++:10430000000000400008038200A0024120200000BD ++:10431000C100050910000900080908000100094052 ++:104320008405020900028220101140110041840519 ++:104330008480111084098409000011050000C01157 ++:10434000C00000214000009008411040032000A060 ++:104350000000908500840400040088A00300000091 ++:1043600000000000030000000301C0008040902016 ++:1043700010219020404008001001020000000000C1 ++:1043800002000000000000008000001021910000E9 ++:104390002000200020000010000000C020000808BD ++:1043A000020008014101080000041040040003005D ++:1043B00002200440050005000200100000408000BB ++:1043C00080400088008488000000101000001080E9 ++:1043D0000040000002020000410001000400001043 ++:1043E0000010000000001000000084042000028083 ++:1043F0000280108805800180840000108400840001 ++:104400000000080000000040000040009010002064 ++:10441000000001000100090982800000A011850050 ++:10442000028082410820002000000080A08021003E ++:104430000009000301A100001000100900000000A5 ++:104440000440020004000000000010080400000204 ++:1044500000850000000841028284082003A00004B7 ++:1044600000011082090041000000000008C0801017 ++:104470001001042004108420008440C00340400048 ++:1044800000200040408441000000401000410040F6 ++:10449000050040082085201004408982A010A0203B ++:1044A00020851101088888C010030002200204C082 ++:1044B00000110502034004410000000002000082D8 ++:1044C0004111002100901001000200000841C008C5 ++:1044D00000418440841110210083201000900003CB ++:1044E0000088004000400405000800004010002142 ++:1044F000400000400188011111900005041090C097 ++:1045000000050010400000100021000002200020E3 ++:104510008282000902000120411110830210030869 ++:10452000031005209008A105020800100240910028 ++:1045300083050040C0210000012000099020912047 ++:104540008420840400080021C002004040112000A3 ++:10455000890500000041C190410080A0000800844E ++:104560002004410400830000051000C000004190B9 ++:1045700041A000000000831180208285834000025A ++:1045800004400085408241C0030009000000100083 ++:104590000204008400840400090400C0020020001A ++:1045A00003A010841108100011200400118404825B ++:1045B0000200100010C090C010040282100000021F ++:1045C000001002040984002000A0412000000040E7 ++:1045D000000008100021002004000000040000007A ++:1045E00000000080008000040000200000000000A7 ++:1045F000000000000000000010020480032008807A ++:104600000080008002400000002110000000000037 ++:1046100001000108000808000000840010000000EC ++:1046200001090000900000001000000500000008D3 ++:104630000100A0000000C000080000001000000001 ++:1046400000000000C1000000008000008880000021 ++:1046500010800000008020000000800089800000A1 ++:104660000000000020000000108300848000401142 ++:1046700000080041000005101005001188084041A5 ++:104680000480408008009100908300C00005041160 ++:10469000000009040588898288A104218803410358 ++:1046A0004040038320A10003911120914109118210 ++:1046B0000284051140100803034000008000090037 ++:1046C0000000000041002100000005008500880076 ++:1046D000118001820004104001C002100808A104EA ++:1046E00088400000040001000000008300088200F0 ++:1046F00001000000000000000001082184840988F6 ++:104700000090888285840108824040830084008371 ++:10471000000000000408050384C082852100838412 ++:104720000000C000408201A08284A0909183840890 ++:1047300082C000A0A001050182000000100020003E ++:1047400000000000000090000100000001C0851082 ++:10475000101000C000C0000100080000080410880C ++:10476000820540400002000100020000000000013C ++:1047700000000100010000890100010100000008A3 ++:1047800089A1018441010800000082C001010040AC ++:1047900001000102000040A00903031108200540A8 ++:1047A0001002090104840040A08820A18383834073 ++:1047B000A111C12183020882C003908582010804EF ++:1047C000C00004008301C1008300048810C10100FF ++:1047D0008590A18400030000002000000002000575 ++:1047E0008000000880050080002100000011020008 ++:1047F0001003100020001100404010401003110968 ++:1048000020808810108010408300110084910821BE ++:1048100008001000088000000421A0C0048283A0CA ++:1048200021A08385042103C0401183001183C1119D ++:104830004000C003C0059080008080A00020804020 ++:10484000800080000000890508041000000089082D ++:1048500005118200118905200011C004A004000484 ++:1048600000800400A0008080008009000800800013 ++:104870000541801080200904104000401100901074 ++:10488000050220048080110800820020C021004120 ++:1048900004050041C102830900008284888220C08F ++:1048A000A00540A100038503048883410221110271 ++:1048B0000808001100A0204182031108210005C052 ++:1048C00020410000410002000000800000000300C1 ++:1048D00000000002008541210005A00005019100B3 ++:1048E00000009008000809108208041000A00104CC ++:1048F0000804C00020019001000000000001000039 ++:1049000008010120414084840490C0849085020302 ++:10491000080200000000900091000000044005A083 ++:10492000830210030005A00485209108830109007B ++:104930000101100108880041C001400120000182EE ++:1049400001088304001001040010840404C0002046 ++:104950000020000000820840A04000400088009035 ++:1049600000000000821084824100C0880040008462 ++:10497000000000000084008400000000000001002E ++:104980000100000085008888090110C04010C0A106 ++:104990008821C000C1040490A083A001000011413F ++:1049A00020049182030983C183910483008900A0BC ++:1049B000A09001018440824141908500880100055A ++:1049C00000840000000200000000000000029001CE ++:1049D0008800100010101104C009100188C00000E8 ++:1049E00000000000000003402080A000880000803C ++:1049F000000000000000008000040010000008001B ++:104A0000111108404000900005C00804898300800F ++:104A1000008200400000838091040821800800008B ++:104A20008503088408829103A1A00808831040032D ++:104A30000311A12102401100828285880208112001 ++:104A40004190110003004000001100000000000030 ++:104A5000000300208008808003101104031083806D ++:104A600000880013C200000006420013C200424149 ++:104A700000000013C200000000000013C2000A8101 ++:104A80000042000BC20000420000001300000000C2 ++:104A900000000000C200008100000022C2000041AE ++:104AA000000000000004C20082900000001010000E ++:104AB0000A8800000010010007C400000008000080 ++:104AC0002100000000420100810011000013440099 ++:104AD000000000000042440042000000000B010002 ++:104AE000000000000000800000005F5F303FFFFF1B ++:104AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF20089C ++:104B0000100400C041C13C3C0303555F7D7F141479 ++:104B100014140000000005002D00FFFFFFFF552DBD ++:104B2000FF2D0000000002430F3F5F7F00010000E7 ++:104B30000000000000C2000200000000F8F830F0A1 ++:104B400028BE5F5F043C343C41557D5500000000A9 ++:104B500000000000000000000000000004AE404023 ++:104B6000585800A000000000000000005050303FE6 ++:104B7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:104B8000800240010000414100000303000F3C3F50 ++:104B900000000F0F00000000FFFAFFD200FF0F0F10 ++:104BA000002DAA2D00000000CBDF003C557D010147 ++:104BB0000100000000E10000000000000A0330F8DE ++:104BC000303028BE0F0F040034000014FFD700005F ++:104BD00000000000000000000000000000000404CD ++:104BE000EA40080800A00000000000000000FFFFED ++:104BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF69005A ++:104C0000FFFF22110000EBC328000000A000FFFFFF ++:104C1000FFBAFCFCF5BC00000000F0F03C3C0F0FBC ++:104C2000FFBEFFFFFFFF0000D7C3D7C38200808015 ++:104C3000404000C0008700000000020000000200A9 ++:104C40003F1D1D0C8BEB8B8B3C3C000000000000DB ++:104C5000000000000000FFFF000000002828F0F026 ++:104C600000000000AAFAAAF80000000000000000FE ++:104C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:104C80000069FFFF0000221128002800003C003CC2 ++:104C9000FFFFFF30C3C2C3C300000000AAAAFF0089 ++:104CA000F0F0FFBEFFFFFFFE0000D7C3D5C08200BB ++:104CB0000000000000000000000080008200820070 ++:104CC00002003F1D1D0C828B82822C202C200000B4 ++:104CD0000000000000000000FFFF00000000282886 ++:104CE000000000000000AAF8AAF2A08450F4A8B8BE ++:104CF0000005A08609E501B00800A0865070A0B0AC ++:104D00000805A0C450E108B0000000965265A0B8A4 ++:104D1000A085008600E000B000800086006008B832 ++:104D2000008505840A7008B800000000A086527152 ++:104D3000A0B000850080001100B000000086007067 ++:104D400000B000000186000000890080008670E04D ++:104D500000B800000086006103A00000008600602B ++:104D600000900000058600C00880000500000000DB ++:104D700000000000ACACFF0F55553C3C00000000AB ++:104D80003C3C0000000000000000000000000000AB ++:104D900000000000BEBEAAAA000000000000000043 ++:104DA0000CFF5DFF00000000000000000000FFFF9E ++:104DB00000000F5F3F5FF0FF55FF0F0F0F0FAAAA14 ++:104DC000AA3C00000000FCFCFF3C5C5C3C3C00009A ++:104DD0000000555500000000000028280000FFF8E2 ++:104DE000F8F88E828E82FEBEFAAAAEFF5DFF00004A ++:104DF000000000000000ACACF00000FF0F0F00004E ++:104E000000003C2C1000000000000000000000002A ++:104E1000000000000000BC3CA0000000800010006A ++:104E200000000C0C5D5D10000000000000000000A0 ++:104E3000FFFE00000F0A030AF0FF00FF7F3FFF3F65 ++:104E40003C3CAA3C000000000C0C003C5C5C55554E ++:104E50000000000000FF0F0F000000002F280F00CF ++:104E6000FF2828280C000C00FC3CF0005100A20098 ++:104E7000FF10000000000000F03C003C3C55FF0F1C ++:104E80000000000000000000FFAA00000000000079 ++:104E900000000000000000000000000055FF55FF6A ++:104EA000C300F2F00C0C0303FF00F0FF0000000051 ++:104EB00000007D7D0D0D3C550FFFAAAAFF00FFFFEE ++:104EC000FFFFAA3CACACAAFFF0FFFF3CFFF03CFFA9 ++:104ED0003F3F00000000AAC0553F00000000FFFF58 ++:104EE0000082000000000F5F3F7FEFFF10005AA517 ++:104EF0005AA5FF10001000000000F00000003C5513 ++:104F0000000F0000000000000000FFAA5500000094 ++:104F1000000000000000000000000000100055FF2D ++:104F200055FFC30082000C0C03030000F0000000DA ++:104F300000000000007D000D3C550F00FFFFFFFF4B ++:104F400055557FFFAA3CACAC0055000FC3000F00C5 ++:104F50003C00303000000000AACF553000000000B7 ++:104F60004F0F00820000000000553C7DFDFF020055 ++:104F700000FF00FF04001100030005A021404100D4 ++:104F80001100040021001100000041102000210048 ++:104F900011A01100090000A01190041021000010C0 ++:104FA0000400040000002100000011000020021095 ++:104FB00004000490000005000200040009900400B1 ++:104FC000000041000820030011000000200800003C ++:104FD000020002201100029004000088000000007E ++:104FE000200021000410119000000084000008102F ++:104FF000000000A00010900004000000004090009D ++:105000000000000000000400000084000400040010 ++:1050100000002000000020009000000000000200BE ++:1050200020000000C000040000090000040000008F ++:1050300000000000C000000000000000A0002010E0 ++:10504000000082000000000000000000C0002000FE ++:10505000000000000000001090002000001100007F ++:10506000100010000000A020000000000000000060 ++:105070000000000000000000000000000000000030 ++:105080000000000000200000000000000000000000 ++:105090000000000000000000000000A00020000050 ++:1050A0000000000000400000000000880000000038 ++:1050B00000000000000000000000000000C0000030 ++:1050C00000000082000000820020000000000010AC ++:1050D000000000000000008400200000000000A08C ++:1050E00000000000000000000000000000000000C0 ++:1050F000000000000000002000000000001004007C ++:10510000001100100040000000000011001100001C ++:10511000001000000000000000100041000202200A ++:1051200000200010040000110041000000000041B8 ++:1051300002210008002000000008000002410000D9 ++:1051400000000021022100030020001000000010D8 ++:105150008200001002090010002100000020020857 ++:10516000A000002000210000000900020000000251 ++:10517000001000100000000800410041201041080C ++:1051800041904100000000400000000000000000CD ++:1051900000104140000210002000000000000084C8 ++:1051A000044000000000000004104000000005085A ++:1051B0000000004000000090090003000000000013 ++:1051C00011400988000800000300210008040900BC ++:1051D000000040820084410200900200210009008A ++:1051E0004184000210844000008208100040081032 ++:1051F000101011020502210800824100000002097E ++:105200000400020000218800A041A000821000409C ++:105210000220100082410010000000000000000089 ++:105220000840000084051008000082008421C000AE ++:1052300000050440824010108811C008400500009D ++:105240008810841100118241000000118440004048 ++:1052500000401040004104110011C0050220C005AB ++:105260008205A0021040C00210020010C0400800D9 ++:105270000000C01000200008A00000000010000086 ++:10528000210005000584200020901088029008C0AD ++:10529000008210000800022000C0119000000300EE ++:1052A0000504008410A008000090008410904100C4 ++:1052B00000001000050000000000000000000000D9 ++:1052C000000000000500000010100800039010000E ++:1052D00021002000410000001000000000001088A4 ++:1052E00005001090400000000500000000101000B4 ++:1052F00040900000000000000000080000002000B6 ++:105300000000000800110010080000050000A021A6 ++:10531000000000000005C0050800000000100000AB ++:105320000000000000088220C0050000C04100000D ++:1053300000000209000088058808004102000009F9 ++:105340000200000010000000881140090000022146 ++:105350000010A00884000004842108400241A0003D ++:1053600000102000021002008802C020A0040000EB ++:10537000000200110004C000080000008440101169 ++:1053800010001010030200000000001010000500C3 ++:10539000000000004182000000C000002000411019 ++:1053A00000021000000010000000030203000000D3 ++:1053B00000020000040204080000001010000000B9 ++:1053C0000010002000000800090009000040000053 ++:1053D00000000090000800000000000005820000AE ++:1053E0001008030000000002008208000002000014 ++:1053F0000084000000000000000000000000000029 ++:10540000000000000000000000030040400904000C ++:1054100002090240A04182000002C0000021C00930 ++:10542000000090030000002100008411002184414D ++:10543000100000414010884140100005404100111B ++:1054400000008403901100004021C010C005020933 ++:10545000001000050403A0100021000502119002B5 ++:10546000040984410041022184038221004140401B ++:10547000000082090000C000900988008400100923 ++:1054800000108400001000090088108800400010FF ++:1054900000000000100000040000000000C0000038 ++:1054A0000800000040000240100000020000200040 ++:1054B000008809001020004000000000410000406A ++:1054C0000000100000000000000000004100110476 ++:1054D000000009C000000200102000001190000030 ++:1054E0004100218800000020100000002100000081 ++:1054F00000100000008408002000100008000500D3 ++:1055000000000000000020004100020000090040EF ++:1055100010090000C04110100010000000008410AD ++:105520000008000000210000080082100005C000F3 ++:105530001041000000419040000000000000020007 ++:105540000000820000110021C04000000241000064 ++:105550000000002182208411040882000000000362 ++:105560000005C02000000041C0208840000000006D ++:1055700010000000202084110000020004008800B8 ++:10558000082010008420020084001000FFFFFFFFAD ++:10559000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:1055A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:1055B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:1055C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB ++:1055D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB ++:1055E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB ++:1055F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:10560000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00BCEC ++:1056100022200C44801000000A06000060180800D8 ++:105620000200020411000000040004000404000051 ++:105630001100200005040000040004A02100040063 ++:1056400004000000000000000420112004000304F6 ++:10565000042000008000000004000400849000008A ++:105660001004829000A082088410801004000008BA ++:105670000000032003900209200004C004200090D1 ++:1056800000082108030004000404000000020004D4 ++:1056900020A01120000440900440000041100000B0 ++:1056A000000008400480200082000100000001800A ++:1056B000002100000500200500000000000000009F ++:1056C000000021001000000000000080A080000009 ++:1056D0000080008000002000000000000000410069 ++:1056E00000400180410000111080210010002100C5 ++:1056F000000004000490C00000208500010000802C ++:105700000000000000000010000000800000208069 ++:105710000080000000800080000000800000004049 ++:1057200000000000000000C0000000820400802093 ++:105730000020000000000020000100C000A00000C8 ++:1057400000200000000000018000000800000000B0 ++:105750000000000000000040002000C00000000029 ++:10576000000900C000C18003000500020000000322 ++:10577000000000200000800000A000000001802048 ++:105780008000000000008001001000000000000008 ++:1057900000000011000100010000000100A0000055 ++:1057A0000240000004110010001000000000010879 ++:1057B00004A12000001000100010000400210000CF ++:1057C00082000090000000100020042100089000DA ++:1057D000000390200009001000A00000000000203D ++:1057E000001000820000000220820084008800086F ++:1057F00000C00000001090001020000900000020F0 ++:1058000020212008000000000420900000109010CB ++:10581000001002410040001000048210002000210E ++:1058200000000141000000050000850810A00940AB ++:1058300009200011110011000090000100000484F3 ++:1058400004820420040200100308001000110284E6 ++:10585000008400C00010000000000090004021A162 ++:1058600010A01001004000002000A0C08040A00453 ++:10587000204109010001000900C0000000A0020051 ++:1058800005000401001100411010002004200084D4 ++:105890000500214000102100000440A02085208543 ++:1058A000000010001000400000409011048491108E ++:1058B0000090008000200011000000100002000095 ++:1058C000010501000180014100000000000000040A ++:1058D00001100010004000000000000800000085DA ++:1058E00000400110010800850000010011001000B7 ++:1058F0002180834000081040008288008408004016 ++:1059000089210010C120002000A082000000018039 ++:1059100000000000000000400040A0000100012045 ++:105920000110000001000100010000A01000410072 ++:1059300008A11100410000001020000010A000008C ++:105940001000400005000900410000201000100078 ++:10595000100480010400040004000001090010008C ++:105960001000020000018200000000001000100181 ++:105970008001020009011001412010209000410027 ++:1059800009004100040000840900A0890201100000 ++:10599000002000000300040090000040A10010005F ++:1059A000108400000900110021000000A009C005BA ++:1059B000200082200005000300090085000400117A ++:1059C000004000210041C021001010058284000326 ++:1059D00090100080024000000000000000400041E4 ++:1059E000001020000121C040100084090000900038 ++:1059F000C0082008850484040020008010A104054C ++:105A00008204001084080520002184000204004064 ++:105A1000000000058410880001000420824102007B ++:105A200000000800840288110000000400108000BB ++:105A3000000000A0101100008420410088000088B0 ++:105A400000C00020080200084084080008821100FD ++:105A5000008200024108110104001000000200C091 ++:105A600041020040098410C04108C1891020000093 ++:105A700005842011A0050510008908000800840095 ++:105A800002820500800008008008109104050820AB ++:105A900041820388038400000400050000004100E7 ++:105AA0008582880100028388410010000000830085 ++:105AB00020080000000000200000218000000400F9 ++:105AC0000000000000000000880009000000000045 ++:105AD0000000000000000021004000000000000065 ++:105AE0000000000000000000011000C10808008054 ++:105AF00000000800010821840003000400000010D9 ++:105B0000050500100000040000100410000201A0B0 ++:105B1000008000000000000000000000880000007D ++:105B2000000002002004000040000000000000000F ++:105B3000400041A02084202000200084009000200C ++:105B400002200008080000851140008440100288EF ++:105B5000801000C0001003100000000000C0000210 ++:105B6000020404828200880083000540000800824D ++:105B70004100000020044004020010080411041039 ++:105B8000048440080488088420C020408000200845 ++:105B900080841004028420900083000020000240D2 ++:105BA000020004000200200008001004000180210F ++:105BB0000408210500000002828304090041844199 ++:105BC0009080009000000003C004008000050003E6 ++:105BD0000000200310008809880000000041000533 ++:105BE00000000080000020002000080082A10000CA ++:105BF0000000000000000180018005040183832073 ++:105C0000A100A1008291100000418800844020037F ++:105C1000C1912000C080010084204040A00000000D ++:105C200000800000890001000000010010208402B3 ++:105C300010021021840202008200A100038010855E ++:105C4000A020044041088003C004084100210980CD ++:105C500040000400418080008080040000808003B8 ++:105C60008009080800808003000908004040A183E3 ++:105C70000090408502000080C0030909C002A0090D ++:105C8000418300C10285038500059008A003004000 ++:105C900008080920411140410080000000800000F8 ++:105CA00080114120040502410283200900050903F7 ++:105CB0004083832141C00988018421900290000221 ++:105CC000010820A000A101092000820100010000BC ++:105CD00000880082418401100204080800A000042A ++:105CE000088304890021002020914005208241037F ++:105CF00041838409010900400000910101018501EF ++:105D0000410191C1A0852141000800014001090025 ++:105D100000000001410188010101008200400010E3 ++:105D2000000240010801020100010183A0910090DE ++:105D300001C0410509040205000482018400218894 ++:105D40000500080020008900100484004000900134 ++:105D50008800830101008908848504100300040081 ++:105D6000050408002184A0218503020105880300A1 ++:105D700009A0C1000300A00102880000910009836E ++:105D8000C00089200909A10020908508C0040408EA ++:105D900004A1400110901082A1118800020190001E ++:105DA00002000002010001C001030140C001910096 ++:105DB00011048283050040008308850003408202AD ++:105DC00089808800100884008500A10088001100E7 ++:105DD00000031100110208009000040800041000E4 ++:105DE000000089800921410000888309800888001B ++:105DF000100083402011A00091058541000091040E ++:105E0000099080038390C010C0000900901000002A ++:105E1000000000C00008020003840590030400088D ++:105E200000000000000011052000058241800540AF ++:105E30008200A1808089020082002080C10000844D ++:105E400080909182809020028040009003904000DA ++:105E500000020989400900080040808200A000007B ++:105E600000004000008009090008C08900030808FC ++:105E70000000118900030010800220020088000049 ++:105E800009C00004400985032041900304028504F1 ++:105E900008000800038083000904040504204189E8 ++:105EA000000080008500000002082180418041033D ++:105EB000858500910009A185032080A00021A141D2 ++:105EC000200208C1820504890100100820A18889E8 ++:105ED00001880085018408A000900009A0A188899C ++:105EE0000004020204900004009040C1C10300219C ++:105EF0000109889088090089009182088308A0A17F ++:105F0000000091090001000390030108038882A1A9 ++:105F100083A000A000900084C0C091020084000310 ++:105F200004A00000C000850008000121010800084D ++:105F3000859140C0040500A191820101104140C13A ++:105F40009005000204410001008800402000A001EB ++:105F5000C08801900101000000020041880010008B ++:105F60008808020804A0820002C0858883210800F6 ++:105F7000C040838911008501080440908301048496 ++:105F800090020000018941080100049009050409FC ++:105F9000C00040200100001000000182000201103A ++:105FA0000084011002008200900020080500218971 ++:105FB000040210008200A0C1A088089000000085A3 ++:105FC00000010002000380100040008000008009F2 ++:105FD00080020000030805080402028000038020FC ++:105FE0008020000000890000000800808391048860 ++:105FF0008000000083C08400C04000000004100541 ++:106000008491008000002089C180401182000989AC ++:1060100080408003800002091080040010804185C8 ++:10602000110220C1208000050000800000C1030093 ++:1060300085080341820080200091008580000005D2 ++:1060400000850021000000000013C200008800004D ++:106050000013C200000000000000C200068482009D ++:106060000013600021001100001344000000000034 ++:1060700000131000000000000013440000000000A6 ++:10608000001000000A00000000000000C2004200F2 ++:1060900000000022D000004100000042000000414A ++:1060A0000000001002008200000040130000000009 ++:1060B000000000080100000000000042C200006073 ++:1060C00000000000000042000000000080BF00004F ++:1060D00000000000FFFFFFFF2424CF0FFF0F000F81 ++:1060E000000000006E660C000000000000000000D0 ++:1060F000FF000000FC0000000F000000FF00000097 ++:1061000000060006000000000000FFFF6F2F00C324 ++:1061100000000000FFFFFF67FF0366660F0F00002F ++:106120000000B818BDB86FFC60FC00000000000063 ++:106130000000333C6A66C3C33C3C0000000010080A ++:10614000180000000000FFFF6E0C0000000000FFC0 ++:10615000000000000000FFFF666E2424CF0FFF0F39 ++:10616000000F000000000C000C0000000000000008 ++:10617000000099000000FC000000FF000000C300C8 ++:106180000000000600060000400000006F2F6F2F87 ++:10619000000010000000FFFF676703033C3CFF00A6 ++:1061A00000000000B818B8186F0C600C0000000068 ++:1061B000000000003C3C66663C3C00000000000023 ++:1061C00018001800000000006E0C6E0CFFFFFFFFAF ++:1061D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:1061E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:1061F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10620000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10621000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10622000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10623000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10624000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00F468 ++:1062500043930C44801000180A060000906500006B ++:10626000000000000F0FFFFFFFFF00FF00FF60E3D3 ++:1062700060E3FEFEFFFF00000000FCFCFEFC0000EF ++:1062800000000000FFFF000000FF0000B0B00000B1 ++:10629000003C000000FF00F0F000607CFFFF000009 ++:1062A00030000000303000003076000000000000B8 ++:1062B0000000818100000000F6FFF6FF00C33CFFF4 ++:1062C00000000000000000000020006466565696A2 ++:1062D000FFFF020D04080C007E3E8101FFF4000B5D ++:1062E0000000000000001F07F6FFFEFF60FF7CFFBC ++:1062F000606060E3FCFCFFFF000000003C3C7E3C73 ++:106300000000000000000F0F0000000F0000B0B000 ++:10631000000000FF0000000F00F0F000607C607CD7 ++:1063200000003000008100000C0C30306666000078 ++:1063300040000002818300000000F6FEF6FF009F8F ++:1063400060FF0000000000000000000000246666FE ++:106350005656F0F000000404000CBD3D4202FF243C ++:1063600000DBA08600F0A8800000008600210880E5 ++:1063700000000886006008B00000008600800188E8 ++:1063800000850086000101800803C0C7C02130A03D ++:106390004903C0C7C0A130B0430300860A6100B002 ++:1063A00000000000A0865A70A0B900A500860AE18E ++:1063B00000B00080008600E100B00000A18650F12E ++:1063C000A8B000850086002100A00000088600E03B ++:1063D00008B9000000020A310880001000860A6037 ++:1063E00000B80080FFAAFFAA00000000BFBEBFBE29 ++:1063F000FF05FFF50000000005FF0DFFFF00FF0097 ++:1064000020A07FFF2000000000000004FFE3FFA0A9 ++:106410003DFF3DFF0F0FFFBEFFFFFFFFFEBEFC3C39 ++:10642000555DFFFF000000000000000000147F2009 ++:10643000FF0014FF1FFF000000007FFFFFFF0000B0 ++:106440000000141EFFFFFFFFAAEA0000000050003A ++:106450007C3C3C3D000503FC56AA0C3F33CC0000BD ++:106460000000F0F0F0F0FFAAFFAA040001001F14E2 ++:106470001F140505F5F50000000000FF0CFFFE5499 ++:10648000FE5420A07FFF0000000000000000FFA0DD ++:10649000FFA03D3D3DFFF0F0FFBE7FFFFFFFFAAAEA ++:1064A000F000000CFFFF00000082008200000014DA ++:1064B000FD08FF0000FF0FFF000000000FFF0FFFAF ++:1064C000000000000000EBE1FFFFFFFF0000000004 ++:1064D0005000500000050005CF309AAA000033CCD0 ++:1064E00000000000F0F5F0A00000F0E00000006007 ++:1064F000AF3FAF300ACB3EFF000000000C5D5555AA ++:10650000FFF00000003C00FF20000000000000043D ++:10651000000000007FFFFFFFFFBCBCBC58F85DFD22 ++:106520003C3CAA000F3F5F7F000000000000050513 ++:106530000D05FFBCFFA07FFFFFFF000000003C3CFB ++:106540003C3C000000000F550F55C3C300AA5FDF9D ++:106550005FDF00000000000000000C00F7FF04FBFC ++:1065600059592F0F28005F3C0A3C0010F0F0000042 ++:106570000030A03FA0300ACB3EFF000000000C5DC1 ++:106580000000FFFC000C417D00FF00000000000047 ++:106590000000000100005FFFFFFFFFA0A0A008A80F ++:1065A0000DAD00003030003C557D000000000000C3 ++:1065B00000000C00BCBCA0A03CFFFFFF00000000DE ++:1065C0001C3C3C3C000000003C003CFFC3CB00AA4C ++:1065D0005F5F5F5F00000000000000000C00F7FF3D ++:1065E00000FF555528002800AF3C053C044011052C ++:1065F000041004048400020004A00200031004003C ++:106600002020840091000800000904000200110409 ++:106610001100210000881101040411000000020093 ++:10662000002004200000000003100400000004907B ++:10663000040021082100C0048408800821200300F0 ++:1066400011000000040020012000914021020401FB ++:106650008421000002A004401100001011A00020BD ++:10666000002011C00204000411002100112000804C ++:1066700000C09000A0801000000000002100001069 ++:106680000800048004000200000000020000000076 ++:1066900000C1000004000000102000800000020083 ++:1066A000900000000000080000000000A011004061 ++:1066B0000000000000002000058004800408008223 ++:1066C000200008008400001000080100208088805D ++:1066D000C00805A0900000000280000000800000BB ++:1066E0000480008000008291000000000000828091 ++:1066F000001100010001804100A000200000000006 ++:10670000008200018010002100100000001008012C ++:106710000000000000008010000000C100A0000088 ++:106720000000000000200000000000000000000049 ++:1067300000C00000042004C000000001000100218E ++:106740000020000000000000804000000001000068 ++:106750000040100000008040800000008000000128 ++:1067600000A01020000880000000000000002000B1 ++:106770000000022000200220202000030041001021 ++:1067800000210011902004080220000000110011D7 ++:106790000020001100000021204100100004001022 ++:1067A00000210010000000A1020000100041004183 ++:1067B00000100000000000100000901000200040B9 ++:1067C000A02000A0000900000041201000100002DD ++:1067D000001100900121001020A1201120000200D2 ++:1067E0000040001001100090041000110041000052 ++:1067F000010000100301000209A0418800200220CE ++:1068000021090020000020022000002000840090C8 ++:1068100000840040008400000002000400C000105A ++:1068200000840010001000080921008800A00082E8 ++:10683000001000080000041000A000C009000000C3 ++:10684000009000008002000000100440000000A042 ++:1068500020042082A0400000002000A009100010A9 ++:1068600000840020101000840001000304200010A8 ++:10687000800200C000A090400440400084000080DE ++:10688000008000A0848200000111090584A110414C ++:10689000004110000010000300080000009082007A ++:1068A000A000002000401003C00800208200100259 ++:1068B00000050002004000000011C0218805100002 ++:1068C00088028800881004110203880582C18800AC ++:1068D00000400140A1110920000010A11000C000DB ++:1068E00082001000C000000390038220C0A0C1C03D ++:1068F00000000400900090000300200120000884A4 ++:1069000041010000410010000000040141018084A9 ++:106910000000100040104100000082C09000A10063 ++:106920000000000000001000020040002000C10034 ++:10693000030011000310030000000000100010000D ++:1069400008000000008410C00000080010000900CA ++:10695000020002000300100020844100100020000B ++:1069600005000200080008000800002003000001E4 ++:10697000800003004000100480000000A104010911 ++:1069800000000040000000210000000089200020DD ++:106990000441000900000100000500212000200042 ++:1069A00002000000000200000000000000000000E3 ++:1069B00004100010000900218800000000000800F9 ++:1069C00000000000000000090000100800000000A6 ++:1069D0000000A00000000005000001000000000011 ++:1069E0008240C000A12100000005000000800000DE ++:1069F00000080400C00001000080020004A0100094 ++:106A00008005041000820000820080009041000494 ++:106A10000008800400000400009000C000821010F4 ++:106A2000050480C0102010840002004010821082F3 ++:106A30000000032020080002000800A00000410020 ++:106A40000084410003A000012021410291100000B8 ++:106A5000100241101085008420044182058400202A ++:106A60000400030010C000000001050880824100FE ++:106A70000200000410000484C000C10120828510BF ++:106A80000000048401090009101004404020200483 ++:106A90008288400320830010000000104011100085 ++:106AA00000000080100000000040C0110200001132 ++:106AB0000400104100908400100084410010000088 ++:106AC000000084000000A003044084C0A0801040A7 ++:106AD000A00020000011010400110180900200219B ++:106AE0000000030000000021C011A01000210200DE ++:106AF000000001000003000011002100202011000F ++:106B00001100048400040204001000C040844110FD ++:106B100000C04000058241840021051021841040FE ++:106B2000000080840000080200A080010020021004 ++:106B3000028400080911004000082082008241847C ++:106B4000000000C0020002100588000000400200A2 ++:106B50000010001041C021084140200010001082A8 ++:106B600010820010C10090900040004005100910F4 ++:106B70000020008420000205004010A0200020001A ++:106B800003840010010000800180900000000000DC ++:106B9000000004000100000000009004000000005C ++:106BA000018004002000000000100000042000000C ++:106BB0000900020200000020009000000010000008 ++:106BC0000000004000000003000000000000008002 ++:106BD0000005088000000000000008C140000141DD ++:106BE0009100A000000020002000000000800400B0 ++:106BF00000000000000010000008088000000100F4 ++:106C0000010000000800094021414041409080C13E ++:106C1000A1021141800040001000000082804080ED ++:106C20000880410040008000210008000405800821 ++:106C30000808100405000500C10004000000000061 ++:106C4000000000000080800000000000000088823A ++:106C50008541C00908840000000010000000C00346 ++:106C6000852020402000000020000200000000805D ++:106C7000008000000000091040111108004120119F ++:106C8000A020A10303050100210388030102A089BC ++:106C90000820080500C02000C10001000000090212 ++:106CA00084C0019001C00100040000000100000147 ++:106CB00002002100010140009000110000000000CE ++:106CC00000000000000000008200008400000000BE ++:106CD00003408484110200840000C0000100000011 ++:106CE0000501820101000100A000850000000000F4 ++:106CF000008202080000000488010000A0010001D9 ++:106D000000010500C100000108C00900C110090010 ++:106D1000010400A0004001008800C000880000C0FD ++:106D200000000120018800000100000001A0010115 ++:106D3000010000900110000041082100048283003E ++:106D40000000000100000000000000000020000022 ++:106D500000002011C08841A1840400408800A000E8 ++:106D6000400009008400110005C0C1000900A10015 ++:106D7000859000000000C000400800100000008264 ++:106D8000014005100300C0044101000340001080D1 ++:106D90008900200041002004100020000508A00008 ++:106DA00021831100100005082003110004081000C1 ++:106DB00020100200400004C10300910008000200FE ++:106DC0002000000000080000000000000000000596 ++:106DD0000000000003844021A09040894080020010 ++:106DE000200005031120C1008200838010004005AF ++:106DF000A000C103000900000000808000410000E5 ++:106E000000040980918090002000830903C01000D5 ++:106E10002090C04102058803A041C1850000000008 ++:106E20000880808000808083400880A0008800A0C7 ++:106E30000283804020214100102182050090111022 ++:106E400008900008000000000000000000000000A2 ++:106E5000000004048000049008100482020880806E ++:106E60000000000000000240008005000883008050 ++:106E70000000028080000000000080000080080305 ++:106E800004040009104002850403052083830109DE ++:106E9000010804850320018809C0020421890290A9 ++:106EA000000000A002880002020220018209000501 ++:106EB000000901A004C000820120010811A10009FD ++:106EC000018900859089000000000000000000009A ++:106ED000000000820105200082050203C1410891E3 ++:106EE000A002000000A00090010500100190100514 ++:106EF00000400000010202A000C000A0900000823B ++:106F000001000011000811080104008401A010050F ++:106F100084040401400090080040012101000000A9 ++:106F200040218805900102020100000001000100DB ++:106F300000900010000000000000000000010100AF ++:106F40000010000000010020000000000000000010 ++:106F5000000082020083008500008388A120840055 ++:106F600041C000040000000100088320C089C00166 ++:106F7000040504898401A00084C04084840040008A ++:106F800090000340A100080004000002001100006E ++:106F900000C080A080048004000021800904082033 ++:106FA00004000003801000028080030021022003FF ++:106FB0001000000000A1000400004100042121088D ++:106FC00040000082004000020000000000000000BD ++:106FD000000000000080000400210000832005055F ++:106FE000A005A020008300100002008088058340D7 ++:106FF000A10380858803002180208000008000009C ++:1070000000000000030005008000090000C10082AC ++:107010000011000021000013C20042000A0000130A ++:107020000000000000820013C2004200008400063D ++:10703000C200005000880000C200000006000013DB ++:10704000C20000002100001300000000000000004A ++:1070500000000000000000000000000081000000AF ++:107060000042C200000000000000C20000000081D9 ++:107070000000C200825000000013C2008200000025 ++:1070800000210000000000000080C200000000009D ++:107090000080D0000000000000007DFF7D7D15977E ++:1070A0003DBF143FD73F000000000000000000017A ++:1070B0000002000F050F000000005FFF7FFF7D7FD3 ++:1070C000FFFFFFFFFFFF00000000040F0F0F000095 ++:1070D00000000000000000000000000000000000B0 ++:1070E00055553CC31FDFDFDF00000000000000003B ++:1070F00000FF0F0F82820000FFFF00000000000071 ++:107100000000000000000000003C0055000F353575 ++:10711000000000002000270F0000000041FF414157 ++:10712000018329AB1403D703000000000000000016 ++:107130000000000000000505000000005F5F7F7F89 ++:10714000555FFFFF3C7DFFFF0000000004040F0FB0 ++:10715000000000000000000000000000000000002F ++:1071600000000F0F3CC31F1FDF1F000000000000C6 ++:10717000000000FF0F0F14142828FFFF000000007C ++:1071800000000000000000000000003C0055000F5F ++:10719000353500000000FFFB0F1BEBF3EBF3FFFFA7 ++:1071A000F5F000BF00000F0B000000000000FFBA68 ++:1071B000BABA00000000FF30FFBA00000000FFFF75 ++:1071C000FEBEFFFFFFFFFFFFFFFF00000000FFFF0D ++:1071D000FFFF0000000000000000000000000000B1 ++:1071E000000000007DFA7D50BCBCA0A000000000A3 ++:1071F000848484FF00505FFA0000BEBF00000000DE ++:10720000FFFFFFFF00000000000000000000000082 ++:107210000000FFFF5A5A4E5AFDEFA99AAAF0AAF0B1 ++:107220005F0F550040FF00000F1F0000000000002E ++:10723000FF30303000000000FF30FF300000000061 ++:10724000FFFFBEBEFFFFAEBEF828F000000000004A ++:10725000FEBEFC3C0000000000000000000000003A ++:1072600000000000000028FA2850FFBCA0A0000089 ++:107270000000FF8484840050000000F0FEBE000087 ++:107280000000FFFFFFEA0000000000000000000017 ++:1072900000080000FFFF5AD85A5A0210A99A008627 ++:1072A00000E109B00000008602E101B00000A08604 ++:1072B0005035A88000850886006508B0000000866B ++:1072C0005074A8B80005008600E109B000000086EF ++:1072D00000E101B800800000000000000000000094 ++:1072E0000000000000000000058600F108B8000062 ++:1072F0000086006008B0000500860A6C08B900A08E ++:1073000000865020A8B000000084006100B000009A ++:10731000058600E100B00000008600F100B9001011 ++:10732000B8202000FFFFFFFF00000000550F550FA1 ++:10733000FFFFC0C07D3C7D3C000000003030353593 ++:1073400000000000AA0F280C000000001400140028 ++:107350000000000005FF3DFF0000000000000000ED ++:107360000000000000000000000000000000001409 ++:107370000F1F00000000D700D7C3FFFAFFFF14144F ++:10738000141400000000FF00FF00F0F030000000C7 ++:107390003030FECEF2C2A000000000000000141F3A ++:1073A000FFFFB820200010FF15FF00000000003C88 ++:1073B000FF3CFFC0FFC05500FFFF000000000000C1 ++:1073C000050500000000AA0FAA0F0000000000053C ++:1073D00055050000000000FF00FF00000000000055 ++:1073E0000000000000000000000000000014001079 ++:1073F0000014001400000000140014C3FFFAFFFE84 ++:10740000041414140C0C000CFF14EB00F0F02020FA ++:10741000030300003E0E3202A00000000000000046 ++:10742000141F141FCFFCCFFC3C3CFFFF7F757A700C ++:107430000000000000000000AEFEAEFE14140000CC ++:10744000000000000000000000000000000000003C ++:107450000000000000000000555DFFFF000000007C ++:107460000000000000000000000000000000FF7CA1 ++:107470007C7C000017C3000000000F000F0000001C ++:107480000000FFFFFFFF000000009FFF0F6FFFFFE6 ++:10749000FFFFFFFF00FF00000000000000000000F1 ++:1074A000000014FF1FFF00000000555FFFFF2F25A5 ++:1074B0002A2000000000000000000CFC0CFCF4146A ++:1074C000F0000000000000000000000000000000CC ++:1074D00000000000000000000000000CFFFF0000A2 ++:1074E000000000000000000000000000000000009C ++:1074F000FF3C3C3C0000170000000000550055FF19 ++:10750000000000007FFFFFFF0000000090F000601F ++:10751000FF003C3CFFFF00FF0000000000000000F7 ++:107520000000000014141F1FFFFFFFFFFFFFFFFFFD ++:10753000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B ++:10754000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B ++:10755000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B ++:10756000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B ++:10757000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10758000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10759000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:1075A000FFFFFFFFFFFFFFFFFFFF0070BC080C4461 ++:1075B000805000000A0600002409080004000401AD ++:1075C0004004031084200020040400000000000098 ++:1075D000040040001000040011C0000004008020DE ++:1075E000111011001100200002108000009000C056 ++:1075F000020000000400400020080000020000C05B ++:1076000000092120040010110200110100000200F5 ++:10761000020003001100040104002010080040884B ++:10762000C0002000040011100400400011000200FE ++:1076300020000001200003002000000000002000C6 ++:10764000000802800000208084802080000200006A ++:107650000000010000000100000000000005000023 ++:107660000400000000000000000001000200000013 ++:10767000000020000000200090000000000000003A ++:107680004000004084000000012001004020000074 ++:107690000000000000000000004090000100010018 ++:1076A000410004000100000000000000000088000C ++:1076B00000000100000200000000000000000000C7 ++:1076C000000100000001000100000004002000A0F3 ++:1076D00000218000002000000010000100030020B5 ++:1076E00000000010800000C1000000200000000128 ++:1076F000000080A10021000000882000000100C0DF ++:10770000000000C00001004100A0000000A00040F7 ++:10771000A0040020800000110000001000200008DC ++:1077200000008010000000400008000000000088F9 ++:10773000000000030004000000000000000800C07A ++:107740000021000402200020002000108282020894 ++:1077500000100020042100900021A0A10220A0A080 ++:1077600004C1000000084021000404109020A01172 ++:1077700000040241024000840010001001000004D7 ++:10778000000000000221020402A000000008001016 ++:10779000009005800010082000400021902000008B ++:1077A000022100111021C0110080000000210008FA ++:1077B00004208200008800A10020001000100010AA ++:1077C00000210040009000C000844102000400102D ++:1077D00000100082001000032084008400100002CA ++:1077E0008004020280A000A0009000C0008400C0BD ++:1077F0000000008420C000820002000200A000847B ++:107800000010000000C00020008404C08020004060 ++:107810000041400921840310034082102110218877 ++:1078200004200008000200024010000200C0008492 ++:10783000008200880000001000008004004000A0CA ++:1078400000000040820000008400002084080088BE ++:1078500084000003000000058820010000081000DB ++:107860000021400082410403100000210008002193 ++:107870008200C041000801108208000800050000D5 ++:1078800040408400000084000090820210090480BF ++:107890000000100890A084000085841021050000DD ++:1078A0000010001000400441C0020040C021000848 ++:1078B0000400C000040090000200020020800000CC ++:1078C0000800004000400000200000000500800883 ++:1078D00020000800418420820400052041902100FE ++:1078E000030020002000110003000500040900002F ++:1078F00000004100000020000000410020000300C3 ++:107900000300100008000000030004000000040051 ++:107910004000080009011000032020830004020138 ++:1079200000C008002000001009000000000010A1A5 ++:1079300000C020002000030221002084002011004C ++:107940002100050010000800841085008203A010AB ++:107950000800000300030400004183100880A041D8 ++:1079600000008409080500100000000008008920BC ++:107970000811004102000000012108000010C105AB ++:1079800000410005822102100000000001000810E3 ++:10799000010001410800A0080000C080C004008868 ++:1079A000C0040800000009000041004182000003FB ++:1079B00008040005A0000041000000000000004194 ++:1079C000080082000000A00000002082039021082F ++:1079D000030000A000A04088059000C041400302C1 ++:1079E00008200082410008020003400041100910F5 ++:1079F0001000000020841104100800C02010200591 ++:107A000010401140020004001008000000001000A7 ++:107A1000000202044000218503C104020240040266 ++:107A2000000403A0030000A0081041C01040400063 ++:107A30000004000400000000084080840000C088AA ++:107A40002020A11008000390050041000000000064 ++:107A5000C01010008441C000000088000011000028 ++:107A6000001100800005000082212008C0000000F5 ++:107A700000050000000801000090000300000188DC ++:107A800001C00210000000000000900000C00005CE ++:107A90000021002000C001211020882001050000E5 ++:107AA0000105008000050000900901C010400000A1 ++:107AB000010000800085840000110400100000090E ++:107AC0004100899020110009C000C0211021101030 ++:107AD000030020004120000000C01084030000A02B ++:107AE0000810001090000310000041C00000112099 ++:107AF000000005080400100400040904000400004C ++:107B000000840002040090108008000000000000C3 ++:107B10004100100400C0C100038408109020002020 ++:107B200000840484A100008402C005040090028443 ++:107B300020C0000280820010000000000000002031 ++:107B40000200100010041000100010000800800057 ++:107B5000000000000008000082210041C021C04157 ++:107B6000A000820000000200000000000000A00051 ++:107B700090110005000000000080828000A182803A ++:107B80000009C0000800C10920002000C009004110 ++:107B90000000001082800010040500000040114128 ++:107BA000A0000000010008001041010000A18400B5 ++:107BB00005400000208002000000000010000000CE ++:107BC000000088001000880008000000000000008D ++:107BD0000200210900090008100888918209C010DC ++:107BE0004140000000000000000000039111C104AA ++:107BF0000020008880110908000808004108402082 ++:107C0000404008118009008208888003114100214A ++:107C10000340000002028009830440408002000209 ++:107C20000910032000800900008000000989C009B4 ++:107C3000104140040205000809110920000000005D ++:107C40000000000091039100020841020000800042 ++:107C50000800000000000001200000000888410921 ++:107C6000838301880000C000900000000001030031 ++:107C7000A10000010089C008020400050100000104 ++:107C800000010101080002210009000410010001A7 ++:107C90000001010000008901C00108000101880005 ++:107CA000840089000001888201A000040010008285 ++:107CB00020A1850501000101040000000101000070 ++:107CC000000000000000910191000100010000008F ++:107CD000C00000000000010000890001010009004F ++:107CE0008289888983C10000000000880100820029 ++:107CF0009100890240000400C09088000804C00080 ++:107D00009082C101030004000984110009000100F0 ++:107D10000182018201010000100084002002039111 ++:107D20000890C000081082000001000100000088D7 ++:107D30000401050090A0030905A005824104830108 ++:107D40000100010001000000910091008900830002 ++:107D50000800820008C0A00008001190001009006F ++:107D6000C00904828010898500000000000009001D ++:107D70000000910089800504000880408011000403 ++:107D800000000880A020890008000800080489007D ++:107D90000200418021800303000088118900020055 ++:107DA000891180008000808080090010000400009C ++:107DB000001109024100400090098200C080211199 ++:107DC00083090800410010004121910091008900C1 ++:107DD0008300800000000000004108400003000212 ++:107DE000C00002000020900911090000218000005D ++:107DF00000001000000040809180200080000400FE ++:107E000008800820000409A04000020200820489C2 ++:107E1000889103020004030200030080049010090B ++:107E200040090840208810800000088380800000FE ++:107E30009000008002020040C08910100340112011 ++:107E4000218911400000000000000000409100A1C5 ++:107E500000A1C08300000000050000000100000038 ++:107E60000001830001C08841A003880200040008CB ++:107E7000000420A00182000400A0898201040804FB ++:107E80000808088800410009008501A021A0900988 ++:107E9000A0A1888201010001010100010080000908 ++:107EA0000120009121C001900188000290C1821040 ++:107EB0001090A140108201910088908501830103F8 ++:107EC000000900850805000000000000080001917D ++:107ED00000A100A1898300040082010800080110AC ++:107EE00001410000010041018891000001080000EB ++:107EF0000000000000000004000100010088831160 ++:107F000089000900091001080005010101400088ED ++:107F10000108000000100182010001110000008032 ++:107F20008211820888010890000000A000000088EB ++:107F30008802002090008800040010C1200040103A ++:107F400001A0018500010004000000010000000103 ++:107F500000910001000100880001000000000008FD ++:107F60004000081040000800100389084005080080 ++:107F70000000000900110000000400410002008020 ++:107F80001003C100900090800909000840400400DF ++:107F900020820404080811000380040002834010BA ++:107FA00000808083001100400000000900000000F4 ++:107FB0000080008000008000000080118002000529 ++:107FC00080800800401120401180000000410041E5 ++:107FD0000008009100410002008000200000000025 ++:107FE000000000410013C200004182410013C200A2 ++:107FF000118182000013C200000000000013C200C3 ++:108000000000810000130000820000840000C20014 ++:10801000820000600013C200000000000000810028 ++:108020001242000081820013C200420000000010D2 ++:1080300000000000810000138100410000000013D7 ++:10804000C200000000000022C20021000000000069 ++:108050000000000000000013C2000000000000004B ++:1080600000000000FFFF7F7C1E181E18FF7FFF67C7 ++:10807000FFF0FF0000000000000000000000000012 ++:10808000000000006F7E097E00000000FFFF00007E ++:1080900066F666F6FF00FF00FF006F0000000000BC ++:1080A000000000000000000000007F107F100000B2 ++:1080B00000003C3CC3C300000000000000000000C2 ++:1080C00000003636360042424F42090009000000E7 ++:1080D000000000000000000000006F6F6A660000F2 ++:1080E00000000000000000004340060006000019E8 ++:1080F00000016F60FF0000000000000000000000B1 ++:108100000000000000006F180918000000007676DB ++:10811000101066366636FE807E00FF007F1000007D ++:10812000000000000000000000000000FF906F0051 ++:10813000000000000000FFFF000000000000000041 ++:1081400000000000C9C9C9007E7E7F7E09000801C9 ++:108150000000000000000000000000006B6E62667E ++:10816000000000000000000000000000000000000F ++:1081700000000000000000000000000000000000FF ++:1081800000000000000000000000000000000000EF ++:1081900000000000000000000000000000000000DF ++:1081A0008210020000218440000000000000000056 ++:1081B00000000000000000000000000000000000BF ++:1081C00000000000000000000000000000000000AF ++:1081D000000000000000000000000000000000009F ++:1081E0000000000000000000000089FF80FFC2C204 ++:1081F000FEFE02FE00FF8080BFBF0000000066663A ++:1082000066666630FFFF00000000907EF67E00008C ++:108210000000666666660000F0FF00FF00FF0000D9 ++:108220007EFF0000000000000000000000FF00FFD3 ++:108230000600F6FF686EF8FE000000000000000077 ++:108240000000000044CC243C6030663C0000F0009C ++:108250007D7D3DFE00000000647CE5FD3636F6F6CF ++:1082600000387EFB00000000000000000076007F68 ++:10827000C2C2FEFE02FE06F600003F3F0000000004 ++:108280000000FFFF663000FF000009009018F6189C ++:1082900000000000606360630600F6FF02F200FF6A ++:1082A0008000FEFF00000000000000000000E4E489 ++:1082B00000FF0C00FCFF080E989E0000000000006C ++:1082C00000000000000042C3223390C099C3080898 ++:1082D000F8083C3C3C3C000000004058C1D9363610 ++:1082E000060600343CFF000000000000000000868D ++:1082F00070F500B000000086709401A000000086B8 ++:1083000000E109B00000008604E0000000000086E3 ++:108310000C80018000000086007400B00000008620 ++:1083200000750010000000000000000000000000C8 ++:10833000008600F501B00000008600E100B90000F1 ++:10834000A0865011A1B00005008400F008B0000024 ++:108350000086007100A00010000000000000000076 ++:1083600000060A60000200100086006000B00000F5 ++:108370000000000000000000AA00AA0001000000A8 ++:1083800000000000F0FCF3FF00000000424201C2C8 ++:10839000FCC0FF001400D7FF0000000041E100A076 ++:1083A00000000000FFFF0CFC0000000000000000C7 ++:1083B0000000FFFCFFFF00003C3C0000000000004C ++:1083C00000FFF0F0F0F0003C0C0CFA0AFCFC000F8F ++:1083D0000202000000000014000000000000000085 ++:1083E0000000000000000000FF00000000000C285A ++:1083F0000C000000000000000000FF55AA00000073 ++:10840000000000000000000C030F0000000000004E ++:108410000000BE82FF000C00CFFF0000000041E121 ++:1084200000A00000000000000CFC000000000000A4 ++:1084300000000000FFFCFFFE00001C3C00000000EC ++:108440000000007FF0F0B0B0003C0C0CFA0A0C0CFD ++:10845000000F000000000000040400000000000005 ++:108460000000000000000000FFFB00FB0000000017 ++:108470000C000C000000000000000000F4F40404F4 ++:10848000FFFF437F0000000000000000000000002C ++:1084900004380000FFFF000034F700FF0000000078 ++:1084A0001414BEBE3CA03CA0F3FFF5F50000000094 ++:1084B00000000000000000000000FFFFFFFF0000C0 ++:1084C0000000FFFFFFFF2FFFF00000000000FFF0A3 ++:1084D000F0F02D552DFF00000000FFFC00550000BE ++:1084E00000000000000000000000FAEA05EA0000B9 ++:1084F000000028AF7DAF0000000000000000F5F094 ++:1085000005000F0F437F0000000000000000000086 ++:108510000000003C0000EF2FE02004C700FF000037 ++:10852000000005AF05AF00A000A0F3FFFFFF0000B3 ++:108530000000000000000000000000007FFFFFFFBF ++:10854000000000007FFFC0FF28280000000000009E ++:10855000FFF0FFF02D002DAA00000000FFFC0055E9 ++:10856000000000000000000000000000050500FF02 ++:108570000000000028057D05080020008208910009 ++:108580000020042121202104110004880200200180 ++:10859000040003020400002011000204040004107F ++:1085A00000000200021104000200020011A00300FA ++:1085B00004A020002090A10000000000020003A001 ++:1085C00010A0400402040405100104000310000080 ++:1085D00000000440900000109108030011A0210049 ++:1085E00000000400210002C0020011008000A00071 ++:1085F000A00009001000020021000000010002009C ++:10860000400800C1008400800080200000000000BD ++:108610000420000000C1010004800200208000004E ++:1086200090000000010000040000010005000000AF ++:108630000400000001000100200000000200010011 ++:1086400000008500018001800084012000000000FE ++:1086500000002000908003002000100000000000B7 ++:10866000000020000000000001000000C000040025 ++:108670000400040520008500C00082000000000006 ++:1086800000080008080000000020000000000009A9 ++:10869000000021A100011021000400000090000052 ++:1086A00000010000000000000090800100000200B6 ++:1086B000000000C0800000100000000800C00000A2 ++:1086C0000004000400008020002110200041000070 ++:1086D0000000100000000001000080010000801078 ++:1086E0000000001000000000000000A0800000203A ++:1086F00000210005800000010001000900010220A6 ++:108700008200001000008310001000100209001009 ++:10871000028200002020022002840090004100001C ++:1087200000110004004100210021002102049011E9 ++:1087300002210008002010100020021090200000EC ++:108740000010829000A000104090048403A10084D7 ++:1087500000210041000000200004001010108210D1 ++:1087600002080010004100410041000000412021AA ++:108770000080008400A01010002020200020004075 ++:10878000000000C0004000400000110220000088EE ++:10879000020080C000C08082002000100084001011 ++:1087A00000C00084008400200084200280020400B5 ++:1087B000004000C000C0040200080002000800A041 ++:1087C000000000C000C1002080C0808800A08000A0 ++:1087D00080840584042021200020004000000091B6 ++:1087E00000042040200800910001000000840000E7 ++:1087F00011A0820000218485002103400010001098 ++:1088000080C010410440C00900800408002109090B ++:10881000C0218821400082001008820088210800C1 ++:1088200002000000000004000084882001410211C1 ++:108830000121004000080000014088C000054011EF ++:1088400000100000000510041083201020000021FB ++:1088500004030405824185908890C08200201000A6 ++:10886000A004108001000520000400041021000570 ++:108870000003C0410420100405040084100010030C ++:1088800002000200850003008000020010000500C5 ++:108890000000000002000000200008000301410168 ++:1088A00000000041030010044100200103104100BA ++:1088B00010000500000003008390A00009002000C4 ++:1088C000100104000000000010000502200020003C ++:1088D0000300C10120090000100005002000050070 ++:1088E00002008082200009002000051100004100E4 ++:1088F00010000001100004000200800002000500CA ++:10890000050021004100200010214010110000034B ++:108910001000840002000000100310008200080410 ++:108920000820A00008088200840020088204C010EB ++:1089300000000000084100100010100302000000B9 ++:1089400001000002A10500000005C141C0C10000F6 ++:10895000011082001008A120A0410941000001413E ++:10896000A010000010090103020009050240A01038 ++:108970000005000084400000A10085000400A10063 ++:1089800000000000A000A02100000240040002102E ++:108990000310050010081084000041840084411079 ++:1089A00041104104000000820900208420002002C0 ++:1089B00041822100210021100082408410400240A9 ++:1089C00009C0000400880040000010901100040459 ++:1089D0000904C110A09090049010058810100000A8 ++:1089E00002028002A0030541089000040084418433 ++:1089F000004010404100108804200411112004217F ++:108A0000840041C00440210020000000001000212B ++:108A100040110041042104088410900082030010DA ++:108A2000002100000080000800001004090021104F ++:108A300001409000880000008811101010110400FF ++:108A4000008000100091200288A00040A00040217A ++:108A5000019010002000210021902000000000055E ++:108A60000000001020032004000404000090900087 ++:108A70000010000500000000000900000320900025 ++:108A800001842100821001000009110020002184CE ++:108A900010841121080003A0000820002100081004 ++:108AA0000001410900A004000290102000100410F1 ++:108AB00080000500001000102190080008A0088820 ++:108AC0000201831041A010C004000088000000894A ++:108AD00010000800000904C00490109003822100D7 ++:108AE00000C01010100020C0210002000584218267 ++:108AF0001090100400014100030000C0800010200D ++:108B00002010001000410000000040000801000893 ++:108B100008008200A0C08400000000090005820057 ++:108B20000800884000408200C1000800A180820047 ++:108B3000000002000000C000100002000009000058 ++:108B400000058440400008000040C0008400008010 ++:108B50000004100084000040011001000121000009 ++:108B600090098840C0000003030300001103044083 ++:108B700082030000008510048400822100000200AE ++:108B800088800111000000A0000500000100824063 ++:108B90008003090410200041208989100241030547 ++:108BA0000010802021100408802080098040108857 ++:108BB0000390090941C105110302000909052009B3 ++:108BC0000280400040804000080508094004200958 ++:108BD0000000000488208808000910002000C1005F ++:108BE00000800305C0000409081080838502082066 ++:108BF0000041088000800080000005000000110096 ++:108C0000040000808000090000808085000211407F ++:108C100000404001C1010001000188884111C041AC ++:108C20000088000008010100000088C1408982829C ++:108C3000000991090885010200040101C00100003A ++:108C400000000002C090014001200101C1010100AB ++:108C50000100000088000801090100010008A000CF ++:108C600010040010090109008900000108824085F4 ++:108C70000002000101400084000800080000040018 ++:108C800000000000400840C08804000808890084F3 ++:108C900010010091C00082C0204120008300108894 ++:108CA0008804830188004000840021000800081027 ++:108CB0008820100020009041030141001100C1886C ++:108CC00004108988C0004103C020C0834100880887 ++:108CD000A1010101000000010021010200090110B1 ++:108CE0000000002001880400C0088900418910C0EC ++:108CF00090004190840888A0200111000300020028 ++:108D0000C00005001000011000000110000808005C ++:108D100000C0880084080000008000910002040068 ++:108D200011A09008890500000000A00083048809B4 ++:108D300090808080080000000003900809009005E2 ++:108D400088A00591098410054102000490202000AC ++:108D500091C12141092000000020040408C10941FB ++:108D600011830408098041400403098085104140B3 ++:108D7000820920040400A0110404082085000220B8 ++:108D8000000000080500C10040040211020040116B ++:108D900080090000800580400200000005001100ED ++:108DA0000888008004890910402000041090A00564 ++:108DB000108000C00009208505000080090940845A ++:108DC000088800400009C0000008808400110005E8 ++:108DD000008200020489A002000089800080100047 ++:108DE00040000084041108008000024000C00820F8 ++:108DF0000591200000008884A184002080041009CF ++:108E0000000800900020009000880000840003000B ++:108E1000000040008000000011000110000401C0AB ++:108E20004108014082048205000301110082008490 ++:108E300009C000080009101101890100844010A137 ++:108E40000089890500C000414090000904104008D5 ++:108E5000900900090004008505A00000040800C076 ++:108E600001C005904088090200A08202019000C163 ++:108E7000000905880804840209A0094088009000C0 ++:108E80008301000100100085008500C000A011A032 ++:108E90008910C0040090104004080040018801A01F ++:108EA000010001208241882008000804000100839D ++:108EB00000000040410089A0100004840110000857 ++:108EC000000101000910A008880190041001410070 ++:108ED000080008C0010200A000000140000090024C ++:108EE000400840014000840810219000080008401C ++:108EF00089000401C1104011020582891088C0094F ++:108F000088104000A00800410009000000108410F3 ++:108F10000240C000020011088904C100C0C00382E1 ++:108F20000400200020800303834005052080000802 ++:108F30000091002000800900C040101110800584BD ++:108F40001120080440000880050089404080C1408D ++:108F5000100282042000038510040909208000000B ++:108F60001100050202024100800000880003800019 ++:108F700082408405410220808090008800C08000EB ++:108F8000000900048041008000200088000000806B ++:108F9000800000000005000083002000880002809F ++:108FA00000000013C200000011820013C200110073 ++:108FB00000000008C200420041880013C200008186 ++:108FC00000840021C200420000810004C2000A00A7 ++:108FD000000000130000000000810013C200000028 ++:108FE00000001200001381000000000000100200C9 ++:108FF000008211000013C2002100000000000200E6 ++:1090000000000000000002000000000000008100DD ++:10901000000000000080010000608100001381005A ++:1090200000007171F0F000000000BFBFAFFF00FF53 ++:1090300000FF000000000F0F003CFC00FCFF000FD1 ++:10904000000F3C3C3C3CAAAA00FF503CFFFF437F82 ++:10905000437FCF41CF7D080A080A5C5C5555013D2E ++:1090600083BF000000FF5555000000000000000015 ++:109070005C5C5C5C7F3CFF3C00000000000000008A ++:1090800000FF000000000000081C495D0000000017 ++:1090900055FF0F3C00000000000000000000000031 ++:1090A00000000000717100FF00000000101000506F ++:1090B00014D73CFF000000000000003C0C000CFF37 ++:1090C000000FF0FF0F553C3C000000FF503C00003B ++:1090D000023E023E0C410C7D080A0D0F0CFC00FF05 ++:1090E00000FF00FF00000F0F3C3C000000000000EC ++:1090F00000005C5C5C5C7D3C7D3C0000000200008C ++:10910000000000FF000000000000081C495D000096 ++:10911000000055000F3C00000000000000000300AC ++:109120005555000000000F3C0F0F00000000F2F347 ++:10913000F2F0FFFF0000BEFCBEC0FFFF0000AA006F ++:10914000BE1435353A3AFF00FF00FFFF0000FF0074 ++:10915000FF00FFFC0F0C00000000FEFEAEAEFF0A99 ++:10916000FD08BEFF1400000050001010A0FFA0007A ++:1091700000000000F775B634FFFFBABAC300C3029F ++:10918000ACACACACFA0AFCFC00000000FA0A3808EF ++:1091900000000000FFAA550000000000F0FF3C00A6 ++:1091A000C505C000000000000F3CAAAA0000000096 ++:1091B000703070F0BF8FB08082FC82C0FF0055001D ++:1091C000AA00FA503A3A3535FA0ABE82FFAAFFAA37 ++:1091D000AFAFACACF0FC000C000000000202A2A299 ++:1091E000FF0AFD08FAFF500000005F001C1CA000F1 ++:1091F000A00000000000E361A220BABABABAC3001E ++:10920000C300FF0FF000FA0A0C0C00000000000081 ++:10921000380800000000FFAA550000000000F00020 ++:109220003C0000000000000000000886047108B047 ++:1092300000000086709401A000000086007000B05D ++:1092400004100086009401800080008670750090F4 ++:1092500000000086707500B0000000860C6100B050 ++:1092600000000586007500B000000000A18650F1E6 ++:10927000A1B00005A08650F1A8B80005008600A0A6 ++:1092800009800005A0865070A8B00005A086507027 ++:10929000A8B000850086006008B00000008650F08D ++:1092A000A0B000050586008009A0000500000000B0 ++:1092B000FFFFFFFFFF000C0C00000000000000009B ++:1092C000FFFF3F00EF04EB000303FFFF000000007F ++:1092D0000000FFFFFDD5BC94033FD7D7FEFFFEFF84 ++:1092E0003FBFFFFF00000000171700170000AAAAE9 ++:1092F000FF00000282022F2F282800045554FF008F ++:10930000BF830000FFFFFFFDFFBCDF8FFFFF3F7D3E ++:10931000302800000000000000002F0F0F0FC3C313 ++:10932000C3C32A3FAA3F2D2D2828990099FF00008A ++:109330000000BFBFFF3FFF000C0C0000200000003A ++:109340000000FFFF7D00EF04EB000003FCFF0000C6 ++:10935000000000A05FFAE9C1A880033F1414FEFFDB ++:10936000FE3CFFBFFFFF00000000000000170000F0 ++:10937000F0F03C3C0007D7072F2F2A280000000000 ++:10938000FF00BC80202A757FC3C1C380FFFFFFFFA1 ++:109390003F7D302800000000000000003F0F1F0F3D ++:1093A00002020200AA00A8002D282D28990099FF8A ++:1093B0000000000000900006AABE0014FFFF437FDB ++:1093C00000000000000C00CF3030F0F001FD03FF82 ++:1093D000FFFFFCFF003CCFCF000000003CFF5F5FC1 ++:1093E000EBFC28FC0505000C000000000E5E0E5E84 ++:1093F000000000000000000000007C7C3C3C0000FD ++:1094000000000000000000FF00FFFAFFAFFF00288F ++:109410000000000038380004005500000000FDFD89 ++:10942000FFFD0000BF1F00000000FFAA00AA003CD3 ++:1094300082BE0000000090000600AAFA00500F0F44 ++:10944000437F0000000000140014F330F0F001FD31 ++:1094500003FFFFFAFCFA003C0C0C000000003CFF8C ++:109460005F5FEBC028C00000000C00000000045447 ++:109470000454000000000000000000007C7C3C3C24 ++:109480000000000000000000007F80FFFAF0AF0F36 ++:10949000080800003C0038380000005100000000BF ++:1094A000FFFFFFFD0000B01000000000FF3C003C8B ++:1094B000003C82BE400982828001840000000400DA ++:1094C00021A0020811001100040804000084021009 ++:1094D000040011900300041021100000000002009D ++:1094E000211002A02110000084100500110040008E ++:1094F000030811000000090002000400200800C059 ++:109500000308040080000200200004C002202100A3 ++:1095100040008040119000000010040811009000ED ++:109520000208401000000421042004000420000070 ++:10953000040020010408010221082004400000006A ++:109540000000840001000000000090000000900076 ++:1095500000000000000000008400200090000000D7 ++:1095600000000000050004000200020020000000CE ++:109570002100000000000000000021002000010088 ++:1095800090009000A0000200010000000000208078 ++:109590000000010002800000000004000000040040 ++:1095A000110090800500200001A00180A100018031 ++:1095B000A0000000830820800000000000A100023D ++:1095C0000011009000C10000800000000000009029 ++:1095D0008000008800908000109100A00000000032 ++:1095E000009000000000800800000000000010084B ++:1095F000904000001000020800C0000000080010A9 ++:109600000000000100000000000000000082800057 ++:109610000000000000000002000080000000800048 ++:1096200080010001800100000082000000000000B5 ++:10963000000000000000000000000011000800040D ++:1096400000880420000802100410401100102003BC ++:109650000210101000100210020003200000020887 ++:10966000001000112011021104C10021041000415A ++:109670000111038800100521A11000000008000856 ++:1096800000100011000490110010000000110008EB ++:1096900008219008000000410090002104410000D2 ++:1096A0001010100482400420902182080000200342 ++:1096B000001000100000A0004021900000104104A4 ++:1096C000000403114088000005000202008400002D ++:1096D00080C00040000800C000840040044021C059 ++:1096E00000C00082001000C000A000200010008414 ++:1096F000828209888385400011100020000010A09C ++:10970000008400C02000008300000908008221C0FE ++:109710000010C004891005840085008404C000A0E6 ++:109720000000048200008011004080090020111018 ++:109730000900090900080084000000090021100048 ++:109740000080A090000203050810001008400041AE ++:10975000820502098203A000C00000080802000080 ++:10976000840902408808000590101010C004009081 ++:10977000A0080200C00002401103C00308C100009D ++:109780008221C000C0008500C00410211040C0101C ++:109790008211881105C1044082008420C005110097 ++:1097A0000040A021C108A000100800001088C0A13E ++:1097B000004100008220102110000000004090A015 ++:1097C000C100100010000000020040001000020064 ++:1097D000001005841000100004004100100020213A ++:1097E000000000000300200021000000200008000D ++:1097F0000000900009014000020002000200040085 ++:1098000000000000050000008400040000002000AB ++:109810009000100002A005020500100802200800B8 ++:1098200003202004800002000500020000088408D4 ++:109830000400000100000500800000008300030018 ++:109840008301100900000805000082000021844106 ++:1098500088059010080308109111011102050005F8 ++:10986000008284100011A0000900C003C000C000E5 ++:1098700020410000400000400140C100830003047B ++:10988000A104000088000005080021000100080074 ++:10989000012120001005010020900000108008899F ++:1098A0000021088900C10408200000410000008058 ++:1098B0001100030810041000002020000200100016 ++:1098C000C0000420400221402004021009000000D2 ++:1098D00021020084110810840800090021C01090A2 ++:1098E0004102084000820000414003C005A010C0B2 ++:1098F0000840048808840300414010A1020203A02C ++:10990000051010C1000003A0108402820211021091 ++:10991000A110030400A0828505A0000108000340F7 ++:1099200020830500002010040000008441044089C9 ++:1099300010000320051010C0000110040383000074 ++:109940000000000004200188000041800180822086 ++:109950000021020040000400000084109000A010CC ++:109960000120888010091020A0200090880000218C ++:109970008808041040410021002084C100404100BB ++:109980000010A08284200040821004119100030482 ++:109990008540200000C10008034004000020820030 ++:1099A000000811049000A0089080C00000210090E1 ++:1099B000010810111080C005900082201188C0207D ++:1099C000000300058409099009C0208802900884DA ++:1099D000008820000800050400200984008400207D ++:1099E00090848891A0208010028400C0088410A078 ++:1099F00011840200080020C005A040C088A1021008 ++:109A00000540200000A041080000058400A000A03F ++:109A1000418400A002C002844108044102208588DC ++:109A20001020112000A010000320028400A0088450 ++:109A300041008008A0C009090308118400841108AE ++:109A4000808202888200A10002838200010000005F ++:109A50008241C0001100010000000011000300213C ++:109A600000004011402010801000000000000000A5 ++:109A70008811A04100408440894120408511024066 ++:109A800084400080000000110080008000008205FA ++:109A900000000000000000000000008000C0000086 ++:109AA00040400080020000000005824100000000EC ++:109AB0008400000010800404008802800000100070 ++:109AC00020001000020004000400022091038940DD ++:109AD00002024141218080094000004003042041EE ++:109AE00021410905080320094004411180A00041DB ++:109AF000000000410200C1004000090040100008C1 ++:109B0000041003084088802011910405000009809A ++:109B1000100011004100000009000300008005A1B1 ++:109B20000000111105028380000008004080A08021 ++:109B30000000A0000300A04180048841408510007F ++:109B4000090000000500004100418040000991012A ++:109B5000050100019101008284A1000000C1010003 ++:109B60004000010100009001110000000000888306 ++:109B7000008400000000010082000000000091014C ++:109B8000A000000101010082C021000200C000000D ++:109B90000002010400C000C0880803080108000298 ++:109BA0000182C0A001A100908582108883880104F1 ++:109BB00009888484098800008540400103880004E6 ++:109BC00089000100020000000000000010000000F9 ++:109BD00041001182A1024185A1014089A009080428 ++:109BE0001000820090108500C08890C0408405005D ++:109BF00082C02000A08810000500040889C0090167 ++:109C000008001085100183008901111088081100D7 ++:109C10000000C0000900028410C004C0C00102009E ++:109C20004100040002020301200803000401059022 ++:109C300004080300830089A0091008019040110165 ++:109C4000000000100101008201014110400000905D ++:109C500009008808898021888590024082A1C0403F ++:109C6000A108830004009191900805000504891162 ++:109C70000311000000000008002185008480058099 ++:109C800010200000800880058300100308800080F9 ++:109C90000305000009048200888011800200090485 ++:109CA00003004004A1408200911141801110C102C3 ++:109CB000C09020801002400085009005C0104080B8 ++:109CC0000508040002802004000020042080A00079 ++:109CD0000500880002400011098991034010808826 ++:109CE00021801082021100100284081184054005B1 ++:109CF00040891003080000008000400000400089F7 ++:109D00000090800840C000C008C000910409800491 ++:109D100000A000400080000800C100C10089800050 ++:109D200000001180000000830002A08941A0009083 ++:109D30008009114000A080038003208580A10508D0 ++:109D40000041802140038008034011418000020847 ++:109D500008041000410501A1000301C1910301099C ++:109D6000A09183849110019000110040004182086D ++:109D7000014001844189010002009000000000219F ++:109D800000100084404100400009008408080040A1 ++:109D9000081002C190400080000188C120C1A08944 ++:109DA00082400040048402A000209089A085A08801 ++:109DB0000009C010111010898202A000A11088882B ++:109DC000008900904001A0C18201010100008200D1 ++:109DD0000001010000009001824184C18401A009BA ++:109DE00041C003019100414001000001000000A0BA ++:109DF00001C10004000900080191000800000108E9 ++:109E000000410101000101040100000100010040C6 ++:109E1000208589A0830089880080908484A1900097 ++:109E20009002000100910000001085418401200093 ++:109E3000058485418901A00188C08220880108012C ++:109E40000402210090004101094000000090000040 ++:109E50000000000000000000004084101020C1211C ++:109E60004091404020104010100008094008401068 ++:109E700041000308099105021110400340800400CD ++:109E800011000490404011020800400410410340BA ++:109E900003800585400008001100008000A000201C ++:109EA0000040000000100002000900808310040838 ++:109EB000910211808382881090029002001180101C ++:109EC000804000008311020020104000000000804C ++:109ED00000210000004100030041008000880013C1 ++:109EE00084008200210002218400000000000000A4 ++:109EF0000000420000000013C20042008100001375 ++:109F0000C200060000000013200042000000000014 ++:109F100044000048410000131000420000000050BF ++:109F20000013C200000000000081810041840A503B ++:109F30000013C200000000000081100042008100F8 ++:109F40000013810021000000001300000000000049 ++:109F50000013C200414100000013C20000002404AD ++:109F60000020992409CBFCBC3C3C6E6E0C0C000814 ++:109F70000000FFFFFFFF00000000000000003F6640 ++:109F8000036600000000000000000000FE0E00005C ++:109F9000000043434040FFF3FCF0FF7E99180000AF ++:109FA00000000000000000000000000000000000B1 ++:109FB0000000C0C099009900FE7E03C300000000AD ++:109FC00000000000FC000C006F0910760F0F0F3C22 ++:109FD000000000006F636F63000000000F0F3C3C47 ++:109FE00000000000FF000909C08000006E6E0C0C2C ++:109FF00000080000363636060000000000000000B1 ++:10A000003F6603660000000000000C000000F80836 ++:10A010007E0E7000C300C3000F030C00FF6F990990 ++:10A020000000000000003C2430240000000000007C ++:10A030000000000960699900D940FE7E03C39F3C7F ++:10A04000063C00000000F600F6006F09101066667E ++:10A05000663C000000006C606C60000000000F0FA8 ++:10A060003C3C000000000000000000000000000078 ++:10A0700000000000000000000000C2080400001101 ++:10A0800088610000000000000000000000000000E7 ++:10A0900000000000000000000000000000000000C0 ++:10A0A00000000000000000000000000000000000B0 ++:10A0B00000000000000000000000000000000000A0 ++:10A0C0000000000000000000000000000000000090 ++:10A0D0000000000000000000000000000000000080 ++:10A0E000000000003636CCCCFFFFFFFF81E781E7A0 ++:10A0F000780000004246626600F6C3F600000000E9 ++:10A1000000000000666666660000000000000000B7 ++:10A1100000000000000300000000FFFF30F330F3F8 ++:10A120000303FCFC0000000000000000F100000040 ++:10A1300000000E7E0E0019191F1F00800000000095 ++:10A1400000000000000000000000FBC3FFC300008F ++:10A150000000F3FFF3F00000000000000000C0C0AA ++:10A16000F0F0000000000606BC8CFEFEF2FE006669 ++:10A17000006678780078000420240090C3900000E6 ++:10A18000000000000000C3FF00FF0000000000000E ++:10A1900000003CBCBCBC0000000099996666F3F36B ++:10A1A00030F30303FCFC0000000000000000F0009E ++:10A1B000000000000242020019191F1F00000000E9 ++:10A1C000000000001C049F0600000000E3C3FFC362 ++:10A1D00000780000F3FFF3FF0000000000003030C3 ++:10A1E000C0804040040000000082046508B2008086 ++:10A1F0000084704109B800800186026000B8000048 ++:10A2000005860A6100B900A00084025109B000056A ++:10A210000086006100B0000500860C6000B00010F0 ++:10A220000086026101B0001000000086006508B0E1 ++:10A230000000A0865071A0B0000508860265098064 ++:10A240000000058650A000980080A086008009804C ++:10A250000005058600A000890000A08650F0A8B087 ++:10A260000085008600E0A8B000003CF0AAAA00101B ++:10A2700030100F030B0B414141410000000000AAC8 ++:10A2800000F00000000041414141000000000000DA ++:10A2900000000000000017D7FFFF00000000410091 ++:10A2A0007D00FDFC515543437F7F0000000000000E ++:10A2B000FFFAFFFF000000002DAFAFAF0000BEF0BF ++:10A2C00000D0FFD010405555B0F010007F20FFA007 ++:10A2D000143CD7FF3CFA3C5035353F3F00000000AE ++:10A2E0000000000000000000000000003CF0000042 ++:10A2F00003060C060C0008080000014100000000E5 ++:10A30000282830300000000000010101000000009A ++:10A3100000000000000000001414FFFF0000000017 ++:10A320004D004D00FDFC515503C33FFF0000F0B050 ++:10A33000F000FFFAFFFF0000000005AFAFAF000024 ++:10A3400014F080D0FDD010400000100010007F20DD ++:10A350005F000000FFFF3CFA3C5030303A3A00000A ++:10A3600000000000000000000000000000000000ED ++:10A3700000000A0A5F5F0000FFFF14001455000090 ++:10A3800000000FFF0FFF0000000004045454000001 ++:10A39000FFAA4070000000000000003C00550000D3 ++:10A3A00000003A3FAAFFFFF03C3A2D002D000000CC ++:10A3B000AAAAA8800183018300FF00FC00002AAA4A ++:10A3C000F5A0F5A055555555FFFF3C7D0FF02D78B4 ++:10A3D000FFFFAA0000FF34F700000303F8FDF8FDBB ++:10A3E000000000000000000000000000000000006D ++:10A3F0000000000014BE14BE0041EBFF050505057A ++:10A400000000000004FF0CFF000000000005505594 ++:10A4100000AAFF00417D010D00000000000F000FA9 ++:10A42000000000003035005500F0AA3A28007D00F9 ++:10A430000000AAAA000005AF000000FF00F0000025 ++:10A4400000AAF5A03C3C755555550F0F3C7D3C3C92 ++:10A450002D78F5FFA00000FF04C70000F3F3080DFE ++:10A46000080D0000000000000000000000000404CF ++:10A47000000003008408840011000400910011080A ++:10A4800084002010800004C00200200021C00308C6 ++:10A49000200004000300100011000000040004006C ++:10A4A00021000400000011000411110004400310F9 ++:10A4B0002000000020042000000004A02000001064 ++:10A4C0000090042000112100001000000000000195 ++:10A4D0002000800000000000000000A00402211005 ++:10A4E0001100A000200010000201800011002100D6 ++:10A4F000040020000000118004000210020040004F ++:10A500002000040008031000000001000005000006 ++:10A5100004008900900020000100000010000000ED ++:10A520000200000008000000C000002000000080C1 ++:10A530000480000000000000A000000000000010E7 ++:10A5400000000000A0000002200000000010000039 ++:10A55000001000001000000000000000000001805A ++:10A5600000008200200000000100A1201000A000D7 ++:10A570000000000001000000000000A0200000001A ++:10A580000000000000010000000000000001009039 ++:10A59000000000088020000000000000800000C1D2 ++:10A5A000004000100000000000000000000000005B ++:10A5B00000008000800000C000008000000000005B ++:10A5C000000000000040000800000000000000043F ++:10A5D000000800000000000000000000000000086B ++:10A5E0000001000000000001000000010000000167 ++:10A5F00000010000000000040000820002110100C0 ++:10A6000090110010A0000008000820200010002079 ++:10A6100000100010009010A00000000002001010B8 ++:10A6200000040088000000080009820800100000F3 ++:10A6300000080008080802000000000002100421C1 ++:10A640000010A020002100A00083000000000011E5 ++:10A6500000A1009000110008000040000020000848 ++:10A6600000900020001000210004000200200010D3 ++:10A67000000800200010400000A0020103A103A078 ++:10A6800040A0001011088400001020C0408420A0C9 ++:10A690002120802004000040210005C000A000000F ++:10A6A00021000040402080820008038400C0000890 ++:10A6B000028400C00002080000A100000590000014 ++:10A6C00000002009110200000584001000000000B5 ++:10A6D0000284851000000882009000000008000934 ++:10A6E00003A00008008441000008000404000421C5 ++:10A6F0008400051100020400411000A000200008A1 ++:10A70000A0059108100010211000000083400910DE ++:10A71000851090C14080400040111021C00384008A ++:10A720000020000810108290204100C18400841194 ++:10A7300002908410101082800105000400001000B7 ++:10A740001000C000838420A10021820000C11008F5 ++:10A7500000030010040000038500004110101041A8 ++:10A7600000080000108000210000000000800100AF ++:10A77000118209000008C08082000000C00041086A ++:10A7800010408300100820400383000041020300B2 ++:10A790004108004041A00500412010404000000059 ++:10A7A00004001000208541000500050080000040E5 ++:10A7B00005400900110000014100080000000000F0 ++:10A7C000000010000808C1400000100220400040B6 ++:10A7D00000004188050041002020202010000000DA ++:10A7E0000300000800000400090000001000210020 ++:10A7F00000010200100010002100090000002000EC ++:10A800001080208004000080008000400000008054 ++:10A81000C0000084000000001000008000800000E4 ++:10A8200000000010000010080000000900032000D4 ++:10A830000080008000008800004000000810000038 ++:10A840000000000421001090108000000080001023 ++:10A850002080000000000000000000800080000850 ++:10A860000000000000800000010000000000010066 ++:10A8700000000004010003000100020000000000CD ++:10A880000000200021A041044188418405A00088E7 ++:10A8900005400082100105A0A10041001000004009 ++:10A8A00000C005A010000510884005000304030542 ++:10A8B000000505A000C010080001084000000800C5 ++:10A8C00008030000080008402100A0020000000268 ++:10A8D000080000200000000041081000100010A037 ++:10A8E0008000820000040091000400830500000045 ++:10A8F00000001004000100010301A0000500000099 ++:10A9000010000089012000080080000504030000F9 ++:10A9100010004080A00001088803400382218500C8 ++:10A92000000500200000020000001089840000885B ++:10A93000C08800A010090020C02084200800021058 ++:10A940000005102000C0A0001000001021A19003FD ++:10A9500000801021002100000010100800211100CB ++:10A96000840004080500008010088480C0081003DB ++:10A9700000100021108000040020002005210000AC ++:10A980000000840000400220830405A004A103828B ++:10A9900005A0208408C110849008414005000300F0 ++:10A9A0000384058541A00588080021840582204094 ++:10A9B0002088112010000000020008880000088490 ++:10A9C00041A080A01008000000C00002040200089E ++:10A9D0000040004002400210001020900010414052 ++:10A9E00000C000100284008403400084002000A006 ++:10A9F00000002100201011900220009002854100EB ++:10AA00001188020041000040828004C00000014023 ++:10AA10008800000020000020000011808289C00012 ++:10AA200000000000082000040000000000000008F2 ++:10AA30000000000000800010000001000000000085 ++:10AA4000010000000200000000000000840000007F ++:10AA50000080000000800080000000000000000076 ++:10AA600000000000000000000000000000000000E6 ++:10AA7000000000000000C000000001800000000491 ++:10AA80000000000000000000000000C00941852017 ++:10AA90000088090580A040201020400300112008F4 ++:10AAA0001040C005040320102040090000001000E1 ++:10AAB000090009008980098020008205008820841F ++:10AAC000408584808080000008000000110900A0FB ++:10AAD00003101008040000004100040010004100B1 ++:10AAE00000002000030000002100200000090041B8 ++:10AAF00000044041000000000000050091840909A5 ++:10AB000000084040030080000200050088112190E9 ++:10AB100082A104410091A0A1008900040101040068 ++:10AB2000000001019001050001010100000000008A ++:10AB30000100000088101184004001040911008404 ++:10AB4000000801081082408400820110000000000B ++:10AB50000085000500110000020000000000010057 ++:10AB600001000000000001000000000000000000E3 ++:10AB7000000100000100000000000000000004824D ++:10AB800001A0A0820021A1004000010000000010EF ++:10AB900008410909C1080001009000000140C000FF ++:10ABA000902090110000900489A008048401030003 ++:10ABB0004000100089000500A001880085080300FE ++:10ABC0009084908902041100C100A1008205000058 ++:10ABD0000200100008000208040102000800010041 ++:10ABE0000000000001000101000800C0018901000F ++:10ABF000000000040000000000100100000000013F ++:10AC00000310A00108100808000400000100010161 ++:10AC10000983410490100905112100000020030060 ++:10AC20000900100000100200038040008380C04132 ++:10AC30004000820085004000090403040000C002B7 ++:10AC4000C00403000320050090008500050090402B ++:10AC50000000C1400900410004A010400900880024 ++:10AC6000400000000000050009200380400005218D ++:10AC70001009040002800200410409804100040020 ++:10AC8000030910C004088080804109800000210071 ++:10AC900020099000110010800000C14000082040F1 ++:10ACA000830220A000022089889100090508000085 ++:10ACB00084830040004000090005802110821110AB ++:10ACC00000910305808400C11005008500108011EB ++:10ACD0008090000005C08008008980050010008277 ++:10ACE0000089004100400040001000830003110271 ++:10ACF0001002008304000005000909050002000994 ++:10AD000020100003850583402111200500204020EC ++:10AD100000200000829084024084102008A1C08995 ++:10AD200040C00504014000210141418900C000C12B ++:10AD300000080441000200A00082002182104004AB ++:10AD40008211200888C0C040088409210009A02081 ++:10AD50000803C08900000105100282A040A100C0C4 ++:10AD600000900084000500C0009000010089008868 ++:10AD7000008201088882000000000001100100002C ++:10AD800000000001000082010900C10182010004ED ++:10AD9000019000831090848889401100048810007D ++:10ADA00002000400A10001010103010000C0000035 ++:10ADB00000010000000200A00000000100C04004EB ++:10ADC00004028400400840000310C10090409090AD ++:10ADD000008488009000000010899001100110008C ++:10ADE00082000204100010C00000000000010000FA ++:10ADF000009001010000010001000140010000007D ++:10AE0000000000000000000084014004909084A035 ++:10AE100000020000000100008403400484040200DA ++:10AE20008200110041050800090220852003080066 ++:10AE300009412020034121000011001000050000FD ++:10AE400000090085000500008502C104C010828051 ++:10AE50000089000900040000000080100040800507 ++:10AE600080008010001180090080000000000008B0 ++:10AE70000000410004401005200009000584400442 ++:10AE80000000000000050041000080100084808068 ++:10AE9000808000800000002100000000008181000F ++:10AEA0004181000000814400004800880013C20076 ++:10AEB000000000000013100000000000000000006F ++:10AEC000000000000013810041000000001300009A ++:10AED00000000000000881000000000000000000E9 ++:10AEE000C20000000000000000000000000000138D ++:10AEF000480000000000008100000A00004100132B ++:10AF0000C200000000840004C20000000000001322 ++:10AF1000C200410000000013C2000A00040404AE95 ++:10AF200000000000020243430020002A0000FFFF4F ++:10AF300000FF00FF003C0F3FF0F05F5F00000000EB ++:10AF40000A0FFCFF000000000B08EB280EFE0000BB ++:10AF500000000CCF00000000FFFF99FF0000000080 ++:10AF60000000000F777F00000000051D1D5F00003E ++:10AF7000000000080000BCFFFFFFAAAA088A00002A ++:10AF80000F0F00FF00FF00000000000000C00000E5 ++:10AF90000000000C000C0000000000000000000099 ++:10AFA00000000000000000C300C330203F2A200042 ++:10AFB0007FFF007F80FF00000F0FC0C07F7F000079 ++:10AFC0000000000F3F3F000000000B08000004F4E9 ++:10AFD0000000000055550000000099FFFFFF000031 ++:10AFE000000000000C0F777F000000000000000050 ++:10AFF0000000000000000040BFFFFFFF0000088AC3 ++:10B0000000F00FFF0000F0F000000000000000FF63 ++:10B010000000000000000200000000000400040026 ++:10B020000C0C0C3C8300800082C282C2FFFF000037 ++:10B030007D7D7DF03D3DBFBF555500543410340437 ++:10B0400000000000FE7DBE3C00000000000010106B ++:10B05000000F000A0000030000000000FFDBFFE714 ++:10B060000000FFF3FFC33030FBFB000000000000D6 ++:10B07000000000000000FFFFFF00000000000000D3 ++:10B080000000FFFF00007D71417100000000FFFF24 ++:10B09000FFFFFDFDF8FDE8E8E8E800000000000023 ++:10B0A00000000000000083AF80A082C282823C3C8E ++:10B0B000C3C3282828F0BFBFBFBF55550054341460 ++:10B0C000340400000000FE3CBE3C00000000000014 ++:10B0D000000000C300825000530000000000FF7E0B ++:10B0E000FFBD00003C303C003030FBBA00000000E7 ++:10B0F000000800000000000000FF00000000000049 ++:10B10000F3F2F0F096669666BEB282B200000000DE ++:10B11000047000F0FFFFFAFFE8E8E8E80000000034 ++:10B120003C3CFF00A08652F0A0B000050086026102 ++:10B1300000B0001000860A7500B000800086006133 ++:10B1400000B900050086006000B00000A0865050E5 ++:10B15000A0A0000500860261009004000086006047 ++:10B1600008B0008500000086026008B00005008677 ++:10B17000006000B800800086006108990000008629 ++:10B18000006100B000000086007500B0000000867D ++:10B19000006508B80000A08650F0A8B000850086C1 ++:10B1A000006000B800003F3F3F3F00C303030F00B3 ++:10B1B0000C0C04540000000000000000010000001E ++:10B1C0000000FFFFC3C300000000000010000000EB ++:10B1D00000004100D100FFFFFC0A000000F73F3FE4 ++:10B1E0003F3F0F030F0F0000CFCFA5A545414555A9 ++:10B1F000DCD8E433151515550000000030303F3F12 ++:10B2000000000000004000200000000000000000DE ++:10B2100000000000000000005F5FF6F70000000083 ++:10B2200000000000000020A03F3F3A3000C3414131 ++:10B23000550014140CFC08A80000000000000000D9 ++:10B2400000000000D7CFC3C30000000000001000C2 ++:10B2500002020207D100D700FC0AFC0A000000F736 ++:10B260000C0C3F3F0F000F0C00000FF00FF045419A ++:10B270004555DCD8E4331414145500000000303078 ++:10B280003F3F0000000000400020000000000000E0 ++:10B29000000000000000000000005F5FFBFD0000F8 ++:10B2A000000000000000000020000F000E00000A57 ++:10B2B000F5FF838380800000000000000000000094 ++:10B2C00000000000000003830303000000000C7D69 ++:10B2D000CF7DFF00FF003DFFFFFFFFA0FFA8FEFEA8 ++:10B2E00000FE2E0A99A5F0F03F3F00004B1E4B1EBA ++:10B2F00000000000000000001D3F1D3F0000000096 ++:10B30000000000000000000000000000000000003D ++:10B31000000000000000000000000000FF3CB2B28E ++:10B320004141000000000000000000000C000C0083 ++:10B3300000FA05FF00AF00A00000000000000000C0 ++:10B340000008000800000000838383030000000061 ++:10B350000C41CF410000010105FFFFFFB6A0B6A8D8 ++:10B36000FEFEFEFEAF2E5A99F0003FFF0000E1B452 ++:10B37000E1B400300000000000000C1D0C1D0000B6 ++:10B3800000000000000000000000000000000000BD ++:10B390000000000000000000000000000000C300EA ++:10B3A000B2B2500050000000000000000000210078 ++:10B3B0008200020091002000A1080004C00080006B ++:10B3C00004081100910000009100042011052000E4 ++:10B3D00011000400200000001100200020A0200027 ++:10B3E0000400110003000000040011902000000080 ++:10B3F000000004000400048420A0040020082000B1 ++:10B40000040004000400110000000400000011000A ++:10B4100000000000040000000400410004000000DF ++:10B420002000110020002000000004002000200067 ++:10B4300000002100A100100000000800828011001F ++:10B440000800010084000200000040009085208870 ++:10B45000A000040020000000000000000000A00088 ++:10B4600000000000020000000000200000000000BA ++:10B47000000000000000000090000000A00090000C ++:10B48000A0000000000004000000000020000000F8 ++:10B4900000000000000000000000000000000000AC ++:10B4A0000400000000000000000000002000000078 ++:10B4B000000000000000800000000000000000000C ++:10B4C0000000000000000000000000000000000478 ++:10B4D000000000000000000000000000000000006C ++:10B4E000000000000000000000000000000000005C ++:10B4F00000000080000000000000000000000000CC ++:10B5000000840000000000000000000000000000B7 ++:10B51000000000000000000000000000000000002B ++:10B52000000000000000000000000000000000001B ++:10B5300000000000000000000810000000210000D2 ++:10B5400000080010000000030000002100000011AE ++:10B550000080000000000011002100000000001029 ++:10B56000001000080000000800100010000000108B ++:10B570000010A010000000000004000000100021D6 ++:10B58000001000100010004100000010A01000107A ++:10B59000001000100010000000000000004100003A ++:10B5A00000410041004100000000001000100010A8 ++:10B5B00000100010001021000010030000004000E7 ++:10B5C000201004101001008400008300211000C02E ++:10B5D000A1000491808404A0030003000510000072 ++:10B5E000000000A0111005000000418410000000C0 ++:10B5F0001100100010C00000000000000082410097 ++:10B6000000000000000000000000000000820000B8 ++:10B6100003C01100110009000900000000004100F2 ++:10B620000000000003000000000000000000000017 ++:10B630000000000000000500901100000000C000A4 ++:10B6400084218321011111020000881040000200B2 ++:10B650000008084010201040020990410820040012 ++:10B66000840010008200C000021000001020A040E2 ++:10B67000C0030000824190110000C0110000C00012 ++:10B680008800000000110000000000000009000018 ++:10B690000000C00000000200840000001000C02173 ++:10B6A000100082001000C000000010000000000028 ++:10B6B00000000000C00300030000410005004040FE ++:10B6C000100041002090A000200005004000000074 ++:10B6D0000000000003002000088200002100050097 ++:10B6E000050010000000410000000382410020001E ++:10B6F00041000800000020000000000000000000E1 ++:10B7000000000300410000000540100000000000A0 ++:10B7100004000200000000004100100000000300CF ++:10B7200010000000000009000000410000001000AF ++:10B730001000110000000000020010000000820054 ++:10B74000910000000000821105001000101101009E ++:10B750000021000000000000001000080009820025 ++:10B76000000300000000000082040000000300004D ++:10B7700020000800001000110002000000008800F6 ++:10B780008208000084002000020010400000000039 ++:10B790000000000010000000000000000000002079 ++:10B7A0000000200000000000000000000000000079 ++:10B7B0000000000000000004000000000000000085 ++:10B7C000100003001100008810009000100008C055 ++:10B7D00000A00888100000001000042020110000C4 ++:10B7E0000000000010080010110000000000080018 ++:10B7F0000200000021000300000003000000000020 ++:10B800000000418800400000000000000000080027 ++:10B810000000040000000000000000001100000013 ++:10B820000000100000001088000000000000000070 ++:10B830000000000000000000000000000000000008 ++:10B84000002104410421C002400000030402110051 ++:10B8500000000000112088001000C00001851108C0 ++:10B860000000A010A003900090089000A0111021EB ++:10B87000A010C00090081000900004090021A00052 ++:10B8800000001009C00984118811A00008001040B0 ++:10B8900084110000000000000000000000001020E3 ++:10B8A0009008000900000811A0001003000000002B ++:10B8B000840010001008C008000000000000000014 ++:10B8C000C000119000004100210010880800804055 ++:10B8D000000000081090001000000004001020205C ++:10B8E0001000100000000000000020880000000090 ++:10B8F0000000000000000082004000000000030083 ++:10B900000300000000000000088441000000000067 ++:10B910000000000000000000000010000000000017 ++:10B9200000000000000000000000200000000000F7 ++:10B9300000200000000000000000100000000000D7 ++:10B940000000000000001003100988088221880010 ++:10B9500004008800040804008800904110000000E2 ++:10B9600001809120000000000000000000000000A5 ++:10B9700000000000000000000000000008000000BF ++:10B980000000000000000000C000C040A0008200D5 ++:10B990000800100000404000040082000000002069 ++:10B9A000002010000400040000000000000000005F ++:10B9B0000000000000000000000000000000000087 ++:10B9C00000000000000000008300008083410000B0 ++:10B9D0000300004189888300030000030341000045 ++:10B9E000030000C10900000000000000000000008A ++:10B9F0000000000000000000000000000000000047 ++:10BA00000000000000000000000000000000000036 ++:10BA10000000000000000000000000000000000026 ++:10BA20000000000000000000000000000000000016 ++:10BA30000000000000000000000000000000000006 ++:10BA400000000000000000000082838200C08341EB ++:10BA500000820102024182C0098885820001010141 ++:10BA6000000201A0C0C100000000000000000000B2 ++:10BA700000000000000000000000000000000000C6 ++:10BA800000000000000000000000000000000000B6 ++:10BA900000000000000000000000000000000000A6 ++:10BAA0000000000000000000000000000000000096 ++:10BAB0000000000000000000000000000000000086 ++:10BAC00000000000000000000000820040820083AF ++:10BAD0000000820411820082C0029083838200836E ++:10BAE000C100820003820083010400000000000006 ++:10BAF0000000000000000000000000000000000046 ++:10BB00000000000000000000000000000000000035 ++:10BB10000000000000000000000000000000000025 ++:10BB20000000000000000000000000000000000015 ++:10BB30000000000000000000000000000000000005 ++:10BB40000000000000000000000000000000008075 ++:10BB50000083000000008280008080001083208924 ++:10BB60000083C100090082800083410000000000C2 ++:10BB700000000000000000000000000000000000C5 ++:10BB800000000000000000000000000000000000B5 ++:10BB900000000000000000000000000000000000A5 ++:10BBA0000000000000000000000000000000000095 ++:10BBB0000000000000000000000000000000000085 ++:10BBC0000000000000000000000000000000000273 ++:10BBD000000083C1000000000000802011C100406F ++:10BBE00000008302000000000080800000000000D0 ++:10BBF0000000000000000000000000000000000045 ++:10BC00000000000000000000000000000000000034 ++:10BC10000000000000000000000000000000000024 ++:10BC20000000000000000000000000000000000014 ++:10BC30000000000000000000000000000000000004 ++:10BC400000000000000000000000000000000000F4 ++:10BC50000001008283C10000000000C0828940C151 ++:10BC600000830082838300000000000482820000C1 ++:10BC700000000000000000000000000000000000C4 ++:10BC800000000000000000000000000000000000B4 ++:10BC900000000000000000000000000000000000A4 ++:10BCA0000000000000000000000000000000000094 ++:10BCB0000000000000000000000000000000000084 ++:10BCC0000000000000000000000000000000000074 ++:10BCD0000000834101820183000004400182A183AE ++:10BCE00002A183820101018300004082000401015E ++:10BCF00002C1000000000000000000000000000081 ++:10BD00000000000000000000000000000000000033 ++:10BD10000000000000000000000000000000000023 ++:10BD20000000000000000000000000000000000013 ++:10BD30000000000000000000000000000000000003 ++:10BD400000000000000000000000000000000000F3 ++:10BD5000000000000203048041020000008008800F ++:10BD60009082004002820403028300008080000071 ++:10BD7000024000C0000000000000000000000000C1 ++:10BD800000000000000000000000000000000000B3 ++:10BD900000000000000000000000000000000000A3 ++:10BDA0000000000000000000000000000000000093 ++:10BDB0000000000000000000000000000000000083 ++:10BDC0000000000000000000000000000000000073 ++:10BDD000000000000000000000000000124200000F ++:10BDE00000000000124281480013C200124200000D ++:10BDF00000000000124200000000000000000000EF ++:10BE00000000000000000000000000000000000032 ++:10BE10000000000000000000000000000000000022 ++:10BE20000000000000000000000000000000000012 ++:10BE30000000000000000000000000000000000002 ++:10BE400000000000000000000000000000000000F2 ++:10BE50000000000000000000FFFFFFFFFFFFFFFFEA ++:10BE6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10BE7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10BE8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:10BE9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:10BEA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:10BEB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:10BEC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 ++:10BED000FFFFFFFFFFFFFFFFFFFF00243B8F0C442E ++:10BEE000807000E80A0600006059AEDE0000000025 ++:10BEF0000000000000000000000000000000000042 ++:10BF000000000000000000007B7500000000000041 ++:10BF10000000000000000000000000000000000021 ++:10BF20000000000000000000000000000000000011 ++:10BF30000000000000000000000000000000000001 ++:10BF400000000000000000000000000000000000F1 ++:10BF500000000000000000000000000000000000E1 ++:10BF6000000000000000000000000000067BC00090 ++:10BF7000000000000000008C07000000000000002E ++:10BF800030000000000000000003DE600000000040 ++:10BF900000000000000000000000000000000000A1 ++:10BFA0000000000000000000000000000000000091 ++:10BFB0000000000000000000000000000000000081 ++:10BFC0000000000000000000000000000000000071 ++:10BFD0000000000000000000000000000000000061 ++:10BFE000000000000000000000000000000003004E ++:10BFF000C100100011000300210003000200000036 ++:10C000002100210021002100000010081100000083 ++:10C0100020090300040080A00410040004100000A4 ++:10C02000040021000420030820018000000000001B ++:10C030001100200000000000110004000000200892 ++:10C0400000000300040004000405000000040304D1 ++:10C050000300040011000000000000002100200087 ++:10C06000200000200000000000000000000011007F ++:10C07000000040000100000000000000200001005E ++:10C08000000090002000400000000000210000009F ++:10C09000000300889000002104000080900021002F ++:10C0A0009000820020000080008001042000000039 ++:10C0B000000000000000000000410000000000003F ++:10C0C0000180000000000000000000A000000080CF ++:10C0D00000800000000000000000000000000000E0 ++:10C0E00001000000008000000000000000000000CF ++:10C0F00000000000000000000000000080000000C0 ++:10C1000000000000000000000000000000028000AD ++:10C1100000C00000000000208011000000000000AE ++:10C12000040000000000000000000000000000000B ++:10C13000000000C0004000000000000900000000F6 ++:10C1400000000000000000000002000000000000ED ++:10C150000000040000000082000000000000000059 ++:10C1600000000001000000000000000100010000CC ++:10C1700000010000000000000000A01000000410FA ++:10C1800000080000000000000000001090100000F7 ++:10C1900002100000000000210480042000000010B4 ++:10C1A000000005000011C0109000201000100000D9 ++:10C1B000001000100000008000000000004000009F ++:10C1C00000100041001000000010A000001000103E ++:10C1D000000000100110000000000000000000003E ++:10C1E00000410000000400000010000000200020BA ++:10C1F00000000020001004002000000040C0418426 ++:10C2000000010000058800008400094000000008CB ++:10C21000008400C000401000052083A040C1080039 ++:10C2200005202101210021000882410090A00090FA ++:10C230000900410805840000000010080000050006 ++:10C2400041084100000800A00900000002000008A9 ++:10C25000000000000000A10000000000000000003D ++:10C2600011000000000000000000000000000000BD ++:10C2700000000000001000001000111182000000FA ++:10C2800000080002000010000000100010831000E1 ++:10C2900000008400C00000000100009104000108BB ++:10C2A000110000800040C0000000010000000400F8 ++:10C2B00000000000000084080000901100800000D1 ++:10C2C00000000000000000910000000000000109D3 ++:10C2D000008000400000000002000000000000009C ++:10C2E00000000000000000000040000000400011BD ++:10C2F000001000000000000000001000040090008A ++:10C3000002000900C100410020004100200003009C ++:10C3100000000000C00041000201C10010008301C4 ++:10C3200000000000410083000200410041001000B5 ++:10C330001000030003000000090000000500800059 ++:10C34000410010200200040004010000000003006E ++:10C350002100030100000000000021011000410045 ++:10C360001000000000000300050010000000900114 ++:10C370000000040010000500210010008900841056 ++:10C38000410085200002040000000508C000A02034 ++:10C3900000000020A0414120004101404000014137 ++:10C3A000102004000000020004058300C000000506 ++:10C3B00020000100000000000200820800000000D0 ++:10C3C000020088000000910000002040C000000032 ++:10C3D0000200000000080000000000000002000051 ++:10C3E0000000010000001000820082000008C00070 ++:10C3F0000408C000010082000000000000004100AD ++:10C4000002C10040000000400020418441A100889A ++:10C410000985412041010400210800002100C000DD ++:10C420000408040004400884000041100089210031 ++:10C43000410005A00300000003821000020000007C ++:10C44000020182A0028840000588028810001000C6 ++:10C4500004001000000020A09001108800002101BD ++:10C460000000000010004100000010002100A100A9 ++:10C4700000000400030010840020008800840000F5 ++:10C480000000010410008400102100A184000002BB ++:10C49000840000408480082000000000100010107C ++:10C4A0004100018011000100830000009000C040A5 ++:10C4B0000000820000000000104004008400110011 ++:10C4C00000C0C14011400100010500090100004009 ++:10C4D00000000000A000000001000420040088000B ++:10C4E0000020820000000100001100000000000098 ++:10C4F00004000000010000000000008000000000B7 ++:10C50000000004090310080202A020200501100009 ++:10C5100005040010211000C08021208210000000BE ++:10C520008000100190008400842005100011052077 ++:10C5300000000400400041C0200005000000004051 ++:10C5400003080000410000410409000041900090F0 ++:10C550004000804003002004000410900000000010 ++:10C5600000000040000000000300009000000300F5 ++:10C5700003004100C10103011000850904200000EF ++:10C5800000210000008888030080200000000020B7 ++:10C5900002050080C000C005A0000240000082002B ++:10C5A000C0000211C004100021002100008084900E ++:10C5B0000080840000000420000000000000C00093 ++:10C5C000000084C10000000000881088000090086E ++:10C5D0000420040002840000000010001108200064 ++:10C5E0000011000000C0000000000000000000007A ++:10C5F0000000000000001008820882001082018004 ++:10C60000000000A00000050802020308410804051C ++:10C61000000008410810000502104121000511002A ++:10C62000800021000800400302084140044000004F ++:10C630000000400000000000000020000000400555 ++:10C6400000091020000800000489020440842089A9 ++:10C65000410021802000418000000000090000000E ++:10C660008983088011834189030000000000400095 ++:10C6700011000000000009008003000411110008EF ++:10C68000008000800280000001018901000001019A ++:10C690000000040001000101000040000100000052 ++:10C6A00000008200000000000901080105010001EE ++:10C6B00000000200910000000000080000000000DF ++:10C6C000010190010101000100000008009001C07B ++:10C6D00001080082904001040104000000000000F5 ++:10C6E0000000898382C0000401890100000000006D ++:10C6F000010000000000000001008401A001010011 ++:10C7000000010088A08400880090020008040491C1 ++:10C710004088000100400001001040010000A00816 ++:10C72000408340000000A0009001040109008389BB ++:10C730000010C082A000A082820100000000010061 ++:10C74000000000000100000000000000C100050022 ++:10C75000A10002A1C000010009C08408410020001E ++:10C76000A00085010200A0841103A10000000000C8 ++:10C77000000000000100010000000000C101C182B2 ++:10C78000A091A0820001C00088008404C0058380BD ++:10C7900082880000004005904005208200080300C8 ++:10C7A0008380C0A020000200850004050011100055 ++:10C7B00005050880008000008080800504000400DA ++:10C7C00010000900000040004100020000002005A8 ++:10C7D000850085002005080308008500A141A00010 ++:10C7E00084004100C0080800080002411003000056 ++:10C7F000000000000000110040000400400010058F ++:10C800000280080811800020000080008000088855 ++:10C81000004000880088202000A1008509901000B9 ++:10C8200000000000058000C000A000028005040296 ++:10C8300000852120C0090000110000800080000058 ++:10C8400000000080808040400082200900850000B8 ++:10C85000020500850090830300C0800490218000C1 ++:10C8600000800000000000000221000509A10389EA ++:10C8700000040010000200110008000811210090BF ++:10C88000090000000200C08000000000000000005D ++:10C890000010002100840009000800880008090534 ++:10C8A00001C000040002C1C0000300C10020040553 ++:10C8B00000A0001101C09000002000040008408288 ++:10C8C00000A0000000A0888200A0001101C10009A2 ++:10C8D000000000C004910010039000850884A1C0EE ++:10C8E00010C0000400C00002000201008203838522 ++:10C8F0009141000000000000000000010000000164 ++:10C900000889000200400082890800A002C082104D ++:10C9100000400503A105830009021108840090016D ++:10C9200002000408200982000088000000000000C6 ++:10C93000001091050111200108400001008800004D ++:10C9400000880000000000010000001001A00000AD ++:10C950000000000010010401A001904002A1C001EC ++:10C960000400040200000000000000C00089010271 ++:10C9700001010110000000000000000000000001A3 ++:10C9800000000000832089018501408888C0A00044 ++:10C99000A000A004831020082041C180A0800403CF ++:10C9A00041404000800080200041008000000009DC ++:10C9B00000050080100840402002890000400080EF ++:10C9C0000000000000000040002000000080400443 ++:10C9D000054041000000801080088008800080022F ++:10C9E000000380040000000500040009000020A0EE ++:10C9F00040A111400980000000000000000000007C ++:10CA00000040000400000302C10990214000000220 ++:10CA100000000000000000410000C2000000000013 ++:10CA2000001381000000820000130000005000008D ++:10CA300000000000060000880013C2000000000093 ++:10CA4000008100008141000000130000000000810F ++:10CA50000000C2000000000000000000000000888C ++:10CA600000000000C2008200000000008100000001 ++:10CA7000000000818100005000000000000006005E ++:10CA800000000022C2000000000000130000066049 ++:10CA900000000013000000002D2DFF6600010000C3 ++:10CAA000F0C060400000F7C7000000000000000078 ++:10CAB000000000006FFFCF0F0FBD0F24FFFFFFFF2F ++:10CAC0000000000000000000000000000000000066 ++:10CAD000FC0CFC0CFEC23E020000000000003E66A2 ++:10CAE0007E0600000000660F660F000000000000D8 ++:10CAF0000000890809090000000000000000000093 ++:10CB000000B0000000003C3C3F3CF9FFC1020000C7 ++:10CB1000000000000000000000002D2D9900000022 ++:10CB2000000030002000000034040000000000007D ++:10CB3000000000000000FF6600000FBD0F24FFFF93 ++:10CB40007FFF000000000000000000000000000067 ++:10CB50000000FC0CFC0CFEC23E02000000000000C5 ++:10CB6000BF667E0600000000663C663C00000000D8 ++:10CB7000000000008100000006063C0600000000E6 ++:10CB80000000002000000000FDFDFDFDF9FF000099 ++:10CB9000000000000000000000000000FFFFFFFF99 ++:10CBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:10CBB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10CBC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10CBD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:10CBE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:10CBF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10CC0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10CC1000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00041E ++:10CC200043030C4480F000180A0600005014C000B2 ++:10CC30000000D8FCD8FC0000000060FFF9FFC0C075 ++:10CC400000C360666F6600000000FCFF6666C6F603 ++:10CC5000C3FFF666F6FF00000000000000000000C1 ++:10CC60000000CCC3CFCA00FF00FF6FF6F66F0000D4 ++:10CC7000210000C360F666FF00000000FFFFFFFF19 ++:10CC800000000000000000003535FEFE000F020E1F ++:10CC9000000000000000000000000000C3E3D3E338 ++:10CCA00020202000FFFFFFDF000000000000000048 ++:10CCB000C0C00000C0E4C0E404040000009F0006FF ++:10CCC0004242424260006FFF00000000FCFC6666CA ++:10CCD0000636003C90009099000000000000000023 ++:10CCE000000000003C5A3CC330303F3F099090099F ++:10CCF000000028000000247E247E00000000FEFFCB ++:10CD0000FFFF0000000000000008353501010000B1 ++:10CD100002020000000000000000000000000060AF ++:10CD2000906020200000FFFFFFFF000000000000D7 ++:10CD300000000586006408B0008000860C2008B062 ++:10CD400000850086006101B000000086006000B030 ++:10CD5000008000860ABCA0880000008600E000B0C9 ++:10CD6000000000860061001000000086007400B022 ++:10CD7000000000000086026000B0008000860060B5 ++:10CD800008B000050086006008B0000500860A5162 ++:10CD900000B00000000000000000000000860061FC ++:10CDA0000898000005860A210090000000860041D6 ++:10CDB00000A00000FFFFFFFF10303030140014F01F ++:10CDC000BFFFBFFFAAAFFFAF6FB07FA000000000A2 ++:10CDD000FFFFFFFFF0F0F0F0553C553C0000000075 ++:10CDE0002ED1FF2E00000000555500FF000000006E ++:10CDF000EB82FFAA0000405503FFC3F0C355C3C92F ++:10CE0000CECEAAAAFF0F000000000E024F7F000046 ++:10CE100000005555555500000000000000000000BE ++:10CE20000000FFFF0000F2F18241577F55FFF3F74A ++:10CE3000F3A205AF05AFE8EBFCFF00300030410086 ++:10CE400041F0BFFF8FCFAAAFAAAF14EB55AA0000E5 ++:10CE500000005D5D55FF7D7D28280F0F0F0F00003E ++:10CE60000000D12E2E000000000055553C3C000073 ++:10CE70000000EB82FAA00000BFFAFC00C3F0C3552B ++:10CE8000C3963C3CAAAAC3C3000000000E024F7F19 ++:10CE90000000000000F00FFF000000000000000094 ++:10CEA00000000000FFFF0000F0F000005555555550 ++:10CEB00030753020042CC7EF000000000000FFFF99 ++:10CEC000000000000000000000000000AA2882000E ++:10CED0000000000000143C7D000000005C5F5C5F0F ++:10CEE00000000000CC9955AA0000000000000000DE ++:10CEF0000000000000000000000000001000EE44F0 ++:10CF000044EEFF7C3F7C55FF55C3000000000070DD ++:10CF1000F070FFFFFFFECFC055550000000000007D ++:10CF200000000000000000000000000000005C3C69 ++:10CF30005FFFAB03EAC00A00FFFF00000000000033 ++:10CF4000001E000000000000000000000000AA28F1 ++:10CF500082000000000000143C7D000000005C50D6 ++:10CF60005C50000000009933AA550000000000004A ++:10CF700000000000000000000000000000001000A1 ++:10CF8000BB1111BBFF00F000553C55000000000034 ++:10CF90000040F040FFFE0001303F5555000000000A ++:10CFA0000000000000000000000000000000000081 ++:10CFB0005C3C5000AA00AA000A000A00040000001D ++:10CFC00000000400000002000208800011000400BC ++:10CFD000A000042011000000119004004000210076 ++:10CFE0009100040011001100040011014000210013 ++:10CFF00000000000400080004000400000000400ED ++:10D000000000000004000000040004000400000010 ++:10D010000000800000000400000004000400040080 ++:10D0200000000000040000000000000000000000FC ++:10D030000000000000000400000004000400A00044 ++:10D0400000000000000000000100010002000000DC ++:10D05000000002000080000000000000000004004A ++:10D06000000010009000A000000000000008010077 ++:10D070000000040000000000400000000400000068 ++:10D0800000000000000000000000000000000000A0 ++:10D090000000000020000000000000000000000070 ++:10D0A0000000000000000000000000000000000080 ++:10D0B0000000000000000000000000000000000070 ++:10D0C0000000000000000000000000000000000060 ++:10D0D0000000000000000000000000000000000050 ++:10D0E000000000000000000100000000000000003F ++:10D0F000000000000000000000000000000000012F ++:10D1000000C000000000000000000000000000005F ++:10D11000000000000000000000000000000000000F ++:10D1200000000000000000000000000000000000FF ++:10D1300000000000000000000000000000000000EF ++:10D1400000000000000000210000000000000000BE ++:10D1500000000000000000000010000000000000BF ++:10D1600000000000000000000004000000000000BB ++:10D17000000000000000000000100021000000007E ++:10D180000008000000000000000000000000000097 ++:10D19000000000000000000000000010000000007F ++:10D1A000000000000000000000000011000000006E ++:10D1B000000000000000000000000010000000005F ++:10D1C00000000000000000000000000000018000DE ++:10D1D000800100000500000010C0840000C080082D ++:10D1E00080400002400200008082A0A10000008276 ++:10D1F0000040000005841000000810A0000000009E ++:10D2000000000000000000C000020082800000C09A ++:10D2100000A0000000010004000400010000000064 ++:10D2200000A003002000000100000000000000003A ++:10D2300000000000000000000001000000010000EC ++:10D24000000100000000C021C00084000010004068 ++:10D25000020510100000C0418200010005411010BD ++:10D260001085208084A10180820020411104C041EA ++:10D27000100000C100211000000084800100C041A6 ++:10D28000840082000000000000051080C000100033 ++:10D290001000C02182000008008000800004A0036C ++:10D2A000C00000000000010400200000C000A00039 ++:10D2B0000000000000000000000000048400C00422 ++:10D2C0000400002000000000200000000200020016 ++:10D2D0000200200011000000400002000500400094 ++:10D2E0000900100020000300000005001000850068 ++:10D2F000030040000900000003000300210041007A ++:10D3000010000500020000000000000009001001EC ++:10D310000500410011000000100002000000410063 ++:10D3200005000000000000000900000000004100AE ++:10D3300041000000100000004100000020004100FA ++:10D3400020000200040005000400000000000000AE ++:10D3500001000000000000000000010000000000CB ++:10D360000100000001008300000000050000010032 ++:10D37000200000000100000000000000000000008C ++:10D38000000200000000100000000000000000008B ++:10D3900000400000900000000000010000000000BC ++:10D3A000000000000000000000000000000000007D ++:10D3B000000000000000000000000000000001006C ++:10D3C0008400010000000100000001000000410095 ++:10D3D000410000008200100108100040100082018E ++:10D3E0000500C1200000808203C000A000000304EB ++:10D3F000000000880000900210000000050000847A ++:10D40000410021A000004100100000880000000041 ++:10D410001000020041110000000041C01083000014 ++:10D420000004000020040001A000000100A0000092 ++:10D4300000000000000000C000000000000000002C ++:10D44000000041008040000080A00000000090002B ++:10D450000021100500000300100801808885C0002D ++:10D46000034000410480001010050000000000008F ++:10D470000080C005000500004080012184040000F8 ++:10D480000000A000100000000021890800000040FA ++:10D49000000000051100C040104182000000014062 ++:10D4A00000001080C0000180000821000004000975 ++:10D4B0000021000000000000000000030000101028 ++:10D4C00000000000C0002021000004000000000057 ++:10D4D00009001100040000001040038202000082D5 ++:10D4E00000C0034010000300418805820040051081 ++:10D4F000099002000000410403000000020000A0A7 ++:10D5000009004184114000820590030005080420B1 ++:10D510000000008400A005000000000000840288D4 ++:10D5200020001000000420000240000000000088DD ++:10D530000000000000C00000000400C00000100057 ++:10D5400000000000000002000900020000000000CE ++:10D550001120000000000400000000800000000016 ++:10D56000000000000000010000000000000000803A ++:10D57000000000000000000000800000000000002B ++:10D58000000000000000000000000000000000801B ++:10D59000018000000000000000000000000000000A ++:10D5A000000000000000008001000080000000007A ++:10D5B000000000000000000000000000000000006B ++:10D5C000000000000000000000000000000000005B ++:10D5D00000000080000080000000000010C000106B ++:10D5E00020C1110304000008104041204103000243 ++:10D5F000004020100520000200020509C0000000C4 ++:10D600000000090021400008001041202000000017 ++:10D61000090000000000034000400300050903006A ++:10D6200000002000200000008040201002020220A4 ++:10D6300000020004200500000000000000000000BF ++:10D640000000000000000305004100410940008087 ++:10D650004080108000000000C00000000000C18277 ++:10D6600020850110008408008400010000000001F2 ++:10D6700000000000010100010000000000010500A1 ++:10D680000000000000000000000100010000010097 ++:10D690000000000000000000C10184010000010042 ++:10D6A00001000000010000000000880101010000ED ++:10D6B0000101000000000100000000000000000067 ++:10D6C0000000000000000000010100000000010057 ++:10D6D0000008C140011000A020004000040002002A ++:10D6E000A00140008200104090020804050185045A ++:10D6F000050041004020200000000001010201015E ++:10D700000800A00082004100A100890090000200F2 ++:10D7100000000000010000000000030040000200C3 ++:10D7200002008900400040000800000000000000E6 ++:10D730000000000000000005010000900000000053 ++:10D74000000000000000000000000000008801014F ++:10D75000010108004000000010C0000080008000AF ++:10D7600080020008800000008080850000C08505E0 ++:10D770009080900088000500210000004002058094 ++:10D780001003C000020041008300100040000200AE ++:10D79000C0000500020005000000000011000000AC ++:10D7A0004100890011008500C100800009000300CC ++:10D7B00000410200000002000020090000000000FB ++:10D7C0000000000000000000000000004100418057 ++:10D7D00005210809804180000000808000000000D1 ++:10D7E000008000000240008291C000080510002067 ++:10D7F00040204089044000200002054141090020EA ++:10D80000020220200002002000050040050800114F ++:10D810000000090900900040000500890000090887 ++:10D8200000820020408300C000C100A10090089148 ++:10D830000005002104200041000200094002000010 ++:10D8400000000000000000000000000000000503D0 ++:10D8500000030002090800808000C1808000008869 ++:10D8600000900084002001898404A1C0C0200089A8 ++:10D8700000A00102C0110001000100000101000030 ++:10D880000001010001010000000000000001000192 ++:10D89000000100000000000300A0008200880000DA ++:10D8A000000300C00002C140000500040084000520 ++:10D8B000018800040005040100010000000191003E ++:10D8C0000000000000000000000000000000000058 ++:10D8D000000000000001000000408882A08488024F ++:10D8E00000000000000000908441A020400002C021 ++:10D8F000C0088340A100C084000000850001000230 ++:10D900000004008400000000000100030000000487 ++:10D9100000000001000100200040000000010000A4 ++:10D92000000000010085000100400001000000002F ++:10D9300000200002018400400000000001400001BE ++:10D9400000000000000000000000000000000000D7 ++:10D950000000000400000000000084038400400078 ++:10D9600040A00020000000000000808200808000B5 ++:10D970008000032011910203C080000500C0002038 ++:10D980000000008000800000000000200010000364 ++:10D9900000800040000500050000008000020040FB ++:10D9A00000000000002000A0001000800003000420 ++:10D9B0000003000009004005028441000300408488 ++:10D9C0000021020000000000000000000000000034 ++:10D9D00000000000058005020341080080030000EC ++:10D9E00080000000000000000000000000000000B7 ++:10D9F000000000001200001300000000008800007A ++:10DA0000C200000000000000C20000500000000042 ++:10DA1000C20000000000000000000000120000131F ++:10DA20000000000000000000000000008100000075 ++:10DA3000000000000A0000000000C20000000042D8 ++:10DA40000000C20000000000008100000000000093 ++:10DA500000000000000000000000C2000A000000FA ++:10DA60000013000021000000000000000000000082 ++:10DA70000000E1FF00E1D4D71417FFFF00FF000012 ++:10DA80000000CF000F000000000000800000000038 ++:10DA9000000069BB69C3000000000F0F0F0F0000FA ++:10DAA0000000141D1D7D000000000000D7D41714D5 ++:10DAB000000000000000FFFF40704F7F000FFF0FCD ++:10DAC00069696996000FA0AF000000000000000027 ++:10DAD0000000000000000000000082C300550000AC ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000FF00001417D4D75D5D00FF98 ++:10DB000000000000F2000200000000000000000021 ++:10DB100000000000396939C3000000009696696969 ++:10DB200000000000141D1D7D0000000000001417FF ++:10DB3000D4D70000000036C636C640704F7F3C3C4C ++:10DB40003C3C69696996202F202F000000000000EE ++:10DB5000000000000000000000000000030300308F ++:10DB600000000000000000000000000000000000B5 ++:10DB70000000FFFFFFFF00000000FEBEFEBE3C698C ++:10DB800069C3FF3CF0B2BFBCB3B000500040FFFF20 ++:10DB9000FFF000000000AAFFB2F3428100003C0544 ++:10DBA0003C5000000000FCB8FCB80000AA69559683 ++:10DBB000FF55AA0000000000AFA0AFA0FBD3FBD32D ++:10DBC000AAAAF0F0AA3FAA30FFFF0F0F0000000042 ++:10DBD000000000000000000000000000FFFFAA009D ++:10DBE000FF30FF30000000000000000000000000D7 ++:10DBF00000000000FFCFFFFF00000000FC3CFC3CE9 ++:10DC0000C396963CC300E8AA8F8C83800010000066 ++:10DC1000FFFFFFF000000000AA00B2307EBD3C3CD8 ++:10DC20003CF53C5F00000000B830B830000069559A ++:10DC300096AABE14BE1400000000ACACACAC381008 ++:10DC400038103C3CF0F0AA3FAA30FAFA0A0A000069 ++:10DC50000000000000000000000000000000FFFFC6 ++:10DC6000AC00FF70FF2000000000000000000086F4 ++:10DC7000006000B000000086006000B00000008678 ++:10DC80000C6101B8008000860A6408B00000000042 ++:10DC90005010A00800050086007000B0001000863B ++:10DCA000006000B8008000860061019000800000E4 ++:10DCB0000086006000B800800086006000B80000A8 ++:10DCC0000086007000B0000000000014000000009A ++:10DCD0000086006100B000000000000000000000AD ++:10DCE00000000000080000000086002100900000F5 ++:10DCF00000000000FFFFFFFF5F5FEEEF005F005FCF ++:10DD0000C3000000FFFFAEEF0000000000000000B5 ++:10DD10000000000000000000000000000000000003 ++:10DD20000000000000000000000000000200575545 ++:10DD30000000000000003FFDC0C20000000005C55B ++:10DD400035F50000000066CC66CC00000000000045 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000FFFFF00000FFC6 ++:10DD70000FFF00000000000F3C3F5F5FFBBFC3438D ++:10DD800083C3C3030000AAAA088A000000000000A1 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000000020071 ++:10DDB0005755000000000000050FFAF000000000B9 ++:10DDC00005C535F50000000033663366000000002D ++:10DDD0000000000000000000000000000000000043 ++:10DDE000000000000000000000000000FFFFB01075 ++:10DDF00001FF0DFF00000000FFFFFFFFFF0FACACB5 ++:10DE0000A0A0C300000000003C3C3C3C000000001F ++:10DE100055558FDF000000000000000000000000EA ++:10DE2000417D417D00000000DD7788220000000078 ++:10DE3000000000000000000000005AA9AAAA00008B ++:10DE400000001E4B4B1E0000000000000000000000 ++:10DE500000000000000000000000000000000000C2 ++:10DE60000000000000000000000000000000090A9F ++:10DE7000000034340000000000001F5F0000F000CC ++:10DE8000ACAC0000000000000000F50505F5000046 ++:10DE9000000000555F5F000000000000000000006F ++:10DEA00000000C0CCFCF00000000FFFFAAAA00006A ++:10DEB000000000000000000000000000595B595BFA ++:10DEC00000000000B4E1E1B4000000000000000028 ++:10DED0000000000000000000000000000000000042 ++:10DEE0000000000000000000000000000000000032 ++:10DEF0000A0A0000080800000000000000000000FE ++:10DF0000000000002000200100000000008420002C ++:10DF100000002000000000000000000021000000C0 ++:10DF2000200000000000210100000000200004008B ++:10DF300000000000000020000000000000002100A0 ++:10DF400020010000000000000000000000000000B0 ++:10DF500004000000000000000400000000000000B9 ++:10DF600000000000000000000000000000000000B1 ++:10DF700000000000000000000000000000000000A1 ++:10DF80002000000000000000004000000000000031 ++:10DF90000000000000000000000000000000000081 ++:10DFA0000000000000000000004000000000000031 ++:10DFB0000000000000000000000000000000000061 ++:10DFC0000000004000000000000000000000000011 ++:10DFD0000000000000000000000000000000000041 ++:10DFE0000000000000000000000000000000000031 ++:10DFF000000000000000000000000000FFFFFFFF25 ++:10E00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 ++:10E01000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:10E02000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10E03000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 ++:10E04000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ++:10E05000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10E06000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10E07000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00F4BA ++:10E08000BBCE0C44808800C00A06000080A20000BD ++:10E090000000000000000000000000000010000070 ++:10E0A0000000001000100000000000000000000050 ++:10E0B0000000000000000000000000000011000847 ++:10E0C0000000002100080000000000000000000027 ++:10E0D0000000000000100000000000000000000030 ++:10E0E0000000000000000000000000000000000030 ++:10E0F0000000000000100000000000000000000010 ++:10E10000000000000000000000000000000000000F ++:10E1100000000000000000000000050000000000FA ++:10E12000000010000084000000000000000000005B ++:10E1300000000000031000000000000000000000CC ++:10E1400000000000000000000000000000000000CF ++:10E150000000000000000008410000000000000076 ++:10E1600000000000000000000000000000000500AA ++:10E17000000000000000100000000000000000008F ++:10E18000000000000000000000000000000000008F ++:10E1900005000000000000000000820000000000F8 ++:10E1A0000000C000000000000008000300000000A4 ++:10E1B000000000000000000000000000000010004F ++:10E1C000100000000000000000000000000000003F ++:10E1D00000000000000000001000000000008400AB ++:10E1E000C000100000000000C0000000000000009F ++:10E1F000000010000000000000000000000000000F ++:10E20000000000000000000000000000000000000E ++:10E2100000000008050000000000400000000000B1 ++:10E2200000000000000000000000050000000000E9 ++:10E2300000000000000000000200000000000000DC ++:10E24000200000000000000000002000000000008E ++:10E25000410000000000000000002000000000005D ++:10E2600000000000000000000000000000000000AE ++:10E27000000000000000000000002000000000007E ++:10E28000000000000000000000000000000000008E ++:10E29000000002000000FFFFFFFFFFFFFFFFFFFF86 ++:10E2A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10E2B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10E2C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:10E2D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:10E2E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E ++:10E2F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:10E30000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D ++:10E31000FFFFFFFFFFFFFFFF00A8A5EF0C44808871 ++:10E3200000100A06000080200000410000C000002C ++:10E3300000000008000000000000000000000000D5 ++:10E3400000000000000010000000000000000000BD ++:10E3500000000000000000000000000000000000BD ++:10E3600000000000000000000000000000000000AD ++:10E37000000000000000000000000000000000009D ++:10E38000000000000000000000000000000000008D ++:10E39000000000000000000000000000000000007D ++:10E3A000000000000000000000000000000000006D ++:10E3B000100000210000000000080010000000080C ++:10E3C000000000000000000000000000000000004D ++:10E3D000C000000000001000100000000000C0009D ++:10E3E000000000001000C00300000000000000005A ++:10E3F0001000C00000000000C00000008400000801 ++:10E4000000001000000000000000000000000000FC ++:10E4100000001000000000000000000000000000EC ++:10E42000C00000000000000000001008000009000B ++:10E4300000000000000000000000200000100000AC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000200000000000100000000000000002006A ++:10E48000000010000000000000000000000000007C ++:10E49000000000000000000000000000000000007C ++:10E4A0000000000010000000000000000000FFFF5E ++:10E4B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:10E4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:10E4D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10E4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10E4F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10E50000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10E51000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10E52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:10E530000080EFA70C44808800700A06000000C32A ++:10E54000010000000000004000000000000000008A ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000200000000000006B ++:10E59000000000000000000000000100000000007A ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C0000000080000000000000000000000000043 ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000000000000000000000000000000000001B ++:10E60000000000000000000000000080000000008A ++:10E6100000000000000000000000000020000000DA ++:10E6200000000000000000000000000000000000EA ++:10E6300000000000000000000000000000000000DA ++:10E6400000000000FFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10E65000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:10E66000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:10E67000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:10E68000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10E69000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A ++:10E6A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7A ++:10E6B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A ++:10E6C000FFFFFFFFFFFF00607B330C44808800E802 ++:10E6D0000A060000004100000000000000000000E9 ++:10E6E0000000000000020000000000000000000028 ++:10E6F000000000000000000000000000000000001A ++:10E700000000000000020000000000000000000007 ++:10E7100000000000000000000000000000000002F7 ++:10E7200000000000000000000000000000000000E9 ++:10E7300000000000000000000000000000000000D9 ++:10E7400000000000000000000000000000000000C9 ++:10E750000000000000000000FFFFFFFFFFFFFFFFC1 ++:10E76000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9 ++:10E77000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9 ++:10E78000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 ++:10E79000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10E7A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:10E7B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69 ++:10E7C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59 ++:10E7D000FFFFFFFFFFFFFFFFFFFF00445F9E0C44B2 ++:10E7E000808800D80A06000040D300000020000006 ++:10E7F0000100000000000000000000000000000018 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000000000000000000000000000F8 ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000100000000000000000000000000D7 ++:10E8400000000000000000200000000000000000A8 ++:10E8500000000000000000000000000000000000B8 ++:10E860000000000000000000000000000040000068 ++:10E870000000020000000000000000000000000096 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000004028 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000200000046 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F00000000900000000000010000000000000FF ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000010000000000000E7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000010080000000000000000000000BF ++:10E9400000000000000000000000000001000000C6 ++:10E9500000000000000000000000000000000000B7 ++:10E9600000000000000000000000000000000000A7 ++:10E97000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 ++:10E98000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 ++:10E99000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 ++:10E9A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 ++:10E9B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 ++:10E9C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 ++:10E9D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 ++:10E9E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 ++:10E9F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 ++:10EA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:10EA1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:10EA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10EA3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:10EA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10EA5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:10EA6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 ++:10EA7000FFFFFFFF0000000000000000000000009A ++:10EA80000000000000000000000000000000000086 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000800010048800000000085 ++:10EAC0000000000000000000000000000000000046 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB30000000000000000000004000000000000095 ++:10EB400000000000000000000000000000000000C5 ++:10EB500000000000000000000000000000000000B5 ++:10EB600000000000000000000000000000000000A5 ++:10EB70000000000000000000000000000000000095 ++:10EB80000000000000000000000000000000000085 ++:10EB90000000000000000000000000000000000075 ++:10EBA0000000000000000000000000000000000065 ++:10EBB00000000000000000000000102000001020F5 ++:10EBC0000000000000000000000000000000000045 ++:10EBD0000000000000000000000000000000000035 ++:10EBE0000000000000000000000000000000000025 ++:10EBF0000000000000000000000000000000000015 ++:10EC00000000000000000000000000000000000004 ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000004000000000000000A4 ++:10EC30000000004010000000000000000000000084 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC8000000000000000000000000000000008007C ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000020000000000000000000000000062 ++:10ECB0000000000000000000000000000000000054 ++:10ECC0000000000000000000000000000000000044 ++:10ECD0000000000000000000000000000000000034 ++:10ECE0000000000000000000000000000000000024 ++:10ECF0000000000000000000000000000000000014 ++:10ED00000000000000000000000000000000000003 ++:10ED100000000000000000000000000000000000F3 ++:10ED200000000000000000000000000000000000E3 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED8000008082A30C8500400400040004000400FD ++:10ED90000400040004000400CC2600000000000071 ++:10EDA00000000C44408000A0CC26000000000000C1 ++:10EDB00000000C4440800030CC2600000000000021 ++:10EDC00000000C44408000B0CC2600000000000091 ++:10EDD00000000C44408000F0CC2600000000000041 ++:10EDE00000000C4440800008CC2600000000000019 ++:10EDF00000000C4440800088CC2600000000000089 ++:10EE000000000C4440800048CC26000000000000B8 ++:10EE100000000C44408000C8CC2600000000000028 ++:10EE200000000C4440800028CC26000000000000B8 ++:10EE300000000C44408000A8CC2600000000000028 ++:10EE400000000C4440800068CC2600000000000058 ++:10EE500000000C4440800018CC2600000000000098 ++:10EE600000000C4440800098CC2600000000000008 ++:10EE700000000C4440800058CC2600000000000038 ++:10EE800000000C44404000E8CC26000000000000D8 ++:10EE900000000C44402000A8CC2600000000000028 ++:10EEA00000000C4440200068CC2600000000000058 ++:10EEB00000000C4440A000E8CC2600000000000048 ++:10EEC00000000C4440E00030CC26000000000000B0 ++:10EED00000000C4440E000B0CC2600000000000020 ++:10EEE00000000C4440E00070CC2600000000000050 ++:10EEF00000000C4440E000F0CC26000000000000C0 ++:10EF000000000C4440E00008CC2600000000000097 ++:10EF100000000C4440E00088CC2600000000000007 ++:10EF200000000C4440E00048CC2600000000000037 ++:10EF300000000C4440E000C8CC26000000000000A7 ++:10EF400000000C4440E00028CC2600000000000037 ++:10EF500000000C4440E000A8CC26000000000000A7 ++:10EF600000000C4440E00068CC26000000000000D7 ++:10EF700000000C4440E000E8CC2600000000000047 ++:10EF800000000C44401000E8CC2600000000000007 ++:10EF900000000C4440900078CC26000000000000E7 ++:10EFA00000000C44405000E8CC26000000000000A7 ++:10EFB00000000C44403000E8CC26000000000000B7 ++:10EFC00000000C44407000A8CC26000000000000A7 ++:10EFD00000000C4440700068CC26000000000000D7 ++:10EFE00000000C4440F000E8CC26000000000000C7 ++:10EFF00000000C4440880040CC26000000000000C7 ++:10F0000000000C44408800E0CC2600000000000016 ++:10F0100000000C44408800D0CC2600000000000016 ++:10F0200000000C4440880030CC26000000000000A6 ++:10F0300000000C44408800B0CC2600000000000016 ++:10F0400000000C4440880008CC26000000000000AE ++:10F0500000000C4440880088CC260000000000001E ++:10F0600000000C4440880048CC260000000000004E ++:10F0700000000C44408800C8CC26000000000000BE ++:10F0800000000C4440880028CC260000000000004E ++:10F0900000000C44408800A8CC26000000000000BE ++:10F0A00000000C4440880068CC26000000000000EE ++:10F0B00000000C4440880018CC260000000000002E ++:10F0C00000000C4440880098CC260000000000009E ++:10F0D00000000C4440880058CC26000000000000CE ++:10F0E00000000C44408000400C8500800A060000AF ++:10F0F0008020000000000000000000000000000070 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F140000020000000000000000000000000008817 ++:10F1500000000000000000000000020000000000AD ++:10F16000002002000000000000000000000000007D ++:10F17000000000000010000000000010000000006F ++:10F18000001000000010000000000010000000004F ++:10F19000000000100010000000000010000000003F ++:10F1A000001000000010000000000010000000002F ++:10F1B000000082100000001000000000021000009B ++:10F1C000000000100000001000000200001000000D ++:10F1D00000000000001000100000000001100000FE ++:10F1E000000000108300001000000000001000006C ++:10F1F00000000000001000000000000000000000FF ++:10F2000000000000000000000000000000000000FE ++:10F2100000000000000000000000000000000000EE ++:10F2200000000000000000000000000000000000DE ++:10F2300000000000000000000000000000000000CE ++:10F24000000000000000000000002000000000009E ++:10F25000000000000000000000000000009000001E ++:10F26000000000000000020000000000000000009C ++:10F270000000000000900000FFFFFFFFFFFFFFFF06 ++:10F28000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10F29000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10F2A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10F2B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:10F2C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:10F2D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E ++:10F2E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:10F2F000FFFFFFFFFFFFFFFFFFFF00FC3BEC0C44A5 ++:10F30000408000600A06000080E30000000000006A ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000010000000BD ++:10F340000000000000000000000000000000008835 ++:10F35000000000000000000000000000000000C0ED ++:10F360000084000000000000000000000000000019 ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000A000A0000D ++:10F3C000A000000000000004080000000000000091 ++:10F3D000C000A00000000800000082000000000043 ++:10F3E000000008000000000000000800000200000B ++:10F3F000A00000000000000000000000000000006D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F4400000000000000000000000000000000000BC ++:10F450000000000000001000090000000000000093 ++:10F4600000900000000000000020000000000000EC ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000000000000000003C ++:10F4D0000000080000000000000000000000000024 ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000000000000000EB ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000100000000000000000000000006B ++:10F590000000000000000000000000000800000063 ++:10F5A0000000000000200000000000000000080033 ++:10F5B0000000A000000000000000000000000000AB ++:10F5C00000000000A000000000000000000000009B ++:10F5D000000000000000A000A0000800A000000043 ++:10F5E00000410000000000000800A00082000000B0 ++:10F5F0000000000008000000A0000000A0000000C3 ++:10F6000000000000000000000000000008000000F2 ++:10F61000000000000000FFFFFFFFFFFFFFFFFFFFF4 ++:10F62000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA ++:10F63000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA ++:10F64000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:10F65000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:10F66000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:10F67000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10F68000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A ++:10F69000FFFFFFFFFFFFFFFF0040C62F0C4440802D ++:10F6A00000700A0600000041000000000000000099 ++:10F6B000000000000000000000000000000000004A ++:10F6C000000000000000000000000000000000003A ++:10F6D000000000000000000000000000000000002A ++:10F6E000000000000000000000000000000000001A ++:10F6F000000000000000000000000000000000000A ++:10F7000000000000000000000000000000000000F9 ++:10F710000090000000000000004000000000000019 ++:10F7200000000000000000000000FFFFFFFFFFFFDF ++:10F73000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD9 ++:10F74000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9 ++:10F75000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9 ++:10F76000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9 ++:10F77000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 ++:10F78000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10F79000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:10F7A000FFFFFFFFFFFFFFFFFFFFFFFF00F03CD564 ++:10F7B0000C44408000E80A06000000410000000000 ++:10F7C0000000000000000000000000000000000039 ++:10F7D0000000000000000000000000000000000029 ++:10F7E0000000000000000000000000000000000019 ++:10F7F0000000000000000000000000000000000009 ++:10F8000000000000000000000000000000000000F8 ++:10F8100000000000000000000000000000000000E8 ++:10F8200000000000000200000000000000020000D4 ++:10F830000000000000000000000000000000FFFFCA ++:10F84000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8 ++:10F85000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8 ++:10F86000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 ++:10F87000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98 ++:10F88000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88 ++:10F89000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF78 ++:10F8A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:10F8B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 ++:10F8C00000584E4D0C44408000D80A06000060DB12 ++:10F8D0000000000000000000000000000000000028 ++:10F8E0000000000000000000000000000000000018 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000000000000000F7 ++:10F9100000000000000000000000000000000000E7 ++:10F9200000000000000000000000000000000000D7 ++:10F9300000000000000000000100000000000000C6 ++:10F9400001000000000000000000000000000000B6 ++:10F9500000000000000000000000000000000000A7 ++:10F960000000000000000000000000000000000097 ++:10F970000000000000000000000000000000000087 ++:10F980000000000000000000000000000000000077 ++:10F990000000000000000000000000000000000067 ++:10F9A0000000000000000000000000000000000057 ++:10F9B00000000000004000000000000000400000C7 ++:10F9C0000000000000000000000000000000000037 ++:10F9D0000000000000000000000000000000000027 ++:10F9E0000000000000000000000000000000000017 ++:10F9F0000000000000000000000000000000000007 ++:10FA000000000000000000000000000000000000F6 ++:10FA100000000000000000000000000000000000E6 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000010080000000000AE ++:10FA4000001008000000000000000000000000009E ++:10FA5000000000000000040000000000030000009F ++:10FA60000400040011000300040004001100110050 ++:10FA70000400110002000000000011000800020054 ++:10FA800088000400100000000200000004000000D4 ++:10FA90000000020010000000000000001100110032 ++:10FAA000040000000000030000000000000003004C ++:10FAB0000200020002000200090000002100030011 ++:10FAC00000004000100002000300110000000000D0 ++:10FAD000040004000200000000000000000000001C ++:10FAE0000000000001000000000000000000000015 ++:10FAF0000000000000000100000000000000000005 ++:10FB000000000400000001000000010000000000EF ++:10FB100000000000000001000000000000000000E4 ++:10FB200000000000000000000000000000000000D5 ++:10FB300000000100010001000100000000000000C1 ++:10FB400000000000010001000100000000000000B2 ++:10FB500000000000000000000000000000000000A5 ++:10FB600000000020000000209120000000020000A2 ++:10FB70000000000080008020100000000000000055 ++:10FB80000000000004000000000000000000000071 ++:10FB9000080000000000041000A000C000000000E9 ++:10FBA0000020004000C000000000032000200004EE ++:10FBB000000000218001800080A10020040280203C ++:10FBC0008089201000200020000804000040004030 ++:10FBD00000412088000000000000200000000041DB ++:10FBE00000000400008000000080109000000090E1 ++:10FBF000000000000000082020A103000000000019 ++:10FC00008220002000200000002000100000840955 ++:10FC10000000002000100000002000000000000094 ++:10FC200000000200009000100200021000A00090EE ++:10FC300000C082000084020440001008009001808F ++:10FC40000400101005200010000982C1012100A14C ++:10FC500000A082828320002000000000012000001C ++:10FC600000900010000000100000001000001000C4 ++:10FC70000000000000000000000000000084000000 ++:10FC8000000000000000801080848010000200103E ++:10FC90000010000080200000004000000010000064 ++:10FCA000002000900000000000A000900000001064 ++:10FCB0000000009000100000002000000002000082 ++:10FCC00000840084008800100088000000A000006C ++:10FCD00000C00090009000A0000000000040000460 ++:10FCE0000000000000000000000000000000000014 ++:10FCF00001000000000008000000000000000000FB ++:10FD000000000000000000000800200004000000C7 ++:10FD100000000000000004808200C000880008008D ++:10FD200000000000000000000000000000001000C3 ++:10FD3000000000000000000000000080C000008003 ++:10FD40009000000000000000108000000000000093 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000080800080018000080104000500080078 ++:10FD70000400050080008304800000200001801042 ++:10FD800000010004000020000004400003010310F3 ++:10FD9000041005001021102188010000100000004F ++:10FDA00080000000210485010204000421011000EC ++:10FDB00003002109850400840000100000C10540F3 ++:10FDC000100090C0000105010220102000C00200B8 ++:10FDD0002100041105000000050190020800000048 ++:10FDE00041840800200020042000000401000000DD ++:10FDF0000000A11100002041208002001080C020DE ++:10FE0000020010201080A0000100008001001010EE ++:10FE1000A000114100000882C0A00220840001005F ++:10FE2000A00020000000C0C1102000901080A0049D ++:10FE3000C0419000108840A18210004100000020C5 ++:10FE4000008088210400081082108280088500004C ++:10FE500000400000014084000000001008800021E4 ++:10FE6000C000C000000008000800092000100000C9 ++:10FE700000000000100010004002202010040010BC ++:10FE800000000040000020842000410020A011A0BC ++:10FE900008000400042010C04082020420041084E2 ++:10FEA0001000100403400000034040001084410093 ++:10FEB00002A02100080021A00320404102400000D0 ++:10FEC0002088414040C0034008400888102041215C ++:10FED0000000032021004100000000004100200438 ++:10FEE00000000010100000A00100010000800000D0 ++:10FEF0000000000000000000000001800100008000 ++:10FF0000000000000080000001000100000001006E ++:10FF1000000001000000018000000100018001805C ++:10FF200000000000008000800000000900000000C8 ++:10FF30000000000000000000000000000040000081 ++:10FF400000000100000001000080010001000080AD ++:10FF5000008400000000000000000000000000001D ++:10FF60000100000000000000001080051001412188 ++:10FF7000C101100080000000800100A0A0058005E4 ++:10FF8000201100840000000000000000200080001C ++:10FF90002010030020A00020008488C0A0A18400BD ++:10FFA00000010000088480011000000080000000B3 ++:10FFB0000000009110841040210003000084100014 ++:10FFC0008500881080104000004000218001000161 ++:10FFD0008084000110004140038490000000000074 ++:10FFE0000010020000000010000005200884A0207E ++:10FFF000C0A020208200400084000208000041824E ++:020000040002F8 ++:10000000208401048211840000004000C000090522 ++:1000100020001100824183000080820040004104E2 ++:100020002100100400000000024040000000040015 ++:10003000000000110040080082900241404100058C ++:100040000820020004050405C141008084A00420AA ++:1000500008200811101000000240000010000010DD ++:10006000000000100110000000000041108000009E ++:10007000800021000000000000800080008002025B ++:10008000000921110909030080004000110000004F ++:100090000000000000000002911100400008111152 ++:1000A000880989210904100500400002021000009F ++:1000B0000409401000100911000000004000000079 ++:1000C000021100C182021120000000008000000027 ++:1000D0008480800010001100080000000000100063 ++:1000E0000080000040000000000000000000000050 ++:1000F00000009000110000000002008402A000082F ++:1001000001011001010101018900C000830000000C ++:1001100000000000000000000001910188010001C2 ++:1001200009C11105C1C1010000010001000000006A ++:1001300000000400000104000000000008000000AE ++:1001400000000109A0850440000500880010400857 ++:10015000000088829090908200040000000000005F ++:100160000000C082A0C001A000020000000000004A ++:10017000000088019001A00283890300850005002A ++:1001800009908900C10009890901C110A00000106F ++:10019000A100000000000000010082019083C089DE ++:1001A00082C09001C10002201101880000A001015D ++:1001B0008201000000040184000001000000000032 ++:1001C00000000000040088101010C0082110000278 ++:1001D00009080800C0011000880082910000010099 ++:1001E0000002000000019000000411040000000063 ++:1001F000000000000008801180008989100890002C ++:10020000100083021000C10088088309110011004A ++:10021000400010020000001100000900400289099E ++:1002200009C091808002C10000008309000009001C ++:100230000520900300000480410041414009000076 ++:100240000000000000000504098082824040020096 ++:1002500011002010910000400000800080C00800C4 ++:1002600002000800210000020000000089000000D8 ++:10027000000000000000800000002100808000805D ++:1002800000000000000002100091098940080009E8 ++:1002900004000009808380000000020000001100BB ++:1002A000000000C08988020220910940C0830241F9 ++:1002B0000041110908090000104005050041032014 ++:1002C00000000000000000804108800810C00440C9 ++:1002D000000910089091009000910080800080C07B ++:1002E0000000000800C000800080800000000000C6 ++:1002F0000000000000000000C000008201008882B1 ++:100300000008000004C0A0000183009101850904D9 ++:100310000004000200C10883820000000100000008 ++:10032000010000C000A1898301C189890503050975 ++:100330000040008800000100000001090089000061 ++:100340000109C0400008000800880002040303857A ++:100350000083008200081010A0880004C0C09088AC ++:10036000888300040084001104C00008C0040888C9 ++:10037000A090000000000000A00090018810A000E4 ++:10038000C0880888080100014000019001030001B5 ++:1003900000C0008900010001000000880088000002 ++:1003A000000091018989A101A18884001009000041 ++:1003B000008800910184000001C000000008018451 ++:1003C000000001004008084082000800820110057A ++:1003D00008000390C10004081000C0828201880058 ++:1003E0000400100800080008000000008384850451 ++:1003F000400041000000000100000000801180006A ++:10040000800000800009000400080000031004912F ++:100410000021080000400008000200000000000069 ++:100420000000000091118920A1404080804080118F ++:100430000004008004824002044110800000028019 ++:100440004008090440000000008000008000000314 ++:1004500089C0844102000300020082008280801172 ++:100460008000000000800000000000000000888084 ++:1004700010801100100000000040000200004188C0 ++:100480000013C200000000600013C2000000000062 ++:100490000000C200000000000013C2000A00004279 ++:1004A0000000C200420012420013C200000012828B ++:1004B0000013C200000082000013C204008100008B ++:1004C00000000013C200008800000013C2000000FA ++:1004D00000000013C200820000410013C20000416E ++:1004E00000000013C200000006000013000000001E ++:1004F00000820013C200000006000013C2000000CA ++:1005000000000000000000000000000000000000EB ++:10051000FF7E3CFF0000100800000000C342000006 ++:10052000000000000000000008000000FF0000FFC5 ++:10053000000000003C33666A4444004405A000000B ++:1005400000006E086E083C1E3C1E0000000000000B ++:1005500000008E0E8E0EFF2FFF2400100020FC0CDA ++:100560000C0C000000007E7E4242000000006F6024 ++:100570006F603000F000000000000000000000008C ++:10058000000000000000000000000000000000006B ++:100590000000FF7E3CFF0000180000000000C34286 ++:1005A000FF00000000000000000000000000FF004D ++:1005B00000FF000000003C3C66668888008805A0BB ++:1005C00005A00000FF906F003C003CFF0000000011 ++:1005D00000000000860686060F2F002400000000A1 ++:1005E000FC0C0C0C000000003C3C00000000000073 ++:1005F0000F000F003000F0000000000000000000BD ++:1006000000000000FFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10061000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA ++:10062000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA ++:10063000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:10064000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:10065000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:10066000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10067000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A ++:10068000FFFFFFFFFFFF00FC8B5C0C4440400018A5 ++:100690000A06000070DF00000000FFFF00000000FD ++:1006A000000000000600040B000000000000000035 ++:1006B00000003030303000000000FFFF0000FFFF7E ++:1006C000FFFB8040102000FF40BF6666F0F0000096 ++:1006D000004400600090000024F4FFFFE0FFE3FF0F ++:1006E00000000000000000003938393E993C783C99 ++:1006F00000000000003CC0FC000000000000000002 ++:1007000000000000300030FF00000000FFFF00008C ++:1007100000000000FFFFFFFF00000000FFFF0000DF ++:100720000000000004000900000F00001800140081 ++:10073000000000003030307600000000FFFF0000B5 ++:10074000FFFFFFFF0102080400FF00FF96960F0F56 ++:100750000000000000060009000024F400F0200062 ++:10076000230000000000000000003038303E003C54 ++:10077000783C00000000003CC0FC000000000000CD ++:10078000000000000000300030FF00000000FFFF0C ++:1007900000000000000066666666A00650B4A10076 ++:1007A0000000008600C508A000100586007000B09B ++:1007B0000010008600E100B90000A0005014A00065 ++:1007C0000000000670B401080000008600F401B2C9 ++:1007D000001000060060A1B000050000008600F0D7 ++:1007E00008B00000A086007100900000008600D1D3 ++:1007F00008980000088600E508B00080000000812D ++:10080000080800050086006001B0048001820274BF ++:1008100000B000000086006009B00400FF00FF0087 ++:10082000F5F5A5A5BE000000C33CC33C00000000D8 ++:10083000407C427E00000000FCFCAFA000000000F5 ++:10084000000000007F80FF00FF0FF00FAA5500009E ++:100850004400004400000000303030300000000050 ++:1008600000000303FFFFFF3000300454AEFEFEBE65 ++:10087000FC3C5F5FD7FFFCC03C0000300F3FFE0434 ++:100880007F7FEBFF0D8F000000000C0C00FF550078 ++:10089000CCCC5514FFFC0000000000000000DF205D ++:1008A000FF000A0AA5A514000000C33CC33C0000D9 ++:1008B0000000003C023E000000000C0CAFA0000055 ++:1008C000000000000000FF00FF0000F0F00FAA553C ++:1008D0000000880000880000000030303030000048 ++:1008E000000000000303FFFFFF3000300404AEAE41 ++:1008F000EAAAC0000A0A0028FCC03C0000300F3FF2 ++:10090000FE04202000140D8F000000000C0C00FFDE ++:10091000FF0000000000FFFC0000000000000000DD ++:1009200000000000FBFF393CFFC0C0C030FF30308A ++:1009300000000000707A757F0000000000000000D9 ++:10094000000000000000000000000000FBFF393C38 ++:10095000A00000A000009606000000000000414139 ++:100960000000000000000000000000000000000087 ++:100970000000FFFF00000CFF5D5DFFF00F001400A2 ++:1009800014FFF0B2EBFFDFDF027F00000000000089 ++:100990000000000000820F0F0000000000000000B7 ++:1009A0000000000000000400393CFF00000030306F ++:1009B000303000000000202A252F00000000C0C0B9 ++:1009C0000000000000000000000000000000040023 ++:1009D000393CAA0000AA9606000000000000555508 ++:1009E0004141000000000000000000000000000085 ++:1009F00000000000F2C232020C0C5D5DF0F000005D ++:100A0000140014FFF0B228000808027F0000000064 ++:100A100000000000001000820F0F00000000000026 ++:100A200000000000000004000000040000000400BA ++:100A30000000040002000400020000001100200079 ++:100A4000200011010200000002001100110000004E ++:100A50000900040000000000000082000000020005 ++:100A60000000040000000000040003000400000077 ++:100A70004000A000A00110001000000000000200D3 ++:100A800004000008110040001000020002000200F3 ++:100A90000400030000000400040011000200040030 ++:100AA00004000090040000000000000000000000AE ++:100AB00088000000000000000000000004000000AA ++:100AC0000100010000200100000001000000000002 ++:100AD000000090000000040000000200200004005C ++:100AE00000000000004000400000910004000000F1 ++:100AF00000000100050005400100010000000000A9 ++:100B000001000000000000000100010001000400DD ++:100B100001000000000000000000000000000100D3 ++:100B200000000000000000000000000000000000C5 ++:100B30000000000000400000000000000000000174 ++:100B40000000000004000000000008000000800019 ++:100B500000C0000100008001000000000000030050 ++:100B6000100000000000200000C000200000004035 ++:100B70000000008800002020800100020210110007 ++:100B800000000002A14000A0002100A0002000847D ++:100B9000000000014004219080A1008800080000AE ++:100BA000004100A00000000411000000000000103F ++:100BB00000100000000000800000020000000000A3 ++:100BC00000080400002100100000000004210010B3 ++:100BD0002010001000080000040800000841001068 ++:100BE00082000110000000100900000000800010C9 ++:100BF000904000400410000001001020008090216F ++:100C00000021001000A104000010000400410010A9 ++:100C10000021000000100190A0100202000000A0BE ++:100C2000002100840009000090A0001000000010C6 ++:100C30000084000000100010000000100000000000 ++:100C40000010000000000000000000000002000092 ++:100C500000400020004080A08000800000000003D1 ++:100C60000000001000000090000000C0000000889C ++:100C70000090800000000020000000000011002013 ++:100C8000000000A000880002404102410010000066 ++:100C9000008400A00083000300A000024002008442 ++:100CA000008400110000000000900000008400009B ++:100CB0000000C01004000800001000008802C005F9 ++:100CC00088400000000000000200C0000041000059 ++:100CD0000000040000800000040004000400000084 ++:100CE000C00402008402900000118400840000000F ++:100CF000040008410400A000824100088200842012 ++:100D000000C10005A0400009889101200120A00039 ++:100D1000A00000051000844084028200100011022F ++:100D200000050005000400000000000000030000B2 ++:100D300010000088A1080008030008A01041020567 ++:100D40001000008241A00584209010001040204037 ++:100D500041A0090103000020049000A00400C1008C ++:100D6000030202C0890008080585090410900200EA ++:100D700000000020850985C0058205820000110061 ++:100D800010A110C1000102000201C10080A0840175 ++:100D9000A101000882020840C140400102A0419127 ++:100DA00005000000410002002000004000048420F3 ++:100DB00085400000000020900080C000C000008836 ++:100DC00085848209000090000000010000000000FE ++:100DD00001808821000808091080A100C0050103D6 ++:100DE000040384808400202100A1C00884800121A4 ++:100DF000080000009080048404100000C0008400FB ++:100E00008205820201020040011101022041040911 ++:100E100021404004C090038900891089C14000002E ++:100E2000840200210800084101009109101000808F ++:100E300021A10410040041000484020004001000F9 ++:100E40004100000005000000800040004000040058 ++:100E500041202100000000000010000080008200FE ++:100E6000000084000000020000012103088220002D ++:100E70000300090000000800090008100800200411 ++:100E800003042089089003C0214180A110A1118290 ++:100E90000400A100008400A00382411003A0A1046B ++:100EA00000042002000100840000211180414188DB ++:100EB000410000880088000000000110010090003F ++:100EC0000100100084000000040004000100001074 ++:100ED00001219080080000000003000000000400D1 ++:100EE0000400000005210000000084040020C00070 ++:100EF0008400C0080021000011050000A10989003C ++:100F0000000000000020000002110202040804207A ++:100F10008200010904088205000510051000000088 ++:100F2000208000800180C0040000000000400420F8 ++:100F3000000000000000000011008000A0008400FC ++:100F40001140004000400800110002100000022083 ++:100F50000084418410A000A00000801000400084A4 ++:100F60000491040004000900100020101000020584 ++:100F7000218410821082418400000810880041847E ++:100F8000A1401090021010A0410002820440001005 ++:100F900000842040C0040003108382010008200563 ++:100FA0000200009040118040000400008085808491 ++:100FB000418800C0001100822001000010002111B2 ++:100FC0002100020082400040A10090008300A000A8 ++:100FD000018000000005080010000040081100001A ++:100FE0000005030811400111881000001105C00020 ++:100FF000008400218400C040C009000000000921D5 ++:101000000000040302008203C0102005900005C107 ++:10101000A02000049110218390848802030800A17D ++:1010200088080000000001022090009000001008D5 ++:10103000200000000000000400050004C000800043 ++:1010400089000300020080000500090000838884F5 ++:101050000391008988088441044041400000808059 ++:1010600000000000001140108000004010008000CF ++:10107000C000110010400000001111000000A08508 ++:101080008008030005100309091020411009050814 ++:1010900085C0A080400411038009100804040040AA ++:1010A000400500C1000911830009110202822000DD ++:1010B0002000110040001010C00905081141050072 ++:1010C000820011000100010084000000900008A0CF ++:1010D0000409900300108900C00090010001008203 ++:1010E000C084000200C000000001C00000004100F8 ++:1010F000C0008300000001010000000100000000AA ++:10110000888390119182884001000801010100014B ++:1011100000110210200801000509104190830040D1 ++:1011200000A000408809900803C188910089004010 ++:1011300088000100000000001000C0010000000154 ++:10114000010001000182010005000000204000892B ++:101150008908020210C1C1022082C184080209006C ++:101160008800090002A0080400200000000200001E ++:101170000400020101000000000000200100000046 ++:101180000000A00182094188019008000201098342 ++:10119000880000A1C000C102A0C0C00009404003F7 ++:1011A000850140000500C00088000800C18241910F ++:1011B0008301050041004100C100880004000300D4 ++:1011C00089002000200040000905A00402000280E0 ++:1011D000058590918080808210C10580A00080915B ++:1011E000C00505094000090085C100000800008015 ++:1011F00008008400910302001105000000000509A9 ++:1012000000000000092008C0858040800300C02144 ++:101210000885200441108400050011890500C18063 ++:101220000511830909052000C00011008500A100F7 ++:1012300040C0830511000800020089000900110068 ++:101240000200090200100090034000A000400002CC ++:10125000200200A0058003800380838000092141D3 ++:1012600041C0408000008000000000000800200015 ++:101270000000808000090090038980890008001028 ++:101280000002000400000409004080088088100467 ++:10129000041103888088080402900082000302057C ++:1012A000044000091103004000400084000505854A ++:1012B000004100099103000300031009000311110C ++:1012C000004004090390008300A100C12003001125 ++:1012D00000C101C0008500028510088410A000A094 ++:1012E0000182008511080000400004000800000091 ++:1012F000000000001088008200050084888800003B ++:1013000000000001000000009003840590828883A3 ++:1013100000A1004000848240010800400085029145 ++:1013200000A000A1008389C10040004000A0048803 ++:10133000004000010009090100C0004001C1020194 ++:1013400000C000040089000800000009000100003E ++:1013500082009000840100008503850108C002829C ++:1013600000010004010001C1A0A0080104001082D6 ++:10137000008800010001000000040041000000009E ++:101380000008004000000100000082A18820020047 ++:101390004140000300040000000285C0A14041C09C ++:1013A000854001C101C1010000C00240408400002D ++:1013B000C10001880183000000400090008400010A ++:1013C0000000000100100001000400000090001067 ++:1013D00000008000000080050000828209100940A2 ++:1013E000C1840020410540112088808480200004B1 ++:1013F0008080090000100421020000000004004168 ++:10140000000008800584040040000000C111A0898C ++:1014100009000500091004800500008088001008FC ++:10142000A003C1890383219108041100C00040007A ++:101430000300C000038904910304090000000008B0 ++:1014400000090000004000200003008082500013CB ++:10145000C2000A5000500000C2000000000000134B ++:101460000000114100000013C20041000081001380 ++:10147000C2000050810000130000000082410013F0 ++:10148000C200218100000000C20000000000000036 ++:101490000013C200008481500013C2008242000089 ++:1014A00000130000000000000013C20082000000D2 ++:1014B00000000000000000000000C2004200128492 ++:1014C0000013D000000000840013C2000088000058 ++:1014D00000000000812400000000000088443C3C23 ++:1014E00000FF000000003DFF3DFFF5FDF5FD0000A1 ++:1014F0000000000000003F3F0F0F00000000000050 ++:1015000000000CFF5DFF0FFF3535CFCF417D0000A0 ++:101510003CFF3FFF0CFF5DFF000F555F55FF0F3C89 ++:10152000003C033F00040000555FFC3C4D4D00FFB4 ++:10153000000F3C0F00300F3FFDFD10BF5555033F1E ++:1015400000000000FFFF000000000000407FC0FF1F ++:10155000000000008124000000000000884400001A ++:101560000F0F5555000000003D053D05053D053DAB ++:1015700000000000000000003F3F0F0F00000000CF ++:10158000000000000C0C5D5D00F035350C0C417D59 ++:1015900000003C3C3F3F0C0C5D5D000F555F55006B ++:1015A0000F3C003C033F0000040055500C3C5555D7 ++:1015B000033F000F3C0F00300F3F080810BF4D4D98 ++:1015C00000FF00000000BABA450000000000003F24 ++:1015D00080BF00000000240081000000000030C037 ++:1015E0000C03A0A0B4B4BEBE1414BEFCAAF0FFFF4E ++:1015F000E8E800000000000000803CFF3C00FAFA30 ++:10160000505000000000FFFFBA300F0FF0F055AA55 ++:1016100055AA0000FF003C00FFBCFFA0FFFF300008 ++:10162000F0F03C00FF3C003CFBF8EB28FF0CABABC0 ++:10163000F0F0BE82FC0CF000F03CF000FCC0B2B256 ++:10164000F3F0AAEB0000000043C38000FF00FF009E ++:10165000FFFF0000000000000024008100000000E7 ++:1016600000000000F5A0A0A0AAAA0000BEFCAAF0FD ++:10167000E8E8E8E800000000000000003C003C0052 ++:10168000AAAA000000000000BA30BA300F0FF0F034 ++:1016900055AA55AA0000FF000000FFBCFFA03000C3 ++:1016A0003000F0F03C00FF000000F8F82828F300BC ++:1016B000A8A8FCC0AAAAFC0CF000F03CF000FF00B7 ++:1016C000AAAA30F0AA2800000000C3C30000FCC092 ++:1016D000BE82FCFA0C0A008600F4A1B00005008668 ++:1016E000006400B08005018602E100B000000086C1 ++:1016F00000E108B000000086006408308000008629 ++:1017000000E001900000008650F4A198000501005F ++:101710000010080000000000A00050910000000030 ++:1017200000860C74A9F00485008602E100B90080EF ++:10173000088604F108B200100086006000B800803E ++:101740000886047008B200100086007401B9040015 ++:1017500000860074008000000000000090000090EF ++:10176000AAFF550000FF05FF3CFC00C000FF00FF82 ++:1017700000000000404F404FFFFFFFFFFFFF000051 ++:1017800000000000FFFF0000000000000008FFF75D ++:1017900000000000000000000000FB10FDFDFF3F06 ++:1017A0004D550000000000000000000000004F0F39 ++:1017B0004F4F0000000002003E3CFF280028003090 ++:1017C0000F3F0000000041414141000000000C5C5F ++:1017D0000C5C000000007CFC3C3C000000000600AB ++:1017E0000006AAFFA5F000C300C3BE3C82000101B1 ++:1017F000292900000000000F303FFFFFFFBF00005D ++:10180000000000000000FFFF0000000000000000DA ++:10181000FFFF00000000000000000000FB108080BF ++:1018200000034D55000000000000400000000001D2 ++:101830004F4F4F4F0000000000003C3CFF280028A5 ++:1018400000300F3F00000000005500550000000070 ++:101850000C5C0C5C000000007C3C3C3C0000000088 ++:1018600000000000000000003CFF3CFFFDAD5D0DEE ++:101870000C0CFCFC000000000CFC0CFC0014003004 ++:101880000000010000000000000000000000000057 ++:101890000C0C0C0C00000000000000000000F4E044 ++:1018A000FFD7D7FF0E4F00000000FFFFFFFFFFFF35 ++:1018B000FFF000005005FF3000300C14FFFFFF3038 ++:1018C00000300C000CFFFF3000307BE29966000016 ++:1018D0000000FC00FCFF000000003C3C3C3C000021 ++:1018E000000000000000000000003CFF3CFFF8A8E2 ++:1018F000580805F505F50000000050505F5F000036 ++:1019000000300000000000000000000000000000A7 ++:1019100000000C0C0C0C0000000000000000000097 ++:10192000F4E0280000280E4F000000007FFFFFFFBA ++:10193000FFFFFFF000005005FF3000300014FFFFF4 ++:10194000FF3000300C000CFFFF3000301D7B66992B ++:1019500000000000FC00FCFF000000007C7C3CFC60 ++:101960000400210002002000040000000300030026 ++:101970000000000004000000030002000400030057 ++:101980004100080000004100210002208200A00068 ++:10199000000008002002034000080400042000C0EA ++:1019A00000000000040008001108040004000420E6 ++:1019B0001000004088000420800002000400200085 ++:1019C000111121A00400000004000400080002001E ++:1019D00084000200001020000020042004400400C5 ++:1019E00011000000000000000200000000000000E4 ++:1019F000820000000400000000000400000000005D ++:101A0000000084000800000004000000208008009E ++:101A1000030000000000C08000808200A0008280DF ++:101A200000000040000010000100900000000000D5 ++:101A30000000010002001100008002000000000010 ++:101A40000000001000000000000000008200010003 ++:101A50002000400000000200000000000000000024 ++:101A600090000000000000000020200000000000A6 ++:101A70000000000000000004000200000000004020 ++:101A8000040402000000000000000000000000014B ++:101A90000000000000000001000000000000000045 ++:101AA0000001000900C00020008800208000002004 ++:101AB00000880000004000000001000080000020BD ++:101AC000840000000000030000008000A1000088E6 ++:101AD00000C00488020000A00000000000400000D8 ++:101AE0000000000000108200000000000400000060 ++:101AF0000000000004100000009000A00020000082 ++:101B000000800490001000000000000000000000B1 ++:101B1000000802000021000000200000000000007A ++:101B20000009000400080000000000000000101080 ++:101B300000000020000000200041000200211009E8 ++:101B400000091108000800030008000840081010F0 ++:101B50000020902101000003000020400209002124 ++:101B600002000011000000410000000021C08000C0 ++:101B700000000000000800008001880080001000C4 ++:101B80000301000005410009000000000000000002 ++:101B90000084001000010010001000000810001068 ++:101BA0000510000200820504000000104120209072 ++:101BB000000020820010008400408000100888840B ++:101BC0000010880085C010A1840041A005A08308F2 ++:101BD000110841C0001010C041400004000000A0E6 ++:101BE000008411400008008480A002000000000072 ++:101BF000100300000000C0050005020811000200EB ++:101C000011210008C0101088C0C090000000000022 ++:101C1000C0008220880200021008A021001091411B ++:101C200020001000A0101000108000000020820092 ++:101C30000200C004A0098200840910084041A010DD ++:101C40002120100408084041841011218400000262 ++:101C50000821100082100000821100000000200006 ++:101C600002050000820084080000200400000090AB ++:101C700003400000090041004100C10080008000D5 ++:101C80000500100000008001090010001000110084 ++:101C900010000500000000000000040000820400A5 ++:101CA00000004100000009880200118400000200C9 ++:101CB000020083000500110089008000400002003E ++:101CC00020004100000088014100000120000800C0 ++:101CD00000901040000000001082100482000240BA ++:101CE000090041400200084083408488020000004F ++:101CF00002001000A003000308000800040408000C ++:101D0000400000208804000310100000A021000003 ++:101D1000820000008400000000000204A1000021F5 ++:101D2000000000080021900500218800002100002B ++:101D3000082108084000C003082108052003A1006D ++:101D400009400120080802004002002000409141A3 ++:101D50000003A00904030809040408040089100012 ++:101D6000C0000000002185009000084120410000D3 ++:101D70000000000003000000000002100900400005 ++:101D8000A10040018805800100002182C02180035C ++:101D9000080040A008000884000100A1030800001A ++:101DA00000000000008200020000008420004100CA ++:101DB00000001000000220880000051041004108CA ++:101DC00005000885400840C0000400840810102069 ++:101DD00005894002030204902000410204C0000073 ++:101DE000008409821004108200A0008841100000C5 ++:101DF0001082000082000011001100210000840008 ++:101E00001121042101200504024000008200041079 ++:101E10000820002110000200100010100002000035 ++:101E2000000000400805C005404020048400002157 ++:101E3000101100000200200402102004080300001A ++:101E40000811200901082010830300028821834023 ++:101E5000018984400000C000C000840288000000A6 ++:101E60001000A010000000000000824002040009E1 ++:101E7000A004030000000000090011010900000097 ++:101E800010000088022182014000000880109001AB ++:101E9000000008041184050041002110094003845A ++:101EA000109000881100212010C0020800080000D6 ++:101EB000001005100000090041100910102009C091 ++:101EC000020002C10410802084C002041008109097 ++:101ED000900400890388004000100008004000883A ++:101EE0000090008408200000098480C1000800825E ++:101EF000008400111082000000080003821000001E ++:101F000082000011C000828204408320209140A002 ++:101F100040200209208088000000000000410041AC ++:101F200000000800820400050005082100000005EB ++:101F300084038441080000000408201004000840C5 ++:101F4000A00088030020080304080340A11090416A ++:101F50000100020900048405820000002000041131 ++:101F600000400200A0000010000000410802200410 ++:101F700000000000202000108080830000C141C1CB ++:101F800000000380804183A0088088000002C11106 ++:101F90000380C08000C108000000830000C183C12D ++:101FA00080000380801021C10380830000A00341D2 ++:101FB0000500800080A103000080000083000088ED ++:101FC00083C18000038000C183A02000800000C086 ++:101FD0004008C0808300800808000000830000885B ++:101FE00083C1800008000021832005000880008351 ++:101FF0000321900083808002030082048384A0C1B7 ++:1020000011C10082010882A183C10504051000836B ++:1020100041000108821008A101000082838290C162 ++:1020200083C1028201C0200302C001044182000377 ++:1020300001010082C00882A10100000000828382A9 ++:1020400008C183C140820110880583C101C0C0401E ++:102050000082910021A0838410910100008283827C ++:1020600008C183C10282019082912184008291C0C3 ++:102070000083010083828310208301000400088212 ++:10208000000191C0828283820083C010411082834C ++:1020900000830900888340830011012182000482AB ++:1020A000008303828282A1820082C1210283828214 ++:1020B0000083C100838311C000830083000082007D ++:1020C000C08200830282828283820083C190038364 ++:1020D000A12000A103002102C005008301048200A9 ++:1020E00088820083028282824182008285919004EC ++:1020F000C0C1000902018320C1830083010980005F ++:102100008080004141800080028000A1890982898D ++:1021100041C10083884141A11020002140400000BE ++:1021200000800083888000800280008390204183AB ++:1021300009820083C100022082C100904003000098 ++:1021400000008089008388C00080028000828300B4 ++:10215000210390030003A00202408390008341A06A ++:10216000000000800083C0800080028000800303A4 ++:10217000048588830083830302098490008341409F ++:1021800000050000C1C183C10000000083C103C17C ++:10219000002000008208800000020000A141000031 ++:1021A0000011008080C1A0C100000080030309C1AC ++:1021B000004000008302000000820080C102000095 ++:1021C000000000030000830240410000000083097A ++:1021D00002C100C0000083828000001100000002E4 ++:1021E00080000011418088C1C041000000008321AF ++:1021F00089C10011000083830000001100008302E8 ++:10220000000000000004C1C111C10000008483412E ++:1022100000C100C100100882820000A0008208C135 ++:102220004000000000C082C182C1000000084104DB ++:1022300000C100830082838300000041001082837C ++:10224000A000000000000082838300910000008253 ++:10225000839000C100050020A1C1400000200020A3 ++:1022600040912000000000C083C1829100000082E4 ++:10227000834110C10082008283022000002000847C ++:10228000838300008305018283A102C083820183CE ++:102290000283C0830408011001820000908900823B ++:1022A0000101C010100500822141908283A00083AB ++:1022B000A08220888383010101830000C0C1011135 ++:1022C000010088C0000002830082219008838300FF ++:1022D0000183058210030508010900820000908235 ++:1022E00001040001C021108901829189088283C004 ++:1022F00000838382C0038300010100830000828287 ++:102300000120010110030283418041A1008302806A ++:102310000483858380830911418441900000050373 ++:1023200020822102008891032080410200A1020046 ++:1023300009830510001102A020030283000085C15B ++:102340000441021100840000838340800240008821 ++:1023500002002083C0838088908202204185000093 ++:10236000088904C00821800291030280410200A074 ++:10237000020011834088008802404102038300006C ++:1023800004C00440020880C1000000000000125098 ++:1023900081600013C200124241840013C2008242D5 ++:1023A00000000000000012000000000000001242C7 ++:1023B00041820013C20012428150000660001242A6 ++:1023C00000000000000000420000000000000000CB ++:1023D000124241480004D000124221410013C200C1 ++:1023E0004242000000000000124200000000000015 ++:1023F000124221480042D000124221480042D0003F ++:1024000082420000000000001242FFFFFFFFFFFFBA ++:10241000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC ++:10242000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC ++:10243000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC ++:10244000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C ++:10245000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C ++:10246000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C ++:10247000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:10248000FFFFFFFFFFFFFFFFFFFFFFFF00300283A3 ++:102490000C44402000E80A0600006059AE5E0100CE ++:1024A000000000000000000000000000000000002C ++:1024B000000000000000000000807A75AE5E0100A0 ++:1024C000000000000000000000000000000000000C ++:1024D000000000000000000000007B750000AEDE80 ++:1024E00000000000000000000000000000000000EC ++:1024F0000000000000000000000000807A75AEDEE1 ++:1025000000000000000000000000000000000000CB ++:102510000000000000000000000000007B751E7B32 ++:10252000C002000000000000408C07000000000016 ++:10253000000030020000000000004003DE781E7B37 ++:10254000C002000000000000408C070000000000F6 ++:102550000000300200000000000040031E78000070 ++:102560000678C000000000000000008C070000009A ++:102570000000000030020000000000004003DE7890 ++:102580000678C000000000000000008C070000007A ++:1025900000000000300000000000000000031E608A ++:1025A000910000009100040004000400210091004B ++:1025B00004012000840020000000000020002020F2 ++:1025C000200008000000200490009100110020006D ++:1025D000044020000000020000000200000004008F ++:1025E00000000000040802000904040000000500C7 ++:1025F000020000012100A100840000000000111071 ++:10260000110000000400020021000200200021004F ++:1026100000A0020004081100040080884100A00806 ++:102620000008020000000800000000000000200078 ++:102630002000004001002000010000000000010017 ++:102640000180010001000400910021001000000041 ++:102650009100908082000000000000000100000056 ++:10266000200000000000900000000080000000003A ++:102670000000000000040000100002000000000044 ++:10268000000000000800020001000000000000003F ++:10269000000000000000008000000000200000009A ++:1026A0000200000000000004800080010000000023 ++:1026B000800000008000000000A1030180000000F5 ++:1026C00000000000040000000000110000000000F5 ++:1026D00000000484000080008000200000C003008F ++:1026E0000020000000C000000000002000000000EA ++:1026F0000000000080200000002091000000000188 ++:1027000000000001000800110008000040C000089F ++:102710000000001040C0000800004001004084009C ++:10272000001000110001004100C10800400200003B ++:1027300000410800041002000010000804082000F6 ++:1027400000000000001000000000820002030000F2 ++:102750000000820004200000202020002110000042 ++:1027600000000008002000000000041100800000AC ++:1027700000080000000004880411009002110010FD ++:102780000010000002400400C04082A1002100109F ++:102790000421001000110010009000080140A088E2 ++:1027A00021000008000202080001008400008000EF ++:1027B00000000300000000A08000008400000082F0 ++:1027C00000001000000000000584001000820020BE ++:1027D00000001104000000000010408805200000E7 ++:1027E00000A00000021000A00000008921100010CD ++:1027F0000941000021080000020840881000020280 ++:102800000000004000A0084000028040000280104C ++:1028100000400000004000840040002009400010FB ++:1028200000004008020009C0000800080000100075 ++:1028300008008400900020000000200040000000FC ++:10284000A0000004820000201000000000028200AE ++:102850000884A00020800000A0002000A0008400C8 ++:102860000000844000000000004000000240000022 ++:102870000000908800008490041000900000000088 ++:10288000000000208284400800830000108800843B ++:10289000088308804000009000000090002188C15B ++:1028A00002030010001001000800000811002002BF ++:1028B000100082000200000004000000040000007C ++:1028C00008000300100020844100040010002010C4 ++:1028D000050003008020032084014121200003889B ++:1028E0000300020008002100210103000000040091 ++:1028F000200005008804029000080200110000007A ++:1029000008090201020008901001050800000809EA ++:102910002000090400A000000000080002001108C7 ++:1029200009010002110304000900840041000000B5 ++:102930008380000005100100842011200020090080 ++:10294000004001000800C00001000000010000007C ++:102950000180C000A00004208289212010A08300F3 ++:10296000C000000810050041001100209000000088 ++:1029700000090009A0000400C01100001009004077 ++:102980008800882021400100030000088421A00461 ++:1029900002C00041C08000009000084100001021EA ++:1029A000C08008020880088200400000081020084B ++:1029B0008001000010002000410000888082000497 ++:1029C000000004014110040821020000000421005D ++:1029D0001000000110004100020004A003004102A9 ++:1029E00004901000088400002110034100200241DF ++:1029F000000080000090C088009100821140100209 ++:102A000000880010058802100002088800000200FB ++:102A10000088024003C041400008008809002120CE ++:102A20002090090220081008020400C003001000D2 ++:102A300003001008000001000103904000000204A0 ++:102A400000802011050820C089C100110400001178 ++:102A500040000000000800001000C01010401000EE ++:102A60000000840004000000000000400008002175 ++:102A700001020000100000000800000484104080E3 ++:102A800090080004C0080000018820804100001068 ++:102A90000300004001820008C08088210008000077 ++:102AA00040030005008088A1008000C0880840081D ++:102AB00000088800104002040000400100000520CA ++:102AC000000020820001110004840210020800901E ++:102AD0002110008811008040210108912088020007 ++:102AE0002100101002080410411083888008210181 ++:102AF000100088000000101021000502001041C0E5 ++:102B000010081000200000A011848284008420108E ++:102B100000848040828205A0804004101020009034 ++:102B2000002041080084000840820902A102110827 ++:102B3000000804101010010005800000C110000002 ++:102B40000000000000000002000089008500000075 ++:102B500000000000000000044000100402400009D2 ++:102B600088418800030001000000100020000400DC ++:102B70000020900004000000000808009091100060 ++:102B8000A040A040A000101100008211031008090D ++:102B90008280080002910210000020801091002124 ++:102BA000A04100401000000082C001000089208583 ++:102BB00000000041C0A0A008008308890320004154 ++:102BC0000880000000004100108010008300100009 ++:102BD00021C04180009003A000000000110000000F ++:102BE00085A000A109004000A08804A04182A1089E ++:102BF000C0038020040504020000C01000A11009D9 ++:102C000008C01005080220100985808508908008FA ++:102C10000004200500842084101103C11040020923 ++:102C20000884000005001000000091838204000069 ++:102C3000000940800900000041802083858500054F ++:102C400000910082000200040020038291A0200471 ++:102C500003A00105000200C00141900040000000F7 ++:102C60000400118800A0820000C01008888500853B ++:102C70008421052182A0A1830088000040010884EE ++:102C800088020105009108210040002140830011C5 ++:102C9000C00500000205888589400140898321899B ++:102CA00001020011C002C008008208C0910910058D ++:102CB00000C000910182002000A000080300110064 ++:102CC000118402020400000021100100050220000E ++:102CD0002182020000000084000100400000000189 ++:102CE000000001000500820089040909010040017B ++:102CF000102011011188880008A0A0080000040815 ++:102D0000A020090482A0010102909103918289010F ++:102D1000C0100911090201008302A1108202020100 ++:102D2000C000C102A08308038200100410A0A1000B ++:102D3000C084A10085C00800098221058390A041BC ++:102D400082009180A11184004100850020009180C3 ++:102D500082100800A10521050080050321800900DB ++:102D600011041000081020044003850090A00811F1 ++:102D700009401100A041A1080400C0800009000022 ++:102D8000A0001000050204210803904005200880DF ++:102D90001002C00005829008100240800580C080AB ++:102DA00084029102850004108003000980008000E5 ++:102DB00091044000900083898411028085114100B4 ++:102DC0000380000008A111030008004080100011DA ++:102DD00000C08540C19080C0212100100020030068 ++:102DE00080000080040000809009808520C08382DC ++:102DF00010210805A088210509800283A18405C04F ++:102E0000000082828090C1A10388898900028885A0 ++:102E10000091048380021183902040910020A1053D ++:102E20008404A0C0411004109008000080000080BD ++:102E3000000000400080809082030010A04020022B ++:102E400000040110A082888441880001A0010801CB ++:102E5000000020020820048540020000A001820139 ++:102E6000910020880010004090822104080911A0E0 ++:102E700089090320C1850984050300208202108589 ++:102E8000C1100000820904A184100310102088845E ++:102E9000C0840404A020880282A004A0019108A09C ++:102EA000098984838484018400C010C100A00202C7 ++:102EB000A084000800084040A01191110001050104 ++:102EC0008200400001044182820103C00010000022 ++:102ED00000000021000400A1000000828404A085FD ++:102EE0002000C0000008000900020001C0A0880402 ++:102EF0000400000010904003100210A0088420007D ++:102F00008200008900008900A1C0080085C08541B9 ++:102F100040101000C0C085058904A0011011830075 ++:102F2000048205A1A1108402211002001100840175 ++:102F300090022088C08385C109A182A0A0901120A1 ++:102F4000C090C001A0200320900510402080008088 ++:102F50000005001000880003008400400080A1806C ++:102F60000040850382000080008400040005A089E1 ++:102F7000A18020082000000500C100890080808019 ++:102F8000800200080008000003000500A040058042 ++:102F900082C00880A00208C08802A1A01010C185CC ++:102FA000210021802010C1008580908005099000BB ++:102FB0008010000080008088834191914040808093 ++:102FC000838080004041210000000013C200820085 ++:102FD00000810013C200000000000013C20000883E ++:102FE00000000013C200005000000013C2000000E7 ++:102FF00081000013C200004800880000C2000000E9 ++:103000000000001300000A00000000820013C2202C ++:103010008250000000130000418100000013C20034 ++:103020000000000000000000420000000000C2009C ++:103030004200000000000000414800000000C20003 ++:10304000000021000013C2004200F0000303FF0053 ++:10305000000000000000FFFF000000000000FFF083 ++:10306000FF003E3EFFFF7F4F7F4F0000000000004B ++:1030700000003C0F3C007F3F7E3C00000000FFFF53 ++:103080006F6F00000000FFFF0F0F00001E1EFF66A5 ++:1030900099FF990CFFFFFFFF06C70606FFFF3E06DC ++:1030A0003F300F00FFFF3F0FFFFF2F24FF0C000CEE ++:1030B000FF0F663C00000000000000000000F00070 ++:1030C000FF3C8100FFFF3C3CFF663C0FF000030328 ++:1030D000FF00000000000000FFFF103000000000B3 ++:1030E000FF42FF003E3E06067E427E420000000098 ++:1030F000000000003C0F3C006F0F66000000000065 ++:10310000FFFF6F2F00000000FFFF060000001E1EE3 ++:10311000990000FF000C6E0C660000C30000FFFF6A ++:1031200000003F300F00FFFF3C002F242F24FF0C36 ++:10313000000C000F663C0000000000000000F000E2 ++:103140000000FF3C81000F0F7E7E00663C0FFFFFFA ++:10315000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10316000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F ++:10317000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F ++:10318000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F ++:10319000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:1031A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F ++:1031B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F ++:1031C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F ++:1031D0000038239A0C4440A000180A060000304D25 ++:1031E0000000C0C3003F667F000000000000000038 ++:1031F00000000000F3F3F3F36060FFFF24FFE7FF3C ++:10320000000000000000000000FF66FF3CFFFCFF24 ++:1032100000603C7C0010F0107E7EC0FC7CFF7CFFD8 ++:1032200000007CFFFFFF0C0FFCFF3CFF3CFF30FF6A ++:10323000FFFF0000000024F4FFFF000000063CFF39 ++:10324000FCFF3CFC7EFE0000F0FC000000000000E3 ++:10325000000000818100000A000B000000003030F7 ++:10326000303C7E7EC0C3003F003F000000000004F1 ++:10327000000000000000000091007C7C7C7C242485 ++:10328000E7E700000000000200000000660000FF09 ++:10329000F0FF00600060000000004242C0FC3CFF04 ++:1032A0003CFF00003CFFFFFF000FF0FF3CFF3FFF33 ++:1032B00000FFFFFF04069D9F24F424F40020002655 ++:1032C00000FFF0FF00F066F60000003C0000000088 ++:1032D0000000000000818100000A000400000000DE ++:1032E0000000003C0586046100B000850086006493 ++:1032F00008B00000A08650F1A0B80005008600616B ++:1033000008B00000A0865071A0300085A0865091C2 ++:10331000A3800005A086507CA8B0000500860AE0C6 ++:1033200000B000000000058600E400B00005008643 ++:10333000006100B00000A08602B108B00000008665 ++:10334000006000B0000000865070A8B000800086C9 ++:10335000006000B0000005860A7000B2001008840A ++:10336000004101B0000000003C3C0A0A00FF0000E0 ++:1033700000000000000000000000414100FFF2F2E8 ++:103380000202000000000000000000000000A05F3A ++:10339000FF0000FF51AEFEBEBEBE143C1C3CAAA006 ++:1033A000AA000C0F0D0F0000FFFFFC3C0F3F5F7FDA ++:1033B0001414140000000808FFFFFFFF00300F3F47 ++:1033C00080A080003C3C3C3EF4F0140014FF1FFF42 ++:1033D000FFFFBCA01F1F1FFFFF3CFF203FFF3FFF61 ++:1033E000FBCB3B0B00000000A0001C3C141400FFB2 ++:1033F0000000000000000000000000000C0C00FFB6 ++:10340000FCF00C00000000000000000010000A0AA0 ++:10341000FF00FF0000FF51AEFEBEBEBE003C0C3CF4 ++:10342000A0A00000000F050F0000FFFF3C3C003C87 ++:10343000557D343434200000000FD020F0000030DF ++:103440000F3F00A000000000000AF0F0000014147C ++:103450001F1F000000001F1F1F1F003C00203CFF1B ++:103460003FFFF8C8380800000000FF20FF0800FFF9 ++:103470003C3CAAAAAAAA3CBE3CBEFF08FF012D2DD7 ++:103480002D2DFFC33C0000000000000000000000E4 ++:103490000000EBFF140000FF03FC78787878555F9C ++:1034A000FFFFF3F3BE820CFF5DFF00003F30AFAFC4 ++:1034B000555DFFFFFEBEFAAA555FFFFFF0F0FFFA71 ++:1034C000FFFFFFFFFFF0FFF05000A000000C0C001A ++:1034D0000C000CFFFEBEFC3C3C7D3F7FFFFFFFBCB1 ++:1034E0003C3F7D7F50000020000F553CFF00FF0057 ++:1034F0000F0F5555AEAAAABA3CBE3CBEFF00FF0056 ++:103500000055AAFFB2B2B2B20000000000000000F5 ++:1035100000000000C3FF3C0000FF0FF078787D78CA ++:10352000000FFFFF3030BE820CFF5DFF00003F3018 ++:10353000A0A0555DFFFFFC3CF000000FFFFF000066 ++:10354000FFFAFDFFFFFFFFF0FFFE5000A000000CA0 ++:103550000C000C000CFFFAAAF00000550F5FFFA052 ++:10356000FFA0000F555F00000000000F553C080051 ++:103570000000210004400000A1000000A000800025 ++:103580000400041000000400910004002000040066 ++:103590009100802120101100002020000240000234 ++:1035A00000000200800088000220C000040000002B ++:1035B00020000400900203100000004002000400FC ++:1035C0000202020411201100042003408440034041 ++:1035D000C008910002000208904002004100040867 ++:1035E0008020828810000091000811000000000077 ++:1035F000000000000000008000002000000020000B ++:1036000008000000A0002000000008009000010059 ++:10361000000004002002010000050080000090006E ++:103620009000040000004000090000800200C0007B ++:1036300000000300000009800000040000000000FA ++:1036400000008200004000802000000010004000C8 ++:103650000400020002008400000008800000000056 ++:103660000000048010000100400400000000000081 ++:1036700000000000800003000001000020000000A6 ++:103680002000000000000000000191108000910067 ++:1036900002100000100004000001110004000400EA ++:1036A0000020000100000000000000000000800079 ++:1036B00000A000C08020800080008000000000008A ++:1036C0000091000000000000000000000000000069 ++:1036D00000000001000000000000000100110021B6 ++:1036E00000A1002100408008800800410000000285 ++:1036F0000000000000214021000000040000010043 ++:1037000000000500000082410021002020902000E0 ++:10371000200040A00000010002000008000000108E ++:1037200001100408000800200008002104210020E6 ++:1037300002000241000004000400040020210008EF ++:1037400000100004004000200009001100100000DB ++:103750000000020002400200000000000040009053 ++:10376000C0A0002040A00080108010A0048800218C ++:1037700000800011402011C000000084118400C1AD ++:1037800040010000110400C00284910402040010F2 ++:1037900002102000020020000090400800000000FD ++:1037A000110400001100001080C180008041001051 ++:1037B00000081001000000004009C041900900C14C ++:1037C00000108000840180C0002000900020212093 ++:1037D000200020820084001080C00000804000C0D3 ++:1037E0000084082000208482000800A020081041E6 ++:1037F00009400088004020088400004184410041C5 ++:10380000000411041008C090101100100280828082 ++:10381000008400001004080083410000118084002F ++:10382000000010000000400084111020401002022F ++:10383000008210801102C0020000038802A01188DB ++:1038400008108809400921024002A0A00020088534 ++:103850000890100810050205820004000041108045 ++:1038600000029000C180008905021088000010C08D ++:10387000098800A0000000808890020008A00000D5 ++:1038800000002000A0002001880341001100030473 ++:1038900005004100032183C190C01108209005401C ++:1038A00011000800050002824005040000000983A1 ++:1038B0002000081000200200020100000200200980 ++:1038C0009000040500000000100040008900410045 ++:1038D0008810051082000200000200A04040008510 ++:1038E000008410000801200408A0880180028009DB ++:1038F0000921C1894189108303101088000000004C ++:10390000000000000100210001041020004100001F ++:1039100000801000000000A00420080000800100CA ++:1039200000801000C0000002000011A00040000054 ++:1039300010040140C180000001000840000085051E ++:1039400091C0210001C0001000100005000004001B ++:1039500000000400A0002000110000800000110001 ++:1039600000200000200001408489100004044080F1 ++:103970001088000810088402000482000000000083 ++:10398000008441844184108403100010100421003D ++:10399000050003002010080003000520081084041F ++:1039A00005880020040000200000210803102109E0 ++:1039B000400900024001C0098008044003200000C3 ++:1039C000C0018920C000100341C000830010101006 ++:1039D00008858800C11180210008400000104008BF ++:1039E000410882404100C1008041108209118220BB ++:1039F0000840020810C09041050004040000088837 ++:103A000000000008000800218821822100000280B7 ++:103A1000820000110000010901000005008000047F ++:103A20001100821100028505A090102084804000C2 ++:103A3000C02020089020200808200200038084086D ++:103A400000004102020011028410A0218240840380 ++:103A5000032102201000049010A08210A000000892 ++:103A6000008000C10210101010020890011100081F ++:103A7000108500A11190090803C010000110100565 ++:103A80008510050000840900051000001084100056 ++:103A9000104020102184020000200000410010008E ++:103AA000A000090109008300050040010989800484 ++:103AB00000000040051083A0C01088001040A0A0A6 ++:103AC0000410000010091103100388A000109110C9 ++:103AD0000004081002C009C0080003840588020819 ++:103AE00000840000410010208384028283C009C04A ++:103AF000218500A0410190098008A0A108A0208292 ++:103B000008008841000900000000000000000008D3 ++:103B10000000410000000000010000C11000000092 ++:103B2000000004040208000004000000012000203E ++:103B3000042100000000000004050400090000004A ++:103B40002000110000001184008483C0110088004F ++:103B500004008490000000000000C040C00000008D ++:103B6000000000000000880000001000400020401D ++:103B700020000004001000201188108402080000BA ++:103B80000000000802840000820021000000000004 ++:103B900000000000000008000000080011001141B2 ++:103BA00091099108020211050311800240049088D6 ++:103BB00011100502881021031010400988100040E0 ++:103BC000101108050009008010058085891184887E ++:103BD000088580C0051109828305A0200511880988 ++:103BE00000808580200040800090021000800088C6 ++:103BF0001103111091A0110420118204A00400856A ++:103C0000200005C002840891000040000000000070 ++:103C10000000000000009000000002000000000012 ++:103C2000000091010800000000010000C000010038 ++:103C30000989020310A0C1A105010100040041008F ++:103C40009089098402900011000091018485090384 ++:103C500083020009A00404C000858801C08588C0D3 ++:103C600008A02010A0C0019001100003090110104D ++:103C7000000200C101C1C04100A0208809112040FC ++:103C800000C0048209059102010809000100200416 ++:103C900021000100000000000001C0004100A00060 ++:103CA0008201890190080289839000080001880937 ++:103CB0002000040103018909A00009100904C18240 ++:103CC000100040A04188C010820500009004C09000 ++:103CD00085A19010A188C100024040020400849098 ++:103CE0008900A1018800A1908388C0834104050850 ++:103CF000A1851101A0018300C18800820920848868 ++:103D0000C0851100044140010804C08482001000F5 ++:103D10004000030020004102200002200900A10011 ++:103D2000400080052003898008218982110040100D ++:103D30004090110291400402900808100800088089 ++:103D40008520820441800882840988880040C0114F ++:103D500040209002C084400508004080C0008200DE ++:103D60008840850041110511020005418588200029 ++:103D70002080858510051002100910800583A0841D ++:103D8000800003858341048989088980840200803A ++:103D90000080008000000000000002800080008998 ++:103DA000004000820089040409090889C1890302CE ++:103DB00005092010A005400491400003A083114094 ++:103DC000411102908888842082A04091A1050000C2 ++:103DD00005112091100209830811041100894088FF ++:103DE000101000899183418300C08008888280A0E0 ++:103DF000881105200088110308040040880890C03D ++:103E000000828020A18885218984210582C1A108A2 ++:103E10000004002000840000020000080010008858 ++:103E2000000800400011C08901C0000000A1888284 ++:103E300021000000010109010005A10000A08889FE ++:103E4000002000020085081108900804A184830561 ++:103E5000000002A001110421200300000011C08510 ++:103E60000405104182C0414009880009C0A008052E ++:103E7000C0A18440408400090841100084C010C1E2 ++:103E8000908300038405098485C1210804A12008CA ++:103E900091820000000000000020000000010001ED ++:103EA00000000002008200000082830388A08300DB ++:103EB000C0C0014000840000002002A08905A100CC ++:103EC000A04000C00084000001018488C1A1828458 ++:103ED0001190000083889141C10385408503A19121 ++:103EE0000200A188820409849000880884410405A6 ++:103EF0008884C08402414111210002C09091880849 ++:103F0000C0018888C00010410910850982C18483DE ++:103F1000C0890440000000080008000000000040C4 ++:103F20000020000000050088000000808911881032 ++:103F30004002040003800520100800020800C14070 ++:103F400008040980000440000841111084914021B8 ++:103F5000038921000000830911080208888083C1B9 ++:103F60000408A008048091C084042010A0008002EE ++:103F7000020302890300848305C19041208080915F ++:103F800080100021808008410891A00491118021B7 ++:103F900000A000A100800000000048000000120006 ++:103FA0000006C200000000000013C200115021886A ++:103FB0008013C200410000000013C200060081000F ++:103FC0000013C200000000000013C2000000000047 ++:103FD0000013C200008200000A900013C2000050CB ++:103FE00000000013C20000000000001300000000E9 ++:103FF00000410000C200824800000013C2004100DE ++:1040000000000013C200006000000013C2000000A6 ++:1040100000000013C2004200000000000000000089 ++:104020000000000000000000000000000000000090 ++:104030000000FFFF207F207F00500500AA0AFF0F2D ++:104040000000000100553F3F000C00000C5DFFFF29 ++:1040500005FF3DFF0CCFCFCF00000020000800017E ++:10406000000000C30030FFFFFFFF0CFFFFFF3C3FDD ++:104070007D7F000400000C0C0CFF053DFFFF000CD1 ++:10408000300000000000A575AF7F495DCBDF002048 ++:10409000DFFF00000000013D83BF000000000000C2 ++:1040A000000000000000000000000000000040C010 ++:1040B00000001E001EFF005FA0FF005005008202EE ++:1040C000C3030000000100003F3F000C55550C5D8C ++:1040D0000C5D05053D3D0CCFCFCF0000000000007A ++:1040E0000000080000C30030005504510C0CFFFF15 ++:1040F0003C3F3C3F0000050000000000053D053D41 ++:10410000000C30000000000000200A2A081C8A9ED3 ++:104110000020DFFF00000000019701970000000071 ++:10412000FF0FFF1F00000000F0F0F0F000000000A3 ++:1041300000040004FF00FF00FFFA000A0020000056 ++:10414000AAAA0000FF3CFE3CFFF8FF280000008008 ++:10415000FFFCFF3CFEFABEAAFFFFFFFF0000FFFFCF ++:10416000BA3000000000B23C000020000000100047 ++:104170001000FFFF3C3C00000000FFBCFFA0FFFF61 ++:10418000FFAABA303030F0FF3CAA7D747D24FFFDD9 ++:1041900000088200FFFFF0AA3CFFFEEBC282000095 ++:1041A0000000FFFFFFFF00000000E8F0F0F000005B ++:1041B000000000040004FE0EF202FFFC000C0000F0 ++:1041C0000000A8A00105FF00AA00F8F82828800038 ++:1041D0000000FFF0FF00FCF03C0000C000E8000021 ++:1041E000BA30BA3000000001B20000000000000048 ++:1041F0003C000000FFFF7D7C00000000FF3CFF0052 ++:10420000FFFFFF2830303030F0003CAA287428240B ++:10421000FFFD000882000000F0AA3C007C6940001D ++:104220000086006008B000A0A0865061A9900085BB ++:104230000086007100B00000000200B5010000001F ++:10424000A58650F0A0B0000500860C91038900857A ++:1042500005860AF0A0B00005A18650F0A0B00005C8 ++:104260000000A58650F5ABB90085058602F008B0C0 ++:104270000080008400C100800000088E006408B047 ++:104280000000008600E108B20000A0065AB1A88034 ++:104290000005008602F100B80015A0865AF1A8B802 ++:1042A0000085000000000006000600000000000F6E ++:1042B00000FF00000000F5F55555F720FCFC7D7D62 ++:1042C00014D700000000000000007F805FA00041C4 ++:1042D000FFBE0000000005FF3DFFFFFFFC3C0CFFA0 ++:1042E0005DFF0000001000000000555DFF00BC00F5 ++:1042F00005FFFFFF3000F000555D55F7AA8228004A ++:1043000010BABABAF03CF0003C3FFFFFFFFFFFFFDE ++:104310000FFF0FAFFF04FB000FFF0FFF3CFFF0AAE2 ++:1043200024B42EBE000000000090009000000000A9 ++:10433000000F00FF0000000075F55555F720C0C0C4 ++:10434000414100FF00000000000000007F805FA0EE ++:104350000055FFAA0000000005FF3DFFFFFFF00031 ++:104360000C0C5D5D0000000000200000000CFF0050 ++:10437000A00005FF05FF3000F000555555FFA28253 ++:10438000200000000000F03CF0003C3CFFFFD0208B ++:10439000F0000FFF0FAFFF04FB0003FF0AFF3C001C ++:1043A000F0AA24142E1E0000000000C300410000EB ++:1043B000000000000000000000002F0F0F4F000061 ++:1043C000000055FF383D0000000055FFFFFF7F5FF4 ++:1043D00080A014EB10EF000000003C3FFFFFFFBC8B ++:1043E000FFA000000001000030003C003C7D3F7F4A ++:1043F000FFFFFC3C0F5F3F7F7FBC7E7E0438FFFFEA ++:10440000FF3AF03A0F3F5F7F78782828053DFFFF9D ++:104410000000000028FF18FFFEEAD6C28F8C0C0CAB ++:10442000AAF0FF3C0C0CCFCF0000000000C30041FD ++:104430000000000000000000000000000F0F0F0F40 ++:104440000000000000AA383D0000000055FFFFFFFB ++:104450007F5F80A014EB10EF00000000000FFFFF53 ++:10446000BCBCA0A0002000000000300000000055EF ++:104470000F5FFC3CFC3C00553C7D3C3C3C3C003C24 ++:10448000FFFF0F3A003A003C557D78782828053D1B ++:10449000053D0000040014FF0CFF7C685440BFBCC5 ++:1044A0003C3CAAF0003C034D034D210021002000BC ++:1044B000000011820000200004000400000004003D ++:1044C000200004000400000020000920110000006A ++:1044D000110000A003000008210004000888040067 ++:1044E000040004000400020004C0000021C0000811 ++:1044F0000300200003000400032004A005000010B6 ++:10450000000011004108000000840488040011002C ++:10451000048204A021400400200004202020200068 ++:104520001100041004002108000004000200000033 ++:1045300000008200000000000000000000000000F9 ++:104540000000A000000000000000000000000000CB ++:1045500004002000200000000000C00000009000C7 ++:104560000800A000002000000000821000000000F1 ++:104570001000001090030040C003820000000400FF ++:1045800004000000880082009002820000002000E9 ++:104590008200840088000000000008000800040079 ++:1045A000A0008800A0008200000000008800000039 ++:1045B00000000000000000000000000000000000FB ++:1045C00000000000000000000000000000000000EB ++:1045D00000000000000000200020000000C00000DB ++:1045E00000000000030000000000000000200000A8 ++:1045F0000000000000100000000000C0000000A04B ++:1046000000000000000000000000000000000004A6 ++:104610000000000000200000000000200020000436 ++:1046200000900020008200000084008400C0000090 ++:104630000000020000110041001100000000901075 ++:104640000200000000100021001000000010000017 ++:1046500000000400900000000421001082000010FF ++:1046600000000010002100100011000000100000E8 ++:104670000000001000100200021082100010002143 ++:104680000008101000410020820800000000020312 ++:104690000220000500100020000802100010000099 ++:1046A0000041001000210020002000000000002038 ++:1046B0004010000000000008090000100000030086 ++:1046C0004100000041000000001000000000410017 ++:1046D00021840010001003000502211000000000DA ++:1046E000210200100400030009A004C000004000E3 ++:1046F000080000000400110041840088410005000A ++:10470000210002400000110011400290030000004F ++:1047100008900010090800000888050005A0008422 ++:104720004100410000000910088402100400094003 ++:104730000008000000210000000000001000100927 ++:1047400000410000A00000050000000582000041BB ++:104750000000100084000041C00288058200C000F3 ++:10476000C01084009040A01190418441844000001A ++:104770008821844100000421100982411040A000DA ++:104780000000A021042100088200402110008421A3 ++:104790008400002100110800000540410200104182 ++:1047A00004031005A0038840C021A00982008240B4 ++:1047B0008240820308400000110010000000000049 ++:1047C00000001100000000004100200002000088ED ++:1047D000040020000200200009001000000000007A ++:1047E0001100000000C000100400090002000300D6 ++:1047F000410020000000000000000000200009002F ++:1048000000002100410009000000400405000000F4 ++:10481000000000020800210000000200419000900A ++:10482000009040824082000408000500040011004E ++:1048300020004100050000000021200000000803C6 ++:104840000000001008410005100982030803000061 ++:1048500090098400881182002000400902000003B2 ++:10486000040382110009002100410000C0009000F3 ++:1048700000008800A000880800008400904190009B ++:104880000205A0408440A000A009A0001011C011A2 ++:10489000000004411041C00000218408C011080438 ++:1048A00008418809904110000041A01188110209B7 ++:1048B0000421000900410000002100000000000068 ++:1048C00005000000000010000000050010100000AE ++:1048D00000000000000000001000001010000500A3 ++:1048E000000000200000000004004100050000104E ++:1048F00000000000058200C0038400000900009051 ++:1049000000C0418800C000882100210005A00300EC ++:104910001002000200000300200800000082009046 ++:104920000000001021000008100805000010210000 ++:1049300003A0084000002100000000000009000062 ++:1049400088008800000000008800001100050802AF ++:104950000020100520059021840008081021100374 ++:1049600010020010100000001003C000001104111C ++:10497000C00888038821042104400803000082093C ++:10498000C003842100408400C0418200081040051B ++:1049900088088209004100020203881004080440CC ++:1049A0000403000500218809001184219021A02121 ++:1049B00002118400881102098400A0008411000003 ++:1049C000000000080084411000000000000000000A ++:1049D000020041000200110000002000050000005C ++:1049E00000C00000410000080400000011000200A7 ++:1049F00009000000218440000000020000040000C3 ++:104A000010822082000400000890000002020000D2 ++:104A100008000400008400881040000000400200EC ++:104A200004820000100410100000210020820940C0 ++:104A3000048409820884054000A02184419000403C ++:104A400000000420000000000000000088000800B2 ++:104A5000000000000000000000000000400088008E ++:104A60000005002010408840820004000000100370 ++:104A7000000000002000200200000000001140049F ++:104A800000000000001188039020022000110200A5 ++:104A900082411010200440100010100582051041C2 ++:104AA0008200820082000421040310000021200300 ++:104AB0009009000982090011000084410221C021EF ++:104AC0009008FFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:104AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:104AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:104AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:104B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 ++:104B1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5 ++:104B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:104B3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:104B4000FFFFFFFF00A0E41C0C44401000000A0619 ++:104B50000000601804002000040040001100214003 ++:104B60000400110004002000410104009100110024 ++:104B7000040004000001A0008200400004000200C4 ++:104B8000040084080001110020A08400020000003D ++:104B900000080320000080038421A00988912108D7 ++:104BA000000409000484211121004020040911009F ++:104BB000110021000202C1089100900103000008C9 ++:104BC0000000211004000001820104000221830082 ++:104BD000200104012040000000000000000000004F ++:104BE00000000000C00000000000044000002000A1 ++:104BF00000000000900000082000200001000000DC ++:104C00002000000041008204000000100403004165 ++:104C1000000304002000000008820590058805407C ++:104C2000008000808411200320C00000218020A08B ++:104C30000000400082000380040040000308900050 ++:104C40000480000020802000200820209100088897 ++:104C500008400008844000C00400800008000000F4 ++:104C6000000000000000000110000000808800002B ++:104C7000000102000020001000400000800210002F ++:104C8000002000880000002080000000000080104C ++:104C9000000000000020002000C0002000000010E4 ++:104CA00000000000040000000041800000008001BE ++:104CB0000000002000008000000000100000001034 ++:104CC00000000000000000002000000080900010A4 ++:104CD000009000200082002000210100040001005B ++:104CE000000000000200000002200100000040104F ++:104CF000000082040200002040000000000002804A ++:104D0000050000000021A00020100220002020212A ++:104D100004000020001000100010000084A000001B ++:104D200004A000100010910000000284081004206C ++:104D3000024000110010001002200020002100009D ++:104D40000000400900090021001041000021100866 ++:104D50000408002000100220000004080000800069 ++:104D6000000000A00000000000000208008210A067 ++:104D7000000082A00000020211C00884800200002E ++:104D80000084108500108000030004200510040436 ++:104D90000003848800000002110005010000C00526 ++:104DA0000001851182C18001001005A083A085103B ++:104DB0002110C14191000008800902010008800013 ++:104DC000100002080284C1C10208C0402040A109AD ++:104DD0008910042004200089059100A00010000023 ++:104DE0004000000000001000000000000110000062 ++:104DF00001000000410000000180000001002000CF ++:104E00001000820084040000200000009080000058 ++:104E100000001004080200410000C0000040000033 ++:104E20000582C00808880420044000000000200516 ++:104E30001080004104A004100000202000408200E7 ++:104E40002000A00000C111411008840005890080E5 ++:104E5000104004009180019020040020A000000474 ++:104E6000410005000082C100050010000000100094 ++:104E700000000500050003001000100000000008FD ++:104E8000004005880002001020040000A00000007F ++:104E900003A00200040088000500050004000401CE ++:104EA00000000801080082018400100420001000A6 ++:104EB00004000089200090008491209021000000CF ++:104EC0001090400000820201000104000200400036 ++:104ED00088000800040003001000100010014001C9 ++:104EE00000000000002000004000000000008200E0 ++:104EF00000000010000082008400000004218200F5 ++:104F00000800100020000080008000030000200046 ++:104F100008008208831000102105000000000140F5 ++:104F2000012000000920010003200200020091007E ++:104F3000000001000010C0000410054011008800AE ++:104F4000C000820085030003C040002001218220B0 ++:104F500010210405001011100000040000200004BE ++:104F600009040800000000000901100120410000B0 ++:104F700000890588410009100082050000880010A2 ++:104F8000001003001000004010100200200010006C ++:104F900005001002090000010000090010000000D7 ++:104FA000084010200000841084C01021102000A0B0 ++:104FB0004082041004844108044091200482048447 ++:104FC00000820508008821A0000802090982210941 ++:104FD00000108085410802C120000401200905015C ++:104FE0000400000008040400000000080004012080 ++:104FF00008000040000000000000000000009000D9 ++:1050000000000000000001000080000001210100FC ++:105010000000000000800005040400058421002138 ++:10502000000000C100800000058021000188008090 ++:105030000000850001008900C082A021408000009E ++:1050400000080000000300210020000010200000E4 ++:1050500088880000020200800040012008200040F3 ++:10506000C040011100000080030010000000020099 ++:1050700021082090200084200000100021822100BF ++:105080000010098304002004001084850200001031 ++:105090001188020009002020100010000000030009 ++:1050A00011101084022000C00000881004849000B9 ++:1050B00002000384008483042000110400100420F3 ++:1050C0000420080040082082001082C0041041081B ++:1050D000080905090200090309101008022105202A ++:1050E00021200020002011A1000088001000A00055 ++:1050F0000000000085100100204000210841084008 ++:105100000000000000024000202010000240024089 ++:10511000900000002000000083000000000000005C ++:1051200000000000000000800000000005001100E9 ++:1051300005001100000010000200000000008209BC ++:10514000008000C0020002118900C0004002030874 ++:105150000005C0409088880300820280008001A082 ++:1051600000800080000000200040000009030420AF ++:10517000000841A0200280091120032108039009A2 ++:105180000805080400000000410000000809850827 ++:1051900040030320000000000000000000000000A9 ++:1051A0001000008008030009050840110080908568 ++:1051B00002A08909030888888909098209828480F4 ++:1051C0000500400003000905002002201020000017 ++:1051D000050008000000800005802100000080829A ++:1051E00083048089009105118304094005C04001B2 ++:1051F0000090008201400001C00100000100000198 ++:10520000C1000101000000000400000000000100D6 ++:105210001001090001000000C00000000000009023 ++:10522000889001080010880184000000010000003F ++:1052300089838408C1040005918810098904A0109D ++:1052400009A08502A14001400089908800C0880122 ++:105250000000C1000200000084008508A00090004A ++:1052600084A00209204100C000C004000003002106 ++:105270000000010001000100898284820521058966 ++:105280000800842004010541900041820400098443 ++:105290002100824020202091000000010020000019 ++:1052A00000010000000000010400200010C04000C8 ++:1052B00000008900082001A083830940899184109F ++:1052C000400109040020A1038208A10000C0098850 ++:1052D00002408410A0001108C0C1854020040910BC ++:1052E000C082010000000002001040000282411054 ++:1052F00083111140080008004003028985009010C6 ++:105300000911081090000841081104402080A000F5 ++:10531000C08011410221028302C1000000200080F0 ++:105320000008004000030000000304009100840016 ++:10533000090000001102410310808291A080044006 ++:10534000090885414082040585A1C184020320909B ++:10535000051190214103A103858088118588208053 ++:105360008500840210094120110003800300C02041 ++:1053700005C1A0C11108000584091008028200209F ++:1053800040090821402000900004058800000080AA ++:1053900008000000088300002089880980000000C0 ++:1053A0002100800080000080020000800290002028 ++:1053B0000002008300004008219003824103028321 ++:1053C00083840810009000888004108800108004F6 ++:1053D00000891188400880114120000580C000002C ++:1053E0000208401100A141802080000041001041CE ++:1053F0008541A0A0820400014001A00040010111EC ++:10540000000400034108000500100004A111000879 ++:10541000000800A00090902000A001A0400402021B ++:105420000002010404084000A0C005A0208800215B ++:105430000088000020400000A1090089C0910201FD ++:1054400000C0400483090411009082890085100384 ++:1054500010084002822190090408008900A004A0DD ++:10546000008200850110A0C100040188C09083A0C3 ++:10547000C00882022085409090000000900000004B ++:10548000830011410800100883000904C10009C00D ++:10549000830404008401A004010841048401A004E1 ++:1054A00000400084000000008204C04004000000AE ++:1054B000000000010000004000008304A010044030 ++:1054C00001C001C101000000000989A0A102400043 ++:1054D000C0A185C0A1090801412082058440208225 ++:1054E0000803822089A1022002102100219041009E ++:1054F000080001012091900001880000000880113F ++:10550000000089080202A020A1808302C004A10239 ++:10551000100089C100418202080003A0858488022E ++:1055200011800080000000000000808000800000EA ++:105530000000000800100008000000008480050240 ++:10554000410905004183090041031108032082201D ++:10555000830091409000C183880805008083000586 ++:1055600080898090C01190C0C021A080A0008900D7 ++:105570004100110010080841400911008284001305 ++:10558000C220000000600006C200064800000000C3 ++:105590000000000000840000600082008200001310 ++:1055A000C200004141000006C200000000000013DC ++:1055B000C2000050000000130000000000000000C6 ++:1055C0000013C200006021000013C20082004100ED ++:1055D00000130000414800000013C2004200000018 ++:1055E0000013C200428200000013C200000000004D ++:1055F0000013C200000000000013C2000A000000F7 ++:105600000000C280C2C2FFFB0400FE08FF000000D1 ++:105610000000BD9F249FF3F3C3C300000000990066 ++:105620000000FFFFFFFF00000000FFFFFFFFFFFF84 ++:10563000FFFFFFFFFFFFFFFFFFFF04082010000038 ++:10564000FFFFFF3F000000003F3F7E420FFF663C30 ++:10565000000000C0F6F63606FF7FFF7E3C0F66FFB7 ++:10566000000000003F3C0300FF00FF00FF000F0FA1 ++:105670003F300F000000000000000000EFC32C00CE ++:1056800000000000C2808080FFFF0000FF00FF00DC ++:1056900004000200BD062406F0F000000000000037 ++:1056A00099000101FFFFFFE700000000FFFFFFFF7F ++:1056B000FFFFFFFFFFFFFFFFFFFFFFFF0201408033 ++:1056C0000000FFFFFF3C0200080003037E420F00C2 ++:1056D000663C00400000060606063F3F3C3C3C0F8F ++:1056E0006600000000003F3C0300FF00CF0CFF00FD ++:1056F0000F0F3F300F00000000000060300000007E ++:105700000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 ++:10571000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 ++:10572000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10573000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:10574000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69 ++:10575000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59 ++:10576000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49 ++:10577000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39 ++:10578000FFFFFFFF0070FF910C44401000180A0655 ++:1057900000009065F909C0C00008000E00FF10FF6E ++:1057A0000000FFFF7E7EC0FC34B576F700000000ED ++:1057B0000000001003030303FFFFFFFFFFFFFFFFD5 ++:1057C000FFFFFFFFFFFFFFFFFFFFFFFFFFFF0C30AB ++:1057D000000005A00000707070FF24FFF4FF333359 ++:1057E000FFFF003C303C000000007E7E7EFE00207B ++:1057F000303000C030F00000000000000000000069 ++:10580000000024E724E787000000F300F3FF0066B0 ++:10581000606064FFFFFFF909CFCF0F080F0E00FF94 ++:1058200000EF2000EFFF4242C0FC109152D3000075 ++:1058300000000000000002030303FEFFFFFFFFFF64 ++:10584000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:1058500003C005A000000000606060FF2424F4F491 ++:10586000003300FF00003030000000007E7E7EFE2E ++:105870000020303010D030F00000000000FB000BA2 ++:10588000000000002E2EEEEE9F000000F300F3FF5C ++:105890002424606064FF64FF00860A0501B000856F ++:1058A00000A6007408B0000005860A6000B0000081 ++:1058B000008E006400B00080A58252F1A1B80005FE ++:1058C000A0865971A1900805A0865070A090080587 ++:1058D00000C6006100B000000000A0845090A0B994 ++:1058E0000000008600E101B80085058600E101A006 ++:1058F0000000A0865230A8B00000A08600F108B8D1 ++:105900000080018400E108B00005008600E100B0DD ++:105910000000A1865231A8B00005000050500000E0 ++:1059200000000505C0CF0000022AC0CF0505001009 ++:105930005010FCC0EBEB0F35FF35F7F7FF3C0000D4 ++:1059400000000000000000000000FAFA0A0000F564 ++:10595000F5F5000000000C0C0D0D00000A0A0A000D ++:1059600000000010000000000CCF7D7D0000000052 ++:10597000D70CD7CFFAFAFAFA0CFF5DFFFFF0ACAC08 ++:1059800020AD70FDFCC0EBEB1C1C1C1C3CFFAAF006 ++:105990000CCF0F0F000000000F0F05050000505046 ++:1059A00000000000F5F5C0CFAAAA022AC0CFF5F585 ++:1059B000A0B0F0B0FCC028280035F035F7F7C300E0 ++:1059C000000000040000000000300000FAFA0A00A5 ++:1059D00000FAFAFA000000000000050500000000CF ++:1059E0000A0000200008000000000CCF41410E0C0E ++:1059F0000200140C14CFFAFAFABA0C0C5D5D0F0019 ++:105A0000ACAC008D50DDFCC0282820702F7F3C00FE ++:105A1000AAF00F0F0F0F00F000F0EF4FE545002048 ++:105A200000000000000000000000008228AA000022 ++:105A30000000D4FC0000000000005F5F287D000033 ++:105A40000000FFFFFFFF000000000000000030BA70 ++:105A500000AA0000000000000000AAFF1E1E0000B7 ++:105A6000C000C30001010404B2B2B2B200FF00FFE3 ++:105A7000FC3CFAAA0000C3C3FFFFFFFF14555541C9 ++:105A8000000000001C1C1C1C0000FF009CDC9FDFB1 ++:105A9000FFFF000000000000B2B23C3CFBFF7DEBCA ++:105AA000000020000000000000000000A0A0A0A056 ++:105AB00000000000D4C00000000000000A0A287D99 ++:105AC000000000007FFFFFFF00000000000000005A ++:105AD00030300000000000000000000000551E1ED5 ++:105AE0000000C000000001010404FF3CC3007FFF70 ++:105AF000FFFFFC3CFAAA41C34100FFFFFFFA145527 ++:105B000055410000000020702F7F0000FF00004082 ++:105B10000343FFF30C0000000000B2B20000FBFFE3 ++:105B20000000040084008200080004001101040148 ++:105B30008401000020012100040004014000040150 ++:105B400011002000000811002101030104000200DF ++:105B50000301004020008408202020901110040040 ++:105B600004100000040011000400040010201120A3 ++:105B700011004003828403000400A00020014100C2 ++:105B800004100408210003918420821004040400FE ++:105B9000020120880200110204A00400200021203C ++:105BA0001120118282001000040001000000000892 ++:105BB0000040020200000008000000000040010058 ++:105BC000001000000000008000000002000401003E ++:105BD000030040200080010020004100040000007C ++:105BE0000000A00000008400000000000000008011 ++:105BF0000080A00005A00400000020102000044048 ++:105C0000000000800003200000200200410000800E ++:105C100000000040040000050000000084000000B7 ++:105C200000000000A0000000004000000001000093 ++:105C30000000000000000000000000000000000064 ++:105C4000000000000000000000000088000080004C ++:105C50000000000000000000000010000000000034 ++:105C600000000000000000C0000000000000002054 ++:105C70000000000000200000000000000000000004 ++:105C800000000020000000000000002000C000888C ++:105C900000C0000000C0000000000000082000005C ++:105CA0000000000000000000000004800800001058 ++:105CB0000000000000000000000090000000400014 ++:105CC00000080000A01000000000A000002100005B ++:105CD00002410000820002009000000090200000BD ++:105CE0000021A0210011820000000000904100006E ++:105CF000001000100000029082100021000000102F ++:105D000000210041000800080021001000100010D0 ++:105D100040020011001000080010020900210009D3 ++:105D2000004100200010002102108000000200103D ++:105D30000089002000200000009000A000000090DA ++:105D400040200010008800200002004000100000E9 ++:105D500000100084210200840000002000000808D8 ++:105D60000040009000C0001000A0000000000000F3 ++:105D7000000000008084001000A0890011110011B3 ++:105D800000010200001004100000001002020000D8 ++:105D9000028803020010008400848084001008A0A0 ++:105DA0000002098408C0008200080002040082008A ++:105DB00000001002C0000005400040008441C00007 ++:105DC0000200018990000008C0058208004100001F ++:105DD00082050009884100111010C00882000000EF ++:105DE00083031021000300098203C0410000000565 ++:105DF00082100021080004218400000040080404EF ++:105E0000900408040105402185030003080385056B ++:105E100000080008C083C00800080021022110000B ++:105E200010009000820010030021000000214100BA ++:105E30000500050084000500100009004100410034 ++:105E4000000010000088030000C02100A000100224 ++:105E500010001084080009001000200041002000FC ++:105E600010000208410000001000200005000000A2 ++:105E70004100080000004100040004000400040088 ++:105E8000200004004004040020000300040000017E ++:105E9000410003A0080020000200000010004000A4 ++:105EA0000000080008000800400000001000050085 ++:105EB00000000200000021000000000000000000BF ++:105EC00000000000000008000000880088000400B6 ++:105ED00000020000100000000200080001000000A5 ++:105EE00001000000200000000000A00000000000F1 ++:105EF0000000000000000000000011008900010007 ++:105F00000100C10001000080090001410000010002 ++:105F10000020100900210200100000050000001000 ++:105F200000000003A021000000000000002100216B ++:105F300000000000020241400010081002020202AC ++:105F400002C005C1088508404188100000100240C9 ++:105F500090898088A14088001089101120828002D9 ++:105F600020100000200000040510098800A0410056 ++:105F70000040000009C0000021100302880000203A ++:105F8000900085824100410004009000040210C08E ++:105F9000032000000089410080408003029002A09D ++:105FA0008020000100000082008205004100098479 ++:105FB0000300100000000840001004A100030005C9 ++:105FC000400088411020882000400400900002001A ++:105FD000900002200402040004058820000401004F ++:105FE000020001000010010000000003C02184082D ++:105FF000C0214000000084008400C0000000200395 ++:106000001080040340090021040083002000910057 ++:1060100088418810A040000410410291048489083E ++:10602000030920808420000388100021081010003C ++:106030001020841000030300100190100801208438 ++:106040000084000080400000100000204084008494 ++:106050000300110002000082000000840984C100D6 ++:1060600008000800100004002000001021000210A9 ++:1060700040000084000800002110098408C009A025 ++:1060800000000000008200200988100020C04100AC ++:1060900020C002820040004000088040202004848C ++:1060A0000000048209040820000400844088414064 ++:1060B000108400C0008808840011004004410204DC ++:1060C0001000840000000441000500000090000062 ++:1060D00008000000000008212000820000000002EB ++:1060E00002058200820000008410C00000008200CF ++:1060F0000000000000000000008000110000880087 ++:10610000000000008200000002800800C02090080B ++:1061100000100000100508090000000020000180A8 ++:1061200000000000010000000800008000000000E6 ++:106130000000000008000000000008838082418504 ++:1061400008824003C0044005414003830410040555 ++:1061500008118080828002000080848380C0418595 ++:10616000088902100004800811090490048200418B ++:106170004084000000000000000000C0000000009B ++:1061800000000000008000002180000000004000AE ++:1061900008008000A08310A000800840000020803C ++:1061A000C000008080008980838000801003000090 ++:1061B0000009100800000000000000000189844070 ++:1061C000104101408901C00100010100C18984C062 ++:1061D000028301042082C084011000080889044160 ++:1061E000A003000221880084042000200082008493 ++:1061F00000A10108000000000000000000000000F5 ++:1062000000000000000000881008C1A000C00400C9 ++:1062100085004100080004830085040800A100886F ++:106220004184200400C0409003204020000400016D ++:10623000000000000101000000000000000041001B ++:1062400000008900900441008400410040C1C00169 ++:1062500000008800C0C002000900C1001111040044 ++:1062600040008900A1820800C004910821010900B2 ++:10627000A0040509891000000000000000000000D3 ++:10628000000000000000000040001002880002C072 ++:106290000082000000040001A1110800831040905A ++:1062A0000001080088028441C021200020828483EC ++:1062B00001C00001004000000000000000000000DC ++:1062C0000841040088009005040889080800099125 ++:1062D00005400800830009800803080041000320EE ++:1062E0009005C00082000880100084004008090961 ++:1062F000880204002108099000000000000000004E ++:106300000000000000000000000080050000800088 ++:1063100000020080004100000041A0C08200410056 ++:106320000200000300110000008800888040800007 ++:10633000001102001020108010000000000000007A ++:1063400000000890000900848591400800081003AF ++:106350000520020800050803058800800080908061 ++:106360008080028980A0C08405C0000280048289E8 ++:10637000C0002008800880094004000000000000E0 ++:10638000000000000000000000000000000000000D ++:106390000000008080000400400000004002054032 ++:1063A0008020110580000380108000800080840020 ++:1063B00040000080100200110011110900000000CF ++:1063C00000000000010500C000A0418801830040DA ++:1063D00001A0918901C00000C0C001890002A00491 ++:1063E0008540844000048241400401890001C0408E ++:1063F00088852100010008018401010000000000DF ++:10640000000000000000000000000000000000A0EC ++:10641000000082A0008840020108019088900800D6 ++:1064200090018401C000082000102084900420C046 ++:10643000820202A004A0050000000000000000008D ++:106440000000000000008241C00100000440820002 ++:10645000100008010888C0918800C00000040401F1 ++:10646000400188001010040188414001C0028540AD ++:106470000040000009409111050990001008010139 ++:10648000000000000000000000000000000000000C ++:10649000A1A1880002000000001000080000000018 ++:1064A0000804844008910804C0A0049082020402F9 ++:1064B0008200204088828802000000400001000025 ++:1064C00000000000000000008020001000408080DC ++:1064D000800380400008000000408020000300008E ++:1064E000001000110002000080038088804080803E ++:1064F000892009880000200009880488040441805C ++:106500000820000000000000000000000000000063 ++:1065100000000920C00000004000000000800000D2 ++:106520000000800400028003008080008000008062 ++:1065300080808009800000800080000000820020B0 ++:106540000000000000000000000081500013C200A5 ++:106550000000000000210000000081000013000086 ++:106560000600008400066000000021000013000007 ++:106570000A5000810013C200000000880000C20021 ++:10658000000000000000000000000000000000000B ++:10659000000000000600001360000000004200132D ++:1065A000C200820000000013C2000050000000136F ++:1065B000C200420000000013C2004182000000003F ++:1065C000C200000000000000000000000000000009 ++:1065D0000055AAFF0000000000C33CFF00000000BF ++:1065E0003C4DFF4D000000000000000000000000D6 ++:1065F0000CCFD7D70000FFFF00FF00FF20207F7FD8 ++:10660000707F00FF0000000000000000000000009C ++:10661000000000000000FFFFFFFFFFFFFFFFFFFF84 ++:10662000FFFFFFFFFFFFFFFFFFFF008100240000CF ++:106630000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF68 ++:10664000FFFF0090000600000000000000000000B6 ++:1066500000002D2D2D2D000000001717171700002A ++:106660000000004DC34D00000000000000000000CD ++:1066700000000CCF1414280028FF202F202F00A08A ++:106680005FFF404F00FF000000000000000000001E ++:1066900000000000000000000000FF3CFFFFFFFFC3 ++:1066A000FFFFFFFFFFFFFFFFFFFFFFFF8100240051 ++:1066B00000000000FFFFFFFFFFFFFFFFFFFFFFFFE6 ++:1066C000FFFFFFFF90000600000000000000000038 ++:1066D000FF003C3CF775E361FFF03CAAFABE50BEF8 ++:1066E000FF003C3C3F3F303000000000AAAAFFA260 ++:1066F000FFF03CAAFCEBFC28AAAAAAFCFFFE0302BE ++:10670000AAAAEBE8FFFF0000000000000000000064 ++:1067100000000000000000000000FFFFFFFFFFFF7F ++:10672000FFFFFFFFFFFFFFFFFFFF6900FFFF6009A3 ++:106730000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF67 ++:10674000FFFF2222FFFF22110000000000000000D6 ++:106750000000F0F0AAAAB634A22000F03CAAFA1475 ++:106760005014F0F0AAAAFA0AFA0A00000000000089 ++:10677000FFA200F03CAAC0EBC028AAAAAAFCFFFE18 ++:106780000302AAAA2B28BFBA1510000000000000BF ++:10679000000000000000000000000000FFFFFFFFFD ++:1067A000FFFFFFFFFFFFFFFFFFFFFFFF0069FFFF8E ++:1067B00000006009FFFFFFFFFFFFFFFFFFFFFFFF7C ++:1067C000FFFFFFFF1111FFFF00002211000000007A ++:1067D0000000000000860AC40180800500860A606F ++:1067E00000B0000000860A8001800000008600657D ++:1067F00000B0001000860A8101800000008600B50C ++:10680000009000000086007400B00000000000004E ++:1068100000000000000000000000000000000086F2 ++:10682000098001800800A08650F5A8B00805A0C620 ++:1068300000F108B00000A08659F1A8B00805A086B4 ++:1068400050F1A8B00800A0400010080000000000AF ++:1068500000004CE8100055557D418AAADFFF5555D0 ++:1068600000FF10150000FF0FFF000000C3FFBEBEB9 ++:10687000828200000000FF00BF800000FFFFC3C352 ++:106880003C3C0FF00FF0EBFCEBC000000000000000 ++:1068900000000000000000000000000000000000F8 ++:1068A000FF00FF0F8282FFFF00000000550F3CFF3A ++:1068B000F0AAFF3C000000000302010000C300003A ++:1068C000FFF0AA3C007D007D0000000000000000F9 ++:1068D0000000000000000000AAAABE8208AA5DFF16 ++:1068E000C3C30F0FBABF0000FA0AFF001400D7FF9E ++:1068F000FCC0FCC000080000FF00FF001000BFFF4C ++:10690000C3C33C3C0FF00FF028FC28C0000000007F ++:106910000000000000000000000000000000000077 ++:106920000000FF00FA0A00827DFF00000000550F02 ++:106930003C00F0AA003C00000000020200000043FE ++:10694000000000F0AA3C088A5DDF000000000000A3 ++:1069500000000000000000000000FFFC0F0C00FF22 ++:1069600000FF00000000A0A028AAFFFF00007D7D1E ++:1069700000FFAFA03F3F5F5F287DFFF7002000FFD3 ++:1069800000FFFF3AF03A55550F0FAFA03F3F0F35CC ++:10699000FF350000000000000000000000000000C3 ++:1069A00000000000FFFF000000FF00FF00000000EB ++:1069B000000000007D28F5F50505F5F5FFFCFFF06A ++:1069C00000550F55FFACF0ACAD55ADFF0000000019 ++:1069D000000000000000000000000000FFFC0F0CA1 ++:1069E000003C82BE00000000A0A028000CFF0C00AC ++:1069F00000FF00FFAFA030300A0A287DFFFF000033 ++:106A000000FF10BF0F3A003A00FF3C3CAFA030300F ++:106A10000035F0350000000000000000000000001C ++:106A2000000000000000F3F00300303000FF000021 ++:106A30000000000000007D28A0A0303F303F3F3C18 ++:106A40000F0000550F550FAC00AC080008AA00005D ++:106A50000000000000000000000000000000FFFF38 ++:106A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36 ++:106A7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26 ++:106A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:106A9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:106AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:106AB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:106AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:106AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:106AE000005492620C44405000000A0600006018F6 ++:106AF0000400040040000400000000000400110035 ++:106B0000000020000400110000010001000102014A ++:106B100004001000040004004100110108400401B9 ++:106B200008822100200004000220030003008404E6 ++:106B30000000202021200420042004080421032038 ++:106B400011052108080104080501040120010401C0 ++:106B5000040120040420840004000008080009083F ++:106B600091080000000080000300000004001000F5 ++:106B700080000100A000840000000000400001002F ++:106B8000A0000000000090000000000890400002FB ++:106B90002010001001000000000020000040400014 ++:106BA0000010020800000008000000800000000043 ++:106BB000208000000080008000800080900000881D ++:106BC00000808282000001080000040200080040EA ++:106BD000000220100480208004000800000005004E ++:106BE000200004000000022120002000000000110D ++:106BF00001201000000000400000800000000000A4 ++:106C00000000402000A00000000000000000000084 ++:106C10000000000000000020218200000000800031 ++:106C2000000080000000000000A000000020000024 ++:106C30001100000000C000000005800000000000FE ++:106C400000000000001000820000000000000000B2 ++:106C50000000000000000000000000A00020000074 ++:106C60000020800000A000C0000000900000000094 ++:106C7000000008208010002000C100004000022019 ++:106C8000000000004080000000000008002000001C ++:106C90000000000090000000A0039009C000001058 ++:106CA000200000102000001000410400022100100C ++:106CB0000021000000100000900900842020024103 ++:106CC000001000000420002000210010002190107E ++:106CD00000410020001000200011001000100008EA ++:106CE00000100010022002100021002000210021CD ++:106CF0000010002101102020000000020000000010 ++:106D00002090000120000000040108010803030195 ++:106D10000008000800900008001000A08004808493 ++:106D200000880041100200040000000000028010F2 ++:106D3000001000C000880010000000100020052096 ++:106D400085020000000203000020001000C00010B7 ++:106D5000840005000300210220004188040820204F ++:106D600000202084204005C109A010100000204010 ++:106D70000084800841100584000800110080000094 ++:106D80000000010008040305900841048404102059 ++:106D9000002010118800840900A1082110001010A3 ++:106DA0001000084108048208088200411005000014 ++:106DB0000221A0200020020000410000000000008D ++:106DC00000002010100084108800008000201000B7 ++:106DD000C00021039003C010C00001000005850021 ++:106DE00000A184A1090309000004000000020000C2 ++:106DF000011000000400C00008001041048800C019 ++:106E00000400040003008802C100200041A000002B ++:106E100003A041000082200003840002090010103A ++:106E200000020200030209044100090402004100BB ++:106E300010000090C10005100000200000001000AC ++:106E40000988200020000000210009002100050021 ++:106E500010002000000002000000000008002000D8 ++:106E60000000208200004100058210000200200185 ++:106E700000000300200090000500410041020100D5 ++:106E800082100108A100C0110400040000000810D5 ++:106E90008204000090000002C00040418408040009 ++:106EA000401020050800A000080282000000000039 ++:106EB000820008000004040082102000000000008E ++:106EC0008200081008000800080000001000000000 ++:106ED000102000000000002100000000000000055C ++:106EE000001010200005000000410005080000000F ++:106EF000010400001041010040000003A041008097 ++:106F000000020240401021000402052021080485EF ++:106F1000001040C1418810110010101010200810FE ++:106F20002191031000A0211000000000200484081B ++:106F300000100040080000840000030041000084AD ++:106F400000000002080004100500000240C0218477 ++:106F500000000002830209009010001005000040AC ++:106F600080208400040004400000208804400000C9 ++:106F700010880501A0838800034121A00241020876 ++:106F800008000221000000000000A1020080101093 ++:106F9000A10400090020A0000004000088000800EF ++:106FA0008800400200000400A00800099000C120F1 ++:106FB0000500A0099020A0000211A0208820000058 ++:106FC00010000000000000000000000000000000B1 ++:106FD00000000010C009080088000420820510038A ++:106FE0009021040005210120210304108500A00840 ++:106FF00000000000000421042008000400000140FB ++:1070000000000000000041000020000080109040BF ++:107010008040214003080010200005840002038402 ++:10702000090210000000000100010240000400A05D ++:1070300000040010008402100010008400004100D1 ++:107040000200410800008000100000000000040061 ++:1070500041000010080020889084211000C000909A ++:1070600041000000101009A0410041080420104018 ++:1070700080A0801080044100108441C010102100C5 ++:10708000410005C02008004082000000A000040567 ++:1070900004000480A0910005A000A10508410003A0 ++:1070A0000000C041880890090040044000000880AA ++:1070B00040000880A0000811000000118800A00016 ++:1070C00000000010000000C02000000000000000D0 ++:1070D00000410000000510008200020000100009BD ++:1070E00000000005080000000000002000000180F2 ++:1070F0000041200020052080000000100000002139 ++:1071000000000000100500008388001083A01040DC ++:107110001008100904419111A1A1894008414009BA ++:10712000110300041111830511090021000010044E ++:107130008840000910080808000080004000000096 ++:10714000000000000000000000800482028910108E ++:1071500041C1820302400805100910032004030501 ++:10716000400440090020C002110900808800888086 ++:107170000000000400090500401103400010001049 ++:107180000910089004C1004041108983A084A00523 ++:1071900089030100C101C00110001189A108820901 ++:1071A00000000000C0000000890001000001000094 ++:1071B0000100820040010001010100000200010005 ++:1071C00000000000000000000000000000884009EE ++:1071D000419001110401000191010000010103002F ++:1071E00000010000C10084010301000000881108B3 ++:1071F00083080010000000010000000001010000F1 ++:107200000000000101820084208801080101900231 ++:107210008900011002A00388A1858500108200A0CA ++:1072200088C18900A000880810010484C100C00042 ++:10723000C00404100400850041030984000000001C ++:107240000000000001820000000000010000820137 ++:10725000400490888988830108008888018800009C ++:107260000000010000211001A00882A14085080152 ++:10727000820088101010C000C0089000C1000100FA ++:10728000010800010100880040C0100090C01120DA ++:107290000008881020898980880088088940911119 ++:1072A00000809108090003044000890540A1020202 ++:1072B00084000900911040050800888809800000BA ++:1072C0000000000000000980090000000009000023 ++:1072D00004030200029009004010040004804108E9 ++:1072E00002050800410005A0000200800005009092 ++:1072F00000020000808000004000088000040900B7 ++:1073000040004180100809110402020880080200B0 ++:107310004104008402888880080840100009881011 ++:10732000000088C0800911C01182000805024008D1 ++:10733000080000114100200308110008000908900E ++:1073400000000000008000000000000000000000BD ++:10735000000004400090000900800904009100042E ++:107360000590024000A004918520112100080084AE ++:1073700021400080808008000080088800904089BB ++:10738000888803080009100940400540000289046C ++:1073900041100082820290A0418801030005001183 ++:1073A00083110088A002A0010889001000110108C3 ++:1073B00000090100000101000101010400C100C138 ++:1073C000A01100080084001000020000000000006E ++:1073D00000000000000188088889008800900008EB ++:1073E000004001890121004100A08901001000A096 ++:1073F000001040030010100883100088014000C0F6 ++:107400000041888209000000010101000000000124 ++:107410008400010188110800900111820110010906 ++:107420000100004085418890080008088308830116 ++:10743000080110820801A020020188888301110838 ++:107440008400028200200000000000000000000113 ++:1074500000000000000009108902100088001001DF ++:107460008889C00000C088C0081108000400830596 ++:10747000852084004088110808828200C004010130 ++:107480000008000101A1010000A000000000A00010 ++:107490004108A000034005824104C003888009C060 ++:1074A0001010080808910904C040110400008391DD ++:1074B00005048908C18080400082002000008910F6 ++:1074C0009009804040800080000000000000000023 ++:1074D00000030011000000008909A0908400000052 ++:1074E00080100090801100000000800480080000DF ++:1074F0008390050084008300898400000000000060 ++:107500000902000904044041090010911108080013 ++:1075100010114002400920008100001300000650B5 ++:1075200000810021C200005081810013C2000000D0 ++:1075300000000000C200004100840000840100003F ++:1075400000880006C200064800000000000000009D ++:1075500000000013C2001100000081810013C2006E ++:10756000420011000013C20000000A000013C20014 ++:10757000000000000013C2000000120000134800C9 ++:10758000008100420013C200000000840000C2001D ++:1075900082000000001384000000EFE32F236E0C34 ++:1075A0006E0CFFFF0000FF03FC00FF660066FFF0AB ++:1075B0006F60FF0F6C6CBD24BD2400000000666688 ++:1075C0006060FF7E007EFF00FF0000000000000002 ++:1075D000000000000000000000000000FFFF0000AD ++:1075E000FF00FF000000000027FF273C0000000014 ++:1075F000F7F4C7C4CF0C7E7EBDBD6F090000FFFF4E ++:1076000000000000EFEF8080FF00CFCFFF3F003091 ++:10761000FF00FF00FE6EF86804082010ECE02C204C ++:107620000C0C0C0C1EFF1E00FE02FE02FF0F000FD2 ++:107630009F900F00F0006C6C9F9F060600000000FA ++:1076400000006060FF7E007EFF006C6C00000000A8 ++:107650000000000000000000000000000000F9F041 ++:107660000900BF26BF260000000027C32700000036 ++:10767000000037340704CF0C424224246F09000075 ++:10768000FFFF000000006F6F0000FF000C0CFF6F99 ++:1076900000607F1976109E0E980802014080FFFF5F ++:1076A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA ++:1076B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA ++:1076C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA ++:1076D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA ++:1076E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA ++:1076F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A ++:10770000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 ++:10771000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 ++:107720000038F5920C44405000180A060000F0BEE4 ++:1077300090F6BDBD0000000000FF00FF0406FDFF45 ++:1077400066F03CF08199E7FF00F00FFF300030F069 ++:10775000E724C3000000FFFF00FF00FF0000FFFF61 ++:10776000000000000000000000000000C2C2C2C211 ++:107770000000003C033F040CF7FF427EFCFCFF3C92 ++:1077800066F000FF3C3C90BDF6BD0F6CFF6C000046 ++:1077900000000000000000000000187E99FF191989 ++:1077A0007F7F666666660700F7FF16761F7F08080C ++:1077B000000090F624247E3CFF3C202FE0EF0400E4 ++:1077C000FDF966F03CF00018667E363636363060DD ++:1077D0003060242400000000FFFD023EC2FE060CC3 ++:1077E000F6FC000000000000000000000000E6E6DB ++:1077F000E6E6000000FF00FF040CF7FF427EC0C079 ++:10780000003C66F06666F0F09024F624006CF06CA4 ++:10781000000000000000000000000000187E00666C ++:10782000101076766C6C606F0400F4FF107019799C ++:107830000000000000860CC001880080008600F572 ++:1078400000B0000000860094018000000586006002 ++:1078500008B000050086006408B20080008600754C ++:1078600000B000000086006000B0000000860060EC ++:1078700008B000000000008600940180000000862F ++:107880000AA00980000500860A7109900005058696 ++:1078900000F108B000050086008009800000008625 ++:1078A00000750010000000000014000000000086B9 ++:1078B0000CC100B80000F5F4F5F4C3C3FFFF0000ED ++:1078C000000020300000FEC2FF000000AFAFAFA0FC ++:1078D0003F3F153D97BFFF3CC30000000000FCC0C8 ++:1078E000EBEBC4C7F4F7000000000030A0B00000CC ++:1078F0000000000000000000BE14FF000A0AFFFFA5 ++:10790000F5F5F5A002433E7FFFAA3CF028000FFFEB ++:10791000FA507D7D0505F5F53C3C3C3C0000FFFF41 ++:107920000000000000FF1E1E00000000000000001C ++:10793000FAFAFC0C00000000F5F4F4F440437C7FFC ++:107940000000000000100000FEC2FF001010BFBFCA ++:10795000AFA03030012983ABE8E8E8E80000000080 ++:10796000FCC0282804073437000000000030003035 ++:1079700000000000000000000000FA50FF00000AB4 ++:10798000F5FFA0F5A0A002433E7F00AA3CF028002E ++:1079900000F0FA502828303F303F3C3C2D28400072 ++:1079A0007CFF0000000000FF1E1E00000000000021 ++:1079B00000000A0AFC0C00000000AE04FFFF00FFFC ++:1079C00000FF0000000000000020FFFF0000287DF5 ++:1079D000AAFF0000000014BE14BE000000001ABA86 ++:1079E0001FBF00000000707C737F000000000000DB ++:1079F000000000000000000000000000FAFF0A0084 ++:107A00000F3C003C000000003C3C3C3C00000000FF ++:107A10000000000000000000503F5F3FFEFE00003D ++:107A200080BF00FF000000000F000FFF00000000FB ++:107A3000000000000FF03C3C03FF10DFAE04F0F04C ++:107A40000A0A0A0A00000000000000005F0F500050 ++:107A500000FF00FF000000000A0A5F5F0000000056 ++:107A600010B015B500000000404C434F000000006E ++:107A70000000000000000000000000000000FCFF0B ++:107A80000C003C3C3C3C000000000F550F55000032 ++:107A90000000000000000000000050305F30FFFEDA ++:107AA0000100003F00FF00000000553C553C000075 ++:107AB0000000000000000FF0000000FC10DF0400D8 ++:107AC00021009100210091000300020080002100AC ++:107AD00040A0850082001100A10280040400030080 ++:107AE000040005001100110021001100110204A181 ++:107AF000A0010400040002002190000804000040DE ++:107B0000210005002188020800010400840204000D ++:107B10000000040003000320080011000000200002 ++:107B20000300840083008204839002A0200184006B ++:107B300000081120040404000200000000000400FA ++:107B400001002000200020002000000000000200B2 ++:107B50000000010040002003000040802080080059 ++:107B60000000000000000000000000000000008095 ++:107B700001200404830041002000000020000000D8 ++:107B800000008200000082000580001000002080BC ++:107B9000200000000000C000008000000010200055 ++:107BA000210008000400040004800441901001201A ++:107BB00020000200000002802000000002000000FF ++:107BC000001104C0040004200000000004000400B0 ++:107BD00000000000000002000000000000020000A1 ++:107BE0008005002100C0008400200000000000107B ++:107BF00080000000009004A00000000100210000AF ++:107C0000000000C0000000200000008800010040CB ++:107C1000000000000000000400000000000000015F ++:107C200002000001009000000020000100A00004FC ++:107C3000000000040010001000010000800000009F ++:107C40008040000801000100030004410000011011 ++:107C5000011000000041004100200010821000903F ++:107C6000820040C0C0408820000082210009000935 ++:107C7000A0202010000000100010000800080008DC ++:107C8000A010001000000020A090001000210002B1 ++:107C900000880020A01100200088021000100211AE ++:107CA0000204020800400200001100900020900031 ++:107CB0000090000002A10000021100400010081016 ++:107CC000001002C10091850020851040A000000036 ++:107CD000830091022000800020402000000000006E ++:107CE00003202004A00203C000A000000202C11073 ++:107CF000800380900002118420A00001031005047D ++:107D0000008400000084000041C000000002001058 ++:107D100000908885000000A000C0051000910004BC ++:107D200000102140051041200000802020000901A2 ++:107D3000201004840011008820002000208820A04A ++:107D400000820008418200402000052082000521B9 ++:107D500000212041202105054000C19001418211F0 ++:107D60008402C002C1A121108221000000109040B5 ++:107D70002000400440000040900011101004001149 ++:107D8000C0109002000082000000840010008400F7 ++:107D9000A000000020021000084010410000100464 ++:107DA00084800021880000050000020320C14111E9 ++:107DB0008408011001050004C000C1411102C10086 ++:107DC000010500410000C0090804100011108000E6 ++:107DD00021000400418202002001108210000000F6 ++:107DE000400021A01040200004000020028808006C ++:107DF00010004100050000000520200020000500C3 ++:107E00008400100003002100200000002001020176 ++:107E10002001000120C0200004A0210008880500E6 ++:107E200000000000104090041100100510008800B0 ++:107E300010001000200010001000020000001000D0 ++:107E400002004100800000004140020000000010DC ++:107E500004000800010900090905092090008404B4 ++:107E60000803C109820004200103010904009009EC ++:107E700002002141004110001011008301000000A8 ++:107E800004202141A000000000008200000010201A ++:107E900001200820082083000009850000058211C8 ++:107EA000A0000000000802052085A00300C0820099 ++:107EB000040010090000010000410800011000004A ++:107EC0000000A0030808400800000880C100050069 ++:107ED0001002212009011088112041004100C188B1 ++:107EE000110002004100038840419020000300007F ++:107EF0004182100200111000101041892120100150 ++:107F00002002200210028000100000200901000061 ++:107F100003000200109011004084414003C0801013 ++:107F2000008804020000000220024100409041103D ++:107F3000024083894002402004400204001004A152 ++:107F400000C021000000808421001008020210847B ++:107F50000010002110809040000300210400040064 ++:107F600020410010404100119005910220100004B2 ++:107F70008400C01000001040C02140210004000017 ++:107F8000820401000100000204000010400000040F ++:107F900000804005000000000002400000101009B1 ++:107FA0002002C000820010080003C00884104000B6 ++:107FB000840202004002000200000405418000002B ++:107FC0000020200000000240040900001011C11030 ++:107FD00000000400210004000510041083A010908C ++:107FE0000910098409880210048410001184050016 ++:107FF00008001010090411C00800100210841000BD ++:1080000009C002100382028420840500411005018A ++:108010002190000000000500418405844182020493 ++:108020000000400111402000414010C0050109013D ++:108030000000021100C00000110004000004200034 ++:108040000000000021880500210021C010004184AB ++:10805000020105100100100001008200010004006F ++:1080600000000021024000002108A00300400000A1 ++:1080700000410840A00084030440841188C08800A7 ++:10808000200000218400C009C0008300000000001F ++:108090000040000000C0000000000000000010418F ++:1080A0000010001101408400C00500000000821093 ++:1080B000000400000140C010100090080100008082 ++:1080C0000140840084050000100000400000000012 ++:1080D00000000040100040200009C0040809090207 ++:1080E000894089040041008340C1004100880308A1 ++:1080F0008805400510200000008020000080030358 ++:108100000040000940080289808202A005020305A0 ++:108110000084000410040000000000004100000082 ++:108120001083804040044100020200090008050855 ++:1081300008080011100203080000000040000000C1 ++:108140004008000905084000111100090004040856 ++:10815000080080000400080001000801050001007B ++:1081600000000501A100000100110008002100022B ++:1081700008004100010000010004C01001100010BF ++:108180001101000000000001C188C0028205000446 ++:10819000090100C00008019000000000400000003C ++:1081A0000000001140000140000801010001000131 ++:1081B000000008008800000001000000000001002D ++:1081C0001000000008014001010000000001000152 ++:1081D0000101C100C00000000100000400C00190C6 ++:1081E0000101A0104102A0C0A10082004100400492 ++:1081F000A182C100C0A02101C10008000800400008 ++:10820000090003000310A1001100A000401089A183 ++:1082100005A0C00085081101A000000000020000B8 ++:1082200000080104010088C0104083C00000000065 ++:10823000000801000500000903208200A001A00140 ++:108240008800C00109C0A088091108110400C18874 ++:108250002100410011081000A100830000801100DE ++:10826000210809400980C0800010094109119000CF ++:10827000898503800800030841020300090000000B ++:1082800004002000C0000800024003000900C18073 ++:10829000A0200904000020008540000200000084A6 ++:1082A00004000000080002091000094183000300D7 ++:1082B0001000080009001100080302118800402086 ++:1082C0000908890010089011910021089089000088 ++:1082D000880004400903208009000200901000007B ++:1082E00011880009400909C0408800090989001067 ++:1082F0000040004100032088008204C008110000F3 ++:10830000800000800080200900400084008308096C ++:1083100080410009408202200010C0204008000077 ++:108320000000400000000000411080408080008379 ++:1083300010100008090989900888008208050004C7 ++:10834000000000800200008008C02183000900C0F6 ++:10835000080800402009008000020020059000036A ++:10836000009000090011A104000500880085100498 ++:10837000A0001000A0000001014100090084054098 ++:1083800000028204C08400400140000000840041DB ++:10839000000840C00011018801011000A1018901FD ++:1083A000000000900190008288080009088810A051 ++:1083B00004090000000100010289000800C10089D1 ++:1083C000408800A000C001C04088010501040021D0 ++:1083D0000803010100010001008800040083010975 ++:1083E00000100100000800000001010100A00100D0 ++:1083F00001888541881082C00502010501840000C2 ++:1084000001100010000100000090010100A0000018 ++:108410000010090088A004000310004101000100C1 ++:10842000000200001002040102000400850002A006 ++:108430000201A008000000C1000100000100008846 ++:108440000000000802918820C000400109010803D3 ++:1084500004010808010000080001000000040001F8 ++:108460000001001009000484090900090921090913 ++:108470004004408083C040C0000920004110100427 ++:108480000240080000C00004000400000340104047 ++:10849000080011000900C104020290001140040804 ++:1084A0001000080000008000000800050000831094 ++:1084B00040101010048000000088004000000200FE ++:1084C0000211040008800003808000400008890336 ++:1084D0008008080580800904101000400900009100 ++:1084E00000100002000000420021C2000000004213 ++:1084F0000021C200000000000000840000600000B5 ++:108500000013C20000000000000000008200000014 ++:1085100000818400420082410013C200000000007C ++:108520000013C20011000000000000130000000052 ++:10853000000000218400000000840007C200000049 ++:10854000008800008400824100000013C200210066 ++:1085500000410013C200060000840004C2000000B5 ++:108560000000000000000000F050FF5F555500FFC4 ++:1085700070007FFF025700FFFF55003C000F0C0CFE ++:108580001C9E5DDF000000000000000000000000F5 ++:108590005F5F287DF0FF5C5C8000FF7F80FD00FF57 ++:1085A00014051405C3E800E8000000000000000006 ++:1085B00000003C550FFF0F0F5C5C0000000004F74B ++:1085C0000CFF0000808013933BBB00000000000004 ++:1085D00000000000FFFF033F00FF00003CFF00FF22 ++:1085E00000FF00000000555500FF00500F5F0F0F07 ++:1085F00000FF20002FFF025700FFFF55003C000F37 ++:108600000C0C088A49CB000080000000000000002C ++:1086100000000A0A287D000F5C5C00007F7F007D5F ++:1086200000FF55005555FFE83CE800000000000041 ++:10863000000000003C550F0000005C5C00000000E2 ++:1086400000F308FB149600001B9B3BBB00000000DE ++:10865000000000000A0A0A0A417D00FF41007DFF78 ++:1086600002570257000000000F0F3C3CBF83BC8044 ++:10867000FFFF00003C3C3C3CBFBF0101F0003F3F1E ++:10868000BEBEFA507878FF550000000000000000E0 ++:10869000FFAAFFFFF03CFF00FA502828AAAAA8A8CA ++:1086A000FFFF00000000FF785F505F5000000000F7 ++:1086B0000000FFFFFFFFFFFFF000BEBEFCC03F3029 ++:1086C000AFA07FFF20A000000000141F14140000C2 ++:1086D0000000FFFFF3F3FF00FF00FF00FF00FF00BB ++:1086E000FF0FFFFF005500000000E0F02000BF83F7 ++:1086F000BC80F5A0F5A0787D7828BEBE0000F00013 ++:108700003F3F1414FA507878AA00000E0F040000BE ++:108710000000FFAA3C3CF03C0000FA502828AAAA1E ++:10872000ABA8FF3E0002FFFFFFFF5F505F5000005D ++:1087300000000000FFFFFAFA00FFF0008282FCC098 ++:10874000FF00FF007F5F2000C3C300C0141F14148C ++:1087500000000000FF3CF330FFFFF0F0FF00B4B476 ++:10876000FF00FC0CFFFA00500000000000000000B9 ++:10877000008600F500B00000008600F500B00000A3 ++:108780000886047008B2001000860C7000B000105B ++:108790000086006000B00000088604710892001096 ++:1087A00000860094018000000086004000B00000B8 ++:1087B00000000086006100B000000886047008A276 ++:1087C000001000860074009000000086707408B8E5 ++:1087D000000000865031A8800085008600F500B0BA ++:1087E000000000860075009000000086006000B860 ++:1087F0000000000000003434202000000000FFFFD3 ++:10880000FFFB00FF00FF000000000000000000A0D0 ++:10881000A0A00000000000FF00FF0000000000C357 ++:108820003CFFFC0CFF0F0000FFFF000000000000F9 ++:1088300000000000B2B2FFC30088004438381010B6 ++:1088400045C76DEF00000000FFFF000000000000C2 ++:10885000FFFF5FFFFFF28F823075FF75FFFFFFF3B1 ++:10886000FF0F553C00000000FFFF0000000000006B ++:108870000A0008000000000000F500A00000000051 ++:10888000FFFFFFFF00C000800000000000000000AC ++:1088900000C0C0C000000000007F00FF000000001A ++:1088A00000C33CFFFC0CF000024302430000000048 ++:1088B000000000000000B2B23C0088004400FA0052 ++:1088C000500004862CAE00000000FFFF00000000F6 ++:1088D0000000FFFF5CFCFFF28F823075FF75FEFE2B ++:1088E000FEF2000F553C00000000FFFF00000000FA ++:1088F0000000000008000000000000000000000070 ++:108900000000FFFFFFFB00FD005DFFFFFFFF000019 ++:1089100000000103C1C300000000000000000000CF ++:1089200000001E1E55FFFDBCC180353500FFFFFF56 ++:10893000FFFF0F35FF3500000000000000000000C1 ++:10894000F5F57D7D050F0A00000000000000000025 ++:1089500000000000001400410000000000FF0F0FA5 ++:1089600000000000FFFFFFFF0000000000C33CFF0D ++:10897000000000001400AAFF00000000000000003A ++:1089800000000000FFFFFFFF00A800087FFFFFFFBF ++:10899000000000000100C1C0B2B2BE8200001000A1 ++:1089A000000000001E1E00AAFDBCC180353500FF7E ++:1089B000FFFEFFFE0035F035000000000000000063 ++:1089C0000000A0A07D7D0A00000000000000000063 ++:1089D00000000000000000140041000000003CFF07 ++:1089E0003F3F000000002DAF7DFF000000000C0C99 ++:1089F0000C0C000000001E0A00552000A000A10081 ++:108A0000050000A004010420000000080482030007 ++:108A1000000004400400840084820410040000C0AC ++:108A200040088000000005002002040090080200B9 ++:108A3000200002002000028820080000040000003E ++:108A40000204200020C02000200084002004200018 ++:108A50002004049002102108041004100210A01039 ++:108A600020002000020002C0840940100000030022 ++:108A7000210184A1040000108240020121000500B0 ++:108A80000400A000000000202080200004800000DE ++:108A9000000020009080A000040010008210000060 ++:108AA0008400038020000000000000800100059089 ++:108AB00020000300020000000000A00000000000F1 ++:108AC0000000000000000100010091002100018071 ++:108AD000010000800000A00004002000020001004E ++:108AE00005009100000000000000100804000000D4 ++:108AF000000004400210001000000280212040000D ++:108B0000000000C009C00000000000080008800349 ++:108B1000000100000000008303080001100083042E ++:108B200080088082402100880200029104018000B8 ++:108B3000000000000002000000000000000000C073 ++:108B40002000A00000010000000100000000000063 ++:108B50000000004100000001800000000000002033 ++:108B6000000400010204800400200020000300082B ++:108B70000000114000000010000000000090000103 ++:108B8000000000000000000084000041909004C13B ++:108B90001040000200200010000890C10002830075 ++:108BA0001080028040100040A010832190400140BE ++:108BB000202100410010909000210200002100417E ++:108BC000000001100341000400419040900000208B ++:108BD00002110011008400080040200000008800FD ++:108BE00000080088000401C1029002A1009002A0C8 ++:108BF00000880011009000100090901002410008C1 ++:108C0000822004004100100400C000C00000412187 ++:108C10008802050080000000008280400040102093 ++:108C200020000082000000000402009000081002F2 ++:108C30001004004000A041A004C000820208408847 ++:108C4000008200000040030011900904001000029F ++:108C500000100410008410844008A00105010910D0 ++:108C60000000000840080082030804000091000092 ++:108C700004C08088002003C00920002005C085C0F2 ++:108C800002009020010084419080840500050011BD ++:108C90000082041084000208841082000282820292 ++:108CA000080209020002001008001090000800826B ++:108CB00008108590820010001005A121102010805E ++:108CC000100010020000402100410800C090840004 ++:108CD000201010001041C0418410C010050484040D ++:108CE0000041104100211005002100050405100875 ++:108CF000100002000210A090004088C100A10000F6 ++:108D000010400141408000100400410003000500B4 ++:108D1000201000C002002000A00002208500A00357 ++:108D20000210020184400201800010000388020446 ++:108D30000003008309102000020020400404050104 ++:108D40000500850091000000040041004100000082 ++:108D500000000300000000000800000020400800A0 ++:108D60001000030108008501090302001000100033 ++:108D70004100000041004101030002000301200006 ++:108D8000100290012100C1000091002140008205E5 ++:108D900090050005000300210521110010C00421E9 ++:108DA000108440838310048903202000042088114C ++:108DB00004800484020404918510840809000921B8 ++:108DC00008020800104140000000011000100800D7 ++:108DD00084000000C000000000000010C00011214D ++:108DE0000808A000C010010910200884824010006B ++:108DF00011000010000000100020000009210008F0 ++:108E00000121C0A1100800001000000200000000B5 ++:108E1000201010A040820484000084020410080284 ++:108E20000540904004402102411000004100C1C0B3 ++:108E300005C02120104010200084000000A1000087 ++:108E400000C000000002408208000000410810023B ++:108E500003100801801008010200038400000000D4 ++:108E6000098404A011840408058209020010081076 ++:108E7000001009841000218404202090000041206B ++:108E80000984214021A0841041028420902184097A ++:108E9000A0210103841088000400C000111041408B ++:108EA0004088048003900180000004000040000915 ++:108EB0000208A02000C090004180022100050008A7 ++:108EC0000041C00084000041004100050040000056 ++:108ED00000024000000420002004C0008441100073 ++:108EE00082008400A1100000010800054005044034 ++:108EF00004000000840391009040028341020000BE ++:108F000000910400048002001020401003804108FA ++:108F100000000000004021900420034010000008E1 ++:108F2000089010902082900920002011080480846D ++:108F30008001822182042184C14000000884080449 ++:108F4000080404040084000104850283C1100000A9 ++:108F5000040004002000020000044084110002000C ++:108F600010040000080004000088C11103892121B9 ++:108F70000084000004841084210880A000C0000246 ++:108F800010001084000008840300020920910408E6 ++:108F9000200000412010C005000000000000A000DB ++:108FA00040A100000240850009A0010083082004C0 ++:108FB0000800040805040989A0001020020500002B ++:108FC0000080A0000380C000842000200220040054 ++:108FD0000040090000008400000000C10000020001 ++:108FE00000000200100008002121000008201020CD ++:108FF00008A000210005000001008280040000009C ++:109000000080C0000021C00001000000118810088D ++:109010000209208400092040090811000000000016 ++:10902000110008850483411041A04085C00491A12E ++:1090300020881003C04002C0000809030008090886 ++:1090400003088283C10591410310000300208020A2 ++:1090500000200000080809200041080802100489C7 ++:1090600000C104A00280808902082020008088803E ++:10907000A080408002008400100009800303A11139 ++:109080008502081008000000100003000003891189 ++:1090900041410341C0882083821100110400000077 ++:1090A00000000000A185891020830110018308A021 ++:1090B000C008911002A1831020C000050001040126 ++:1090C000A0000101058908C0C00201C00001000024 ++:1090D00010000000000089010101000100000203EE ++:1090E000000300110009010882110000000800823D ++:1090F0009090A08800040082104000109088090120 ++:10910000400010010001A0008800010000000001E3 ++:10911000100000010000040182088804830100009F ++:1091200001400191000021200401092002010221D7 ++:109130008810C0908241890588A0402182020221C6 ++:1091400002009040100083001110884003020002CA ++:10915000000000040000000001080108000101C037 ++:109160000800028411110201010100100008011021 ++:1091700083019108118820C11001100109A088887D ++:109180000010018801C00101008284009082908853 ++:1091900088004100210011A00402080085418905D2 ++:1091A00011004100080211400580092005820510C8 ++:1091B000899040020405908311C0088310829103B6 ++:1091C00020C085410380C10520028480C1C109807F ++:1091D0000000000000000000000008C14100400243 ++:1091E000098882008400A141050910400080080818 ++:1091F00009801008880085894091C008C02020801F ++:10920000C002038021002040052000C08000000033 ++:1092100080821109400010001000058200040089BE ++:109220000808000810400008804089402002A188FA ++:109230000808839120409040A083900910A1A1804C ++:109240009000C04021040284C00409000005088980 ++:109250000389202004404100410000000840002014 ++:109260000009202002410004008900A02000002005 ++:109270000089888800108083809080A08088800387 ++:10928000834100051188210500A0111180110010F3 ++:109290004008000811C000050008109000200408D4 ++:1092A000A0A10905000000000001820120C08984FE ++:1092B00010859005204010C141C0028305A0C1085F ++:1092C000040883A040C100C0018420200002A085C2 ++:1092D00005050188000000000000030000000100F7 ++:1092E000000000010000000084C00485A0110000FF ++:1092F000C0880203041000098810A0A18883408957 ++:10930000104009824010004001030041208404A065 ++:1093100000020110C004001100110009004104887E ++:1093200089A00000A082010001000000000003905D ++:10933000002000880010850102A0A00008408341A1 ++:10934000A140A021054082C18841080008101111E8 ++:109350008941100020A00000004000000000000033 ++:10936000110010901000C000011000A101010004C4 ++:10937000850008904001A000838410828201C1888A ++:1093800000419005C00100C1010201080100010077 ++:109390008200C082040008C1A00104C1C00088404E ++:1093A00004898409090909801000080809091000C6 ++:1093B00083110409108941408341C18504020400DE ++:1093C000839008880282890080908010800200804B ++:1093D00089A0A0A08509890000000000000000000D ++:1093E00000008900C0088840110009A00441212024 ++:1093F00003808900C040A00820008588918020104B ++:1094000040800083004100100008038010A1020387 ++:10941000080080400000000080408010800580042B ++:10942000800006600013C20000821200401300009A ++:1094300000420A500013C200000082410013C20023 ++:1094400000840A500013C2000A8282410013C20045 ++:10945000006021840013C2000041210000130000BD ++:109460000000000000600021C200000000880081B0 ++:10947000C200000000600021C200060000000021C0 ++:10948000840011000A004021C200118800500081B0 ++:1094900084204100000000218400420000000004FC ++:1094A00000000000FC0CF6063636FF0000007E18B7 ++:1094B000BF2600009F0640C1662666209F9F9F3CF6 ++:1094C000FFF036366F60FCFC3636363600000000A2 ++:1094D000FFFFBFBFFFFF0000FF00FF6600000000AE ++:1094E0000C0C0C0C0000FDFF04069F06BD24FFFFC2 ++:1094F0000000FE98FF00FF7F8101FF00FF00F0F0F9 ++:10950000F0F000033C03000000002D0F000020805D ++:109510002400FFFFFFFF00000000F099301800005A ++:1095200000003FFF3F3FFF00FF00FF00FF00000083 ++:109530001E1EB92000009F0640C166006600060698 ++:10954000063C0F0036366F600C0C3636363600009F ++:109550000000FF7EBF3EBD9F2406FF009F06000067 ++:1095600000000C0C0C0C0000FDF90400FF00FF00D3 ++:10957000FEF80E086E08FF007E7F000166006F098E ++:10958000006000A0000300030000000000000000D5 ++:1095900020002400FFFFFF7F00000000C0810000CA ++:1095A0000000000000CF00FFFFFFFFFFFFFFFFFFF5 ++:1095B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:1095C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB ++:1095D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B ++:1095E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B ++:1095F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B ++:10960000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A ++:10961000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A ++:10962000FFFFFFFFFFFFFFFFFFFF00C02A7C0C448E ++:10963000403000180A06000070DF20BF60FF20E005 ++:109640002FEF00000000080C0B0FF07E000034FF2D ++:1096500000000000FF78FFFF9FFF00000000303097 ++:109660003F3F000000000000000078F93CFF0000D0 ++:10967000FFFF00000000000000000000F0F0D8FC38 ++:109680003020FFEF00FF00FF02BF42FF01FD01FDA0 ++:10969000C300FFFF00000000000F030300000000F4 ++:1096A00006060000FFFFFFFF0000FEFF00000000B5 ++:1096B00000000000F072FF3CB0BF000020BF009F20 ++:1096C0000000FFFF0000000000040307F04200005C ++:1096D0000000000000000078FFFF87E7000800049A ++:1096E00006F606F6080004000020000078603C0042 ++:1096F00000B4FFB400204000000000000000F0F0C3 ++:10970000C0E40020CFEF30F33CFF00BD40FD00FC83 ++:1097100000FC42007EFF00000000000FC0C00000FF ++:10972000000066668090FEFF3CFF00000000000025 ++:109730000000000000006672003C202F0000008640 ++:10974000009401A000000186006001F00400A586DD ++:1097500050F4A1B00085A58650F4A1B90005A586F6 ++:109760005AF4A1B80005A0865AF4A1B0008500867D ++:109770000A940180000000860AE001B800000000A1 ++:109780000086007400B000000086007500900000A4 ++:109790000086007400B00000008600B000000000E9 ++:1097A000A0865031A1B8000505860AF408B000056E ++:1097B0000086003008B0000500860A6104B8000089 ++:1097C000AA00BE140000008000000000000000009D ++:1097D0000000FFFF4040C3C3000A000C5C5CF0FFC8 ++:1097E000F0F0FF00FF7FFF7F3030BE82DFC3FFC39A ++:1097F000FF00BF1540C07FFF000000000000000018 ++:109800000000ACFFAC0F000000000000000000FFF3 ++:109810000F0FAA3C0A0C0505AFAF0000FFFF28A8F8 ++:10982000A828FAFFFAFF000A050F00000000000058 ++:1098300090067878FF5580008000FFFFFFFFFFFF54 ++:10984000FF55AA00BE140000000000000000000048 ++:1098500000000000FFFF0040C3C3A0AA303C5C5CD6 ++:10986000000F3C3CAAAAFFFF7F7F3030BE82DFC3DF ++:10987000D7C3FF00BA1000803FBF00000000000007 ++:1098800000000000ACF0AC00000000000000000090 ++:1098900000FF0F0FA0300000005500550011AAFF77 ++:1098A000A828A828FFFFFFFF0C0C0C0C00000000EC ++:1098B000900600007878AA0080800000FFFFFFE893 ++:1098C000FFCFFFCFFF5000507D7DF0FF0000000074 ++:1098D0000000000000007F700A0A00AAFFAA3C787E ++:1098E000553CFF0FFFFFFFF00000000000000000EC ++:1098F0001400143CFFFE00C200FF00FF0000000047 ++:109900000000000000000000000000000000100047 ++:1099100000000C7DCF7D7D287D2800000000FFFF2A ++:10992000000000000000BE00B40000343C34000021 ++:10993000000000000000000000000A0005500000C8 ++:109940000000553FFF3FFF1400147D7D303F0000B5 ++:1099500000000000000000002F200A0A282800AAAA ++:10996000F078553C000FFFFFBEBE00100001000064 ++:109970000000000C000CFF7C0040407F00FF000056 ++:1099800000000000000000000000000000000000D7 ++:10999000000000000C41CF41FFFF555500000000C2 ++:1099A000FFF000019C0000001E00140000043C04B5 ++:1099B00000000000000000000000000000000000A7 ++:1099C00000000000FFFFFFFF000021400002030035 ++:1099D000040004840400110800000408044011007D ++:1099E0001100040004080400110004081108040018 ++:1099F00003900308000041900482041003900408BF ++:109A000000900420040804A00000000002A085A02B ++:109A100004A020008410830004A020A0840004047B ++:109A2000911002000400041020081108820884002C ++:109A300004A0201021100400209011000090844008 ++:109A40000000049000000400110000000080048069 ++:109A50000400000000000000908000000100218050 ++:109A600020000000000000000000000000000000D6 ++:109A7000000084000000000000000100010040051B ++:109A800021000000A0000080200000000400000071 ++:109A900020000100050021002000000083002000BC ++:109AA0000080200000009100A100040002000500D9 ++:109AB00021008900080002002000A1002000900081 ++:109AC00010800000820000008200200000000010D2 ++:109AD0000020000000000000000000408020002066 ++:109AE0000000801000000001210080402100804023 ++:109AF00080200000000000000000000100200001A4 ++:109B000080110011000000000000000000C00000F3 ++:109B1000000080000020800000058001002000017E ++:109B2000000080008000800100010001800100042D ++:109B3000000100010004000080000000001000008F ++:109B40000200001080000000000000000200000081 ++:109B5000000000000041002100000021009004A04E ++:109B60000090821004200005000888100490A005D1 ++:109B700040C140000021004100100010004000A141 ++:109B80000020042000200020001000100010000021 ++:109B90000000000004100090041100A004200091B7 ++:109BA000C0040021202120210420002000200420C6 ++:109BB0000080040400040491002010110220000819 ++:109BC000001001210002020820000000900801009E ++:109BD000900500040000A040000800A002A0008240 ++:109BE00008108441410800A1009000A00808050267 ++:109BF00011000002090004001102898209A040C07E ++:109C0000408200400000114010000000410041006F ++:109C10000000000420100004208520002000200007 ++:109C200082100008040400C08004000800400900FD ++:109C300000C0402080200020042011000000098482 ++:109C400084C0000000A00200001021100910801044 ++:109C50000984118800800000219000C1C008C02143 ++:109C60008208000810081000C02084000010008244 ++:109C700090118400C005A040C110000920211040AF ++:109C8000C0000010C00884000089004100210000CD ++:109C900000000000008011000880910801050140CB ++:109CA00001402021C0410080001004800000C0213C ++:109CB000A005000204834080008000899040820358 ++:109CC0000008040510410010910882090000C0112D ++:109CD00002210041A10010000582880003820400D7 ++:109CE00041000500050003820509C100114005205F ++:109CF00000402100002004084100039020A0080338 ++:109D000020031002020202024110210221000390EE ++:109D100002C083000000A00104010001C14000C195 ++:109D200010042004800410900000090080A00000AE ++:109D3000904010C00020040008002000200005A072 ++:109D400020A0410010400300098208404100A1000A ++:109D5000100003001020100001000000044100006A ++:109D600000102000100084000000002040000000CF ++:109D70000000A000880000C0088082008400C000AD ++:109D800000C00090208000801080104100800010F2 ++:109D900000030000040000000520012000202080B6 ++:109DA000C0200080828004C00000C00310030203B2 ++:109DB0000000401100000080C100104000001100B0 ++:109DC00000001000840000008200100010800800D5 ++:109DD0000204000584000090050003C00004100088 ++:109DE000108240A02110414010C010404100038863 ++:109DF000C14041910988088408A0040020002090F7 ++:109E0000004009A00090100003C00000218410024F ++:109E100000080008008805A000000200008400007F ++:109E2000100211A04101A1A000A105C021000482DF ++:109E300005A0030021404100834000C0208402109F ++:109E4000000010104100000000C01000000002419E ++:109E500090004184030205000984A0108200028062 ++:109E6000850000100021400990054040C108C00352 ++:109E7000400820104004000591218500C100010028 ++:109E800089400490102008211010840000118800DF ++:109E90009020008000008200842100C0010510088D ++:109EA00000218821001000042010880400100810F0 ++:109EB0000008042000210408002140080021A10519 ++:109EC00010100003900584050005881001090003A7 ++:109ED00001C0040010000091002108000088032048 ++:109EE00000840888104000C00290410041108208A0 ++:109EF000090820090310098980A01182A00020848C ++:109F000082100040909000400240090120104184DE ++:109F100082024100A10005908505020800000200B0 ++:109F2000050410400040102100044004080510C042 ++:109F3000030410C000A0002000904100002020C0B9 ++:109F400011A0A0820201009020821040029010A077 ++:109F500009840200000000880084040000A00000C2 ++:109F600084000000020000800000000000000400E7 ++:109F70001180829100909000884020030000112001 ++:109F80000141021188034000C0000000821000005F ++:109F9000204140212000020084000802008000408F ++:109FA0000000008000000000C04000800180C088E8 ++:109FB000010000000103100000000000000000008C ++:109FC00001000009020000400000000000008400C1 ++:109FD000000010410100000000000000C00000046B ++:109FE0000285090811081140108005002000410079 ++:109FF00000030004880403200408094009082041E4 ++:10A0000000410040808900118083400002000991D6 ++:10A010000083911041800000828020800080418078 ++:10A020000000000000000400000008800080418063 ++:10A0300010808809800520201008038384A021084F ++:10A0400005A104000000840000000005201080200D ++:10A0500000081100000003000880C080008010008C ++:10A0600003008885058800C00020020889040004D8 ++:10A070000102C0010001A1000001C0008400000035 ++:10A0800000010000004002100000408389A001A0F0 ++:10A09000008800098408910800A088820010908838 ++:10A0A0000102000000040488024000A00310408464 ++:10A0B000A0840184210040000000030104A020C00E ++:10A0C0000508014000049040080000000001010163 ++:10A0D000C00000000088049000A0000408840884E8 ++:10A0E000012001C0110085054184410283019110C6 ++:10A0F00089410810A01010004010848208009000D0 ++:10A10000C000C089042090A0409182080001000096 ++:10A11000009001C01040C000044091A100A0018443 ++:10A120000110000000000102010000A00100010573 ++:10A130000104011100900100018200000100C0082B ++:10A14000208409C1210089C0110105C003C000009D ++:10A15000000400000100090101C000004191080055 ++:10A160008982A0A102029009028488C18889111005 ++:10A1700004804021098441898800038091858011F1 ++:10A1800008104100048388C10041800980841020A8 ++:10A190000005000003830083800000800320080086 ++:10A1A00008004003020000001000104110001010D1 ++:10A1B0002008080802102002080008840420100269 ++:10A1C0002180A0080805C121114089402000C00954 ++:10A1D00041000000002009008810208009001020A4 ++:10A1E0000509040004058380914000201008200424 ++:10A1F000000880A080A000901020200308080840DC ++:10A200008840004104882005A000A1000400080047 ++:10A2100000000080900000830080419080808003D7 ++:10A220000011A002800800050000000002000400E8 ++:10A2300080000010A01021208009881000904008A4 ++:10A2400090080505200485A08841801189410200FD ++:10A25000000010000000000004000020000485043D ++:10A26000800400028000058500C182419040832067 ++:10A270000241400910090884004101C100C0019059 ++:10A280002105414100040184C003030008000100CE ++:10A2900021000290C008880400410084080404845E ++:10A2A000400300008300100108000000A088888897 ++:10A2B00008080488A0890389C02040041189000986 ++:10A2C0000189059000C021031105100982884040D2 ++:10A2D00000829004010000000000A00000820290B3 ++:10A2E0000304C00400044082890804098520A004F6 ++:10A2F000A085A0A0200041908801C10882209085FF ++:10A300001000C0C082208488A001400885401084CD ++:10A310008800090283888488A00004001101C0001D ++:10A32000040088400140010100000000000000100E ++:10A33000008500010000910808852001C10000008F ++:10A340000110010101000184008300010008844024 ++:10A350001009A000C00401000000010001008500F8 ++:10A360004002880084080590051182011182832033 ++:10A3700041100583C100102010100210A0008005BC ++:10A380000005000880008021000200108080830505 ++:10A3900020002000408083800000000084008303B0 ++:10A3A00000001110000003800904030909000000E7 ++:10A3B0000080004000100000108082082010100073 ++:10A3C00003000589200805002091091003080300F7 ++:10A3D00080C18088000300004000080420000800BD ++:10A3E000820040100303C080A0032090031010805F ++:10A3F00000000081810041500000000000000000CA ++:10A40000210000130000005082410013C2000050E0 ++:10A4100006600013C200000000880000C2000000B7 ++:10A420001200001300000A000A00001300000A00D6 ++:10A4300000000A000013C20000000A500013C2000E ++:10A44000000000820021C200820000000013000012 ++:10A45000000000000013C200420000000021C20002 ++:10A46000000000000021000000000000008100004A ++:10A470000048FF1E1E1E4D007D0000A3A3A30C007C ++:10A480000F00000000000FCFFFFF000000000000E1 ++:10A4900028283C3C55550000000000003C3C0000D2 ++:10A4A000FFFF00000F0F00000F0FD7D70CCF287D44 ++:10A4B0005F5F000000000000000000000A0A008248 ++:10A4C0000002000214BE5F5F0500000070737C7F15 ++:10A4D00043576B7F00000000171717171C081C1C40 ++:10A4E000000000000000300004042C2C0003C0C356 ++:10A4F000553C553C001E1E1E410071000000A3008B ++:10A5000004000F0000000000C3C0C3C3000000002F ++:10A510000C3C0C3C00FF0F0F0000000000003C3C16 ++:10A520000000000000000F0F00000F0F14140CCFEC ++:10A53000287D0A0A00000000000000000000000062 ++:10A5400000820002282A14BE0A0A05003C0040438B ++:10A550004C4F02162A3E0000000017171717080874 ++:10A56000081C00000000000000000014283C4141CD ++:10A57000414155553C3CFB3800000000FFFF000006 ++:10A580000000FFFE5554B2B2FFB200000000343CA0 ++:10A590003414F0F5FFF5F0AA00003C3C3C3C3C3C98 ++:10A5A00000003C3C0000FF0000000000FFFF000036 ++:10A5B000000000B4000000000000000000000800DF ++:10A5C0000000000000000000410041000000000009 ++:10A5D0008010CCD0FA005000000000007D287D28BB ++:10A5E00000000000BEBE1414000000000000BE8287 ++:10A5F00000000000003C00AAD3100000000000A8EA ++:10A6000000000000FFBE5514B2B24D00B4FFB4000C ++:10A6100020282000F0A000A03C3C00003C3C3C3C3A ++:10A620003C3C00003C3C0000FF000000FFFFFFFF3F ++:10A630000000000000B4B4B40000000000000000FE ++:10A640000000000000001E140A00C0C0000008083E ++:10A65000F808C2DCC89E7800780000000000FAFA12 ++:10A660005050BE00BA00BEBE14140000000000002E ++:10A67000B2B2000000000C0C0A0AA5865071A0B00E ++:10A6800000050086006000B8000000860AE101B005 ++:10A690000000A0865075A1B00005A58650F4A1B0B9 ++:10A6A0000845A2C75174A0B4494502C701E101B4ED ++:10A6B0004140058600E001B000000000A08650F196 ++:10A6C000A1B00005A18650F5A1B00005A086507488 ++:10A6D000A0B0000500860CE000B00080A08650F01D ++:10A6E000A0B80085008600E108B000000086006088 ++:10A6F00000B000000086006100B0008000F000B0F3 ++:10A700003C3C0F55BEB2000000002AAA3C3CF0F0D1 ++:10A7100004F75457FA0A3F3F00000000BEFA14FA4B ++:10A7200000000000FF0F3A3AA8A8A0AA50C050C0ED ++:10A73000000050F0000000000000000000000000D9 ++:10A74000000001F1000000001010000000000000F7 ++:10A7500000003D0001000000000000C30202FFB441 ++:10A7600055B404043434000000000000000055001B ++:10A77000540004142C3C417D0000E040FFFF00A089 ++:10A7800000A00000000082B2000000002828FF00A6 ++:10A79000AAAA04F75457FA0A303034F520A0BE5064 ++:10A7A000145000000000F0003A3A0808000A55C3AF ++:10A7B0000000000010F00000000000000000000099 ++:10A7C000000000000101000055001010005003536C ++:10A7D0000000000001000100000000000000020273 ++:10A7E000AAB400B4003C003C0000000000000000DF ++:10A7F0001400140000102838407040700000FFFF63 ++:10A80000FCC00000283C2800A220202004F407F708 ++:10A810000000000008280828000000000043C3438F ++:10A82000AAF0AAF00F3C55FF3F30FAFA00000000F2 ++:10A83000F734E320101C3C3CAAFF3CF00000000071 ++:10A840000000040E0404000000007878FFAA000055 ++:10A8500000000000000000000000000C000C5D0083 ++:10A860000800FFAA00AA0000D3DF000000000000DB ++:10A870000000F0AA000055553C3CFFFFFCBCFFFF68 ++:10A88000FFFFAAAA00000A0F0A00820000000000D1 ++:10A8900000000000000008281C3C000000000040F0 ++:10A8A000C340AAF0AAF00F3C55003F300A0A00004E ++:10A8B00000000000000000003C3CAA003CF000004A ++:10A8C00000000000000A0000000000007878550039 ++:10A8D0000000000000000000000000000A0A000064 ++:10A8E00008000800FFAA00AA0000101C00000000D9 ++:10A8F000000000003C3C000055553C3C3C3C3C3CCE ++:10A90000FFD2FFFF210000C0100000002100050061 ++:10A910000500211004100000110011000090040037 ++:10A92000110020C00410880882039000C0108241EA ++:10A930008202A01111A01100000002A0030021C09A ++:10A9400011020300000004000000000004002100C8 ++:10A9500004C004002108030003101100210020009E ++:10A96000211011082000000002020200040004006F ++:10A970001100030440C00400210021000400410034 ++:10A980008400A00484090000A00002000000000070 ++:10A9900000000400900000000000A000A0000000E3 ++:10A9A0000000200004002080218041C009000980AF ++:10A9B000098809A04108A00000009000A100000043 ++:10A9C0002000000090000000200000000200900025 ++:10A9D00002000000000004009000040000000000DD ++:10A9E00004002000820000000000A102010300001A ++:10A9F00000000400048001000000000004002000AA ++:10AA00000000080004802088000000000000000012 ++:10AA100000000000008200000000000000000000B4 ++:10AA200000100000000000C080048009800100A127 ++:10AA30000010800980830000000000000000000179 ++:10AA4000000000000000800400C0000000000000C2 ++:10AA50000000000000C00000000000000000000036 ++:10AA600000000008000000000000000080008000DE ++:10AA700080000000800080000000800000000000D6 ++:10AA8000000000008000000300000005001100002D ++:10AA90000020001000000000000000210010001045 ++:10AAA00000210008000004102010401010C0081001 ++:10AAB0000010008940820440004100110021001074 ++:10AAC000000800110011A0110490000000110208FC ++:10AAD0000010000000000000000000080008000056 ++:10AAE00000088200000800080000000800032000A1 ++:10AAF000401010000010200020000000080000415D ++:10AB000000080041000840080004000000A0000008 ++:10AB10002190410200840010088200C0091000004A ++:10AB20000000050004C005C008A0090082088511C6 ++:10AB30008400000840029004A005A0090010000055 ++:10AB4000000010900000210000000400000000C080 ++:10AB500000C00000008400000000040000000000AD ++:10AB600000000000000800000000000000000000DD ++:10AB700000000900000041880000201100000000D2 ++:10AB8000000003082182100080002084C00100081A ++:10AB90008411C0108441004100051040C041C01123 ++:10ABA00082009021841000210005C011840511C18C ++:10ABB000041021210040028009A041A005C082416B ++:10ABC000000000110000C041C040C00001090000A9 ++:10ABD000840008008200100310008200840300003B ++:10ABE0008820C040A0100000841084218205C0216C ++:10ABF000C0218208C00088080000900009201000D1 ++:10AC0000824100038208C00082000800110810047D ++:10AC100009000000210041000200000003000000C4 ++:10AC20000000000000002100050004001100049055 ++:10AC300002000201A0020000C0001021202110909B ++:10AC400010900000030083010000000000000000DD ++:10AC50000000410010001000200000001100090059 ++:10AC6000090002000000022000000300100005009F ++:10AC700000000300090803100800050000A0C1053A ++:10AC8000020021008000C100050841000200C1014E ++:10AC9000820000000000880000100240040800004C ++:10ACA00040008811821108210200021110110000D9 ++:10ACB0008800010001202111000041202120051001 ++:10ACC00000040004000400001040001110000800FF ++:10ACD0000000000000100000000000000000200044 ++:10ACE00000000000000000000400C0090000000097 ++:10ACF000000000219000000890800000000000008B ++:10AD000004200000000004004000000000000000DB ++:10AD10000420200000100000000005C0000000001A ++:10AD2000031000000400000005C000080900001026 ++:10AD300004080300852088008001A120050020016F ++:10AD4000100182050000110005A0050000100000A0 ++:10AD500000002004000000000020410000840010DA ++:10AD60000000000000A000004100000010000000F2 ++:10AD70001000100010000000000000001100100082 ++:10AD8000080021009011000041A008881000000078 ++:10AD900090112001A1050005001004000440900856 ++:10ADA000C0109005C0020008000500088821C005F9 ++:10ADB00010211008880002850800040810211020C6 ++:10ADC0000120021005880000C04010098211000017 ++:10ADD0000010102011A10000000000408400840534 ++:10ADE0004000100310001021A000A0030020A021AB ++:10ADF0000005C003001084218400081184050000B0 ++:10AE0000000001000008410810001010010084003B ++:10AE1000002108100520108400400082000000A0DE ++:10AE200000100000100010101100030000000900C5 ++:10AE3000040003002184214004030904901141000F ++:10AE40000888900008820803050005C0210400005E ++:10AE500020000000400410880000000000001000E6 ++:10AE60000040000000000000000010001000090079 ++:10AE70001010050000000200004010000008030050 ++:10AE8000000800040200000010000091020200C04F ++:10AE9000031100040884000000000020000082402C ++:10AEA0000000000000008204000088000008040088 ++:10AEB00090412003100010009000919090801008A5 ++:10AEC000042000000821100000A08800880304115D ++:10AED0009020000020000000C000000000000000E2 ++:10AEE0000000A000000900030011A00300000004FE ++:10AEF0000020C00000000000000000000000000072 ++:10AF00000000000800000000201101000010008572 ++:10AF10000009004000008200004010000000000016 ++:10AF20000000000000000000000000000000000021 ++:10AF3000000000000000000000000000808003808E ++:10AF400080C1C1C0808020800082C10483808300D2 ++:10AF500000040341C0008080800203000000000064 ++:10AF600000000000000000000000000000000000E1 ++:10AF700000000000000000000000000000000000D1 ++:10AF80008300008083410000030000418988830022 ++:10AF90000300000303410000030000C1090000009A ++:10AFA00000000000000000000000000000000000A1 ++:10AFB000000000000000000000000000080008A0E1 ++:10AFC000C11008C108C10804014090088384091019 ++:10AFD0001182000401018382820482A10100000029 ++:10AFE0000000000000000000000000000000000061 ++:10AFF0000000000000000000000000000000000051 ++:10B000000082838200C0834190820184024182C019 ++:10B010000988858200010101000201A0C0C1000071 ++:10B020000000000000000000000000000000000020 ++:10B030000000000000000000000000000000000010 ++:10B0400082008408002102820202C10400008441BF ++:10B05000A1838383008303008382858300830104AB ++:10B0600000000000000000000000000000000000E0 ++:10B0700000000000000000000000000000000000D0 ++:10B080000000820088820083000082041182008216 ++:10B09000C004908383820083C10082000382008306 ++:10B0A000010200000000000000000000000000009D ++:10B0B0000000000000000000000000000000000090 ++:10B0C000000000000080002104880080C100001101 ++:10B0D0000983028320840083C100028904A000A0A8 ++:10B0E00008800000000000000000000000000000D8 ++:10B0F0000000000000000000000000000000000050 ++:10B10000000000000000008000830000000082803A ++:10B1100000808000108320A00083C100090082808D ++:10B12000008341000000000000000000000000005B ++:10B13000000000000000000000000000000000000F ++:10B14000000000000010000083A0C0C1000000004B ++:10B15000832120C100020080A00200000040008086 ++:10B16000844180000000000000000000000000009A ++:10B1700000000000000000000000000000000000CF ++:10B180000000000000000002000083C10000000079 ++:10B190000000802011A10040000083020000000098 ++:10B1A000008080808000000000000000000000009F ++:10B1B000000000000000000000000000000000008F ++:10B1C000000000000000000100C0A01005C1000048 ++:10B1D0000002051103C1000500C08383900000A197 ++:10B1E00000C082A1820000000000000000000000FA ++:10B1F000000000000000000000000000000000004F ++:10B2000000000000000000000001008283C1000077 ++:10B21000000000C0828990A1008300828383000027 ++:10B220000000000482A08200000000000000000076 ++:10B23000000000000000000000000000000000000E ++:10B2400000080000008200001111008241A1048367 ++:10B2500011080183A14110880482010101830000CB ++:10B26000C10101830101C083000000000000000053 ++:10B2700000000000000000000000000000000000CE ++:10B2800000000000000000000000838901820183AB ++:10B29000000004400110118304C083820101018376 ++:10B2A0000000400800040101A0C1000000000000EF ++:10B2B000000000000000000000000000000000008E ++:10B2C0000000000000000000000041821080822089 ++:10B2D00000A08280408302C080210489040302838D ++:10B2E0000000820341C04103808300000000000091 ++:10B2F000000000000000000000000000000000004E ++:10B3000000000000000000000000000002030480B4 ++:10B3100041020000008041009082008202900403FC ++:10B320000283000080800000210200C000000000B5 ++:10B33000000000000000000000000000000000000D ++:10B3400000000000000000000000000000000000FD ++:10B350000000124221820013C200124281600013D9 ++:10B36000C200124200000000000012420000000073 ++:10B3700000000000000000000000000000000000CD ++:10B3800000000000000000000000000000000000BD ++:10B39000000000001242000000000000124281483C ++:10B3A0000013C20012420000000000001242FFFF22 ++:10B3B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D ++:10B3C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10B3D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D ++:10B3E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D ++:10B3F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D ++:10B40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10B41000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10B42000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10B4300000D4CDD10C44407000E80A0600006059E9 ++:10B4400000000000000000000000000000000000FC ++:10B4500000000000000000000000000000000000EC ++:10B460000E5E01000000000000000000000000006F ++:10B4700000000000000000000000000000807A7062 ++:10B4800000000000000000000000000000000000BC ++:10B4900000000000000000000000000000000000AC ++:10B4A0000000AEDE00000000000000000000000010 ++:10B4B000000000000000000000000000000000008C ++:10B4C0007B7500000000000000000000000000008C ++:10B4D000000000000000000000000000000000006C ++:10B4E00000001E7BC002000000000000408C07002E ++:10B4F00000000000000030020000000000004003D7 ++:10B50000DE780000000000000000000000000000E5 ++:10B51000000000000000000000000000000000002B ++:10B5200000000000067BC000000000000000008C4E ++:10B5300007000000000000003000000000000000D4 ++:10B540000003DE6000000008110000000400040099 ++:10B550000090030004008300001004000410841015 ++:10B560008401110820080000000820C00004030026 ++:10B57000201004082000A0022020040008910000F0 ++:10B580000004210400000400200020000440800486 ++:10B590002004110020009100000020000409200078 ++:10B5A00080001100030111001100110000002100B2 ++:10B5B00000000400A0A0000000000400200080049F ++:10B5C0001100200484014000000000000000000081 ++:10B5D0000000400000000000080000000000000023 ++:10B5E0002000040400800000000000000000008033 ++:10B5F000000000000180010005804180010001047D ++:10B6000000000080A08000000000A1000000008079 ++:10B6100020800180000001002000A0000000000444 ++:10B6200000000800200000040000000020000400CA ++:10B63000000000000000042100000000A000020043 ++:10B64000048000000080044000900003008200009D ++:10B6500000000002000200000000000000000000E6 ++:10B66000000000000000000000000000004000009A ++:10B6700000010000000000000001000100090001BD ++:10B68000000100000010000000C0000000A08000C9 ++:10B690008000000000000011000400000000000015 ++:10B6A0000000000000010000000000000000000198 ++:10B6B000000000000000000000000000000000008A ++:10B6C0000000000000008000800100210008000050 ++:10B6D0000021000000000000000800000010000829 ++:10B6E0000000000000110000001000210021209047 ++:10B6F000002100020000000000110004000400848A ++:10B700000020002000080080000800000000000069 ++:10B710002010200000000000000400830000000052 ++:10B72000000000000000001020000008000082005F ++:10B7300004400000000000000010000000000000B5 ++:10B740000000040000210000020002200008008424 ++:10B75000050000A002002000110000840010000875 ++:10B7600000000410000041A0000200C00001000120 ++:10B770000885000811C080C005100340C0080420DF ++:10B78000040884040300002141C080000000000080 ++:10B7900000204120910000840000101020000008CB ++:10B7A0000004800000001010008200000010000063 ++:10B7B0000000030000000000000000008004000002 ++:10B7C0000090108200C000100000000000850003FF ++:10B7D00000100000000801000121002104100000F9 ++:10B7E0000000A00589050000000000008241A002C1 ++:10B7F00082020008A08882001000A02100C00580FD ++:10B8000011800380218800000090000004000000E7 ++:10B810000000008500800400A000C0400400C100BA ++:10B8200000000091200000000000002100008200C4 ++:10B83000C000C00008001000840000000000048068 ++:10B84000000000001121C0098400001100009004D4 ++:10B85000C100000000000000000020010200910073 ++:10B8600000000500108400000400090005008000AD ++:10B870000900110000000000109010002000850059 ++:10B880000000030010000000030005000500C101D6 ++:10B89000000020010000C1000001000000002000A5 ++:10B8A0001000100010001000050000000000100043 ++:10B8B000000000000000000041040000030003003D ++:10B8C0008000030011008200050005002000020036 ++:10B8D0000402080200000002000000030040100003 ++:10B8E000200000000021010000000000040084008E ++:10B8F0002000900000000000002100098400C0101A ++:10B9000020001000004001000000000000100000B6 ++:10B91000402000000120000004000008C005820053 ++:10B9200009200000000000000000040000000000EA ++:10B9300001400040900410000000000020000000C2 ++:10B9400000000241900020200408A00010008400A4 ++:10B9500003000080001000000000048400000000CC ++:10B96000000480840441104100000201040404002A ++:10B9700003040440850010C1108500010004030089 ++:10B98000C105001000C11000800810C000000000B8 ++:10B99000082000100000000000A0410080004101CC ++:10B9A00000000800000011000000040004820000F4 ++:10B9B00000004100108400C000A00200051100003A ++:10B9C00010000000008410000000000800000000CB ++:10B9D000000010C0024000000000001085100010A0 ++:10B9E000C0000080020000029002000001040180FB ++:10B9F00001000080014110009140C002901084833A ++:10BA0000080302C0100084200020108908090000EB ++:10BA100000000080840000C000000000000004005E ++:10BA2000000800000000000000000000010001000C ++:10BA3000000000000000000000000000C108000835 ++:10BA40009005001084000021000000008400100018 ++:10BA50001000000008001100000400000004410074 ++:10BA60000400200021400084410004C04040000048 ++:10BA70000420028400400290219002822004119050 ++:10BA8000210005A020002082000441A10404080038 ++:10BA90001091902090209010000000A000000090D5 ++:10BAA00004A041840404049004850801004080003F ++:10BAB000820000A0002040004140100400A010407F ++:10BAC00000000000002010A0100004004020002012 ++:10BAD0008010800002000210020000000000000040 ++:10BAE0000000000000008280000000000000848050 ++:10BAF00000000000000002800100884100112000C9 ++:10BB00000041C00000200404202000002010030099 ++:10BB1000840000040400201120A100400000000067 ++:10BB2000000000000000108000000040051000210F ++:10BB30000400050900000000000000800000000073 ++:10BB40000080000000000000000000000100010073 ++:10BB5000000004000405000002000521000591001A ++:10BB600091400040000009800200000009008900A7 ++:10BB7000890041000000090008000000400080002A ++:10BB8000890040000200090041004100008011804E ++:10BB9000C1000300C00309118000418900000000BA ++:10BBA0000000C100000080210040020400200321A9 ++:10BBB00000092005044002000000210008000000E8 ++:10BBC00000004000000000008000820000004000F3 ++:10BBD00000088041002089830091009110890001B4 ++:10BBE000C000C001000188202104018800A00100DC ++:10BBF000050003000100880001002000000089000A ++:10BC00004000A000010089000900000001000404B8 ++:10BC10008508C082000088018400080001910000AE ++:10BC2000000008001000000020004000010000009B ++:10BC300001000401010000010100C00091000100A9 ++:10BC40000000000000000000000082004000000032 ++:10BC50000100000102000001898300100010018929 ++:10BC60000800008800008200020020014000888255 ++:10BC70004190100111209000059040019004410175 ++:10BC800041A0200082058500000004010802040094 ++:10BC9000040090820101042001109008019001002D ++:10BCA0000000018200010090000100000008000077 ++:10BCB00000000900C0088800830100000100012085 ++:10BCC0000101100000000100010020002000100010 ++:10BCD000200001820000000400004100088491015E ++:10BCE000850000000000002080080009000400001A ++:10BCF00080C0A000912090800541C00008042180F0 ++:10BD00000908092180000089832100008204400085 ++:10BD10004003410405A0050540851080828041054F ++:10BD20001040000009804120040000200000008233 ++:10BD300000030002A0008980800589050000400002 ++:10BD40002180092088000400100005008000800088 ++:10BD500080008011088021002100040009004000BB ++:10BD600021219021020000000080048080000080DA ++:10BD70001100000000092009218580838080208037 ++:10BD800011000080008002000011800380800010FC ++:10BD900011400009009000A0A08400830902210541 ++:10BDA0000005A110000000001100200000000800A4 ++:10BDB0000000028003000040000209C004000008E7 ++:10BDC0000008000400A10000000000000000008046 ++:10BDD000000000808000020811022041894102C059 ++:10BDE0000005894080210008000800840088822026 ++:10BDF0002004828800A09021012100884083824095 ++:10BE0000010200829040000800A000204021822012 ++:10BE100000040082C08802099021A1A0A083000034 ++:10BE20000101000011010000A0C000020182080011 ++:10BE30000588009001080020008900A1010390A05E ++:10BE400000A100C100C0008200C0004000200040EE ++:10BE5000002000900084028801010001000003011D ++:10BE60000104840189058208000100000100000826 ++:10BE700008880810080008A0000300400000001017 ++:10BE800000A000400000000083208501100088A071 ++:10BE90000090008900010000020000044000A1A100 ++:10BEA00000908582008801000000004000880001A9 ++:10BEB0000000000401080000010001910090010051 ++:10BEC0000088009000000000000000000000000159 ++:10BED0000000000100000000004000000089000098 ++:10BEE000000000890090010001881111030010007A ++:10BEF00003808085008000000000008800910040E1 ++:10BF000000800005000200050000834109409111F6 ++:10BF1000800000000020002000008421408983214F ++:10BF2000100840804085099110000000000000903A ++:10BF300000020000030005000300200009110205B3 ++:10BF40004004038000000000000000000000000822 ++:10BF50000020000000030000000000000000008539 ++:10BF60000002000040900209110410000A000013B2 ++:10BF7000000000000000000081004160818100138A ++:10BF8000C200000082000013810041001200001373 ++:10BF90000000000000000081810041000042001309 ++:10BFA000C20042000000008181001100000000007A ++:10BFB00000818100810000000000C200000081417A ++:10BFC0000013C2000A0000810013C200000000003C ++:10BFD0000000000000000A000021C2004200000032 ++:10BFE0000081000081000000008181000050FFC33B ++:10BFF000FF430000000000000000000000000000FF ++:10C0000000000FFF663C0000000000000000060674 ++:10C010000F006600FF0000000000FF09FFF99F9F6E ++:10C02000BD24FCFC000300004F0D090918090000A5 ++:10C0300000000000000000003636FF0F0000000086 ++:10C04000FFF700340F0F0F0F00000000FF6699008C ++:10C0500000000000000000000000000000000000E0 ++:10C0600000000000E6FE260200004F0D0202020260 ++:10C07000FFC3FF00000000000000000000000000FF ++:10C08000000000000F00663C0000000000000000FF ++:10C0900006060F006600000000000000F600060023 ++:10C0A0000606BD240C0C00F300004200000018003E ++:10C0B000000000000000000000003636F000000024 ++:10C0C0000000FFC700046F2D6F2D0000000030300E ++:10C0D0003030000000000000000000000000000000 ++:10C0E000000000000000E6FE260200004200C3003F ++:10C0F0000202FFFFFFFFFFFFFFFFFFFFFFFFFFFF4A ++:10C10000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:10C11000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F ++:10C12000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F ++:10C13000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F ++:10C14000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ++:10C15000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF ++:10C16000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10C17000FFFFFFFF00705CFB0C4440F000180A0654 ++:10C1800000005014F4F4FFFF000000000000000065 ++:10C19000000000000000000000000000000000009F ++:10C1A000C090C0900000000066663C3C00000000AB ++:10C1B0000009F6FF0000000070007F003C3C66664E ++:10C1C00040C100C30000000000007C7F7C7FF000C5 ++:10C1D000000000000000006F80EF0000FFFF000083 ++:10C1E000000000F00FFF0000000000C1C3C100000C ++:10C1F0000000000000003C363C36420342C3333CA2 ++:10C20000FCFF0C060C0CF4F4F4F400000000000039 ++:10C210000000000000000000000024E730F30000F0 ++:10C2200000000000C39900000000000000000000B2 ++:10C230000000006F90FF0000000010001F00C33CD2 ++:10C24000A566404000000000000000001C101C100B ++:10C250002400240000000000006F80EF6464FDFDF6 ++:10C260000000000000F00FFF000000000040C3408D ++:10C27000000000000000000066366636420042C042 ++:10C28000333C030000060000000600E101900000BE ++:10C29000A0865070A0B00005A08650F4A1B900851A ++:10C2A000A08650F0A1B00005058600E001B900A00D ++:10C2B000A0865071A0B80005A0865094A88900857A ++:10C2C00000000AF0003000000000A08650E0A8B096 ++:10C2D0000005A0865070A0B000050006007401A003 ++:10C2E0000000008600E4003000000086006000B01E ++:10C2F0000000008600E109B00405008600E000B0FF ++:10C30000008000860A5100B0000000000000000814 ++:10C31000FFF72C00002C417D0000000000003F3F93 ++:10C3200014D70000000000000100AFA03030287DCD ++:10C33000000000000000FF3500000E0E0404FFFFA7 ++:10C3400028280000FF00FFFF0000000000000000A0 ++:10C35000B2FFB2FF0000000000000000000000007B ++:10C360000DFD0FFF0000000000003B3B000000003F ++:10C370001E1E0F3C0000000000F000F00000000056 ++:10C3800000000000000000003C3C00FF0000000036 ++:10C390000000FFFF83000083407040700000000039 ++:10C3A000030314D70000000000000100AFA03030EC ++:10C3B0002070207000000000003500000A0A000014 ++:10C3C00055FF000A0000FF00000000000000000010 ++:10C3D0000000004D004D00000000080808CB0000E0 ++:10C3E000000008F800F000000000C3033B3B000021 ++:10C3F00000001E1E0F3C0000000010F000F00000C6 ++:10C40000000000000000000000003C3C00FF0000B5 ++:10C410000000BEBE555580D082D7000820280000FD ++:10C42000000082AA8A8A000000000C00CFFF0000F2 ++:10C4300000007D7F7DFF000000000FFF0F0F5505FE ++:10C4400050004040707000003C3C0F0F00000000A6 ++:10C4500000000000000000000000000000000000DC ++:10C46000000000005050050F000000000000000018 ++:10C4700000000000C3C3C3C3000000000000008030 ++:10C480000000000000000000FFFFAAAA00058005D0 ++:10C49000000000004141000080D00000000BE0EBF4 ++:10C4A0000000000000280808000000000F030F3FF4 ++:10C4B0000000000055555555000000000FFF0F0FFC ++:10C4C000500050000000303000003C3C0F0F0000D6 ++:10C4D000000000000000000000000000000000005C ++:10C4E000000000000000D755000F00000000000011 ++:10C4F000000000000000C3C3C3C300000000000030 ++:10C5000000000000000000000000FFFEAAA90000DB ++:10C5100000004000000082000400000800900400B9 ++:10C5200000000000802021000010000000008000BA ++:10C53000409040000000040020000400040040007F ++:10C5400000000000000020000408A10000002004FA ++:10C550000000000040000000000011000400040082 ++:10C5600020002000040084008000800804000000F7 ++:10C57000000000000400000040000400040041002E ++:10C580000000000004000400000020002100000062 ++:10C590000000210000000000210000000000000059 ++:10C5A000040000000000088000000000900000006F ++:10C5B00020009000000000000000010001000100C8 ++:10C5C0000400400000002000200001800400000062 ++:10C5D00000800000000000000000000000000005D6 ++:10C5E0000000000000000100410004000480000081 ++:10C5F0000000040000000000000000000000000037 ++:10C600000400000000000000000000000000000026 ++:10C61000A00000000000000000000000000000007A ++:10C62000000000000000000000000000000000000A ++:10C6300000000000000000000001000000000000F9 ++:10C6400000000000000000000000000000010000E9 ++:10C6500000000000000000C000000000000000001A ++:10C6600000000000000000000000000000000000CA ++:10C6700000000000000000000000000000000000BA ++:10C6800000000000000000000000000000000000AA ++:10C690000000000000000000001100000000000089 ++:10C6A000000000000010000800000000000000086A ++:10C6B0000000001000080000000000020000000060 ++:10C6C0000000000000100008000000000021002011 ++:10C6D0000000000800000000000000000000000052 ++:10C6E000000000000000001000000000000000003A ++:10C6F000000000000000000000000000000000003A ++:10C700000000000000000008000000000000000021 ++:10C710000010000000000000000000C000008000C9 ++:10C720008000008504010301002000200085000135 ++:10C73000000100C00000000000000000098410009B ++:10C740008001040004000400830100000082004016 ++:10C750000001000000000000410000000000000097 ++:10C760001082000000000000000000000000050131 ++:10C7700000001000000000000000000000000000A9 ++:10C78000001000000000000010000000050005007F ++:10C790000000000000000000000000000003000096 ++:10C7A0002000202100021104840400800080001079 ++:10C7B0000020001084080008000084008203841117 ++:10C7C00010000440850091008300402000410003D8 ++:10C7D0000080002000000000C00000000000C00039 ++:10C7E000C00084000000000884000000C021000098 ++:10C7F0000002100011000000840000000000000092 ++:10C800000000000000030000000388008400000016 ++:10C810000000C0008800100000008400000000003C ++:10C8200000000500000004008900850004000800E5 ++:10C8300089000401100002000001000084011000C2 ++:10C8400009010300400000000000A00020002000BB ++:10C850002000000041000000200000001000000047 ++:10C86000100000000000100009000000000000009F ++:10C8700000000000000000000000000000000200B6 ++:10C880000000000004000000000002001000000092 ++:10C89000020020002000020000000900000000004B ++:10C8A0000000000000000000010020000400010062 ++:10C8B0000100080001200100010000200000200804 ++:10C8C0000000004000000000000000020400000022 ++:10C8D0000000000000000000000000000000000058 ++:10C8E000000000000000000000000009000000003F ++:10C8F0000000000000000000000000000000000038 ++:10C900000000000000000000000000000000000027 ++:10C910000000000000000011000000000000000006 ++:10C9200000000040000003012000C18420400004FA ++:10C93000C1108000042003000421001020200020EA ++:10C940004120410000000000102005000000100000 ++:10C950008000000000001000000080000000800146 ++:10C960008082000000820000000000000000000043 ++:10C9700010000000000000000000000000000000A7 ++:10C9800000000000000000000000000000000000A7 ++:10C990000000000100000000000000000000000096 ++:10C9A0000001800100800010004001214000118042 ++:10C9B0000091202108080188001001A0008001805A ++:10C9C000008800A184008400100004A10000000081 ++:10C9D0001000042184218800C000840004030400A6 ++:10C9E0000804202100C000000000842100408800CD ++:10C9F000C00000000000C00000000005C0000003EF ++:10CA00000000000000000000000000000000000026 ++:10CA100000000003100400000000002100000000DE ++:10CA2000C000C0042004000000840200000280C096 ++:10CA3000000104000020041088000500044103C028 ++:10CA400040102005850210000084040009404000C9 ++:10CA5000400020002004002000900088004000904A ++:10CA60000000200000000000000040000000004026 ++:10CA70000000410000400000000020000000001005 ++:10CA80000082000000000000000004000000200000 ++:10CA90001000100000000000000000022000002034 ++:10CAA0000000000020400000000000000100000025 ++:10CAB00040000020110000800180210000000110D2 ++:10CAC0000000008001A010800000000000000000B5 ++:10CAD0000100010000000100000000000000000053 ++:10CAE0000000000000000000004000000000000006 ++:10CAF0000000000000000000000000000000000036 ++:10CB00000000000000000000000000000000000025 ++:10CB10000000000000000000000000000000000015 ++:10CB200000000000200000000000000005000000E0 ++:10CB3000008011110009000209090008081080880E ++:10CB400000880005910200800082000000002000A3 ++:10CB500000801103800903A0050300000000850088 ++:10CB600000000983008000800983000000000000AD ++:10CB70000000000000000000000000000080418074 ++:10CB80008080008000000000000000000000000025 ++:10CB90000000000000000000000000000000000095 ++:10CBA00000000000020300000005090000820140AF ++:10CBB000000800C089010001A001010100000191ED ++:10CBC00010C1000902C191851010000802C0048440 ++:10CBD0000002000801A18291900500000000A00061 ++:10CBE000020000000182000400040188000000002F ++:10CBF00000000000000000000000000000000088AD ++:10CC0000C0400220000400000000000000000000FE ++:10CC10000000000000000000000000000000000014 ++:10CC20000000000000000100000000000100000002 ++:10CC30000000A0A000850189000000A00089010972 ++:10CC4000111100C1018282019108C08982C00000D7 ++:10CC50000100000000A000018982219121830000D1 ++:10CC60004100A000100001000000010001000000D0 ++:10CC700000000000000000000000000000000000B4 ++:10CC800003004000880021C00000000000000000F8 ++:10CC90000000000000000000000001000000010092 ++:10CCA0000000000000000000000000000002010081 ++:10CCB0000040000000000083021000000080008996 ++:10CCC00010048589088810800002888200A0808472 ++:10CCD00011002000030003020002C100A0A083890C ++:10CCE0000000C0004100C100090003000800090065 ++:10CCF0000000000000000000000000000000000034 ++:10CD00000000104185008300038000000000000047 ++:10CD100000000000000000000000410010000000C2 ++:10CD20001000000000000000000009000300038064 ++:10CD300009000000000003000000414104412009F7 ++:10CD400089830800100000808980020000000980AB ++:10CD5000A08000808080008000004110800209A037 ++:10CD6000110300800080000000000040800880095E ++:10CD70008011000000000000000000000000000022 ++:10CD80000000000000800080408000800000000063 ++:10CD90000000000000000000000000000000000093 ++:10CDA000210000000000000000000000000200055B ++:10CDB000090400050040880003000088000001010C ++:10CDC0000101898901004188A0A089820000A0C0DA ++:10CDD00082A0898200020840A040020000A10491C4 ++:10CDE000838901010004000400C000000001020169 ++:10CDF00088010201000000000000000000000000A7 ++:10CE00000000000000000040004082200088000078 ++:10CE10000000000000000000000000000000000012 ++:10CE20000000000000000000000000000000000101 ++:10CE3000000101000000900020008800A002404096 ++:10CE400010828801C000838485828901010091A13C ++:10CE50008903A000A1888402C000000002000389A9 ++:10CE600090210100030200000000000000200000EB ++:10CE700000100001000000000000000000000000A1 ++:10CE80000000000000000000024088004000022076 ++:10CE90000000000000000000000000000000000092 ++:10CEA0000000000100000000000000000000000081 ++:10CEB0000000002000000000000000000000000052 ++:10CEC00080808000002100008880108221400800BE ++:10CED0009111C110910040808000001100400000BD ++:10CEE0008383209102022000000200040011000050 ++:10CEF000000000840021000000000000000000008D ++:10CF00000000000000000000000080C180058000DB ++:10CF10000000000000000000000000000000000011 ++:10CF200000000000002000020000000000000000DF ++:10CF30000000000000050005000000600000C200C5 ++:10CF4000004206600013C20000000A500013C20035 ++:10CF500082480A600013C200000081810013C200F1 ++:10CF6000000000420013C2000A500000001300003D ++:10CF700000000000008181000000000000000000AF ++:10CF8000000000000000000000000000210000136D ++:10CF90000000000000000000000000000000000091 ++:10CFA0000000000000840000840000000000000079 ++:10CFB00000000000000000008100000000000000F0 ++:10CFC0000000000000000000556530CF0000001098 ++:10CFD0000000000030100C04000000000000000001 ++:10CFE0000000000055FF2D2DFF553C0F00000000F4 ++:10CFF0000000000000000000303000500000000081 ++:10D000000000000000000000000000000000000020 ++:10D010000000000000000000000000000000000010 ++:10D020000000000000000000000000000000000000 ++:10D030000000000000000000000000A008A80000A0 ++:10D0400000000000000000000000555500FF000037 ++:10D05000000000000000C0400301000000000000CC ++:10D0600000000000000000AA2D2D00553C0F00001C ++:10D070000000000000000000000030305000000000 ++:10D0800000000000000000000000000000000000A0 ++:10D090000000000000000000000000000000000090 ++:10D0A0000000000000000000000000000000000080 ++:10D0B00000000000000000000000000000A002A22C ++:10D0C0000000000000000000EF10FF003C3C3C3C72 ++:10D0D000EFFFFFFFA8BC283C960000000A0A0A0ADE ++:10D0E0000000000055514541FC0CAFAFF0FFFFAA16 ++:10D0F00000000000FFFFFA50FFFFC3C3000A003A20 ++:10D10000000000000000000000000000000000001F ++:10D11000000000000000000A000200000000000003 ++:10D120000000000000000000000000000000FFFF01 ++:10D13000FFFF0000000000000000FFFF0F0F0008CD ++:10D1400000FD0000000000000000FF00FF00C3C35E ++:10D15000C3C3FFFFFFFFFCFC3C3C009600000A0A33 ++:10D160000A0A0000000014100400FC0CA0A0F0004B ++:10D1700000AA0000000005AF0000FFFFC3C30000CD ++:10D18000003C000000000000000000000000000063 ++:10D190000000000000000000000A00020000000083 ++:10D1A000000000000000000000000000000000007F ++:10D1B000FEFEFFFF0000000000000000FFFF0F0F59 ++:10D1C0000008000800860064A8B0A005008600F5ED ++:10D1D00009920000000270F509100000000652B527 ++:10D1E000A90000050086006509B0848508860494BE ++:10D1F00008820010008600E00090000000860251C6 ++:10D2000000B000000000000000000000000000006E ++:10D2100000000000000000860080018000A00000E7 ++:10D2200000000000000000000000000000000000FE ++:10D2300000040800000000000000000000000000E2 ++:10D2400000100000000010002000C3C33C3C600040 ++:10D250000900FFFF0000F000AAAA0F0FFF007F8067 ++:10D26000FF00FF0FF00F3C0000005C555C5500EB29 ++:10D270000028407040700000000010F010F0000026 ++:10D28000000000000000000000000000000000009E ++:10D2900000000000000000007878FF00000FFFFF92 ++:10D2A000000000000000000000000000000000007E ++:10D2B000000000000000000000000000000000006E ++:10D2C000000000000000000000000000C3C33C3C60 ++:10D2D00060600909FFFF00000F00AAAA0F0FFF00FE ++:10D2E000FF00FF0000F0F00F003C00003C353C3533 ++:10D2F000002800280030003000000000100010005E ++:10D30000000000000000000000000000000000001D ++:10D3100000000000000000000000FF00FF00000C03 ++:10D32000FFFC000000000000000000000000000002 ++:10D3300000000000000000000000000000000000ED ++:10D34000000000000000000000003C3C3C3C550098 ++:10D3500055000000000000000000208020800F0F1A ++:10D36000000024008100FBFF393C22001100000076 ++:10D37000000000FF00A00500AF000000000050000A ++:10D380005FFFFFFFAAAA00000000000000000000ED ++:10D39000000000000000000000000000FFFFF0009F ++:10D3A00000FF05F500000000000000000000000084 ++:10D3B000000000000000000000000000000000006D ++:10D3C000000000000000000000000000BFFF3C3C27 ++:10D3D000550055000000000000000000288228824F ++:10D3E0000F0F0000002400810400393C00220011CE ++:10D3F00000000000000000A0050005000000000083 ++:10D40000550555F5FFFEAAA9000000000000000028 ++:10D4100000000000000000000000000000003FFFCE ++:10D42000300000FF0CFC00000000000000000000C5 ++:10D4300000000000000000000000000000000000EC ++:10D4400000000000000000000000000000000000DC ++:10D4500000000000000000000000000000000000CC ++:10D460000000210000000000000004000000000097 ++:10D4700000000000000000000000000800000000A4 ++:10D48000000021000000000000000000000000007B ++:10D49000000000000000000000000000000000008C ++:10D4A000000000002000200000000000000000003C ++:10D4B000000000000000C1010000000000000000AA ++:10D4C00000002000000000000000000000004000FC ++:10D4D000000000000000000000000000000000004C ++:10D4E00000000000C00000000000A00000000000DC ++:10D4F000000000000000A0000000000090000000FC ++:10D500000000000000000000000000000400000017 ++:10D51000000000000000000000000000000000000B ++:10D5200000000000000004000000000000000000F7 ++:10D5300000000000000000000210000000002000B9 ++:10D5400000000000000020000000000000000000BB ++:10D550000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFD9 ++:10D56000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB ++:10D57000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB ++:10D58000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB ++:10D59000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B ++:10D5A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B ++:10D5B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B ++:10D5C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B ++:10D5D000FFFFFFFF00BCDC7F0C44408800C00A0650 ++:10D5E000000080A2000000000021000000000000F8 ++:10D5F000000000000000000000000010000000001B ++:10D600000000000000000000000000000003000017 ++:10D6100000000010000000000000001000000000EA ++:10D6200000000000000000000000000000000000FA ++:10D6300000000000001000000000000000100000CA ++:10D6400000000000000000000000000000000000DA ++:10D6500000000000001000000000000000100000AA ++:10D6600000000000000000000000000000000010AA ++:10D6700000000000000000000000000800000000A2 ++:10D680000082000000000000000000000000000018 ++:10D690000000410000000000000010000000000039 ++:10D6A0000000000000000000000000004100000039 ++:10D6B000000000000000000000000000000000006A ++:10D6C000000000000000000000000000000000005A ++:10D6D000000000000000000000000000000000004A ++:10D6E000000000000000000000000000000000003A ++:10D6F0000000000500000000000000000000842180 ++:10D700000000C00300000000000000000000000056 ++:10D7100000000000C00800000000000082000000BF ++:10D7200000000000000000000000004100000000B8 ++:10D7300000000000000000000010000000000000D9 ++:10D7400000000000000000000000000000000000D9 ++:10D7500000000000000000000000000000001000B9 ++:10D7600000000000000000000000000000000000B9 ++:10D77000000000000900110000001100000002007C ++:10D7800000000000000040901000000000000000B9 ++:10D790000000000000000000000000000000200069 ++:10D7A0000000000000000000000000000000000079 ++:10D7B0000000000000000000000000000000000069 ++:10D7C0000000000000000000000000000000000059 ++:10D7D0000000000000000000000000000000400009 ++:10D7E000000000000000000000000000FFFFFFFF3D ++:10D7F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39 ++:10D80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28 ++:10D81000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 ++:10D82000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 ++:10D83000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8 ++:10D84000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8 ++:10D85000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8 ++:10D86000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00D0F6 ++:10D8700049F10C44408800100A0600008020000096 ++:10D880000000000000000000000000000000000098 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000004100000037 ++:10D8B0000000000000000000000000000000000068 ++:10D8C0000000000000000000000000000000001048 ++:10D8D0000000000000000000000000000000000048 ++:10D8E00000000000000000000000000000A0000098 ++:10D8F0000000000000000000000000000000000028 ++:10D900000000000000000000000000000003001004 ++:10D91000000000038400000384218400C000002173 ++:10D92000C0000003C00800008400000000000000E8 ++:10D9300000000008000000210000000000080000B6 ++:10D9400000000003000000000000000000000000D4 ++:10D9500000000000000000000000000000000000C7 ++:10D9600000000000000000000000000000000003B4 ++:10D970000000000000000000002100000000000086 ++:10D980008400000000000000000000000000110002 ++:10D990000900090002000000000000000000000073 ++:10D9A000008840020000000000400000000000006D ++:10D9B0000000000000000000000000000000000067 ++:10D9C000000800000000000000000000000000004F ++:10D9D0000000000000000000000000000000000047 ++:10D9E0000000000000000000000000000000000037 ++:10D9F00000000000000000000010100009000000FE ++:10DA000000000020FFFFFFFFFFFFFFFFFFFFFFFF02 ++:10DA1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:10DA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:10DA3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10DA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:10DA5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10DA6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:10DA7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 ++:10DA8000FFFFFFFFFFFF002C12120C4440880070C4 ++:10DA90000A06000000C300000000000000000000B3 ++:10DAA0000000000000000000000000000000000076 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000000000000000000000000000000056 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000100000000000000000000000000000014 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000000000F5 ++:10DB300000000000000000000000000000000000E5 ++:10DB400000000000000000000000000000000000D5 ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB700000000000000000000000000000000000A5 ++:10DB8000000008000000000000000000000000008D ++:10DB900000000000000000000000FFFFFFFFFFFF8B ++:10DBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10DBB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10DBC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:10DBD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:10DBE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10DBF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:10DC0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 ++:10DC1000FFFFFFFFFFFFFFFFFFFFFFFF007C9DA057 ++:10DC20000C44408800E80A060000004100000000A3 ++:10DC300000000000000000000000000000000000E4 ++:10DC400000000000000000000000000000000000D4 ++:10DC500000000000000000000000000000000000C4 ++:10DC600000000000000000000000000000000000B4 ++:10DC700000000000000000000000000000000000A4 ++:10DC80000000000000000000000000000000400054 ++:10DC90000000000000020000000000000000000082 ++:10DCA0000000000000000000000000000000FFFF76 ++:10DCB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:10DCC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:10DCD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 ++:10DCE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:10DCF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10DD0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10DD1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10DD2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:10DD30000074185D0C44408800D80A06000080E397 ++:10DD400000000000000000000000000000000000D3 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000000000000000B3 ++:10DD700000000000000000000000000000000000A3 ++:10DD80000000000000000000000000000000000093 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000020000053 ++:10DDB0000000000000000000000000000000000063 ++:10DDC0000000000000000000000000000000000053 ++:10DDD0000000000000000000000000000000000043 ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000000000000000000000000012 ++:10DE10000000000000000000000000000000000002 ++:10DE200000000000000000000000000000000000F2 ++:10DE300000000200000000000000000000000000E0 ++:10DE400000000000000000000000000000000000D2 ++:10DE500000000000000000000000000000000000C2 ++:10DE600000000000000000000000000000000000B2 ++:10DE700000000000000000000000000000000000A2 ++:10DE80000000000000000000000000000000000092 ++:10DE90000000000000000000000000000000000082 ++:10DEA00000000000000000000090000000000000E2 ++:10DEB0000000010000000000000000000000000061 ++:10DEC000000000000000FFFFFFFFFFFFFFFFFFFF5C ++:10DED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 ++:10DEE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 ++:10DEF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 ++:10DF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 ++:10DF1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 ++:10DF2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 ++:10DF3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 ++:10DF4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 ++:10DF5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 ++:10DF6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 ++:10DF7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 ++:10DF8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 ++:10DF9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 ++:10DFA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 ++:10DFB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 ++:10DFC000FFFFFFFFFFFFFFFFFFFF0000000000005B ++:10DFD0000000000000000000000000000000000041 ++:10DFE0000000000000000000000000000000000031 ++:10DFF0000000000000000000000000000000000021 ++:10E000000000000000000000000000000800000008 ++:10E0100048000000000000000000000000000000B8 ++:10E0200000000000000000000000000000000000F0 ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E0500000000000000000000000000000000000C0 ++:10E0600000000000000000000000000000000000B0 ++:10E0700000000000000000000000000000000000A0 ++:10E080000000000000000000000000000000000090 ++:10E090000000000000000000000000000000000080 ++:10E0A0000000000000000000000000000000000070 ++:10E0B0000000000000000000000000000000000060 ++:10E0C000000000000000000000000000000000F858 ++:10E0D000DEC50C85004004000400040004000400B8 ++:10E0E000040004000400CC26000000000000000032 ++:10E0F0000C44C00000C0CC2600000000000000005E ++:10E100000C44C0800000CC2600000000000000008D ++:10E110000C44C0800080CC260000000000000000FD ++:10E120000C44C08000A0CC260000000000000000CD ++:10E130000C44C0800060CC260000000000000000FD ++:10E140000C44C0800030CC2600000000000000001D ++:10E150000C44C08000B0CC2600000000000000008D ++:10E160000C44C0800008CC26000000000000000025 ++:10E170000C44C0800088CC26000000000000000095 ++:10E180000C44C08000C8CC26000000000000000045 ++:10E190000C44C08000A8CC26000000000000000055 ++:10E1A0000C44C0800098CC26000000000000000055 ++:10E1B0000C44C0800058CC26000000000000000085 ++:10E1C0000C44C02000A8CC26000000000000000085 ++:10E1D0000C44C0200068CC260000000000000000B5 ++:10E1E0000C44C0A000E8CC260000000000000000A5 ++:10E1F0000C44C0E00030CC2600000000000000000D ++:10E200000C44C0E000B0CC2600000000000000007C ++:10E210000C44C0E00070CC260000000000000000AC ++:10E220000C44C0E000F0CC2600000000000000001C ++:10E230000C44C0E00008CC260000000000000000F4 ++:10E240000C44C0E00088CC26000000000000000064 ++:10E250000C44C0E00048CC26000000000000000094 ++:10E260000C44C0E000C8CC26000000000000000004 ++:10E270000C44C0E00028CC26000000000000000094 ++:10E280000C44C0E000A8CC26000000000000000004 ++:10E290000C44C0E00068CC26000000000000000034 ++:10E2A0000C44C0E000E8CC260000000000000000A4 ++:10E2B0000C44C01000E8CC26000000000000000064 ++:10E2C0000C44C0900078CC26000000000000000044 ++:10E2D0000C44C03000E8CC26000000000000000024 ++:10E2E0000C44C07000A8CC26000000000000000014 ++:10E2F0000C44C0700068CC26000000000000000044 ++:10E300000C44C0880080CC26000000000000000003 ++:10E310000C44C0880040CC26000000000000000033 ++:10E320000C44C0880060CC26000000000000000003 ++:10E330000C44C08800E0CC26000000000000000073 ++:10E340000C44C08800D0CC26000000000000000073 ++:10E350000C44C0880030CC26000000000000000003 ++:10E360000C44C08800B0CC26000000000000000073 ++:10E370000C44C0880008CC2600000000000000000B ++:10E380000C44C0880088CC2600000000000000007B ++:10E390000C44C0880048CC260000000000000000AB ++:10E3A0000C44C08800C8CC2600000000000000001B ++:10E3B0000C44C0880028CC260000000000000000AB ++:10E3C0000C44C08800A8CC2600000000000000001B ++:10E3D0000C44C0880068CC2600000000000000004B ++:10E3E0000C44C08800E8CC260000000000000000BB ++:10E3F0000C44C0880018CC2600000000000000007B ++:10E400000C44C0880098CC260000000000000000EA ++:10E410000C44C0880058CC2600000000000000001A ++:10E420000C44C00000400C8500800A06000000413A ++:10E4300000000000000000000000000000000000DC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000000010200000102000000000000000003C ++:10E48000000000000000000000000000000000008C ++:10E49000000000000000000000000000000000007C ++:10E4A000000000000000000000000000000000006C ++:10E4B0000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF6A ++:10E4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:10E4D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10E4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10E4F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10E50000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B ++:10E51000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B ++:10E52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB ++:10E53000FFFFFFFF0030976E0C44C08000400A06CA ++:10E54000000080200000000000000000000000002B ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000000000000000008B ++:10E59000000000000800000000000000080000006B ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000001000000000000000000000000000000B ++:10E6000000000000000000000000000000000010FA ++:10E6100000000010000001000000000000000100E8 ++:10E6200000000000000000000000000000000041A9 ++:10E63000000000200010000000100000000000009A ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E66000000000000000000000000000000000109A ++:10E67000000000000000000000000000000000009A ++:10E68000000000000000000000000000000000008A ++:10E69000000000000000000000000000000000007A ++:10E6A00000000000000000000084000000000000E6 ++:10E6B000001000000000000000A0000000000000AA ++:10E6C00000000000000000000000FFFFFFFFFFFF50 ++:10E6D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A ++:10E6E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A ++:10E6F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A ++:10E70000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19 ++:10E71000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09 ++:10E72000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9 ++:10E73000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9 ++:10E74000FFFFFFFFFFFFFFFFFFFFFFFF00F853FB8F ++:10E750000C44C08000E00A06000080610000000058 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000000000000099 ++:10E780000000000000000000000000000000000089 ++:10E7900000000000A000A000000000000000000039 ++:10E7A000A00000000000A000A000A00000000800E1 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000000039 ++:10E7E0000000000000000000000000000000000029 ++:10E7F0000000000000000000000000000000000019 ++:10E800000000008800000000000000000000000080 ++:10E8100000000000000000000000000000000000F8 ++:10E820000000000000A00000000000000000000048 ++:10E8300000000000000000000000000000000000D8 ++:10E84000001000A000000000000000000000000018 ++:10E8500000C00000000000000000000000000010E8 ++:10E860000000000000000000000000100000000098 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000008400000000000094 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E93000001000000010000000000000000000C0F7 ++:10E94000000000000000000000000000000000C007 ++:10E9500000000000000000000000001000000000A7 ++:10E9600000000000000000000000000000000000A7 ++:10E970000000000000000000000000000000000097 ++:10E980000000A041000000000000000000000000A6 ++:10E9900000000000A0000000A00400000020000013 ++:10E9A0000000000000000000000000000000000067 ++:10E9B0000000000000000000000000000000000057 ++:10E9C000000000000800000000000000000000003F ++:10E9D0000000000000000000000000000000000037 ++:10E9E000000000000000FFFFFFFFFFFFFFFFFFFF31 ++:10E9F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 ++:10EA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 ++:10EA1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 ++:10EA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 ++:10EA3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 ++:10EA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 ++:10EA5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 ++:10EA6000FFFFFFFFFFFFFFFF000C1F380C44C080BB ++:10EA700000700A06000000C3000000000000000053 ++:10EA800000000000000000900000000000000000F6 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000001000000000055 ++:10EAC0000010010000000000000000000000000035 ++:10EAD00000000000000000000088000000000000AE ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000050000000000000000000000000000 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB300000000000000000000000000008000000CD ++:10EB400000000080100000000000000040000000F5 ++:10EB50000000000040000000000000000000000075 ++:10EB600000000000000000000000000000000000A5 ++:10EB7000000000000000000000000000FFFFFFFF99 ++:10EB8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 ++:10EB9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 ++:10EBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 ++:10EBB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:10EBC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:10EBD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10EBE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:10EBF000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00A47F ++:10EC00004EE30C44C08000480A06000000410000AA ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC40000000000000000000000000000000004084 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC80000000000000000000000000000000000084 ++:10EC9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 ++:10ECA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 ++:10ECB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 ++:10ECC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 ++:10ECD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 ++:10ECE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 ++:10ECF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 ++:10ED0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:10ED1000FFFF00B852AB0C44C08000280A06000078 ++:10ED200000410000000000000000000000000000A2 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED7000000000000000000400000000000000008F ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA00000000000FFFFFFFFFFFFFFFFFFFFFFFF6F ++:10EDB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 ++:10EDC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 ++:10EDD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 ++:10EDE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:10EDF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:10EE0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 ++:10EE1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:10EE2000FFFFFFFFFFFF009073720C44C08000687B ++:10EE30000A06000080200000000000000000000022 ++:10EE400000000000000000000000000000000000C2 ++:10EE500000000000000000000000000000000000B2 ++:10EE600000000000000000000000000000000000A2 ++:10EE70000000000000000000000000000000000092 ++:10EE80000000000000000000000000000080000002 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000000000022 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000400000000000000040000000000081 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF600000000000000000000000000000000000A1 ++:10EF70000000000000000000000000000000000091 ++:10EF80000000000000000000000000000000000081 ++:10EF90002020000000000000000000000000000031 ++:10EFA0000000000000000000000000000000000061 ++:10EFB000000000000000000000000000FFFFFFFF55 ++:10EFC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 ++:10EFD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 ++:10EFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 ++:10EFF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 ++:10F00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 ++:10F01000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 ++:10F02000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 ++:10F03000FFFFFFFFFFFFFFFFFFFFFFFFFFFF002CB2 ++:10F04000CEF40C44C08000D80A060000A86B000073 ++:10F05000000000000000000000200000010000008F ++:10F0600000000000000000000000000000000000A0 ++:10F070000000000000000000000000000000000090 ++:10F080000000000000000000000000000000000080 ++:10F09000000000200000010000000020000000002F ++:10F0A000000000200000000000000020000001001F ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D00000000000000000000040000000000200EE ++:10F0E0000000000000000000000000000000000020 ++:10F0F0000000000000000000000000000000000010 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000040000000000200000000000000AD ++:10F12000020000000000000000000040000000009D ++:10F1300002000000000000000000000000000000CD ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000900A6 ++:10F16000000000000000000000000000000000009F ++:10F17000000000000000000000000000000000008F ++:10F18000000000000000000000000000000000007F ++:10F1900000000000000000000900000000000080E6 ++:10F1A00001000000000000810100000000000000DC ++:10F1B0000900000000000000000000000000000046 ++:10F1C000000000000000000000000000000000003F ++:10F1D000000000000000000000000000000000002F ++:10F1E0000000000004000000000011000000040006 ++:10F1F0000000110011000400800011000000000058 ++:10F2000000000000040000001100000008000800D9 ++:10F2100000000000000004000400000000000000E6 ++:10F2200000000000000000000500000002000400D3 ++:10F2300000000000050004000300000002000800B8 ++:10F240000200000002000900200004002000040069 ++:10F25000030000002000000000000000000000008B ++:10F26000000000000000010000000000000000009D ++:10F27000010000000000000001002000000000006C ++:10F28000000000000000000000000000000001007D ++:10F29000010000000000000001000000000000006C ++:10F2A000000000000000000000000000000001005D ++:10F2B000000000000000000000000000000001004D ++:10F2C000000000000000010000000100010001003A ++:10F2D00000000000000001000000000000008000AD ++:10F2E00000000000000000000000000020002000DE ++:10F2F000000080008000000000000000000000000E ++:10F300000000000080000020000000000040040019 ++:10F31000801140000000000000C00000000000005C ++:10F3200000008011800480018000000000000000C7 ++:10F33000000000000000004100010000000000018A ++:10F3400080000001000100058001000000000000B5 ++:10F3500000010000000000C080000000000000006C ++:10F36000020000000000000000000000000001009A ++:10F37000010000004000200000000000000000002C ++:10F3800000008200001020000090000000000080BB ++:10F3900005212008011000000041000000000000CD ++:10F3A0000000000020822090020840100000084168 ++:10F3B000000090000021002100C09020900000007B ++:10F3C0000220040002040204028204020000002160 ++:10F3D000000082040000000000090400000000009A ++:10F3E000000000000000000000000000000000001D ++:10F3F00000008000000000000000000000A00000ED ++:10F4000000A0004080000000801000840000000088 ++:10F41000004000001004808400900020000080C0A4 ++:10F420008084801000C0000000020008000200007C ++:10F43000001000000020000000200010000000006C ++:10F440000002000000040002000200880004000422 ++:10F4500000040000000000C000080084000200005A ++:10F46000000000000000000000000000000000009C ++:10F47000000000002000000000000000000000006C ++:10F480000000000000802000000040000000840018 ++:10F490008400008000000180100000000080000057 ++:10F4A00004000400040000000000008000800080D0 ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000800080000000023A ++:10F4D00000000080000000000000008000000080AC ++:10F4E000000000000000080000000000000088008C ++:10F4F000200010000400040005040004800500043E ++:10F500004000200104000200A10205000301830065 ++:10F5100003000004054005880401040008000300FE ++:10F5200000000500030003200500A0010000C10148 ++:10F530000320100002001000210010010000400113 ++:10F540000221080000000801000041000000000046 ++:10F550000000000000000401102041A00000050090 ++:10F56000100000000000000001000000000000008A ++:10F5700003000100010001000100008000800482FE ++:10F58000008001000104C1008300208000000040D1 ++:10F5900004000000C080008500008508C100C10093 ++:10F5A000C000000000210800008010052104C021D7 ++:10F5B000100200808400C141C000821001100021AF ++:10F5C000010485840000C005082000210800000017 ++:10F5D000C000004100210000010800800000000080 ++:10F5E000000000000000000000000000000000100B ++:10F5F00000000000040040A0208420100310400000 ++:10F600000300031020044002C00420040010400244 ++:10F610000084208420C02000000041000400040079 ++:10F6200004000410000010000800000000000300A7 ++:10F6300041004110400240C000400020020008028A ++:10F6400000004040412008841010202000000800E5 ++:10F6500020000800418820001000000800880000F9 ++:10F66000001000100000000000000000000000007A ++:10F670000000000000000100010001000100000086 ++:10F680000100000000000180018040800180000036 ++:10F690000100000001000100010000000000010065 ++:10F6A0000100010001000000000001000000004016 ++:10F6B00000000000000001800000000000000000C9 ++:10F6C00000000000010000800000000000000000B9 ++:10F6D00000000000000000000000000000800000AA ++:10F6E000000000000000000000000000000000001A ++:10F6F00000C0000000000010040000000000000036 ++:10F700000001031100900210000240A000840000DC ++:10F71000408420C002842000418441100008000081 ++:10F7200008000800080008000000800085A1000112 ++:10F730008400411005C0C0000501000082110000D6 ++:10F740000584020000010001000400C021840000C3 ++:10F7500020000000080000000004000000102185C7 ++:10F7600021010084000000000001000000000041B1 ++:10F770000000000000000000000001000000000088 ++:10F7800000000002000200000100008001000005EE ++:10F79000000001000100A1000100000000900080B5 ++:10F7A00000000100110001101100000004410820B8 ++:10F7B00082200500000000214100000200000940F5 ++:10F7C0000000002110001040C002848008001000DA ++:10F7D000C0000100000008000800009000001000B8 ++:10F7E000C0080040000000000000002000000000F1 ++:10F7F00000000080000009000000008088008000F8 ++:10F8000040400908911100090010090991110908E7 ++:10F8100002C109099110400941020909402020094B ++:10F8200000050041000200000000000000C040038D ++:10F830004120414100000003800940110002C00343 ++:10F84000052090020040051110020004100800007D ++:10F8500080000400000000031002090803040005F2 ++:10F860000011110500040400000000000900000060 ++:10F8700000000000000800000000000000C08940F7 ++:10F88000C0848840019091010001400001019191E4 ++:10F89000C1010889010191019001010101010101EA ++:10F8A0000101000100010000000040040000000010 ++:10F8B00003010001030100000001840100000000B9 ++:10F8C00041014101C00100011100010100000001DE ++:10F8D0000000C00000000000400111010000010014 ++:10F8E0000401A00000010000000000000000000072 ++:10F8F00001000000000000900000000000000088EF ++:10F90000890085888901098990018388888985858E ++:10F91000080003888901858505000188000111011F ++:10F9200000000004104110000002A082000201004B ++:10F93000000000400108008201001000090440019D ++:10F940008390000000C001010108910188840991A1 ++:10F9500083C00800000002820201010001830082CE ++:10F9600001000100010801830100000000000110F6 ++:10F970000100100000000000000011000000000065 ++:10F98000000008008800901003910002418010825E ++:10F99000838900080880A102838910004180000249 ++:10F9A00083090000008080050000008000800008BE ++:10F9B0000300000040804080000003008040890078 ++:10F9C00000118300000402004020030005039000A2 ++:10F9D00011C08280C00010400980104002000288DF ++:10F9E0004080030811004000118240000000000028 ++:10F9F00005000900000000000000090000000000F0 ++:10FA00000000410000088082090800C002020010C6 ++:10FA10000921400302080011090940030390001165 ++:10FA20000589C083414000404000050000000200FD ++:10FA300040808080008020021010004010030009E8 ++:10FA40000080008011840220004110C10083091051 ++:10FA50000088000989040000000000808000830401 ++:10FA60004004400200034010000808088908001004 ++:10FA700000110810802000000000000000000000BD ++:10FA80000000000001000089C09109084089018937 ++:10FA900000000189C1410103C0A101C101030109A5 ++:10FAA00000090185A189011000010000100000A0DB ++:10FAB000000001A088820080010000000001020116 ++:10FAC0000010000800A00988008300080010A0832F ++:10FAD0000000001100008211C00200C000848204F6 ++:10FAE00009C100A100C1A0C1010300C0001182C171 ++:10FAF0000000000000008201000000000000000083 ++:10FB0000000000080000000083898589890089C001 ++:10FB10001102898382008888858989898900890200 ++:10FB2000018801830188010101C001A001000100D9 ++:10FB300001880103030000000080010000010101B1 ++:10FB4000010009880940880088900908880082011E ++:10FB50008800914008A04001888800A000000000B3 ++:10FB600000C00182010001910000010400040100B5 ++:10FB700000000000000000910000000000000000F4 ++:10FB8000000000000080000000008988051189083D ++:10FB9000C0008391829110001000839084110900AD ++:10FBA0002000038004111080214109802080020080 ++:10FBB00040000380408202080800008003000940E2 ++:10FBC000202120000388048011080900830000021E ++:10FBD0000221020003801109094000000000000812 ++:10FBE000000800000380040002034011030002101B ++:10FBF00002040800000000090040000000000000AE ++:10FC000000000000000000000000000000000013E1 ++:10FC1000C2000000124100066000420000420013D2 ++:10FC200060000000064100066000210041840006DB ++:10FC30006000000012000006C20082000000820086 ++:10FC400000060000000012410013600000000000E8 ++:10FC500000130000000081000006C2000A4281413A ++:10FC60000006C22000420000001360001242210082 ++:10FC70000013C200004241840013C2000042000091 ++:10FC80000000000000000000000000000000FFFF76 ++:10FC9000FFFF3C7C3C3E5C3C2424CC3C5666FD0291 ++:10FCA0006600FC036566DF206600FC036566F7FFFF ++:10FCB0000800FDFDFDFDBDBDBC3D000000000000D5 ++:10FCC0000C30000005A00000FC0C6F6F00003C3CF5 ++:10FCD000444400004488000000000090FFFF04003E ++:10FCE0000000000000000000000000000000000014 ++:10FCF0003C99C30FFFCFF0C0000000000C000C00C7 ++:10FD000000000000000000000000000000000000F3 ++:10FD1000FB0004003C3E3C3E3C3C24243C3C6666EC ++:10FD2000FF006600FF006666FF006600FF00666673 ++:10FD3000FFFF0000FDFDFDFD3C3C3C3C00000000E1 ++:10FD4000000003C0000005A00000FC0C6060000083 ++:10FD50003C3C88880000448800000060009004005B ++:10FD6000040000000000000000000000000000008F ++:10FD70000000C399C30FFFCFF0C0000000000000D7 ++:10FD8000240000000000000000000000000000004F ++:10FD90000000000000000000000000000000000063 ++:10FDA0000000000000000000000000000000000053 ++:10FDB0000000000000000000000000000000000043 ++:10FDC0000000000000000000000000000000000033 ++:10FDD0000000000000000000000000000000000023 ++:10FDE000000000000000000000000000C21002003F ++:10FDF00000218461000000000000000000000000FD ++:10FE000000000000000000000000000000000000F2 ++:10FE100000000000C0C0C0C0F0F0F0F000FF04FB24 ++:10FE200096660FF0F0F0D4F066690FF020DF00FF67 ++:10FE3000A6A6333300FF04FB00000000FFFF000014 ++:10FE4000000066660000000090600000505096962A ++:10FE5000303F0000F0F000000C300000906024F40F ++:10FE600042F23CFF1CFF0000000000000000000008 ++:10FE7000000000000000009600964B4B424200003C ++:10FE80000000009966FF0000000000000000000074 ++:10FE9000000000000000C0C0C0C0F8F8F4F800FF87 ++:10FEA00000FF96660FF0F0F0F0F066690FF000FFCB ++:10FEB00000FFA6A6333300FF00FF00000000FFFF95 ++:10FEC00000000000999900000000090600000A0ADD ++:10FED0009696303F00000F0F000003C00000090697 ++:10FEE00024F424F43C3C1C1C00000000000004002E ++:10FEF0000000000000000000C3960096424B424BF9 ++:10FF0000000000000000FFFF00000090090000005A ++:10FF10000000009009000000008600D10880001059 ++:10FF2000058600B401A20010058600B500A20010ED ++:10FF300005860074019204100086007401300000F0 ++:10FF4000100000F009104860000000C700E0013018 ++:10FF50005100080604750198486000C700E10030B0 ++:10FF600051000586007009B004000086006409F0A5 ++:10FF700004000886046008B200100586007009F8C5 ++:10FF800004000086026409B0040000000020001094 ++:10FF9000014000000020001001403000F0003D3C16 ++:10FFA0007C3CFF00FF00FFC3FFFFAAAEAEAA00002B ++:10FFB0000004000000000C000000000000003C3CB9 ++:10FFC00000000000F0F03C3CFF00000000000000DA ++:10FFD00055550000FFFFFFFF0030FFFF000002004B ++:10FFE00000000000FE3DC201FFFFF0F00000000035 ++:10FFF0000000000000000000FFFFFEFF0000000006 ++:020000040003F7 ++:100000003C3C3E3C0000000000000000004040007E ++:100010000002020000404000000202000000000058 ++:100020003C3C7D3CDF20FF00FFC3FFFFAEAAAEAA31 ++:1000300000000000000000000C00FFAA000000000B ++:100040003C3C00000000F0F03C3CFF0000000000E1 ++:10005000000055550000FFFFFDFF0030FEFE0000D0 ++:10006000000000C00080EA29D615FFFFF0F0000074 ++:1000700000008000000000000000000004000000FC ++:1000800000003C3C3E3E000000000000000040003C ++:1000900000000000000240000000000000023C3CA4 ++:1000A0003C3CFFFFFFFF000000000F1B0F0FA0A054 ++:1000B00000003C3F3D3E000000000000C3C30000C4 ++:1000C00000000000FF000000F0F00F0F0000000033 ++:1000D0000000000000000000000000000200FDFD24 ++:1000E0000000000000000000000000001E1E14BE02 ++:1000F00000000000FFFF7DFF000000000000000086 ++:1001000000000000000000000000000000000000EF ++:1001100000000000000000000000000000000000DF ++:100120007CBCFC3C04380000000000000F0F0F0FE7 ++:10013000A0A000003C3F3C3F000000000000C3C303 ++:10014000000000000000FF000000F0F00F0F0000B2 ++:10015000000000000000000000000000000002029B ++:10016000FDFD0000000000000000000000001E1E59 ++:1001700014BE00000000FFFF7DFF00000000000033 ++:10018000000000000000000000000000000000006F ++:100190000000000000000000080000000000000057 ++:1001A0000800000000000000210000000000000026 ++:1001B000000002000000000000000000000021001C ++:1001C000110000000000000004000000000000001A ++:1001D000000000000000000000000000000000001F ++:1001E000000084000900210000000000210021001F ++:1001F000000021001100110000002100000011008A ++:1002000021000400040004000000040084000440F5 ++:1002100011000400000000000000010000000000C8 ++:1002200000000100000000000000000000000000CD ++:1002300000000000000000000000000000000000BE ++:1002400000000000000000000000010000000000AD ++:10025000000000000000040000000000000000009A ++:10026000000000000200000000000000000000008C ++:10027000000000000000000000000000000000007E ++:10028000000000000000000000000000010040002D ++:10029000000000000000000000000000000000005E ++:1002A000000000008000040004008400040000003E ++:1002B00000000000000000000000800000000000BE ++:1002C0000400000000000000000000A0000000008A ++:1002D00000000000040000C0000002000000000058 ++:1002E0000040400008000010000940C0000000006D ++:1002F00000000300020000200000880180000001CF ++:1003000000008000800084000088000000000000E1 ++:10031000000000008000000000000000000000005D ++:100320000000000000000200010001004100010087 ++:1003300000000000000000000000000008000000B5 ++:10034000000001000000A000000000008400000088 ++:10035000001100000000011000000000011000006A ++:10036000001000800100010000C1009001000000A9 ++:10037000000000419000A10090910009211002109E ++:1003800000208200020004000900000000000000BC ++:1003900000000000000004008200000000000000D7 ++:1003A000000000000000000000000000000000004D ++:1003B0000000000000000000000000C00084802059 ++:1003C00000000000000400040000000000840000A1 ++:1003D00000000010000000000082000000000090FB ++:1003E0000010000000080040000080C100820020D2 ++:1003F000008400C0002000C00082008400A000A093 ++:10040000002080C000C000090082002000C000A1C0 ++:10041000008800010000801000000084000000003F ++:1004200000000000000000000000000000000000CC ++:10043000000000000000000000410000A0000000DB ++:1004400020800010000000C100800000000000219A ++:10045000C0000000000000000000000000000000DC ++:10046000A0100005C010908000800000040400115E ++:1004700000910405000200209011C041C00000005E ++:10048000004100101000A000A0C08420A080A000A7 ++:10049000A00200400004000520100009C041000037 ++:1004A00000000000800000000000000000000010BC ++:1004B0000000008220A000000088A08804208001A5 ++:1004C000000002209000800200028800840402A044 ++:1004D00003004188020000900004A10441040000D0 ++:1004E0000384038411A0118411000908104182853E ++:1004F000049104000541004000000982020000014F ++:1005000000900890411000A009000001210008009F ++:1005100000900420020000040400040484100082FF ++:1005200000000000000002000000000000000000C9 ++:1005300000800000000001000000000003000180B6 ++:100540000420000000802000048000802103098036 ++:100550000000000082001000000000804080008049 ++:1005600000000005001090100000000002800082D2 ++:100570000210012001050002008088000000C10077 ++:100580000020820088000010001000008840000356 ++:10059000010500000180000000800100858021002D ++:1005A000000000000000000000000000210000002A ++:1005B0000200000000C0112004002010200002846E ++:1005C0002010200020100000200040000000040047 ++:1005D0000810008240C0040041A00002090441004C ++:1005E0000090000000104188000004000500024057 ++:1005F00040400820020441C041400500092021A0DC ++:100600001120024021C011A0038800000002000850 ++:1006100000044004000000000088801004000484EE ++:100620000004208400400000900000008800A0002A ++:100630000000000000000000008001000100010334 ++:100640000120010001000100000001000000000085 ++:100650000103C01000000000012000000000008025 ++:10066000000000020000C002A00000210100900074 ++:100670000100010511400380000000808209000094 ++:100680000405A08904000000080000108800001183 ++:100690000880408089800000000082090409010070 ++:1006A0008500C0908900000000000000000000A04C ++:1006B00000000000000008C004000400000000006A ++:1006C00020842040004080C0000083A02020000043 ++:1006D000800008820000000000C0000003008004C9 ++:1006E0000202000041820000C140038480108901A1 ++:1006F00010844000108485008208020111834100AB ++:1007000000A0808408840088030208854108030053 ++:1007100000C0104000000010004041000000000434 ++:1007200040844084000084C00000000000000000FD ++:1007300000000000000000000100010001000000B6 ++:1007400000000100018000802000000008000189F5 ++:1007500000002000000010000010000084050000D0 ++:100760001080828082110000000002800003088057 ++:10077000024001210100C10002004080C0080002C7 ++:100780001003000004000009000000800010008039 ++:1007900000000000018000000080900000000000C8 ++:1007A00008800100010300000500000000000000B7 ++:1007B0000080000004000000008080800400808031 ++:1007C00000000010000940000000048400880000C0 ++:1007D0000000C0C0000580402040800588092140FD ++:1007E0000908004000400011000800C0808320205C ++:1007F0001082030589C080040211082005200840EA ++:1008000021114104410302000440204190080004EA ++:100810000009081003038440090004080000800058 ++:100820004180000011110009800209090000000048 ++:100830000000001000000000000000C008880184D3 ++:1008400010A000900001000101000000048200855A ++:100850000000000289838888088301090801890152 ++:100860008300010010000000000000000000408331 ++:100870000889001100088482840001C10140C10080 ++:100880008489A191018800019000A0010100090163 ++:100890000001000001010100840000000000009040 ++:1008A000C0400240009089010001080101010100DF ++:1008B000000000000008000000000000008808019F ++:1008C000C090880083C09100C1C100901101C00197 ++:1008D00085850000018883009000088801908201CE ++:1008E0008488C1888901000000080000010100001F ++:1008F00000000020000001A00801044090019100C8 ++:10090000089000028800838284010805109183C04A ++:100910001000C000080004008301C000090290A07C ++:1009200090000000400040880188000000A0010104 ++:1009300010000000000000000300000000000000A4 ++:100940008008C000800889901000400900008909D3 ++:1009500004048809000003A040080500008003800B ++:100960000802808085808911050011900008030825 ++:10097000000000400500030003000440000089104F ++:100980008300821100800020830802038083854158 ++:100990008300800000008000800010200500C1005E ++:1009A000A0000040000000000009020000000080DC ++:1009B000030900000000000011000000000000001A ++:1009C00040000080000000000080C01000090909FC ++:1009D0000000800800000909400002020005A04054 ++:1009E0004183000200880308089080000000020094 ++:1009F00003000000050900C10003000310110020DE ++:100A0000830341109105000811A0030805C00020D0 ++:100A10000000050304400040004008202084000539 ++:100A200000A00091000080000880008004041141B3 ++:100A300000098983000000000000000000000000A1 ++:100A400000000100000810008210008889A100A0A9 ++:100A500001A190008801A010C111010001419090F6 ++:100A600091010189008900080083C089820000008B ++:100A70000100A000000000900810000400410140A7 ++:100A800088A09008418883A09089008401C00091CB ++:100A90000041000800090000000000A0C00000089C ++:100AA00000A000408809008204A0838400020101A4 ++:100AB0000101000189890000000000000000000021 ++:100AC00000000000000090118882100089880188D1 ++:100AD00001100000008883C0C084A00008008200CC ++:100AE0008803880040408310011008001104019021 ++:100AF000018800000100000091C084008800880087 ++:100B00008301404088002000418585A008009008AE ++:100B100041A01104040010080000000000000010B3 ++:100B200082000441C00004908404A0020800020274 ++:100B300000020009000100010000000000000000A8 ++:100B400000000000000000008811C089400088807B ++:100B5000108004800000008008000000001189005F ++:100B6000800080400000000090914111834090007F ++:100B700003001000100011000000030002052041D6 ++:100B80004100831008110209000503A108008840F4 ++:100B900040000311844111418080000400000000E6 ++:100BA0000080800900C100048000800500008000F2 ++:100BB000800000800091002100090000000000007A ++:100BC0000000000000000000000000410010600074 ++:100BD000420000880006600000000041000660003E ++:100BE0000000000000136000000000000013C200BD ++:100BF000000011410006C200420000000000004257 ++:100C00000000000000840013600000000084001356 ++:100C1000600012600000001300008100004100131A ++:100C2000C200000082000013C20021000000001377 ++:100C3000C200000081810013C2000000000000001B ++:100C4000000000000000000000000000FFFFFFFFA8 ++:100C50000000000000FF00FF30CF30CF3C3C3C3CA8 ++:100C600028D728D700000000FF00C3C30F3FCFFFE5 ++:100C70003CFF3F3F2C20505F0000000000000000C0 ++:100C8000300C0000030C00FF00FF040000003C5586 ++:100C9000FF0F85758F7F00005005000006060000DD ++:100CA0000000000000040000000000555500000096 ++:100CB00000000000000000000000556530CF00007B ++:100CC00000000000000000000000000000007FFFA6 ++:100CD000FFFF0000000000FFFF0030CF30CF3C3CA2 ++:100CE000C3C328D728D7000000005FA063C300302B ++:100CF000C0F000C303030000505F000000000000CC ++:100D00000000C0030000C03055550F0F0000000068 ++:100D10003C55000F8A7A80700000A00A0000909075 ++:100D20000000000000000000000000002075752099 ++:100D3000000000000000000000000000555500FF0A ++:100D400000000000000000000000000000000000A3 ++:100D500000000000AFAF5050FF00FF00F3F30C0C99 ++:100D6000AAAA55AAC0C0FFFF55555555C6C65A5A1E ++:100D7000FB0BF808FFFF0000000000013333000008 ++:100D80000000330000000AA000003C3CAAAA7DFF3E ++:100D90000041FFFF00003C3C0000606000002814A0 ++:100DA00000000000ACA000000000FF3C003C01017E ++:100DB000ABAB0000000000000000EF10FF003C3C67 ++:100DC000AAAA0000000000000000000000000000CF ++:100DD000000000000000AFAF505000FFFF00F3F331 ++:100DE0000C0CAAAA55AA3F3F000055555556C6C639 ++:100DF0005A5AFB0BF8087D287D2800000001333388 ++:100E00000000000000330000055000003C33AAA59C ++:100E1000FFFF0082FFFE0001C3C3000009090000BC ++:100E20008241000000000C0000000000FF000000F4 ++:100E30000500AFAA0000000000000000FF00FF0056 ++:100E4000C3C39696000000000000000000000000F0 ++:100E5000000000000106009400800803C086C075F1 ++:100E600030B00803C084C055308042030080008148 ++:100E700008820010008600F008800000A5865274E9 ++:100E8000A9B04C65000000C7006104B051000584A2 ++:100E9000006508B080A0A58E00B508B8486000C7FE ++:100EA00000A1009051000086006408380000008610 ++:100EB000027109800000008600B10890008500865C ++:100EC00000F40192001000000090090000000000F2 ++:100ED000009009000000000000003CFF3C3C0000C6 ++:100EE0000000FFFBFFFBFFFFFFFF00F000F0FB082F ++:100EF000FEFE0000FFFFCFCFDFDF2F001F0000004E ++:100F00000000000000000000B1B1FFAA4FDF0F5F3A ++:100F10003A3A3F30FFFFFFFF08FFFF083DFFFDFFAC ++:100F20000004AAAE3C3D7D7C0000000000FF0000F4 ++:100F30000000000000000000FFFF90A07D3C773320 ++:100F400000000000FFFF0000000000200010014032 ++:100F50000000002000100140D020F0003CFF3C3C8D ++:100F600000000000FFFBFFFBFFFFFFFE00F000F0B2 ++:100F7000FB08020230303F3FCFCFDFDF2000100000 ++:100F800000000000000000000000B1B100555FFF4C ++:100F90001F7F3A3A3F30577FFFFF08080808C2001A ++:100FA0000200AAAE00043C3C7D7D0000000000FF72 ++:100FB00000000004000200100000FFFFA0A0550088 ++:100FC000550000000000FFFF00000040400000024C ++:100FD000020000404000000202000070AAAA0202C3 ++:100FE000010200000000656530300055C3C3333393 ++:100FF0003333B4F0FFBE1CBC1CBC0000000000007A ++:10100000000000000000000000000000005000147C ++:1010100000000000A0A0C3C33C3C3C3C20002000DA ++:10102000FF553C55000000008200A00000000000B9 ++:10103000554D5555000000000000000870505050FC ++:10104000FF00C33C00000000000000004000000062 ++:1010500000000002400000000000000200700000DC ++:10106000010100030000000065653030FFAAC3964F ++:1010700033333333B4F000141CBC1CBC000000003C ++:10108000008855DD00000000000000000000005056 ++:10109000001400000000A0A03C3CCC3C3C3C2000E4 ++:1010A000200000553C55000000000000A00000009A ++:1010B00000005555555500000000000000002000BC ++:1010C0000000AAAAAAAA0000000000000000000078 ++:1010D00000000000000000000000000021000000EF ++:1010E00000000000200000000000000000000000E0 ++:1010F00000000000000041000000000000000000AF ++:1011000004024000210020000090200000000000A8 ++:101110000000000041000000000000002100080065 ++:1011200084000800A00000008000A00088002010BB ++:1011300021000000040020001182000004001100C2 ++:101140000000040404002000080004002000044003 ++:10115000000000000000000000000000000000008F ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:101180000000090001000000000000000100000054 ++:10119000000000000000000000002000000000002F ++:1011A00000000500010005000000400010001100D3 ++:1011B00000800000000000000000000000000000AF ++:1011C0000000000000000000820000000000040099 ++:1011D000000000000000000000000000000000000F ++:1011E00000000000000000000000000000000000FF ++:1011F00000000000000000000000000000000000EF ++:10120000000000000000000000001000000080004E ++:1012100080000040000000000090000000900000EE ++:10122000004000008000020000400020000000415B ++:101230000008802100000000000000000000000005 ++:10124000000000000004000000000000000000009A ++:10125000000000000000000000000000000000008E ++:10126000000000000000000000000000000000007E ++:101270000000000000000000000000000008000066 ++:10128000000000000000000000000000000000005E ++:10129000041010000000000000000000000000002A ++:1012A0000011000000410400014100800000200006 ++:1012B00000A0008804C00000000000000000000042 ++:1012C0000000000000000000000000000000000816 ++:1012D00000000008200800000000000000000000DE ++:1012E00000000000000000000000000000000000FE ++:1012F000000011100900050000000082000000003D ++:1013000000000000000000000800000009000900C3 ++:101310000000002000000000000000000584000024 ++:101320001000020000C0000000008240849090A0E5 ++:10133000400211910410028208C041000000040024 ++:101340000000040000000000000000001000040085 ++:1013500000004100210021000000400000000000CA ++:101360000010000000050000000000000000000068 ++:1013700082030021000000000000000000000000C7 ++:1013800000000000000000104000001020050021B7 ++:1013900000008440A005004100002000C021004062 ++:1013A00000000003002100058221000021C121214D ++:1013B00011048590A0080090011082118200C003E2 ++:1013C000C0039000C00000000040000000000005C5 ++:1013D00008000000000008100000000000000000ED ++:1013E0000000000000000000000000000000008479 ++:1013F00000000000000000000000210000000000CC ++:101400000000000000040000004000001100800007 ++:10141000840009C0000000820004000000000000F9 ++:10142000000000042000000000C00400C0908841BB ++:1014300002C110001000022100080888000000828C ++:1014400000A0000000A0210000001000000000002B ++:1014500000000000040041000900410000000000FD ++:10146000000000000000000000000000000000007C ++:10147000000000000000000000000000000000006C ++:10148000A008000088000000000000000200001119 ++:10149000080002000003A00000000080000090008F ++:1014A0000000024100000003000984030041050020 ++:1014B00009C091040303C01101C00090C110C00015 ++:1014C0000004020000000000A000002182040000CF ++:1014D0000000000000102000840400000000000054 ++:1014E00000000000000000000000000000000000FC ++:1014F00002000000000000000000000000080200E0 ++:1015000000000200000000000200020002000000D3 ++:101510000000058805000000000000000000000039 ++:101520000900000000A0008400000002000000008C ++:1015300000010011804100008011040988838000AF ++:10154000030000000000004000400000000000C058 ++:10155000100000000010000040000000098205009B ++:101560000002400000000000000000000000000039 ++:1015700000000200000502098200000000210008AE ++:10158000000000000003002100008800000084002B ++:101590004004002020212000020800080003004031 ++:1015A0000000000020000020C00500050403041115 ++:1015B00020000002009004C01041400289C01108C0 ++:1015C00004210411C0008421C0029000A0218408DD ++:1015D0001010000000001000000000000400A00037 ++:1015E000901000000000000000000000000000005B ++:1015F00000000000000000000000040000000000E7 ++:1016000000000000009021400900020003000900D2 ++:1016100010400000040000001000000000002084C2 ++:1016200000100000000000000900000441000984CF ++:1016300000840000040000110001098980C100013C ++:101640002010001000000000110000040000000045 ++:1016500000080000000410100090040000000000CA ++:101660001100000000000000000000000000000069 ++:101670000000000000410000000000000400002005 ++:101680000020040000000000000000000000001026 ++:101690002005A00084000009044090000000001014 ++:1016A00000058810000000008805900388030000F2 ++:1016B0000000880800200109108410401008400232 ++:1016C000A040100384A0C000C04102000000004000 ++:1016D0000040000010041000104020008841000469 ++:1016E00020008805820000000000000000000000CB ++:1016F00000000000000000000000000000000000EA ++:1017000000000000000080000000000000008000D9 ++:1017100009000080800403000300002103418000D1 ++:101720000000800203000080000000000080000034 ++:1017300000000300008080C1830003000003034118 ++:101740008000000080020300000000000000000094 ++:101750000000000000000000000000000000000089 ++:101760000000000000000000000000000000000079 ++:101770000000000000000000000000000000000069 ++:101780000000000000000000820000000082000055 ++:10179000820000000010108401C0C182000001011D ++:1017A000828200C08283010000000000000000A0CF ++:1017B00000000000010000A082C183A0A1840001FC ++:1017C0000101828200848283010000000000000089 ++:1017D0000000000000000000000000000000000009 ++:1017E00000000000000000000000000000000000F9 ++:1017F00000000000000000000000000000000000E9 ++:1018000000000000000000000000000002000000D6 ++:1018100000000000050000018400888382830083AB ++:10182000C10082000582008200A000000000C0000C ++:10183000000000010000C1000001C001908385820A ++:101840000005C10082008582008200820000000045 ++:101850000000000000000000000000000000000088 ++:101860000000000000000000000000000000000078 ++:101870000000000000000000000000000000000068 ++:1018800000000000000000000000000000008000D8 ++:10189000000000000000040000410000028309A0D5 ++:1018A0000083C10000008480008000000000000070 ++:1018B0008000000000030000C1000003800340839B ++:1018C00002890083C10000000480008000800000C5 ++:1018D0000000000000000000000000000000000008 ++:1018E00000000000000000000000000000000000F8 ++:1018F00000000000000000000000000000000000E8 ++:1019000000000000000000000000000000000000D7 ++:1019100000000000000000000000000009C10011EC ++:10192000000083C1000000000000830000000000F0 ++:10193000000000000000000000000000008003C163 ++:10194000001100008302000000000000830000007E ++:101950000000000000000000000000000000000087 ++:101960000000000000000000000000000000000077 ++:101970000000000000000000000000000000000067 ++:101980000000000000000000000000000000000057 ++:10199000000000000000000000000000004000C146 ++:1019A0000082008283C10000000000C0838200002A ++:1019B000000000000000000000000000000000C067 ++:1019C00001C10082008283830000000000848382C2 ++:1019D0000000000000000000000000000000000007 ++:1019E00000000000000000000000000000000000F7 ++:1019F00000000000000000000000000000000000E7 ++:101A000000000000000000000000000000000000D6 ++:101A10000000000200000001000000000082A100A0 ++:101A20000000830001830183000082820000010026 ++:101A3000029000000000000000010000008201820E ++:101A40008300000083820001018300008282008203 ++:101A50000101C08300000000000000000000000041 ++:101A60000000000000000000000000000000000076 ++:101A70000000000000000000000000000000000066 ++:101A80000000000000000000000000000000000056 ++:101A9000000000000080000000020000000009803B ++:101AA00040000000021040834183000000800000DD ++:101AB000024180410000000000000003000000809F ++:101AC00004800200000002C0410302830000008085 ++:101AD000008002038083000000000000000000007E ++:101AE00000000000000000000000000000000000F6 ++:101AF00000000000000000000000000000000000E6 ++:101B000000000000000000000000000000000000D5 ++:101B100000000000000000000000000012000000B3 ++:101B20000000000012002150000660001242000078 ++:101B3000000000001242000000000000000000420F ++:101B400000000000000012428148001348001242C9 ++:101B50000000000000001242000000000000000031 ++:101B60000000000000000000000000000000000075 ++:101B70000000000000000000FFFFFFFFFFFFFFFF6D ++:101B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 ++:101B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 ++:101BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:101BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:101BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 ++:101BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 ++:101BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 ++:101BF000FFFFFFFFFFFFFFFFFFFF0040AA570C445E ++:101C0000C02000E80A060000605900000000000043 ++:101C100000000000000000000000000000000000C4 ++:101C20000000000000000000000000400000000074 ++:101C300000000000000000000000000000000000A4 ++:101C400000000000000000007B7500000040000064 ++:101C50000000000000000000000000000000000084 ++:101C6000000000000000000000007B710000000088 ++:101C70000000000000000000000000000000000064 ++:101C80000000000000000000000000000000000054 ++:101C90000000000000000000000000000000000044 ++:101CA0000000000000000000000000000000000034 ++:101CB000000000000000000006000000000000001E ++:101CC000300200000000000040031E780000000009 ++:101CD00000000000000000000000060000000000FE ++:101CE0000000300000000000000000031E60000043 ++:101CF00000000000000000000000000000000000E4 ++:101D000000000000000000000000000000000000D3 ++:101D10000000000000000000000000000000800043 ++:101D200000000000000000000000000000001000A3 ++:101D3000000000000000000000000000040002009D ++:101D400000000000004041000000210021000000D0 ++:101D5000040410000200000000A000002100400464 ++:101D60000482000021004000080000000000020082 ++:101D7000000000001100A0C00800200020000400A6 ++:101D800004000000040004002002200200002000E3 ++:101D90000000000000000000000000000000000043 ++:101DA00010000000000000000000000008002000FB ++:101DB0000100000000000000000000000000010021 ++:101DC0000000000000000080000000000000000093 ++:101DD00000000080010001000000000000008800F9 ++:101DE000008000008200000000000000A000000051 ++:101DF00001000000000000000900010000000000D8 ++:101E00000000000000000000000021802180000090 ++:101E100001000000000000000000000000000000C1 ++:101E20000000200000000000040000004100090044 ++:101E300000000000000000000200000000000000A0 ++:101E4000040000000000000000209000000080005E ++:101E5000840000C0000000000000000000008000BE ++:101E6000A00041008000000000000000002000846D ++:101E7000004000200000020000000000804100003F ++:101E8000801080000000040080200001000000009D ++:101E900080010002000000000000000000000000BF ++:101EA0000000000001000000000001000000000030 ++:101EB000820000000000000000000100000000009F ++:101EC000000001000000000000000080040000008D ++:101ED00004001100000000000000000000000000ED ++:101EE000400011110400400082000000002000802A ++:101EF0000010000000C100000121000090030890C4 ++:101F0000080002800200000021030280000400009B ++:101F10000009200200900000000000000000000006 ++:101F20000000000011000000090011001100000075 ++:101F300000000000200000000000200802880000CF ++:101F40000000000000840000000084002102210045 ++:101F5000101000A00204000000000011418200A146 ++:101F600000100040008400080982004000000000CA ++:101F700000900900004020020088C0A00008201145 ++:101F8000000800080000A1020021040800A00011C0 ++:101F9000000000A0804000400000000000000000A1 ++:101FA0000000000000000000000000000000000031 ++:101FB0008800000002000000000082000000A00075 ++:101FC0000000000000000000000090004000000041 ++:101FD00000000100000000800000000000840000FC ++:101FE000004000000080000500000009C0A00000C3 ++:101FF0000041000000410080000000000305008057 ++:1020000001200080008000090290002001808200F1 ++:102010008202100040000211A00000000000000039 ++:102020000000000000000000000000204000000050 ++:1020300000000000002000010090000040000400AB ++:10204000000100000000000000000000000020006F ++:102050000001800000001000204000000200820803 ++:10206000112190010000840004000820C10021001B ++:10207000840011200500050010011010030002016A ++:102080008300050000A0800000C100100490000043 ++:1020900020000900030003010000101000000000F0 ++:1020A000000000000000000000000000000001002F ++:1020B0000000000000000080882000200000C10017 ++:1020C00000000020000000000000002100000011BE ++:1020D0000000002040050000010000A10000830373 ++:1020E00003102004050490091011C000C1C1404133 ++:1020F000C003104104800000000084200011022170 ++:1021000001020221002000000200100200218900CB ++:1021100000009010C00020000402840000040000B1 ++:1021200000000000000000000000090000000000A6 ++:102130000000000009000900000009040921000056 ++:10214000400000080900804000000010112000003D ++:102150000004000000A0000004000040020800008D ++:10216000108820C0008821400084004002000084C4 ++:102170001002008840C002201090022140900440CC ++:10218000101010881000410008000004034003C034 ++:1021900000000408218804000200004003090084B4 ++:1021A000000000000000000000000000000000002F ++:1021B0000000000000000000000004000000A0403B ++:1021C0000000000000000000020984050200000574 ++:1021D000881100048200004000210100000001007D ++:1021E00000000100010000000080000000800100EC ++:1021F00000404180000501000109900001A001108C ++:10220000010000000010000000000100000000803C ++:102210009000000001800000010001000000044067 ++:1022200000000000000000000000000000000000AE ++:10223000000000000000040000000000002000007A ++:1022400000000000A10020000000040004000000C5 ++:102250000400840000001101002000A0908405000B ++:102260004010000000098040A0048010020000A07F ++:10227000000041880988091010084110910000826F ++:102280000001091004108310004000848440841170 ++:1022900004C1040400900010041100200800038809 ++:1022A00020200400000000000000000000000000EA ++:1022B0000000000000000009000000200000008075 ++:1022C0000009000500001041000000050000880022 ++:1022D0008200000008000000884000900200050015 ++:1022E00004000510000000200405040004000000A4 ++:1022F00000000000A0009000000089830003080592 ++:102300008805002008058808100590A00011030921 ++:102310000302031021410000C000012004802111AC ++:102320000000880001000000000000000000000024 ++:102330000000000000000000000000000000030397 ++:1023400000210503034000080010081100090003E4 ++:10235000000003041109A003000421402003C1036D ++:1023600000002103110800C00005899188080008B9 ++:10237000094010052041040382008800410020002C ++:102380008383C00002C140081041000520110220D3 ++:102390000083400802C000090805400509084105FE ++:1023A0001103008900020484000000000000000006 ++:1023B000000000000000000000000000000000001D ++:1023C00089010000200000008800000001000000DA ++:1023D000880984200000000441010201010001007D ++:1023E000880184002000000000000009208583C1CE ++:1023F000002100000100C101000021008300000055 ++:10240000010089834004910200880100020000015C ++:1024100000009083119001020040000121000000A3 ++:102420000001C101000500010020000000000000C3 ++:102430000000000000000000000000000188000013 ++:10244000010082012010A08985840800100010C1BD ++:102450000900C00020A0A000210009000890200071 ++:102460008300100809008888010000008409910396 ++:1024700089C1888891000800080088C0A0000284F3 ++:10248000028903C10090210009108390020084108A ++:102490000500400540030008020282C004A09088A5 ++:1024A00003A1050089000182010301010000000071 ++:1024B000000000000000000000000000000010000C ++:1024C0000000030009028880808983850000800065 ++:1024D00080098300000089000500830010001000BF ++:1024E00080028304C0800800850003090000C089C1 ++:1024F00090A011A0119011001100410008210811B5 ++:102500008900100890890800C00020098300880510 ++:102510008900050410C080400080804180808900CF ++:1025200010004105C0001000410040910309000067 ++:10253000000000000000000000000000000000009B ++:102540000000400000001000001003A1000308007C ++:102550000000098090000411001040C140032008D1 ++:1025600000910900800303101191108883830000FB ++:10257000A000210085002180020400914090C0103D ++:102580000008000800848003408090020005C18399 ++:10259000088500C02109108803808200008008009F ++:1025A000020220A003080308101000022009910372 ++:1025B000000000000000000000000000000000001B ++:1025C00000000000000040000008000000200001A2 ++:1025D000010800100084C040008800080084000149 ++:1025E000008300C00004880900A00021018590211B ++:1025F0000000048809900282A082010000C000103F ++:10260000880100C000840084824100040388108295 ++:102610008305010800C000880941009008C08204B9 ++:102620000304008301080089A108010100010101E0 ++:102630000901000000000000000000000000000090 ++:102640000000018800000100000083098800A0014B ++:1026500002020189008401010190010000000100D3 ++:1026600000080108000100000088000000040000CC ++:1026700000890000884010408801C02082419021DC ++:10268000822120C041C18800400110408540C00225 ++:102690009001034082A040021001082185A0A10002 ++:1026A00090010004000200400001011001880111A6 ++:1026B00000000020000000000000000000000000FA ++:1026C0000000000003801100020800000382800562 ++:1026D0000502898003820004414009800321091119 ++:1026E000081103800380402005030000000000085B ++:1026F000004000880000A120A021A00203808008E3 ++:1027000000080010008003C103112003A000839182 ++:10271000110082402080A14021048408919083040C ++:102720002140881020002184114105104180038040 ++:10273000041104040200000000000000000000007A ++:102740000000000000000684000660000000110088 ++:1027500000060000060000820013C20000002100F5 ++:10276000001300000000810000060000000021426C ++:1027700000136000000000000A500013C200008136 ++:1027800000000013C20000000042000660008282C8 ++:10279000000000130000414121810013600000008F ++:1027A000000000060000000000810013C20000507D ++:1027B00082000013C20000000000000000000000C2 ++:1027C0000000000000000000000F000000000000FA ++:1027D000444400000609000009090303000000004A ++:1027E000CC000000CC0000000660000F0505E2E20E ++:1027F0000000000000A60FCC0000FFFFFFFF00005C ++:1028000000000000000000000000DD4442429F9FE5 ++:10281000BD241482E3400609F0F600000001C7045D ++:1028200004043C3C0F0F000000002C2CC30300D01C ++:1028300000DB3F306666FF006666000000000000B7 ++:1028400000000000000000000000000F0F0F00005B ++:102850000000888800006090000009090303000060 ++:10286000000000CC000000CC00000990066FA0A082 ++:10287000424200000000F0A6F0CC0000FFFFFF7F06 ++:1028800000000000000000000080000044DDDBDBF1 ++:102890000606BD241482E340609000600000000042 ++:1028A00004040404FF006666000000000000FF0F3F ++:1028B000D0D0DBDBFF003636CF0C2727FFFFFFFF32 ++:1028C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 ++:1028D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 ++:1028E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8 ++:1028F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8 ++:10290000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 ++:10291000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 ++:10292000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 ++:10293000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00C0E5 ++:1029400074560C44C0A000180A060000304D000068 ++:102950000000000000000000000000000000000077 ++:1029600000000000F0F00000003300000505DBDB94 ++:102970001300000066660000282800009060000C2C ++:1029800000334242A0A080808181FFFF00FF000051 ++:10299000010000003CFF69666666F0F03CFFBCFF8A ++:1029A00000000000CFFFEFFF1D1D2222000C0C30A5 ++:1029B0000000000000420000F3F3427E99999999CB ++:1029C000FE00FFFF000040006666C0FC6666F0F097 ++:1029D00000000000000000000000000000000000F7 ++:1029E0000000000000000F0F000033000000A0A056 ++:1029F0003434ECFF000099990000414100000906C1 ++:102A00000CFF3300E2E2050580800000FEFF01FEBE ++:102A10000000C1000000C3006966A56633F03CFFFA ++:102A20007CFF00000000000020000C0C11113C3F56 ++:102A300003C0800000000000F0F03030427E000053 ++:102A400000000000000000000000E4E400FF24E7B4 ++:102A5000C0FC0000000000000000000000000000BA ++:102A60000000108E006401B04C6000C700A001A0FF ++:102A70005100108E026400B0486000C700610190F0 ++:102A8000510006C700600190550000860AF501B9A3 ++:102A900000A50000A18650F5A9B00005008600E160 ++:102AA000009800850586006408B9000006C700E1AB ++:102AB00000B05100018600750190048505860A6109 ++:102AC00000B000800086026508B00000088604702F ++:102AD00009B200100000000000000000000000002B ++:102AE000000000000000000000000000FF00FF00E8 ++:102AF000FFBEFFBE0000000008A85DFD0000000052 ++:102B000000800080000000000F3F0515000000005D ++:102B10000000000000000000000055FF2D2DFC0CFF ++:102B2000FC0C05AF05AF82820000FEFFFFFFFF0037 ++:102B30003C000F0F170F4141FDFF30003C00F550E6 ++:102B4000505000000000000000000000008A00005B ++:102B50000000000000000000000000000000000075 ++:102B60000000000000000000000000000000DF2066 ++:102B7000FF00FFBEFFBE0000000008A85DFD0000D2 ++:102B8000000000000000000000000F3F0F1F0000C9 ++:102B900000008000000000000000000100AA2D2DB0 ++:102BA000FC0C03F305AF05AF8292001034FF30FF39 ++:102BB000FC00FC000F0F0F0F4141FFFF00AA00AA0D ++:102BC000F5F5F5500008000000000000008A008ABA ++:102BD00000000000000000000000000000000000F5 ++:102BE00000000000000000000000000000000000E5 ++:102BF000000000003C393C3C00000000A353AC5CEA ++:102C0000FF00FF3C555555550000000000A0202056 ++:102C1000000000007FFF7FFF000000434343953F1B ++:102C200055FF000000008A828A820000000020D048 ++:102C30000000040CC341A5A50F0F00000000000018 ++:102C400001007878FF550000820000000000515D0F ++:102C50005555C33CC33CD7D72828000000000000CE ++:102C60000000000000000000000000000000000064 ++:102C70000000000000003C3C3C3C00000000AC5C5C ++:102C8000A353FF00FF3C155555550000000000A060 ++:102C90002020000000007FFF7FFF0000C100C1C1B5 ++:102CA00095C05500000000000A0000000000000070 ++:102CB000F0F00000143C0301AA5500FF00000000E2 ++:102CC000000000007878AA00008282000000000066 ++:102CD00055555555C33CC33CD7D7282800000000A4 ++:102CE00000000000000000000000000000080500D7 ++:102CF00040004000000000000300040000008000CD ++:102D0000800000000000000000000000000004003F ++:102D10000400040000000000000041040000000066 ++:102D20000000000041000000000020002000C00062 ++:102D300004000400210000000290000000000000D8 ++:102D400000010000044120000400110020002000C8 ++:102D50002000C000A0100800000090000800000043 ++:102D600000000000000000000000000000000080E3 ++:102D70000000000000000000000000000100000052 ++:102D80002000200000000000000000000000000003 ++:102D900000000000000000000000000000800000B3 ++:102DA0000000000000000000000000000000000023 ++:102DB00041000000000000000000010000000000D1 ++:102DC0000000002000009084000501008400000342 ++:102DD0000121010021000500000090001100010008 ++:102DE00000000000000000000000000000000000E3 ++:102DF0000000800000000000000000000000000053 ++:102E00000000000010008000000000001000000022 ++:102E100000000000000100000000000000000000B1 ++:102E200000C0000000000000200000008000000042 ++:102E30008000000000000090000000000000000082 ++:102E40000000000000010020000000000001000060 ++:102E5000000000000000000000000001000000026F ++:102E60000000000000000000000000000000000062 ++:102E70000000000010000000000000000000000042 ++:102E80000000000000000100100000000000010030 ++:102E90000000000000000020000000000002000010 ++:102EA0008400000000000000002001200000040059 ++:102EB00000000400000000000000001100000000FD ++:102EC00000000020900000040080001000000008B6 ++:102ED0000000000000008200000000000008000068 ++:102EE0000080002100000000000000000000000041 ++:102EF00000000000000020000000890000008000A9 ++:102F00008001000002000000031080100004200473 ++:102F10002004A084000005002004000440000001FB ++:102F200000009010000080A000400008A00800C031 ++:102F300011000000000800A00084008200A0001022 ++:102F400000820000000000000020002080010084BA ++:102F5000000000020041000000820000000000109C ++:102F60000001000000100000000000000000000050 ++:102F700000000000000000000100900002000000BE ++:102F80000800042088000241000082000405008936 ++:102F900001808380050308040005850000100111ED ++:102FA0000002000010100000404100030011031156 ++:102FB00000009008C00000000009841100210002F8 ++:102FC00000050041400084110000088500832004B2 ++:102FD0008400C000C0800090002100000008A01103 ++:102FE0000000C0028200002100000000000000007C ++:102FF00000000000000000000000001000820040FF ++:103000000810210021000000809000400000802175 ++:10301000C100800880008020000000408005090376 ++:103020000000000103000001000002840090800005 ++:10303000200000C000000408004002044000080016 ++:1030400002200900020003009082058808418200E6 ++:10305000840041C1C1210482C101009010001040D0 ++:1030600041002000200020000200000000000000BD ++:1030700000000000000000000000000000800000D0 ++:1030800000800180000000000009100000800000A6 ++:10309000048420002080200020000000008004A084 ++:1030A00000A000000020100000040000000000004C ++:1030B0000200011000410000020300000080010036 ++:1030C000002088800000002000000400000004842C ++:1030D00004002100000804A00100101010000000EE ++:1030E0000000000085001100010000400000000009 ++:1030F0000000000000000000000000000000800050 ++:10310000000000008400080100012100000082008E ++:10311000020404202005210100898905008800019E ++:103120000004100400C000C00000100200008082F3 ++:103130000010820104C0000000080009200508C03A ++:103140000000028210830000000240000084801012 ++:1031500002C0054085200240050804001000001050 ++:103160000810054010A000C00040000000C0000092 ++:103170000000000000000000000002210000000923 ++:10318000082090400009080001100020880300007A ++:10319000100404A08584C004C004C0040284082173 ++:1031A0000220000804000008000002218500000041 ++:1031B0000200000009028509000900100008A18230 ++:1031C00003208800012000400000040200050410D4 ++:1031D00008080900008002899180008003008400B3 ++:1031E0001085C0001090A000000000804041002128 ++:1031F00000000000000000000000000000000000CF ++:1032000000008000001000000001001000200400F9 ++:1032100000C000000200008203C041A08200002024 ++:103220000000009080011102009000000408850158 ++:103230000000090011000011C1840082020080A07A ++:1032400000C000A002000084028202C0000004C08E ++:103250000420200441110082209100001000104041 ++:1032600000001000410003001110028400A00300C0 ++:1032700020820000000000000000000000000000AC ++:10328000000000004000000000000010000000806E ++:10329000010000000000000000000000000003002A ++:1032A00000830000000002040000C00000000000D5 ++:1032B00004200000000000008288020000000000DE ++:1032C00010000000000000000000000000000000EE ++:1032D00082000180000000040000014000000100A5 ++:1032E000000000000000C00000000000000000001E ++:1032F00000000100000000000000000000000000CD ++:10330000000000000004901091030020400385009D ++:10331000890409040508000000401008890580049C ++:10332000211104080340000900110840A000118089 ++:103330008400050000C0C0800000C08010000311A0 ++:103340000004804011000000800011001000000304 ++:103350008003031041058311408941080000C0C16A ++:1033600080820804044040108041050404040300E6 ++:10337000020000004100000000000000000000000A ++:1033800000000000000000019001A000000000010A ++:103390009100C0000000880000000000000008014B ++:1033A000400001010000C0010000000001010240D6 ++:1033B000000483200000000004820800021001883D ++:1033C000898920890889000400001000000001009C ++:1033D0000001C0000101000008080903910000205D ++:1033E0002102C003011100040100C0000000000020 ++:1033F00001000000020000000000000000000000CA ++:1034000000000000000000000000000100000101B9 ++:1034100001008804890083009100820389090091DA ++:1034200000000004C00101010400840009C0C004C0 ++:10343000100008000500010800000040008440A0C2 ++:103440000000400040118201900120000400A00013 ++:10345000830182002108100221910200C189081114 ++:1034600083050200108401909089000209881000F1 ++:1034700082000100010900000108000000000000B6 ++:10348000000000000000000000000000090900002A ++:10349000030510000000A1008311104010840508EE ++:1034A0000303000000A1000209100810200088009A ++:1034B0004000A02111008200410000000000000037 ++:1034C00000000010800000880002002082008800B8 ++:1034D000C100830841204000C10503100205848417 ++:1034E0000885850585008800059009110280200067 ++:1034F00082419004204020404109108200000000D9 ++:10350000000000000000000000000000118000002A ++:1035100021804080030900C000009083098400914D ++:1035200040050008901000852088880804081111C3 ++:1035300000108440008980042188809000000008E9 ++:1035400000020510002011900004C1A000888080B6 ++:10355000408800880083008300041083A103024098 ++:10356000852121034105090980C080890540028920 ++:10357000000808C0111000410005200400200000D0 ++:103580000000000000000000000000000000000239 ++:10359000001000080082008800C00010888300101E ++:1035A000000801011001040400C1018489410001E7 ++:1035B0000001000182000010888282858489000059 ++:1035C00000400883099102200011A0832084008913 ++:1035D0004010010800C102050010008200848889A3 ++:1035E00000A110880888210200C004090402108983 ++:1035F0000104000501080020020000000100000194 ++:1036000000000000000000000000000000000000BA ++:103610000000000000010000019100010100911074 ++:10362000010000001001899001000120000000202D ++:10363000A0400400100104048489880020000020B8 ++:103640000000000000000000010884C18840400024 ++:1036500001820000002000000002910041000801EA ++:10366000022085100205080108C0834188008501F9 ++:10367000088401C001850001019083000000000062 ++:1036800088000000000000000000000000000000B2 ++:1036900000000000000040100000039110042140D1 ++:1036A0004080100308008021918003000800000082 ++:1036B0000400000900408002000080088020801182 ++:1036C00000000000050005000000090080208800BF ++:1036D0008800028000030080000800800309A00029 ++:1036E00040408000C09104038502048083838810D9 ++:1036F0008221408003000802114040008300110332 ++:103700000005200000000000000000000000000094 ++:1037100000000000008400426000000082000006FB ++:1037200000000000004200066000004282600006C7 ++:10373000600000000A504006C200004200840013EE ++:10374000C2000084000041000013600000000084FB ++:103750000013C2004250000000066000000012008A ++:1037600000130000008400840013C20082000000E7 ++:1037700000130000820012000013C20000000000CD ++:103780000013600041000000000000000000000085 ++:10379000000000000000F0F0F0F000000000000069 ++:1037A000300C00004444557D7DFF272700FF41BEBB ++:1037B00055EB5555AAAA00000000C3C0FFC0000089 ++:1037C0000000002800280000FFFFFFFF00C0A0400D ++:1037D0005555555590000000000000000000FF0FF7 ++:1037E000AF0A00A50030300CFFBEFFFE0F0F001423 ++:1037F000AAFF1E1E57FF55FF0F0F0000000000001C ++:10380000D700FF000010EFFF0000000000000000E4 ++:103810000000000000000000F0F0F0F000000000E8 ++:103820000000C0030000888800141455727200FF65 ++:10383000AA5514EB330F330F00000000D7C0FFC0B0 ++:10384000000000000028C0E800003CFFFFFF7010EF ++:1038500000C0287828780040101000000000000008 ++:10386000000F0A0AA5003CFCC003000000400F0F37 ++:10387000001400551E1E55FF55FF0F55003C00005B ++:103880000800D700D7000000FFFF00000000000084 ++:1038900000000000000000000000F3F3A200F0F0C0 ++:1038A00000002424000069000000FFFF3030FFFF0B ++:1038B0003F3082A0D7F50000FFFF05FA07F8FFFFB1 ++:1038C000FFFF0000000000AC00000000000000004E ++:1038D00000000000FF00FF000000000000000000EA ++:1038E0003300C0FF2481D15033000C0CFF00FF00D7 ++:1038F0005555054500010001FFCCFF4451A21020A1 ++:10390000D5758020000000000000000000000000CD ++:10391000000000000000000000000000FFFFA20007 ++:103920000F0F0000818100000069000030300000AE ++:1039300000003F30FF5FAA0A0000FFFF55BA7798EA ++:10394000FFFFEFFF0000000000A0000000000000EB ++:10395000000000000000FFF000F000000000000088 ++:103960000000003300C02481D15000333F0CFA0026 ++:10397000FF005555050500000005FF88FF00000009 ++:10398000000055550000000000004C5FC4F5000029 ++:103990000000000000000000000000000000009691 ++:1039A00000E400304860004700E00100510000964C ++:1039B0005265A090A005A5865074A19004000086D1 ++:1039C000026409F02480008600A5089800800000A9 ++:1039D000018600E109B8000500860CB508980005CD ++:1039E000A086006000B5496000C7006101905100E9 ++:1039F000008670E508B080000586002000A0000069 ++:103A00000886007109900000A58250E1A8B00085E9 ++:103A100000000000000000000000000000000000A6 ++:103A200000000000002855FFC3C3C3C3C3FF17171E ++:103A30000C0C0C0C30303030000000000A02FA028E ++:103A4000C3C35AFF00000000FA0AFA0A10D01FDFB1 ++:103A5000000000000000A0004000FF0FF00030F068 ++:103A60003FFF0000000000EB00EBF0F078F05000AA ++:103A70005500A0002000000200000000C3003F3FEE ++:103A80003F3F0000000000000004828282820000AC ++:103A90000000000000000000000000000000000026 ++:103AA0000000000000000F0F55FFC3C3C3C3003C5C ++:103AB0001717A6A6A6A630303030000000000A0274 ++:103AC0000A02C3C3A5FF00000000FF0FF00010D0E2 ++:103AD0001FDF00000000000000400000FF0FF000AA ++:103AE00000C00FCF0000000000EA00E0F0F0F0F0AE ++:103AF00050C055C00000000000030001FFF0C300EB ++:103B0000032B03030000000000000000828200007D ++:103B100000000000000000000000000000000000A5 ++:103B20000000000000000000000000000000000095 ++:103B3000F0F005F500000000E21DE21D00000000AD ++:103B400000AA00AA00000000FA82AAC2AAAAAAAA91 ++:103B50003C3C3C3C000005050404AAFFAAFFFF0012 ++:103B6000FF003C0FFF5500000000F000CC550000A6 ++:103B7000000000410C4D3C003C14C30075F50000F2 ++:103B80000000C3C30000000000000F00AA000000F6 ++:103B90000000000000000000000000000000000025 ++:103BA0000000000000000000000000000000000015 ++:103BB00000000F0F05F5000000001DE21DE20000EF ++:103BC000000000AA00AA00000000057D55BFF0F02B ++:103BD000FF0005F505F5000000000404AAFFAAFF98 ++:103BE0003CF0AAF03C0F005500000000F0FFCCAA0A ++:103BF00000000000000000003C283C3C0000F5F5FF ++:103C00000000000443430000000000000F00AA0071 ++:103C100000000000000000000000000000000000A4 ++:103C20000000000000000000000000000000000094 ++:103C30000000000000000000000000000000000084 ++:103C400000000000200000000082000000000000D2 ++:103C50000000000000004100000000000000000023 ++:103C6000002020000000040000000000020000000E ++:103C7000000000000000200020A000000000020062 ++:103C80000090050002001100400808000400050033 ++:103C900021000300030000002000000000000000DD ++:103CA0000000000000000000000000000000000014 ++:103CB0000000000000000000000002000000000002 ++:103CC00000000000000000000000000000000000F4 ++:103CD00000000000000000000000000000000000E4 ++:103CE00000000000000000000000200000000000B4 ++:103CF00000000000000000000000000000000000C4 ++:103D000000000000000000000000000000000000B3 ++:103D10000000000000000040000000000000000063 ++:103D20000000000000000000000000000000000093 ++:103D30000000000000000000000000000000000083 ++:103D40000000000000000000000000000000000073 ++:103D50000000000000000000000000000000000063 ++:103D60000000000000000000000000000000000053 ++:103D70000000000000000000000000000000000043 ++:103D80000000000000000000000000000000000033 ++:103D9000000000000000000000000400000000001F ++:103DA0000000000000000000000000000000000013 ++:103DB0000000000000000000000000000000000003 ++:103DC00000000000000000000000000000000000F3 ++:103DD00000100000000000000000000000110000C2 ++:103DE0000000000000000000000000004000000093 ++:103DF00000000002000000000000000000000005BC ++:103E000000000000000000000000000000000000B2 ++:103E10000000000000210000200000000010000051 ++:103E20000000000000000000000000000000000092 ++:103E3000000000000000000000000400040000007A ++:103E400040001100110002000900000021000000E4 ++:103E500002002100000000000000410000004000BE ++:103E60000000000000000000110000000008000831 ++:103E70002100000000000400000011000000090003 ++:103E80001000000005820000410000000500000055 ++:103E90000088000003000000000000000000030094 ++:103EA00000A0000000000000000000000000000072 ++:103EB00000000000020002000200040000000002F6 ++:103EC0000003C00090000000042088000002204091 ++:103ED000880004008400001100210000000000059B ++:103EE00000000000000300000041880000080008F6 ++:103EF000000300080000C0050010000000080003D7 ++:103F00008408C000040300000010A021901082115A ++:103F1000842190050021004184000041000500003B ++:103F2000C0000000000000000000000000000000D1 ++:103F300000000000090200000002008200000000F2 ++:103F40000000000000000000000000002100400010 ++:103F50000000000000000000000000000000000061 ++:103F60000000000000000000400009000000000008 ++:103F700000020000052000000000410021000000B8 ++:103F800020000300024000000000000002000000CA ++:103F90000000100002A0000000000000000003006C ++:103FA00000000000410000000000000000000000D0 ++:103FB00000000000000000000000000040000000C1 ++:103FC00000000000001000000000000000000209D6 ++:103FD00008000000080002000200020002000000C9 ++:103FE0000000001140000000000088000040900028 ++:103FF0000008001100400000000000030000000065 ++:1040000000000000000000209000200000100000D0 ++:10401000000000000800044000000008000508003F ++:104020000000000400042000000000000000000068 ++:104030000000000000000000000000000000000080 ++:104040000000000000000000000000000000000070 ++:104050000000000000000000000000000000000060 ++:104060000000000000000000000000000000000050 ++:104070000000000000080000000000000000000038 ++:10408000210000000000000000000000000005000A ++:1040900000000000000008004100000003000000D4 ++:1040A00005000010000000A000000000000000005B ++:1040B000000000000000000000000200901000005E ++:1040C00000210020900004110409020000200009D2 ++:1040D0002008020000002003040302212000002128 ++:1040E000000400000005000540100000000300006F ++:1040F000000000118808840800004000040000212E ++:10410000004000090221002100100000000000030F ++:10411000C008C0091000C040840090210021820026 ++:104120000005C01000008400102100000000000005 ++:10413000000000000000000000000000000000007F ++:10414000000000000000000000000010000000005F ++:10415000000000000000400000000000000000001F ++:104160000000000000880000004000100000000077 ++:104170000900000011000000000000000000000025 ++:1041800000002100000000000902400000000004BF ++:1041900020021100000000000000020008100000D2 ++:1041A000020000100010004000000000100000009D ++:1041B000000000000000000000000000000040209F ++:1041C00040004000402100000409000004000000FD ++:1041D0000000000000009009001100000200000033 ++:1041E000880300009003C000000000008800000069 ++:1041F00000000400040300000000000800040000A8 ++:1042000000000000020004000000000000000400A4 ++:104210000000000000000010040002000020024026 ++:10422000882000008200200300000000C00004007D ++:10423000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10424000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10425000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10426000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E ++:10427000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E ++:10428000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E ++:10429000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:1042A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E ++:1042B000FFFF00140F6C0C44C01000000A06000041 ++:1042C0006018000000000000000000000000000076 ++:1042D00000000900000000000200000000000000D3 ++:1042E00000000000200000000000000000000000AE ++:1042F00000000001000100010400000000000000B7 ++:1043000000000000000100008000210000002000EB ++:1043100011012020030000000304200509002000F3 ++:10432000040020000200020020001120030004828B ++:104330000400042008009100040004011100110091 ++:104340000400040100000000000000000000000064 ++:10435000000000000000000000000000000000005D ++:1043600000000000820000000000000000000000CB ++:104370000000000000040004000201000000000032 ++:104380000000001000000008000002000000000013 ++:104390000100002001800000400000800184000036 ++:1043A0000000010000000000C000010000800000CB ++:1043B000000000000180010010000000004000002B ++:1043C00000000000020400000000000000000000E7 ++:1043D000000000000000000000002001800000003C ++:1043E00000000000000000000000000000000000CD ++:1043F00000000000000000000000000000010000BC ++:1044000000000000000000C00000000000000000EC ++:10441000000000000000000000000000000000009C ++:10442000000000000020000100004100000000002A ++:1044300000000000000000000000000000000085F7 ++:1044400000000000000080000000000000000000EC ++:1044500000000000000000000000C0000104200077 ++:10446000000000000000000000000000000000004C ++:10447000000000000000000000000000000000201C ++:10448000000000000000000000000000000000002C ++:1044900000000000000000410000000000000020BB ++:1044A00090000000020000800220000000000000D8 ++:1044B00002000000000000000000000000000000FA ++:1044C00000040000000000002000000000000000C8 ++:1044D00000000000000009000000000003000200CE ++:1044E0000000000000002100110004012101A101D1 ++:1044F00002000400A10000000000020040000010C3 ++:104500000040000000000500000000000000000066 ++:1045100000908400000000908000800040000300B4 ++:1045200000084110000000850084410000000000E8 ++:1045300000040002000000022108008403000001C2 ++:104540000000400010820000000000200000000079 ++:10455000000000000000000000000000000000005B ++:104560000100000000000000000000418520002044 ++:1045700004200100000008000040000001000100CC ++:104580000005002000000000000000000000000006 ++:10459000000000000300000000000400040001000F ++:1045A000000000000005000000200011880000004D ++:1045B0000000008000030000008000000000900068 ++:1045C000900800000100000000000000A080000032 ++:1045D000000000000000000000000000000000904B ++:1045E000000000000000042000000000A0002040A7 ++:1045F00003A08000000000010300200088000340A9 ++:104600000000034000000000000003000000000064 ++:10461000000000000000A000000000008400040072 ++:104620000400030000009000050004014100210087 ++:104630000000C1000001900041A005000000100032 ++:10464000040000080020850810000090210041406F ++:10465000000000000000000000000000000000005A ++:10466000000090000000881001910000001105007A ++:104670000180840002210000000400008900210064 ++:104680000080000000802000000200000000000008 ++:1046900000000000000000002100000008000400ED ++:1046A000010000000000000004000800A12000003C ++:1046B00008000000400000040400A00000000811F1 ++:1046C000A0000000A0800821208084008200081142 ++:1046D00008000000000000000000000000000900C9 ++:1046E00000000900040000100000C00000000420C9 ++:1046F0000000000020002084A000410004000310FE ++:10470000040005004100210010000800040004001E ++:10471000410000000000100080080201000020009D ++:1047200004002120400020000000040000000004DC ++:104730000304852000000000000004200000200089 ++:10474000030020100000000002100000080010000C ++:104750000000000000000000000000000000000059 ++:104760000000000090000100008000000400000034 ++:10477000018000110211A1000300050000000100EA ++:1047800000000140000000000000004001000100A6 ++:104790000100000000000041000040000102000094 ++:1047A0000100010000800100010000000100000084 ++:1047B0000000000320000000000000000180000055 ++:1047C0000100A003900000000000000004000000B1 ++:1047D00000000000000000000000000000000000D9 ++:1047E00000001000000000008001000480010801AA ++:1047F0008801800184402182042000A00020200044 ++:10480000A1200088000010008300210003000000A8 ++:1048100008840000041000000900040000000000EB ++:1048200000000000008800044000000009000401AE ++:1048300005C00420099004200488050000008500BC ++:1048400011000000410008A01004030080000805CA ++:104850000000210000100000000000000000000027 ++:1048600000000000002100008800202004910404C2 ++:1048700005100920041005000000000000000000E1 ++:104880000100200000000000884002200000040019 ++:104890000000010000000100000000000000000016 ++:1048A0000000000000000000000001000000000007 ++:1048B000004000000180C000C1A00800000000000E ++:1048C00020000000000000000010000000000400B4 ++:1048D00000C0001000000000000000000000000008 ++:1048E000000000000000000000008385C08991A046 ++:1048F00009898080910000800000002020890880C4 ++:1049000000A10000090900050005008302090083D9 ++:104910000011400320400020000500C04021000499 ++:104920002040000321050211000321008500040935 ++:104930004000411000020000404000200000200024 ++:10494000200000000510000909200309000880204C ++:1049500041400008000000000000000000000000CE ++:10496000000000000000000000000000088321217A ++:10497000A111010588829184908800040410110916 ++:1049800090100008C00085010000000000400109EF ++:104990000008000001010101000000000000890082 ++:1049A00084010000000000010100000000009100EF ++:1049B0008901010001010001820001010001A00044 ++:1049C0008500010000000001A001010000000001BD ++:1049D0008200000100000000000000000000000054 ++:1049E00000000000000000000000000000000500C2 ++:1049F00084880301911021019100880083C188A05F ++:104A0000002111C084011001C001C000890204000E ++:104A1000A002089041100800A104020083C0000019 ++:104A20000000010021008500010000A0888801002D ++:104A3000010001C001010000A10100C1000482A029 ++:104A40004000C100C000C001020082C0C08908004F ++:104A500010000400A100820000000000000001001E ++:104A60000000000000000000000000000000000046 ++:104A700088090380820209A19008C1008000908902 ++:104A8000000020092180A1098040000983008303E0 ++:104A90008004098000A1838080094100410083C116 ++:104AA0000000020020000500A02011000000A0A1CD ++:104AB00009001000048010022102100311830085F8 ++:104AC00080040000080000008010210040C1208503 ++:104AD0002005880089001000890202000200000001 ++:104AE00020000000000000000000000000000000A6 ++:104AF0000000058580918089C0C0008080004080D2 ++:104B0000808080A0840009890021800000820985BE ++:104B10008085090000008000030020C100C1400919 ++:104B20000083000020400040004003C020090040F6 ++:104B30000021C04100100091004105032000000049 ++:104B400008800400000000001180000041200000E7 ++:104B500000044105080000800000418000000000C2 ++:104B60000000000000000000000000000000000045 ++:104B7000000000000103C0C0848589050020880072 ++:104B800083A0888288841190C109A040880000C158 ++:104B90000184208201000400A00011900108000897 ++:104BA000010200830000002100850041C1020100D4 ++:104BB000000000008300000100110089C189018804 ++:104BC000008400A040A000C000A0008400A000035A ++:104BD00000C00008010200A0000200200004000044 ++:104BE00000000000200000000000000000000000A5 ++:104BF00000000000000003848483A001C020909185 ++:104C000088900200888801C000200000008883A1ED ++:104C100000A0840002828588118208001008030029 ++:104C20000282C00005C000000120000001000190C8 ++:104C300000000140000000000000009100000000A2 ++:104C40008991C088C10090880000000000000088A1 ++:104C500000000020000001A0000000000000004053 ++:104C6000000000A0000100000000000000000000A3 ++:104C700000000000000000008385098991022000E7 ++:104C80008091800080008080092100800000210048 ++:104C90008902050585110080838084C120001100F0 ++:104CA0000309040509042080000008800002101098 ++:104CB00010802100409140030300210005104011A5 ++:104CC00020002083918020118280000000000000DD ++:104CD0000080030204A10921400000030009001024 ++:104CE000000000000005004100000000000000007E ++:104CF000000000000000000000000000004248002A ++:104D0000110021840006600000001182000660008E ++:104D10000000008100066000006012000006C20072 ++:104D20004150000000060000000000000A000006DC ++:104D30006000008282000013C2000088005000065C ++:104D40006000000021000006C20081008200000611 ++:104D50006000000082410006C200000082000013D3 ++:104D600060000A0000410006602000000000000012 ++:104D700000000000000000000000000042020606E3 ++:104D8000093D09090000000000000000FFFF0000CD ++:104D90003CC3FF000FFFF0000F0FF00F0909FFFFEA ++:104DA000000000000C03000005A00000000000004F ++:104DB0003030FFFFFF7FFF991E1E097E6F7EFFFFD1 ++:104DC000F6F63C00CFDFFFFF3CFF000000000000D4 ++:104DD0000000000000003C3C3838003C66660000E3 ++:104DE00000000000000000000000000000000000C3 ++:104DF00000000000000000000000000000000000B3 ++:104E00000606090909090000000000000000C3C3EC ++:104E10003C3C3CC3FF000FFFF0000F0FF00F0018E9 ++:104E20007E7E0000000030C0000005A000000000F1 ++:104E300000003030FFFFFF7F66001E1E09186F184C ++:104E400042DB42D200000F1F999930F000000000B1 ++:104E500000000000000000003C3C383E0000666698 ++:104E60000000000000000000000000000000000042 ++:104E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 ++:104E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 ++:104E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 ++:104EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 ++:104EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 ++:104EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:104ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:104EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:104EF000FFFF00C84CFA0C44C01000180A0600005E ++:104F000090650000000000000000000000000000AC ++:104F100000002000FFFF6666000D00000000F0F0BA ++:104F200033333CC300FF00FF0FF0C03FC03FFFFF23 ++:104F300066001800909000006969000000330000CE ++:104F4000009600000000810000000000F066FF668F ++:104F5000009966FF42C342C304040000FFFFE6E677 ++:104F6000F0F0F0F000000000F0F00000003C003C29 ++:104F7000FFF7FF000000000024FCE7FC0000000039 ++:104F8000FBFBFFFF0000000000000000000000002D ++:104F9000000000000000FFFF0000000D0000000006 ++:104FA000F0F033333CC300FF00FF0FF0C03FC03FC1 ++:104FB000000099FF0018909000006969000033001C ++:104FC0000000960000000080111001000000006643 ++:104FD0000F6618187E7E42C342C304000000C3C39C ++:104FE000C0C0FCFCFCFC00000000F0F0000000FD74 ++:104FF00000FFF7F700000010000024C0E7C0000029 ++:105000000000FFFFFFFF00000000000000000000A4 ++:10501000000000000000058600B0009000000006BF ++:10502000009401000803C086C0F431B00803C082B8 ++:10503000C035301042030586007101904C60004776 ++:1050400000210000510000000186026001B0040050 ++:105050000086007109A800000086006408B2008084 ++:1050600000860C2101C0000000860061A19000159F ++:1050700000867065098000800006026109A00005B5 ++:105080000086006408B0000000000000000000007E ++:105090000000000000000000C300EB28010101F146 ++:1050A000F708FF00FF3CC33C000000008E828E8E9C ++:1050B000C6C601010F0FFF008782D282FFFF0000EA ++:1050C0000000FFFF3CC333F0000000000000008040 ++:1050D000A000000000000000000000000000AAFF87 ++:1050E000FFFFBCBCA0A040005050000000000FFF1C ++:1050F000FFFF000000000000000000000000004072 ++:10510000000000000000000000000000000000009F ++:1051100000000000000000000000C300CB080101F7 ++:105120000101FF00FF0000C3C33C00000000BEB24D ++:10513000BEBEC6C6FEFE0F0F00FFD2828782FFFFF3 ++:1051400000000001FFFE3CC333F00000000000003F ++:1051500000080082000000000000000000000000C5 ++:105160000A5F5F5FBCBCAAA0400070700000000036 ++:1051700001FFFFFF00000000000800000000000029 ++:10518000000000000000000000000000000000001F ++:105190000000000000000000000000002800F5F5FD ++:1051A000000000087F80FF00FFFE01FE07FA877AFB ++:1051B00055FF550000000000FFFFFFFFFFFAFFA0B2 ++:1051C000080A3EFF00000000AAAAF0F0000000005C ++:1051D00000005500AA0000000000FF00FF000000D2 ++:1051E000000000000000000000003C3CFFFF000049 ++:1051F0000000AAAAA8A0000000000F0F0F0F0000D7 ++:10520000000000101000000000000000000000007E ++:10521000000000000000000000000000000000008E ++:10522000F5F500000000FF000000000101FE07F896 ++:1052300057A8553C553C000000007FFFFFFFFA00D7 ++:10524000A000080A3EFF0000000069AA72F00000FA ++:10525000000000005500AA0000000000FF00FF0051 ++:10526000000000000000000000000000FFFFD7D792 ++:1052700000000000AAAAA8A0000000000D078F0FE0 ++:10528000000000000000000000000000000000001E ++:10529000000000000000020000000000000000000C ++:1052A00020002000200040000800800104010000D0 ++:1052B0000000000100000400000000000040004069 ++:1052C0000000000021000400040000C000002100D4 ++:1052D000000000000000000004000000030040A0E7 ++:1052E0004100200020000400202104000000A0054F ++:1052F00082000400210011002000030004000400CB ++:1053000004004000C00004001100110000008400EF ++:1053100091000000000000000100000000000000FB ++:105320000000090001000100000000000404010465 ++:105330000800000000040000000000000000000061 ++:105340000000000000040000000000000000000059 ++:1053500000000000000082000000000000000000CB ++:1053600000000000010001009000014000008400E6 ++:1053700002C00200010000000000830000000105DF ++:105380000000000091000500000004000000000083 ++:1053900020000400000000000000000000000000E9 ++:1053A000000000000000400000000000000040007D ++:1053B000400040000000000000000000000000006D ++:1053C00000000000000000000000000000000000DD ++:1053D0000000000000C0000000000000000000000D ++:1053E0000000000004000000000080000000000039 ++:1053F00000000000000000008000800000000000AD ++:10540000800000000000000000000000800000009C ++:10541000000000000000000000000000000000008C ++:10542000000000000000400001000000000000003B ++:105430000100010001000000000000004000000029 ++:10544000000000000000000000000000000000025A ++:10545000000000000021000000000000000000210A ++:105460000000000000000102000000000400000035 ++:105470000000000000000000000020000400000008 ++:105480000000100000410000000002000021200088 ++:10549000000000000000000000000000000000000C ++:1054A000000000000000000020002000C00020A13B ++:1054B000800404008000000020000000200009009B ++:1054C00040000000008400002100000000020020D5 ++:1054D0000000000000840000000000000000000048 ++:1054E00000840000000080A0000400000000000014 ++:1054F0000002080000000004008500000000000019 ++:1055000000001100000000A00002009000000484D0 ++:10551000000000C08000000000000000000000004B ++:105520000000000000000000000001000100210058 ++:10553000890420800500200000000100A000010077 ++:10554000000088000411C000004000001000100995 ++:10555000C091C009002000020011000000000000FE ++:105560000000020090000000040000800000200005 ++:105570000002840001000000008000049000000090 ++:105580008405C000000020000000000000001000A2 ++:10559000C103A040001004008810000000000000BB ++:1055A00000000000000000000000000000000000FB ++:1055B00000000002000000001101000100000000D6 ++:1055C00000A10200090002000000000000008008A5 ++:1055D00000000000100000C003004000000000A018 ++:1055E00021000800000041000000000000C0110080 ++:1055F000410020008200050000000500100082002C ++:10560000020020001000030005000000020020003E ++:105610002000C00040000500030000A002000000C0 ++:1056200000000000000000000000000000008800F2 ++:10563000000088009080000000400004024000004C ++:105640000000000400050000000000000000000051 ++:1056500002800000000000000000820084000000C2 ++:1056600000000000000000050000000000008400B1 ++:1056700000000000C10003008221000000000800BB ++:1056800020000000010000000000000000000400F5 ++:1056900009004111210003000800A00000001000D3 ++:1056A00000000000000000000000400000001100A9 ++:1056B000000080C00200800000110000890000008E ++:1056C00009000000210200000000040000844010D6 ++:1056D0000000000000020220002000000000000086 ++:1056E00000000020090000C004004100002041101B ++:1056F00000000040048241041090052003010004D2 ++:1057000000A1040004000482040021844000080079 ++:105710004102800088A085008040002120000420F4 ++:10572000100000000000000000000005000000095B ++:1057300000000000020000400440000400000400DB ++:1057400000000403A009908900020000010000008D ++:1057500000211003040000090191C000C0001000E6 ++:10576000840000000000000000000009000000802C ++:105770000021C00000000100002000210000000204 ++:105780000083000401000100010501210021000047 ++:10579000C0210000040004000405040000200100F2 ++:1057A00001210000000000000000000000000000D7 ++:1057B0000000008200010000000009010001030256 ++:1057C00000020010000000000000000000C02100E6 ++:1057D0000284000000000000000002410000000000 ++:1057E000000000C00000000000002100080041206F ++:1057F00000000501020011C00000021000011000AD ++:1058000000002000214000C00202009002100000B1 ++:1058100010000300050410884100008403011000FB ++:10582000088821C080000000000000000000000087 ++:1058300000000000000000020000040990200002A7 ++:10584000004000058440000000000000001000003F ++:1058500000000000400000000009840088020000F1 ++:105860000000820002000040000008000000080064 ++:1058700000800000A008004100000041080008402E ++:1058800010000000010010000041000000000000B6 ++:105890000000000000008480000084000005082053 ++:1058A0001000000300402000000000000000000085 ++:1058B0000000000000000000800000000510000053 ++:1058C000000300000000091082030900C00000006E ++:1058D00082030000C0800000000800080911008455 ++:1058E000000000000000000000C0000000000000F8 ++:1058F0000000098000000400088003090909411123 ++:105900004040000080004000000040C100090891B4 ++:105910001184004000400020004000838000C0103F ++:10592000104010884009021141840000000000006E ++:1059300000000000000000000000040082000000E1 ++:1059400000000001000020000000898900A0C09034 ++:10595000004089898888A09000840082A00000C04F ++:105960000004000000000000000000000000000033 ++:105970000000000000880088C00400080100C00189 ++:10598000890001010000040000000000A18888894E ++:1059900011A00040000100010000000102890884FC ++:1059A00009050004108940400510010800000000AE ++:1059B00000000090000000000000008803001000BC ++:1059C0008220030010018200028803859001008577 ++:1059D0000488414090008884008841850888080038 ++:1059E00002A008820000000000000000000000008B ++:1059F00000000000000088011000888808090901E3 ++:105A000011828800850488000000A0008201020045 ++:105A10008802890941A00000000000000001010087 ++:105A2000080089004100050185008800C1C0000010 ++:105A30000000000000004000000000000000C00363 ++:105A40008005008083218002000080808385801093 ++:105A50000003008003008040000000800340000538 ++:105A600000008000808000000000000000000000B6 ++:105A700000000000000000000040800080008088DE ++:105A8000200388808000890000000000000080035F ++:105A9000114040008202890500000000000000085B ++:105AA000404180009008830040400400C00089808D ++:105AB00000000000000000000000000000000000E6 ++:105AC000008000002090008300800000118000838F ++:105AD000000000800200C103000000800000C0033D ++:105AE0000400800020801000000000000000000082 ++:105AF0000000000000000000000000080004040492 ++:105B000000880000009100098404008000001180DA ++:105B10000080200900040089C1C1080000000000C5 ++:105B2000030000008010001011834089809080895C ++:105B3000408900000000000000000000000000009C ++:105B4000000020020008008400050004000000049A ++:105B50001005C09000904104898900000090828265 ++:105B600089890000848809849040000000000000BA ++:105B70000000000000000000000000000090080885 ++:105B80000010008900040040000510000002009091 ++:105B90000084002001020405C0A14088010000002B ++:105BA0000000010000C008A0000500890010A0400E ++:105BB000A0091188000000000000000000000000A3 ++:105BC0000000000002000582020000020588880033 ++:105BD00002010282018904889001908801C1840039 ++:105BE00040019088840108080200C0900000000075 ++:105BF000000000000000000000000000000008831A ++:105C0000882010000840A1090389A000C0020001FB ++:105C100000010000008811A08810A0000208020006 ++:105C2000400000000000090888114000A0A0020800 ++:105C30008805080010A0000000000000000000001F ++:105C4000000000000000802190808000008083859B ++:105C5000900080218080031000800021800003409C ++:105C60000000002180008002800080008080000011 ++:105C70000000000000000000000000000000000024 ++:105C80000082808080008000090341030404020038 ++:105C9000000300400000000009109111910209006A ++:105CA00080008000000000008311C088910000097E ++:105CB000004080208009000000000000000000007B ++:105CC00000000000000000000041001060004200E1 ++:105CD00081840006600000820000001360008200E2 ++:105CE000000000130000000000000013000000503E ++:105CF00000000000000000000000000000000000A4 ++:105D00000000418100136000420081810013C20045 ++:105D1000820000000000C2000A4841880013C2004F ++:105D20000000000000066000006081000013840095 ++:105D3000000081810013C20000000000000000008C ++:105D40000000000000000000000000FF0000000054 ++:105D500000FF000000FF0000FFFF0000FFFF000049 ++:105D600055550000FFFF00005555000000000000E1 ++:105D70000000000000000000000000000000000023 ++:105D80000000000000000000A03CAF3C00C03CFC54 ++:105D900000FF00FF0000000000000000080AFDFFF7 ++:105DA000505F303F00000000000000000055000F71 ++:105DB000000F00FF0000000000FF00FF00000000D7 ++:105DC00000000000000000000000000000FF0000D4 ++:105DD000000000FF000000FF0000000000000000C5 ++:105DE000000055550000000000005555000000005F ++:105DF00000000000000000000000000000000000A3 ++:105E000000000000000000000000503C5F3C00006B ++:105E1000FFFF05AF55FF0000000000000000080074 ++:105E2000FDF500FF00FF000000000000000000552D ++:105E3000000F000F0000000000000A5F287D000036 ++:105E40000000000000000000000000000000F0F072 ++:105E5000F0F03C3C00003C3C0000FFFF0000AAAA20 ++:105E60000000FFFF0000AAAA00000000FFFF40039F ++:105E700055FF0000000000000000000000000000CE ++:105E80000000000000000000000000000000000012 ++:105E9000FFC0BF807D7D0000000000000000AAAAB6 ++:105EA000FF00FF00FFF700343F303F3000000000EC ++:105EB000A0A03030AAFF3C00AFAFAFAFFFFC000C9A ++:105EC00000000000000000000000000000000000D2 ++:105ED000F0F0F0F03C3C00003C3C00000000000012 ++:105EE000AAAA000000000000AAAA0000FFFFFFFF0E ++:105EF000BFFCFA00000000000000000000000000ED ++:105F00000000000000000000000000000000000091 ++:105F10000000FFC0BF80FDFD808000000000000089 ++:105F2000AAAABFB01F10FFE30020FAFA0A0A000075 ++:105F30000000A0A03030AAFF3C00AFACA3A0FFFA45 ++:105F4000000A000000000000000000000000000047 ++:105F50000000A8865175A094494512DF21A441A4F0 ++:105F60006940A2C75180A084494002C701800084D3 ++:105F700041400086026100B0000000000000000007 ++:105F800000000000000000000000000000860094F7 ++:105F900009800005008600B401A0000000860060B2 ++:105FA000A8B0001500860094018000000086002142 ++:105FB00008B000050886049009820010008600944D ++:105FC0000180000000000010080000000000000038 ++:105FD000090000005FFFFFFFFFFFFFFFFF00FF0062 ++:105FE000FFC3FFFF000400040100000000040004E0 ++:105FF000000000003C553C0F0505AFAF000000005D ++:106000000000000000000000000000000000B4B428 ++:10601000FF00000DFFFD3C3C787899FF99FF0000E0 ++:10602000000000000000FF00BF010000FFFF00FFB4 ++:10603000000000000000FF00E8E80000FFFFBF8351 ++:10604000BC80088A5DDF0000000000000100000045 ++:106050000020000001005FFFFFFFDFFFFFFFDF20E8 ++:10606000FF00FFC3FFFF0000000001000000000070 ++:10607000000000000A003C0F3C5505AF05AF0000D2 ++:106080000000000000000000000000000000000010 ++:10609000FF00FF00000DFFFD3C3C7D2899009900AA ++:1060A0000000000000080000FF00BE0040007F3F2D ++:1060B00000FF000000000000FF00E8E835003500A8 ++:1060C000FF00FF000000FFFF004000000000000094 ++:1060D000004000000000020000000000FFBFFFFFC2 ++:1060E000000000000F0F0F27000300000000000059 ++:1060F000000000000000000003032B2BAAAA33CCF1 ++:10610000000000000000000000000000000000008F ++:106110000000FFF7282000FF05F50000000000FF49 ++:1061200000FF0000000000000000FFFF000000FF73 ++:1061300000FF0000000000000000FEAE5404505FAD ++:10614000F0FFFFFF000000FF505F000000000000B4 ++:106150000002000000000000000000000000FFFF3F ++:10616000FFFF000000000F0F0F0F000000000000F5 ++:106170002800000000301010000017173F3F555551 ++:1061800033CC000000000000000000000000000010 ++:1061900000000000FFF7282000FF0CFC00000000BA ++:1061A000085D8ADF00000000008200FFFFEA004077 ++:1061B000407F003F0000000000000000FEAE5404DD ++:1061C000000FA0AFE8FFE80000FF303FFFFFFFFF38 ++:1061D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:1061E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:1061F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10620000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10621000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10622000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10623000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:10624000FFFFFFFFFFFFFFFFFFFFFFFFFFFF002438 ++:106250008C330C44C05000000A060000A8A90000BE ++:10626000000000008000000000000000100000009E ++:10627000000000000000000000000000000000001E ++:106280000000000000A0000000000000000000006E ++:10629000000000001100000080000000000000006D ++:1062A00000002000090040000200820020002000C1 ++:1062B0008500040000009000040004000400820037 ++:1062C000000040000040040000002000200000000A ++:1062D0000000000010002021040020002000110018 ++:1062E00000000000000002000000000000000000AC ++:1062F000000000000000000000000000000000009E ++:106300000000000300000021002100000000000048 ++:1063100000050000002000210000400000000000F7 ++:1063200000000000010000000000830004000100E4 ++:106330008300020083000000020001000100A100B0 ++:1063400004000000010090802000A00000009100E7 ++:106350002000000000000100008400009100010006 ++:106360000402000000000000000000000000000027 ++:106370000000008800C000000000000000000000D5 ++:1063800000040000000000000000000000004000C9 ++:1063900000000000000000000000000000000020DD ++:1063A000000000C000000000000000000000808825 ++:1063B00000000001000800008000020000048000CE ++:1063C000000000000000000000000001200020008C ++:1063D000000000000000000080010000000000003C ++:1063E00000408000000000000000000000000000ED ++:1063F00000000000C00000000000000000000000DD ++:1064000000000080000000200000000000000000EC ++:10641000000000000000000000000000000000007C ++:1064200000800000000000000000000000090000E3 ++:10643000200000080004008000000400010000802B ++:1064400020000000A000000000000000004001004B ++:10645000010000000400040000001008000000001B ++:10646000A000A0802000000000000000000000004C ++:106470000000000000000000000000A000040084F4 ++:106480008000000900010284020210000020004088 ++:10649000000000100010008800000040004004844C ++:1064A000000000A00088000000C0004000040410AC ++:1064B0000004000000000040000000C0000280A0B6 ++:1064C000000000200000009011100090000000402B ++:1064D00000A0000000400000000000841001201017 ++:1064E000800000900000000000000000000000009C ++:1064F000000000000000000000000000000000801C ++:1065000000001021A0C000400009910001000040DF ++:1065100004000000000082000040000000800091A4 ++:1065200000418204880200000000000088218800E9 ++:106530000100048000009040A0000005000500025A ++:106540000241000502000000C000820000000000BF ++:106550000000000000050200C04102001000A10878 ++:1065600003002005104010008441000000000000DE ++:106570000000000000000300000080000020002058 ++:1065800080000041000802880000000003004084F1 ++:106590000204000000000000000005004190028895 ++:1065A000C0000000020009210000000000010000FE ++:1065B000830020A0200000008505020105000500E1 ++:1065C00009011001000000002100C10002101000AC ++:1065D00003004100101010822100840010002000F0 ++:1065E0004090208821008000090082000000000007 ++:1065F000000000000005002182050000040000C129 ++:1066000088C10405004084800000000300002000D1 ++:106610000021010500000000000000100000000043 ++:106620000111030000218200008800410000840461 ++:10663000A00020410100010000000484A1400009E5 ++:106640000000C002C008C021000088002000031024 ++:106650000000100000000000000000002100902158 ++:106660000100010000410000204100000400000082 ++:1066700000000000090000000000090040000000C8 ++:1066800000000000020000C10040909000000240A5 ++:1066900000020084001100840000000000A000003F ++:1066A00002000200404100004000100210A0000063 ++:1066B0000020000003400240008821C00900804003 ++:1066C000008540084102820200C0089008200200B4 ++:1066D0004102080005880040000003042100030077 ++:1066E000C1000500410809000302400004901100A8 ++:1066F000000000000000000000000000400000005A ++:1067000000210003000300030040000009030040D3 ++:10671000840988008800002000000000004000007C ++:106720000005C000910001C0A0400100010001006F ++:10673000000000000011000000000000002188009F ++:106740002005A04001C000100385002100000000CA ++:10675000002100210000002090C000000000000087 ++:1067600082001009082000900040020090200202E0 ++:106770001009000000000000000000000000000000 ++:1067800000001100890400008000022000C0008485 ++:1067900000C0000000040084000421C00000008448 ++:1067A00000208000210000008084400002001021B1 ++:1067B0000000000005C021A04184001102882004CF ++:1067C0004104110500A1218480118040418400C052 ++:1067D0002084009000A00010000002080410200097 ++:1067E0001000100041A0410009081000218403009E ++:1067F00008000290000000100000000500000000EA ++:1068000000000000000020890000200901000000B5 ++:106810000021000500000000000002000000000050 ++:10682000C00010804020C005002020000100820030 ++:1068300001A0000000000000000084000040A14111 ++:10684000018000C100C00002000010100280820020 ++:1068500082000100C00084008200000000000000EF ++:10686000000000000000000000000080040900009B ++:106870000000000001000000000000000000000017 ++:106880000000000000004085401000410910088809 ++:10689000008003080891110005001000400000006E ++:1068A0000000000000001040000010000302080873 ++:1068B00080114008111100C005100020400509108A ++:1068C00009090040898000904083108288100840A8 ++:1068D00008880009840210020080000040000000C7 ++:1068E0000340000900084004091180092108021032 ++:1068F00008410009110803400000000000000000EA ++:10690000000000000000000000099041C0010141AA ++:106910000183A0028405010200008900010000003B ++:106920000000000000000000000004000000010062 ++:1069300000004000010000000000040140010000D0 ++:10694000000004000200A0080410C083A1A10302FB ++:1069500000048888000108050010000804100104E4 ++:10696000000401010001000001009001C0010001CC ++:106970000001030000010001000100000000000010 ++:106980000040000000000000000008009188410164 ++:1069900001C1020083004010840020A020000400F8 ++:1069A000C01000000000000000004000108801013D ++:1069B00041001000A011A10085000000C1008588E1 ++:1069C000C0011000410084C088048504A000092093 ++:1069D000880885918201A010890411000800C00078 ++:1069E0000800840000000000000101000100108286 ++:1069F0001000010003002184910103040000000045 ++:106A00000000000008000000000000008409108061 ++:106A100005214189800008008800900080108000D6 ++:106A200000008080000000000000000000009002D4 ++:106A300010050900400040C08811830800002000B4 ++:106A40000811080888000240030089098908C0402D ++:106A500040058840832008021000A1020941090076 ++:106A600010009100840009000000101009000500CA ++:106A7000118089080941A004C080210289410000D9 ++:106A8000000000000000000000000000000004C042 ++:106A900000088004081140C000088090089100039D ++:106AA000009000C10008000000000000800000030A ++:106AB00000050589110811840091008240030080BF ++:106AC0008202000241C08205021000020490109070 ++:106AD000A00800101008088304108002C10904886F ++:106AE00000008000000000000302000402092000F2 ++:106AF000040500C111A080A040040008200921C0A5 ++:106B00000000000000000000000000000000000085 ++:106B100000099040A00808400002C091A005214053 ++:106B200000C0000800859000000000000000820006 ++:106B300000820008011000C10008000500112011AA ++:106B40000080091000900084409101A0C001001154 ++:106B5000890882100404A10100410000C0C1401155 ++:106B6000888900900240880800400101000000016F ++:106B7000C10000A0002100850889010400A101894D ++:106B800002090000000000000000000000000000FA ++:106B9000000000089008C001404000010002000011 ++:106BA0000090109084889000080800000000000009 ++:106BB0000000010800000000000000880101010140 ++:106BC0000190008001A1010000000008859088A1CB ++:106BD000A0014040859088080010889011418908E4 ++:106BE0001000408200000000000100040190000439 ++:106BF0000000000001C00185000001008288C00380 ++:106C00001100030800000000000000000000000068 ++:106C10000000000004100889910211000020000902 ++:106C200000090000800400000000000000000000D7 ++:106C3000000000002080021002111100090841101C ++:106C4000102110800080400304090809110082050A ++:106C5000820800210900830088C004884009894017 ++:106C600090911010828000020004000800000900CA ++:106C70001002040200000200084004000800048220 ++:106C800004080209400000000000000000000000AD ++:106C900000000000000000000013C200000000001F ++:106CA0000013C20000000000000600000000000009 ++:106CB00000130000005000810000C20000500000DE ++:106CC000001300000000000000000006C2004200A7 ++:106CD00081000013C200000081000013C2000A00FE ++:106CE00081810013C200005000000000000000007D ++:106CF00000810013C2000A0000820013C2000A00D3 ++:106D000000410013C200000000000000000000006D ++:106D10000000000000000000B000B0000909000001 ++:106D200000000000000000010000000091C3EF3CE3 ++:106D30000000000000000000FFFFFF6F663066F3F8 ++:106D40007E187E18AA5A47E7000000000240FFFFA5 ++:106D50007F7E3C3CFF99FD0DF40400000000000024 ++:106D6000000036FF3600FF24DB00000000000000BA ++:106D700000000F6F0060BF83BF83FF3FFFFF7DBE3A ++:106D8000BD7E0F0F0F0FFF00FF800000000000000E ++:106D900000000000000000000000F00000000008FB ++:106DA000000800000000000000000000000081F367 ++:106DB0007E0C00000000000000003F3FFF6F66CF28 ++:106DC000660C6F6F0909A5AA424700000000400247 ++:106DD000FFFF6F663C3C6600FD0DF4040000000000 ++:106DE00000000000FFFF0000DF04DF0400000000DF ++:106DF000000000000F6F00603E023E02FFBFFFBFB9 ++:106E000041828142CF4E0C4EFF007F000000000007 ++:106E10000000000000000000000000000000000072 ++:106E20000000000000000000000000000000000062 ++:106E30000000000000000000000000000000000052 ++:106E40000000000000000000000000000000000042 ++:106E50000000000000000000000000000000C20868 ++:106E60000400001188610000000000000000000024 ++:106E70000000000000000000000000000000000012 ++:106E80000000000000000000000000000000000002 ++:106E90000000000000000000000000000000363C80 ++:106EA000FFFF34FF3CFF4040000000009000000066 ++:106EB00000000000000000000000000000007E7ED6 ++:106EC000FFFF000000FF66F066F01FBFE84D000006 ++:106ED00000000000000100893C3C00FFE7E424E4DE ++:106EE000000000000000000000FF64FD2020EFEF24 ++:106EF00000000000FFE7FFFF003C003C9918FF7E08 ++:106F000003FF03FF02C23EFE00FC03FF8081FEFF81 ++:106F10000000000000000000000000000000000071 ++:106F20000000FFFF04FF00FF000000000000000061 ++:106F30000000000000000000000000000000000051 ++:106F40007E7EFFFF900090FF3C003CFF080D17B2D3 ++:106F5000000001000000019989996666666624E4D4 ++:106F6000E7E4000000000000000000FF049D003086 ++:106F7000CFFF00000000FFE7FF0FC0FC427E0018BB ++:106F8000667E00FC03FF02C23EFE02FE02FE00011E ++:106F90007E7F0000001008000000000000000100DB ++:106FA00000000086008108800000008400F008B026 ++:106FB00000000086006000B000000086006100B0A4 ++:106FC000000000860C6408B8000000860C6000A970 ++:106FD00000A00000A086706100B00005008600B02F ++:106FE00001A0000005860AA001A900A00086009467 ++:106FF000018000000086006000B0008000860075FF ++:1070000000B0000001860074009800000086007542 ++:1070100000B000000000000000000100000000209F ++:107020000000000000800080000000000000000060 ++:10703000FFFFFFFBFFFFA3F03DFD3DFD0000000053 ++:1070400000000000000000000000005500000000EB ++:107050000000000000000000000088004400FE4026 ++:10706000FE40D77D7DD7FF00FF0060606F6FFE544C ++:10707000AE040A005F55000000001F9F3FBF0000E4 ++:1070800000000000000000000000C3C3FFFFFFFA83 ++:10709000FFFF0001000000400000000000000000B1 ++:1070A00000000000020000000000000C00000000D2 ++:1070B0000000FFFFFFFFF0A0F0A001C101C1000030 ++:1070C00000000000000000000000100000000000B0 ++:1070D00000008000000000000000000022001100FD ++:1070E000FF41BE0082282882EB41AA0090909F9F1A ++:1070F000FE54AE040A005F55000000001F1F1F1F52 ++:1071000000000000000000000000000043C37FFFFB ++:10711000FFFABEBE000100000000000000000002F7 ++:1071200000000000000000004100000000200020DE ++:10713000FFFF00000F0B0F0F0000000039FFC9FF19 ++:1071400000000000000000000000000003033F3FBB ++:107150000000000004040434000000000000F6FFFA ++:10716000F9FFACACACAC027F027FFAFA3CFA005FEC ++:1071700080DFFBFB0B0BC1FD003CFFFFFEFE0AFFA7 ++:10718000FCFF0000000000000000000000000FFFF6 ++:107190000FFF0000000055555514000000000000CE ++:1071A00000000000000000000000000000000000DF ++:1071B00000003E3E02000000000000000000390018 ++:1071C000C9000000000000000000000000000303F0 ++:1071D0003F3F0000000008080838000000000000E1 ++:1071E0009FFF6FFFACACACAC007D82FF50503C50B9 ++:1071F000005F80DFF8F80808013D003CFFEBFEEA85 ++:1072000000003F3F00000000000000000000000000 ++:107210000FFF0FFF0000000055555515020002003A ++:107220000000040000000000000004000000200036 ++:107230000000000000400000000000000400040006 ++:1072400000000000000000000000000000018000BD ++:107250008000002000000000000802000000100074 ++:1072600021008302A00004000400000409000000C3 ++:1072700004002100020008000300000000002100BB ++:107280000200110821080400800002000001200013 ++:1072900020000000000021042001020002880100FB ++:1072A00001000000010000000000000001000000DB ++:1072B00001000000000000000000000000000000CD ++:1072C00000000010000000000005000000000002A7 ++:1072D00010001000201100000000008000000000DD ++:1072E0000100000002000300010001000080C00056 ++:1072F000000001000000000000000000A0000000ED ++:107300000400020000800480A100040000000020AE ++:10731000010021002000A000828000080100000080 ++:1073200000000000000000008000000000000500D8 ++:10733000090000408400090000000001000800006E ++:107340000000800000820800004000001090000053 ++:10735000809080000000800000020000000000001B ++:1073600000C00001000000000004000000008000D8 ++:10737000800102000040841080C000000000000076 ++:1073800000000000000000000000000000000000FD ++:10739000000000000000000000410000001080001C ++:1073A0000088000000000000000002000000000053 ++:1073B00000000000008005000000000000200080A8 ++:1073C0000000000004000000041000800000010024 ++:1073D0000000400004410000041000800000001084 ++:1073E0000000000000080020001100A000000200C2 ++:1073F00020002004010000C00580102100000021B1 ++:107400000041A00000000000840000000000000017 ++:1074100000000000000000200000008800000000C4 ++:10742000200000200000000000000000800000009C ++:10743000000000000020001084A00400000280086A ++:10744000A0892041200200020000000300C000408B ++:1074500000C0002080000088008800022100400257 ++:107460001004004100008008849000012002000008 ++:1074700000010021040100840010008904100000B4 ++:1074800003400000000200C00388418480840000A3 ++:1074900000020000000000000000208820102100F1 ++:1074A00020004108A10000000000000000000200D0 ++:1074B0004000400000210000000005000100002104 ++:1074C0004082102000201000001000000008004141 ++:1074D00090000000008540050000000200004041CF ++:1074E000914101000008000010910340C002038098 ++:1074F0009000840400840404C000000082089010FE ++:1075000000119011A011A04190001000C0000220B5 ++:1075100090000000901010118400C0089102090032 ++:1075200082008302028040410000000000008000D1 ++:107530000000000004000000000000004000800087 ++:1075400005000484108480821000001000000020D8 ++:10755000000080A08001000800C0C0000988000071 ++:1075600009000000000000890000100000A0008257 ++:10757000808500000300000100840400004010101A ++:107580002110000000000000902100001000000009 ++:1075900021100000000002A10800001000000910E6 ++:1075A00000011000400020208200000000000000C8 ++:1075B0002000000000000100000088000000010021 ++:1075C000200000050105C1002000000002000000AD ++:1075D00000C1824102051010008500000500000076 ++:1075E0000000004100100000A00800001100000091 ++:1075F000000020200041840002040000014100A19D ++:1076000001A1028088038200880010C0000082006F ++:1076100020008400000300210108A00300090803E2 ++:107620000041000400000100C10021000000100022 ++:1076300000C00300004000022000208400080384F2 ++:10764000000404C000204020202020200410040258 ++:1076500020020402000040844102084040901010C3 ++:10766000000000880488400221100040000000084B ++:1076700020012020098803010800A12002200084A5 ++:1076800000401040031111004104110021101000AE ++:107690000304089000C004C0000009840082A00018 ++:1076A0001082050420A010041040410405020000CF ++:1076B000000000000010008000000102010000A096 ++:1076C00090000080401100404000C1800140100047 ++:1076D00001C0001001030000000000000100912122 ++:1076E00082050000000940410041000984090000B2 ++:1076F00000A1110805208809840884002040852104 ++:1077000000008200010090020011821100408400FC ++:107710000000A0001011C000000000000000820066 ++:107720002100C009A0A1112010800000A08900A0A4 ++:10773000000000010000001000C0200000000082D6 ++:10774000118400042002001000C10008051000C0D0 ++:1077500000100000091000848240028500019000A2 ++:10776000800004A00000202100C0041000000000E0 ++:107770000000118510844184A00508080004084019 ++:10778000809100000000000191110000008400C001 ++:10779000029000C0000000009001030010001001E2 ++:1077A00003000500201020104100211000000002FD ++:1077B00003100000000400000000000001000000B1 ++:1077C0000000000000808980000000100080004060 ++:1077D0000000201000050000100021C10104C004B9 ++:1077E000201040119010900090A0880084000800A4 ++:1077F0000221004004080100000021840080008074 ++:107800000080040400410000001008200000000077 ++:1078100000000000100010000040024010000010A6 ++:1078200003088400000083001100A0000000000095 ++:10783000084100009105804003830911890910A0C7 ++:10784000082000411085102009081041C0100008D0 ++:107850000990039000000880028000800880C10029 ++:107860008880080002A080030983400810000500FA ++:107870000000410000800011824104090009000558 ++:10788000002040201004208908C000051184000059 ++:107890000000090000000500000011000500C08084 ++:1078A0001000848020801100890010000800090366 ++:1078B00009200940101082218288001001900808D8 ++:1078C0004110C110002121830189830001894004F6 ++:1078D0008401C0080010009091C0000800C001821F ++:1078E0000810040800040310C0A000100010882035 ++:1078F00001840090000000000000050090000000DE ++:107900000001400101010000C0820184008200C02A ++:107910000000880000000000000088000000000057 ++:1079200089101084081000C0880009008800010038 ++:10793000880101000000000183004188092108211D ++:1079400000008484880010400801110888092190F3 ++:107950000800820011048301900189000900418818 ++:10796000000101000100009108001000C10810A1F1 ++:107970000101010000C0002000001000888900887B ++:1079800010010810048805A08400002100000002F6 ++:1079900000880800200009C0080000000100010064 ++:1079A00001000001C000000002C001000101000050 ++:1079B00001010900A101A1C0C100100904808521B5 ++:1079C00040090900C0000000A0009102880090401A ++:1079D0008800800803009000900800404000C0002C ++:1079E000034009404005050040410511A000020088 ++:1079F000000802101000108008000000000900209C ++:107A000000910040008020804080892009031100FF ++:107A1000008010008000200089001100020040005A ++:107A20000800400000030000000000801100200456 ++:107A300040002021020009042000892003828008E0 ++:107A40008888410040400020802000880888008409 ++:107A5000C191004010080088114108080000800012 ++:107A6000A180808000090011A008004040028091A0 ++:107A7000A085A003000400110040000800000400DD ++:107A80000000030010800203034009208010004022 ++:107A900005000040410900000000008000000009CE ++:107AA00000110082001000000011808800918010F9 ++:107AB000000440C000098011001111048008011168 ++:107AC0001088028501C00090088408400011001150 ++:107AD00088101003902100040009008305040008A9 ++:107AE0008840A084881002888802A1C10801010989 ++:107AF0008811A08488C10000840120018800000052 ++:107B000000000002011001900004008901090288B0 ++:107B10000001900082009000002000080084C0084E ++:107B200000C000C10009000200080000A08508880C ++:107B30008290000401A0021082A0000800049002BC ++:107B40008400008900000188908800C0880101102D ++:107B5000418441838300402084918440040040405C ++:107B600084001041A000C0888284C000820004000C ++:107B70008491088988001088849008019000C000D2 ++:107B80000000910940841000912000000140010193 ++:107B900001A082A01000A000080000010000000069 ++:107BA00000400004000000000000102088000800D1 ++:107BB00000080088008400010000008900C1000165 ++:107BC00000829103080808032080408420202010B0 ++:107BD00009800380410802114000808300000020DA ++:107BE00000808000801100008080808000040010F0 ++:107BF00000008020800400058080800080410040DB ++:107C000000000000038390001100880041100288EA ++:107C10000820100080008004000800000010000907 ++:107C200000080080000000040008000080008000C0 ++:107C3000000000800000000900200000008900848E ++:107C40000009008000000013C20082000000001341 ++:107C5000C200000000000013C2000000000000137A ++:107C60006000210000840013608000000000001309 ++:107C7000C200000000000013C2000000000000006D ++:107C800000000000000006000013C200828800000F ++:107C90000013C200000000000013000042000000BA ++:107CA0000013000000000000000000000000810040 ++:107CB000001300008200000000008400410000006A ++:107CC0000000840041600000F0B0404140410030BD ++:107CD00000000000010055550000E0F0EFFF00003B ++:107CE0000000000200000000000000000000000092 ++:107CF0000000555F55FF000000000F550F0F0000FA ++:107D000000000FFD0F3D0000505CFCFC0000000077 ++:107D1000330FF0333C0F3CFF00000000003C00003C ++:107D20000000000000000000000000004AFF4FFFBC ++:107D300000000000F555F5F500000000000070F0AF ++:107D400000000000AA3CAA0F000000400100010052 ++:107D50000000000000000100CCCC003010001F0F1C ++:107D60000000000000000000000000000000000013 ++:107D700000000000005F41AF000000003C553C3CAB ++:107D800000000000053F053F0000000C0C0C000047 ++:107D90000000CCF00FCC3C003CF000000000003CA8 ++:107DA00000280000000000000000000000000505A1 ++:107DB0000F0F00000000A0F0F5F50000000000002B ++:107DC00000F000000000003C000FFFFFAA00FFAA27 ++:107DD000FF000000000000000808FF0FFF007E42C7 ++:107DE000FCC0DFFFFFFFF00F0FF0000000000A0AE9 ++:107DF00000AA00000000FF3CFC30FCB8B830B2F331 ++:107E0000B2F300000000FF55FE540000FFFFFFFF2B ++:107E100000000000FCFFFCF0AAFFAA00FA507878EE ++:107E2000B2B28282000000000000000000000000EA ++:107E3000F8F8FF2F00000000000000000000000024 ++:107E4000FFFE5554F03C00C3DFFFFFFFFFFFA80813 ++:107E5000FFA8FF080C000000000000003F3F30308A ++:107E6000FCC0FCC0FFFFFFFF00FFFF0000000000A0 ++:107E70000A0A00AA00000000BE28FC300000000032 ++:107E8000B230B23000000000FE54FE540000FFFF8C ++:107E9000FEFF000000000C0F0C00F0F0F0F0FA50B4 ++:107EA0007878303000000000000050000000000032 ++:107EB0000000F8F8F82800000000000000000000B2 ++:107EC0000000FFBE5514F03C00C3FFFFFFFF00861B ++:107ED000006108900000008600F10880000008861C ++:107EE00000F008800000008600A1A08000850086C8 ++:107EF000002500900010A08650E1A09000050086AB ++:107F00000031009200800086006000B80080000010 ++:107F1000058652B0A38000050086007100B0000005 ++:107F20000086026100B000000086006000B0000022 ++:107F30000086006000B00080008600800190000094 ++:107F4000A0865070A8B80005A0865A70A8B0008519 ++:107F5000FFFFFFFF3D053D050F0F00003C7D0F4F6C ++:107F6000F700FF0000020000FF3A3A3A2C6DFFFFD5 ++:107F7000FFFF3C0000FF0FFF08002800000000008A ++:107F8000FFFFAB0005FF05FF00FF00000000000041 ++:107F90000000FB0BF808FF550F5500000000FFFF25 ++:107FA000FFFF2CBF936C000000000000000040F0B9 ++:107FB00000F000000000FFFFFFFFFF00AA004141AA ++:107FC0007D7D00000000F3F3F3F3000000000000EB ++:107FD0000100FFFFAAAA3C003E0A000000003C414D ++:107FE0000F4FFF00FF0000020000FF3A3A3A2C6DED ++:107FF0000041FFFF381001FF0DFF000028000001C5 ++:108000000001FFFFA80004FF45FF00FF0010000073 ++:1080100000000000FB0BF80800550F5500000000A1 ++:10802000FBFFF1FF083E36C9000000000000000021 ++:1080300000F000F000000000FFFD7F7DFF00FA501F ++:1080400000C33CFF00000000F1F0F1F3000000006D ++:108050000000010000400000BA92FFFF0040004114 ++:10806000AAAFFFFFD7FFD7D700002000C0C0000095 ++:10807000000055550028001805060000CFFF4414E5 ++:10808000000000000000702000001010000A000036 ++:108090000000000000000000000055553C3C0000BE ++:1080A00000000F8F0F0F5AA593360000000000004C ++:1080B0000000010000000000000000000000FF00C0 ++:1080C000FF0F0A0A5F5F00000000000000000000D0 ++:1080D0000000FFFFFFFF00000000AA82FFFF00403A ++:1080E0000000000F555FFFFFFFFF00002000C0C031 ++:1080F00000000C00C33C0028002805060000CFFF4C ++:108100000000000000000000F0A00020103000007F ++:1081100000000000000000000000000055550F0F97 ++:10812000000000000FDF0F0F5AA56CC9000000000F ++:10813000000000000000000000000000000000003F ++:10814000FF00FC0C0A0A5F5F000000000000000056 ++:10815000000000007FFFFFFF0000000000000000A3 ++:108160000800000000000000000000000000000007 ++:108170002100000400A0000010000000000000002A ++:108180000400000000000000000000C0000000002B ++:10819000000080000000000000000000000000A0BF ++:1081A00002000400800000400300100000004000B6 ++:1081B000030000002000000002000000000020403A ++:1081C000000004002000210004008802400041005B ++:1081D00000002000840020002000000000000000BB ++:1081E000000000000000000000000000000000008F ++:1081F00000000000008000000000010000000000FE ++:10820000000000000000000000000000000000006E ++:10821000000000000400000000000000000000005A ++:108220000000010000001000908088000100A00004 ++:108230000100000000000002000300000000A00098 ++:108240000080000000000000A00301002080010069 ++:108250000000000009001100010001000000000002 ++:108260000000000000000000000000000500000009 ++:10827000000000000000000005002100000000A038 ++:1082800000008000004000400000000000000020CE ++:1082900000A08000800000008082000000C000007C ++:1082A00000000000000500000011000000000000B8 ++:1082B00000000000000100A000000000000080009D ++:1082C000000000000000000000011000000020007D ++:1082D00000000000410000100000850000000000C8 ++:1082E000000000000000000000000000000000008E ++:1082F000000000000000000000000000000000007E ++:10830000000000030410008000800008002100002D ++:1083100000200000020002410000100000200000C8 ++:108320000000000000000090001100080010004153 ++:108330000041000000200008000000000000004193 ++:1083400020000000001100000000000800200010C4 ++:1083500001090008000000000009000004000020DE ++:10836000000000000000000000000000000000000D ++:108370008000040080008900002000000500040146 ++:1083800010A00000400080040240000100400010E6 ++:108390004010034004008084109000C000C000A082 ++:1083A0000000118240028082C085040811102082E2 ++:1083B00040204082410002850008001003028840EE ++:1083C000419000200302004005C000840008030122 ++:1083D00080001000411090401100024000C01100C8 ++:1083E00010400000880000000000000040400041F4 ++:1083F00000102000011020000200002000400005B5 ++:10840000000801210000050004C183210040008014 ++:1084100000008300004040024010C141001188214B ++:1084200000030000400089000410414000000010DB ++:108430004100400500008441894084800000C0055F ++:1084400002A084400000004108A182030000C08017 ++:108450008440040390210000112110200100C0007D ++:108460009000100800000000110000000000000053 ++:1084700000000000000000000000004100000000BB ++:1084800004001100A00100000200040002008900A5 ++:108490000801000141001101000002854140000077 ++:1084A00009000000000000004001000041010082BE ++:1084B00021000004211011100200C0000200000081 ++:1084C000030000000810000040A003042100000089 ++:1084D0002100090010101000090084008200000033 ++:1084E0000008081003400000000000000000000029 ++:1084F00000000000020000008800C00000C0001062 ++:1085000000000000000011080000000089030100C5 ++:10851000020001100020882100020041010810A182 ++:1085200084050011841000000009014000000010C3 ++:108530000040000000A1004100030009414101008A ++:108540000000004108410000040300000885840089 ++:108550000041C010881008050041002110050541A8 ++:1085600000108490C1001080000000000000000096 ++:108570000000000000000900A0000010200400001E ++:10858000000200000589000000008400402009046A ++:10859000800002100810000004C009400000210003 ++:1085A000414041404104098400008020002100C076 ++:1085B0008088110010102040912000900902824113 ++:1085C0000500092021C00800040000020502000087 ++:1085D0000500004008000382210091400502A1022D ++:1085E00010C0051041042088118400080408001000 ++:1085F0000410000504000010040805110011019189 ++:10860000880984C184000408842100050500004114 ++:1086100000800211050001C08800002102024041D3 ++:1086200004100480040088008800000002088240D2 ++:10863000820240210000010041800200002100412F ++:1086400003828400840082210021C1210000820075 ++:10865000000010410040A010002110090200820417 ++:1086600010809000000004112011C02100000000C3 ++:108670000000000000000000000002004000200098 ++:108680004001200004400088008402102000910175 ++:1086900004008040114009000010000000A09184F7 ++:1086A0000010100141C10000040009C0000010C00A ++:1086B000210000C082A0004090100020024108006C ++:1086C000001100A005820084400000A002A0090063 ++:1086D00080C002A082820484401000A020042110E7 ++:1086E00003000008020000C04110211040040000F7 ++:1086F0000000000000000000000000000000010376 ++:108700000110C02001210005A0200000000300008E ++:1087100004020000040000908221002100100209E0 ++:1087200004000000C120C0400208C0110000000089 ++:1087300082050021000303410000114100410002B5 ++:10874000090000408800C00900000100000000008E ++:1087500000002003C121200000000110880000005B ++:10876000840000211090001000051003C08011004B ++:1087700000000000000000000000000000000000F9 ++:1087800008800980048009800000911141090900D6 ++:108790000000000020000000098310000005000315 ++:1087A0002085118503C020801008000400400009C6 ++:1087B00000000040901140C0008808038040401035 ++:1087C00009110000800041000000000000000000CE ++:1087D0000000830000090805202040050005054031 ++:1087E00080834080000002802000108982C18900BF ++:1087F0001004000000000000000000000000000065 ++:1088000000000190052090C0018400008901010151 ++:1088100000000000200000000000058301400088E7 ++:108820000040910220400010001000C100880008A4 ++:1088300000C0000000A1848801C0009100018200F6 ++:1088400000000000000082000000000000000000A6 ++:1088500000000000200020010100010120891041DA ++:108860000089881001040088008801909082040823 ++:10887000C0C0000000000000000000000000000078 ++:1088800000000000100108000800848982008900AF ++:1088900089C08300410009212000090388A1C00488 ++:1088A000C10341888201C005094011C000000010C9 ++:1088B0000000000000000401C020A1109004A000EE ++:1088C000040002008400400004A0100083C04100A6 ++:1088D000900090049000020085004000850108018E ++:1088E000820221858511000001A00182010005009E ++:1088F000C188880811090000000000000000000085 ++:1089000000000000000000080005000080A04000FA ++:10891000C0008580A00008110940000303831108EE ++:108920000000890203000810912082854184000024 ++:1089300000800021000000000002000210009105EC ++:10894000100011002000A00009094000C0058800A7 ++:1089500002001000090010000000410000418920C1 ++:1089600000402000219083890000088005851000C8 ++:108970000240880084890983000000000000000094 ++:108980000000000000000000000800080208008845 ++:1089900011110009009189830000000021808000EE ++:1089A00009104109030409034020800000A11005BB ++:1089B00003098005000220080000100080800000EC ++:1089C0008000400900080009054000000000048004 ++:1089D00000000000000000000000034100022089A8 ++:1089E00010032008802003100541004000040821E6 ++:1089F0000003400800800089208000000000000083 ++:108A00000000000000000000000090409020008264 ++:108A100008100100000000A08983A0080084010262 ++:108A20002010000090018200020100008888088464 ++:108A300085104100040108010100000001C082020C ++:108A4000A0C020A000000091009001910020000033 ++:108A500000840090000000000000C00001900008A9 ++:108A60000011010201080482908988020005008833 ++:108A70008308024101A1041004110102000000005A ++:108A80000000000000000000000000000821C08875 ++:108A90002000C08800010001000100881111880039 ++:108AA000840141A085C0A103A000C0408410020041 ++:108AB000820140840084050005000200000083104C ++:108AC00004011000900200080001000000A083C013 ++:108AD00008848801C0A000010001000000400121BD ++:108AE0000040000001A0098440908201A08201089A ++:108AF0000109000001000185898390010410000034 ++:108B00000000000000000000000000000000000362 ++:108B100000008000800000110020004000801083D1 ++:108B2000C011A1090800834002C005108000880917 ++:108B300021040908058003800800080040000000A7 ++:108B40009080004100404100000300200008000028 ++:108B500003101008020311000040004000040080D0 ++:108B600009020585051020001091A0A10841088088 ++:108B700003004004001140000985858480030080C3 ++:108B800000000000000000000000000000000000E5 ++:108B900000000013C20021000000000810000000C7 ++:108BA00000000013C200425000000013000000004B ++:108BB0000000001300000000000040130000060049 ++:108BC000000081000013C2000A0000810000C20002 ++:108BD0000A0000000000C200426000000013000014 ++:108BE000000000810000C200420011000013C2001A ++:108BF000004821000013C200008411820013C2004B ++:108C000041600000000000000000000000000000C3 ++:108C1000000000000000FBFFFFFF00000000F3FF6A ++:108C2000C3FF00000282000000000609F0F644883D ++:108C3000B910968E170F7E2481DB00098181FF2DEC ++:108C4000002D0000FFFFC3C3000000000000000073 ++:108C5000000000004E4EFF4E00000000000000002B ++:108C600000000000FF4E004E66006600000000009D ++:108C700000020000FFFFFFFF660FE7CFFFFF0000CD ++:108C80003C003C000000000000000000000000006C ++:108C90000000000000000000FFFFFFFF00000000D8 ++:108CA000FFFFFFFF3C0080000000000060900060BC ++:108CB0004488B91096B2D4F081DB7E24000900000C ++:108CC000FF2D002D00000000C3C3000000000000C5 ++:108CD0000000064697D74E4E004E000000000000F0 ++:108CE000000000000000FF4E004E7F1976106666FF ++:108CF000260000020000003C4242660F240C99004E ++:108D000099007E427E42FFFFFFFFFFFFFFFFFFFF54 ++:108D1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 ++:108D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 ++:108D3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 ++:108D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 ++:108D5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 ++:108D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 ++:108D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 ++:108D8000FFFFFFFFFFFFFFFF0008C2470C44C0309A ++:108D900000180A06000070DF00000000000000005C ++:108DA00000000000000000000000000000000000C3 ++:108DB000FF9FFF9F3C3C1C3C000000000C0C22224B ++:108DC0004747A0A0BD18422469966699000002009A ++:108DD000DD44BB22000000000000FCFCFCFFFF00A3 ++:108DE000FFFFE4F0C3FF00F00FFF00000000FFFFF3 ++:108DF000FFFF00000000202020380EFE0EFE999993 ++:108E0000FFFFF4FFFFFFF0F00FFF00000000FFFF87 ++:108E1000FFFF24BDBD240E0FFEFF00000000000078 ++:108E20000000000000000000000000000000000042 ++:108E30000000FFFFFFFF3C3C3C3C000000002E2EEA ++:108E40001111424205053C0081189966699600009F ++:108E5000000044DD22BB000000000000F0F0F0FF45 ++:108E60009900FF996672003C3636363600000000E5 ++:108E7000FBFB38FB000000000000001802F202F2C9 ++:108E80009090F6F6040F0F0F060000F000000000AF ++:108E9000FF9F009FBD2424BD0E0CFEFC00000000BF ++:108EA000000000000000000000000000A0865081CB ++:108EB000A0A800050006006008090000A186502156 ++:108EC000A090486500C7006000B0510000860C21EA ++:108ED00000B800800086002100B00000000000867D ++:108EE0000C6109A0008500860A6408B000000886AD ++:108EF000007000B000000086006000B000800086B6 ++:108F0000007400B000000086006001B0001005860B ++:108F1000007101B90080008602B401A000000000C9 ++:108F20000000000000000000000000000000F069E8 ++:108F3000F0AAFEFFFEFF0000000055AAFF00F0F0BF ++:108F4000F8F4555F555FD7D7EEBF00000000A0A032 ++:108F5000BCBC0FFF5F5F0C3F0C3F00000000000037 ++:108F6000FCFCEB280000000000000000555FFFFF44 ++:108F70000000C240000000000000000000000000EF ++:108F8000000000008200AAAA00003C3C044500004A ++:108F90000000000000000100EA40EA408E8E82BE20 ++:108FA00000000000000000000000000000000000C1 ++:108FB000F0AAF0AAFFFFFCFF000000000000000084 ++:108FC00000002814555D55DFD7D7EFFB00000000E7 ++:108FD00050007C3C00F050500C3F0C3F0000000063 ++:108FE0000000C0C0EB280000010000000000000FDE ++:108FF000FFFF00000000000014000000000000005F ++:109000000000000000008080AAAA0000FE3C0CCFF7 ++:10901000088A0000000000000100FF00FF000C0CA7 ++:10902000003C000000000000000000000000000004 ++:109030000000FECA3E0A0F5A3C3C000000000F0B25 ++:10904000040B0000000053C35FFFBEBEFCC0101045 ++:109050000000FFFFFFFF8A80DFD500000100000055 ++:1090600000000000000000003000200000000000B0 ++:109070000FAFFF3F00000000280055FF0000000078 ++:109080002A0FAAFF000000002DFFFFFF0000FC0CCC ++:109090001F5F1F5FF0FFF3F30000000055AAF0F020 ++:1090A0008ADF005500000000000000000000000002 ++:1090B00000000000FECA3E0A0F0F3C3C000000000A ++:1090C0000004040B0000000050005C3C8282FCC0E5 ++:1090D00038102800495D4155202A757F00000000A6 ++:1090E00000000000000000003420300020000000DC ++:1090F000000000003CFF000000002D0500AA000059 ++:109100000000AA008A000000000005FFFFFF000029 ++:10911000AAAA1F1F1F5FF0F0F3F30000000055AA7A ++:1091200055AA085D00550000000000000000000086 ++:109130000000000000010000200000000401000801 ++:109140002108210300000000000020900000009092 ++:1091500000400001C001112000100220912084A0D5 ++:10916000800080204000000020002000004082405D ++:1091700011100040110040004000804010001040DD ++:10918000020020000200200000000000210020005A ++:10919000100110002100A040110000000300000099 ++:1091A00000000440840004000000000000000000F3 ++:1091B000000000000000001000000100000001405D ++:1091C0000080008000880000000000000000000017 ++:1091D00000000080882041200080008001802080E5 ++:1091E0000500040004800100000000000000008071 ++:1091F0000280000000800000000001091080C1050D ++:109200000180010000002100C000000002000000F9 ++:109210008200010801000400048000000000040036 ++:109220008800000001801100A10000000000000083 ++:10923000000000000000000000000000000000002E ++:10924000800000000000000400000000800000001A ++:1092500000000000004080000000000000C000008E ++:109260000005000000000000000100C00000000038 ++:1092700000000010000000000001000000C080019C ++:109280008009880500080000000000000000800040 ++:1092900002080001000100000000000100000000C1 ++:1092A0000040000000000041000900010000000033 ++:1092B00000000000000000000000000000000000AE ++:1092C00000002000000000000080000000000200FC ++:1092D00000000000000000800200000000110041BA ++:1092E0000021008400110000000000020000004185 ++:1092F0000010002100000020000000080000000015 ++:10930000024002C00990008000000005000000003B ++:109310000211018090400040000000100008880801 ++:10932000000004800010000088A000A000200000C1 ++:109330000000000000000000000004000000000029 ++:109340008201110000000409040104010403050066 ++:10935000000000100000000811400000408400845C ++:10936000802000414084C10200201084008500005C ++:1093700011C000A009C04110000209820040A140B4 ++:10938000111080A000402121000200400040000098 ++:109390000000804000888085909005400000008893 ++:1093A000000002900501004011000010021190829F ++:1093B0000000000000000000000504000408000098 ++:1093C0000010210400100000018401040104018444 ++:1093D00002009005904000000003C0C10440C0009E ++:1093E00000090280C0C0831040214083054104046D ++:1093F00000000005C0210041C00800008800820074 ++:1094000040A100210400C009A0A000A1004000006C ++:10941000100000000200000020081000A008080052 ++:109420000010100891001008C0050221C04011086A ++:10943000100000000000000000000000000000001C ++:10944000000000A000880010000000004021002063 ++:1094500002040940040811000405028400A0000071 ++:1094600040090084020080A0908341201120042044 ++:10947000008500000084000010824008098200403E ++:1094800004001009030803218200852010A00300B6 ++:1094900000C021000800000100C01000000805C045 ++:1094A0000300000405080082000005008802100087 ++:1094B000C1080304000000000000000000000000DC ++:1094C00000000000000040000000000000100184C7 ++:1094D0000080858000900080001100A00010000036 ++:1094E000000001A0880020000205204000800080CC ++:1094F0001180844000000000840000002100000072 ++:1095000000800121019000800040110040A1000571 ++:109510008200000000210000104082000010008046 ++:1095200000000000000000108410000810090490E2 ++:109530008821108900800000000000000000000069 ++:109540000000000000000200000000002000801069 ++:10955000008580088001020808004084094003104B ++:10956000000000100084802080C082100011008460 ++:109570000300C01100840000002000200201A003AD ++:109580000040C04011909008100110851004842004 ++:10959000410003404100034005400982050021408D ++:1095A0001000038200C00902038200020000830849 ++:1095B000000008848310400800000008000000003C ++:1095C000000000000000000300100010000801105F ++:1095D00020080004201104040111001001200003E0 ++:1095E00000000040A0800805402102104105000253 ++:1095F00000000040040802030000000000200008F2 ++:10960000414004C102A1820008800002014000C064 ++:1096100005800011880000000080000000000000AC ++:109620000008011000050000000800000000100004 ++:1096300002A1A020C000104008900000000000001F ++:1096400000000000000000000000000020000000FA ++:1096500002000404000800000011109000C0008403 ++:1096600000000040008400100308008200108010F9 ++:109670002008829010000010000000000388008481 ++:1096800000088284098882A011108211000000095C ++:1096900080404010218240840300418410A0418218 ++:1096A000200008C1410903000302908203088240A0 ++:1096B00000040200100005918290054100000000A6 ++:1096C00000000000000000000000000090000141C8 ++:1096D0000000900001004080400040200100000098 ++:1096E0000000000000800000000004830000100063 ++:1096F0001000001004000000000000000000004006 ++:1097000000080041200300410300C0004110000098 ++:10971000888804A0119000002110C01084108800D7 ++:109720000000882100400088C00000C12000000027 ++:1097300010000010101000000020040000200000A5 ++:109740000000000000000000000000000000021106 ++:109750000009400308081103004021082040104080 ++:1097600080881040041180C000034082000008047B ++:10977000000909052005A0802085824100A1008004 ++:109780000011800510900390200880112109851197 ++:1097900021038810A0091110100000000200080029 ++:1097A000402088111120024090050520040011403E ++:1097B0004005001004104108110008808580090050 ++:1097C0000000000000000000000000000000000099 ++:1097D0009101080100000001000188000000000163 ++:1097E00000081085009000900882C0000011004021 ++:1097F0000100080000000000880840C00391000834 ++:1098000000000004849101110089018384880120F3 ++:1098100091888901C10002000101019040040020EB ++:109820000100010008000100000085A18400004043 ++:109830000041C0018400000000010840A010C08465 ++:109840000004000000000000000000000000000014 ++:1098500000000000000001880088019000A10102C2 ++:10986000000001010090080008900800211020C0AD ++:1098700084021090104040A041A011009000000010 ++:1098800008080000030103C0212185000400000432 ++:10989000A0C00241A1008502A18308894100901067 ++:1098A00088012000A00101A0040085C0C00009C0FB ++:1098B000210008C000010502C0400304051091000A ++:1098C0004190854100000000000000000000000001 ++:1098D000000000004010200002001180080040033A ++:1098E00005C103091108100089088900800588084E ++:1098F0000809A0808009838000A109059100050066 ++:109900002000A1820000900240C188858805914016 ++:1099100040028900A111A003C0808505A11110009B ++:10992000000010212020091008000920C09103091F ++:109930000500050941A00802A08021918880A0901F ++:1099400004008500881000000000000000000000F6 ++:10995000000000000000109100030340410383A0B9 ++:1099600011084008892108098009009008C0118069 ++:1099700080800000A080028803880005028803110F ++:109980000090080005000000082000A1000302214B ++:10999000400900110890214008910420112089C03D ++:1099A0000009000880A000880282000520820805C6 ++:1099B000200880040388044008210090401010858E ++:1099C00000A02084A10900030000000000000000A6 ++:1099D000000000000000000001020088000891085B ++:1099E0000502009101901040001084840884408991 ++:1099F000000282908810400200050011008302835B ++:109A000001C08810018220400000000900C0081039 ++:109A10000290000840914003009100A001410041E4 ++:109A20000589004088C1088408080110000201C0AF ++:109A300000210088821190840220002000C10109C9 ++:109A400008080009C004100240A100000000000046 ++:109A500000000000000000000000041010908401CD ++:109A6000400001000084010001009110C1000801C4 ++:109A7000880091201001080190081040100000009B ++:109A80001008084108011000909000004085020075 ++:109A900020012002820182008800099083882182AF ++:109AA000200088C00101000101010082C010214096 ++:109AB000000090A09141C0112101091004894109C1 ++:109AC0009100C088208502408201C008000000008B ++:109AD0000000000000000000000000008080000383 ++:109AE00000028000030041A141002000088088118D ++:109AF0004002080020049010900208002102200873 ++:109B00002011020000088041800500000000208331 ++:109B10008408030200008903201109112003C08971 ++:109B2000408509008000100809080821008008000D ++:109B300005400308210003820810C1202080110283 ++:109B400004414009800000908004004100000000B2 ++:109B500000000000000000000000000000002100E4 ++:109B60000013C200000000000013C2000600000045 ++:109B70000013C200000000000006000042000000C8 ++:109B80000013C200000000840013C2002100000086 ++:109B900000000000C2000A000600001300000600DA ++:109BA00000410013C20041000000000000000060FE ++:109BB00000810000C200000000000013C20082000B ++:109BC000000000000000000021000013C20000009F ++:109BD0000000000000000000000000000000000085 ++:109BE00000000000153FD5FF141400100C5F0F5D3E ++:109BF0007DBF7D3DFFFFFFFF7DDDD7DD0000000065 ++:109C0000557FAA8033C3C9C3000000001E1E1E1E5C ++:109C1000000000FF5F5F0C3F0FFF0C0FFCFF0D3DCE ++:109C2000073FAAFF0F0FFFFFFFFF50000000283C77 ++:109C3000283CAAAAAAAA000F777F35355555050FEB ++:109C4000040E000F555F05000C00000000000030FE ++:109C5000CFCF000000000000000000000000000066 ++:109C6000000000000000002AC0EA000000000C5FB5 ++:109C70000FFD05550555FFFFFF7F41111411000031 ++:109C80000000057EFF813C3C6B6B000000001E1E47 ++:109C90001E1E000000FF0F0F000F0C3F000FF0FF13 ++:109CA0000D3D373F00550F0FDFFFFFFF00000000A5 ++:109CB000280020288A8000000C0F777F303F00FFAB ++:109CC000000A040E0000555555503C3000000000BD ++:109CD00041710C0C000000000000000000000000BA ++:109CE00000000000FFFF0804FC3CFC3CD7D7070045 ++:109CF000D540C00004FB55BE00000000FFFFFAAADB ++:109D000005000000DFFFFFFF50505050820082002E ++:109D10000000F1F100007D7D3C3C002800822F2FE7 ++:109D20002F2F3CFF00F3BEBEBFB03A3F3A300000D9 ++:109D30000000000082000F0AFFFFFFFE00FEAAFFE6 ++:109D4000EBEBFFFFBEBA555501010404050000000E ++:109D50000000000000000000000000000000000003 ++:109D600000000000000008040804FD3CBC3CFFFFAC ++:109D70000800D540C00003FCFF0000010000FFFF09 ++:109D8000F00000000000FFFFFFFF555500008300BA ++:109D9000830000000353000055555550507850D2B1 ++:109DA0002B2B2B283CFE00F214141F103A3F3A30A4 ++:109DB00000000000000000000F0CFFFFFFFC00FC93 ++:109DC000FFFFEBEBFFFF1410555500413434F50055 ++:109DD000000000000000E80000000000000000009B ++:109DE00000000000000000000086006109B80000CB ++:109DF000A5865A60A0B00085018600610898000021 ++:109E000000860C6000B0008001860260003800000F ++:109E10000086028408A80000000000860C6000B0E4 ++:109E2000000000860C6101A0008000860AFCA0B83A ++:109E300000000086006000B800800186006408B061 ++:109E400080050586006008B000050086006000B04F ++:109E50000000008600E109B90005000000000000D4 ++:109E600000000000008000000000DFFFFFFF5C5FDB ++:109E7000FCFF000000003D7DC2821E001EFF0000AE ++:109E8000FFFFFFEFFFEF00F100FDC300EB283C3CBC ++:109E9000FA05FCC0FCC07DBF824000000000000845 ++:109EA000C0F0FCFC7D28FAFA00000000E8E8FF3C66 ++:109EB000A0A0C300000000000100FFFF828200009C ++:109EC0005DFDFFFF141450503FFF5F5F08081C1C2E ++:109ED000D7D7FFFFFFFE5554F20202020000000038 ++:109EE000000000000000000000000000FFFFFFFF76 ++:109EF000FFFFFFFF00000000195DEEAAEBFFEB0083 ++:109F00000080FF7FFF2CFFEFF1FFFDFFFF3CEB2800 ++:109F10003C3C05FAFFFF00000555FAFA000000007E ++:109F2000000840F07CFC7D28505004000000E8E868 ++:109F3000C30000000000000000005100FFFF82AAE3 ++:109F400000005D5DFFFF003C00F00F0F5F5F0A0047 ++:109F50005F00CFFFCFFFFFFA555000000000000068 ++:109F600000000000000000000000000000000000F1 ++:109F70000000000000000000000000000000AF052D ++:109F8000AFAFFF000000DCDC6C6C8ECF4DCF00006B ++:109F9000000000002828EB28E8E8FFFF1E1E000054 ++:109FA000FFFF3FFF000F7DDFFFFFAAF3000000006F ++:109FB00000000000BFF36FF300000A00FF8FFFFFF7 ++:109FC000000000000055147DB2B2B2B2140C140CA3 ++:109FD0000000000000FF55550A0A0A0A00003C0F65 ++:109FE0000000000000000000400000000000000031 ++:109FF0000000000000000000000000000000000061 ++:10A00000870587AFFF0000009C9C33338E0C4D0CFE ++:10A010000000000040018001EB28E8E800001E1E5F ++:10A020000000FFFFFFFF003F7DDFFFFFFFF3282859 ++:10A03000280000000000DFF3EFF300000000FFDF66 ++:10A04000FFFF000000000055147DFFFF000000002E ++:10A050003C3C000000000F0F0F0F08080800000034 ++:10A060003C5500000000000000000000000000005F ++:10A070000000000000000000020000880000000056 ++:10A0800000000000000000002100000000000000AF ++:10A090000000050000A000000400210021000000D5 ++:10A0A00021000000000000200091110000000000CD ++:10A0B000A000C00209000002001000000000001013 ++:10A0C00000208408000000040002000000000004DA ++:10A0D0000400040020100002000000000000210025 ++:10A0E0000404210000000000000000000000000047 ++:10A0F0000000000000000000000000000000000060 ++:10A10000000000000000000000000000000000004F ++:10A110000000000000000000000000000000000837 ++:10A120000000000000008800000000100000000097 ++:10A130000000050011800000008088800000000001 ++:10A1400090800080108000000080008000000000EF ++:10A15000008401000000008000800000000000007A ++:10A1600000000180900000000000000000000000DE ++:10A1700000000000000000000000000000000000DF ++:10A1800000000000000000000000000000000000CF ++:10A1900000000000000000000000000000000000BF ++:10A1A000000000000000004000C0000100000000AE ++:10A1B0000082000000010008000000C00000000054 ++:10A1C000000000028084000900000001000000007F ++:10A1D00000008000002000080000000000110000C6 ++:10A1E00000000082000000080000000000000000E5 ++:10A1F000000000000000000000000000000000005F ++:10A20000000000000000000000000000000000004E ++:10A21000000000000000000000000000000000003E ++:10A2200000000000000000100000000000400000DE ++:10A23000000000000000000400C100110000000048 ++:10A240000000000000A00421008400000040000085 ++:10A25000000000080800009100800000001000824B ++:10A26000000000210041002100C1000000000000AA ++:10A2700000000000000000000000020000000000DC ++:10A2800000000000020000000000000009100000B3 ++:10A290001100020021000010210000000400000055 ++:10A2A000020004C0000000000000000000000204E2 ++:10A2B00002838400040000040200808308900320CD ++:10A2C00011000000008441840001A08400A020014E ++:10A2D0000085411000820382800400A1000009C0B3 ++:10A2E000008400A0119040C0001111110000000076 ++:10A2F0000000000000000000000000000003000556 ++:10A3000000000000000300000005881000000408A1 ++:10A31000A00800419005000900030041002100024F ++:10A320000021000384410010C0000021000000054E ++:10A33000C1850102100000080083004140080509A2 ++:10A34000A0800010104100410000A0042100000086 ++:10A3500085408840024000088221208900021010B8 ++:10A3600082218210884090410505400410040000BD ++:10A3700000000000000000000000000000000000DD ++:10A380000082009000200088000000000000000013 ++:10A390000000000000000000000040820082090070 ++:10A3A0000300000020200800000000000000000062 ++:10A3B00000000000009000000088088200000000FB ++:10A3C000000000000901400000000000030003003D ++:10A3D0001100004000010000000008000091900002 ++:10A3E000001000A00300210800004100000120012E ++:10A3F000000000000000000000000000000000005D ++:10A400000000000000000000000800000000001034 ++:10A4100000000000000000009000000000000000AC ++:10A4200090210011000000000020002100400011D8 ++:10A430000000000000009003200000080103040059 ++:10A4400000000011001190020009001188038840EB ++:10A450000000A0098841001088000008830900203E ++:10A460001000109100000011A0100000004000201A ++:10A4700001080000000000000000000000000000D3 ++:10A4800000000000000000000000000000000000CC ++:10A49000000000000000000000880000000009200B ++:10A4A0000000000000000084000000000000000028 ++:10A4B0000000000041000000000190C0000004A165 ++:10A4C0002040000010C0004000A0850010001003D4 ++:10A4D00000A01010039000A083A0000800088001D5 ++:10A4E0002040408400C0000000A0800000024041E5 ++:10A4F000800002400000000000000000000000009A ++:10A50000000000000000400800000020004100089A ++:10A51000A003000388039011A011900390219011D3 ++:10A520000408041002104002001104080000040591 ++:10A530000421040500000021000900101003C010D0 ++:10A540000210A11004118400024004410221000005 ++:10A550000410400005009000A0400211A0890005F1 ++:10A56000081001001103C003000982080200001056 ++:10A57000C0102008C008000000000000000000001B ++:10A5800000000000000000000000000000000000CB ++:10A5900000000000000000000000000000000000BB ++:10A5A00000000000000011880000000000000020F2 ++:10A5B0000000001000000000000011400282218213 ++:10A5C000091000A0000002000000001000840082BA ++:10A5D000001008100010004000100010410210840C ++:10A5E0000010008400850000000000200084008826 ++:10A5F00000840810008410830000000000000000A8 ++:10A60000000000000000000000000008900088002A ++:10A6100000118840880000000000000000000000D9 ++:10A62000900900000011000000000000000500007B ++:10A630000020000000400000000090000090880012 ++:10A640009003040488098804000000000000000949 ++:10A65000000000000141004000000000044100A093 ++:10A6600090418802A00200200000C0000083820305 ++:10A670000000000003A0041005040000000000001A ++:10A6800000000000000000000000000000000000CA ++:10A6900000000000000000000000000000000000BA ++:10A6A00000000000000000000000000000000000AA ++:10A6B0000000000000000000000000000000830017 ++:10A6C000008083C1000003000041C0890300030033 ++:10A6D000000303410000030080C11000000083005C ++:10A6E0000080834100000300004190848300030048 ++:10A6F000000303410000030080C1200000000000AF ++:10A700000000000000000000000000000000000049 ++:10A710000000000000000000000000000000000039 ++:10A720000000000000000000000000000000000029 ++:10A730000000000000000000000000000000008297 ++:10A74000838200C083410082014088C182C001042D ++:10A750000982000101010090019010C101000082F6 ++:10A76000838200C083C10082012088A183C08382CC ++:10A770000984000101010090019010C10000000057 ++:10A7800000000000000000000000000000000000C9 ++:10A7900000000000000000000000000000000000B9 ++:10A7A00000000000000000000000000000000000A9 ++:10A7B0000000000000000000000000000000000099 ++:10A7C00082009082008300008210A1820082C0205B ++:10A7D000098383820083C1008200038200830120F9 ++:10A7E0008200888200830000821041820082C020A3 ++:10A7F000098385820011C1018200038200830190D8 ++:10A800000000000000000000000000000000000048 ++:10A810000000000000000000000000000000000038 ++:10A820000000000000000000000000000000000028 ++:10A830000000000000000000000000000000000018 ++:10A840000000000000800083000000800280008083 ++:10A850008080908310830083C10040008280008349 ++:10A860004180000000800083000000808280008022 ++:10A870008080908341830083C108400082800083F0 ++:10A880004100000000000000000000000000000087 ++:10A8900000000000000000000000000000000000B8 ++:10A8A00000000000000000000000000000000000A8 ++:10A8B0000000000000000000000000000000000098 ++:10A8C000000000000002000083C1000000000080C2 ++:10A8D000801020C1002100008302000000000080E1 ++:10A8E000830080000002400083C10000000000805F ++:10A8F000801002C1001100008302000000000080EF ++:10A9000083000000000000000000000000000000C4 ++:10A910000000000000000000000000000000000037 ++:10A920000000000000000000000000000000000027 ++:10A930000000000000000000000000000000000017 ++:10A940000000000000000001008283C10000000040 ++:10A95000001082A101C100820082838300000000F8 ++:10A9600000C0828202000001008283C1000000005A ++:10A97000001082C1A0C10082008283830000000019 ++:10A9800000048282000000000000000000000000BF ++:10A9900000000000000000000000000000000000B7 ++:10A9A00000000000000000000000000000000000A7 ++:10A9B0000000000000000000000000000000000097 ++:10A9C00000000000000000008301018201890000F6 ++:10A9D000104000820583C089838201010183000049 ++:10A9E0008282000001018288838901820183000044 ++:10A9F00010200082A083108883820101018300005F ++:10AA0000828200880101C0080000000000000000F0 ++:10AA10000000000000000000000000000000000036 ++:10AA20000000000000000000000000000000000026 ++:10AA30000000000000000000000000000000000016 ++:10AA40000000000000000000000002031080410828 ++:10AA50000000800041804082001002C00403028395 ++:10AA60000000008000000208002002030480410270 ++:10AA7000000080000280C182800302C004030283C0 ++:10AA8000000000800000024100C000000000000043 ++:10AA900000000000000000000000000000000000B6 ++:10AAA00000000000000000000000000000000000A6 ++:10AAB0000000000000000000000000000000000096 ++:10AAC0000000000000000000000000000000000086 ++:10AAD00000001242000000000000124281480013F2 ++:10AAE000C2001242000000000000124200000000FC ++:10AAF00000001242000000000000124281480013D2 ++:10AB0000C20012420000000000001242FFFFFFFFDF ++:10AB1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 ++:10AB2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 ++:10AB3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 ++:10AB4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 ++:10AB5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 ++:10AB6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 ++:10AB7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5 ++:10AB8000FFFFFFFFFFFFFFFFFFFFFFFFFFFF005C77 ++:10AB9000D1510C44C07000E80A0600000881000092 ++:10ABA00000000000000000000000000000000000A5 ++:10ABB0000000000000000000000000000000000095 ++:10ABC0000000000000000000000000000000000085 ++:10ABD0000000000000000000000000000000000075 ++:10ABE000AEDE0000000000000000000000000000D9 ++:10ABF00000000000000000000000000000007B7565 ++:10AC0000AEDE0000000000000000000000000000B8 ++:10AC100000000000000000000000000000007B7544 ++:10AC20000000000000000000000000000000000024 ++:10AC30000000000000000000000000000000000014 ++:10AC40000000000000000000000000000000000004 ++:10AC500000000000000000000000000000000000F4 ++:10AC60000000067BC000000000000000008C070010 ++:10AC700000000000000030000000000000000003A1 ++:10AC8000DE60067BC000000000000000008C0700B2 ++:10AC90000000000000003000000000000000000381 ++:10ACA000DE60000000000000000000000000000066 ++:10ACB0000000040080000400000000010001000109 ++:10ACC00080010000000000002000000000000000E3 ++:10ACD000000000000000000083000000000000A150 ++:10ACE00000000000000000000000000000A00008BC ++:10ACF00000000000A000840020008409000810016A ++:10AD000080000000000000000000000084008400BB ++:10AD10000400800004002100000004002000200046 ++:10AD200020000008000000000000000000000000FB ++:10AD300000000000010020000100000000200020B1 ++:10AD40000020202000000021000000000000000082 ++:10AD500000000000000000000000020000000000F1 ++:10AD600000080000000000000000000000000000DB ++:10AD7000008000000000050005210100108800800F ++:10AD8000014002000000000000100000000021004F ++:10AD9000210001001000000000000000A1000100DF ++:10ADA00001000100000000000000000000000000A1 ++:10ADB0000000000000000000000000000000000093 ++:10ADC0000000000000000000000000000000000083 ++:10ADD00000000000000000000000000000000084EF ++:10ADE00000820090008200C0000000000008000007 ++:10ADF00000000000000000000000000000000082D1 ++:10AE000000000008000000000000000000C000007A ++:10AE100000000000000180000000000000000004AD ++:10AE20000082000000000008000000000000000098 ++:10AE30000000000000000000000000000000000012 ++:10AE40000000000000000000000000000000000002 ++:10AE500000000000000000000000000000000000F2 ++:10AE60000000000000000000000000410000008021 ++:10AE700000000000000000000000000000000008CA ++:10AE800000410000008000000000001000000000F1 ++:10AE9000000000000000000804000021001000086D ++:10AEA0000000000000000000009000000000000012 ++:10AEB000000000000000000000000400000084000A ++:10AEC000000000000000800000000300A00002005D ++:10AED000C100000102000900020000000290090008 ++:10AEE000008840000000040009A00000000009855F ++:10AEF000890840C000908040001000000020102011 ++:10AF000080010001008203414140808400A0831041 ++:10AF10000085000000C000081108000800C002A061 ++:10AF200010400000210003C0000000840000000069 ++:10AF30000000000000000000000000000100000010 ++:10AF400005000000000000002000000000002100BB ++:10AF5000010020000040010000000100000001038A ++:10AF600000050000014100000005824100000008CA ++:10AF70000020108811089041200000030005009077 ++:10AF80000180042000208241A0880080100000057C ++:10AF9000400000209000000000410000C08500003B ++:10AFA000010001A100000041000084000003000036 ++:10AFB0000000000000000000000000000000000091 ++:10AFC0002000200020000000000000000000000021 ++:10AFD000000000000000050000000000000002006A ++:10AFE0004000100000000400020005000200000004 ++:10AFF0000000040041000000800009002000A000C3 ++:10B0000000002100030004009000830080840800F9 ++:10B01000000804004100000110014100000084000C ++:10B020000500000010100200090010000088000058 ++:10B0300000000000000000000000000000004000D0 ++:10B0400000000100050001000000000000000020D9 ++:10B050000010040000000020000000200000000597 ++:10B06000004001040503040000410121002001000B ++:10B0700000000009010088090400204100000100CF ++:10B08000030000000005000201091100040504008E ++:10B090000100008501000000000201080000000816 ++:10B0A000200000210011000300210000000000002A ++:10B0B0000020000000000000000000000000000070 ++:10B0C000000000000000000000000001200000005F ++:10B0D0000001800000000001000980000000020162 ++:10B0E0001000100004A00084008800400000000050 ++:10B0F000004000000084C1840508104000000000EA ++:10B100001110410004000421042004200582008461 ++:10B1100004200902408800A11003901100C0000023 ++:10B120008082008200C0108402A0108441000000D0 ++:10B130000000828400000000000000000000000009 ++:10B1400000000000000000000000000000040100FA ++:10B150000000000420000008C00400041000880063 ++:10B1600001080500000000000000000800000000C9 ++:10B1700000000080004000101000008001800008E6 ++:10B180000021C02100008900C18801808980000061 ++:10B190000000018000100110000801A005400021FE ++:10B1A0000021202104000000C008011088050000D3 ++:10B1B00000109000111000000000000000000000CE ++:10B1C000000000000000400000004000400020009F ++:10B1D000000800002000040000000000000900003A ++:10B1E000000040000000024002081010008202022D ++:10B1F000042020000020000040840584000800A0F6 ++:10B20000002009880088008404020010001004A0B7 ++:10B210000000004011840511090100042008000409 ++:10B22000042004C000080284058420104108090499 ++:10B2300000880090042011200000000000000000A1 ++:10B24000000000000008000200030420902000001D ++:10B250000100040004200120000000000000400460 ++:10B26000040300000000040000000180002004101E ++:10B2700000A1000004410021000001000000008046 ++:10B2800000000000040000000411000000000000A5 ++:10B29000000000000080000082A0002000000004E8 ++:10B2A00000000000000000000010042188030000DE ++:10B2B000000000000000000000000000000000008E ++:10B2C00000000000000000000000838084890591D8 ++:10B2D0000080030380090011000000030009000042 ++:10B2E00000211180000000001000201005114020F6 ++:10B2F00021400800210010000300000020218004EC ++:10B30000032103082040030540410541032000219B ++:10B31000880200082100000040208008C00340206F ++:10B32000911021114100000000000500050000807F ++:10B3300000000300040400092103000000000000D5 ++:10B3400000000000000000000000000089200585CA ++:10B35000008800C0A101108982A000A000010001A6 ++:10B360000000000000822088000801900001010018 ++:10B3700000010000000000000100000000002100AA ++:10B3800004010000010041018400000100000100EF ++:10B39000A002419000910000040001008400A0017F ++:10B3A000000002010100000000000000000001A0F8 ++:10B3B000000800900040A00008010000000000000C ++:10B3C000000000000000000000000000000020005D ++:10B3D00091008800850908000500A00091A1C00027 ++:10B3E00002000200030190001010A10008054000B7 ++:10B3F0008500410009900200A100850041C00000C5 ++:10B400000001010001000082040011214020900091 ++:10B4100008008904000020080101C090C18808C00C ++:10B420000088002100A101090102002100030001A0 ++:10B430000201A00490012002040084C02101030045 ++:10B4400000000000000000000000000000000000FC ++:10B4500080084100800083898005C1000000030945 ++:10B4600011000000000003052140A08085038585B0 ++:10B4700000408800050005000809100088001080C1 ++:10B48000000002201000050000808200A0020811C8 ++:10B49000050303004000400080C01140400010043C ++:10B4A000C0000500030520080340208020C040881C ++:10B4B000114080050080002100C141000200901071 ++:10B4C000200000000000000000000000000000005C ++:10B4D0000000008000800089000300008080800957 ++:10B4E00000030000004100898003000800000808F4 ++:10B4F00000C10340000000C010400008008800A008 ++:10B500000021008010110020000205884040000248 ++:10B5100008C10305024000042009008500402120E5 ++:10B520000040A08220054090058210038002411156 ++:10B530000320801000050021000200404040000070 ++:10B540000589000500000000000000000000000068 ++:10B5500000000000000890208203002100881002F3 ++:10B5600002A100A10000000100A1200100A1829021 ++:10B5700083918803012100840084010900400003B5 ++:10B5800000840090008001080020009100C0018824 ++:10B590000082018588410108C00220210089002025 ++:10B5A0000102008883028890011000211103040029 ++:10B5B00000010101A0010001A0000001A001019112 ++:10B5C0000082008500410000000000000000000033 ++:10B5D00000000000000004102000020008000188A4 ++:10B5E0001100A00090A001890100010100A011112B ++:10B5F0008308910189101020880120000202A021F7 ++:10B600004000820010840080040288108200000044 ++:10B61000010101030000002003101121080020098E ++:10B620008200090084004100039009412140A001EB ++:10B6300000A000000103010085A120008300C004D8 ++:10B64000011100A101000040000000000000000006 ++:10B6500000000000000000008091800080110000C8 ++:10B66000038084001111000003A0410002210000AA ++:10B67000888802089121088080C100400004800071 ++:10B6800000A0001100008080008080808080000089 ++:10B690000000100305C01141208009828510402060 ++:10B6A000830889200520C121100003000490108325 ++:10B6B000110821000909028808009008A000100064 ++:10B6C000208009900940200941000000000000008E ++:10B6D0000000000000000000000000000013C20095 ++:10B6E000820000000013C200820000000000C200BF ++:10B6F000000000000000000000000000000000004A ++:10B700004100000000000000000000008200001363 ++:10B710000000005000000000C20021000081001362 ++:10B72000C20011008200401300000042000000131C ++:10B73000C200000000000081C20000600000008123 ++:10B740000000000000810000C200000000000000B6 ++:10B7500000000000000000000000000000000000E9 ++:10B7600099000000F000000099000000000F0000A8 ++:10B77000F00000003E3E3E7CFFFF7E240000000003 ++:10B78000FF7E99180000000090996F6E0000000085 ++:10B7900000008000000066006600FFFF7F6F3F3FF3 ++:10B7A0003030FE986E0824240000000800000000DD ++:10B7B0000000000000003C3C00BF6F0F6F2F000036 ++:10B7C0000003818181C3FFFF0000BD813C000000B8 ++:10B7D0000000000000000000000000000000000069 ++:10B7E000000099000000F000000099000000000F28 ++:10B7F0000000F0000000024040407E2400000000F5 ++:10B800000000667E001800000000D0DD2F2A000036 ++:10B8100000000000000000006600E680FFFF3F0F10 ++:10B82000FF0FF000FE986E080000400000080000C6 ++:10B8300000000000000000000C0C00EF6E0A6E2AF1 ++:10B8400009000903838183C3001E001EBD813C00E3 ++:10B8500000000000000000000000000000000000E8 ++:10B8600000000000000000000000000000000000D8 ++:10B8700000000000000000000000000000000000C8 ++:10B8800000000000000000000000000000000000B8 ++:10B8900000000000000000000000000000000000A8 ++:10B8A0000000000000000000000000000000000098 ++:10B8B0000000C208040000118861000000000000C0 ++:10B8C0000000000000000000000000000000000078 ++:10B8D0000000000000000000000000000000000068 ++:10B8E0000000000F000F000000000000000F00002B ++:10B8F0000000000000C300000000000000007070A5 ++:10B9000070F09F099F9FFFFFFFFF000000005CA3F6 ++:10B91000CA3500000C042C2CFCFFFCFF800000004A ++:10B9200098181000F0F0F0F03C3C3C3C78787878C7 ++:10B930000000000000000000000000000000000007 ++:10B94000F4F4FCFD000000000000000000FF00FF18 ++:10B9500033660F66000000000000000000000000D9 ++:10B9600000000000000F000F0000F0F00000000FCA ++:10B970000000F0F0000000C300003C3C00000000AC ++:10B98000303030F09F098B8BF6FFFFFF0000000086 ++:10B990005CA3CA35000008082C2CFCFFFCFF8100CA ++:10B9A000000099981810C33C3CC369966996787852 ++:10B9B00078783C3C3C3D00000000000000000000A6 ++:10B9C0000000F4F4F4F50000000000000000F0F0C6 ++:10B9D000FFFFCC66F06600000000000000000000E1 ++:10B9E0000000000000000086C04130A04903C0C72D ++:10B9F000C08030804903C0C7C06030B043030086B8 ++:10BA0000006000B000000086006000B0008000868A ++:10BA1000006000B8000000000086022101B80000AC ++:10BA20000086506000B00005008600940080000091 ++:10BA30000086006101F8040005860A6100B900A0D3 ++:10BA4000A0865061A8B000850086006100B00000AB ++:10BA50000086007400B0000000000000000000003C ++:10BA600000000000000000003C3FAAAF35553555EE ++:10BA7000000000000000000000000000FF00FF00C8 ++:10BA8000FCBD8103CFCF0C0C4341555F01833DBF0B ++:10BA9000FCB800000CAC5CFC0000FF0000000000E3 ++:10BAA000000000000000E7FFDBFFF3F3FF005CFC99 ++:10BAB000ACFC74008B7400FF00FFF3F3FF00CFEFCA ++:10BAC0000F2F0000000000000000000057F70000EA ++:10BAD0000000000000000000000000000000000066 ++:10BAE000000000000000000000003C30AAA0300070 ++:10BAF0003FFF000800080C00000000000000FF00ED ++:10BB0000FF00FFFFC3C3FF00FF00FDBEAAA001832B ++:10BB10003DBFB83000000CAC5CFC0000FF000A0A1E ++:10BB20003050000000000000BDFF7EFF3030FF00FD ++:10BB30005C0CAC0CFF74748B69690F0F3030FF0024 ++:10BB4000CFEF0F2F00000000000000000000F7F70B ++:10BB5000000000000000000001FF00FF00000000E6 ++:10BB6000000000000000000000000000FF000000D6 ++:10BB700000003C3C01000100000002000000000049 ++:10BB8000FFFFFFFF33663333E72424E700000000A4 ++:10BB90003CC3C33C00000000555555550000000053 ++:10BBA00000000000000000000000EEBBFFFFF0AA54 ++:10BBB000F0AA3C3C555500000000F0F0FFFF0000EB ++:10BBC0000000000000000000000000000000000075 ++:10BBD0000800FFFFFFFF0000000000004000000021 ++:10BBE0000000000000000000000000000000FF88CE ++:10BBF00088880F003F3C00000000000002000000A9 ++:10BC000000007FFFFFFF66CC3333DB1818DB00003A ++:10BC10000000A5A5A5A50000000003FCF30C000092 ++:10BC2000000000000000000000000000DD77FFFFC2 ++:10BC3000F03CF03C0F0F0F0F00000000F000FFF091 ++:10BC400000000000000000000000000000000000F4 ++:10BC500000000800EFFF4FFF0000000000000000A0 ++:10BC60000000000000008001000000000000000053 ++:10BC700000000000000000000000000000000000C4 ++:10BC80000020000000000000800000000000000014 ++:10BC90000000000020000000000000000001000083 ++:10BCA00000000090000800000000000020000000DC ++:10BCB0000000210000A000000000000000001100B2 ++:10BCC00000000000000000000400000004A02000AC ++:10BCD00000010000000180000001000000000000E1 ++:10BCE0000000000000000000021000000000000042 ++:10BCF0000000000000000000000000000000000044 ++:10BD000000000080000000000000020000000000B1 ++:10BD1000000000000000010000000000000000081A ++:10BD20000000000000000000000000000000010012 ++:10BD30000000000000000000000000000000000003 ++:10BD400000000000000000000000010000000000F2 ++:10BD500000000008000000081000000800000010AB ++:10BD60004000000000000000000000000000000093 ++:10BD700000000000000000000000000000000000C3 ++:10BD800000000000000000000000000000000000B3 ++:10BD900000000000000000000000000000000000A3 ++:10BDA0000000000000C000000000000000000000D3 ++:10BDB0000000000000000000000000000000000083 ++:10BDC0000000000000000000000000010000000072 ++:10BDD0000000000000000000000000000000000063 ++:10BDE0000000000000000000000000000000000053 ++:10BDF0000000000000000000000000000000000043 ++:10BE00000000000000000000000000000000000032 ++:10BE100000000000000000000021000000210000E0 ++:10BE2000000000000008000000000000000000000A ++:10BE300000030000000000000000001100000000EE ++:10BE400000000000000000210005000000080000C4 ++:10BE5000001100110010000000030000000000109D ++:10BE600000000000001000000000000000000000C2 ++:10BE700000000000000000002000000000000000A2 ++:10BE800003000200000000000000000000000000AD ++:10BE90004100000000848200200000000001020038 ++:10BEA000000000C000820000000000A0008400101C ++:10BEB00000A00000A01002000000000005840000A7 ++:10BEC00000840000000000000000000000A100C08D ++:10BED000040800000000000000080000000000C08E ++:10BEE00000820000001000002000000000000000A0 ++:10BEF0000000000000000000000001000000000041 ++:10BF00000010000001000000001000000000000010 ++:10BF100000000000000000001100010000410004CA ++:10BF20000100000800000040002100000010002176 ++:10BF30000000000000212100010300030000840331 ++:10BF40008400002100030000000800080000000237 ++:10BF500000080180000000080003000082000000CB ++:10BF6000004100000000000000008500000000000B ++:10BF700000000000000000000000000000000000C1 ++:10BF800000000000040000000001000000000300A9 ++:10BF9000030000000000000000000000000000009E ++:10BFA0000000000000000900000000000000000088 ++:10BFB0000000000000000400000009000000000074 ++:10BFC00005001000000000000000000084000000D8 ++:10BFD000000003002000000010000000002000000E ++:10BFE0000000030000000500000000002000000029 ++:10BFF000000000000000000000000000000000023F ++:10C000000000000000000100000000080000000027 ++:10C010000000000000000000000000000000000020 ++:10C020000000000000000000000000000000000010 ++:10C0300000000000000000000000000300000000FD ++:10C0400000000000000000000000000000002100CF ++:10C05000000000000000010000000000000200805D ++:10C0600000000000000000020000000000000100CD ++:10C0700000000000000000000000000000000000C0 ++:10C080000000040080208000040000000400040080 ++:10C0900000A00082002000000010000080010000CD ++:10C0A0000000000000000000000800000000800008 ++:10C0B00000000010000000000000000002A00000CE ++:10C0C000000003000000000000000000000000105D ++:10C0D0000200000000000001000000001008000045 ++:10C0E00041000000000041004100000000C0058246 ++:10C0F0002000000000000000000000000000000020 ++:10C100000000000001100480042101210000011141 ++:10C11000890300000000008000000011002102409F ++:10C1200000000000000300050000000800000040BF ++:10C130001021000000000008004100000011C103B0 ++:10C14000000804210000000588050010C000000060 ++:10C15000C010010384100000C02000210000100066 ++:10C160000000001110000000000000100000C010CE ++:10C17000100001000000000000000000110000009D ++:10C180000000000000000000000000000088000027 ++:10C190000002408200880020009000200010000073 ++:10C1A000042000000008001000000000008210843D ++:10C1B00000080010000000000000040000840010CF ++:10C1C0002008020000080010008400000040110058 ++:10C1D0000000090003840000004000000000008807 ++:10C1E0000084000000104000000041000220008296 ++:10C1F0000004030802A0000000000000000000008E ++:10C20000000000000000000000000000000000002E ++:10C21000000000000000000000800000008000001E ++:10C22000000000000000000000000000000000000E ++:10C2300001000080000000000000840000000000F9 ++:10C2400000000100001000000000000000000000DD ++:10C2500000000000000000000000000000000000DE ++:10C2600000000000000000000000000000000000CE ++:10C27000000000000000010000000000000000803D ++:10C280000000000000008000082189052103004112 ++:10C29000008000800800008000000000880000008E ++:10C2A0000200000020800580001080021020211074 ++:10C2B000000000000000100000000000000000006E ++:10C2C000000000000000000000000000000000006E ++:10C2D00000000000910011000000080000000000B4 ++:10C2E00003000000000000000000114000110010D9 ++:10C2F00010110000000040000000000000000000DD ++:10C30000001000000000000010000101A1009100D9 ++:10C310000000000482849100000200902008059033 ++:10C3200000A00190402000040104000182000101EE ++:10C3300000010000000000000100000000000000FB ++:10C3400000000000000000000000000000000000ED ++:10C3500000000000880091000000000000000000C4 ++:10C3600000000000000000000000000000000000CD ++:10C3700000010100000000000100000001000000B9 ++:10C3800000A000080000000000000000020000A063 ++:10C39000000020C1200084000040008890010800B7 ++:10C3A000200000C0080090001120200001000020A3 ++:10C3B000000000000000000001000000000000007C ++:10C3C00000000000000040001001040040100000C8 ++:10C3D000000000000000000000000000000101005B ++:10C3E00000000082000000000100000001000000C9 ++:10C3F000000000000000000000000000000102003A ++:10C400000000008000080800000000000000910308 ++:10C4100005800021C1898003800000800000001099 ++:10C420000000000000002000000085000500100052 ++:10C43000400002401100000005000500410000001E ++:10C4400000000000000000000005800580008080E2 ++:10C45000000000000000000000000000000000419B ++:10C460001000020003802040400011002100100055 ++:10C470000500210003000000000000000000000390 ++:10C48000000000000000110000000000000000009B ++:10C49000000500830982C041000000000000000088 ++:10C4A0000000000000000000002000C1809100A1F9 ++:10C4B00003A00040000903850003000300080003F7 ++:10C4C000000000000000000000000000000000006C ++:10C4D00000000000000000000000000000001180CB ++:10C4E0008080004100214120000500000000008004 ++:10C4F0000000081000080008050800000000000007 ++:10C50000000000000000000000000000000000002B ++:10C51000000000A0000401038920000890848288A4 ++:10C520000090000820C000900000009084102010AF ++:10C5300000040010000000210103000000000000C2 ++:10C5400000000000000000000000000000000000EB ++:10C5500000000000000000000000000000000000DB ++:10C560000088C082000000000001A001000000005F ++:10C5700000202000000100000000000100400090A9 ++:10C580000082000000000000000000000000000029 ++:10C59000000000009005208300002020202088005B ++:10C5A0004000088808012000900000820020004020 ++:10C5B000000000C0010001010101000000000000B6 ++:10C5C000000000000000000000000000000020004B ++:10C5D0002000A0000020000000000000000000007B ++:10C5E000009000000000002000000001000000009A ++:10C5F000000000000000000000010000000000A09A ++:10C60000000000000000000000000000000000002A ++:10C61000000000000000058280C10303C100008506 ++:10C620000000000000000040000000000080001139 ++:10C630000003000800800900051009202100000007 ++:10C6400000080041000000000000000000000000A1 ++:10C6500080038000000000000000000000000000D7 ++:10C6600000000000000000000000001100020000B7 ++:10C670000000001100000000000000100003000096 ++:10C6800000000000000000000000000000000000AA ++:10C69000000000000000000000000013C200420083 ++:10C6A000000000130000000000000013000000481C ++:10C6B000000000000000000000000000C2000A416D ++:10C6C000000000000000000000000000000000006A ++:10C6D000000000420000C200000000000000000056 ++:10C6E000000011000013C240000012840013C200B9 ++:10C6F00000840000001300000000000000000000A3 ++:10C70000000000600000C2000042000000000000C5 ++:10C710000000000000000000000000000000000019 ++:10C7200000400000000000000000000000000000C9 ++:10C7300000000000000081C0BDFC08FF20FFF000E9 ++:10C74000FC3C000000000F3F3FFF00000000000025 ++:10C7500000000000000000000000000000000000D9 ++:10C7600000000000000000000000000000000000C9 ++:10C7700000FF3FFF0000000000000000000000007C ++:10C78000FFFFFFFF000000000000000000000000AD ++:10C790000000000000000000000000000000101079 ++:10C7A0000000004000000000000000000000000049 ++:10C7B000000000000000000003423F7E0808202027 ++:10C7C00000003C3C00000000000C0C0F00000000CA ++:10C7D0000000000000000000000000000000000059 ++:10C7E0000000000000000000000000000000000049 ++:10C7F000000000283FCF0000000000000000000003 ++:10C8000000007FFFFFFF00000000000000000000AC ++:10C810000000000000000000000000000000000018 ++:10C820000800000000000000000000000000000000 ++:10C83000000000000000000000007D7D2828BEBE32 ++:10C84000BFB0AAAAF0F000000000FFFFFAA00000AD ++:10C8500000000000000000000000000000000000D8 ++:10C8600000000000000000000000000000000000C8 ++:10C8700000000000FFFCFF0A000000000F0014147D ++:10C880003838103828282828000000000000000050 ++:10C890000000000000000000000000000000000098 ++:10C8A0000000080080800000000000000000000080 ++:10C8B0000000000000000000000000007D287D282E ++:10C8C00014141F10EB28F33000000000FAA0000041 ++:10C8D0000000000000000000000000000000000058 ++:10C8E0000000000000000000000000000000000048 ++:10C8F000000000000000FCFC0A0A000000000F001D ++:10C90000141438101010F000F000000000000000B7 ++:10C910000000000000000000000000000000000017 ++:10C920000000008600B108800000008600C1008081 ++:10C93000000000860081008000000086006000B0DA ++:10C9400000000086006008B0000000000000000049 ++:10C95000000000000000000000000000008650649D ++:10C9600008B0000000000000000000000086006128 ++:10C97000A93000050086006509B080850086006149 ++:10C98000003000000000000000000000008600648D ++:10C9900008B08005000000900900000000000000C1 ++:10C9A000010000007DBEFF3C55555555FFFFFFFFC0 ++:10C9B0002000F7FF00500000000000000000000011 ++:10C9C0003C0CDFDF00000000EB82147D0000000063 ++:10C9D00000000000000000000000000000000F0048 ++:10C9E0000F05000000000000000000000000000033 ++:10C9F0000000AAAAFF0000000000000000000000E4 ++:10CA0000000000FF00000000000000000000000027 ++:10CA1000000000A800A80000002000100140000055 ++:10CA20000020000000004182C3005D555155FF5DAC ++:10CA3000FFDF0000FFFF000000000008000800000A ++:10CA400000000C0C7D7D00000000147DEB820000D6 ++:10CA500000000000000000000000000000000000D6 ++:10CA600000000000000000000000000000000000C6 ++:10CA700000000000000000000000000000000000B6 ++:10CA80000000000000FF00000000000000000000A7 ++:10CA90000000000000A800A80040400000020200C2 ++:10CAA0000000000000000200000000006969FFFFB4 ++:10CAB000AAC3AA3CC5C5C5C50000100001000100FD ++:10CAC000D7827D2876C373C30000000000000000F9 ++:10CAD0000000000000000000000000000000000056 ++:10CAE00000000000000015B51FBF0000000000009E ++:10CAF0000000000000000000000000000000000036 ++:10CB00000000000000000000000000000000000025 ++:10CB100000000000000000000000400000000000D5 ++:10CB20000002000000000000000000000000696931 ++:10CB30000000AAFFAA0035353535000010000000BE ++:10CB4000000087D22D78393933330000000000000F ++:10CB500000000000000000000000000000000000D5 ++:10CB6000000000000000000010B01ABA0000000031 ++:10CB700000000000000000000000000000000000B5 ++:10CB800000000000000000000000000000000000A5 ++:10CB90000000000000000000000000000000000095 ++:10CBA0000000000000000000000000000000000085 ++:10CBB0000000000000000000000000000000000075 ++:10CBC0000000000000000000000000000000000065 ++:10CBD0000000000000000000000000000000000055 ++:10CBE0000000000000000000000000000000000045 ++:10CBF0000000000000000000000000000000000035 ++:10CC0000000000000000000000000000000800001C ++:10CC10000000000000000000000041002000FFFFB5 ++:10CC2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14 ++:10CC3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04 ++:10CC4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4 ++:10CC5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4 ++:10CC6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 ++:10CC7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4 ++:10CC8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 ++:10CC9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 ++:10CCA00000D883750C44C08800C00A0600008020AC ++:10CCB0000000000000000000000000000000000074 ++:10CCC0000000000000000000000000000000000064 ++:10CCD0000000000000000000000000000000001044 ++:10CCE0000000000000100010000000000000000024 ++:10CCF0000000000000000000000000000000000034 ++:10CD000000100000000000210010000000000000E2 ++:10CD10000000000000000002000000000000000011 ++:10CD200000110000000000030010000000000000DF ++:10CD300000000000000000000000000000000000F3 ++:10CD400000000000000000000000000000000000E3 ++:10CD500000000000000000000000000000000000D3 ++:10CD6000001000000000000000840000000000002F ++:10CD70000000000000000082000000080000000029 ++:10CD800000000000000000000000000000000000A3 ++:10CD90000000000000000000058200000500000007 ++:10CDA0000000000000000000000000000000000083 ++:10CDB0000000000000000000000000000000000073 ++:10CDC0000021002100000000000000000000000021 ++:10CDD0000000000000210000000000050008000025 ++:10CDE0000000000800000000000800000000000033 ++:10CDF0000000000000000000000300100000000020 ++:10CE00000000000000000000000000100000000012 ++:10CE1000000000000000000000000000000800000A ++:10CE200000000000000000000000000000000005FD ++:10CE3000000800080000FFFFFFFFFFFFFFFFFFFFEC ++:10CE4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 ++:10CE5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 ++:10CE6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 ++:10CE7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 ++:10CE8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 ++:10CE9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 ++:10CEA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 ++:10CEB000FFFFFFFFFFFFFFFF00FCFEC10C44C08827 ++:10CEC00000100A06000080200000000000000000A2 ++:10CED00000000000000000100000000000820000C0 ++:10CEE0000000000000000000000000000000000042 ++:10CEF0000000000000000000000000000000000032 ++:10CF00000000000000000000000000000000000021 ++:10CF10000000000000000000000000000000000011 ++:10CF20000000000000000000000000000000000001 ++:10CF300000000000000000000000000000000000F1 ++:10CF400000000000000000000000004100000000A0 ++:10CF500000000003000000000000000000000000CE ++:10CF600000000000000000000005000000000000BC ++:10CF70000000000000080008000800000005000094 ++:10CF8000000500000000000000000000000000009C ++:10CF90000000000000000008000000210000000068 ++:10CFA0000008000000000000000000210000000058 ++:10CFB0000010000000080000002000000008000829 ++:10CFC0000008000000000000000000000000000059 ++:10CFD0000000000000000000000000000000000051 ++:10CFE0000010001000000000000000000000000021 ++:10CFF0000000000000080000000000000000000029 ++:10D000000000000000000000000000000000000020 ++:10D010000000000000000000000000000000000010 ++:10D0200000000000000200000000040000000400F6 ++:10D0300000000000004000000000000000000000B0 ++:10D040000000000000000000000000000000FFFFE2 ++:10D05000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ++:10D06000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 ++:10D07000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 ++:10D08000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 ++:10D09000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 ++:10D0A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 ++:10D0B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 ++:10D0C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 ++:10D0D00000CC1ECD0C44C08800700A06000000C3BE ++:10D0E0000000000000000000000000000000000040 ++:10D0F000010000000000002000000000000000000F ++:10D10000000000000000000000000000000000001F ++:10D11000000000000000000000000000000000000F ++:10D1200000000000000000000000000000000000FF ++:10D1300000000000000000000000000000000000EF ++:10D1400000000000000000000000000000000000DF ++:10D1500000000000000000000000000000000000CF ++:10D1600000000000000000000000000000000000BF ++:10D1700000000800000000000000000000000000A7 ++:10D18000000000000000000000000000000000009F ++:10D19000000000000000000000000000000000008F ++:10D1A000000000000500000000000000000000007A ++:10D1B000000000000300000000000000000000006C ++:10D1C000000000000000000000000000000000005F ++:10D1D000000000000000000000000000000000004F ++:10D1E00000000000FFFFFFFFFFFFFFFFFFFFFFFF4B ++:10D1F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F ++:10D20000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E ++:10D21000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E ++:10D22000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E ++:10D23000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE ++:10D24000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE ++:10D25000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE ++:10D26000FFFFFFFFFFFF004C448D0C44C08800D837 ++:10D270000A060000E9600000000000000000000055 ++:10D28000000000000000000000200000010000007D ++:10D29000000000000000000000000000000000008E ++:10D2A000000000000000000000000000000000007E ++:10D2B000000000000000000000000020000000004E ++:10D2C000000000000000000000000020000000003E ++:10D2D000000000000000000000000000000000004E ++:10D2E000000000000000000000000000000000003E ++:10D2F000000000000000000000000000000000002E ++:10D3000000000000000000000040000000000200DB ++:10D31000000000000000000000000000000000000D ++:10D3200000000000000000000000000000000000FD ++:10D3300000000000000000000000000000000000ED ++:10D3400002000000000000000000000000000000DB ++:10D3500002000000000000000000000000000000CB ++:10D3600000000000000000000000000000000000BD ++:10D3700000000000000000000000000000000000AD ++:10D380000000000000000000000000000000090094 ++:10D39000000000000000000000000000000000008D ++:10D3A000000000000000000000000000000000007D ++:10D3B000000000000000000000000000000000006D ++:10D3C000010000000000000000000000000000005C ++:10D3D000010000000000000000000000000000004C ++:10D3E000000000000000000000000000000000003D ++:10D3F000000000000000000000000000FFFFFFFF31 ++:10D40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C ++:10D41000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C ++:10D42000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C ++:10D43000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC ++:10D44000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC ++:10D45000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC ++:10D46000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC ++:10D47000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC ++:10D48000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC ++:10D49000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C ++:10D4A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C ++:10D4B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C ++:10D4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:10D4D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:10D4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:10D4F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:10D50000000000000000000000000000000000001B ++:10D51000000000000000000000000000000000000B ++:10D5200000000000000000000000000000000000FB ++:10D5300000000000000000000000000000000000EB ++:10D5400000000000000000000000000000000000DB ++:10D5500000000000000000000000000000000000CB ++:10D5600000000000000000000000000000000000BB ++:10D5700000000000000000000000000000000000AB ++:10D58000000000000000000000000000000000009B ++:10D59000000000000000000000000000000000008B ++:10D5A000000000000000000000000000000000007B ++:10D5B000000000000000000000000000000000006B ++:10D5C000000000000000000000000000000000005B ++:10D5D000000000000000000000000000000000004B ++:10D5E000000000000000000000000000000000003B ++:10D5F000000000000000000000000000000000002B ++:10D60000000000000000000000000000000000001A ++:10D61000000000000000000000000000000000000A ++:10D6200000000000000000000000000000000000FA ++:10D6300000000000000000000000000000000000EA ++:10D6400000000000000000000000000000000000DA ++:10D6500000000000000000000000000000000000CA ++:10D6600000000000000000000000000000000000BA ++:10D6700000000000000000000000000000000000AA ++:10D68000000000000000000000000000000000009A ++:10D69000000000000000000000000000000000008A ++:10D6A000000000000000000000000000000000007A ++:10D6B000000000000000000000000000000000006A ++:10D6C000000000000000000000000000000000005A ++:10D6D000000000000000000000000000000000004A ++:10D6E000000000000000000000000000000000003A ++:10D6F000000000000000000000000000000000002A ++:10D700000000000000000000000000000000000019 ++:10D710000000000000000000000000000000000009 ++:10D7200000000000000000000000000000000000F9 ++:10D7300000000000000000000000000000000000E9 ++:10D7400000000000000000000000000000000000D9 ++:10D7500000000000000000000000000000000000C9 ++:10D7600000000000000000000000000000000000B9 ++:10D7700000000000000000000000000000000000A9 ++:10D780000000000000000000000000000000000099 ++:10D790000000000000000000000000000000000089 ++:10D7A0000000000000000000000000000000000079 ++:10D7B0000000000000000000000000000000000069 ++:10D7C0000000000000000000000000000000000059 ++:10D7D0000000000000000000000000000000000049 ++:10D7E0000000000000000000000000000000000039 ++:10D7F0000000000000000000000000000000000029 ++:10D800000000000000000000000000000000000018 ++:10D810000000000000000000000000000000000008 ++:10D8200000000000000000000000000000000000F8 ++:10D8300000000000000000000000000000000000E8 ++:10D8400000000000000000000000000000000000D8 ++:10D8500000000000000000000000000000000000C8 ++:10D8600000000000000000000000000000000000B8 ++:10D8700000000000000000000000000000000000A8 ++:10D880000000000000000000000000000000000098 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000000000000078 ++:10D8B0000000000000000000000000000000000068 ++:10D8C0000000000000000000000000000000000058 ++:10D8D0000000000000000000000000000000000048 ++:10D8E0000000000000000000000000000000000038 ++:10D8F0000000000000000000000000000000000028 ++:10D900000000000000000000000000000000000017 ++:10D910000000000000000000000000000000000007 ++:10D9200000000000000000000000000000000000F7 ++:10D9300000000000000000000000000000000000E7 ++:10D9400000000000000000000000000000000000D7 ++:10D9500000000000000000000000000000000000C7 ++:10D9600000000000000000000000000000000000B7 ++:10D9700000000000000000000000000000000000A7 ++:10D980000000000000000000000000000000000097 ++:10D990000000000000000000000000000000000087 ++:10D9A0000000000000000000000000000000000077 ++:10D9B0000000000000000000000000000000000067 ++:10D9C0000000000000000000000000000000000057 ++:10D9D0000000000000000000000000000000000047 ++:10D9E0000000000000000000000000000000000037 ++:10D9F0000000000000000000000000000000000027 ++:10DA00000000000000000000000000000000000016 ++:10DA10000000000000000000000000000000000006 ++:10DA200000000000000000000000000000000000F6 ++:10DA300000000000000000000000000000000000E6 ++:10DA400000000000000000000000000000000000D6 ++:10DA500000000000000000000000000000000000C6 ++:10DA600000000000000000000000000000000000B6 ++:10DA700000000000000000000000000000000000A6 ++:10DA80000000000000000000000000000000000096 ++:10DA90000000000000000000000000000000000086 ++:10DAA0000000000000000000000000000000000076 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000000000000000000000000000000056 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000000000000000000000000000000000015 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000000000F5 ++:10DB300000000000000000000000000000000000E5 ++:10DB400000000000000000000000000000000000D5 ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB700000000000000000000000000000000000A5 ++:10DB80000000000000000000000000000000000095 ++:10DB90000000000000000000000000000000000085 ++:10DBA0000000000000000000000000000000000075 ++:10DBB0000000000000000000000000000000000065 ++:10DBC0000000000000000000000000000000000055 ++:10DBD0000000000000000000000000000000000045 ++:10DBE0000000000000000000000000000000000035 ++:10DBF0000000000000000000000000000000000025 ++:10DC00000000000000000000000000000000000014 ++:10DC10000000000000000000000000000000000004 ++:10DC200000000000000000000000000000000000F4 ++:10DC300000000000000000000000000000000000E4 ++:10DC400000000000000000000000000000000000D4 ++:10DC500000000000000000000000000000000000C4 ++:10DC600000000000000000000000000000000000B4 ++:10DC700000000000000000000000000000000000A4 ++:10DC80000000000000000000000000000000000094 ++:10DC90000000000000000000000000000000000084 ++:10DCA0000000000000000000000000000000000074 ++:10DCB0000000000000000000000000000000000064 ++:10DCC0000000000000000000000000000000000054 ++:10DCD0000000000000000000000000000000000044 ++:10DCE0000000000000000000000000000000000034 ++:10DCF0000000000000000000000000000000000024 ++:10DD00000000000000000000000000000000000013 ++:10DD10000000000000000000000000000000000003 ++:10DD200000000000000000000000000000000000F3 ++:10DD300000000000000000000000000000000000E3 ++:10DD400000000000000000000000000000000000D3 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000000000000000B3 ++:10DD700000000000000000000000000000000000A3 ++:10DD80000000000000000000000000000000000093 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000000000073 ++:10DDB0000000000000000000000000000000000063 ++:10DDC0000000000000000000000000000000000053 ++:10DDD0000000000000000000000000000000000043 ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000000000000000000000000012 ++:10DE10000000000000000000000000000000000002 ++:10DE200000000000000000000000000000000000F2 ++:10DE300000000000000000000000000000000000E2 ++:10DE400000000000000000000000000000000000D2 ++:10DE500000000000000000000000000000000000C2 ++:10DE600000000000000000000000000000000000B2 ++:10DE700000000000000000000000000000000000A2 ++:10DE80000000000000000000000000000000000092 ++:10DE90000000000000000000000000000000000082 ++:10DEA0000000000000000000000000000000000072 ++:10DEB0000000000000000000000000000000000062 ++:10DEC0000000000000000000000000000000000052 ++:10DED0000000000000000000000000000000000042 ++:10DEE0000000000000000000000000000000000032 ++:10DEF0000000000000000000000000000000000022 ++:10DF00000000000000000000000000000000000011 ++:10DF10000000000000000000000000000000000001 ++:10DF200000000000000000000000000000000000F1 ++:10DF300000000000000000000000000000000000E1 ++:10DF400000000000000000000000000000000000D1 ++:10DF500000000000000000000000000000000000C1 ++:10DF600000000000000000000000000000000000B1 ++:10DF700000000000000000000000000000000000A1 ++:10DF80000000000000000000000000000000000091 ++:10DF90000000000000000000000000000000000081 ++:10DFA0000000000000000000000000000000000071 ++:10DFB0000000000000000000000000000000000061 ++:10DFC0000000000000000000000000000000000051 ++:10DFD0000000000000000000000000000000000041 ++:10DFE0000000000000000000000000000000000031 ++:10DFF0000000000000000000000000000000000021 ++:10E000000000000000000000000000000000000010 ++:10E010000000000000000000000000000000000000 ++:10E0200000000000000000000000000000000000F0 ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E0500000000000000000000000000000000000C0 ++:10E0600000000000000000000000000000000000B0 ++:10E0700000000000000000000000000000000000A0 ++:10E080000000000000000000000000000000000090 ++:10E090000000000000000000000000000000000080 ++:10E0A0000000000000000000000000000000000070 ++:10E0B0000000000000000000000000000000000060 ++:10E0C0000000000000000000000000000000000050 ++:10E0D0000000000000000000000000000000000040 ++:10E0E0000000000000000000000000000000000030 ++:10E0F0000000000000000000000000000000000020 ++:10E10000000000000000000000000000000000000F ++:10E1100000000000000000000000000000000000FF ++:10E1200000000000000000000000000000000000EF ++:10E1300000000000000000000000000000000000DF ++:10E1400000000000000000000000000000000000CF ++:10E1500000000000000000000000000000000000BF ++:10E1600000000000000000000000000000000000AF ++:10E17000000000000000000000000000000000009F ++:10E18000000000000000000000000000000000008F ++:10E19000000000000000000000000000000000007F ++:10E1A000000000000000000000000000000000006F ++:10E1B000000000000000000000000000000000005F ++:10E1C000000000000000000000000000000000004F ++:10E1D000000000000000000000000000000000003F ++:10E1E000000000000000000000000000000000002F ++:10E1F000000000000000000000000000000000001F ++:10E20000000000000000000000000000000000000E ++:10E2100000000000000000000000000000000000FE ++:10E2200000000000000000000000000000000000EE ++:10E2300000000000000000000000000000000000DE ++:10E2400000000000000000000000000000000000CE ++:10E2500000000000000000000000000000000000BE ++:10E2600000000000000000000000000000000000AE ++:10E27000000000000000000000000000000000009E ++:10E28000000000000000000000000000000000008E ++:10E29000000000000000000000000000000000007E ++:10E2A000000000000000000000000000000000006E ++:10E2B000000000000000000000000000000000005E ++:10E2C000000000000000000000000000000000004E ++:10E2D000000000000000000000000000000000003E ++:10E2E000000000000000000000000000000000002E ++:10E2F000000000000000000000000000000000001E ++:10E30000000000000000000000000000000000000D ++:10E3100000000000000000000000000000000000FD ++:10E3200000000000000000000000000000000000ED ++:10E3300000000000000000000000000000000000DD ++:10E3400000000000000000000000000000000000CD ++:10E3500000000000000000000000000000000000BD ++:10E3600000000000000000000000000000000000AD ++:10E37000000000000000000000000000000000009D ++:10E38000000000000000000000000000000000008D ++:10E39000000000000000000000000000000000007D ++:10E3A000000000000000000000000000000000006D ++:10E3B000000000000000000000000000000000005D ++:10E3C000000000000000000000000000000000004D ++:10E3D000000000000000000000000000000000003D ++:10E3E000000000000000000000000000000000002D ++:10E3F000000000000000000000000000000000001D ++:10E40000000000000000000000000000000000000C ++:10E4100000000000000000000000000000000000FC ++:10E4200000000000000000000000000000000000EC ++:10E4300000000000000000000000000000000000DC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000000000000000000000000000000000009C ++:10E48000000000000000000000000000000000008C ++:10E49000000000000000000000000000000000007C ++:10E4A000000000000000000000000000000000006C ++:10E4B000000000000000000000000000000000005C ++:10E4C000000000000000000000000000000000004C ++:10E4D000000000000000000000000000000000003C ++:10E4E000000000000000000000000000000000002C ++:10E4F000000000000000000000000000000000001C ++:10E50000000000000000000000000000000000000B ++:10E5100000000000000000000000000000000000FB ++:10E5200000000000000000000000000000000000EB ++:10E5300000000000000000000000000000000000DB ++:10E5400000000000000000000000000000000000CB ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000000000000000008B ++:10E59000000000000000000000000000000000007B ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000000000000000000000000000000000001B ++:10E60000000000000000000000000000000000000A ++:10E6100000000000000000000000000000000000FA ++:10E6200000000000000000000000000000000000EA ++:10E6300000000000000000000000000000000000DA ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E6600000000000000000000000000000000000AA ++:10E67000000000000000000000000000000000009A ++:10E68000000000000000000000000000000000008A ++:10E69000000000000000000000000000000000007A ++:10E6A000000000000000000000000000000000006A ++:10E6B000000000000000000000000000000000005A ++:10E6C000000000000000000000000000000000004A ++:10E6D000000000000000000000000000000000003A ++:10E6E000000000000000000000000000000000002A ++:10E6F000000000000000000000000000000000001A ++:10E700000000000000000000000000000000000009 ++:10E7100000000000000000000000000000000000F9 ++:10E7200000000000000000000000000000000000E9 ++:10E7300000000000000000000000000000000000D9 ++:10E7400000000000000000000000000000000000C9 ++:10E7500000000000000000000000000000000000B9 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000000000000099 ++:10E780000000000000000000000000000000000089 ++:10E790000000000000000000000000000000000079 ++:10E7A0000000000000000000000000000000000069 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000000039 ++:10E7E0000000000000000000000000000000000029 ++:10E7F0000000000000000000000000000000000019 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000000000000000000000000000F8 ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000000000000000000000000000000D8 ++:10E8400000000000000000000000000000000000C8 ++:10E8500000000000000000000000000000000000B8 ++:10E8600000000000000000000000000000000000A8 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000000000000000000018 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000000000000000000000000000000D7 ++:10E9400000000000000000000000000000000000C7 ++:10E9500000000000000000000000000000000000B7 ++:10E9600000000000000000000000000000000000A7 ++:10E970000000000000000000000000000000000097 ++:10E980000000000000000000000000000000000087 ++:10E990000000000000000000000000000000000077 ++:10E9A0000000000000000000000000000000000067 ++:10E9B0000000000000000000000000000000000057 ++:10E9C0000000000000000000000000000000000047 ++:10E9D0000000000000000000000000000000000037 ++:10E9E0000000000000000000000000000000000027 ++:10E9F0000000000000000000000000000000000017 ++:10EA00000000000000000000000000000000000006 ++:10EA100000000000000000000000000000000000F6 ++:10EA200000000000000000000000000000000000E6 ++:10EA300000000000000000000000000000000000D6 ++:10EA400000000000000000000000000000000000C6 ++:10EA500000000000000000000000000000000000B6 ++:10EA600000000000000000000000000000000000A6 ++:10EA70000000000000000000000000000000000096 ++:10EA80000000000000000000000000000000000086 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000000000000000056 ++:10EAC0000000000000000000000000000000000046 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB300000000000000000000000000000000000D5 ++:10EB400000000000000000000000000000000000C5 ++:10EB500000000000000000000000000000000000B5 ++:10EB600000000000000000000000000000000000A5 ++:10EB70000000000000000000000000000000000095 ++:10EB80000000000000000000000000000000000085 ++:10EB90000000000000000000000000000000000075 ++:10EBA0000000000000000000000000000000000065 ++:10EBB0000000000000000000000000000000000055 ++:10EBC0000000000000000000000000000000000045 ++:10EBD0000000000000000000000000000000000035 ++:10EBE0000000000000000000000000000000000025 ++:10EBF0000000000000000000000000000000000015 ++:10EC00000000000000000000000000000000000004 ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC80000000000000000000000000000000000084 ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000000000000000000000000000000064 ++:10ECB0000000000000000000000000000000000054 ++:10ECC0000000000000000000000000000000000044 ++:10ECD0000000000000000000000000000000000034 ++:10ECE0000000000000000000000000000000000024 ++:10ECF0000000000000000000000000000000000014 ++:10ED00000000000000000000000000000000000003 ++:10ED100000000000000000000000000000000000F3 ++:10ED200000000000000000000000000000000000E3 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA0000000000000000000000000000000000063 ++:10EDB0000000000000000000000000000000000053 ++:10EDC0000000000000000000000000000000000043 ++:10EDD0000000000000000000000000000000000033 ++:10EDE0000000000000000000000000000000000023 ++:10EDF0000000000000000000000000000000000013 ++:10EE00000000000000000000000000000000000002 ++:10EE100000000000000000000000000000000000F2 ++:10EE200000000000000000000000000000000000E2 ++:10EE300000000000000000000000000000000000D2 ++:10EE400000000000000000000000000000000000C2 ++:10EE500000000000000000000000000000000000B2 ++:10EE600000000000000000000000000000000000A2 ++:10EE70000000000000000000000000000000000092 ++:10EE80000000000000000000000000000000000082 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000000000022 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000000000000000000000000000000001 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF600000000000000000000000000000000000A1 ++:10EF70000000000000000000000000000000000091 ++:10EF80000000000000000000000000000000000081 ++:10EF90000000000000000000000000000000000071 ++:10EFA0000000000000000000000000000000000061 ++:10EFB0000000000000000000000000000000000051 ++:10EFC0000000000000000000000000000000000041 ++:10EFD0000000000000000000000000000000000031 ++:10EFE0000000000000000000000000000000000021 ++:10EFF0000000000000000000000000000000000011 ++:10F000000000000000000000000000000000000000 ++:10F0100000000000000000000000000000000000F0 ++:10F0200000000000000000000000000000000000E0 ++:10F0300000000000000000000000000000000000D0 ++:10F0400000000000000000000000000000000000C0 ++:10F0500000000000000000000000000000000000B0 ++:10F0600000000000000000000000000000000000A0 ++:10F070000000000000000000000000000000000090 ++:10F080000000000000000000000000000000000080 ++:10F090000000000000000000000000000000000070 ++:10F0A0000000000000000000000000000000000060 ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D0000000000000000000000000000000000030 ++:10F0E0000000000000000000000000000000000020 ++:10F0F0000000000000000000000000000000000010 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000000AF ++:10F16000000000000000000000000000000000009F ++:10F17000000000000000000000000000000000008F ++:10F18000000000000000000000000000000000007F ++:10F19000000000000000000000000000000000006F ++:10F1A000000000000000000000000000000000005F ++:10F1B000000000000000000000000000000000004F ++:10F1C000000000000000000000000000000000003F ++:10F1D000000000000000000000000000000000002F ++:10F1E000000000000000000000000000000000001F ++:10F1F000000000000000000000000000000000000F ++:10F2000000000000000000000000000000000000FE ++:10F2100000000000000000000000000000000000EE ++:10F2200000000000000000000000000000000000DE ++:10F2300000000000000000000000000000000000CE ++:10F2400000000000000000000000000000000000BE ++:10F2500000000000000000000000000000000000AE ++:10F26000000000000000000000000000000000009E ++:10F27000000000000000000000000000000000008E ++:10F28000000000000000000000000000000000007E ++:10F29000000000000000000000000000000000006E ++:10F2A000000000000000000000000000000000005E ++:10F2B000000000000000000000000000000000004E ++:10F2C000000000000000000000000000000000003E ++:10F2D000000000000000000000000000000000002E ++:10F2E000000000000000000000000000000000001E ++:10F2F000000000000000000000000000000000000E ++:10F3000000000000000000000000000000000000FD ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000000000000CD ++:10F3400000000000000000000000000000000000BD ++:10F3500000000000000000000000000000000000AD ++:10F36000000000000000000000000000000000009D ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000000000004D ++:10F3C000000000000000000000000000000000003D ++:10F3D000000000000000000000000000000000002D ++:10F3E000000000000000000000000000000000001D ++:10F3F000000000000000000000000000000000000D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F4400000000000000000000000000000000000BC ++:10F4500000000000000000000000000000000000AC ++:10F46000000000000000000000000000000000009C ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000000000000000003C ++:10F4D000000000000000000000000000000000002C ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000000000000000EB ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000000000000000000000000000007B ++:10F59000000000000000000000000000000000006B ++:10F5A000000000000000000000000000000000005B ++:10F5B000000000000000000000000000000000004B ++:10F5C000000000000000000000000000000000003B ++:10F5D000000000000000000000000000000000002B ++:10F5E000000000000000000000000000000000001B ++:10F5F000000000000000000000000000000000000B ++:10F6000000000000000000000000000000000000FA ++:10F6100000000000000000000000000000000000EA ++:10F6200000000000000000000000000000000000DA ++:10F6300000000000000000000000000000000000CA ++:10F6400000000000000000000000000000000000BA ++:10F6500000000000000000000000000000000000AA ++:10F66000000000000000000000000000000000009A ++:10F67000000000000000000000000000000000008A ++:10F68000000000000000000000000000000000007A ++:10F69000000000000000000000000000000000006A ++:10F6A000000000000000000000000000000000005A ++:10F6B000000000000000000000000000000000004A ++:10F6C000000000000000000000000000000000003A ++:10F6D000000000000000000000000000000000002A ++:10F6E000000000000000000000000000000000001A ++:10F6F000000000000000000000000000000000000A ++:10F7000000000000000000000000000000000000F9 ++:10F7100000000000000000000000000000000000E9 ++:10F7200000000000000000000000000000000000D9 ++:10F7300000000000000000000000000000000000C9 ++:10F7400000000000000000000000000000000000B9 ++:10F7500000000000000000000000000000000000A9 ++:10F760000000000000000000000000000000000099 ++:10F770000000000000000000000000000000000089 ++:10F780000000000000000000000000000000000079 ++:10F790000000000000000000000000000000000069 ++:10F7A0000000000000000000000000000000000059 ++:10F7B0000000000000000000000000000000000049 ++:10F7C0000000000000000000000000000000000039 ++:10F7D0000000000000000000000000000000000029 ++:10F7E0000000000000000000000000000000000019 ++:10F7F0000000000000000000000000000000000009 ++:10F8000000000000000000000000000000000000F8 ++:10F8100000000000000000000000000000000000E8 ++:10F8200000000000000000000000000000000000D8 ++:10F8300000000000000000000000000000000000C8 ++:10F8400000000000000000000000000000000000B8 ++:10F8500000000000000000000000000000000000A8 ++:10F860000000000000000000000000000000000098 ++:10F870000000000000000000000000000000000088 ++:10F880000000000000000000000000000000000078 ++:10F890000000000000000000000000000000000068 ++:10F8A0000000000000000000000000000000000058 ++:10F8B0000000000000000000000000000000000048 ++:10F8C0000000000000000000000000000000000038 ++:10F8D0000000000000000000000000000000000028 ++:10F8E0000000000000000000000000000000000018 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000000000000000F7 ++:10F9100000000000000000000000000000000000E7 ++:10F9200000000000000000000000000000000000D7 ++:10F9300000000000000000000000000000000000C7 ++:10F9400000000000000000000000000000000000B7 ++:10F9500000000000000000000000000000000000A7 ++:10F960000000000000000000000000000000000097 ++:10F970000000000000000000000000000000000087 ++:10F980000000000000000000000000000000000077 ++:10F990000000000000000000000000000000000067 ++:10F9A0000000000000000000000000000000000057 ++:10F9B0000000000000000000000000000000000047 ++:10F9C0000000000000000000000000000000000037 ++:10F9D0000000000000000000000000000000000027 ++:10F9E0000000000000000000000000000000000017 ++:10F9F0000000000000000000000000000000000007 ++:10FA000000000000000000000000000000000000F6 ++:10FA100000000000000000000000000000000000E6 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000000000000000000C6 ++:10FA400000000000000000000000000000000000B6 ++:10FA500000000000000000000000000000000000A6 ++:10FA60000000000000000000000000000000000096 ++:10FA70000000000000000000000000000000000086 ++:10FA80000000000000000000000000000000000076 ++:10FA90000000000000000000000000000000000066 ++:10FAA0000000000000000000000000000000000056 ++:10FAB0000000000000000000000000000000000046 ++:10FAC0000000000000000000000000000000000036 ++:10FAD0000000000000000000000000000000000026 ++:10FAE0000000000000000000000000000000000016 ++:10FAF0000000000000000000000000000000000006 ++:10FB000000000000000000000000000000000000F5 ++:10FB100000000000000000000000000000000000E5 ++:10FB200000000000000000000000000000000000D5 ++:10FB300000000000000000000000000000000000C5 ++:10FB400000000000000000000000000000000000B5 ++:10FB500000000000000000000000000000000000A5 ++:10FB60000000000000000000000000000000000095 ++:10FB70000000000000000000000000000000000085 ++:10FB80000000000000000000000000000000000075 ++:10FB90000000000000000000000000000000000065 ++:10FBA0000000000000000000000000000000000055 ++:10FBB0000000000000000000000000000000000045 ++:10FBC0000000000000000000000000000000000035 ++:10FBD0000000000000000000000000000000000025 ++:10FBE0000000000000000000000000000000000015 ++:10FBF0000000000000000000000000000000000005 ++:10FC000000000000000000000000000000000000F4 ++:10FC100000000000000000000000000000000000E4 ++:10FC200000000000000000000000000000000000D4 ++:10FC300000000000000000000000000000000000C4 ++:10FC400000000000000000000000000000000000B4 ++:10FC500000000000000000000000000000000000A4 ++:10FC60000000000000000000000000000000000094 ++:10FC70000000000000000000000000000000000084 ++:10FC80000000000000000000000000000000000074 ++:10FC90000000000000000000000000000000000064 ++:10FCA0000000000000000000000000000000000054 ++:10FCB0000000000000000000000000000000000044 ++:10FCC0000000000000000000000000000000000034 ++:10FCD0000000000000000000000000000000000024 ++:10FCE0000000000000000000000000000000000014 ++:10FCF0000000000000000000000000000000000004 ++:10FD000000000000000000000000000000000000F3 ++:10FD100000000000000000000000000000000000E3 ++:10FD200000000000000000000000000000000000D3 ++:10FD300000000000000000000000000000000000C3 ++:10FD400000000000000000000000000000000000B3 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000000000000000000000000000000000093 ++:10FD70000000000000000000000000000000000083 ++:10FD80000000000000000000000000000000000073 ++:10FD90000000000000000000000000000000000063 ++:10FDA0000000000000000000000000000000000053 ++:10FDB0000000000000000000000000000000000043 ++:10FDC0000000000000000000000000000000000033 ++:10FDD0000000000000000000000000000000000023 ++:10FDE0000000000000000000000000000000000013 ++:10FDF0000000000000000000000000000000000003 ++:10FE000000000000000000000000000000000000F2 ++:10FE100000000000000000000000000000000000E2 ++:10FE200000000000000000000000000000000000D2 ++:10FE300000000000000000000000000000000000C2 ++:10FE400000000000000000000000000000000000B2 ++:10FE500000000000000000000000000000000000A2 ++:10FE60000000000000000000000000000000000092 ++:10FE70000000000000000000000000000000000082 ++:10FE80000000000000000000000000000000000072 ++:10FE90000000000000000000000000000000000062 ++:10FEA0000000000000000000000000000000000052 ++:10FEB0000000000000000000000000000000000042 ++:10FEC0000000000000000000000000000000000032 ++:10FED0000000000000000000000000000000000022 ++:10FEE0000000000000000000000000000000000012 ++:10FEF0000000000000000000000000000000000002 ++:10FF000000000000000000000000000000000000F1 ++:10FF100000000000000000000000000000000000E1 ++:10FF200000000000000000000000000000000000D1 ++:10FF300000000000000000000000000000000000C1 ++:10FF400000000000000000000000000000000000B1 ++:10FF500000000000000000000000000000000000A1 ++:10FF60000000000000000000000000000000000091 ++:10FF70000000000000000000000000000000000081 ++:10FF80000000000000000000000000000000000071 ++:10FF90000000000000000000000000000000000061 ++:10FFA0000000000000000000000000000000000051 ++:10FFB0000000000000000000000000000000000041 ++:10FFC0000000000000000000000000000000000031 ++:10FFD0000000000000000000000000000000000021 ++:10FFE0000000000000000000000000000000000011 ++:10FFF0000000000000000000000000000000000001 ++:020000040004F6 ++:1000000000000000000000000000000000000000F0 ++:1000100000000000000000000000000000000000E0 ++:1000200000000000000000000000000000000000D0 ++:1000300000000000000000000000000000000000C0 ++:1000400000000000000000000000000000000000B0 ++:1000500000000000000000000000000000000000A0 ++:100060000000000000000000000000000000000090 ++:100070000000000000000000000000000000000080 ++:100080000000000000000000000000000000000070 ++:100090000000000000000000000000000000000060 ++:1000A0000000000000000000000000000000000050 ++:1000B0000000000000000000000000000000000040 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000000000000000000000000000020 ++:1000E0000000000000000000000000000000000010 ++:1000F0000000000000000000000000000000000000 ++:1001000000000000000000000000000000000000EF ++:1001100000000000000000000000000000000000DF ++:1001200000000000000000000000000000000000CF ++:1001300000000000000000000000000000000000BF ++:1001400000000000000000000000000000000000AF ++:10015000000000000000000000000000000000009F ++:10016000000000000000000000000000000000008F ++:10017000000000000000000000000000000000007F ++:10018000000000000000000000000000000000006F ++:10019000000000000000000000000000000000005F ++:1001A000000000000000000000000000000000004F ++:1001B000000000000000000000000000000000003F ++:1001C000000000000000000000000000000000002F ++:1001D000000000000000000000000000000000001F ++:1001E000000000000000000000000000000000000F ++:1001F00000000000000000000000000000000000FF ++:1002000000000000000000000000000000000000EE ++:1002100000000000000000000000000000000000DE ++:1002200000000000000000000000000000000000CE ++:1002300000000000000000000000000000000000BE ++:1002400000000000000000000000000000000000AE ++:10025000000000000000000000000000000000009E ++:10026000000000000000000000000000000000008E ++:10027000000000000000000000000000000000007E ++:10028000000000000000000000000000000000006E ++:10029000000000000000000000000000000000005E ++:1002A000000000000000000000000000000000004E ++:1002B000000000000000000000000000000000003E ++:1002C000000000000000000000000000000000002E ++:1002D000000000000000000000000000000000001E ++:1002E000000000000000000000000000000000000E ++:1002F00000000000000000000000000000000000FE ++:1003000000000000000000000000000000000000ED ++:1003100000000000000000000000000000000000DD ++:1003200000000000000000000000000000000000CD ++:1003300000000000000000000000000000000000BD ++:1003400000000000000000000000000000000000AD ++:10035000000000000000000000000000000000009D ++:10036000000000000000000000000000000000008D ++:10037000000000000000000000000000000000007D ++:10038000000000000000000000000000000000006D ++:10039000000000000000000000000000000000005D ++:1003A000000000000000000000000000000000004D ++:1003B000000000000000000000000000000000003D ++:1003C000000000000000000000000000000000002D ++:1003D000000000000000000000000000000000001D ++:1003E000000000000000000000000000000000000D ++:1003F00000000000000000000000000000000000FD ++:1004000000000000000000000000000000000000EC ++:1004100000000000000000000000000000000000DC ++:1004200000000000000000000000000000000000CC ++:1004300000000000000000000000000000000000BC ++:1004400000000000000000000000000000000000AC ++:10045000000000000000000000000000000000009C ++:10046000000000000000000000000000000000008C ++:10047000000000000000000000000000000000007C ++:10048000000000000000000000000000000000006C ++:10049000000000000000000000000000000000005C ++:1004A000000000000000000000000000000000004C ++:1004B000000000000000000000000000000000003C ++:1004C000000000000000000000000000000000002C ++:1004D000000000000000000000000000000000001C ++:1004E000000000000000000000000000000000000C ++:1004F00000000000000000000000000000000000FC ++:1005000000000000000000000000000000000000EB ++:1005100000000000000000000000000000000000DB ++:1005200000000000000000000000000000000000CB ++:1005300000000000000000000000000000000000BB ++:1005400000000000000000000000000000000000AB ++:10055000000000000000000000000000000000009B ++:10056000000000000000000000000000000000008B ++:10057000000000000000000000000000000000007B ++:10058000000000000000000000000000000000006B ++:10059000000000000000000000000000000000005B ++:1005A000000000000000000000000000000000004B ++:1005B000000000000000000000000000000000003B ++:1005C000000000000000000000000000000000002B ++:1005D000000000000000000000000000000000001B ++:1005E000000000000000000000000000000000000B ++:1005F00000000000000000000000000000000000FB ++:1006000000000000000000000000000000000000EA ++:1006100000000000000000000000000000000000DA ++:1006200000000000000000000000000000000000CA ++:1006300000000000000000000000000000000000BA ++:1006400000000000000000000000000000000000AA ++:10065000000000000000000000000000000000009A ++:10066000000000000000000000000000000000008A ++:10067000000000000000000000000000000000007A ++:10068000000000000000000000000000000000006A ++:10069000000000000000000000000000000000005A ++:1006A000000000000000000000000000000000004A ++:1006B000000000000000000000000000000000003A ++:1006C000000000000000000000000000000000002A ++:1006D000000000000000000000000000000000001A ++:1006E000000000000000000000000000000000000A ++:1006F00000000000000000000000000000000000FA ++:1007000000000000000000000000000000000000E9 ++:1007100000000000000000000000000000000000D9 ++:1007200000000000000000000000000000000000C9 ++:1007300000000000000000000000000000000000B9 ++:1007400000000000000000000000000000000000A9 ++:100750000000000000000000000000000000000099 ++:100760000000000000000000000000000000000089 ++:100770000000000000000000000000000000000079 ++:100780000000000000000000000000000000000069 ++:100790000000000000000000000000000000000059 ++:1007A0000000000000000000000000000000000049 ++:1007B0000000000000000000000000000000000039 ++:1007C0000000000000000000000000000000000029 ++:1007D0000000000000000000000000000000000019 ++:1007E0000000000000000000000000000000000009 ++:1007F00000000000000000000000000000000000F9 ++:1008000000000000000000000000000000000000E8 ++:1008100000000000000000000000000000000000D8 ++:1008200000000000000000000000000000000000C8 ++:1008300000000000000000000000000000000000B8 ++:1008400000000000000000000000000000000000A8 ++:100850000000000000000000000000000000000098 ++:100860000000000000000000000000000000000088 ++:100870000000000000000000000000000000000078 ++:100880000000000000000000000000000000000068 ++:100890000000000000000000000000000000000058 ++:1008A0000000000000000000000000000000000048 ++:1008B0000000000000000000000000000000000038 ++:1008C0000000000000000000000000000000000028 ++:1008D0000000000000000000000000000000000018 ++:1008E0000000000000000000000000000000000008 ++:1008F00000000000000000000000000000000000F8 ++:1009000000000000000000000000000000000000E7 ++:1009100000000000000000000000000000000000D7 ++:1009200000000000000000000000000000000000C7 ++:1009300000000000000000000000000000000000B7 ++:1009400000000000000000000000000000000000A7 ++:100950000000000000000000000000000000000097 ++:100960000000000000000000000000000000000087 ++:100970000000000000000000000000000000000077 ++:100980000000000000000000000000000000000067 ++:100990000000000000000000000000000000000057 ++:1009A0000000000000000000000000000000000047 ++:1009B0000000000000000000000000000000000037 ++:1009C0000000000000000000000000000000000027 ++:1009D0000000000000000000000000000000000017 ++:1009E0000000000000000000000000000000000007 ++:1009F00000000000000000000000000000000000F7 ++:100A000000000000000000000000000000000000E6 ++:100A100000000000000000000000000000000000D6 ++:100A200000000000000000000000000000000000C6 ++:100A300000000000000000000000000000000000B6 ++:100A400000000000000000000000000000000000A6 ++:100A50000000000000000000000000000000000096 ++:100A60000000000000000000000000000000000086 ++:100A70000000000000000000000000000000000076 ++:100A80000000000000000000000000000000000066 ++:100A90000000000000000000000000000000000056 ++:100AA0000000000000000000000000000000000046 ++:100AB0000000000000000000000000000000000036 ++:100AC0000000000000000000000000000000000026 ++:100AD0000000000000000000000000000000000016 ++:100AE0000000000000000000000000000000000006 ++:100AF00000000000000000000000000000000000F6 ++:100B000000000000000000000000000000000000E5 ++:100B100000000000000000000000000000000000D5 ++:100B200000000000000000000000000000000000C5 ++:100B300000000000000000000000000000000000B5 ++:100B400000000000000000000000000000000000A5 ++:100B50000000000000000000000000000000000095 ++:100B60000000000000000000000000000000000085 ++:100B70000000000000000000000000000000000075 ++:100B80000000000000000000000000000000000065 ++:100B90000000000000000000000000000000000055 ++:100BA0000000000000000000000000000000000045 ++:100BB0000000000000000000000000000000000035 ++:100BC0000000000000000000000000000000000025 ++:100BD0000000000000000000000000000000000015 ++:100BE0000000000000000000000000000000000005 ++:100BF00000000000000000000000000000000000F5 ++:100C000000000000000000000000000000000000E4 ++:100C100000000000000000000000000000000000D4 ++:100C200000000000000000000000000000000000C4 ++:100C300000000000000000000000000000000000B4 ++:100C400000000000000000000000000000000000A4 ++:100C50000000000000000000000000000000000094 ++:100C60000000000000000000000000000000000084 ++:100C70000000000000000000000000000000000074 ++:100C80000000000000000000000000000000000064 ++:100C90000000000000000000000000000000000054 ++:100CA0000000000000000000000000000000000044 ++:100CB0000000000000000000000000000000000034 ++:100CC0000000000000000000000000000000000024 ++:100CD0000000000000000000000000000000000014 ++:100CE0000000000000000000000000000000000004 ++:100CF00000000000000000000000000000000000F4 ++:100D000000000000000000000000000000000000E3 ++:100D100000000000000000000000000000000000D3 ++:100D200000000000000000000000000000000000C3 ++:100D300000000000000000000000000000000000B3 ++:100D400000000000000000000000000000000000A3 ++:100D50000000000000000000000000000000000093 ++:100D60000000000000000000000000000000000083 ++:100D70000000000000000000000000000000000073 ++:100D80000000000000000000000000000000000063 ++:100D90000000000000000000000000000000000053 ++:100DA0000000000000000000000000000000000043 ++:100DB0000000000000000000000000000000000033 ++:100DC0000000000000000000000000000000000023 ++:100DD0000000000000000000000000000000000013 ++:100DE0000000000000000000000000000000000003 ++:100DF00000000000000000000000000000000000F3 ++:100E000000000000000000000000000000000000E2 ++:100E100000000000000000000000000000000000D2 ++:100E200000000000000000000000000000000000C2 ++:100E300000000000000000000000000000000000B2 ++:100E400000000000000000000000000000000000A2 ++:100E50000000000000000000000000000000000092 ++:100E60000000000000000000000000000000000082 ++:100E70000000000000000000000000000000000072 ++:100E80000000000000000000000000000000000062 ++:100E90000000000000000000000000000000000052 ++:100EA0000000000000000000000000000000000042 ++:100EB0000000000000000000000000000000000032 ++:100EC0000000000000000000000000000000000022 ++:100ED0000000000000000000000000000000000012 ++:100EE0000000000000000000000000000000000002 ++:100EF00000000000000000000000000000000000F2 ++:100F000000000000000000000000000000000000E1 ++:100F100000000000000000000000000000000000D1 ++:100F200000000000000000000000000000000000C1 ++:100F300000000000000000000000000000000000B1 ++:100F400000000000000000000000000000000000A1 ++:100F50000000000000000000000000000000000091 ++:100F60000000000000000000000000000000000081 ++:100F70000000000000000000000000000000000071 ++:100F80000000000000000000000000000000000061 ++:100F90000000000000000000000000000000000051 ++:100FA0000000000000000000000000000000000041 ++:100FB0000000000000000000000000000000000031 ++:100FC0000000000000000000000000000000000021 ++:100FD0000000000000000000000000000000000011 ++:100FE0000000000000000000000000000000000001 ++:100FF00000000000000000000000000000000000F1 ++:1010000000000000000000000000000000000000E0 ++:1010100000000000000000000000000000000000D0 ++:1010200000000000000000000000000000000000C0 ++:1010300000000000000000000000000000000000B0 ++:1010400000000000000000000000000000000000A0 ++:101050000000000000000000000000000000000090 ++:101060000000000000000000000000000000000080 ++:101070000000000000000000000000000000000070 ++:101080000000000000000000000000000000000060 ++:101090000000000000000000000000000000000050 ++:1010A0000000000000000000000000000000000040 ++:1010B0000000000000000000000000000000000030 ++:1010C0000000000000000000000000000000000020 ++:1010D0000000000000000000000000000000000010 ++:1010E0000000000000000000000000000000000000 ++:1010F00000000000000000000000000000000000F0 ++:1011000000000000000000000000000000000000DF ++:1011100000000000000000000000000000000000CF ++:1011200000000000000000000000000000000000BF ++:1011300000000000000000000000000000000000AF ++:10114000000000000000000000000000000000009F ++:10115000000000000000000000000000000000008F ++:10116000000000000000000000000000000000007F ++:10117000000000000000000000000000000000006F ++:10118000000000000000000000000000000000005F ++:10119000000000000000000000000000000000004F ++:1011A000000000000000000000000000000000003F ++:1011B000000000000000000000000000000000002F ++:1011C000000000000000000000000000000000001F ++:1011D000000000000000000000000000000000000F ++:1011E00000000000000000000000000000000000FF ++:1011F00000000000000000000000000000000000EF ++:1012000000000000000000000000000000000000DE ++:1012100000000000000000000000000000000000CE ++:1012200000000000000000000000000000000000BE ++:1012300000000000000000000000000000000000AE ++:10124000000000000000000000000000000000009E ++:10125000000000000000000000000000000000008E ++:10126000000000000000000000000000000000007E ++:10127000000000000000000000000000000000006E ++:10128000000000000000000000000000000000005E ++:10129000000000000000000000000000000000004E ++:1012A000000000000000000000000000000000003E ++:1012B000000000000000000000000000000000002E ++:1012C000000000000000000000000000000000001E ++:1012D000000000000000000000000000000000000E ++:1012E00000000000000000000000000000000000FE ++:1012F00000000000000000000000000000000000EE ++:1013000000000000000000000000000000000000DD ++:1013100000000000000000000000000000000000CD ++:1013200000000000000000000000000000000000BD ++:1013300000000000000000000000000000000000AD ++:10134000000000000000000000000000000000009D ++:10135000000000000000000000000000000000008D ++:10136000000000000000000000000000000000007D ++:10137000000000000000000000000000000000006D ++:10138000000000000000000000000000000000005D ++:10139000000000000000000000000000000000004D ++:1013A000000000000000000000000000000000003D ++:1013B000000000000000000000000000000000002D ++:1013C000000000000000000000000000000000001D ++:1013D000000000000000000000000000000000000D ++:1013E00000000000000000000000000000000000FD ++:1013F00000000000000000000000000000000000ED ++:1014000000000000000000000000000000000000DC ++:1014100000000000000000000000000000000000CC ++:1014200000000000000000000000000000000000BC ++:1014300000000000000000000000000000000000AC ++:10144000000000000000000000000000000000009C ++:10145000000000000000000000000000000000008C ++:10146000000000000000000000000000000000007C ++:10147000000000000000000000000000000000006C ++:10148000000000000000000000000000000000005C ++:10149000000000000000000000000000000000004C ++:1014A000000000000000000000000000000000003C ++:1014B000000000000000000000000000000000002C ++:1014C000000000000000000000000000000000001C ++:1014D000000000000000000000000000000000000C ++:1014E00000000000000000000000000000000000FC ++:1014F00000000000000000000000000000000000EC ++:1015000000000000000000000000000000000000DB ++:1015100000000000000000000000000000000000CB ++:1015200000000000000000000000000000000000BB ++:1015300000000000000000000000000000000000AB ++:10154000000000000000000000000000000000009B ++:10155000000000000000000000000000000000008B ++:10156000000000000000000000000000000000007B ++:10157000000000000000000000000000000000006B ++:10158000000000000000000000000000000000005B ++:10159000000000000000000000000000000000004B ++:1015A000000000000000000000000000000000003B ++:1015B000000000000000000000000000000000002B ++:1015C000000000000000000000000000000000001B ++:1015D000000000000000000000000000000000000B ++:1015E00000000000000000000000000000000000FB ++:1015F00000000000000000000000000000000000EB ++:1016000000000000000000000000000000000000DA ++:1016100000000000000000000000000000000000CA ++:1016200000000000000000000000000000000000BA ++:1016300000000000000000000000000000000000AA ++:10164000000000000000000000000000000000009A ++:10165000000000000000000000000000000000008A ++:10166000000000000000000000000000000000007A ++:10167000000000000000000000000000000000006A ++:10168000000000000000000000000000000000005A ++:10169000000000000000000000000000000000004A ++:1016A000000000000000000000000000000000003A ++:1016B000000000000000000000000000000000002A ++:1016C000000000000000000000000000000000001A ++:1016D000000000000000000000000000000000000A ++:1016E00000000000000000000000000000000000FA ++:1016F00000000000000000000000000000000000EA ++:1017000000000000000000000000000000000000D9 ++:1017100000000000000000000000000000000000C9 ++:1017200000000000000000000000000000000000B9 ++:1017300000000000000000000000000000000000A9 ++:101740000000000000000000000000000000000099 ++:101750000000000000000000000000000000000089 ++:101760000000000000000000000000000000000079 ++:101770000000000000000000000000000000000069 ++:101780000000000000000000000000000000000059 ++:101790000000000000000000000000000000000049 ++:1017A0000000000000000000000000000000000039 ++:1017B0000000000000000000000000000000000029 ++:1017C0000000000000000000000000000000000019 ++:1017D0000000000000000000000000000000000009 ++:1017E00000000000000000000000000000000000F9 ++:1017F00000000000000000000000000000000000E9 ++:1018000000000000000000000000000000000000D8 ++:1018100000000000000000000000000000000000C8 ++:1018200000000000000000000000000000000000B8 ++:1018300000000000000000000000000000000000A8 ++:101840000000000000000000000000000000000098 ++:101850000000000000000000000000000000000088 ++:101860000000000000000000000000000000000078 ++:101870000000000000000000000000000000000068 ++:101880000000000000000000000000000000000058 ++:101890000000000000000000000000000000000048 ++:1018A0000000000000000000000000000000000038 ++:1018B0000000000000000000000000000000000028 ++:1018C0000000000000000000000000000000000018 ++:1018D0000000000000000000000000000000000008 ++:1018E00000000000000000000000000000000000F8 ++:1018F00000000000000000000000000000000000E8 ++:1019000000000000000000000000000000000000D7 ++:1019100000000000000000000000000000000000C7 ++:1019200000000000000000000000000000000000B7 ++:1019300000000000000000000000000000000000A7 ++:101940000000000000000000000000000000000097 ++:101950000000000000000000000000000000000087 ++:101960000000000000000000000000000000000077 ++:101970000000000000000000000000000000000067 ++:101980000000000000000000000000000000000057 ++:101990000000000000000000000000000000000047 ++:1019A0000000000000000000000000000000000037 ++:1019B0000000000000000000000000000000000027 ++:1019C0000000000000000000000000000000000017 ++:1019D0000000000000000000000000000000000007 ++:1019E00000000000000000000000000000000000F7 ++:1019F00000000000000000000000000000000000E7 ++:101A000000000000000000000000000000000000D6 ++:101A100000000000000000000000000000000000C6 ++:101A200000000000000000000000000000000000B6 ++:101A300000000000000000000000000000000000A6 ++:101A40000000000000000000000000000000000096 ++:101A50000000000000000000000000000000000086 ++:101A60000000000000000000000000000000000076 ++:101A70000000000000000000000000000000000066 ++:101A80000000000000000000000000000000000056 ++:101A90000000000000000000000000000000000046 ++:101AA0000000000000000000000000000000000036 ++:101AB0000000000000000000000000000000000026 ++:101AC0000000000000000000000000000000000016 ++:101AD0000000000000000000000000000000000006 ++:101AE00000000000000000000000000000000000F6 ++:101AF00000000000000000000000000000000000E6 ++:101B000000000000000000000000000000000000D5 ++:101B100000000000000000000000000000000000C5 ++:101B200000000000000000000000000000000000B5 ++:101B300000000000000000000000000000000000A5 ++:101B40000000000000000000000000000000000095 ++:101B50000000000000000000000000000000000085 ++:101B60000000000000000000000000000000000075 ++:101B70000000000000000000000000000000000065 ++:101B80000000000000000000000000000000000055 ++:101B90000000000000000000000000000000000045 ++:101BA0000000000000000000000000000000000035 ++:101BB0000000000000000000000000000000000025 ++:101BC0000000000000000000000000000000000015 ++:101BD0000000000000000000000000000000000005 ++:101BE00000000000000000000000000000000000F5 ++:101BF00000000000000000000000000000000000E5 ++:101C000000000000000000000000000000000000D4 ++:101C100000000000000000000000000000000000C4 ++:101C200000000000000000000000000000000000B4 ++:101C300000000000000000000000000000000000A4 ++:101C40000000000000000000000000000000000094 ++:101C50000000000000000000000000000000000084 ++:101C60000000000000000000000000000000000074 ++:101C70000000000000000000000000000000000064 ++:101C80000000000000000000000000000000000054 ++:101C90000000000000000000000000000000000044 ++:101CA0000000000000000000000000000000000034 ++:101CB0000000000000000000000000000000000024 ++:101CC0000000000000000000000000000000000014 ++:101CD0000000000000000000000000000000000004 ++:101CE00000000000000000000000000000000000F4 ++:101CF00000000000000000000000000000000000E4 ++:101D000000000000000000000000000000000000D3 ++:101D100000000000000000000000000000000000C3 ++:101D200000000000000000000000000000000000B3 ++:101D300000000000000000000000000000000000A3 ++:101D40000000000000000000000000000000000093 ++:101D50000000000000000000000000000000000083 ++:101D60000000000000000000000000000000000073 ++:101D70000000000000000000000000000000000063 ++:101D80000000000000000000000000000000000053 ++:101D90000000000000000000000000000000000043 ++:101DA0000000000000000000000000000000000033 ++:101DB0000000000000000000000000000000000023 ++:101DC0000000000000000000000000000000000013 ++:101DD0000000000000000000000000000000000003 ++:101DE00000000000000000000000000000000000F3 ++:101DF00000000000000000000000000000000000E3 ++:101E000000000000000000000000000000000000D2 ++:101E100000000000000000000000000000000000C2 ++:101E200000000000000000000000000000000000B2 ++:101E300000000000000000000000000000000000A2 ++:101E40000000000000000000000000000000000092 ++:101E50000000000000000000000000000000000082 ++:101E60000000000000000000000000000000000072 ++:101E70000000000000000000000000000000000062 ++:101E80000000000000000000000000000000000052 ++:101E90000000000000000000000000000000000042 ++:101EA0000000000000000000000000000000000032 ++:101EB0000000000000000000000000000000000022 ++:101EC0000000000000000000000000000000000012 ++:101ED0000000000000000000000000000000000002 ++:101EE00000000000000000000000000000000000F2 ++:101EF00000000000000000000000000000000000E2 ++:101F000000000000000000000000000000000000D1 ++:101F100000000000000000000000000000000000C1 ++:101F200000000000000000000000000000000000B1 ++:101F300000000000000000000000000000000000A1 ++:101F40000000000000000000000000000000000091 ++:101F50000000000000000000000000000000000081 ++:101F60000000000000000000000000000000000071 ++:101F70000000000000000000000000000000000061 ++:101F80000000000000000000000000000000000051 ++:101F90000000000000000000000000000000000041 ++:101FA0000000000000000000000000000000000031 ++:101FB0000000000000000000000000000000000021 ++:101FC0000000000000000000000000000000000011 ++:101FD0000000000000000000000000000000000001 ++:101FE00000000000000000000000000000000000F1 ++:101FF00000000000000000000000000000000000E1 ++:1020000000000000000000000000000000000000D0 ++:1020100000000000000000000000000000000000C0 ++:1020200000000000000000000000000000000000B0 ++:1020300000000000000000000000000000000000A0 ++:102040000000000000000000000000000000000090 ++:102050000000000000000000000000000000000080 ++:102060000000000000000000000000000000000070 ++:102070000000000000000000000000000000000060 ++:102080000000000000000000000000000000000050 ++:102090000000000000000000000000000000000040 ++:1020A0000000000000000000000000000000000030 ++:1020B0000000000000000000000000000000000020 ++:1020C0000000000000000000000000000000000010 ++:1020D0000000000000000000000000000000000000 ++:1020E00000000000000000000000000000000000F0 ++:1020F00000000000000000000000000000000000E0 ++:1021000000000000000000000000000000000000CF ++:1021100000000000000000000000000000000000BF ++:1021200000000000000000000000000000000000AF ++:10213000000000000000000000000000000000009F ++:10214000000000000000000000000000000000008F ++:10215000000000000000000000000000000000007F ++:10216000000000000000000000000000000000006F ++:10217000000000000000000000000000000000005F ++:10218000000000000000000000000000000000004F ++:10219000000000000000000000000000000000003F ++:1021A000000000000000000000000000000000002F ++:1021B000000000000000000000000000000000001F ++:1021C000000000000000000000000000000000000F ++:1021D00000000000000000000000000000000000FF ++:1021E00000000000000000000000000000000000EF ++:1021F00000000000000000000000000000000000DF ++:1022000000000000000000000000000000000000CE ++:1022100000000000000000000000000000000000BE ++:1022200000000000000000000000000000000000AE ++:10223000000000000000000000000000000000009E ++:10224000000000000000000000000000000000008E ++:10225000000000000000000000000000000000007E ++:10226000000000000000000000000000000000006E ++:10227000000000000000000000000000000000005E ++:10228000000000000000000000000000000000004E ++:10229000000000000000000000000000000000003E ++:1022A000000000000000000000000000000000002E ++:1022B000000000000000000000000000000000001E ++:1022C000000000000000000000000000000000000E ++:1022D00000000000000000000000000000000000FE ++:1022E00000000000000000000000000000000000EE ++:1022F00000000000000000000000000000000000DE ++:1023000000000000000000000000000000000000CD ++:1023100000000000000000000000000000000000BD ++:1023200000000000000000000000000000000000AD ++:10233000000000000000000000000000000000009D ++:10234000000000000000000000000000000000008D ++:10235000000000000000000000000000000000007D ++:10236000000000000000000000000000000000006D ++:10237000000000000000000000000000000000005D ++:10238000000000000000000000000000000000004D ++:10239000000000000000000000000000000000003D ++:1023A000000000000000000000000000000000002D ++:1023B000000000000000000000000000000000001D ++:1023C000000000000000000000000000000000000D ++:1023D00000000000000000000000000000000000FD ++:1023E00000000000000000000000000000000000ED ++:1023F00000000000000000000000000000000000DD ++:1024000000000000000000000000000000000000CC ++:1024100000000000000000000000000000000000BC ++:1024200000000000000000000000000000000000AC ++:10243000000000000000000000000000000000009C ++:10244000000000000000000000000000000000008C ++:10245000000000000000000000000000000000007C ++:10246000000000000000000000000000000000006C ++:10247000000000000000000000000000000000005C ++:10248000000000000000000000000000000000004C ++:10249000000000000000000000000000000000003C ++:1024A000000000000000000000000000000000002C ++:1024B000000000000000000000000000000000001C ++:1024C000000000000000000000000000000000000C ++:1024D00000000000000000000000000000000000FC ++:1024E00000000000000000000000000000000000EC ++:1024F00000000000000000000000000000000000DC ++:1025000000000000000000000000000000000000CB ++:1025100000000000000000000000000000000000BB ++:1025200000000000000000000000000000000000AB ++:10253000000000000000000000000000000000009B ++:10254000000000000000000000000000000000008B ++:10255000000000000000000000000000000000007B ++:10256000000000000000000000000000000000006B ++:10257000000000000000000000000000000000005B ++:10258000000000000000000000000000000000004B ++:10259000000000000000000000000000000000003B ++:1025A000000000000000000000000000000000002B ++:1025B000000000000000000000000000000000001B ++:1025C000000000000000000000000000000000000B ++:1025D00000000000000000000000000000000000FB ++:1025E00000000000000000000000000000000000EB ++:1025F00000000000000000000000000000000000DB ++:1026000000000000000000000000000000000000CA ++:1026100000000000000000000000000000000000BA ++:1026200000000000000000000000000000000000AA ++:10263000000000000000000000000000000000009A ++:10264000000000000000000000000000000000008A ++:10265000000000000000000000000000000000007A ++:10266000000000000000000000000000000000006A ++:10267000000000000000000000000000000000005A ++:10268000000000000000000000000000000000004A ++:10269000000000000000000000000000000000003A ++:1026A000000000000000000000000000000000002A ++:1026B000000000000000000000000000000000001A ++:1026C000000000000000000000000000000000000A ++:1026D00000000000000000000000000000000000FA ++:1026E00000000000000000000000000000000000EA ++:1026F00000000000000000000000000000000000DA ++:1027000000000000000000000000000000000000C9 ++:1027100000000000000000000000000000000000B9 ++:1027200000000000000000000000000000000000A9 ++:102730000000000000000000000000000000000099 ++:102740000000000000000000000000000000000089 ++:102750000000000000000000000000000000000079 ++:102760000000000000000000000000000000000069 ++:102770000000000000000000000000000000000059 ++:102780000000000000000000000000000000000049 ++:102790000000000000000000000000000000000039 ++:1027A0000000000000000000000000000000000029 ++:1027B0000000000000000000000000000000000019 ++:1027C0000000000000000000000000000000000009 ++:1027D00000000000000000000000000000000000F9 ++:1027E00000000000000000000000000000000000E9 ++:1027F00000000000000000000000000000000000D9 ++:1028000000000000000000000000000000000000C8 ++:1028100000000000000000000000000000000000B8 ++:1028200000000000000000000000000000000000A8 ++:102830000000000000000000000000000000000098 ++:102840000000000000000000000000000000000088 ++:102850000000000000000000000000000000000078 ++:102860000000000000000000000000000000000068 ++:102870000000000000000000000000000000000058 ++:102880000000000000000000000000000000000048 ++:102890000000000000000000000000000000000038 ++:1028A0000000000000000000000000000000000028 ++:1028B0000000000000000000000000000000000018 ++:1028C0000000000000000000000000000000000008 ++:1028D00000000000000000000000000000000000F8 ++:1028E00000000000000000000000000000000000E8 ++:1028F00000000000000000000000000000000000D8 ++:1029000000000000000000000000000000000000C7 ++:1029100000000000000000000000000000000000B7 ++:1029200000000000000000000000000000000000A7 ++:102930000000000000000000000000000000000097 ++:102940000000000000000000000000000000000087 ++:102950000000000000000000000000000000000077 ++:102960000000000000000000000000000000000067 ++:102970000000000000000000000000000000000057 ++:102980000000000000000000000000000000000047 ++:102990000000000000000000000000000000000037 ++:1029A0000000000000000000000000000000000027 ++:1029B0000000000000000000000000000000000017 ++:1029C0000000000000000000000000000000000007 ++:1029D00000000000000000000000000000000000F7 ++:1029E00000000000000000000000000000000000E7 ++:1029F00000000000000000000000000000000000D7 ++:102A000000000000000000000000000000000000C6 ++:102A100000000000000000000000000000000000B6 ++:102A200000000000000000000000000000000000A6 ++:102A30000000000000000000000000000000000096 ++:102A40000000000000000000000000000000000086 ++:102A50000000000000000000000000000000000076 ++:102A60000000000000000000000000000000000066 ++:102A70000000000000000000000000000000000056 ++:102A80000000000000000000000000000000000046 ++:102A90000000000000000000000000000000000036 ++:102AA0000000000000000000000000000000000026 ++:102AB0000000000000000000000000000000000016 ++:102AC0000000000000000000000000000000000006 ++:102AD00000000000000000000000000000000000F6 ++:102AE00000000000000000000000000000000000E6 ++:102AF00000000000000000000000000000000000D6 ++:102B000000000000000000000000000000000000C5 ++:102B100000000000000000000000000000000000B5 ++:102B200000000000000000000000000000000000A5 ++:102B30000000000000000000000000000000000095 ++:102B40000000000000000000000000000000000085 ++:102B50000000000000000000000000000000000075 ++:102B60000000000000000000000000000000000065 ++:102B70000000000000000000000000000000000055 ++:102B80000000000000000000000000000000000045 ++:102B90000000000000000000000000000000000035 ++:102BA0000000000000000000000000000000000025 ++:102BB0000000000000000000000000000000000015 ++:102BC0000000000000000000000000000000000005 ++:102BD00000000000000000000000000000000000F5 ++:102BE00000000000000000000000000000000000E5 ++:102BF00000000000000000000000000000000000D5 ++:102C000000000000000000000000000000000000C4 ++:102C100000000000000000000000000000000000B4 ++:102C200000000000000000000000000000000000A4 ++:102C30000000000000000000000000000000000094 ++:102C40000000000000000000000000000000000084 ++:102C50000000000000000000000000000000000074 ++:102C60000000000000000000000000000000000064 ++:102C70000000000000000000000000000000000054 ++:102C80000000000000000000000000000000000044 ++:102C90000000000000000000000000000000000034 ++:102CA0000000000000000000000000000000000024 ++:102CB0000000000000000000000000000000000014 ++:102CC0000000000000000000000000000000000004 ++:102CD00000000000000000000000000000000000F4 ++:102CE00000000000000000000000000000000000E4 ++:102CF00000000000000000000000000000000000D4 ++:102D000000000000000000000000000000000000C3 ++:102D100000000000000000000000000000000000B3 ++:102D200000000000000000000000000000000000A3 ++:102D30000000000000000000000000000000000093 ++:102D40000000000000000000000000000000000083 ++:102D50000000000000000000000000000000000073 ++:102D60000000000000000000000000000000000063 ++:102D70000000000000000000000000000000000053 ++:102D80000000000000000000000000000000000043 ++:102D90000000000000000000000000000000000033 ++:102DA0000000000000000000000000000000000023 ++:102DB0000000000000000000000000000000000013 ++:102DC0000000000000000000000000000000000003 ++:102DD00000000000000000000000000000000000F3 ++:102DE00000000000000000000000000000000000E3 ++:102DF00000000000000000000000000000000000D3 ++:102E000000000000000000000000000000000000C2 ++:102E100000000000000000000000000000000000B2 ++:102E200000000000000000000000000000000000A2 ++:102E30000000000000000000000000000000000092 ++:102E40000000000000000000000000000000000082 ++:102E50000000000000000000000000000000000072 ++:102E60000000000000000000000000000000000062 ++:102E70000000000000000000000000000000000052 ++:102E80000000000000000000000000000000000042 ++:102E90000000000000000000000000000000000032 ++:102EA0000000000000000000000000000000000022 ++:102EB0000000000000000000000000000000000012 ++:102EC0000000000000000000000000000000000002 ++:102ED00000000000000000000000000000000000F2 ++:102EE00000000000000000000000000000000000E2 ++:102EF00000000000000000000000000000000000D2 ++:102F000000000000000000000000000000000000C1 ++:102F100000000000000000000000000000000000B1 ++:102F200000000000000000000000000000000000A1 ++:102F30000000000000000000000000000000000091 ++:102F40000000000000000000000000000000000081 ++:102F50000000000000000000000000000000000071 ++:102F60000000000000000000000000000000000061 ++:102F70000000000000000000000000000000000051 ++:102F80000000000000000000000000000000000041 ++:102F90000000000000000000000000000000000031 ++:102FA0000000000000000000000000000000000021 ++:102FB0000000000000000000000000000000000011 ++:102FC0000000000000000000000000000000000001 ++:102FD00000000000000000000000000000000000F1 ++:102FE00000000000000000000000000000000000E1 ++:102FF00000000000000000000000000000000000D1 ++:1030000000000000000000000000000000000000C0 ++:1030100000000000000000000000000000000000B0 ++:1030200000000000000000000000000000000000A0 ++:103030000000000000000000000000000000000090 ++:103040000000000000000000000000000000000080 ++:103050000000000000000000000000000000000070 ++:103060000000000000000000000000000000000060 ++:103070000000000000000000000000000000000050 ++:103080000000000000000000000000000000000040 ++:103090000000000000000000000000000000000030 ++:1030A0000000000000000000000000000000000020 ++:1030B0000000000000000000000000000000000010 ++:1030C0000000000000000000000000000000000000 ++:1030D00000000000000000000000000000000000F0 ++:1030E00000000000000000000000000000000000E0 ++:1030F00000000000000000000000000000000000D0 ++:1031000000000000000000000000000000000000BF ++:1031100000000000000000000000000000000000AF ++:10312000000000000000000000000000000000009F ++:10313000000000000000000000000000000000008F ++:10314000000000000000000000000000000000007F ++:10315000000000000000000000000000000000006F ++:10316000000000000000000000000000000000005F ++:10317000000000000000000000000000000000004F ++:10318000000000000000000000000000000000003F ++:10319000000000000000000000000000000000002F ++:1031A000000000000000000000000000000000001F ++:1031B000000000000000000000000000000000000F ++:1031C00000000000000000000000000000000000FF ++:1031D00000000000000000000000000000000000EF ++:1031E00000000000000000000000000000000000DF ++:1031F00000000000000000000000000000000000CF ++:1032000000000000000000000000000000000000BE ++:1032100000000000000000000000000000000000AE ++:10322000000000000000000000000000000000009E ++:10323000000000000000000000000000000000008E ++:10324000000000000000000000000000000000007E ++:10325000000000000000000000000000000000006E ++:10326000000000000000000000000000000000005E ++:10327000000000000000000000000000000000004E ++:10328000000000000000000000000000000000003E ++:10329000000000000000000000000000000000002E ++:1032A000000000000000000000000000000000001E ++:1032B000000000000000000000000000000000000E ++:1032C00000000000000000000000000000000000FE ++:1032D00000000000000000000000000000000000EE ++:1032E00000000000000000000000000000000000DE ++:1032F00000000000000000000000000000000000CE ++:1033000000000000000000000000000000000000BD ++:1033100000000000000000000000000000000000AD ++:10332000000000000000000000000000000000009D ++:10333000000000000000000000000000000000008D ++:10334000000000000000000000000000000000007D ++:10335000000000000000000000000000000000006D ++:10336000000000000000000000000000000000005D ++:10337000000000000000000000000000000000004D ++:10338000000000000000000000000000000000003D ++:10339000000000000000000000000000000000002D ++:1033A000000000000000000000000000000000001D ++:1033B000000000000000000000000000000000000D ++:1033C00000000000000000000000000000000000FD ++:1033D00000000000000000000000000000000000ED ++:1033E00000000000000000000000000000000000DD ++:1033F00000000000000000000000000000000000CD ++:1034000000000000000000000000000000000000BC ++:1034100000000000000000000000000000000000AC ++:10342000000000000000000000000000000000009C ++:10343000000000000000000000000000000000008C ++:10344000000000000000000000000000000000007C ++:10345000000000000000000000000000000000006C ++:10346000000000000000000000000000000000005C ++:10347000000000000000000000000000000000004C ++:10348000000000000000000000000000000000003C ++:10349000000000000000000000000000000000002C ++:1034A000000000000000000000000000000000001C ++:1034B000000000000000000000000000000000000C ++:1034C00000000000000000000000000000000000FC ++:1034D00000000000000000000000000000000000EC ++:1034E00000000000000000000000000000000000DC ++:1034F00000000000000000000000000000000000CC ++:1035000000000000000000000000000000000000BB ++:1035100000000000000000000000000000000000AB ++:10352000000000000000000000000000000000009B ++:10353000000000000000000000000000000000008B ++:10354000000000000000000000000000000000007B ++:10355000000000000000000000000000000000006B ++:10356000000000000000000000000000000000005B ++:10357000000000000000000000000000000000004B ++:10358000000000000000000000000000000000003B ++:10359000000000000000000000000000000000002B ++:1035A000000000000000000000000000000000001B ++:1035B000000000000000000000000000000000000B ++:1035C00000000000000000000000000000000000FB ++:1035D00000000000000000000000000000000000EB ++:1035E00000000000000000000000000000000000DB ++:1035F00000000000000000000000000000000000CB ++:1036000000000000000000000000000000000000BA ++:1036100000000000000000000000000000000000AA ++:10362000000000000000000000000000000000009A ++:10363000000000000000000000000000000000008A ++:10364000000000000000000000000000000000007A ++:10365000000000000000000000000000000000006A ++:10366000000000000000000000000000000000005A ++:10367000000000000000000000000000000000004A ++:10368000000000000000000000000000000000003A ++:10369000000000000000000000000000000000002A ++:1036A000000000000000000000000000000000001A ++:1036B000000000000000000000000000000000000A ++:1036C00000000000000000000000000000000000FA ++:1036D00000000000000000000000000000000000EA ++:1036E00000000000000000000000000000000000DA ++:1036F00000000000000000000000000000000000CA ++:1037000000000000000000000000000000000000B9 ++:1037100000000000000000000000000000000000A9 ++:103720000000000000000000000000000000000099 ++:103730000000000000000000000000000000000089 ++:103740000000000000000000000000000000000079 ++:103750000000000000000000000000000000000069 ++:103760000000000000000000000000000000000059 ++:103770000000000000000000000000000000000049 ++:103780000000000000000000000000000000000039 ++:103790000000000000000000000000000000000029 ++:1037A0000000000000000000000000000000000019 ++:1037B0000000000000000000000000000000000009 ++:1037C00000000000000000000000000000000000F9 ++:1037D00000000000000000000000000000000000E9 ++:1037E00000000000000000000000000000000000D9 ++:1037F00000000000000000000000000000000000C9 ++:1038000000000000000000000000000000000000B8 ++:1038100000000000000000000000000000000000A8 ++:103820000000000000000000000000000000000098 ++:103830000000000000000000000000000000000088 ++:103840000000000000000000000000000000000078 ++:103850000000000000000000000000000000000068 ++:103860000000000000000000000000000000000058 ++:103870000000000000000000000000000000000048 ++:103880000000000000000000000000000000000038 ++:103890000000000000000000000000000000000028 ++:1038A0000000000000000000000000000000000018 ++:1038B0000000000000000000000000000000000008 ++:1038C00000000000000000000000000000000000F8 ++:1038D00000000000000000000000000000000000E8 ++:1038E00000000000000000000000000000000000D8 ++:1038F00000000000000000000000000000000000C8 ++:1039000000000000000000000000000000000000B7 ++:1039100000000000000000000000000000000000A7 ++:103920000000000000000000000000000000000097 ++:103930000000000000000000000000000000000087 ++:103940000000000000000000000000000000000077 ++:103950000000000000000000000000000000000067 ++:103960000000000000000000000000000000000057 ++:103970000000000000000000000000000000000047 ++:103980000000000000000000000000000000000037 ++:103990000000000000000000000000000000000027 ++:1039A0000000000000000000000000000000000017 ++:1039B0000000000000000000000000000000000007 ++:1039C00000000000000000000000000000000000F7 ++:1039D00000000000000000000000000000000000E7 ++:1039E00000000000000000000000000000000000D7 ++:1039F00000000000000000000000000000000000C7 ++:103A000000000000000000000000000000000000B6 ++:103A100000000000000000000000000000000000A6 ++:103A20000000000000000000000000000000000096 ++:103A30000000000000000000000000000000000086 ++:103A40000000000000000000000000000000000076 ++:103A50000000000000000000000000000000000066 ++:103A60000000000000000000000000000000000056 ++:103A70000000000000000000000000000000000046 ++:103A80000000000000000000000000000000000036 ++:103A90000000000000000000000000000000000026 ++:103AA0000000000000000000000000000000000016 ++:103AB0000000000000000000000000000000000006 ++:103AC00000000000000000000000000000000000F6 ++:103AD00000000000000000000000000000000000E6 ++:103AE00000000000000000000000000000000000D6 ++:103AF00000000000000000000000000000000000C6 ++:103B000000000000000000000000000000000000B5 ++:103B100000000000000000000000000000000000A5 ++:103B20000000000000000000000000000000000095 ++:103B30000000000000000000000000000000000085 ++:103B40000000000000000000000000000000000075 ++:103B50000000000000000000000000000000000065 ++:103B60000000000000000000000000000000000055 ++:103B70000000000000000000000000000000000045 ++:103B80000000000000000000000000000000000035 ++:103B90000000000000000000000000000000000025 ++:103BA0000000000000000000000000000000000015 ++:103BB0000000000000000000000000000000000005 ++:103BC00000000000000000000000000000000000F5 ++:103BD00000000000000000000000000000000000E5 ++:103BE00000000000000000000000000000000000D5 ++:103BF00000000000000000000000000000000000C5 ++:103C000000000000000000000000000000000000B4 ++:103C100000000000000000000000000000000000A4 ++:103C20000000000000000000000000000000000094 ++:103C30000000000000000000000000000000000084 ++:103C40000000000000000000000000000000000074 ++:103C50000000000000000000000000000000000064 ++:103C60000000000000000000000000000000000054 ++:103C70000000000000000000000000000000000044 ++:103C80000000000000000000000000000000000034 ++:103C90000000000000000000000000000000000024 ++:103CA0000000000000000000000000000000000014 ++:103CB0000000000000000000000000000000000004 ++:103CC00000000000000000000000000000000000F4 ++:103CD00000000000000000000000000000000000E4 ++:103CE00000000000000000000000000000000000D4 ++:103CF00000000000000000000000000000000000C4 ++:103D000000000000000000000000000000000000B3 ++:103D100000000000000000000000000000000000A3 ++:103D20000000000000000000000000000000000093 ++:103D30000000000000000000000000000000000083 ++:103D40000000000000000000000000000000000073 ++:103D50000000000000000000000000000000000063 ++:103D60000000000000000000000000000000000053 ++:103D70000000000000000000000000000000000043 ++:103D80000000000000000000000000000000000033 ++:103D90000000000000000000000000000000000023 ++:103DA0000000000000000000000000000000000013 ++:103DB0000000000000000000000000000000000003 ++:103DC00000000000000000000000000000000000F3 ++:103DD00000000000000000000000000000000000E3 ++:103DE00000000000000000000000000000000000D3 ++:103DF00000000000000000000000000000000000C3 ++:103E000000000000000000000000000000000000B2 ++:103E100000000000000000000000000000000000A2 ++:103E20000000000000000000000000000000000092 ++:103E30000000000000000000000000000000000082 ++:103E40000000000000000000000000000000000072 ++:103E50000000000000000000000000000000000062 ++:103E60000000000000000000000000000000000052 ++:103E70000000000000000000000000000000000042 ++:103E80000000000000000000000000000000000032 ++:103E90000000000000000000000000000000000022 ++:103EA0000000000000000000000000000000000012 ++:103EB0000000000000000000000000000000000002 ++:103EC00000000000000000000000000000000000F2 ++:103ED00000000000000000000000000000000000E2 ++:103EE00000000000000000000000000000000000D2 ++:103EF00000000000000000000000000000000000C2 ++:103F000000000000000000000000000000000000B1 ++:103F100000000000000000000000000000000000A1 ++:103F20000000000000000000000000000000000091 ++:103F30000000000000000000000000000000000081 ++:103F40000000000000000000000000000000000071 ++:103F50000000000000000000000000000000000061 ++:103F60000000000000000000000000000000000051 ++:103F70000000000000000000000000000000000041 ++:103F80000000000000000000000000000000000031 ++:103F90000000000000000000000000000000000021 ++:103FA0000000000000000000000000000000000011 ++:103FB0000000000000000000000000000000000001 ++:103FC00000000000000000000000000000000000F1 ++:103FD00000000000000000000000000000000000E1 ++:103FE00000000000000000000000000000000000D1 ++:103FF00000000000000000000000000000000000C1 ++:1040000000000000000000000000000000000000B0 ++:1040100000000000000000000000000000000000A0 ++:104020000000000000000000000000000000000090 ++:104030000000000000000000000000000000000080 ++:104040000000000000000000000000000000000070 ++:104050000000000000000000000000000000000060 ++:104060000000000000000000000000000000000050 ++:104070000000000000000000000000000000000040 ++:104080000000000000000000000000000000000030 ++:104090000000000000000000000000000000000020 ++:1040A0000000000000000000000000000000000010 ++:1040B0000000000000000000000000000000000000 ++:1040C00000000000000000000000000000000000F0 ++:1040D00000000000000000000000000000000000E0 ++:1040E00000000000000000000000000000000000D0 ++:1040F00000000000000000000000000000000000C0 ++:1041000000000000000000000000000000000000AF ++:10411000000000000000000000000000000000009F ++:10412000000000000000000000000000000000008F ++:10413000000000000000000000000000000000007F ++:10414000000000000000000000000000000000006F ++:10415000000000000000000000000000000000005F ++:10416000000000000000000000000000000000004F ++:10417000000000000000000000000000000000003F ++:10418000000000000000000000000000000000002F ++:10419000000000000000000000000000000000001F ++:1041A000000000000000000000000000000000000F ++:1041B00000000000000000000000000000000000FF ++:1041C00000000000000000000000000000000000EF ++:1041D00000000000000000000000000000000000DF ++:1041E00000000000000000000000000000000000CF ++:1041F00000000000000000000000000000000000BF ++:1042000000000000000000000000000000000000AE ++:10421000000000000000000000000000000000009E ++:10422000000000000000000000000000000000008E ++:10423000000000000000000000000000000000007E ++:10424000000000000000000000000000000000006E ++:10425000000000000000000000000000000000005E ++:10426000000000000000000000000000000000004E ++:10427000000000000000000000000000000000003E ++:10428000000000000000000000000000000000002E ++:10429000000000000000000000000000000000001E ++:1042A000000000000000000000000000000000000E ++:1042B00000000000000000000000000000000000FE ++:1042C00000000000000000000000000000000000EE ++:1042D00000000000000000000000000000000000DE ++:1042E00000000000000000000000000000000000CE ++:1042F00000000000000000000000000000000000BE ++:1043000000000000000000000000000000000000AD ++:10431000000000000000000000000000000000009D ++:10432000000000000000000000000000000000008D ++:10433000000000000000000000000000000000007D ++:10434000000000000000000000000000000000006D ++:10435000000000000000000000000000000000005D ++:10436000000000000000000000000000000000004D ++:10437000000000000000000000000000000000003D ++:10438000000000000000000000000000000000002D ++:10439000000000000000000000000000000000001D ++:1043A000000000000000000000000000000000000D ++:1043B00000000000000000000000000000000000FD ++:1043C00000000000000000000000000000000000ED ++:1043D00000000000000000000000000000000000DD ++:1043E00000000000000000000000000000000000CD ++:1043F00000000000000000000000000000000000BD ++:1044000000000000000000000000000000000000AC ++:10441000000000000000000000000000000000009C ++:10442000000000000000000000000000000000008C ++:10443000000000000000000000000000000000007C ++:10444000000000000000000000000000000000006C ++:10445000000000000000000000000000000000005C ++:10446000000000000000000000000000000000004C ++:10447000000000000000000000000000000000003C ++:10448000000000000000000000000000000000002C ++:10449000000000000000000000000000000000001C ++:1044A000000000000000000000000000000000000C ++:1044B00000000000000000000000000000000000FC ++:1044C00000000000000000000000000000000000EC ++:1044D00000000000000000000000000000000000DC ++:1044E00000000000000000000000000000000000CC ++:1044F00000000000000000000000000000000000BC ++:1045000000000000000000000000000000000000AB ++:10451000000000000000000000000000000000009B ++:10452000000000000000000000000000000000008B ++:10453000000000000000000000000000000000007B ++:10454000000000000000000000000000000000006B ++:10455000000000000000000000000000000000005B ++:10456000000000000000000000000000000000004B ++:10457000000000000000000000000000000000003B ++:10458000000000000000000000000000000000002B ++:10459000000000000000000000000000000000001B ++:1045A000000000000000000000000000000000000B ++:1045B00000000000000000000000000000000000FB ++:1045C00000000000000000000000000000000000EB ++:1045D00000000000000000000000000000000000DB ++:1045E00000000000000000000000000000000000CB ++:1045F00000000000000000000000000000000000BB ++:1046000000000000000000000000000000000000AA ++:10461000000000000000000000000000000000009A ++:10462000000000000000000000000000000000008A ++:10463000000000000000000000000000000000007A ++:10464000000000000000000000000000000000006A ++:10465000000000000000000000000000000000005A ++:10466000000000000000000000000000000000004A ++:10467000000000000000000000000000000000003A ++:10468000000000000000000000000000000000002A ++:10469000000000000000000000000000000000001A ++:1046A000000000000000000000000000000000000A ++:1046B00000000000000000000000000000000000FA ++:1046C00000000000000000000000000000000000EA ++:1046D00000000000000000000000000000000000DA ++:1046E00000000000000000000000000000000000CA ++:1046F00000000000000000000000000000000000BA ++:1047000000000000000000000000000000000000A9 ++:104710000000000000000000000000000000000099 ++:104720000000000000000000000000000000000089 ++:104730000000000000000000000000000000000079 ++:104740000000000000000000000000000000000069 ++:104750000000000000000000000000000000000059 ++:104760000000000000000000000000000000000049 ++:104770000000000000000000000000000000000039 ++:104780000000000000000000000000000000000029 ++:104790000000000000000000000000000000000019 ++:1047A0000000000000000000000000000000000009 ++:1047B00000000000000000000000000000000000F9 ++:1047C00000000000000000000000000000000000E9 ++:1047D00000000000000000000000000000000000D9 ++:1047E00000000000000000000000000000000000C9 ++:1047F00000000000000000000000000000000000B9 ++:1048000000000000000000000000000000000000A8 ++:104810000000000000000000000000000000000098 ++:104820000000000000000000000000000000000088 ++:104830000000000000000000000000000000000078 ++:104840000000000000000000000000000000000068 ++:104850000000000000000000000000000000000058 ++:104860000000000000000000000000000000000048 ++:104870000000000000000000000000000000000038 ++:104880000000000000000000000000000000000028 ++:104890000000000000000000000000000000000018 ++:1048A0000000000000000000000000000000000008 ++:1048B00000000000000000000000000000000000F8 ++:1048C00000000000000000000000000000000000E8 ++:1048D00000000000000000000000000000000000D8 ++:1048E00000000000000000000000000000000000C8 ++:1048F00000000000000000000000000000000000B8 ++:1049000000000000000000000000000000000000A7 ++:104910000000000000000000000000000000000097 ++:104920000000000000000000000000000000000087 ++:104930000000000000000000000000000000000077 ++:104940000000000000000000000000000000000067 ++:104950000000000000000000000000000000000057 ++:104960000000000000000000000000000000000047 ++:104970000000000000000000000000000000000037 ++:104980000000000000000000000000000000000027 ++:104990000000000000000000000000000000000017 ++:1049A0000000000000000000000000000000000007 ++:1049B00000000000000000000000000000000000F7 ++:1049C00000000000000000000000000000000000E7 ++:1049D00000000000000000000000000000000000D7 ++:1049E00000000000000000000000000000000000C7 ++:1049F00000000000000000000000000000000000B7 ++:104A000000000000000000000000000000000000A6 ++:104A10000000000000000000000000000000000096 ++:104A20000000000000000000000000000000000086 ++:104A30000000000000000000000000000000000076 ++:104A40000000000000000000000000000000000066 ++:104A50000000000000000000000000000000000056 ++:104A60000000000000000000000000000000000046 ++:104A70000000000000000000000000000000000036 ++:104A80000000000000000000000000000000000026 ++:104A90000000000000000000000000000000000016 ++:104AA0000000000000000000000000000000000006 ++:104AB00000000000000000000000000000000000F6 ++:104AC00000000000000000000000000000000000E6 ++:104AD00000000000000000000000000000000000D6 ++:104AE00000000000000000000000000000000000C6 ++:104AF00000000000000000000000000000000000B6 ++:104B000000000000000000000000000000000000A5 ++:104B10000000000000000000000000000000000095 ++:104B20000000000000000000000000000000000085 ++:104B30000000000000000000000000000000000075 ++:104B40000000000000000000000000000000000065 ++:104B50000000000000000000000000000000000055 ++:104B60000000000000000000000000000000000045 ++:104B70000000000000000000000000000000000035 ++:104B80000000000000000000000000000000000025 ++:104B90000000000000000000000000000000000015 ++:104BA0000000000000000000000000000000000005 ++:104BB00000000000000000000000000000000000F5 ++:104BC00000000000000000000000000000000000E5 ++:104BD00000000000000000000000000000000000D5 ++:104BE00000000000000000000000000000000000C5 ++:104BF00000000000000000000000000000000000B5 ++:104C000000000000000000000000000000000000A4 ++:104C10000000000000000000000000000000000094 ++:104C20000000000000000000000000000000000084 ++:104C30000000000000000000000000000000000074 ++:104C40000000000000000000000000000000000064 ++:104C50000000000000000000000000000000000054 ++:104C60000000000000000000000000000000000044 ++:104C70000000000000000000000000000000000034 ++:104C80000000000000000000000000000000000024 ++:104C90000000000000000000000000000000000014 ++:104CA0000000000000000000000000000000000004 ++:104CB00000000000000000000000000000000000F4 ++:104CC00000000000000000000000000000000000E4 ++:104CD00000000000000000000000000000000000D4 ++:104CE00000000000000000000000000000000000C4 ++:104CF00000000000000000000000000000000000B4 ++:104D000000000000000000000000000000000000A3 ++:104D10000000000000000000000000000000000093 ++:104D20000000000000000000000000000000000083 ++:104D30000000000000000000000000000000000073 ++:104D40000000000000000000000000000000000063 ++:104D50000000000000000000000000000000000053 ++:104D60000000000000000000000000000000000043 ++:104D70000000000000000000000000000000000033 ++:104D80000000000000000000000000000000000023 ++:104D90000000000000000000000000000000000013 ++:104DA0000000000000000000000000000000000003 ++:104DB00000000000000000000000000000000000F3 ++:104DC00000000000000000000000000000000000E3 ++:104DD00000000000000000000000000000000000D3 ++:104DE00000000000000000000000000000000000C3 ++:104DF00000000000000000000000000000000000B3 ++:104E000000000000000000000000000000000000A2 ++:104E10000000000000000000000000000000000092 ++:104E20000000000000000000000000000000000082 ++:104E30000000000000000000000000000000000072 ++:104E40000000000000000000000000000000000062 ++:104E50000000000000000000000000000000000052 ++:104E60000000000000000000000000000000000042 ++:104E70000000000000000000000000000000000032 ++:104E80000000000000000000000000000000000022 ++:104E90000000000000000000000000000000000012 ++:104EA0000000000000000000000000000000000002 ++:104EB00000000000000000000000000000000000F2 ++:104EC00000000000000000000000000000000000E2 ++:104ED00000000000000000000000000000000000D2 ++:104EE00000000000000000000000000000000000C2 ++:104EF00000000000000000000000000000000000B2 ++:104F000000000000000000000000000000000000A1 ++:104F10000000000000000000000000000000000091 ++:104F20000000000000000000000000000000000081 ++:104F30000000000000000000000000000000000071 ++:104F40000000000000000000000000000000000061 ++:104F50000000000000000000000000000000000051 ++:104F60000000000000000000000000000000000041 ++:104F70000000000000000000000000000000000031 ++:104F80000000000000000000000000000000000021 ++:104F90000000000000000000000000000000000011 ++:104FA0000000000000000000000000000000000001 ++:104FB00000000000000000000000000000000000F1 ++:104FC00000000000000000000000000000000000E1 ++:104FD00000000000000000000000000000000000D1 ++:104FE00000000000000000000000000000000000C1 ++:104FF00000000000000000000000000000000000B1 ++:1050000000000000000000000000000000000000A0 ++:105010000000000000000000000000000000000090 ++:105020000000000000000000000000000000000080 ++:105030000000000000000000000000000000000070 ++:105040000000000000000000000000000000000060 ++:105050000000000000000000000000000000000050 ++:105060000000000000000000000000000000000040 ++:105070000000000000000000000000000000000030 ++:105080000000000000000000000000000000000020 ++:105090000000000000000000000000000000000010 ++:1050A0000000000000000000000000000000000000 ++:1050B00000000000000000000000000000000000F0 ++:1050C00000000000000000000000000000000000E0 ++:1050D00000000000000000000000000000000000D0 ++:1050E00000000000000000000000000000000000C0 ++:1050F00000000000000000000000000000000000B0 ++:10510000000000000000000000000000000000009F ++:10511000000000000000000000000000000000008F ++:10512000000000000000000000000000000000007F ++:10513000000000000000000000000000000000006F ++:10514000000000000000000000000000000000005F ++:10515000000000000000000000000000000000004F ++:10516000000000000000000000000000000000003F ++:10517000000000000000000000000000000000002F ++:10518000000000000000000000000000000000001F ++:10519000000000000000000000000000000000000F ++:1051A00000000000000000000000000000000000FF ++:1051B00000000000000000000000000000000000EF ++:1051C00000000000000000000000000000000000DF ++:1051D00000000000000000000000000000000000CF ++:1051E00000000000000000000000000000000000BF ++:1051F00000000000000000000000000000000000AF ++:10520000000000000000000000000000000000009E ++:10521000000000000000000000000000000000008E ++:10522000000000000000000000000000000000007E ++:10523000000000000000000000000000000000006E ++:10524000000000000000000000000000000000005E ++:10525000000000000000000000000000000000004E ++:10526000000000000000000000000000000000003E ++:10527000000000000000000000000000000000002E ++:10528000000000000000000000000000000000001E ++:10529000000000000000000000000000000000000E ++:1052A00000000000000000000000000000000000FE ++:1052B00000000000000000000000000000000000EE ++:1052C00000000000000000000000000000000000DE ++:1052D00000000000000000000000000000000000CE ++:1052E00000000000000000000000000000000000BE ++:1052F00000000000000000000000000000000000AE ++:10530000000000000000000000000000000000009D ++:10531000000000000000000000000000000000008D ++:10532000000000000000000000000000000000007D ++:10533000000000000000000000000000000000006D ++:10534000000000000000000000000000000000005D ++:10535000000000000000000000000000000000004D ++:10536000000000000000000000000000000000003D ++:10537000000000000000000000000000000000002D ++:10538000000000000000000000000000000000001D ++:10539000000000000000000000000000000000000D ++:1053A00000000000000000000000000000000000FD ++:1053B00000000000000000000000000000000000ED ++:1053C00000000000000000000000000000000000DD ++:1053D00000000000000000000000000000000000CD ++:1053E00000000000000000000000000000000000BD ++:1053F00000000000000000000000000000000000AD ++:10540000000000000000000000000000000000009C ++:10541000000000000000000000000000000000008C ++:10542000000000000000000000000000000000007C ++:10543000000000000000000000000000000000006C ++:10544000000000000000000000000000000000005C ++:10545000000000000000000000000000000000004C ++:10546000000000000000000000000000000000003C ++:10547000000000000000000000000000000000002C ++:10548000000000000000000000000000000000001C ++:10549000000000000000000000000000000000000C ++:1054A00000000000000000000000000000000000FC ++:1054B00000000000000000000000000000000000EC ++:1054C00000000000000000000000000000000000DC ++:1054D00000000000000000000000000000000000CC ++:1054E00000000000000000000000000000000000BC ++:1054F00000000000000000000000000000000000AC ++:10550000000000000000000000000000000000009B ++:10551000000000000000000000000000000000008B ++:10552000000000000000000000000000000000007B ++:10553000000000000000000000000000000000006B ++:10554000000000000000000000000000000000005B ++:10555000000000000000000000000000000000004B ++:10556000000000000000000000000000000000003B ++:10557000000000000000000000000000000000002B ++:10558000000000000000000000000000000000001B ++:10559000000000000000000000000000000000000B ++:1055A00000000000000000000000000000000000FB ++:1055B00000000000000000000000000000000000EB ++:1055C00000000000000000000000000000000000DB ++:1055D00000000000000000000000000000000000CB ++:1055E00000000000000000000000000000000000BB ++:1055F00000000000000000000000000000000000AB ++:10560000000000000000000000000000000000009A ++:10561000000000000000000000000000000000008A ++:10562000000000000000000000000000000000007A ++:10563000000000000000000000000000000000006A ++:10564000000000000000000000000000000000005A ++:10565000000000000000000000000000000000004A ++:10566000000000000000000000000000000000003A ++:10567000000000000000000000000000000000002A ++:10568000000000000000000000000000000000001A ++:10569000000000000000000000000000000000000A ++:1056A00000000000000000000000000000000000FA ++:1056B00000000000000000000000000000000000EA ++:1056C00000000000000000000000000000000000DA ++:1056D00000000000000000000000000000000000CA ++:1056E00000000000000000000000000000000000BA ++:1056F00000000000000000000000000000000000AA ++:105700000000000000000000000000000000000099 ++:105710000000000000000000000000000000000089 ++:105720000000000000000000000000000000000079 ++:105730000000000000000000000000000000000069 ++:105740000000000000000000000000000000000059 ++:105750000000000000000000000000000000000049 ++:105760000000000000000000000000000000000039 ++:105770000000000000000000000000000000000029 ++:105780000000000000000000000000000000000019 ++:105790000000000000000000000000000000000009 ++:1057A00000000000000000000000000000000000F9 ++:1057B00000000000000000000000000000000000E9 ++:1057C00000000000000000000000000000000000D9 ++:1057D00000000000000000000000000000000000C9 ++:1057E00000000000000000000000000000000000B9 ++:1057F00000000000000000000000000000000000A9 ++:105800000000000000000000000000000000000098 ++:105810000000000000000000000000000000000088 ++:105820000000000000000000000000000000000078 ++:105830000000000000000000000000000000000068 ++:105840000000000000000000000000000000000058 ++:105850000000000000000000000000000000000048 ++:105860000000000000000000000000000000000038 ++:105870000000000000000000000000000000000028 ++:105880000000000000000000000000000000000018 ++:105890000000000000000000000000000000000008 ++:1058A00000000000000000000000000000000000F8 ++:1058B00000000000000000000000000000000000E8 ++:1058C00000000000000000000000000000000000D8 ++:1058D00000000000000000000000000000000000C8 ++:1058E00000000000000000000000000000000000B8 ++:1058F00000000000000000000000000000000000A8 ++:105900000000000000000000000000000000000097 ++:105910000000000000000000000000000000000087 ++:105920000000000000000000000000000000000077 ++:105930000000000000000000000000000000000067 ++:105940000000000000000000000000000000000057 ++:105950000000000000000000000000000000000047 ++:105960000000000000000000000000000000000037 ++:105970000000000000000000000000000000000027 ++:105980000000000000000000000000000000000017 ++:105990000000000000000000000000000000000007 ++:1059A00000000000000000000000000000000000F7 ++:1059B00000000000000000000000000000000000E7 ++:1059C00000000000000000000000000000000000D7 ++:1059D00000000000000000000000000000000000C7 ++:1059E00000000000000000000000000000000000B7 ++:1059F00000000000000000000000000000000000A7 ++:105A00000000000000000000000000000000000096 ++:105A10000000000000000000000000000000000086 ++:105A20000000000000000000000000000000000076 ++:105A30000000000000000000000000000000000066 ++:105A40000000000000000000000000000000000056 ++:105A50000000000000000000000000000000000046 ++:105A60000000000000000000000000000000000036 ++:105A70000000000000000000000000000000000026 ++:105A80000000000000000000000000000000000016 ++:105A90000000000000000000000000000000000006 ++:105AA00000000000000000000000000000000000F6 ++:105AB00000000000000000000000000000000000E6 ++:105AC00000000000000000000000000000000000D6 ++:105AD00000000000000000000000000000000000C6 ++:105AE00000000000000000000000000000000000B6 ++:105AF00000000000000000000000000000000000A6 ++:105B00000000000000000000000000000000000095 ++:105B10000000000000000000000000000000000085 ++:105B20000000000000000000000000000000000075 ++:105B30000000000000000000000000000000000065 ++:105B40000000000000000000000000000000000055 ++:105B50000000000000000000000000000000000045 ++:105B60000000000000000000000000000000000035 ++:105B70000000000000000000000000000000000025 ++:105B80000000000000000000000000000000000015 ++:105B90000000000000000000000000000000000005 ++:105BA00000000000000000000000000000000000F5 ++:105BB00000000000000000000000000000000000E5 ++:105BC00000000000000000000000000000000000D5 ++:105BD00000000000000000000000000000000000C5 ++:105BE00000000000000000000000000000000000B5 ++:105BF00000000000000000000000000000000000A5 ++:105C00000000000000000000000000000000000094 ++:105C10000000000000000000000000000000000084 ++:105C20000000000000000000000000000000000074 ++:105C30000000000000000000000000000000000064 ++:105C40000000000000000000000000000000000054 ++:105C50000000000000000000000000000000000044 ++:105C60000000000000000000000000000000000034 ++:105C70000000000000000000000000000000000024 ++:105C80000000000000000000000000000000000014 ++:105C90000000000000000000000000000000000004 ++:105CA00000000000000000000000000000000000F4 ++:105CB00000000000000000000000000000000000E4 ++:105CC00000000000000000000000000000000000D4 ++:105CD00000000000000000000000000000000000C4 ++:105CE00000000000000000000000000000000000B4 ++:105CF00000000000000000000000000000000000A4 ++:105D00000000000000000000000000000000000093 ++:105D10000000000000000000000000000000000083 ++:105D20000000000000000000000000000000000073 ++:105D30000000000000000000000000000000000063 ++:105D40000000000000000000000000000000000053 ++:105D50000000000000000000000000000000000043 ++:105D60000000000000000000000000000000000033 ++:105D70000000000000000000000000000000000023 ++:105D80000000000000000000000000000000000013 ++:105D90000000000000000000000000000000000003 ++:105DA00000000000000000000000000000000000F3 ++:105DB00000000000000000000000000000000000E3 ++:105DC00000000000000000000000000000000000D3 ++:105DD00000000000000000000000000000000000C3 ++:105DE00000000000000000000000000000000000B3 ++:105DF00000000000000000000000000000000000A3 ++:105E00000000000000000000000000000000000092 ++:105E10000000000000000000000000000000000082 ++:105E2000000000000000000000000000000050B072 ++:105E3000C308080027989C5000C308000027B89C9E ++:105E400050804300000834001C3080C1060000115F ++:105E50000C000090C004003F3FA0443020C0CF0F92 ++:105E60000B042C080090000108000324804000016E ++:105E7000C0000920102000304002080100008430DA ++:105E8000F3034002333FD010509003010234041456 ++:105E9000A44000020D0105310400001000C0000301 ++:105EA0001000EC300000C00E01000C00007002C0B9 ++:105EB000010302240C3000C10A00000B1040003026 ++:105EC000400208033024C43080C30A00000B0CC019 ++:105ED0009010C3040000110C0000900001040003A6 ++:105EE0002480408000C00009201008F0A0820B0C24 ++:105EF0002526100850A3C2C00009030CF000B0C052 ++:105F0000000C09318C000010C2040000110C684024 ++:105F10004000C0000420008C90000201010003102A ++:105F200040003042020804021008F012830B0C25D6 ++:105F30002B100850A3C2400009030C40B00200C05F ++:105F4000020410000C9000C2000C09310CE0B002F9 ++:105F500000C0022305008430000140040300002437 ++:105F6000400002C000092010400030400208040830 ++:105F7000000C90000281000F30B8C050A1038100D6 ++:105F8000352A8C009030C0800E000B0CC09010C3DE ++:105F9000040000218C500010C10000000910800096 ++:105FA00030010104002310200030400208040210D8 ++:105FB00008F080820B0C1523100850A3C24800097A ++:105FC000030C40B00200C0020410000C9000C2009C ++:105FD0000C09310CE0B00200C00223010084300043 ++:105FE00000400403000024400002C00009201040CB ++:105FF00000304002080408000C90000281003F308D ++:10600000B8C05023038100352A8C0C001000010019 ++:106010001B00240C3032000D0135268C00007082EC ++:106020008F0935060C000070C200000300D4185020 ++:1060300093000000000000000000000000000000CD ++:106040000000000000000000000000000000000050 ++:106050000000000000000000000000000000000040 ++:106060000000000000000000000000000000000030 ++:106070000000000000000000000000000000000020 ++:106080000000000000000000000000000000000010 ++:106090000000000000000000000000000000000000 ++:1060A00000000000000000000000000000000000F0 ++:1060B00000000000000000000000000000000000E0 ++:1060C00000000000000000000000000000000000D0 ++:1060D00000000000000000000000000000000000C0 ++:1060E00000000000000000000000000000000000B0 ++:1060F00000000000000000000000000000000000A0 ++:10610000000000000000000000000000000000008F ++:10611000000000000000000000000000000000007F ++:10612000000000000000000000000000000000006F ++:10613000000000000000000000000000000000005F ++:10614000000000000000000000000000000000004F ++:10615000000000000000000000000000000000003F ++:10616000000000000000000000000000000000002F ++:10617000000000000000000000000000000000001F ++:10618000000000000000000000000000000000000F ++:1061900000000000000000000000000000000000FF ++:1061A00000000000000000000000000000000000EF ++:1061B00000000000000000000000000000000000DF ++:1061C00000000000000000000000000000000000CF ++:1061D00000000000000000000000000000000000BF ++:1061E00000000000000000000000000000000000AF ++:1061F000000000000000000000000000000000009F ++:10620000000000000000000000000000000000008E ++:10621000000000000000000000000000000000007E ++:10622000000000000000000000000000000000006E ++:10623000000000000000000000000000000000005E ++:10624000000000000000000000000000000000004E ++:10625000000000000000000000000000000000003E ++:10626000000000000000000000000000000000002E ++:10627000000000000000000000000000000000001E ++:10628000000000000000000000000000000000000E ++:1062900000000000000000000000000000000000FE ++:1062A000000000000000000000000000000050009E ++:1062B00000000000000000000000000000000000DE ++:1062C00000000000000000000000000000000000CE ++:1062D00000000000000000000000000000000000BE ++:1062E00000000000000000000000000000000000AE ++:1062F000000000000000000000000000000000009E ++:10630000000000000000000000000000000000008D ++:10631000000000000000000000000000000000007D ++:10632000000000000000000000000000000000006D ++:10633000000000000000000000000000000000005D ++:10634000000000000000000000000000000000004D ++:10635000000000000000000000000000000000003D ++:10636000000000000000000000000000000000002D ++:10637000000000000000000000000000000000001D ++:10638000000000000000000000000000000000000D ++:1063900000000000000000000000000000000000FD ++:1063A00000000000000000000000000000000000ED ++:1063B00000000000000000000000000000000000DD ++:1063C00000000000000000000000000000000000CD ++:1063D00000000000000000000000000000000000BD ++:1063E00000000000000000000000000000000000AD ++:1063F000000000000000000000000000000000009D ++:10640000000000000000000000000000000000008C ++:10641000000000000000000000000000000000007C ++:10642000000000000000000000000000000000006C ++:10643000000000000000000000000000000000005C ++:10644000000000000000000000000000000000004C ++:10645000000000000000000000000000000000003C ++:10646000000000000000000000000000000000002C ++:10647000000000000000000000000000000000001C ++:10648000000000000000000000000000000000000C ++:1064900000000000000000000000000000000000FC ++:1064A00000000000000000000000000000000000EC ++:1064B00000000000000000000000000000000000DC ++:1064C00000000000000000000000000000000000CC ++:1064D00000000000000000000000000000000000BC ++:1064E00000000000000000000000000000000000AC ++:1064F000000000000000000000000000000000009C ++:10650000000000000000000000000000000000008B ++:10651000000000000000000000000000000000007B ++:10652000000000000000000000000000000000006B ++:10653000000000000000000000000000000000005B ++:10654000000000000000000000000000000000004B ++:10655000000000000000000000000000000000003B ++:10656000000000000000000000000000000000002B ++:10657000000000000000000000000000000000001B ++:10658000000000000000000000000000000000000B ++:1065900000000000000000000000000000000000FB ++:1065A00000000000000000000000000000000000EB ++:1065B00000000000000000000000000000000000DB ++:1065C00000000000000000000000000000000000CB ++:1065D00000000000000000000000000000000000BB ++:1065E00000000000000000000000000000000000AB ++:1065F000000000000000000000000000000000009B ++:10660000000000000000000000000000000000008A ++:10661000000000000000000000000000000000007A ++:10662000000000000000000000000000000000006A ++:10663000000000000000000000000000000000005A ++:10664000000000000000000000000000000000004A ++:10665000000000000000000000000000000000003A ++:10666000000000000000000000000000000000002A ++:10667000000000000000000000000000000000001A ++:10668000000000000000000000000000000000000A ++:1066900000000000000000000000000000000000FA ++:1066A00000000000000000000000000000000000EA ++:1066B00000000000000000000000000000000000DA ++:1066C00000000000000000000000000000000000CA ++:1066D00000000000000000000000000000000000BA ++:1066E00000000000000000000000000000000000AA ++:1066F000000000000000000000000000000000009A ++:106700000000000000000000000000000000000089 ++:106710000000000000000000000000000000000079 ++:106720000000000000000000000000000000000069 ++:106730000000000000000000000000000000000059 ++:106740000000000000000000000000000000000049 ++:106750000000000000000000000000000000000039 ++:106760000000000000000000000000000000000029 ++:106770000000000000000000000000000000000019 ++:106780000000000000000000000000000000000009 ++:1067900000000000000000000000000000000000F9 ++:1067A00000000000000000000000000000000000E9 ++:1067B00000000000000000000000000000000000D9 ++:1067C00000000000000000000000000000000000C9 ++:1067D00000000000000000000000000000000000B9 ++:1067E00000000000000000000000000000000000A9 ++:1067F0000000000000000000000000000000000099 ++:106800000000000000000000000000000000000088 ++:106810000000000000000000000000000000000078 ++:106820000000000000000000000000000000000068 ++:106830000000000000000000000000000000000058 ++:106840000000000000000000000000000000000048 ++:106850000000000000000000000000000000000038 ++:106860000000000000000000000000000000000028 ++:106870000000000000000000000000000000000018 ++:106880000000000000000000000000000000000008 ++:1068900000000000000000000000000000000000F8 ++:1068A00000000000000000000000000000000000E8 ++:1068B00000000000000000000000000000000000D8 ++:1068C00000000000000000000000000000000000C8 ++:1068D00000000000000000000000000000000000B8 ++:1068E00000000000000000000000000000000000A8 ++:1068F0000000000000000000000000000000000098 ++:106900000000000000000000000000000000000087 ++:106910000000000000000000000000000000000077 ++:106920000000000000000000000000000000000067 ++:106930000000000000000000000000000000000057 ++:106940000000000000000000000000000000000047 ++:106950000000000000000000000000000000000037 ++:106960000000000000000000000000000000000027 ++:106970000000000000000000000000000000000017 ++:106980000000000000000000000000000000000007 ++:1069900000000000000000000000000000000000F7 ++:1069A00000000000000000000000000000000000E7 ++:1069B00000000000000000000000000000000000D7 ++:1069C00000000000000000000000000000000000C7 ++:1069D00000000000000000000000000000000000B7 ++:1069E00000000000000000000000000000000000A7 ++:1069F0000000000000000000000000000000000097 ++:106A00000000000000000000000000000000000086 ++:106A10000000000000000000000000000000000076 ++:106A20000000000000000000000000000000000066 ++:106A30000000000000000000000000000000000056 ++:106A40000000000000000000000000000000000046 ++:106A50000000000000000000000000000000000036 ++:106A60000000000000000000000000000000000026 ++:106A70000000000000000000000000000000000016 ++:106A80000000000000000000000000000000000006 ++:106A900000000000000000000000000000000000F6 ++:106AA00000000000000000000000000000000000E6 ++:106AB00000000000000000000000000000000000D6 ++:106AC00000000000000000000000000000000000C6 ++:106AD00000000000000000000000000000000000B6 ++:106AE00000000000000000000000000000000000A6 ++:106AF0000000000000000000000000000000000096 ++:106B00000000000000000000000000000000000085 ++:106B10000000000000000000000000000000000075 ++:106B20000000000000000000000000000000000065 ++:106B30000000000000000000000000000000000055 ++:106B40000000000000000000000000000000000045 ++:106B50000000000000000000000000000000000035 ++:106B60000000000000000000000000000000000025 ++:106B70000000000000000000000000000000000015 ++:106B80000000000000000000000000000000000005 ++:106B900000000000000000000000000000000000F5 ++:106BA00000000000000000000000000000000000E5 ++:106BB00000000000000000000000000000000000D5 ++:106BC00000000000000000000000000000000000C5 ++:106BD00000000000000000000000000000000000B5 ++:106BE00000000000000000000000000000000000A5 ++:106BF0000000000000000000000000000000000095 ++:106C00000000000000000000000000000000000084 ++:106C10000000000000000000000000000000000074 ++:106C20000000000000000000000000000000000064 ++:106C30000000000000000000000000000000000054 ++:106C40000000000000000000000000000000000044 ++:106C50000000000000000000000000000000000034 ++:106C60000000000000000000000000000000000024 ++:106C70000000000000000000000000000000000014 ++:106C80000000000000000000000000000000000004 ++:106C900000000000000000000000000000000000F4 ++:106CA00000000000000000000000000000000000E4 ++:106CB00000000000000000000000000000000000D4 ++:106CC00000000000000000000000000000000000C4 ++:106CD00000000000000000000000000000000000B4 ++:106CE00000000000000000000000000000000000A4 ++:106CF0000000000000000000000000000000000094 ++:106D00000000000000000000000000000000000083 ++:106D10000000000000000000000000000000000073 ++:106D20000000000000000000000000000000000063 ++:106D30000000000000000000000000000000000053 ++:106D40000000000000000000000000000000000043 ++:106D50000000000000000000000000000000000033 ++:106D60000000000000000000000000000000000023 ++:106D70000000000000000000000000000000000013 ++:106D80000000000000000000000000000000000003 ++:106D900000000000000000000000000000000000F3 ++:106DA00000000000000000000000000000000000E3 ++:106DB00000000000000000000000000000000000D3 ++:106DC00000000000000000000000000000000000C3 ++:106DD00000000000000000000000000000000000B3 ++:106DE00000000000000000000000000000000000A3 ++:106DF0000000000000000000000000000000000093 ++:106E00000000000000000000000000000000000082 ++:106E10000000000000000000000000000000000072 ++:106E20000000000000000000000000000000000062 ++:106E30000000000000000000000000000000000052 ++:106E40000000000000000000000000000000000042 ++:106E50000000000000000000000000000000000032 ++:106E60000000000000000000000000000000000022 ++:106E70000000000000000000000000000000000012 ++:106E80000000000000000000000000000000000002 ++:106E900000000000000000000000000000000000F2 ++:106EA00000000000000000000000000000000000E2 ++:106EB00000000000000000000000000000000000D2 ++:106EC00000000000000000000000000000000000C2 ++:106ED00000000000000000000000000000000000B2 ++:106EE00000000000000000000000000000000000A2 ++:106EF0000000000000000000000000000000000092 ++:106F00000000000000000000000000000000000081 ++:106F10000000000000000000000000000000000071 ++:106F20000000000000000000000000000000000061 ++:106F30000000000000000000000000000000000051 ++:106F40000000000000000000000000000000000041 ++:106F50000000000000000000000000000000000031 ++:106F60000000000000000000000000000000000021 ++:106F70000000000000000000000000000000000011 ++:106F80000000000000000000000000000000000001 ++:106F900000000000000000000000000000000000F1 ++:106FA00000000000000000000000000000000000E1 ++:106FB00000000000000000000000000000000000D1 ++:106FC00000000000000000000000000000000000C1 ++:106FD00000000000000000000000000000000000B1 ++:106FE00000000000000000000000000000000000A1 ++:106FF0000000000000000000000000000000000091 ++:107000000000000000000000000000000000000080 ++:107010000000000000000000000000000000000070 ++:107020000000000000000000000000000000000060 ++:107030000000000000000000000000000000000050 ++:107040000000000000000000000000000000000040 ++:107050000000000000000000000000000000000030 ++:107060000000000000000000000000000000000020 ++:107070000000000000000000000000000000000010 ++:107080000000000000000000000000000000000000 ++:1070900000000000000000000000000000000000F0 ++:1070A00000000000000000000000000000000000E0 ++:1070B00000000000000000000000000000000000D0 ++:1070C00000000000000000000000000000000000C0 ++:1070D00000000000000000000000000000000000B0 ++:1070E00000000000000000000000000000000000A0 ++:1070F0000000000000000000000000000000000090 ++:10710000000000000000000000000000000000007F ++:10711000000000000000000000000000000000006F ++:10712000000000000000000000000000000000005F ++:10713000000000000000000000000000000000004F ++:10714000000000000000000000000000000000003F ++:10715000000000000000000000000000000000002F ++:10716000000000000000000000000000000000001F ++:10717000000000000000000000000000000000000F ++:1071800000000000000000000000000000000000FF ++:1071900000000000000000000000000000000000EF ++:1071A00000000000000000000000000000000000DF ++:1071B00000000000000000000000000000000000CF ++:1071C00000000000000000000000000000000000BF ++:1071D00000000000000000000000000000000000AF ++:1071E000000000000000000000000000000000009F ++:1071F000000000000000000000000000000000008F ++:10720000000000000000000000000000000000007E ++:10721000000000000000000000000000000000006E ++:10722000000000000000000000000000000000005E ++:10723000000000000000000000000000000000004E ++:10724000000000000000000000000000000000003E ++:10725000000000000000000000000000000000002E ++:10726000000000000000000000000000000000001E ++:10727000000000000000000000000000000000000E ++:1072800000000000000000000000000000000000FE ++:1072900000000000000000000000000000000000EE ++:1072A00000000000000000000000000000000000DE ++:1072B00000000000000000000000000000000000CE ++:1072C00000000000000000000000000000000000BE ++:1072D00000000000000000000000000000000000AE ++:1072E000000000000000000000000000000000009E ++:1072F000000000000000000000000000000000008E ++:10730000000000000000000000000000000000007D ++:10731000000000000000000000000000000000006D ++:10732000000000000000000000000000000000005D ++:10733000000000000000000000000000000000004D ++:10734000000000000000000000000000000000003D ++:10735000000000000000000000000000000000002D ++:10736000000000000000000000000000000000001D ++:10737000000000000000000000000000000000000D ++:1073800000000000000000000000000000000000FD ++:1073900000000000000000000000000000000000ED ++:1073A00000000000000000000000000000000000DD ++:1073B00000000000000000000000000000000000CD ++:1073C00000000000000000000000000000000000BD ++:1073D00000000000000000000000000000000000AD ++:1073E000000000000000000000000000000000009D ++:1073F000000000000000000000000000000000008D ++:10740000000000000000000000000000000000007C ++:10741000000000000000000000000000000000006C ++:10742000000000000000000000000000000000005C ++:10743000000000000000000000000000000000004C ++:10744000000000000000000000000000000000003C ++:10745000000000000000000000000000000000002C ++:10746000000000000000000000000000000000001C ++:10747000000000000000000000000000000000000C ++:1074800000000000000000000000000000000000FC ++:1074900000000000000000000000000000000000EC ++:1074A00000000000000000000000000000000000DC ++:1074B00000000000000000000000000000000000CC ++:1074C00000000000000000000000000000000000BC ++:1074D00000000000000000000000000000000000AC ++:1074E000000000000000000000000000000000009C ++:1074F000000000000000000000000000000000008C ++:10750000000000000000000000000000000000007B ++:10751000000000000000000000000000000000006B ++:10752000000000000000000000000000000000005B ++:10753000000000000000000000000000000000004B ++:10754000000000000000000000000000000000003B ++:10755000000000000000000000000000000000002B ++:10756000000000000000000000000000000000001B ++:10757000000000000000000000000000000000000B ++:1075800000000000000000000000000000000000FB ++:1075900000000000000000000000000000000000EB ++:1075A00000000000000000000000000000000000DB ++:1075B00000000000000000000000000000000000CB ++:1075C00000000000000000000000000000000000BB ++:1075D00000000000000000000000000000000000AB ++:1075E000000000000000000000000000000000009B ++:1075F000000000000000000000000000000000008B ++:10760000000000000000000000000000000000007A ++:10761000000000000000000000000000000000006A ++:10762000000000000000000000000000000000005A ++:10763000000000000000000000000000000000004A ++:10764000000000000000000000000000000000003A ++:10765000000000000000000000000000000000002A ++:10766000000000000000000000000000000000001A ++:10767000000000000000000000000000000000000A ++:1076800000000000000000000000000000000000FA ++:1076900000000000000000000000000000000000EA ++:1076A00000000000000000000000000000000000DA ++:1076B00000000000000000000000000000000000CA ++:1076C00000000000000000000000000000000000BA ++:1076D00000000000000000000000000000000000AA ++:1076E000000000000000000000000000000000009A ++:1076F000000000000000000000000000000000008A ++:107700000000000000000000000000000000000079 ++:107710000000000000000000000000000000000069 ++:107720000000000000000000000000000000000059 ++:107730000000000000000000000000000000000049 ++:107740000000000000000000000000000000000039 ++:107750000000000000000000000000000000000029 ++:107760000000000000000000000000000000000019 ++:107770000000000000000000000000000000000009 ++:1077800000000000000000000000000000000000F9 ++:1077900000000000000000000000000000000000E9 ++:1077A00000000000000000000000000000000000D9 ++:1077B00000000000000000000000000000000000C9 ++:1077C00000000000000000000000000000000000B9 ++:1077D00000000000000000000000000000000000A9 ++:1077E0000000000000000000000000000000000099 ++:1077F0000000000000000000000000000000000089 ++:107800000000000000000000000000000000000078 ++:107810000000000000000000000000000000000068 ++:107820000000000000000000000000000000000058 ++:107830000000000000000000000000000000000048 ++:107840000000000000000000000000000000000038 ++:107850000000000000000000000000000000000028 ++:107860000000000000000000000000000000000018 ++:107870000000000000000000000000000000000008 ++:1078800000000000000000000000000000000000F8 ++:1078900000000000000000000000000000000000E8 ++:1078A00000000000000000000000000000000000D8 ++:1078B00000000000000000000000000000000000C8 ++:1078C00000000000000000000000000000000000B8 ++:1078D00000000000000000000000000000000000A8 ++:1078E0000000000000000000000000000000000098 ++:1078F0000000000000000000000000000000000088 ++:107900000000000000000000000000000000000077 ++:107910000000000000000000000000000000000067 ++:107920000000000000000000000000000000000057 ++:107930000000000000000000000000000000000047 ++:107940000000000000000000000000000000000037 ++:107950000000000000000000000000000000000027 ++:107960000000000000000000000000000000000017 ++:107970000000000000000000000000000000000007 ++:1079800000000000000000000000000000000000F7 ++:1079900000000000000000000000000000000000E7 ++:1079A00000000000000000000000000000000000D7 ++:1079B00000000000000000000000000000000000C7 ++:1079C00000000000000000000000000000000000B7 ++:1079D00000000000000000000000000000000000A7 ++:1079E0000000000000000000000000000000000097 ++:1079F0000000000000000000000000000000000087 ++:107A00000000000000000000000000000000000076 ++:107A10000000000000000000000000000000000066 ++:107A20000000000000000000000000000000000056 ++:107A30000000000000000000000000000000000046 ++:107A40000000000000000000000000000000000036 ++:107A50000000000000000000000000000000000026 ++:107A60000000000000000000000000000000000016 ++:107A70000000000000000000000000000000000006 ++:107A800000000000000000000000000000000000F6 ++:107A900000000000000000000000000000000000E6 ++:107AA00000000000000000000000000000000000D6 ++:107AB00000000000000000000000000000000000C6 ++:107AC00000000000000000000000000000000000B6 ++:107AD00000000000000000000000000000000000A6 ++:107AE0000000000000000000000000000000000096 ++:107AF0000000000000000000000000000000000086 ++:107B00000000000000000000000000000000000075 ++:107B10000000000000000000000000000000000065 ++:107B20000000000000000000000000000000000055 ++:107B30000000000000000000000000000000000045 ++:107B40000000000000000000000000000000000035 ++:107B50000000000000000000000000000000000025 ++:107B60000000000000000000000000000000000015 ++:107B70000000000000000000000000000000000005 ++:107B800000000000000000000000000000000000F5 ++:107B900000000000000000000000000000000000E5 ++:107BA00000000000000000000000000000000000D5 ++:107BB00000000000000000000000000000000000C5 ++:107BC00000000000000000000000000000000000B5 ++:107BD00000000000000000000000000000000000A5 ++:107BE0000000000000000000000000000000000095 ++:107BF0000000000000000000000000000000000085 ++:107C00000000000000000000000000000000000074 ++:107C10000000000000000000000000000000000064 ++:107C20000000000000000000000000000000000054 ++:107C30000000000000000000000000000000000044 ++:107C40000000000000000000000000000000000034 ++:107C50000000000000000000000000000000000024 ++:107C60000000000000000000000000000000000014 ++:107C70000000000000000000000000000000000004 ++:107C800000000000000000000000000000000000F4 ++:107C900000000000000000000000000000000000E4 ++:107CA00000000000000000000000000000000000D4 ++:107CB00000000000000000000000000000000000C4 ++:107CC00000000000000000000000000000000000B4 ++:107CD00000000000000000000000000000000000A4 ++:107CE0000000000000000000000000000000000094 ++:107CF0000000000000000000000000000000000084 ++:107D00000000000000000000000000000000000073 ++:107D10000000000000000000000000000000000063 ++:107D20000000000000000000000000000000000053 ++:107D30000000000000000000000000000000000043 ++:107D40000000000000000000000000000000000033 ++:107D50000000000000000000000000000000000023 ++:107D60000000000000000000000000000000000013 ++:107D70000000000000000000000000000000000003 ++:107D800000000000000000000000000000000000F3 ++:107D900000000000000000000000000000000000E3 ++:107DA00000000000000000000000000000000000D3 ++:107DB00000000000000000000000000000000000C3 ++:107DC00000000000000000000000000000000000B3 ++:107DD00000000000000000000000000000000000A3 ++:107DE0000000000000000000000000000000000093 ++:107DF0000000000000000000000000000000000083 ++:107E00000000000000000000000000000000000072 ++:107E10000000000000000000000000000000000062 ++:107E20000000000000000000000000000000000052 ++:107E30000000000000000000000000000000000042 ++:107E40000000000000000000000000000000000032 ++:107E50000000000000000000000000000000000022 ++:107E60000000000000000000000000000000000012 ++:107E70000000000000000000000000000000000002 ++:107E800000000000000000000000000000000000F2 ++:107E900000000000000000000000000000000000E2 ++:107EA00000000000000000000000000000000000D2 ++:107EB00000000000000000000000000000000000C2 ++:107EC00000000000000000000000000000000000B2 ++:107ED00000000000000000000000000000000000A2 ++:107EE0000000000000000000000000000000000092 ++:107EF0000000000000000000000000000000000082 ++:107F00000000000000000000000000000000000071 ++:107F10000000000000000000000000000000000061 ++:107F20000000000000000000000000000000000051 ++:107F30000000000000000000000000000000000041 ++:107F40000000000000000000000000000000000031 ++:107F50000000000000000000000000000000000021 ++:107F60000000000000000000000000000000000011 ++:107F70000000000000000000000000000000000001 ++:107F800000000000000000000000000000000000F1 ++:107F900000000000000000000000000000000000E1 ++:107FA00000000000000000000000000000000000D1 ++:107FB00000000000000000000000000000000000C1 ++:107FC00000000000000000000000000000000000B1 ++:107FD00000000000000000000000000000000000A1 ++:107FE0000000000000000000000000000000000091 ++:107FF0000000000000000000000000000000000081 ++:108000000000000000000000000000000000000070 ++:108010000000000000000000000000000000000060 ++:108020000000000000000000000000000000000050 ++:108030000000000000000000000000000000000040 ++:108040000000000000000000000000000000000030 ++:108050000000000000000000000000000000000020 ++:108060000000000000000000000000000000000010 ++:108070000000000000000000000000000000000000 ++:1080800000000000000000000000000000000000F0 ++:1080900000000000000000000000000000000000E0 ++:1080A00000000000000000000000000000000000D0 ++:1080B00000000000000000000000000000000000C0 ++:1080C00000000000000000000000000000000000B0 ++:1080D00000000000000000000000000000000000A0 ++:1080E0000000000000000000000000000000000090 ++:1080F0000000000000000000000000000000000080 ++:10810000000000000000000000000000000000006F ++:10811000000000000000000000000000000000005F ++:10812000000000000000000000000000000000004F ++:10813000000000000000000000000000000000003F ++:10814000000000000000000000000000000000002F ++:10815000000000000000000000000000000000001F ++:10816000000000000000000000000000000000000F ++:1081700000000000000000000000000000000000FF ++:1081800000000000000000000000000000000000EF ++:1081900000000000000000000000000000000000DF ++:1081A00000000000000000000000000000000000CF ++:1081B00000000000000000000000000000000000BF ++:1081C00000000000000000000000000000000000AF ++:1081D000000000000000000000000000000000009F ++:1081E000000000000000000000000000000000008F ++:1081F000000000000000000000000000000000007F ++:10820000000000000000000000000000000000006E ++:10821000000000000000000000000000000000005E ++:10822000000000000000000000000000000000004E ++:10823000000000000000000000000000000000003E ++:10824000000000000000000000000000000000002E ++:10825000000000000000000000000000000000001E ++:10826000000000000000000000000000000000000E ++:1082700000000000000000000000000000000000FE ++:1082800000000000000000000000000000000000EE ++:1082900000000000000000000000000000000000DE ++:1082A00000000000000000000000000000000000CE ++:1082B00000000000000000000000000000000000BE ++:1082C00000000000000000000000000000000000AE ++:1082D000000000000000000000000000000000009E ++:1082E000000000000000000000000000000000008E ++:1082F000000000000000000000000000000000007E ++:10830000000000000000000000000000000000006D ++:10831000000000000000000000000000000000005D ++:10832000000000000000000000000000000000004D ++:10833000000000000000000000000000000000003D ++:10834000000000000000000000000000000000002D ++:10835000000000000000000000000000000000001D ++:10836000000000000000000000000000000000000D ++:1083700000000000000000000000000000000000FD ++:1083800000000000000000000000000000000000ED ++:1083900000000000000000000000000000000000DD ++:1083A00000000000000000000000000000000000CD ++:1083B00000000000000000000000000000000000BD ++:1083C00000000000000000000000000000000000AD ++:1083D000000000000000000000000000000000009D ++:1083E000000000000000000000000000000000008D ++:1083F000000000000000000000000000000000007D ++:10840000000000000000000000000000000000006C ++:10841000000000000000000000000000000000005C ++:10842000000000000000000000000000000000004C ++:10843000000000000000000000000000000000003C ++:10844000000000000000000000000000000000002C ++:10845000000000000000000000000000000000001C ++:10846000000000000000000000000000000000000C ++:1084700000000000000000000000000000000000FC ++:1084800000000000000000000000000000000000EC ++:1084900000000000000000000000000000000000DC ++:1084A00000000000000000000000000000000000CC ++:1084B00000000000000000000000000000000000BC ++:1084C00000000000000000000000000000000000AC ++:1084D000000000000000000000000000000000009C ++:1084E000000000000000000000000000000000008C ++:1084F000000000000000000000000000000000007C ++:10850000000000000000000000000000000000006B ++:10851000000000000000000000000000000000005B ++:10852000000000000000000000000000000000004B ++:10853000000000000000000000000000000000003B ++:10854000000000000000000000000000000000002B ++:10855000000000000000000000000000000000001B ++:10856000000000000000000000000000000000000B ++:1085700000000000000000000000000000000000FB ++:1085800000000000000000000000000000000000EB ++:1085900000000000000000000000000000000000DB ++:1085A00000000000000000000000000000000000CB ++:1085B00000000000000000000000000000000000BB ++:1085C00000000000000000000000000000000000AB ++:1085D000000000000000000000000000000000009B ++:1085E000000000000000000000000000000000008B ++:1085F000000000000000000000000000000000007B ++:10860000000000000000000000000000000000006A ++:10861000000000000000000000000000000000005A ++:10862000000000000000000000000000000000004A ++:10863000000000000000000000000000000000003A ++:10864000000000000000000000000000000000002A ++:10865000000000000000000000000000000000001A ++:10866000000000000000000000000000000000000A ++:1086700000000000000000000000000000000000FA ++:1086800000000000000000000000000000000000EA ++:1086900000000000000000000000000000000000DA ++:1086A00000000000000000000000000000000000CA ++:1086B00000000000000000000000000000000000BA ++:1086C00000000000000000000000000000000000AA ++:1086D000000000000000000000000000000000009A ++:1086E000000000000000000000000000000000008A ++:1086F000000000000000000000000000000000007A ++:108700000000000000000000000000000000000069 ++:108710000000000000000000000000000000000059 ++:108720000000000000000000000000000000000049 ++:108730000000000000000000000000000000000039 ++:108740000000000000000000000000000000000029 ++:108750000000000000000000000000000000000019 ++:108760000000000000000000000000000000000009 ++:1087700000000000000000000000000000000000F9 ++:1087800000000000000000000000000000000000E9 ++:1087900000000000000000000000000000000000D9 ++:1087A00000000000000000000000000000000000C9 ++:1087B00000000000000000000000000000000000B9 ++:1087C00000000000000000000000000000000000A9 ++:1087D0000000000000000000000000000000000099 ++:1087E0000000000000000000000000000000000089 ++:1087F0000000000000000000000000000000000079 ++:108800000000000000000000000000000000000068 ++:108810000000000000000000000000000000000058 ++:108820000000000000000000000000000000000048 ++:108830000000000000000000000000000000000038 ++:108840000000000000000000000000000000000028 ++:108850000000000000000000000000000000000018 ++:108860000000000000000000000000000000000008 ++:1088700000000000000000000000000000000000F8 ++:1088800000000000000000000000000000000000E8 ++:1088900000000000000000000000000000000000D8 ++:1088A00000000000000000000000000000000000C8 ++:1088B00000000000000000000000000000000000B8 ++:1088C00000000000000000000000000000000000A8 ++:1088D0000000000000000000000000000000000098 ++:1088E0000000000000000000000000000000000088 ++:1088F0000000000000000000000000000000000078 ++:108900000000000000000000000000000000000067 ++:108910000000000000000000000000000000000057 ++:108920000000000000000000000000000000000047 ++:108930000000000000000000000000000000000037 ++:108940000000000000000000000000000000000027 ++:108950000000000000000000000000000000000017 ++:108960000000000000000000000000000000000007 ++:1089700000000000000000000000000000000000F7 ++:1089800000000000000000000000000000000000E7 ++:1089900000000000000000000000000000000000D7 ++:1089A00000000000000000000000000000000000C7 ++:1089B00000000000000000000000000000000000B7 ++:1089C00000000000000000000000000000000000A7 ++:1089D0000000000000000000000000000000000097 ++:1089E0000000000000000000000000000000000087 ++:1089F0000000000000000000000000000000000077 ++:108A00000000000000000000000000000000000066 ++:108A10000000000000000000000000000000000056 ++:108A20000000000000000000000000000000000046 ++:108A30000000000000000000000000000000000036 ++:108A40000000000000000000000000000000000026 ++:108A50000000000000000000000000000000000016 ++:108A60000000000000000000000000000000000006 ++:108A700000000000000000000000000000000000F6 ++:108A800000000000000000000000000000000000E6 ++:108A900000000000000000000000000000000000D6 ++:108AA00000000000000000000000000000000000C6 ++:108AB00000000000000000000000000000000000B6 ++:108AC00000000000000000000000000000000000A6 ++:108AD0000000000000000000000000000000000096 ++:108AE0000000000000000000000000000000000086 ++:108AF0000000000000000000000000000000000076 ++:108B00000000000000000000000000000000000065 ++:108B10000000000000000000000000000000000055 ++:108B20000000000000000000000000000000000045 ++:108B30000000000000000000000000000000000035 ++:108B40000000000000000000000000000000000025 ++:108B50000000000000000000000000000000000015 ++:108B60000000000000000000000000000000000005 ++:108B700000000000000000000000000000000000F5 ++:108B800000000000000000000000000000000000E5 ++:108B900000000000000000000000000000000000D5 ++:108BA00000000000000000000000000000000000C5 ++:108BB00000000000000000000000000000000000B5 ++:108BC00000000000000000000000000000000000A5 ++:108BD0000000000000000000000000000000000095 ++:108BE000000050B0C308080027989C5000C308003C ++:108BF0000027B89C50804300000834001C3080C11E ++:108C0000060000110C000090C004003F3FA044305B ++:108C100020C0CF0F0B042C08009000010800032493 ++:108C200080400001C00009201020003040020801EF ++:108C300000008430F3034002333FD0105090030112 ++:108C400002340414A44000020D0105310400001098 ++:108C500000C000031000EC300000C00E01000C004A ++:108C6000007002C0010302240C3000C10A00000B96 ++:108C700010400030400208033024C43080C30A0092 ++:108C8000000B0CC09010C3040000110C00009000F9 ++:108C9000010400032480408000C00009201008F077 ++:108CA000A0820B0C2526100850A3C2C00009030C9B ++:108CB000F000B0C0000C09318C000010C2040000AC ++:108CC000110C68404000C0000420008C900002019C ++:108CD0000100031040003042020804021008F012A4 ++:108CE000830B0C252B100850A3C2400009030C4035 ++:108CF000B00200C0020410000C9000C2000C093148 ++:108D00000CE0B00200C002230500843000014004E2 ++:108D100003000024400002C0000920104000304041 ++:108D200002080408000C90000281000F30B8C05007 ++:108D3000A1038100352A8C009030C0800E000B0CFE ++:108D4000C09010C3040000218C500010C10000002E ++:108D5000091080003001010400231020003040027F ++:108D60000804021008F080820B0C1523100850A391 ++:108D7000C2480009030C40B00200C0020410000CFD ++:108D80009000C2000C09310CE0B00200C0022301C7 ++:108D90000084300000400403000024400002C000B2 ++:108DA0000920104000304002080408000C90000226 ++:108DB00081003F30B8C05023038100352A8C0C005D ++:108DC000100001001B00240C3032000D0135268CF0 ++:108DD000000070828F0935060C000070C20000038D ++:108DE00000D41850930000000000000000000000B4 ++:108DF0000000000000000000000000000000000073 ++:108E00000000000000000000000000000000000062 ++:108E10000000000000000000000000000000000052 ++:108E20000000000000000000000000000000000042 ++:108E30000000000000000000000000000000000032 ++:108E40000000000000000000000000000000000022 ++:108E50000000000000000000000000000000000012 ++:108E60000000000000000000000000000000000002 ++:108E700000000000000000000000000000000000F2 ++:108E800000000000000000000000000000000000E2 ++:108E900000000000000000000000000000000000D2 ++:108EA00000000000000000000000000000000000C2 ++:108EB00000000000000000000000000000000000B2 ++:108EC00000000000000000000000000000000000A2 ++:108ED0000000000000000000000000000000000092 ++:108EE0000000000000000000000000000000000082 ++:108EF0000000000000000000000000000000000072 ++:108F00000000000000000000000000000000000061 ++:108F10000000000000000000000000000000000051 ++:108F20000000000000000000000000000000000041 ++:108F30000000000000000000000000000000000031 ++:108F40000000000000000000000000000000000021 ++:108F50000000000000000000000000000000000011 ++:108F60000000000000000000000000000000000001 ++:108F700000000000000000000000000000000000F1 ++:108F800000000000000000000000000000000000E1 ++:108F900000000000000000000000000000000000D1 ++:108FA00000000000000000000000000000000000C1 ++:108FB00000000000000000000000000000000000B1 ++:108FC00000000000000000000000000000000000A1 ++:108FD0000000000000000000000000000000000091 ++:108FE0000000000000000000000000000000000081 ++:108FF0000000000000000000000000000000000071 ++:109000000000000000000000000000000000000060 ++:109010000000000000000000000000000000000050 ++:109020000000000000000000000000000000000040 ++:109030000000000000000000000000000000000030 ++:109040000000000000000000000000000000000020 ++:109050000000000000000000000000000000000010 ++:1090600000005000000000000000000000000000B0 ++:1090700000000000000000000000000000000000F0 ++:1090800000000000000000000000000000000000E0 ++:1090900000000000000000000000000000000000D0 ++:1090A00000000000000000000000000000000000C0 ++:1090B00000000000000000000000000000000000B0 ++:1090C00000000000000000000000000000000000A0 ++:1090D0000000000000000000000000000000000090 ++:1090E0000000000000000000000000000000000080 ++:1090F0000000000000000000000000000000000070 ++:10910000000000000000000000000000000000005F ++:10911000000000000000000000000000000000004F ++:10912000000000000000000000000000000000003F ++:10913000000000000000000000000000000000002F ++:10914000000000000000000000000000000000001F ++:10915000000000000000000000000000000000000F ++:1091600000000000000000000000000000000000FF ++:1091700000000000000000000000000000000000EF ++:1091800000000000000000000000000000000000DF ++:1091900000000000000000000000000000000000CF ++:1091A00000000000000000000000000000000000BF ++:1091B00000000000000000000000000000000000AF ++:1091C000000000000000000000000000000000009F ++:1091D000000000000000000000000000000000008F ++:1091E000000000000000000000000000000000007F ++:1091F000000000000000000000000000000000006F ++:10920000000000000000000000000000000000005E ++:10921000000000000000000000000000000000004E ++:10922000000000000000000000000000000000003E ++:10923000000000000000000000000000000000002E ++:10924000000000000000000000000000000000001E ++:10925000000000000000000000000000000000000E ++:1092600000000000000000000000000000000000FE ++:1092700000000000000000000000000000000000EE ++:1092800000000000000000000000000000000000DE ++:1092900000000000000000000000000000000000CE ++:1092A00000000000000000000000000000000000BE ++:1092B00000000000000000000000000000000000AE ++:1092C000000000000000000000000000000000009E ++:1092D000000000000000000000000000000000008E ++:1092E000000000000000000000000000000000007E ++:1092F000000000000000000000000000000000006E ++:10930000000000000000000000000000000000005D ++:10931000000000000000000000000000000000004D ++:10932000000000000000000000000000000000003D ++:10933000000000000000000000000000000000002D ++:10934000000000000000000000000000000000001D ++:10935000000000000000000000000000000000000D ++:1093600000000000000000000000000000000000FD ++:1093700000000000000000000000000000000000ED ++:1093800000000000000000000000000000000000DD ++:1093900000000000000000000000000000000000CD ++:1093A00000000000000000000000000000000000BD ++:1093B00000000000000000000000000000000000AD ++:1093C000000000000000000000000000000000009D ++:1093D000000000000000000000000000000000008D ++:1093E000000000000000000000000000000000007D ++:1093F000000000000000000000000000000000006D ++:10940000000000000000000000000000000000005C ++:10941000000000000000000000000000000000004C ++:10942000000000000000000000000000000000003C ++:10943000000000000000000000000000000000002C ++:10944000000000000000000000000000000000001C ++:10945000000000000000000000000000000000000C ++:1094600000000000000000000000000000000000FC ++:1094700000000000000000000000000000000000EC ++:1094800000000000000000000000000000000000DC ++:1094900000000000000000000000000000000000CC ++:1094A00000000000000000000000000000000000BC ++:1094B00000000000000000000000000000000000AC ++:1094C000000000000000000000000000000000009C ++:1094D000000000000000000000000000000000008C ++:1094E000000000000000000000000000000000007C ++:1094F000000000000000000000000000000000006C ++:10950000000000000000000000000000000000005B ++:10951000000000000000000000000000000000004B ++:10952000000000000000000000000000000000003B ++:10953000000000000000000000000000000000002B ++:10954000000000000000000000000000000000001B ++:10955000000000000000000000000000000000000B ++:1095600000000000000000000000000000000000FB ++:1095700000000000000000000000000000000000EB ++:1095800000000000000000000000000000000000DB ++:1095900000000000000000000000000000000000CB ++:1095A00000000000000000000000000000000000BB ++:1095B00000000000000000000000000000000000AB ++:1095C000000000000000000000000000000000009B ++:1095D000000000000000000000000000000000008B ++:1095E000000000000000000000000000000000007B ++:1095F000000000000000000000000000000000006B ++:10960000000000000000000000000000000000005A ++:10961000000000000000000000000000000000004A ++:10962000000000000000000000000000000000003A ++:10963000000000000000000000000000000000002A ++:10964000000000000000000000000000000000001A ++:10965000000000000000000000000000000000000A ++:1096600000000000000000000000000000000000FA ++:1096700000000000000000000000000000000000EA ++:1096800000000000000000000000000000000000DA ++:1096900000000000000000000000000000000000CA ++:1096A00000000000000000000000000000000000BA ++:1096B00000000000000000000000000000000000AA ++:1096C000000000000000000000000000000000009A ++:1096D000000000000000000000000000000000008A ++:1096E000000000000000000000000000000000007A ++:1096F000000000000000000000000000000000006A ++:109700000000000000000000000000000000000059 ++:109710000000000000000000000000000000000049 ++:109720000000000000000000000000000000000039 ++:109730000000000000000000000000000000000029 ++:109740000000000000000000000000000000000019 ++:109750000000000000000000000000000000000009 ++:1097600000000000000000000000000000000000F9 ++:1097700000000000000000000000000000000000E9 ++:1097800000000000000000000000000000000000D9 ++:1097900000000000000000000000000000000000C9 ++:1097A00000000000000000000000000000000000B9 ++:1097B00000000000000000000000000000000000A9 ++:1097C0000000000000000000000000000000000099 ++:1097D0000000000000000000000000000000000089 ++:1097E0000000000000000000000000000000000079 ++:1097F0000000000000000000000000000000000069 ++:109800000000000000000000000000000000000058 ++:109810000000000000000000000000000000000048 ++:109820000000000000000000000000000000000038 ++:109830000000000000000000000000000000000028 ++:109840000000000000000000000000000000000018 ++:109850000000000000000000000000000000000008 ++:1098600000000000000000000000000000000000F8 ++:1098700000000000000000000000000000000000E8 ++:1098800000000000000000000000000000000000D8 ++:1098900000000000000000000000000000000000C8 ++:1098A00000000000000000000000000000000000B8 ++:1098B00000000000000000000000000000000000A8 ++:1098C0000000000000000000000000000000000098 ++:1098D0000000000000000000000000000000000088 ++:1098E0000000000000000000000000000000000078 ++:1098F0000000000000000000000000000000000068 ++:109900000000000000000000000000000000000057 ++:109910000000000000000000000000000000000047 ++:109920000000000000000000000000000000000037 ++:109930000000000000000000000000000000000027 ++:109940000000000000000000000000000000000017 ++:109950000000000000000000000000000000000007 ++:1099600000000000000000000000000000000000F7 ++:1099700000000000000000000000000000000000E7 ++:1099800000000000000000000000000000000000D7 ++:1099900000000000000000000000000000000000C7 ++:1099A00000000000000000000000000000000000B7 ++:1099B00000000000000000000000000000000000A7 ++:1099C0000000000000000000000000000000000097 ++:1099D0000000000000000000000000000000000087 ++:1099E0000000000000000000000000000000000077 ++:1099F0000000000000000000000000000000000067 ++:109A00000000000000000000000000000000000056 ++:109A10000000000000000000000000000000000046 ++:109A20000000000000000000000000000000000036 ++:109A30000000000000000000000000000000000026 ++:109A40000000000000000000000000000000000016 ++:109A50000000000000000000000000000000000006 ++:109A600000000000000000000000000000000000F6 ++:109A700000000000000000000000000000000000E6 ++:109A800000000000000000000000000000000000D6 ++:109A900000000000000000000000000000000000C6 ++:109AA00000000000000000000000000000000000B6 ++:109AB00000000000000000000000000000000000A6 ++:109AC0000000000000000000000000000000000096 ++:109AD0000000000000000000000000000000000086 ++:109AE0000000000000000000000000000000000076 ++:109AF0000000000000000000000000000000000066 ++:109B00000000000000000000000000000000000055 ++:109B10000000000000000000000000000000000045 ++:109B20000000000000000000000000000000000035 ++:109B30000000000000000000000000000000000025 ++:109B40000000000000000000000000000000000015 ++:109B50000000000000000000000000000000000005 ++:109B600000000000000000000000000000000000F5 ++:109B700000000000000000000000000000000000E5 ++:109B800000000000000000000000000000000000D5 ++:109B900000000000000000000000000000000000C5 ++:109BA00000000000000000000000000000000000B5 ++:109BB00000000000000000000000000000000000A5 ++:109BC0000000000000000000000000000000000095 ++:109BD0000000000000000000000000000000000085 ++:109BE0000000000000000000000000000000000075 ++:109BF0000000000000000000000000000000000065 ++:109C00000000000000000000000000000000000054 ++:109C10000000000000000000000000000000000044 ++:109C20000000000000000000000000000000000034 ++:109C30000000000000000000000000000000000024 ++:109C40000000000000000000000000000000000014 ++:109C50000000000000000000000000000000000004 ++:109C600000000000000000000000000000000000F4 ++:109C700000000000000000000000000000000000E4 ++:109C800000000000000000000000000000000000D4 ++:109C900000000000000000000000000000000000C4 ++:109CA00000000000000000000000000000000000B4 ++:109CB00000000000000000000000000000000000A4 ++:109CC0000000000000000000000000000000000094 ++:109CD0000000000000000000000000000000000084 ++:109CE0000000000000000000000000000000000074 ++:109CF0000000000000000000000000000000000064 ++:109D00000000000000000000000000000000000053 ++:109D10000000000000000000000000000000000043 ++:109D20000000000000000000000000000000000033 ++:109D30000000000000000000000000000000000023 ++:109D40000000000000000000000000000000000013 ++:109D50000000000000000000000000000000000003 ++:109D600000000000000000000000000000000000F3 ++:109D700000000000000000000000000000000000E3 ++:109D800000000000000000000000000000000000D3 ++:109D900000000000000000000000000000000000C3 ++:109DA00000000000000000000000000000000000B3 ++:109DB00000000000000000000000000000000000A3 ++:109DC0000000000000000000000000000000000093 ++:109DD0000000000000000000000000000000000083 ++:109DE0000000000000000000000000000000000073 ++:109DF0000000000000000000000000000000000063 ++:109E00000000000000000000000000000000000052 ++:109E10000000000000000000000000000000000042 ++:109E20000000000000000000000000000000000032 ++:109E30000000000000000000000000000000000022 ++:109E40000000000000000000000000000000000012 ++:109E50000000000000000000000000000000000002 ++:109E600000000000000000000000000000000000F2 ++:109E700000000000000000000000000000000000E2 ++:109E800000000000000000000000000000000000D2 ++:109E900000000000000000000000000000000000C2 ++:109EA00000000000000000000000000000000000B2 ++:109EB00000000000000000000000000000000000A2 ++:109EC0000000000000000000000000000000000092 ++:109ED0000000000000000000000000000000000082 ++:109EE0000000000000000000000000000000000072 ++:109EF0000000000000000000000000000000000062 ++:109F00000000000000000000000000000000000051 ++:109F10000000000000000000000000000000000041 ++:109F20000000000000000000000000000000000031 ++:109F30000000000000000000000000000000000021 ++:109F40000000000000000000000000000000000011 ++:109F50000000000000000000000000000000000001 ++:109F600000000000000000000000000000000000F1 ++:109F700000000000000000000000000000000000E1 ++:109F800000000000000000000000000000000000D1 ++:109F900000000000000000000000000000000000C1 ++:109FA00000000000000000000000000000000000B1 ++:109FB00000000000000000000000000000000000A1 ++:109FC0000000000000000000000000000000000091 ++:109FD0000000000000000000000000000000000081 ++:109FE0000000000000000000000000000000000071 ++:109FF0000000000000000000000000000000000061 ++:10A000000000000000000000000000000000000050 ++:10A010000000000000000000000000000000000040 ++:10A020000000000000000000000000000000000030 ++:10A030000000000000000000000000000000000020 ++:10A040000000000000000000000000000000000010 ++:10A050000000000000000000000000000000000000 ++:10A0600000000000000000000000000000000000F0 ++:10A0700000000000000000000000000000000000E0 ++:10A0800000000000000000000000000000000000D0 ++:10A0900000000000000000000000000000000000C0 ++:10A0A00000000000000000000000000000000000B0 ++:10A0B00000000000000000000000000000000000A0 ++:10A0C0000000000000000000000000000000000090 ++:10A0D0000000000000000000000000000000000080 ++:10A0E0000000000000000000000000000000000070 ++:10A0F0000000000000000000000000000000000060 ++:10A10000000000000000000000000000000000004F ++:10A11000000000000000000000000000000000003F ++:10A12000000000000000000000000000000000002F ++:10A13000000000000000000000000000000000001F ++:10A14000000000000000000000000000000000000F ++:10A1500000000000000000000000000000000000FF ++:10A1600000000000000000000000000000000000EF ++:10A1700000000000000000000000000000000000DF ++:10A1800000000000000000000000000000000000CF ++:10A1900000000000000000000000000000000000BF ++:10A1A00000000000000000000000000000000000AF ++:10A1B000000000000000000000000000000000009F ++:10A1C000000000000000000000000000000000008F ++:10A1D000000000000000000000000000000000007F ++:10A1E000000000000000000000000000000000006F ++:10A1F000000000000000000000000000000000005F ++:10A20000000000000000000000000000000000004E ++:10A21000000000000000000000000000000000003E ++:10A22000000000000000000000000000000000002E ++:10A23000000000000000000000000000000000001E ++:10A24000000000000000000000000000000000000E ++:10A2500000000000000000000000000000000000FE ++:10A2600000000000000000000000000000000000EE ++:10A2700000000000000000000000000000000000DE ++:10A2800000000000000000000000000000000000CE ++:10A2900000000000000000000000000000000000BE ++:10A2A00000000000000000000000000000000000AE ++:10A2B000000000000000000000000000000000009E ++:10A2C000000000000000000000000000000000008E ++:10A2D000000000000000000000000000000000007E ++:10A2E000000000000000000000000000000000006E ++:10A2F000000000000000000000000000000000005E ++:10A30000000000000000000000000000000000004D ++:10A31000000000000000000000000000000000003D ++:10A32000000000000000000000000000000000002D ++:10A33000000000000000000000000000000000001D ++:10A34000000000000000000000000000000000000D ++:10A3500000000000000000000000000000000000FD ++:10A3600000000000000000000000000000000000ED ++:10A3700000000000000000000000000000000000DD ++:10A3800000000000000000000000000000000000CD ++:10A3900000000000000000000000000000000000BD ++:10A3A00000000000000000000000000000000000AD ++:10A3B000000000000000000000000000000000009D ++:10A3C000000000000000000000000000000000008D ++:10A3D000000000000000000000000000000000007D ++:10A3E000000000000000000000000000000000006D ++:10A3F000000000000000000000000000000000005D ++:10A40000000000000000000000000000000000004C ++:10A41000000000000000000000000000000000003C ++:10A42000000000000000000000000000000000002C ++:10A43000000000000000000000000000000000001C ++:10A44000000000000000000000000000000000000C ++:10A4500000000000000000000000000000000000FC ++:10A4600000000000000000000000000000000000EC ++:10A4700000000000000000000000000000000000DC ++:10A4800000000000000000000000000000000000CC ++:10A4900000000000000000000000000000000000BC ++:10A4A00000000000000000000000000000000000AC ++:10A4B000000000000000000000000000000000009C ++:10A4C000000000000000000000000000000000008C ++:10A4D000000000000000000000000000000000007C ++:10A4E000000000000000000000000000000000006C ++:10A4F000000000000000000000000000000000005C ++:10A50000000000000000000000000000000000004B ++:10A51000000000000000000000000000000000003B ++:10A52000000000000000000000000000000000002B ++:10A53000000000000000000000000000000000001B ++:10A54000000000000000000000000000000000000B ++:10A5500000000000000000000000000000000000FB ++:10A5600000000000000000000000000000000000EB ++:10A5700000000000000000000000000000000000DB ++:10A5800000000000000000000000000000000000CB ++:10A5900000000000000000000000000000000000BB ++:10A5A00000000000000000000000000000000000AB ++:10A5B000000000000000000000000000000000009B ++:10A5C000000000000000000000000000000000008B ++:10A5D000000000000000000000000000000000007B ++:10A5E000000000000000000000000000000000006B ++:10A5F000000000000000000000000000000000005B ++:10A60000000000000000000000000000000000004A ++:10A61000000000000000000000000000000000003A ++:10A62000000000000000000000000000000000002A ++:10A63000000000000000000000000000000000001A ++:10A64000000000000000000000000000000000000A ++:10A6500000000000000000000000000000000000FA ++:10A6600000000000000000000000000000000000EA ++:10A6700000000000000000000000000000000000DA ++:10A6800000000000000000000000000000000000CA ++:10A6900000000000000000000000000000000000BA ++:10A6A00000000000000000000000000000000000AA ++:10A6B000000000000000000000000000000000009A ++:10A6C000000000000000000000000000000000008A ++:10A6D000000000000000000000000000000000007A ++:10A6E000000000000000000000000000000000006A ++:10A6F000000000000000000000000000000000005A ++:10A700000000000000000000000000000000000049 ++:10A710000000000000000000000000000000000039 ++:10A720000000000000000000000000000000000029 ++:10A730000000000000000000000000000000000019 ++:10A740000000000000000000000000000000000009 ++:10A7500000000000000000000000000000000000F9 ++:10A7600000000000000000000000000000000000E9 ++:10A7700000000000000000000000000000000000D9 ++:10A7800000000000000000000000000000000000C9 ++:10A7900000000000000000000000000000000000B9 ++:10A7A00000000000000000000000000000000000A9 ++:10A7B0000000000000000000000000000000000099 ++:10A7C0000000000000000000000000000000000089 ++:10A7D0000000000000000000000000000000000079 ++:10A7E0000000000000000000000000000000000069 ++:10A7F0000000000000000000000000000000000059 ++:10A800000000000000000000000000000000000048 ++:10A810000000000000000000000000000000000038 ++:10A820000000000000000000000000000000000028 ++:10A830000000000000000000000000000000000018 ++:10A840000000000000000000000000000000000008 ++:10A8500000000000000000000000000000000000F8 ++:10A8600000000000000000000000000000000000E8 ++:10A8700000000000000000000000000000000000D8 ++:10A8800000000000000000000000000000000000C8 ++:10A8900000000000000000000000000000000000B8 ++:10A8A00000000000000000000000000000000000A8 ++:10A8B0000000000000000000000000000000000098 ++:10A8C0000000000000000000000000000000000088 ++:10A8D0000000000000000000000000000000000078 ++:10A8E0000000000000000000000000000000000068 ++:10A8F0000000000000000000000000000000000058 ++:10A900000000000000000000000000000000000047 ++:10A910000000000000000000000000000000000037 ++:10A920000000000000000000000000000000000027 ++:10A930000000000000000000000000000000000017 ++:10A940000000000000000000000000000000000007 ++:10A9500000000000000000000000000000000000F7 ++:10A9600000000000000000000000000000000000E7 ++:10A9700000000000000000000000000000000000D7 ++:10A9800000000000000000000000000000000000C7 ++:10A9900000000000000000000000000000000000B7 ++:10A9A00000000000000000000000000000000000A7 ++:10A9B0000000000000000000000000000000000097 ++:10A9C0000000000000000000000000000000000087 ++:10A9D0000000000000000000000000000000000077 ++:10A9E0000000000000000000000000000000000067 ++:10A9F0000000000000000000000000000000000057 ++:10AA00000000000000000000000000000000000046 ++:10AA10000000000000000000000000000000000036 ++:10AA20000000000000000000000000000000000026 ++:10AA30000000000000000000000000000000000016 ++:10AA40000000000000000000000000000000000006 ++:10AA500000000000000000000000000000000000F6 ++:10AA600000000000000000000000000000000000E6 ++:10AA700000000000000000000000000000000000D6 ++:10AA800000000000000000000000000000000000C6 ++:10AA900000000000000000000000000000000000B6 ++:10AAA00000000000000000000000000000000000A6 ++:10AAB0000000000000000000000000000000000096 ++:10AAC0000000000000000000000000000000000086 ++:10AAD0000000000000000000000000000000000076 ++:10AAE0000000000000000000000000000000000066 ++:10AAF0000000000000000000000000000000000056 ++:10AB00000000000000000000000000000000000045 ++:10AB10000000000000000000000000000000000035 ++:10AB20000000000000000000000000000000000025 ++:10AB30000000000000000000000000000000000015 ++:10AB40000000000000000000000000000000000005 ++:10AB500000000000000000000000000000000000F5 ++:10AB600000000000000000000000000000000000E5 ++:10AB700000000000000000000000000000000000D5 ++:10AB800000000000000000000000000000000000C5 ++:10AB900000000000000000000000000000000000B5 ++:10ABA00000000000000000000000000000000000A5 ++:10ABB0000000000000000000000000000000000095 ++:10ABC0000000000000000000000000000000000085 ++:10ABD0000000000000000000000000000000000075 ++:10ABE0000000000000000000000000000000000065 ++:10ABF0000000000000000000000000000000000055 ++:10AC00000000000000000000000000000000000044 ++:10AC10000000000000000000000000000000000034 ++:10AC20000000000000000000000000000000000024 ++:10AC30000000000000000000000000000000000014 ++:10AC40000000000000000000000000000000000004 ++:10AC500000000000000000000000000000000000F4 ++:10AC600000000000000000000000000000000000E4 ++:10AC700000000000000000000000000000000000D4 ++:10AC800000000000000000000000000000000000C4 ++:10AC900000000000000000000000000000000000B4 ++:10ACA00000000000000000000000000000000000A4 ++:10ACB0000000000000000000000000000000000094 ++:10ACC0000000000000000000000000000000000084 ++:10ACD0000000000000000000000000000000000074 ++:10ACE0000000000000000000000000000000000064 ++:10ACF0000000000000000000000000000000000054 ++:10AD00000000000000000000000000000000000043 ++:10AD10000000000000000000000000000000000033 ++:10AD20000000000000000000000000000000000023 ++:10AD30000000000000000000000000000000000013 ++:10AD40000000000000000000000000000000000003 ++:10AD500000000000000000000000000000000000F3 ++:10AD600000000000000000000000000000000000E3 ++:10AD700000000000000000000000000000000000D3 ++:10AD800000000000000000000000000000000000C3 ++:10AD900000000000000000000000000000000000B3 ++:10ADA00000000000000000000000000000000000A3 ++:10ADB0000000000000000000000000000000000093 ++:10ADC0000000000000000000000000000000000083 ++:10ADD0000000000000000000000000000000000073 ++:10ADE0000000000000000000000000000000000063 ++:10ADF0000000000000000000000000000000000053 ++:10AE00000000000000000000000000000000000042 ++:10AE10000000000000000000000000000000000032 ++:10AE20000000000000000000000000000000000022 ++:10AE30000000000000000000000000000000000012 ++:10AE40000000000000000000000000000000000002 ++:10AE500000000000000000000000000000000000F2 ++:10AE600000000000000000000000000000000000E2 ++:10AE700000000000000000000000000000000000D2 ++:10AE800000000000000000000000000000000000C2 ++:10AE900000000000000000000000000000000000B2 ++:10AEA00000000000000000000000000000000000A2 ++:10AEB0000000000000000000000000000000000092 ++:10AEC0000000000000000000000000000000000082 ++:10AED0000000000000000000000000000000000072 ++:10AEE0000000000000000000000000000000000062 ++:10AEF0000000000000000000000000000000000052 ++:10AF00000000000000000000000000000000000041 ++:10AF10000000000000000000000000000000000031 ++:10AF20000000000000000000000000000000000021 ++:10AF30000000000000000000000000000000000011 ++:10AF40000000000000000000000000000000000001 ++:10AF500000000000000000000000000000000000F1 ++:10AF600000000000000000000000000000000000E1 ++:10AF700000000000000000000000000000000000D1 ++:10AF800000000000000000000000000000000000C1 ++:10AF900000000000000000000000000000000000B1 ++:10AFA00000000000000000000000000000000000A1 ++:10AFB0000000000000000000000000000000000091 ++:10AFC0000000000000000000000000000000000081 ++:10AFD0000000000000000000000000000000000071 ++:10AFE0000000000000000000000000000000000061 ++:10AFF0000000000000000000000000000000000051 ++:10B000000000000000000000000000000000000040 ++:10B010000000000000000000000000000000000030 ++:10B020000000000000000000000000000000000020 ++:10B030000000000000000000000000000000000010 ++:10B040000000000000000000000000000000000000 ++:10B0500000000000000000000000000000000000F0 ++:10B0600000000000000000000000000000000000E0 ++:10B0700000000000000000000000000000000000D0 ++:10B0800000000000000000000000000000000000C0 ++:10B0900000000000000000000000000000000000B0 ++:10B0A00000000000000000000000000000000000A0 ++:10B0B0000000000000000000000000000000000090 ++:10B0C0000000000000000000000000000000000080 ++:10B0D0000000000000000000000000000000000070 ++:10B0E0000000000000000000000000000000000060 ++:10B0F0000000000000000000000000000000000050 ++:10B10000000000000000000000000000000000003F ++:10B11000000000000000000000000000000000002F ++:10B12000000000000000000000000000000000001F ++:10B13000000000000000000000000000000000000F ++:10B1400000000000000000000000000000000000FF ++:10B1500000000000000000000000000000000000EF ++:10B1600000000000000000000000000000000000DF ++:10B1700000000000000000000000000000000000CF ++:10B1800000000000000000000000000000000000BF ++:10B1900000000000000000000000000000000000AF ++:10B1A000000000000000000000000000000000009F ++:10B1B000000000000000000000000000000000008F ++:10B1C000000000000000000000000000000000007F ++:10B1D000000000000000000000000000000000006F ++:10B1E000000000000000000000000000000000005F ++:10B1F000000000000000000000000000000000004F ++:10B20000000000000000000000000000000000003E ++:10B21000000000000000000000000000000000002E ++:10B22000000000000000000000000000000000001E ++:10B23000000000000000000000000000000000000E ++:10B2400000000000000000000000000000000000FE ++:10B2500000000000000000000000000000000000EE ++:10B2600000000000000000000000000000000000DE ++:10B2700000000000000000000000000000000000CE ++:10B2800000000000000000000000000000000000BE ++:10B2900000000000000000000000000000000000AE ++:10B2A000000000000000000000000000000000009E ++:10B2B000000000000000000000000000000000008E ++:10B2C000000000000000000000000000000000007E ++:10B2D000000000000000000000000000000000006E ++:10B2E000000000000000000000000000000000005E ++:10B2F000000000000000000000000000000000004E ++:10B30000000000000000000000000000000000003D ++:10B31000000000000000000000000000000000002D ++:10B32000000000000000000000000000000000001D ++:10B33000000000000000000000000000000000000D ++:10B3400000000000000000000000000000000000FD ++:10B3500000000000000000000000000000000000ED ++:10B3600000000000000000000000000000000000DD ++:10B3700000000000000000000000000000000000CD ++:10B3800000000000000000000000000000000000BD ++:10B3900000000000000000000000000000000000AD ++:10B3A000000000000000000000000000000000009D ++:10B3B000000000000000000000000000000000008D ++:10B3C000000000000000000000000000000000007D ++:10B3D000000000000000000000000000000000006D ++:10B3E000000000000000000000000000000000005D ++:10B3F000000000000000000000000000000000004D ++:10B40000000000000000000000000000000000003C ++:10B41000000000000000000000000000000000002C ++:10B42000000000000000000000000000000000001C ++:10B43000000000000000000000000000000000000C ++:10B4400000000000000000000000000000000000FC ++:10B4500000000000000000000000000000000000EC ++:10B4600000000000000000000000000000000000DC ++:10B4700000000000000000000000000000000000CC ++:10B4800000000000000000000000000000000000BC ++:10B4900000000000000000000000000000000000AC ++:10B4A000000000000000000000000000000000009C ++:10B4B000000000000000000000000000000000008C ++:10B4C000000000000000000000000000000000007C ++:10B4D000000000000000000000000000000000006C ++:10B4E000000000000000000000000000000000005C ++:10B4F000000000000000000000000000000000004C ++:10B50000000000000000000000000000000000003B ++:10B51000000000000000000000000000000000002B ++:10B52000000000000000000000000000000000001B ++:10B53000000000000000000000000000000000000B ++:10B5400000000000000000000000000000000000FB ++:10B5500000000000000000000000000000000000EB ++:10B5600000000000000000000000000000000000DB ++:10B5700000000000000000000000000000000000CB ++:10B5800000000000000000000000000000000000BB ++:10B5900000000000000000000000000000000000AB ++:10B5A000000000000000000000000000000000009B ++:10B5B000000000000000000000000000000000008B ++:10B5C000000000000000000000000000000000007B ++:10B5D000000000000000000000000000000000006B ++:10B5E000000000000000000000000000000000005B ++:10B5F000000000000000000000000000000000004B ++:10B60000000000000000000000000000000000003A ++:10B61000000000000000000000000000000000002A ++:10B62000000000000000000000000000000000001A ++:10B63000000000000000000000000000000000000A ++:10B6400000000000000000000000000000000000FA ++:10B6500000000000000000000000000000000000EA ++:10B6600000000000000000000000000000000000DA ++:10B6700000000000000000000000000000000000CA ++:10B6800000000000000000000000000000000000BA ++:10B6900000000000000000000000000000000000AA ++:10B6A000000000000000000000000000000000009A ++:10B6B000000000000000000000000000000000008A ++:10B6C000000000000000000000000000000000007A ++:10B6D000000000000000000000000000000000006A ++:10B6E000000000000000000000000000000000005A ++:10B6F000000000000000000000000000000000004A ++:10B700000000000000000000000000000000000039 ++:10B710000000000000000000000000000000000029 ++:10B720000000000000000000000000000000000019 ++:10B730000000000000000000000000000000000009 ++:10B7400000000000000000000000000000000000F9 ++:10B7500000000000000000000000000000000000E9 ++:10B7600000000000000000000000000000000000D9 ++:10B7700000000000000000000000000000000000C9 ++:10B7800000000000000000000000000000000000B9 ++:10B7900000000000000000000000000000000000A9 ++:10B7A0000000000000000000000000000000000099 ++:10B7B0000000000000000000000000000000000089 ++:10B7C0000000000000000000000000000000000079 ++:10B7D0000000000000000000000000000000000069 ++:10B7E0000000000000000000000000000000000059 ++:10B7F0000000000000000000000000000000000049 ++:10B800000000000000000000000000000000000038 ++:10B810000000000000000000000000000000000028 ++:10B820000000000000000000000000000000000018 ++:10B830000000000000000000000000000000000008 ++:10B8400000000000000000000000000000000000F8 ++:10B8500000000000000000000000000000000000E8 ++:10B8600000000000000000000000000000000000D8 ++:10B8700000000000000000000000000000000000C8 ++:10B8800000000000000000000000000000000000B8 ++:10B8900000000000000000000000000000000000A8 ++:10B8A0000000000000000000000000000000000098 ++:10B8B0000000000000000000000000000000000088 ++:10B8C0000000000000000000000000000000000078 ++:10B8D0000000000000000000000000000000000068 ++:10B8E0000000000000000000000000000000000058 ++:10B8F0000000000000000000000000000000000048 ++:10B900000000000000000000000000000000000037 ++:10B910000000000000000000000000000000000027 ++:10B920000000000000000000000000000000000017 ++:10B930000000000000000000000000000000000007 ++:10B9400000000000000000000000000000000000F7 ++:10B9500000000000000000000000000000000000E7 ++:10B9600000000000000000000000000000000000D7 ++:10B9700000000000000000000000000000000000C7 ++:10B9800000000000000000000000000000000000B7 ++:10B990000000000000004140C7001040088801403E ++:10B9A0000180040052884820228488180000480042 ++:10B9B000B22002880800000800200D0000000200EC ++:10B9C0000800200080000002004800C00080000045 ++:10B9D0000200080020008000000200080020108003 ++:10B9E00009110254005001420235C0000008002035 ++:10B9F0000080000002000800200080000002000813 ++:10BA0000002010014402080A002821A240881222C6 ++:10BA10002C80B000C202080B20246000B4C20208CF ++:10BA20000931017403000D0000000200080020002D ++:10BA300080000002000800200080000002000800D2 ++:10BA40002000800000020008002010C04402080A04 ++:10BA5000002821A2808912020008300013803700DC ++:10BA600000000800200080000002000800204004C0 ++:10BA7000021504210050411300031104444803003F ++:10BA80000080000002000800200080000002000882 ++:10BA90000020090002010804108400918080020047 ++:10BAA0004A882808A28400010000083000C0004D28 ++:10BAB00000D30000002050045604005400D8016058 ++:10BAC00007821D0466B0508142054D002144500399 ++:10BAD0008092FE0300020008002092FE77022804F4 ++:10BAE000202800A0848882244A083000C000000377 ++:10BAF000000C801020C2004D00030048030010809D ++:10BB00000100023400D080400235D000000800203F ++:10BB100000800000020008002000800000020008F1 ++:10BB2000002010404402080A002821A2B089120215 ++:10BB30000CC004600D00000002000800200080001E ++:10BB40000002000800201080011520560098C00D4A ++:10BB50002C00000200080020008000000200080005 ++:10BB60002000800000020008002010804502080A22 ++:10BB7000002821A2608912020C0030000D00000094 ++:10BB80000200080020008000000200080020108051 ++:10BB900002050006400300008000000200080020AB ++:10BBA0000080000002000800200080000002000861 ++:10BBB00000200D00000002000800200080000002AC ++:10BBC0000008002000800000020008002000800023 ++:10BBD00000020008002040010019D40000002000ED ++:10BBE0008000000200080020008000000200080021 ++:10BBF000200080000002000800200D00000002006C ++:10BC000008002000800000020008002000800000E2 ++:10BC100002000800200080000002000800201080C0 ++:10BC200001150054C0030C00800000020008002031 ++:10BC300000800000020008002000800000020008D0 ++:10BC4000002010504402080A002821A290891222E4 ++:10BC50002420300042424C00DE0000002000800022 ++:10BC60000002000800204005880D2026E000E0408A ++:10BC700005880D2426F0010600800000020008005F ++:10BC80002000800000020008002010404702080A3F ++:10BC9000002821A2408912020CC004600D0000009F ++:10BCA000020008002000800000020008002003407D ++:10BCB00000152026085001628202152026D8048033 ++:10BCC00011608B09FE804203000080000002000822 ++:10BCD00000200D000000020008002000800000028B ++:10BCE0000008002000800000020008002000800002 ++:10BCF00000020008002010C0081D2074A8D0C11345 ++:10BD0000000B192C64C003090D000000020008009C ++:10BD10002000800000020008002010C04402080A31 ++:10BD2000002821A2708812020CC004600D000000DF ++:10BD3000020008002000800000020008002010849B ++:10BD40008819085680D84113008B19F4404303002A ++:10BD500000800000020008002000800000020008AF ++:10BD6000002010804502080A002821A270891202D2 ++:10BD70000C0030000D0000000200080020008000D0 ++:10BD80000002000800200D00000002000800200052 ++:10BD9000800000020008002000800000020008006F ++:10BDA000200080000002000800200D0000000200BA ++:10BDB0000800200080000002000800200080000031 ++:10BDC000020008002000800000020008002040015E ++:10BDD0000408004660030000800000020008002004 ++:10BDE000008000000200080020008000000200081F ++:10BDF000002010C04502080A002821A21089120262 ++:10BE00000CC004600F1E8011D200000020008000D2 ++:10BE100000020008002000000000000000000000F8 ++:10BE20000000000000000000000000000000000012 ++:10BE30000000000000000000000000000000000002 ++:10BE400000000000000000000000000000000000F2 ++:10BE500000000000000000000000000000000000E2 ++:10BE600000000000000000000000000000000000D2 ++:10BE700000000000000000000000000000000000C2 ++:10BE800000000000000000000000000000000000B2 ++:10BE900000000000000000000000000000000000A2 ++:10BEA0000000000000000000000000000000000092 ++:10BEB0000000000000000000000000000000000082 ++:10BEC0000000000000000000000000000000000072 ++:10BED0000000000000000000000000000000000062 ++:10BEE0000000000000000000000000000000000052 ++:10BEF0000000000000000000000000000000000042 ++:10BF00000000000000000000000000000000000031 ++:10BF10000000000000000000000000000000000021 ++:10BF20000000000000000000000000000000000011 ++:10BF30000000000000000000000000000000000001 ++:10BF400000000000000000000000000000000000F1 ++:10BF500000000000000000000000000000000000E1 ++:10BF600000000000000000000000000000000000D1 ++:10BF700000000000000000000000000000000000C1 ++:10BF800000000000000000000000000000000000B1 ++:10BF900000000000000000000000000000000000A1 ++:10BFA0000000000000000000000000000000000091 ++:10BFB0000000000000000000000000000000000081 ++:10BFC0000000000000000000000000000000000071 ++:10BFD0000000000000000000000000000000000061 ++:10BFE0000000000000000000000000000000000051 ++:10BFF0000000000000000000000000000000000041 ++:10C000000000000000000000000000000000000030 ++:10C010000000000000000000000000000000000020 ++:10C020000000000000000000000000000000000010 ++:10C030000000000000000000000000000000000000 ++:10C0400000000000000000000000000000000000F0 ++:10C0500000000000000000000000000000000000E0 ++:10C0600000000000000000000000000000000000D0 ++:10C0700000000000000000000000000000000000C0 ++:10C0800000000000000000000000000000000000B0 ++:10C0900000000000000000000000000000000000A0 ++:10C0A0000000000000000000000000000000000090 ++:10C0B0000000000000000000000000000000000080 ++:10C0C0000000000000000000000000000000000070 ++:10C0D0000000000000000000000000000000000060 ++:10C0E0000000000000000000000000000000000050 ++:10C0F0000000000000000000000000000000000040 ++:10C10000000000000000000000000000000000002F ++:10C11000000000000000000000000000000000001F ++:10C12000000000000000000000000000000000000F ++:10C1300000000000000000000000000000000000FF ++:10C1400000000000000000000000000000000000EF ++:10C1500000000000000000000000000000000000DF ++:10C1600000000000000000000000000000000000CF ++:10C1700000000000000000000000000000000000BF ++:10C1800000000000000000000000000000000000AF ++:10C19000000000000000000000000000000000009F ++:10C1A000000000000000000000000000000000008F ++:10C1B000000000000000000000000000000000007F ++:10C1C000000000000000000000000000000000006F ++:10C1D000000000000000000000000000000000005F ++:10C1E000000000000000000000000000000000004F ++:10C1F000000000000000000000000000000000003F ++:10C20000000000000000000000000000000000002E ++:10C21000000000000000000000000000000000001E ++:10C22000000000000000000000000000000000000E ++:10C2300000000000000000000000000000000000FE ++:10C2400000000000000000000000000000000000EE ++:10C2500000000000000000000000000000000000DE ++:10C2600000000000000000000000000000000000CE ++:10C2700000000000000000000000000000000000BE ++:10C2800000000000000000000000000000000000AE ++:10C29000000000000000000000000000000000009E ++:10C2A000000000000000000000000000000000008E ++:10C2B000000000000000000000000000000000007E ++:10C2C000000000000000000000000000000000006E ++:10C2D000000000000000000000000000000000005E ++:10C2E000000000000000000000000000000000004E ++:10C2F000000000000000000000000000000000003E ++:10C30000000000000000000000000000000000002D ++:10C31000000000000000000000000000000000001D ++:10C32000000000000000000000000000000000000D ++:10C3300000000000000000000000000000000000FD ++:10C3400000000000000000000000000000000000ED ++:10C3500000000000000000000000000000000000DD ++:10C3600000000000000000000000000000000000CD ++:10C3700000000000000000000000000000000000BD ++:10C3800000000000000000000000000000000000AD ++:10C39000000000000000000000000000000000009D ++:10C3A000000000000000000000000000000000008D ++:10C3B000000000000000000000000000000000007D ++:10C3C000000000000000000000000000000000006D ++:10C3D000000000000000000000000000000000005D ++:10C3E000000000000000000000000000000000004D ++:10C3F000000000000000000000000000000000003D ++:10C40000000000000000000000000000000000002C ++:10C41000000000000000000000000000000000001C ++:10C42000000000000000000000000000000000000C ++:10C4300000000000000000000000000000000000FC ++:10C4400000000000000000000000000000000000EC ++:10C4500000000000000000000000000000000000DC ++:10C4600000000000000000000000000000000000CC ++:10C4700000000000000000000000000000000000BC ++:10C4800000000000000000000000000000000000AC ++:10C49000000000000000000000000000000000009C ++:10C4A000000000000000000000000000000000008C ++:10C4B000000000000000000000000000000000007C ++:10C4C000000000000000000000000000000000006C ++:10C4D000000000000000000000000000000000005C ++:10C4E000000000000000000000000000000000004C ++:10C4F000000000000000000000000000000000003C ++:10C50000000000000000000000000000000000002B ++:10C51000000000000000000000000000000000001B ++:10C52000000000000000000000000000000000000B ++:10C5300000000000000000000000000000000000FB ++:10C5400000000000000000000000000000000000EB ++:10C5500000000000000000000000000000000000DB ++:10C5600000000000000000000000000000000000CB ++:10C5700000000000000000000000000000000000BB ++:10C5800000000000000000000000000000000000AB ++:10C59000000000000000000000000000000000009B ++:10C5A000000000000000000000000000000000008B ++:10C5B000000000000000000000000000000000007B ++:10C5C000000000000000000000000000000000006B ++:10C5D000000000000000000000000000000000005B ++:10C5E000000000000000000000000000000000004B ++:10C5F000000000000000000000000000000000003B ++:10C60000000000000000000000000000000000002A ++:10C61000000000000000000000000000000000001A ++:10C62000000000000000000000000000000000000A ++:10C6300000000000000000000000000000000000FA ++:10C6400000000000000000000000000000000000EA ++:10C6500000000000000000000000000000000000DA ++:10C6600000000000000000000000000000000000CA ++:10C6700000000000000000000000000000000000BA ++:10C6800000000000000000000000000000000000AA ++:10C69000000000000000000000000000000000009A ++:10C6A000000000000000000000000000000000008A ++:10C6B000000000000000000000000000000000007A ++:10C6C000000000000000000000000000000000006A ++:10C6D000000000000000000000000000000000005A ++:10C6E000000000000000000000000000000000004A ++:10C6F000000000000000000000000000000000003A ++:10C700000000000000000000000000000000000029 ++:10C710000000000000000000000000000000000019 ++:10C720000000000000000000000000000000000009 ++:10C7300000000000000000000000000000000000F9 ++:10C7400000000000000000000000000000000000E9 ++:10C7500000000000000000000000000000000000D9 ++:10C7600000000000000000000000000000000000C9 ++:10C7700000000000000000000000000000000000B9 ++:10C7800000000000000000000000000000000000A9 ++:10C790000000000000000000000000000000000099 ++:10C7A0000000000000000000000000000000000089 ++:10C7B0000000000000000000000000000000000079 ++:10C7C0000000000000000000000000000000000069 ++:10C7D0000000000000000000000000000000000059 ++:10C7E0000000000000000000000000000000000049 ++:10C7F0000000000000000000000000000000000039 ++:10C800000000000000000000000000000000000028 ++:10C810000000000000000000000000000000000018 ++:10C820000000000000000000000000000000000008 ++:10C8300000000000000000000000000000000000F8 ++:10C8400000000000000000000000000000000000E8 ++:10C8500000000000000000000000000000000000D8 ++:10C8600000000000000000000000000000000000C8 ++:10C8700000000000000000000000000000000000B8 ++:10C8800000000000000000000000000000000000A8 ++:10C890000000000000000000000000000000000098 ++:10C8A0000000000000000000000000000000000088 ++:10C8B0000000000000000000000000000000000078 ++:10C8C0000000000000000000000000000000000068 ++:10C8D0000000000000000000000000000000000058 ++:10C8E0000000000000000000000000000000000048 ++:10C8F0000000000000000000000000000000000038 ++:10C900000000000000000000000000000000000027 ++:10C910000000000000000000000000000000000017 ++:10C920000000000000000000000000000000000007 ++:10C9300000000000000000000000000000000000F7 ++:10C9400000000000000000000000000000000000E7 ++:10C9500000000000000000000000000000000000D7 ++:10C9600000000000000000000000000000000000C7 ++:10C9700000000000000000000000000000000000B7 ++:10C9800000000000000000000000000000000000A7 ++:10C990000000000000000000000000000000000097 ++:10C9A0000000000000000000000000000000000087 ++:10C9B0000000000000000000000000000000000077 ++:10C9C0000000000000000000000000000000000067 ++:10C9D0000000000000000000000000000000000057 ++:10C9E0000000000000000000000000000000000047 ++:10C9F0000000000000000000000000000000000037 ++:10CA00000000000000000000000000000000000026 ++:10CA10000000000000000000000000000000000016 ++:10CA20000000000000000000000000000000000006 ++:10CA300000000000000000000000000000000000F6 ++:10CA400000000000000000000000000000000000E6 ++:10CA500000000000000000000000000000000000D6 ++:10CA600000000000000000000000000000000000C6 ++:10CA700000000000000000000000000000000000B6 ++:10CA800000000000000000000000000000000000A6 ++:10CA90000000000000000000000000000000000096 ++:10CAA0000000000000000000000000000000000086 ++:10CAB0000000000000000000000000000000000076 ++:10CAC0000000000000000000000000000000000066 ++:10CAD0000000000000000000000000000000000056 ++:10CAE0000000000000000000000000000000000046 ++:10CAF0000000000000000000000000000000000036 ++:10CB00000000000000000000000000000000000025 ++:10CB10000000000000000000000000000000000015 ++:10CB20000000000000000000000000000000000005 ++:10CB300000000000000000000000000000000000F5 ++:10CB400000000000000000000000000000000000E5 ++:10CB500000000000000000000000000000000000D5 ++:10CB600000000000000000000000000000000000C5 ++:10CB700000000000000000000000000000000000B5 ++:10CB800000000000000000000000000000000000A5 ++:10CB90000000000000000000000000000000000095 ++:10CBA0000000000000000000000000000000000085 ++:10CBB0000000000000000000000000000000000075 ++:10CBC0000000000000000000000000000000000065 ++:10CBD0000000000000000000000000000000000055 ++:10CBE0000000000000000000000000000000000045 ++:10CBF0000000000000000000000000000000000035 ++:10CC00000000000000000000000000000000000024 ++:10CC10000000000000000000000000000000000014 ++:10CC20000000000000000000000000000000000004 ++:10CC300000000000000000000000000000000000F4 ++:10CC400000000000000000000000000000000000E4 ++:10CC500000000000000000000000000000000000D4 ++:10CC600000000000000000000000000000000000C4 ++:10CC700000000000000000000000000000000000B4 ++:10CC800000000000000000000000000000000000A4 ++:10CC90000000000000000000000000000000000094 ++:10CCA0000000000000000000000000000000000084 ++:10CCB0000000000000000000000000000000000074 ++:10CCC0000000000000000000000000000000000064 ++:10CCD0000000000000000000000000000000000054 ++:10CCE0000000000000000000000000000000000044 ++:10CCF0000000000000000000000000000000000034 ++:10CD00000000000000000000000000000000000023 ++:10CD10000000000000000000000000000000000013 ++:10CD20000000000000000000000000000000000003 ++:10CD300000000000000000000000000000000000F3 ++:10CD400000000000000000000000000000000000E3 ++:10CD500000000000000000000000000000000000D3 ++:10CD600000000000000000000000000000000000C3 ++:10CD700000000000000000000000000000000000B3 ++:10CD800000000000000000000000000000000000A3 ++:10CD90000000000000000000000000000000000093 ++:10CDA0000000000000000000000000000000000083 ++:10CDB0000000000000000000000000000000000073 ++:10CDC0000000000000000000000000000000000063 ++:10CDD0000000000000000000000000000000000053 ++:10CDE0000000000000000000000000000000000043 ++:10CDF0000000000000000000000000000000000033 ++:10CE00000000000000000000000000000000000022 ++:10CE10000000000000000000000000000000000012 ++:10CE20000000000000000000000000000000000002 ++:10CE300000000000000000000000000000000000F2 ++:10CE400000000000000000000000000000000000E2 ++:10CE500000000000000000000000000000000000D2 ++:10CE600000000000000000000000000000000000C2 ++:10CE700000000000000000000000000000000000B2 ++:10CE800000000000000000000000000000000000A2 ++:10CE90000000000000000000000000000000000092 ++:10CEA0000000000000000000000000000000000082 ++:10CEB0000000000000000000000000000000000072 ++:10CEC0000000000000000000000000000000000062 ++:10CED0000000000000000000000000000000000052 ++:10CEE0000000000000000000000000000000000042 ++:10CEF0000000000000000000000000000000000032 ++:10CF00000000000000000000000000000000000021 ++:10CF10000000000000000000000000000000000011 ++:10CF20000000000000000000000000000000000001 ++:10CF300000000000000000000000000000000000F1 ++:10CF400000000000000000000000000000000000E1 ++:10CF500000000000000000000000000000000000D1 ++:10CF600000000000000000000000000000000000C1 ++:10CF700000000000000000000000000000000000B1 ++:10CF800000000000000000000000000000000000A1 ++:10CF90000000000000000000000000000000000091 ++:10CFA0000000000000000000000000000000000081 ++:10CFB0000000000000000000000000000000000071 ++:10CFC0000000000000000000000000000000000061 ++:10CFD0000000000000000000000000000000000051 ++:10CFE0000000000000000000000000000000000041 ++:10CFF0000000000000000000000000000000000031 ++:10D000000000000000000000000000000000000020 ++:10D010000000000000000000000000000000000010 ++:10D020000000000000000000000000000000000000 ++:10D0300000000000000000000000000000000000F0 ++:10D0400000000000000000000000000000000000E0 ++:10D0500000000000000000000000000000000000D0 ++:10D0600000000000000000000000000000000000C0 ++:10D0700000000000000000000000000000000000B0 ++:10D0800000000000000000000000000000000000A0 ++:10D090000000000000000000000000000000000090 ++:10D0A0000000000000000000000000000000000080 ++:10D0B0000000000000000000000000000000000070 ++:10D0C0000000000000000000000000000000000060 ++:10D0D0000000000000000000000000000000000050 ++:10D0E0000000000000000000000000000000000040 ++:10D0F0000000000000000000000000000000000030 ++:10D10000000000000000000000000000000000001F ++:10D11000000000000000000000000000000000000F ++:10D1200000000000000000000000000000000000FF ++:10D1300000000000000000000000000000000000EF ++:10D1400000000000000000000000000000000000DF ++:10D1500000000000000000000000000000000000CF ++:10D1600000000000000000000000000000000000BF ++:10D1700000000000000000000000000000000000AF ++:10D18000000000000000000000000000000000009F ++:10D19000000000000000000000000000000000008F ++:10D1A000000000000000000000000000000000007F ++:10D1B000000000000000000000000000000000006F ++:10D1C000000000000000000000000000000000005F ++:10D1D000000000000000000000000000000000004F ++:10D1E000000000000000000000000000000000003F ++:10D1F000000000000000000000000000000000002F ++:10D20000000000000000000000000000000000001E ++:10D21000000000000000000000000000000000000E ++:10D2200000000000000000000000000000000000FE ++:10D2300000000000000000000000000000000000EE ++:10D2400000000000000000000000000000000000DE ++:10D2500000000000000000000000000000000000CE ++:10D2600000000000000000000000000000000000BE ++:10D2700000000000000000000000000000000000AE ++:10D28000000000000000000000000000000000009E ++:10D29000000000000000000000000000000000008E ++:10D2A000000000000000000000000000000000007E ++:10D2B000000000000000000000000000000000006E ++:10D2C000000000000000000000000000000000005E ++:10D2D000000000000000000000000000000000004E ++:10D2E000000000000000000000000000000000003E ++:10D2F000000000000000000000000000000000002E ++:10D30000000000000000000000000000000000001D ++:10D31000000000000000000000000000000000000D ++:10D3200000000000000000000000000000000000FD ++:10D3300000000000000000000000000000000000ED ++:10D3400000000000000000000000000000000000DD ++:10D3500000000000000000000000000000000000CD ++:10D3600000000000000000000000000000000000BD ++:10D3700000000000000000000000000000000000AD ++:10D38000000000000000000000000000000000009D ++:10D39000000000000000000000000000000000008D ++:10D3A000000000000000000000000000000000007D ++:10D3B000000000000000000000000000000000006D ++:10D3C000000000000000000000000000000000005D ++:10D3D000000000000000000000000000000000004D ++:10D3E000000000000000000000000000000000003D ++:10D3F000000000000000000000000000000000002D ++:10D40000000000000000000000000000000000001C ++:10D41000000000000000000000000000000000000C ++:10D4200000000000000000000000000000000000FC ++:10D4300000000000000000000000000000000000EC ++:10D4400000000000000000000000000000000000DC ++:10D4500000000000000000000000000000000000CC ++:10D4600000000000000000000000000000000000BC ++:10D4700000000000000000000000000000000000AC ++:10D48000000000000000000000000000000000009C ++:10D49000000000000000000000000000000000008C ++:10D4A000000000000000000000000000000000007C ++:10D4B000000000000000000000000000000000006C ++:10D4C000000000000000000000000000000000005C ++:10D4D000000000000000000000000000000000004C ++:10D4E000000000000000000000000000000000003C ++:10D4F000000000000000000000000000000000002C ++:10D50000000050B0C308080027989C5000C30800D2 ++:10D510000027B89C50804300000834001C3080C1B4 ++:10D52000060000110C000090C004003F3FA04430F2 ++:10D5300020C0CF0F0B042C0800900001080003242A ++:10D5400080400001C0000920102000304002080186 ++:10D5500000008430F3034002333FD01050900301A9 ++:10D5600002340414A44000020D010531040000102F ++:10D5700000C000031000EC300000C00E01000C00E1 ++:10D58000007002C0010302240C3000C10A00000B2D ++:10D5900010400030400208033024C43080C30A0029 ++:10D5A000000B0CC09010C3040000110C0000900090 ++:10D5B000010400032480408000C00009201008F00E ++:10D5C000A0820B0C2526100850A3C2C00009030C32 ++:10D5D000F000B0C0000C09318C000010C204000043 ++:10D5E000110C68404000C0000420008C9000020133 ++:10D5F0000100031040003042020804021008F0123B ++:10D60000830B0C252B100850A3C2400009030C40CB ++:10D61000B00200C0020410000C9000C2000C0931DE ++:10D620000CE0B00200C00223050084300001400479 ++:10D6300003000024400002C00009201040003040D8 ++:10D6400002080408000C90000281000F30B8C0509E ++:10D65000A1038100352A8C009030C0800E000B0C95 ++:10D66000C09010C3040000218C500010C1000000C5 ++:10D670000910800030010104002310200030400216 ++:10D680000804021008F080820B0C1523100850A328 ++:10D69000C2480009030C40B00200C0020410000C94 ++:10D6A0009000C2000C09310CE0B00200C00223015E ++:10D6B0000084300000400403000024400002C00049 ++:10D6C0000920104000304002080408000C900002BD ++:10D6D00081003F30B8C05023038100352A8C0C00F4 ++:10D6E000100001001B00240C3032000D0135268C87 ++:10D6F000000070828F0935060C000070C200000324 ++:10D7000000D418509300000000000000000000004A ++:10D710000000000000000000000000000000000009 ++:10D7200000000000000000000000000000000000F9 ++:10D7300000000000000000000000000000000000E9 ++:10D7400000000000000000000000000000000000D9 ++:10D7500000000000000000000000000000000000C9 ++:10D7600000000000000000000000000000000000B9 ++:10D7700000000000000000000000000000000000A9 ++:10D780000000000000000000000000000000000099 ++:10D790000000000000000000000000000000000089 ++:10D7A0000000000000000000000000000000000079 ++:10D7B0000000000000000000000000000000000069 ++:10D7C0000000000000000000000000000000000059 ++:10D7D0000000000000000000000000000000000049 ++:10D7E0000000000000000000000000000000000039 ++:10D7F0000000000000000000000000000000000029 ++:10D800000000000000000000000000000000000018 ++:10D810000000000000000000000000000000000008 ++:10D8200000000000000000000000000000000000F8 ++:10D8300000000000000000000000000000000000E8 ++:10D8400000000000000000000000000000000000D8 ++:10D8500000000000000000000000000000000000C8 ++:10D8600000000000000000000000000000000000B8 ++:10D8700000000000000000000000000000000000A8 ++:10D880000000000000000000000000000000000098 ++:10D890000000000000000000000000000000000088 ++:10D8A0000000000000000000000000000000000078 ++:10D8B0000000000000000000000000000000000068 ++:10D8C0000000000000000000000000000000000058 ++:10D8D0000000000000000000000000000000000048 ++:10D8E0000000000000000000000000000000000038 ++:10D8F0000000000000000000000000000000000028 ++:10D900000000000000000000000000000000000017 ++:10D910000000000000000000000000000000000007 ++:10D9200000000000000000000000000000000000F7 ++:10D9300000000000000000000000000000000000E7 ++:10D9400000000000000000000000000000000000D7 ++:10D9500000000000000000000000000000000000C7 ++:10D9600000000000000000000000000000000000B7 ++:10D9700000000000000000000000000000000000A7 ++:10D980000000500000000000000000000000000047 ++:10D990000000000000000000000000000000000087 ++:10D9A0000000000000000000000000000000000077 ++:10D9B0000000000000000000000000000000000067 ++:10D9C0000000000000000000000000000000000057 ++:10D9D0000000000000000000000000000000000047 ++:10D9E0000000000000000000000000000000000037 ++:10D9F0000000000000000000000000000000000027 ++:10DA00000000000000000000000000000000000016 ++:10DA10000000000000000000000000000000000006 ++:10DA200000000000000000000000000000000000F6 ++:10DA300000000000000000000000000000000000E6 ++:10DA400000000000000000000000000000000000D6 ++:10DA500000000000000000000000000000000000C6 ++:10DA600000000000000000000000000000000000B6 ++:10DA700000000000000000000000000000000000A6 ++:10DA80000000000000000000000000000000000096 ++:10DA90000000000000000000000000000000000086 ++:10DAA0000000000000000000000000000000000076 ++:10DAB0000000000000000000000000000000000066 ++:10DAC0000000000000000000000000000000000056 ++:10DAD0000000000000000000000000000000000046 ++:10DAE0000000000000000000000000000000000036 ++:10DAF0000000000000000000000000000000000026 ++:10DB00000000000000000000000000000000000015 ++:10DB10000000000000000000000000000000000005 ++:10DB200000000000000000000000000000000000F5 ++:10DB300000000000000000000000000000000000E5 ++:10DB400000000000000000000000000000000000D5 ++:10DB500000000000000000000000000000000000C5 ++:10DB600000000000000000000000000000000000B5 ++:10DB700000000000000000000000000000000000A5 ++:10DB80000000000000000000000000000000000095 ++:10DB90000000000000000000000000000000000085 ++:10DBA0000000000000000000000000000000000075 ++:10DBB0000000000000000000000000000000000065 ++:10DBC0000000000000000000000000000000000055 ++:10DBD0000000000000000000000000000000000045 ++:10DBE0000000000000000000000000000000000035 ++:10DBF0000000000000000000000000000000000025 ++:10DC00000000000000000000000000000000000014 ++:10DC10000000000000000000000000000000000004 ++:10DC200000000000000000000000000000000000F4 ++:10DC300000000000000000000000000000000000E4 ++:10DC400000000000000000000000000000000000D4 ++:10DC500000000000000000000000000000000000C4 ++:10DC600000000000000000000000000000000000B4 ++:10DC700000000000000000000000000000000000A4 ++:10DC80000000000000000000000000000000000094 ++:10DC90000000000000000000000000000000000084 ++:10DCA0000000000000000000000000000000000074 ++:10DCB0000000000000000000000000000000000064 ++:10DCC0000000000000000000000000000000000054 ++:10DCD0000000000000000000000000000000000044 ++:10DCE0000000000000000000000000000000000034 ++:10DCF0000000000000000000000000000000000024 ++:10DD00000000000000000000000000000000000013 ++:10DD10000000000000000000000000000000000003 ++:10DD200000000000000000000000000000000000F3 ++:10DD300000000000000000000000000000000000E3 ++:10DD400000000000000000000000000000000000D3 ++:10DD500000000000000000000000000000000000C3 ++:10DD600000000000000000000000000000000000B3 ++:10DD700000000000000000000000000000000000A3 ++:10DD80000000000000000000000000000000000093 ++:10DD90000000000000000000000000000000000083 ++:10DDA0000000000000000000000000000000000073 ++:10DDB0000000000000000000000000000000000063 ++:10DDC0000000000000000000000000000000000053 ++:10DDD0000000000000000000000000000000000043 ++:10DDE0000000000000000000000000000000000033 ++:10DDF0000000000000000000000000000000000023 ++:10DE00000000000000000000000000000000000012 ++:10DE10000000000000000000000000000000000002 ++:10DE200000000000000050B0C308080027989C5074 ++:10DE300000C308000027B89C50804300000834004D ++:10DE40001C3080C1060000110C000090C004003F8F ++:10DE50003FA0443020C0CF0F0B042C0800900001DD ++:10DE60000800032480400001C00009201020003079 ++:10DE70004002080100008430F3034002333FD01019 ++:10DE80005090030102340414A44000020D01053136 ++:10DE90000400001000C000031000EC300000C00EB1 ++:10DEA00001000C00007002C0010302240C3000C10C ++:10DEB0000A00000B10400030400208033024C43038 ++:10DEC00080C30A00000B0CC09010C3040000110CAA ++:10DED00000009000010400032480408000C000097D ++:10DEE000201008F0A0820B0C2526100850A3C2C0F9 ++:10DEF0000009030CF000B0C0000C09318C000010C8 ++:10DF0000C2040000110C68404000C0000420008CD6 ++:10DF10009000020101000310400030420208040298 ++:10DF20001008F012830B0C252B100850A3C24000E0 ++:10DF300009030C40B00200C0020410000C9000C2A3 ++:10DF4000000C09310CE0B00200C00223050084304F ++:10DF50000001400403000024400002C0000920101A ++:10DF60004000304002080408000C90000281000FBD ++:10DF700030B8C050A1038100352A8C009030C08099 ++:10DF80000E000B0CC09010C3040000218C50001038 ++:10DF9000C10000000910800030010104002310209E ++:10DFA000003040020804021008F080820B0C152398 ++:10DFB000100850A3C2480009030C40B00200C00280 ++:10DFC0000410000C9000C2000C09310CE0B00200FB ++:10DFD000C0022301008430000040040300002440FC ++:10DFE0000002C00009201040003040020804080070 ++:10DFF0000C90000281003F30B8C0502303810035EF ++:10E000002A8C0C00100001001B00240C3032000D83 ++:10E010000135268C000070828F0935060C000070D7 ++:10E02000C200000300D4185093000000000000005C ++:10E0300000000000000000000000000000000000E0 ++:10E0400000000000000000000000000000000000D0 ++:10E0500000000000000000000000000000000000C0 ++:10E0600000000000000000000000000000000000B0 ++:10E0700000000000000000000000000000000000A0 ++:10E080000000000000000000000000000000000090 ++:10E090000000000000000000000000000000000080 ++:10E0A0000000000000000000000000000000000070 ++:10E0B0000000000000000000000000000000000060 ++:10E0C0000000000000000000000000000000000050 ++:10E0D0000000000000000000000000000000000040 ++:10E0E0000000000000000000000000000000000030 ++:10E0F0000000000000000000000000000000000020 ++:10E10000000000000000000000000000000000000F ++:10E1100000000000000000000000000000000000FF ++:10E1200000000000000000000000000000000000EF ++:10E1300000000000000000000000000000000000DF ++:10E1400000000000000000000000000000000000CF ++:10E1500000000000000000000000000000000000BF ++:10E1600000000000000000000000000000000000AF ++:10E17000000000000000000000000000000000009F ++:10E18000000000000000000000000000000000008F ++:10E19000000000000000000000000000000000007F ++:10E1A000000000000000000000000000000000006F ++:10E1B000000000000000000000000000000000005F ++:10E1C000000000000000000000000000000000004F ++:10E1D000000000000000000000000000000000003F ++:10E1E000000000000000000000000000000000002F ++:10E1F000000000000000000000000000000000001F ++:10E20000000000000000000000000000000000000E ++:10E2100000000000000000000000000000000000FE ++:10E2200000000000000000000000000000000000EE ++:10E2300000000000000000000000000000000000DE ++:10E2400000000000000000000000000000000000CE ++:10E2500000000000000000000000000000000000BE ++:10E2600000000000000000000000000000000000AE ++:10E27000000000000000000000000000000000009E ++:10E28000000000000000000000000000000000008E ++:10E29000000000000000000000000000000000007E ++:10E2A000000000000000500000000000000000001E ++:10E2B000000000000000000000000000000000005E ++:10E2C000000000000000000000000000000000004E ++:10E2D000000000000000000000000000000000003E ++:10E2E000000000000000000000000000000000002E ++:10E2F000000000000000000000000000000000001E ++:10E30000000000000000000000000000000000000D ++:10E3100000000000000000000000000000000000FD ++:10E3200000000000000000000000000000000000ED ++:10E3300000000000000000000000000000000000DD ++:10E3400000000000000000000000000000000000CD ++:10E3500000000000000000000000000000000000BD ++:10E3600000000000000000000000000000000000AD ++:10E37000000000000000000000000000000000009D ++:10E38000000000000000000000000000000000008D ++:10E39000000000000000000000000000000000007D ++:10E3A000000000000000000000000000000000006D ++:10E3B000000000000000000000000000000000005D ++:10E3C000000000000000000000000000000000004D ++:10E3D000000000000000000000000000000000003D ++:10E3E000000000000000000000000000000000002D ++:10E3F000000000000000000000000000000000001D ++:10E40000000000000000000000000000000000000C ++:10E4100000000000000000000000000000000000FC ++:10E4200000000000000000000000000000000000EC ++:10E4300000000000000000000000000000000000DC ++:10E4400000000000000000000000000000000000CC ++:10E4500000000000000000000000000000000000BC ++:10E4600000000000000000000000000000000000AC ++:10E47000000000000000000000000000000000009C ++:10E48000000000000000000000000000000000008C ++:10E49000000000000000000000000000000000007C ++:10E4A000000000000000000000000000000000006C ++:10E4B000000000000000000000000000000000005C ++:10E4C000000000000000000000000000000000004C ++:10E4D000000000000000000000000000000000003C ++:10E4E000000000000000000000000000000000002C ++:10E4F000000000000000000000000000000000001C ++:10E50000000000000000000000000000000000000B ++:10E5100000000000000000000000000000000000FB ++:10E5200000000000000000000000000000000000EB ++:10E5300000000000000000000000000000000000DB ++:10E5400000000000000000000000000000000000CB ++:10E5500000000000000000000000000000000000BB ++:10E5600000000000000000000000000000000000AB ++:10E57000000000000000000000000000000000009B ++:10E58000000000000000000000000000000000008B ++:10E59000000000000000000000000000000000007B ++:10E5A000000000000000000000000000000000006B ++:10E5B000000000000000000000000000000000005B ++:10E5C000000000000000000000000000000000004B ++:10E5D000000000000000000000000000000000003B ++:10E5E000000000000000000000000000000000002B ++:10E5F000000000000000000000000000000000001B ++:10E60000000000000000000000000000000000000A ++:10E6100000000000000000000000000000000000FA ++:10E6200000000000000000000000000000000000EA ++:10E6300000000000000000000000000000000000DA ++:10E6400000000000000000000000000000000000CA ++:10E6500000000000000000000000000000000000BA ++:10E6600000000000000000000000000000000000AA ++:10E67000000000000000000000000000000000009A ++:10E68000000000000000000000000000000000008A ++:10E69000000000000000000000000000000000007A ++:10E6A000000000000000000000000000000000006A ++:10E6B000000000000000000000000000000000005A ++:10E6C000000000000000000000000000000000004A ++:10E6D000000000000000000000000000000000003A ++:10E6E000000000000000000000000000000000002A ++:10E6F000000000000000000000000000000000001A ++:10E700000000000000000000000000000000000009 ++:10E7100000000000000000000000000000000000F9 ++:10E7200000000000000000000000000000000000E9 ++:10E7300000000000000000000000000000000000D9 ++:10E7400000000000000000000000000000000000C9 ++:10E7500000000000000000000000000000000000B9 ++:10E7600000000000000000000000000000000000A9 ++:10E770000000000000000000000000000000000099 ++:10E780000000000000000000000000000000000089 ++:10E790000000000000000000000000000000000079 ++:10E7A0000000000000000000000000000000000069 ++:10E7B0000000000000000000000000000000000059 ++:10E7C0000000000000000000000000000000000049 ++:10E7D0000000000000000000000000000000000039 ++:10E7E0000000000000000000000000000000000029 ++:10E7F0000000000000000000000000000000000019 ++:10E800000000000000000000000000000000000008 ++:10E8100000000000000000000000000000000000F8 ++:10E8200000000000000000000000000000000000E8 ++:10E8300000000000000000000000000000000000D8 ++:10E8400000000000000000000000000000000000C8 ++:10E8500000000000000000000000000000000000B8 ++:10E8600000000000000000000000000000000000A8 ++:10E870000000000000000000000000000000000098 ++:10E880000000000000000000000000000000000088 ++:10E890000000000000000000000000000000000078 ++:10E8A0000000000000000000000000000000000068 ++:10E8B0000000000000000000000000000000000058 ++:10E8C0000000000000000000000000000000000048 ++:10E8D0000000000000000000000000000000000038 ++:10E8E0000000000000000000000000000000000028 ++:10E8F0000000000000000000000000000000000018 ++:10E900000000000000000000000000000000000007 ++:10E9100000000000000000000000000000000000F7 ++:10E9200000000000000000000000000000000000E7 ++:10E9300000000000000000000000000000000000D7 ++:10E9400000000000000000000000000000000000C7 ++:10E9500000000000000000000000000000000000B7 ++:10E9600000000000000000000000000000000000A7 ++:10E970000000000000000000000000000000000097 ++:10E980000000000000000000000000000000000087 ++:10E990000000000000000000000000000000000077 ++:10E9A0000000000000000000000000000000000067 ++:10E9B0000000000000000000000000000000000057 ++:10E9C0000000000000000000000000000000000047 ++:10E9D0000000000000000000000000000000000037 ++:10E9E0000000000000000000000000000000000027 ++:10E9F0000000000000000000000000000000000017 ++:10EA00000000000000000000000000000000000006 ++:10EA100000000000000000000000000000000000F6 ++:10EA200000000000000000000000000000000000E6 ++:10EA300000000000000000000000000000000000D6 ++:10EA400000000000000000000000000000000000C6 ++:10EA500000000000000000000000000000000000B6 ++:10EA600000000000000000000000000000000000A6 ++:10EA70000000000000000000000000000000000096 ++:10EA80000000000000000000000000000000000086 ++:10EA90000000000000000000000000000000000076 ++:10EAA0000000000000000000000000000000000066 ++:10EAB0000000000000000000000000000000000056 ++:10EAC0000000000000000000000000000000000046 ++:10EAD0000000000000000000000000000000000036 ++:10EAE0000000000000000000000000000000000026 ++:10EAF0000000000000000000000000000000000016 ++:10EB00000000000000000000000000000000000005 ++:10EB100000000000000000000000000000000000F5 ++:10EB200000000000000000000000000000000000E5 ++:10EB300000000000000000000000000000000000D5 ++:10EB400000000000000000000000000000000000C5 ++:10EB500000000000000000000000000000000000B5 ++:10EB600000000000000000000000000000000000A5 ++:10EB70000000000000000000000000000000000095 ++:10EB80000000000000000000000000000000000085 ++:10EB90000000000000000000000000000000000075 ++:10EBA0000000000000000000000000000000000065 ++:10EBB0000000000000000000000000000000000055 ++:10EBC0000000000000000000000000000000000045 ++:10EBD0000000000000000000000000000000000035 ++:10EBE0000000000000000000000000000000000025 ++:10EBF0000000000000000000000000000000000015 ++:10EC00000000000000000000000000000000000004 ++:10EC100000000000000000000000000000000000F4 ++:10EC200000000000000000000000000000000000E4 ++:10EC300000000000000000000000000000000000D4 ++:10EC400000000000000000000000000000000000C4 ++:10EC500000000000000000000000000000000000B4 ++:10EC600000000000000000000000000000000000A4 ++:10EC70000000000000000000000000000000000094 ++:10EC80000000000000000000000000000000000084 ++:10EC90000000000000000000000000000000000074 ++:10ECA0000000000000000000000000000000000064 ++:10ECB0000000000000000000000000000000000054 ++:10ECC0000000000000000000000000000000000044 ++:10ECD0000000000000000000000000000000000034 ++:10ECE0000000000000000000000000000000000024 ++:10ECF0000000000000000000000000000000000014 ++:10ED00000000000000000000000000000000000003 ++:10ED100000000000000000000000000000000000F3 ++:10ED200000000000000000000000000000000000E3 ++:10ED300000000000000000000000000000000000D3 ++:10ED400000000000000000000000000000000000C3 ++:10ED500000000000000000000000000000000000B3 ++:10ED600000000000000000000000000000000000A3 ++:10ED70000000000000000000000000000000000093 ++:10ED80000000000000000000000000000000000083 ++:10ED90000000000000000000000000000000000073 ++:10EDA0000000000000000000000000000000000063 ++:10EDB0000000000000000000000000000000000053 ++:10EDC0000000000000000000000000000000000043 ++:10EDD0000000000000000000000000000000000033 ++:10EDE0000000000000000000000000000000000023 ++:10EDF0000000000000000000000000000000000013 ++:10EE00000000000000000000000000000000000002 ++:10EE100000000000000000000000000000000000F2 ++:10EE200000000000000000000000000000000000E2 ++:10EE300000000000000000000000000000000000D2 ++:10EE400000000000000000000000000000000000C2 ++:10EE500000000000000000000000000000000000B2 ++:10EE600000000000000000000000000000000000A2 ++:10EE70000000000000000000000000000000000092 ++:10EE80000000000000000000000000000000000082 ++:10EE90000000000000000000000000000000000072 ++:10EEA0000000000000000000000000000000000062 ++:10EEB0000000000000000000000000000000000052 ++:10EEC0000000000000000000000000000000000042 ++:10EED0000000000000000000000000000000000032 ++:10EEE0000000000000000000000000000000000022 ++:10EEF0000000000000000000000000000000000012 ++:10EF00000000000000000000000000000000000001 ++:10EF100000000000000000000000000000000000F1 ++:10EF200000000000000000000000000000000000E1 ++:10EF300000000000000000000000000000000000D1 ++:10EF400000000000000000000000000000000000C1 ++:10EF500000000000000000000000000000000000B1 ++:10EF600000000000000000000000000000000000A1 ++:10EF70000000000000000000000000000000000091 ++:10EF80000000000000000000000000000000000081 ++:10EF90000000000000000000000000000000000071 ++:10EFA0000000000000000000000000000000000061 ++:10EFB0000000000000000000000000000000000051 ++:10EFC0000000000000000000000000000000000041 ++:10EFD0000000000000000000000000000000000031 ++:10EFE0000000000000000000000000000000000021 ++:10EFF0000000000000000000000000000000000011 ++:10F000000000000000000000000000000000000000 ++:10F0100000000000000000000000000000000000F0 ++:10F0200000000000000000000000000000000000E0 ++:10F0300000000000000000000000000000000000D0 ++:10F0400000000000000000000000000000000000C0 ++:10F0500000000000000000000000000000000000B0 ++:10F0600000000000000000000000000000000000A0 ++:10F070000000000000000000000000000000000090 ++:10F080000000000000000000000000000000000080 ++:10F090000000000000000000000000000000000070 ++:10F0A0000000000000000000000000000000000060 ++:10F0B0000000000000000000000000000000000050 ++:10F0C0000000000000000000000000000000000040 ++:10F0D0000000000000000000000000000000000030 ++:10F0E0000000000000000000000000000000000020 ++:10F0F0000000000000000000000000000000000010 ++:10F1000000000000000000000000000000000000FF ++:10F1100000000000000000000000000000000000EF ++:10F1200000000000000000000000000000000000DF ++:10F1300000000000000000000000000000000000CF ++:10F1400000000000000000000000000000000000BF ++:10F1500000000000000000000000000000000000AF ++:10F16000000000000000000000000000000000009F ++:10F17000000000000000000000000000000000008F ++:10F18000000000000000000000000000000000007F ++:10F19000000000000000000000000000000000006F ++:10F1A000000000000000000000000000000000005F ++:10F1B000000000000000000000000000000000004F ++:10F1C000000000000000000000000000000000003F ++:10F1D000000000000000000000000000000000002F ++:10F1E000000000000000000000000000000000001F ++:10F1F000000000000000000000000000000000000F ++:10F2000000000000000000000000000000000000FE ++:10F2100000000000000000000000000000000000EE ++:10F2200000000000000000000000000000000000DE ++:10F2300000000000000000000000000000000000CE ++:10F2400000000000000000000000000000000000BE ++:10F2500000000000000000000000000000000000AE ++:10F26000000000000000000000000000000000009E ++:10F27000000000000000000000000000000000008E ++:10F28000000000000000000000000000000000007E ++:10F29000000000000000000000000000000000006E ++:10F2A000000000000000000000000000000000005E ++:10F2B000000000000000000000000000000000004E ++:10F2C000000000000000000000000000000000003E ++:10F2D000000000000000000000000000000000002E ++:10F2E000000000000000000000000000000000001E ++:10F2F000000000000000000000000000000000000E ++:10F3000000000000000000000000000000000000FD ++:10F3100000000000000000000000000000000000ED ++:10F3200000000000000000000000000000000000DD ++:10F3300000000000000000000000000000000000CD ++:10F3400000000000000000000000000000000000BD ++:10F3500000000000000000000000000000000000AD ++:10F36000000000000000000000000000000000009D ++:10F37000000000000000000000000000000000008D ++:10F38000000000000000000000000000000000007D ++:10F39000000000000000000000000000000000006D ++:10F3A000000000000000000000000000000000005D ++:10F3B000000000000000000000000000000000004D ++:10F3C000000000000000000000000000000000003D ++:10F3D000000000000000000000000000000000002D ++:10F3E000000000000000000000000000000000001D ++:10F3F000000000000000000000000000000000000D ++:10F4000000000000000000000000000000000000FC ++:10F4100000000000000000000000000000000000EC ++:10F4200000000000000000000000000000000000DC ++:10F4300000000000000000000000000000000000CC ++:10F4400000000000000000000000000000000000BC ++:10F4500000000000000000000000000000000000AC ++:10F46000000000000000000000000000000000009C ++:10F47000000000000000000000000000000000008C ++:10F48000000000000000000000000000000000007C ++:10F49000000000000000000000000000000000006C ++:10F4A000000000000000000000000000000000005C ++:10F4B000000000000000000000000000000000004C ++:10F4C000000000000000000000000000000000003C ++:10F4D000000000000000000000000000000000002C ++:10F4E000000000000000000000000000000000001C ++:10F4F000000000000000000000000000000000000C ++:10F5000000000000000000000000000000000000FB ++:10F5100000000000000000000000000000000000EB ++:10F5200000000000000000000000000000000000DB ++:10F5300000000000000000000000000000000000CB ++:10F5400000000000000000000000000000000000BB ++:10F5500000000000000000000000000000000000AB ++:10F56000000000000000000000000000000000009B ++:10F57000000000000000000000000000000000008B ++:10F58000000000000000000000000000000000007B ++:10F59000000000000000000000000000000000006B ++:10F5A000000000000000000000000000000000005B ++:10F5B000000000000000000000000000000000004B ++:10F5C000000000000000000000000000000000003B ++:10F5D000000000000000000000000000000000002B ++:10F5E000000000000000000000000000000000001B ++:10F5F000000000000000000000000000000000000B ++:10F6000000000000000000000000000000000000FA ++:10F6100000000000000000000000000000000000EA ++:10F6200000000000000000000000000000000000DA ++:10F6300000000000000000000000000000000000CA ++:10F6400000000000000000000000000000000000BA ++:10F6500000000000000000000000000000000000AA ++:10F66000000000000000000000000000000000009A ++:10F67000000000000000000000000000000000008A ++:10F68000000000000000000000000000000000007A ++:10F69000000000000000000000000000000000006A ++:10F6A000000000000000000000000000000000005A ++:10F6B000000000000000000000000000000000004A ++:10F6C000000000000000000000000000000000003A ++:10F6D000000000000000000000000000000000002A ++:10F6E000000000000000000000000000000000001A ++:10F6F000000000000000000000000000000000000A ++:10F7000000000000000000000000000000000000F9 ++:10F7100000000000000000000000000000000000E9 ++:10F7200000000000000000000000000000000000D9 ++:10F7300000000000000000000000000000000000C9 ++:10F7400000000000000000000000000000000000B9 ++:10F7500000000000000000000000000000000000A9 ++:10F760000000000000000000000000000000000099 ++:10F770000000000000000000000000000000000089 ++:10F780000000000000000000000000000000000079 ++:10F790000000000000000000000000000000000069 ++:10F7A0000000000000000000000000000000000059 ++:10F7B0000000000000000000000000000000000049 ++:10F7C0000000000000000000000000000000000039 ++:10F7D0000000000000000000000000000000000029 ++:10F7E0000000000000000000000000000000000019 ++:10F7F0000000000000000000000000000000000009 ++:10F8000000000000000000000000000000000000F8 ++:10F8100000000000000000000000000000000000E8 ++:10F8200000000000000000000000000000000000D8 ++:10F8300000000000000000000000000000000000C8 ++:10F8400000000000000000000000000000000000B8 ++:10F8500000000000000000000000000000000000A8 ++:10F860000000000000000000000000000000000098 ++:10F870000000000000000000000000000000000088 ++:10F880000000000000000000000000000000000078 ++:10F890000000000000000000000000000000000068 ++:10F8A0000000000000000000000000000000000058 ++:10F8B0000000000000000000000000000000000048 ++:10F8C0000000000000000000000000000000000038 ++:10F8D0000000000000000000000000000000000028 ++:10F8E0000000000000000000000000000000000018 ++:10F8F0000000000000000000000000000000000008 ++:10F9000000000000000000000000000000000000F7 ++:10F9100000000000000000000000000000000000E7 ++:10F9200000000000000000000000000000000000D7 ++:10F9300000000000000000000000000000000000C7 ++:10F9400000000000000000000000000000000000B7 ++:10F9500000000000000000000000000000000000A7 ++:10F960000000000000000000000000000000000097 ++:10F970000000000000000000000000000000000087 ++:10F980000000000000000000000000000000000077 ++:10F990000180000000880060E0800000002400D0AA ++:10F9A00000000000000000000180000000880060EE ++:10F9B0000180000000880060018000000088006075 ++:10F9C00000000000000000000180000000880060CE ++:10F9D0000180000000880060E0800000002400D06A ++:10F9E0000000000000000000000000000000000017 ++:10F9F0000000000000000000000000000000000007 ++:10FA000000000000000000000000000000000000F6 ++:10FA10000180000000880060018000000088006014 ++:10FA200000000000000000000000000000000000D6 ++:10FA300000000000000000000000000000000000C6 ++:10FA400000000000000000000000000000000000B6 ++:10FA500001800000008800600180000000880060D4 ++:10FA60000000000000000000000000000000000096 ++:10FA70000000000000000000000000000000000086 ++:10FA80000000000000000000000000000000000076 ++:10FA90000000000000000000000000000000000066 ++:10FAA0000000000000000000000000000000000056 ++:10FAB000E0800000002400D0E0800000002400D09E ++:10FAC0000180000000880060018000000088006064 ++:10FAD0000180000000880060E0800000002400D069 ++:10FAE0000000000000000000000000000000000016 ++:10FAF0000180000000880060018000000088006034 ++:10FB00000180000000880060E0800000002400D038 ++:10FB10000180000000880060018000000088006013 ++:10FB2000E0800000002400D0018000000088006018 ++:10FB300000000000000000000000000000000000C5 ++:10FB400000000000000000000000000000000000B5 ++:10FB500000000000000000000000000000000000A5 ++:10FB60000000000000000000000000000000000095 ++:10FB70000000000000000000000000000000000085 ++:10FB80000180000000880060E0800000002400D0B8 ++:10FB90000180000000880060018000000088006093 ++:10FBA0000000000000000000000000000000000055 ++:10FBB0000000000000000000000000000000000045 ++:10FBC0000000000000000000000000000000000035 ++:10FBD000E0800000002400D0018000000088006068 ++:10FBE000E0800000002400D0018000000088006058 ++:10FBF00000000000000000020110000100000000F1 ++:10FC000000000000000000000000000000000000F4 ++:10FC100000000000000000000000000000000000E4 ++:10FC2000E0800000002400D0018000000088006017 ++:10FC3000E0800000002400D0018000000088006007 ++:10FC400000000000000000000000000000000000B4 ++:10FC500000000000000000000000000000000000A4 ++:10FC60000000000000000000000000000000000094 ++:10FC70000000000000000000000000000000000084 ++:10FC800001800000008800600180000000880060A2 ++:10FC90000180000000880060E0800000002400D0A7 ++:10FCA0000180000000880060E0800000002400D097 ++:10FCB0000180000000880060018000000088006072 ++:10FCC0000000000000000000000000000000000034 ++:10FCD0000000000000000000000000000000000024 ++:10FCE0000000000000000000000000000000000014 ++:10FCF0000180000000880060018000000088006032 ++:10FD0000E180000000880060E18000000088006061 ++:10FD1000E180000000880060E18000000088006051 ++:10FD2000E180000000880060E18000000088006041 ++:10FD3000E180000000880060E18000000088006031 ++:10FD400000000000000000000000000000000000B3 ++:10FD500000000000000000000000000000000000A3 ++:10FD60000000000000000000000000000000000093 ++:10FD70000000000000000000000000000000000083 ++:10FD80000000000000000000000000000000000073 ++:10FD90000000000000000000000000000000000063 ++:10FDA000E0800000002400D0018000000088006096 ++:10FDB0000180000000880060018000000088006071 ++:10FDC0000000000000000000000000000000000033 ++:10FDD0000000000000000000000000000000000023 ++:10FDE0000000000000000000000000000000000013 ++:10FDF000E0800000002400D0018000000088006046 ++:10FE00000180000000880060000000000000000089 ++:10FE100000000000000000000000000000000000E2 ++:10FE200000000000000000000000000000000000D2 ++:10FE300000000000000000000000000000000000C2 ++:10FE40000000000000000000E0800000002400D05E ++:10FE500000000000000000000000000000000000A2 ++:10FE60000000000000000000000000000000000092 ++:10FE7000E180000000880060E180000000880060F0 ++:10FE80000180000000880060000000000000000009 ++:10FE90000180000000880060018000000088006090 ++:10FEA0000000000000000000000000000000000052 ++:10FEB0000000000000000000000000000000000042 ++:10FEC0000000000000000000000000000000000032 ++:10FED00001800000008800600000000000000000B9 ++:10FEE0000000000000000000000000000000000012 ++:10FEF0000180000000880060000000000000000099 ++:10FF000000000000000000000000000000000000F1 ++:10FF100000000000000000000000000000000000E1 ++:10FF200000000000000000000000000000000000D1 ++:10FF300000000000000000000000000000000000C1 ++:10FF400000000000000000000000000000000000B1 ++:10FF5000E0800000002400D0E0800000002400D0F9 ++:10FF60000180000000880060E0800000002400D0D4 ++:10FF70000000000000000000000000000000000081 ++:10FF80000000000000000000000000000000000071 ++:10FF90000000000000000000000000000000000061 ++:10FFA000018000000088006001800000008800607F ++:10FFB000E0800000002400D00000000000000000ED ++:10FFC0000000000000000000000000000000000031 ++:10FFD000E0800000002400D00000000000000000CD ++:10FFE000E0800000002400D0018000000088006054 ++:10FFF0000180000000880060000000000000000098 ++:020000040005F5 ++:1000000000000000000000000000000000000000F0 ++:1000100000000000000000000000000000000000E0 ++:1000200000000000000000000000000000000000D0 ++:1000300000000000000000000000000000000000C0 ++:1000400000000000000000000000000000000000B0 ++:1000500000000000000000000000000000000000A0 ++:100060000000000000000000000000000000000090 ++:10007000E0800000002400D00180000000880060C3 ++:100080000000003044B90C44002000E80C850080DA ++:100090000A0600000041AE9E0000000000000000C3 ++:1000A0000000000000000000000000000000000050 ++:1000B000000000007975AE9E000000000000000006 ++:1000C0000000000000000000000000000000000030 ++:1000D0000000000079750000000000000000000032 ++:1000E0000000000000000000000000000000000010 ++:1000F0000000000000000000000000000000000000 ++:1001000000000000000000000000000000000000EF ++:100110000000000000000000FFFFFFFFFFFFFFFFE7 ++:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF ++:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF ++:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF ++:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF ++:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F ++:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F ++:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F ++:10019000FFFFFFFFFFFFFFFFFFFF00BC8B8F0C4443 ++:1001A000802000E80A0600000041AE9E000000002A ++:1001B000000000000000000000000000000000003F ++:1001C00000000000000000007975AE9E00000000F5 ++:1001D000000000000000000000000000000000001F ++:1001E000000000000000000079750000AE9E0000D5 ++:1001F00000000000000000000000000000000000FF ++:10020000000000000000000000007975AE9E0000B4 ++:1002100000000000000000000000000000000000DE ++:10022000000000000000000000007975FFFFFFFFE4 ++:10023000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE ++:10024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE ++:10025000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE ++:10026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E ++:10027000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E ++:10028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E ++:10029000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E ++:1002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFF00E478 ++:1002B00099310C44402000E80A0600000041AE1EBF ++:1002C000010000000000000000000000000000002D ++:1002D0000000000000000000000000807875AE1EE5 ++:1002E000010000000000000000000000000000000D ++:1002F0000000000000000000000000007975000010 ++:10030000AE9E0000000000000000000000000000A1 ++:100310000000000000000000000000000080787570 ++:10032000AE9E000000000000000000000000000081 ++:1003300000000000000000000000000000007975CF ++:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD ++:10035000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD ++:10036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D ++:10037000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D ++:10038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D ++:10039000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D ++:1003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D ++:1003B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D ++:1003C000FFFF00FCCA620C44407000E80A0600000F ++:1003D00000410000000000000000000000000000DC ++:1003E000000000000000000000000000000000000D ++:1003F00000000E1E010000000000000000000000D0 ++:10040000000000000000000000000000000000806C ++:1004100078700000000000000000000000000000F4 ++:1004200000000000000000000000000000000000CC ++:1004300000000000AEDE0000000000000000000030 ++:1004400000000000000000000000000000000000AC ++:1004500000007B75FFFFFFFFFFFFFFFFFFFFFFFFB8 ++:10046000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C ++:10047000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C ++:10048000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C ++:10049000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C ++:1004A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C ++:1004B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C ++:1004C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C ++:1004D000FFFFFFFFFFFF0068C4A20C44C02000E83C ++:1004E0000A060000004100000000000000000000BB ++:1004F00000000000000000000000000000000000FC ++:1005000000000000000000000000000000000000EB ++:1005100000000000000000000000000000000000DB ++:1005200000000000797500000000000000000000DD ++:1005300000000000000000000000000000000000BB ++:1005400000000000000079710000000000000000C1 ++:10055000000000000000000000000000000000009B ++:100560000000000000000000FFFFFFFFFFFFFFFF93 ++:10057000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B ++:10058000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B ++:10059000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B ++:1005A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B ++:1005B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B ++:1005C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B ++:1005D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B ++:1005E000FFFFFFFFFFFFFFFFFFFF0070D9AD0C858E ++:1005F00000500C8500C004000400040004000C85B9 ++:1006000000500C8500A00C8700FF0C8300810C407B ++:100610000024DD610C8500B0040004000400040027 ++:1006200004000400040004000400040004000400AA ++:0406300004000400BE ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1161.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1161.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_1161.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_1161.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,1068 @@ ++# ++# $Id: FPGA_1161.hex 9732 2011-08-24 19:13:55Z dima $ ++# ++:020000040000FA ++:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6ADEFF7F00D89210006ADEFF7F00D89210006ADEFF7F00D892100000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665562635523235D2F3712751111551111551111551118A ++:800080001551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111551111511010000000000181AA1111A2101000000181AA1111A2101181A210100181AE121F112122F21F1121227212592121AE12154 ++:80010000F112122F21F11212230100000000181AA1111A21012425120200181AA1111A2101181A210100181AA1111AA1111A2101181AA1111AA1111A210100002425522225D222F112122F21F1121227212552222552222552222592121AA1111A2101181A612125522225D222F112122F21F112122F21F11212272125D222F112122F21D9 ++:80018000F112122F21F11212272125120200000024255222251202002425522225120200242552222512020000242512020024255222251202002425522225120200000000242512020000002425522225120200000000242512020000000000000000000000000000000000000000000000000000000000242512020000002425522225EA ++:80020000120200242552222552222552222552222552222552E2E5DE9EFFF9F9930F24255222255222251202242512020000000000181AA1111A21010000000000000000000000000000242552222512020000008485D8A8F11A1AAF21F1121223010000002CF112122F21F1121223012CF112122301002CF112122F21F112122B111A21F7 ++:80028000012CF112122F21F112122F21F1121223010000008CF888888FA8F88A8AA72825120200008CFCC8C88F8CFCC8C8830C8CF8888887A8A55A8A8598C8CAEC8CFCC8C8878C85588885588885D888FCC8C88F8CFCC8C88F8CFCC8C8830C0000008CF888888FA8F88A8AA72825120200008CFCC8C88FACFCCACAA72C25D282F8888887DA ++:80030000282512028CFCC8C88FACFCCACAA72C25120200ACFCCACAAFACFCCACAAFACFCCACAA30C000000CCF88C8CCFC8F88C8CC3080000008CF448488FA4F44A4AA72425D2C2F88C8CC308008CF448488FA4F44A4AA72425120200ACF44A4AAFA4F44A4AAFA4F44A4AA304000000CCF88C8CCFC8FAACACCB2A2A22020000CCFCCCCCCFEC71 ++:80038000FEEEEEEF2EF222222FC2F88C8CCFC8F22C2CC7C2C59CCCCAECECFEEEEEEFEEF22E2EE7C2C55CCCC5DCECFEEEEEEFEEFEEEEEEFEEFEEEEEE30E000000C8CAEC1CFEE1E11F1EF2212113020000CCF88C8CCFE8F99E9EEFF9FDDFDFFF1DFCC1C1130C2CF112122BC1CAEC1CF221211302CCF88C8CCFE8F99E9EEF29F11212230100D0 ++:80040000ECF99E9EEFE9F99E9EEFE9F99E9EE309000000C8CAEC1CFCC1C1171C1511010000CCF88C8CCFF8FBBFBFFF3BF333333BC3CAEC1CF441411B444AE4C4F88C8CCFF8FFFFFFFF3FF773733F17F441411B444AE4F4FFFFFFFFFFFFFFFFFFFFFFFFFFF30F0000008CF888888F88F888888308000000CCFCCCCCCFFCFFFFFFFF3FF333A2 ++:80048000333F83F88888830800CCFCCCCCCFFCFFFFFFFF3FF33333330300FCFFFFFFFFFFFFFFFFFFFFFFFFFFF30F000000CCF88C8CCFC8FAACACCB2A2A220200008CFCC8C88FBCFFFBFBBF3FF333333FC3F88C8CCF88F2282887828598C8CAECBCFFFBFBBFBFF33B3BBF83F22828878285D8B8FFFBFBBFBFFFFBFBBFBFFFFBFBB30F0000B1 ++:80050000004445D444F224244B222A22020000CCFCCCCCCFFCFFFFFFFF3FF33333374345D444F22424474245D484FCC8C88FFCFFFFFFFF7FF337377F43F22424474245D4F4FFFFFFFFFFFFFFFFFFFFFFFFFFF30F000000000000000000CCFCCCCCCFFCFFFFFFFF3FF3333333030000CCFCCCCCCFFCFFFFFFFF3FF33333330300FCFFFFFF92 ++:80058000FFFFFFFFFFFFFFFFFFFFF30F0000008485D888F118188B111A210100004CFCC4C44F7CFFF7F77F3FF333333303181A21014CFCC4C44F7CFFF7F77F3FF333333B131A21017CFFF7F77F7FFFF7F77F7FFFF7F7730F00000000009CF339399FC3F88C8CC30800000000CCFCCCCCCFFCFFFFFFFF3FF3333333030000CCFCCCCCCFFC30 ++:80060000FFFFFFFF3FF33333330300FCFFFFFFFFFFFFFFFFFFFFFFFFFFF30F000000000000000000CCFCCCCCCFFCFFFFFFFF3FF3333333030000CCFCCCCCCFFCFFFFFFFF3FF33333330300FCFFFFFFFFFFFFFFFFFFFFFFFFFFF30F000000484AE434F4434337343513030000CCF88C8CCFD8FBBDBDDF1BF331311B434AE434F443433B440A ++:800680004AE4C4F88C8CCFD8FFFDFDDF1FF771711F17F441411B444AE4D4FFFDFDDFDFFFFDFDDFDFFFFDFDD30F000000484AA4646AA6262A22020000CCF88C8CCFF8FBBFBFFF3BF333333B434AA4646AA6464AE4C4F88C8CCFF8FFFFFFFF3FF773733B676AA6464AE4F4FFFFFFFFFFFFFFFFFFFFFFFFFFF30F000000C8CAACCCCA2C0C003C ++:800700000000CCFCCCCCCFFCFFFFFFFF3FF333333BC3CA2C0C00CCFCCCCCCFFCFFFFFFFF3FF33333330300FCFFFFFFFFFFFFFFFFFFFFFFFFFFF30F0000004CFCC4C44F4CFCC4C4430C000000C4C5DCFCF33F3FFF33F333333F43FCC4C44B4C4AA4444A64C4C5DCFCF77F7FFF37F773733B474AA4444AE4F4F77F7FFFF7F77F7FFFF7F77F31 ++:800780007FF3070000004CFCC4C44F4CFCC4C4430C000000C4C5DCFCF33F3FFF33F333333F43FCC4C44B4C4AA4444A64C4C5DCFCF77F7FFF37F773733B474AA4444AE4F4F77F7FFFF7F77F7FFFF7F77F7FFF97FAA9A9973A351303000000004445D444F114144B111A21010000CCFCCCCCCFFCFFFFFFFF3FF3333337434594141A2101CCE0 ++:80080000FCCCCCCFBCFFFBFBBF7FF33737730300FCFFFFFFFFBFFFFBFBBFFFFFFFFFF30F0000004445D464F116166F21F11212230100008CFCC8C88FBCFFFBFBBF3FF33333374345D424F1121223018CFCC8C88FBCFFFBFBBF3FF333333723251202BCFFFBFBBFBFFFFBFBBFBFFFFBFBB30F000000CCF44C4CCFF4F44F4FF73435130300E2 ++:8008800000CCF88C8CCFF8FBBFBFFF3BF333333FC3F44C4CCFB4F44B4BBF84F448488F44F884844FB8FFFBFBBFFFF77F7FFFB7F44B4BBF84F448488FF4FFFFFFFFBFFFFBFBBFFFFFFFFFF30F000000CCF44C4CCFD4F44D4DD7141511010000CCF88C8CCFD8FBBDBDDF1BF331311FC3F44C4CCF14F441411B444AE4C4F88C8CCF98FFF9F90C ++:800900009F5FF775755F17F441411B444AE4D4FFFDFDDF9FFFF9F99FDFFFFDFDD30F000000CCFCCCCCCFDCFFFDFDDF1FF3313113030000C4C5DCDCF33D3DDF13F331311FC3FCCCCCCF1CF771711B474A64C4C5DCDCF77D7DDF17F771711F17F661611B464AE4D4F77D7DDFD7F77D7DDFD7F77D7DD307000000CCF44C4CCFD4F77D7DDF1791 ++:80098000F33131130300008CF888888F98FBB9B99F1BF3313117C3C5DC9CF3393997838598888AE898FBB9B99F9BF339399F83F33838878385D898FBB9B99F9BFBB9B99F9BFBB9B9930B00000000000000000000000000000000009CF889899FA8F44A4AA3040000000000000000000000000000000000000000000000000000000000000B ++:800A000000000000400400000000F0F5970000000000000000000000000000000000000000000000000000220000000000000082000000000000803BD900000000000000000000000000000000000000000000000000000000000000000000000000000000E03B010000000000000000000000000000000000000000000000000020020040 ++:800A800000000000002008004100000000C0F5D30500000000000000000000000000000000000000000000000000000000000000000000000000000000BE13001210022200121002221100420022112021140210011242210011001002220000212002004200000042210000200400000021200200D0A23A490000000000000000000000B7 ++:800B00000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000180018008001004001000028140000001C080024001C4804000088440000003F4D0300000034 ++:800B80000000000000000000000000000000000000000000008021010022180000180000120020180480010000C061F22480028001248042018004804201184824001480814402400118400228001840022814004818804201A05124001C2821814402C08116044002281A684100248002DFBF05000000000000000000000000000000005D ++:800C0000200100002001001001000022110000001308002100131804000082410000C013E30200000000000000000000000000000000000000000000000000000000000000000000000000000000BE13000000000000000000000000000000000000000000000000000000000012100100210000000020080000C061430300000000000064 ++:800C800000000000000000000000120000001800001100000014000000880000001400000040040000F087D500000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100008F ++:800D00000000000000000000000000000000000000000000000000000000000000000000000000000000B833010000000000000000000000000000000000000000000014000000000080018800000000000000000000F0C28800000000000000000000000000000000000000000000000000000000000000400200000000000000001C339F ++:800D8000E80000000000000000000000000000000000000000000000000000000000400100000000000082000000F013F200000000000000000000000000000000800100008001000000000014000000000000001100000010040000BC3382000000000000001800000000000000000000000040011001004001008200000000000000007A ++:800E0000000000000000AFA80A000000000080010000000000000000000000000000000000000000000000000040440100210000881800008C3B1B00000000000012000000000000000000000000000000000040010082000000000000441400000000880000F0A6F900000000000000200100000000000000000000004001400100000081 ++:800E8000000000000000000000100200001800001C3D4C000000000000000000000000820000000000000000000000281A0100001200180000000080810820080018200140F4ED3C0000000000000000000000000000000000000000002200000000000000200100000000000000000000C068B30C00000000000000000000000000000043 ++:800F000000000000000000200100000000000000000000000000000000F0A19600000024000000000000000000000000000010020000000000000000000000000000200100000000008A081C3C6300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B01000000210000000000000048 ++:800F80000000000000000021000000008001000000000000000000200100000000008A088C34F640010000000000000000000000000000000000000000001100000000002100001400000000000000000024BF6B0D000000000080010000000000000000000000000000000040C2821400000000000000000024400200241100008037E2B7 ++:8010000040010000000000000000000000000000000000000000000024241400000024000000000000100200110000004F920400000000008001000000000000000000000000000000001180080000000000400100000021000010020040C2FCB3460100000000000021000021200400200221000000002100000000000024000000000033 ++:801080002800000000100400400200B04D020028000000000000000000001100184002000000002800002400002001000010010020012400880040028002004002D8710000000000880000002400001240420220020000161202000088002800220000000000000040044140422114020020040000BF6E0E1100000000880040020000006E ++:80110000421410022228000000210000800840220200180000001001002003414480581200100600100224403CF882000000000000004810022100180021002400002041022480020000002200210000000000881818000080440200800400005F170E00000000000000000000210010020018000000240000000000881221008018020045 ++:801180000000880012820000248200008001C08F52288002282002222022211262221A64222122121002000000400200000000181218188200200800820000008280280100004248802484044842C8888A04CFD687080022000000000000421002400200000000002400000000002008C0228E221002002100501240011200008800800822 ++:80120000000012C0D8F31D01000080020080818201184A822584011880011800208131122412208121010000181800008008002028280880088288008200190800882308290180F8A98750110080020000000042000000000000000021000000000000808142024002240022220040028200000000250200250200C0F300000000000000AD ++:8012800000000000000000000000000080020000000000002400000000144001000040110100400100E0B60F80020000000000121002122821188041021800000000000000121A81010082002008000020080000000000200400428888C880C48A430582000000000000000000000000000000000000000000008001220000004002601814 ++:8013000040012001002400400240210114E05C88480100220000222002006200102104000082200121001230121002320000121200103242100211882288880082200121860282404122082224414002EC3D9A1322280200288002281228214A82822282221282014002000000244002008001800182009224215022708202228A8A0882E1 ++:80138000146018001A0821424215B14298822324384286612458C6013F76031D81112002000000222812182D422424004002160200001224000012182100181218121A2821E92188D822124212022428882908880082000060288A68144821820029892118E17436130028002220022800123012208125E521A441211220011A0100181210 ++:8014000018298141C212A012A0112001121220022A82282808000088291851211991818A01888800400380C4822384291822F8B6F7002200002880228122813212282381B2120423012301230112000018C012C012800100000082A0182008822008200200000088A081802884288428842804130442824E63F3BA2112A12220082A022839 ++:801480001AA333323AB222B27223F332222B662B557AF21242212B111AF11212A01100A011242D12181E1216B212E1212183A131121A21A1191AA811BA2BF822A22E228E828662280028250220583315A18818821AF98282C227241F18F8C3C1237C42A2882BCC2B8C5A012F24ACC4BF424E4191212A2202282A22A2123AA333182CE121F9 ++:80150000E727D322F142121E331F23D522F143121E12122429A8181A2149B212A111272127212B112B1125022923A2113AA1111AA1911AA1999AAB8B2D622F2EBAA2B8C2D8321803112421407181D313F191811F28B89288F192822BC82CFC82411F34FCC1C22DE22B4A4E464F2694424B414E4223EC281A52111B22802208A022202282BA ++:80158000031E122AD422031E12142F2683E4210125021A091840021A01272112291142A221181AA1111AA1111AA9119AA9AA2D822F22E628F882822D823C082A225222001D8135D311F181818E821A21D822885C221F14D42398C22D224AF482862BC81AA144272882B7ED141D2113022280220228282083B22223E52394222B721B47168E ++:80160000334229E12131121892881218296121242981416221182B11221AA3111AA1111AA1191AA131322F28F262222F225422272833C8212A622223088651313D8117111991121E822423682C2D811F3874C372C2B222E8287646F34294122CBC42EC243D9C008008000000000000000000000000000000000000000000008002000000E7 ++:801680000000000000004001000000002F7F440100000000000000000000000000000000000000001220011A0100250200218008880010011100000024000090822001DC3A4319B23284F21241F01241222F1126F212612AF812612AF912612E922F11E222F952212ED22B252ED233C5923B252CB951C2121B2486B24122B94133921D3281 ++:801700002B491D322B492CF39241182F1924F29241222F19A4822F19A4928E412E9286E122691C2E9223E42239412CB943C2921F44C2121F4462281F442AF941A423F941A42B491F44BA92E444BA92E444B892A4862B4947262B494B865FA646C132422C31612E1213C412134632619E1213E6283161CE1213E62835211F2CB521E23C0533 ++:801780008E53228E51A22F18A4832F11B422D812A483142B8346B13228F4328213E623B941C2921B242CB941E228B941A2881B262B8D1B242BC919F29342119E43229E43229E4343EA19B434F812416B9A2D414B9B1CB4A6C9416F2A89B4A4A9426F2A99644B984C96924CF682BA1301820028000080010080040014100200800818400227 ++:8018000000000080020020020000480040010000800800000000008002440014B0C40F110000008008002D22000040020024000000A0220021000020010000422308000000800200412002111811000024402208400212801A0D82422001290282102124042400480000121002002100122480A2122042220800002880239122100221208C ++:8018800008230825011602002240022C484111114422015240014FEE01190880012622028A084824E0220420641400800125820840021A022125022A022828290900002002322C2442023480082E82409482182A2148022210022718001942422481951210C163F3042004000000112014020000210000000000800300180000000020349F ++:801900008220010000000040012440011601000025016308000000CBD100200100000000000018002004000000110000000000000012A0180000000080082440020000004200210000301280082DF1B30A1C020080012002001200101222023041128041428204420012200400242001001602601100200186022400000000481200800199 ++:80198000002304101202522F49018001001800000000002410A24200190118245012004280010000248001188081010000008821308210022100002021042412002400502240C22DA30413020000002800200100180000420000200400002004000000002C08601100200100000000008004000000200429012088F5322C2004290E002C57 ++:801A0000044812000020021400008001A014422C44011021018081A831001022288104484820A82888003012282100442480014081A441200122442400004935328082220200280000002140221443021002002001210028002004200221000018004A020000280080080030C220110200002810041002F0D4CF0000821200000040A111D5 ++:801A8000800200002200000000000000200400004828804811020000408101800446020080880400210012200110C2A883092829222401304220010014126022424002222120018004421460121200008A01404282A84180051480288822082834122888006121802111C2411A041800000000411F9787040000002220048001232406102A ++:801B0000020000004200000000A04412200100800260284A0200008001248024282CA141828008804402001230125022C052930A24400224C02240020020012014021224001002242100212941C2122001212448808404242C0400004200002400411841904490441004490841100420444441F4BDC21001008002001100100142100148E7 ++:801B8000111C02248002121C0280024E214A14C221212002100111421388D11101180012885820C114390888441248214C25A8112011038818301400211EAB63071B14008004000000422414240042241344820442242C040046011480041813012110024880080011100342290460148246C18240C2111002146011103282401412061434 ++:801C000029D24B084280042306422831003041001001904180052B42122A042A04142848282119C2224211422128A062802284A2812A12E32132812A1A822281884801160188400124181421862181039012492188118434D62200110011000015022440020040220414243C04000048214800140000311003111001004218001800800846 ++:801C80008001420048200100201104920048EF8E0C00002002000080A411000011110000000000001A81A2112001000000009880044A0100230123428201241A080023048004001A01820018188031D600118002282842102304008044020040011B211001222A0121280028800220820440020080084001228298881840C18410424104E7 ++:801D0000304143084901214120040018FFEB074A28018848001410214221741322543250211002112582042414482501118091411848201142021B442592419041108301208881210400000040820842100221002001450412116E95C34D22643280825221140014000048304242141800481190814818182622022210611220810240017C ++:801D80001C023C0334C0720040810412922081089860218800000080824144828844E1EA096A0800CAC4212124422C0260241A44022C642425A2441AA464298444A244C04223A221F041422CD111A2342B1613F4131324241C14E1141463143724271C3F28A14815A1421D211E82681E425A8128F1119514171823215812158104F01311E8 ++:801E00006B8417112381A1984C11A41518181B141E7AE32CA4491D221421221CC4211D211511D11274417111E3214172415331002C14731151231E7315623221481F1152116E223E321F24E511B1417141B221E22401101293423324B4518231218812298924011AC882122C44A111250443088A84E8242D8141624190328021B144013CCA ++:801E8000A142E9043D412391412130622A1202211180642414244021C412111582623468341C3652284002282A3422283A019062216A162332212A9811221D1336A29122313AB142A82256A2988662494AC194248E564A55644644A5844C21D8610125349425C282637894C4424F82335E21100223082190428004000000004081022880FF ++:801F0000020000402104420000200666026282262268226022E022042440424442044448444844214E84400444000010046FBDCC213D133F21722153232D422F267641D333F442411F34F2224337141D111B511225513335F242422D521E4233F422213F22F331633736273217223CF231211B222F22B772B331F732312F13F333313F3263 ++:801F8000D22161212D233F32F263233F327241F121433F337233D123F8B3921F3AF321111F21F222B22F2BB512EA2AF8829327792F59F911122F61516625F5111117496F44D152D123C985777175D626F892966F2951223D822D866F28F442326F433C772E622F21F523211D21882F247623F141411551331F12F243431D411F21A55524D7 ++:802000001D4135D3327442B252F143432CF261233F35F1C3C33D213F15BA62F231331F12E222B272F733317E721F33F771731F33F323231AD1227243D331F423632F12D411F243732F32FB21233D733F19FB23213F33F31313CAEC12F292822F29F891915F18F995917D176F6159267F34F555954F4474147215F357455F71F11111F0A219 ++:80208000B26F69E94183F182126F68F844442E74BF56C7631D531B3537131342827443511115D1317662D313D411B5516125255312111D122F21F112123F31F312433F267153F383232D631B256E213F1282E222F222223F36F732732F37F133323F23F1331223417343F34363357363F141E33F38F991231F13F8D3313B919E33331381A9 ++:80210000C42223E2117991F185133F59311516D216F8C31443AD544F31F551D75F15791253222D866B8B9E126D123D822B898E5667242DD7F3F663213F15F5313315F142422B4617321F14F4434335F36161357341F151511A542237343543F252522F25F553533F27F543633F33F743C33F36F4E3412B621F137221B162F672723D733F7E ++:8021800027D633F673733F33F313332F2121F241412F32F663433D631CF4E3C33F1BF383911F38F931131F1B5B112F31F162621B769AF812123F39F181153F31D911F1841425F6D1C31F15F94444567413F1D3D15F71F917172F21F116B6982F21F152522F2CFD84842F24D522F4641A0000000014400140022414004E1260242004242089 ++:80220000048012812284021021011214211421141814000018800118800100000000421220010092200112E0A1311F421001423021480040119142180000210014C0434021440200214214281E41193212004221422024019011121100800C308118121400C041004011210100008A04008F7749F122124AF4221213D422B141D222B141DE ++:80228000D222B1617282B24122F941212399212B4919B29284F29241283F19A5222F19A4222F11A4822D412AC9412E921D412E921F14E422A9442E921B442CB941C6921B662CB16166281B2696B2617292B221F292C21B222F2DA4222F3D24F2D24326F4D25347422F15F424842D414F42E914F4249646F1A69646F12696424F6229D42469 ++:80230000A9242CE944C2124F44E2183213182D414AF31221F01261222F1124F412614AC8612E921CF421D21CE42249E1126D142E92522E8313E522B841E822A914AE131F2422F9412227194A7392F141322B494E222F19A2242F1924F49221421E614AC821182D61582F1886F9C2211CD51282BD43829523D83F458AF44334181F64EA21CE ++:80238000D441AB491F642AD161A2496CA2696CB29464629A746422F164823DB180080000000000880000000000002008122821000000002200000000000000110000000000210000000022100410C163830E4200190112000010818402242100001C42C14118001411C04180410100000020B422840120311100200800480060144400149D ++:8024000080042901148008000082427F628F82081022D422083011800100188071214202180010521148280080024880761281848801480080022D42400124004220C44100000042862444A12160219041254402200819D8B4092282602248242908000014484A02C012150200191231439280942129011C8422314190621420A821208464 ++:80248000642612282146E21441019081480080048211128094812C2444B1120200E241244004144CFC8DDC004240210112141280010018103221248001001410011400000018004200000000180040020048601400201404004120011612512100800888C0419303000010012400002160110000003011224011420100480080044002806C ++:802500000228422810020080B412028014220200201484880400800124200424008FEA09213041000000001602008021220424602200200200002004A042110010812401121E232800C02200183800194402C0440012A041881C541248250288004A24082D3C4316021C040000002011120211800200242814289021100100800480641400 ++:802580000000224222482A1123020022A012122A215412220040041282584840021E42248088042308F03B6C000000140021000080011820040024120010020048008002002110011218804202002420140200602400A044100480C84110012400A044002D814307C0222234000021204411018012128304622642022812003114480000C7 ++:8026000010013248120080022024070011001100406141231112020012000098302400432824F8BB3D200428200420C24128400224002114502200000018242C0280021121402282224402C0418041828184C232481D1122242008182082C1842C081D142800484840044C060026025C1504421A0480044200200800000000200500000012 ++:8026800000240000002111281800400200800800400210024800304400400200C014006800F03C2A00100242422044B14202860115022824103242683824002A0150121061244002C0210090112302208451220032A82B4111125012002C4181512488414C848102904220C4841200482E2424886C351542484A03150280020048248084E1 ++:8027000044020024C042000000280022110040024E124820011422001A0428002200230800A8484082484104180000C01448008848F0F2F8482A020024202101221811121304601424402221126222001CA122808452211C420200144200100140021C011C0142C0222414408241022490448888125819818401424880C4824180C4E91346 ++:802780000B214228002712202624222404460200000010A21218100213A121484A022819A26120012B41201181210180228402100122241442106121C22412481100208104248004008A015F210D421252311432211110010000421A81051A448104390448C04380840100420000100160124266012308A0222904284A810112242044012C ++:802800002800002400212B4424000020C844D307902100402124044200205112172400212220011021010000122001801202208202004220828184C1212100422411000018111242188014011800004904003FA70B00101101902120021180148202110011901228145011408382A42230322A82022240420223040080218401210029124B ++:8028800021C212A0144002008A381240822144042004A088804437F328000000000000160212004001240000280040430280842444010000142800001C11C21131004230114239118401111242304180912648C04280040048B057022002103252521212521120240400002880020040022800A0440080011100120000220014002C05409C ++:802900000200104281A2210080220418204204004221C01C430E100111000021110024805421401102241820041470410214004880010000210028800600007820341210828104240042202401404232120000242416014DA600006012484800482C040030428004112304621082220C1210420221200411200328121061248282102114FF ++:80298000818411E11402501100821423115412881B8400000022144100D08438B12224902121311E212027423152901148C04119012C01141A430390612E132F125412221466A2452E121CA1424001241A82068022081984D431D222E4221222F4126218213512D212012958224A22681C82004A0710A24400474823E81804AF650FE01116 ++:802A00000514181E4118A0444E411458484A51122F31128261242C022D222F2482819121111420B32121E227B22124A2423A213212241218122E41481E416682A21212183A853452281E224239113112412531422A1221A51C136423122D522B454B41469244421532C2181741AC34EA4AA6222E4134142E432D521F1485B21382C64148A1 ++:802A800025324221521433041F25962242182F261621156324111B542B462124486A0417121384314125322315E112837422A2881A51113A51111D41142F2336411D231B114AF551412CB4124151151E544AB813B141E1146C252751F012622400424224884AF4A4D720246114601440012240210116021642A141E021041A24C242221947 ++:802B0000249241221118901248800414002128C021800228C021C0211820041170410200154224041304100221000000204832F8AAA4644A3241E0144401F032124AF453425AE424A4151AE123B341A4151AE523A7642B373AA7737AB671A2421F22E412A7536AA6133A23A7723AA1331AA1111AB312F372723AE31283F72262286AA732B1 ++:802B80002AF322326E212F24A3332F23B32142A2115E124504E022E242A3999E921AA8BF23F574242B554F42074D444A96412F4404CAF49414DFC689A2646A661217161C34421419C2322B414E533985B112715282F263515AF51142282B462F26A7532F23B372FDE1712E713B2B2B643F12A3775E222F2282A7261AE717E311B331E1219E ++:802C0000E123E323F772311B213AE223F262222B627E215E211F13E211A6621B733E722B272F12F113511F25D143799652121F29B223B636EC1DFC92511BFCFE525E746F26E545B236E666B44634641F24744482EC44F1946EE3A8242AE61296214A641116A1111AF33212143D124AE4259542F022221F15C141246E227AF322622D226AF2 ++:802C8000B251BB31971217241F32A4627AA7222F22A6272AA7662E211E211224212F2727E213A3512F22D622A8773E513E312F23E116F212337E722AB33341B213F151126F4119921355F264668AF941D11AA9FF2F25F474742B546F42D722F244444E444AB442E428A8D54F41D56B85AE723A7371D333F4431335D111B151E222335215E9 ++:802D0000B31384D422F112121E6237121B145E122B612B322F27B262F112722F13F1D1317EA33F11D413D611A3276E222F22A3776AA2737E313E111B122CF312123E7227171D311B533E6227262B7A76E1317333F313633F26B372F732622F35F333113F31F551523F457196D23258613D5449E43DEC19B5D1EF2FF552746F27E565F6762A ++:802D8000422F66B446A6444EC6C69252DE544FF51D0C000020044200000000000021100200000000004200000000004022011200301210022381140221220018200442002004002400DF650D2A4261211424A01111E01204402244420100102202005021100111002142400100104201482C08400114004A041810011901122819044890ED ++:802E0000418250220042808408009C38D919B212D421F31241112F1134212F1136212F11B621F812611B922F11F4219227111F227952E12239522E9213E532B943C2931B242E131B2486B34162191B3427191F24F392411F24F392411B242F197441F2924117222F1936612F11B621D812B621C9411F2249F121924E212E92422ED213C4E4 ++:802E8000D33B243CFD41243CF543248E431F44E219F441242F19D441F292411D262F19C4262B49442B49222B4943B212B424F856511C7422E214E423E116E422F141212CE116C21217169E126E218E121F14E22861148E521B221F2C9521CE51283F2C25F2C351AAB2C3A4A33F1594A233E423DA11B4329A412F23DA11E423E816B432F866 ++:802F000041612F21E8127612F2612196E21626F94121272D4E219E421B221398212F1D2472D322F2D34143FAD3424F437843B13231434F2A7A41D1643B412F213A416F4229F622924B242CF944642C88E2483C5720080000000000004882000000008008180000000000000000180000000000000080081800000000000000C021F05B7C08 ++:802F800088282011012911031A04262113424202284800481800B04102242014011A012113011240029042882002824002292108488A85014240044A064200C260254821299442258202218842DC33B2132208200128428082011611011124212421A02127121393121061322A8482012C621218213A3462008022812211311228009A02D4 ++:8030000060242818142C0823433142246100C01250421228005928D12101881429F1933A28882A8102160223228482E11243031D42142121144280E1268252211A1891213562227280B21232112391433AA22400200222008822482823089683828CA4112984D112C842582CE42204800424122F2122C42246D344D1120180B841D1F23AEE ++:80308000B411001400190118480018000029421202C01112202402486011000018C0120021301242921332120020410248801181082210141204002309490440024A0826128208F0A3CC20016014100122182218158141011400480022002012011100C041230300184821480012002AC4821400004A2802220035024800446048200128B9 ++:80310000200121480080C4937307221E4100006011601128168202C0123824181A042612220628112006280020041400004081925280C121202AA828102204130142C02241138448411491455724C6142484840888124860214FFD05801421141101181922B1112112231181116121481A01302221221400200400230142901120840490DB ++:803180002100580011A0882224220040032448140011144564412904414824800C1280413F3218221800002200402121021022022084028084824211810222B041020000240020011E422870A2018A02208488846211804422428484486448304119C484285220080042C0427FAF05122AA922245A041E410028212C014822001400211E3D ++:803200005188A0422AC611400320A122B0120240A212102101288081A8442B4210011C0128002A829881A0123127281841421901A04823823424644221422CA422F4938E04482200260200800120C421244213828402003304E02104293451104201206422220060220000004220631413041001202188210129044400304400384841480B ++:803280001A828A01DF2F024022284121012B412C121111C241180024602120040000400200480000001200A04148004001002800B082210C2450214E240000A82D81E032024122448818004A08CC38E758281A8481C4512AE13401259121168291411A4201213829A424E01401346262242442121221282180C4222C01141228424A0280A8 ++:8033000064121021621412A0821385226231142374261122C41443642A8230A568224C143482A02548AA81F238E6003022301210820422211002209242009012808822041C0414304128468101220020012C0100186028420012224290820020882281080050111A8254628081044A3412288622C434E302004820827212011100384818B1 ++:80338000002280020010120100188004404261121220812421031A3282424001348004428A012460281C14842428A48154001222002882480000F0D65FA012001400000018112890123022212941611290610000233212002CE4228201182818422C41229251228A012002A21490410048E02408411800414141105432491114C414242C20 ++:803400006821C20046C423F230416013501200208412021140818104100200002B12143021181442140028100114482410224181C94240D22109290B22144AE138848101414114806421352412A18149318244009A0412826BB910810220022044020028000019229111481416810100A041212001200446011800200413141202901242D5 ++:80348000004011020022436214204104A0883240A284214A44C412242001FC31D94200420020240600000011241B4200602424480024200120112281A4141820841202002008118008004A080028444110044502604449022443149444644288824A22086F820B30222410011902008002004A120228110000004001100111120000128079 ++:80350000011842828024282824240882112800A048A08824003121113015A048888008424D8448C018B21120044880040042002C214482A412002A2423220320014200212222001126020028282C8242011982C22228121A8824A114200100411001200400180020080000F058E9481CA8630046816412481820040021211430422C041955 ++:803580000620C422142A942315414112013021211042023012808808212B8A9824421811A80082B0122128211201D024048E827042A2212991124A3122118019E1413FB48004808A142102488004248014210427142006294412822884012442002004254181A6414848B0124451121C85042A044E81601842528001E0241881911134117C ++:8036000096110141200928C0141A840C88EF330D4EA11386641713086A26A414424E1180244291121CD42265224829B611041B54243022350237164842251221C1423621011E5127241E125A0172250125F3624214B21A48033C8EC3528A58236BC2584450421143D834D122082A62214D162B4424C24B933F41A14882136CF833734131B5 ++:80368000C26A02481417141521662400121D1221126AE21296412A721291611F23A6162C4431122A62148041F1512132521344E123F2131148187A52217827222D912F1CF8D161628A3AB23D421F14AD7C4A8C6C1458A84B1147414CF581244D851D4459B143F484855F63788456224F2DC1242D264B142F25A8C44E423A64198AF1D8B4BA ++:80370000281812468344B1620223438124B242E2228255223435A2212985220615722202281E43142F1423D131C122422312F26131469241582C022B642E621CED180929A2891B2821293981188AA81132422CA1848A7251147241412251411924F521131F4115A58C9E94DA98864682E8418824D1943E57002024188132410080818201FC ++:8037800018901180011C05182118400114C041004001100100426024821182112308239841824882480023984450145014501424454112C482412C18C4820020042F2D8EE42435522E42214AA4241984A656524AA51422181A81F122422F24B572F7225223C4322B732B1316D222F112722F3274422181E531F2223223C3313E32237222D2 ++:8038000032132C7142F2621229E322A3978E121F29B332B621AA2AB22B511AA14180A2C29AA3134B591E122F1162226112D014FD14212AE929A1D54F212363214D821C81E941BB34A99C9EFD53F641412F35A5222F24E614F441412AF241416AA6554AA445323E122F212561313F35F772535E422F25F651713F25A3622D422F28F8121292 ++:803880003F26FF43421D131A31413F25F33232B031F732733F23F31233522F21D722F512522F23B732F511822F11F932B23F16F422E22B923CF951919ED14AA8EA4AA4982F23EB63EB46FB12565F4253721D17115F54F492143F63FBB3B46F43F7C2142F4BF3E2F6CE442F4D7591A2554F43A7C99AF9FBA21CC47323E726F532911B454AF5 ++:80390000B241A7737A25A544522E122361241E231D522F27F443622F23B662E331B66336221827292F22F633432F14322219F511232B362B131E717E7323F733123B135AF152122F25F512722F22E326F981123F39BA62B623BAE2F2A2813BD19AB511AC2C2AA1C19AEA23F19644D6F616213653462595414F34FD96353E843F68A4D46FF6 ++:8039800065E34BE567F9C4924D52CAE94DB624A91D9E67E3F341412F35A5622F25E515F541411F12F651517AA3554AA4542AE222F212122D122F32D231F472722F24F562621F16F473322F25F742421E9225F2E3633B441F13E2117141F173722F21A3111B333F37F733332F31A1552F23F512722F25F572422BFB3F31F912933F2AFCE3F0 ++:803A0000E12F22F832A29E931F15A9CC4AACFB7AA7DC2F2AEB63FB64742D565F4252735751515F54F493957F63FBB3A76F46F6D2566F4BFBD2F62F69B4D2F4D2C2DAFDF4F49AAD99BFE58C0400480080044800204202204222022004002400000021480012004823012908290988C08280010018A0148001000040041248444892482148C0 ++:803A80001200E0F13AE240A12410813C2148004200210011C042C04219024A4212021304281413148202601215222104221266220125B1218164229011825812C82820D924014815044414441E412C48C116212048148228292408DF744BF122124E413E1217142CF141612D121F16D222F141212F28F161612B191F16B292D111B292952B ++:803B0000212B59282F19053F3D25F29351223F11A4823D412AF941413E921F14E4227941F122B21F14E4227941C1921F14C6921F14C6921F14F682821F14E229F841212F29D811F292C219F2D2C22AF2D243F0D3C32E243F1D7424F453414F42F843414F4AF941414F6B5B116F627B41F1269613F4A696426F28A9242F28E944D622E1449A ++:803B8000E6F82BDF2192421F24A3211D322F117441A2211F22F112611D921AF641821E611F22AC411F2268152E8356E12238131CBC52C2811BA52E834AE138F141228E434AF392411B34271B2CF1B24113B492D621F2924113369213E6197461B282B421F182411B522B481F227182E132FD82212ED233E832B582F224D139F824D12F447D ++:803C0000D314F541A24F31E4447BB451216F13C4864F1BC4A24B686CEB49E462B8927464F212246AB8940F8800000000000000000000000020081200000000002008880080080000000000000000000000000022200110C19E922024428201601280C21252241381022081014816C162160111110000D0128481511210210440018014012E ++:803C8000202402208121081C243111419041430241442A28082E8231142E12C2181E82809C84239182FFB7C611291812021880C913241A8482312110C232B04252223880914180341212421021018084011E12241541022A84021A28A682C082A022A0A4802288084E83181F2402248280041E441849413294557512140280614213D434B4 ++:803D000031F2E02824322200103112366221683313612640921233031AC2111E221C042F1804002981012304181682C1116602211420A2148A068248C60228B0910228192499512758822F146243295842412A044CE469C2116D8149E24A34126B29A0844B384543F2D8DA14230121A01180611A8084011800281A042420041B1480011BF8 ++:803D800041400100111246011052118002424001228002225880088200C0510000008A090029013F310141008061448E41131141012111304110014A21010080012440020014112200000018A024106111422118008021113112222358210028480031800200001002259121480080040040F277483821122B4424C0120023414222C4124C ++:803E0000283012152242022CC12114A04214502262A04170118112F212112001230140820C00420012181F2202A02116214416C122101241E418C1414524A88C27746C0445021002430ABC32531562118044011D5250129052001800602221001200141394212004203411C022294201199142211210222C218104804801288021130180B7 ++:803E8000022111001439147441A2862974440200004302F05BA238805422100200128015420222271112400221252112210224242220011412481216218101000000502112266221381129024248241512C52200C0842011A488142151441062240082244C3AD916819121221120218261110030424200141121211114100228231391426C ++:803F00001C052042022429A224800480642100004A82224111012CF2114216011A78822122E124B2228401902228882381C622414324284106F0FE1940A3142810021140022012E2214581D12262142A022AE22404181C08186022008001681C0442222C18512222208401881A048248143248A04820882AA4144042012ACA514002424C85 ++:803F80002443240840023C3C25002100112100282382811211810100181002002219018002128214400240028006408172222198611280088001280021000060424420084C040000202428C4244F9E474171520124502119021E2112200270122141232222F222620018302126E2120242182078218256324A0223044A52222A4432113415 ++:8040000088E81B2112181442A0212D6123A181182583022C24A2244C82C8A2114CC812A05461208C0429044F9238FD18C0321001180021262261222F1114012C21042301113C0424C01100281E410018006024002718420048221A02008A82082A0148821C04884A820480721401224A2162244828400488124918023F770824000028182A ++:804080000000123E43208222A121234101280013444201200180934190116211001200252204421A3C110020848213210121191242810818E04A110228A012884A8128818C82048E48539D211A021220012382218104201202400129021322512128221C0820428111021C02111248B0210421800114001A3822221A0829C1C21344230420 ++:804100001180C4221303002821199442C0141004490280F45AC380C4225021400220024815020000210032002A410100261122B12101200100218004201421024A81028800A0460022222190224822209841432204104182F14442482652442450E463160200112712804251122200244214004041022823542182118AC212100100312A2A ++:80418000183322142908221C6422008002246025142E82140040234106444441B0442148954144C024288A02002041F23E632830220080022C0139A114184A220418184A83312228141CE221C41100D011021C4261134A611412481321341100622A21A2285282188A02182D912218181813C865201601449840812122B7123832124399C3 ++:804200008452A8422A328417E4F30A20228212021502000010024800142418000018111812122305222222002420021460141A0280042C84A32840031100189094C811182425012161111002214004212190EC00200100120000008001002118002024820212120000128002200114400120042A280212008082024832880011004D844207 ++:804280000068100400200140C4E433030012144880418301482A0412100200221351128021828212010080041220023121268111011A14822182042110022128002BA4504200244412361232A1444964622488A0A1242D848888CE16001224303213112204602110022004250113012001202188228112C2210040A2418219219241242284 ++:80430000422280042818134402481180C21150547081C4451A02211CC44145042311014827422A14044CC112AC3542212031231511A1233A4232122823842382044A7243F22312232222A2132F1282E511E21233A12822B032136114681827231BE57081A232139222242E12A8A0A2D88A51224622B382E124642B681816F23424A6825130 ++:80438000412EE12E1512442BC225F553461437732D2227212F21C4667A944225F2C6152F28F43F5EB021F2322220413252241F3141B11261141A61242722252131121A217232B233611223D2221701C021902148383981B211A9421F22C2133D123C94416225F161112AE43484A154A0321A2A621829A1424A13E13862263F58647229C4F2 ++:80440000424941F494745E443F51B462F821442B84624B41474A12E049F224248AA1489C3BCE22238522D122611325C2421C43A1141A7462B241840312122021D11141B141D521B22119E31152121F21F311111581B3217751722191111CA1441C01141F1734624E413AA1524AB1A1B272C8212B113F28A5A223D21293113F12E214B14179 ++:804480005552544F1A149526823F18F811243243F233344334344B18CE844B9D28CE824C62224D948F9D81022880082022410100220000242220021001110010011190418811884800C0412114A042008840028840021160242824100120082148211914022388042A140229D8F43791001AB312C1132B5526F24343212F31F112122B5547 ++:804500001A85F412121AF112124A14226121183D321F36E221F311113AE2122252111AB141A6111F1181D111F1B2322F22FE92839A5922682F13A3221E518AD822A4885AA1191F11C1127022A2442C018A89F792921B642F216114424D14881B157AB134B782C8247F48B936F396144B118AA84827284BAA412B894F6588E222F112322F67 ++:80458000237132F291522F25E331F743133F21D122F152121E32322B165AE121B112B442F223322CB322E133F112416E122B93BE313A3231222F12E111A5161B511ED1CEB18AEB33F3B3527E1117213B221F22B77192531BF5BE122BB5FAA287CE133B31328EA237292B623E211F11EB19F712F55F59F4E6114F11F41421222B8147485F8D ++:8046000024F221222F72FDC5217F46FDD6142E844F62B846BCC48BEE267884D242F5849653DF22F232121AB312E321F153513AF1537325E211F112122B553AA4422F21A5112F21A15425E123622217122F217341A1641F13A9231B3219D231A2311B741B311F11A7E81F19FB32122F2BF792A39A59331B622F13B343E413A6EB2F22A6F904 ++:804680007AAF591F11E123A3AA26A3572C83F281911F15F7D6B25F44FE16135F54B141F2242649B9C5F166225F53B7A3FA46247F4CF932346F49F354D49E94AAFE82824BAA4B116F49FC2EE5282E322B313E122F31F111533F25E331F763133F11F111122F25E525A7432F2631122CF112422F24B22293322F12F131133F31F552133F13E2 ++:80470000F3B1313E211D211F12F221113E517E111F11F721517E212E333F33FF63531F35F113223D611F26777193731BF7F6B242AB2FEAEA38F113322F23B2A2FA92722F27F632211F11EB1BF732F33F1BF462173F517444F164344B824F58FC45671F32F773D3CE277F76FFF7122E866D966BCCCAEF2CFEE2A64F6AFBB2566F7834D9005F ++:8047800018C0124002002412461202002100802222212201200222601220022242C012304128004212200128A021A021481A6212601210040041182E4118412C61122C011880092CC824429F780C2D3200141A8102F012121112421222180020217212011E12F041110050111800481215A11110120111C0412921022A04288602123082DD ++:80480000100248442301314413E44208241441422624C4864800A0268A28D2F313F141222F1394212F11042F1124F212611B122F11B621D812B621C9611F22C9211F22F942212E924AE222B941C2921B243CB943C2133B2486B24162191B2427191F24F292411F24FA92414AFA92414AF892411B162F197421F212411F26D812B621F982F8 ++:80488000412E9227181F22691C2ED223EC2239433CBD43E222FD43242E123F4462381F446A1B1F443A921F64BA92F441262F19E464B292E464B89264262B6947262B494F26F8D498482C7341F122126AE422F141612466E121F16121866216921F1672D262162F29B421B2D134212F3924A249223F39A42A3F39A4811CB43299432E921F77 ++:8049000014F4221219F4A2121B44AE121B42AAF9416129D811D222F941612D8226F192821F16E225E814B2928CF253C219F292C3F051832AF2D2434B28DE4243D313B4B6D313B4A4C9416B1A486F2AB941F4A6122AF4A6944AD426E94296824AF61268730A82180000000000000000800400008800000000000028000042000000000000FA ++:8049800000000018000000000000440020F1DC42143012422375124102804182541118002901110012182E122200161112011D2124262101171670820192603120954282284A0282008828200A211524014034C1411120524542266444244D42806824488A21E2923AB926A228172200249AF2411228008228269322122821298384220167 ++:804A000090314E122868C04118882022014218124280A8162C2224F142113928A52198881F23A4248A8421A2414A12924226E2128422644226614122284331224A222D210140F4824188EF8F84C2A21A92312091231C052A4102E0229141222961121C2122240222239211182A738341A31411112F1283C1411C4442A181522A61384A0342 ++:804A800023A4492C9C611AA41A8AC82346A1A218AA82846422492884A1E424432452412A022A512447446A1626252198C4782B283C0B150246924224E0281102008E4111282412104202181218122A3142200400A80080029800001A62242074122102180012C842002C118111622219521450142812159444282220490242214180F8F27B ++:804B0000BF1C34121400008044820440021E82D02208246021400224280080020018199412100200100122884E4100001A094A21A214200424412012410422A0180048441086248104D0B23CED1081149251212C444283711271C2D112A4128021B121410242222A046810632429942114424691C32E4213F8824142128E428A8594A21C59 ++:804B800097811D1236A2212B24218A01002C28031C41822104212F42E44422262514C444215D422D144E8298236428484C8264415B5F34521944024602272414C01134B0420220781232811042020042342224421332214E41882B441B821C084A819842822835811AB11289835222888028012A8101001A04D01212142426E1448841428F ++:804C000044E4418431849823A424422CD1D438970011601100C0422961248A14311218290132218025A2242122249042000040612133B4124402421242882A05142C661448802101482CA924905124400628238446840630447042314223183242004142F0782D00182A02001840023188800482283C04801411C282882C8211411231519A ++:804C80004224002142A01288190248281A82044AA44122284003C0512870428218E451137262022A41B244A1144D440020C2840044221AC87DC180012A041921811242210121200486324213022418A0124286B241612114230440021842208C0AA018242044A11820A214118842130200004882421210220110042021AE3444412002A01A ++:804D0000424F6C0400003100212021026023100280828102108202002800404101241A420211244822241502882231281824800221860198000049C4414149280228480000B022848402DC354C0012481419012C11D22151122088138228B8426226222462211824262246438122851442931146A21468241886B1122204194721A8684A59 ++:804D800081C2211A682400E0114401D612A414644F242294314341A241604258CA224524C8222AE444A2128AF2316D800122100212228022012140022100E011012422C23013C04110010040028A480160282A448292124224132281022821222988C2420040210244424C2AD444810400000000481C228A0224286034240026A142001359 ++:804E0000A6211002001822A0122800191A4202200410A1424002004820011220041848138888084890113011242844823041434822A52823882208B0A21404A048DFB30724200200002400001092238A018AC88214000020012800A0E82042021B88152121840200192284B2811252220021188218230800000042004722001841128632C9 ++:804E80002424002D12AC3EEE80149241182228192422084228821002C052889042281119642442001100481C381200114A012921020082111800A0814E2232290114482812411230825904282F4182219814180043A1C221C2A03426F431D60080010011004286928110222C84044828119042A02BB0820112B082440260262A880220524F ++:804F000021248A0228A0288A2128691422824AD421020090C2A048002A011210028048022A810428004E9B9321081418133412241211800400001229280A1280210220F2422129220500421122118890412004821C4621811C021400232802004021012880022192001148386880280228D012F1B24D4813024200209421460180121181F2 ++:804F800008821890234210026022110014241011128229820882212018022842A04421622A0411118212288880C541884F43A1C831E014A884428824C082221A48324421E0F233F600C0410000A0121100280020014820420100001901A6822A82020000122082022004220012120082C022000000580010013082008228004084089FF3A4 ++:8050000005468254211C041D41801461188A9481118840A28413048846011521541320448161121CA48816011718105112481462200429E2141882918222223581C7122662222A243341482C8299442C54117011914241122D242D8224201122214202AC17034800384830428004004082044043434282022094A124181424241D2280048F ++:80508000212212A88044830A00180048004031114221C011800C1840624448A8241812441829024410A2A1883FF1C2414EC246E214B53191214633224218421425819612342D822381EE28748221122191E148242226021581A8B42B241F38A225F82F12328248C622C3422BA8F011212E212A28A2C2A219225422881A2892832114182401 ++:80510000E02C44B2A4986114672847286C63684441CE1421218A84A22215F2821C33A12240838435521C24E5127241A2A8601AB0828888EC3891138AF4E2122722350217212A7621726212E12682CA221B242B68C02129E818F281111718171422A2299A42141C8CB11139221886E316F8E1B22F21EE13A1446A91212F1198544A21843248 ++:80518000114AF413114F1C7541A2C1A0889AE82B81A9262CD16414C622B6F4ED12002D61241C449143341D414AFAA1411B4413641A133A62A052CA1182611C6AF2217162171229754131913F12A1811D4386F28141C837321411582B18122F2424366128C84ED21AE32CBC42D122E332E113A8144A42F282223E124A17A1411B382F14F31F ++:8052000024844F4C7E4121F144122EB46AFC12812B312F257232C2822CF994E26622DA22AD49763D92224230413041304128130413841201002081B482421142014840114201484001140019011304420030418230820019240882484001488084D814041418A0848008248008460220D8BDC6211D4223C4123B141F2561212C31532A35E9 ++:80528000114E8182138268282D922F19B4C1A25A2B91B219B112C1532F347243934233DE1224C441CE1113C9E32B2E2E932F23C28182E024F24221113C34436E232B38129662111383B1112531A22C542229E617A8484E222D255B425CBC4468594F61711411E114B911B774B934A5151AE921FB22624CB224E329E3533BBE1F129242338A ++:80530000F412631E513B5133F412531B22DED18AF8C1C12AF283838AEC28F892923F35EC17AF9D2F2B5F121F23E315F473621F165E331BF415F261621CF821A13F35C9213F2ECE213F2999A21F11631D1D6127223F36A4AA3F3686D433A5DE5AF5B2F21F12E113E319F5D2B32C887B42F212521F16A7885AF932125F57634C1F2EB291F911 ++:8053800055546F1EF2E5219AF491112F6FEF61B3D27682F292142F23B262F424262F23A1BB4F21C4311F217442D232B573F1515217211D5233E5163791171C881BAA8E822F2CF882922F19F451623B4F2B14BE211D122F11E537F572233F1E8434732D6133C6C14EB11F13EA16EA1AE232F932A23D81B671517242F242811BA82E433B2487 ++:805400001F34B4A2AB7B2F2DEB1DD233F332623F2AB793E2289A527AB132E417E929F4C2322F53B275E65ABE66F991154F51FDD4A77F2EE11DF911F2FEB64F22BDF2A9996F21FB72622E2649E329E3373F6A1F17D7227443F253431E413F357543F152531B621F17E51CFC41411F1AFAA3832F28E828F892923F3DF4F2F22F2CFC32F23783 ++:80548000123F23F371713F27F763633F34F2E3613F32F2616186F1E1611F1FFBA1E13F2C5E333F2BF1A2231F19E91DF421416AF6C1C1AAF243432E413F36A5BA7E522F2BFB21233F33E31CF4F2B22F22FAB2B24AF612721F14F791912F24F162725F56E74CF8E5241F1DFD55547F7DF977772F29FC91112F2FFF34362BDD25F292922F23BE ++:80550000BF62F626262F2BFBB2E2EFF8842401C041008084080000002C094A0980828112813241280000118A12912211230882482122008822882218222422184022A21480810200004C02230116049200100221F01227A3AA382142160121C041221411481B82210024230452261242014821104112212844E124020011A01414100228E6 ++:8055800011484A81E4229122601C2A81C282212A011442244A12A4A4161181C4A4482C1886328218A0942822121C78CECB412F22E314E422F141412CF141612CF161612CF1616127281F16B692F1612127291B222B591B222F298CF2D243223F1D2CF29351222F35A4823D412AD911E42269142E921F14E423F941412E921F14F412921BFB ++:80560000641E921B242CF941619E921F14E229B841B292D811B2929C212BCD282F1D0C3F3D64423F1934243F35F424842F14B4A4FB41414F22D911F434B646F1A492424F6AA9446D924AE628E944F682924E648E25E33D412F13B441A2211B242711139622172429F6618229F241922B281F22A568114E212E812F18C2523B243CBDC3C2B8 ++:80568000931BA42C9D328E434E32BE4117242B4919F212411BA42F18B441B292F6412227191336121B862F19F6618223F861822F18F421528AF42192C6E1326D1C2E5213C8D32B284D511DA44DD32D344D431DB61E434A7892F1413427114AF812414ABA9662642F41A68696F464822F49A4868FD602000000400800000000000000000063 ++:8057000000000000000022000000004004000041000000000000000000001210045C35B14216144A041602C0381682216122148C31221006281812814D21112385012211841158190215E22866812B488211682306126A8122541221322422D042C292682638218866410128282A2162288845624C47212200248821274329C1847F2349E3 ++:805780008128024214C04124204211A649611440A184244E28E014A85498A042D0A13484421A46A2424C15228682C14120F812812C89880815A1426038E0121432A2C0825111108283C24244119051499493228F12E442D148688118822842281B3C8DDE23024353284B429013304129322210B3222864841D22704532814AE282A141C67E ++:80580000A12418AE124A6111882D411668122B242631444AE226B828E12AE118C4812332E2219212C06146612413833261196A422B186E811D283082130A3224671218142F48D11244E284C856432243F814828829F624125EA24D988EEA1C04000000841A011A1164215112004002008D11411B48004C324A808481C412142100428024A7 ++:805880001121892638212460285022502240124421828432112842282022E4480B4B2215E84108000080C27E6306401244022C01008542911800602200800158602200800484102414062187244501488180615187221071821119022B21B04202522041384224C0411B8400218044028123988882888A228412FCAA7FD0416482101268DC ++:80590000112829C124481F4144D1127212922843D12146420483E22A92188E4815D2A1024C12A3622840E181548123A11215A2848F248108843B26CA9CC11A1C0218140012494BF28488124BA2456441902345841224AC2DC6E8C8CF11A666484480B25204AD44E0613D381441812100162182018735112D113824439221242420817848CE ++:80598000029346820229068C2442847445C212281415021A046032481C84D8120414241124B024A4212D8420814A049044174828482B5828F082381244828D84208C54284C42F472AC00622504A116420228413044813181168224024912A8122A682114248144112222C01110582848AB414D8842291848E84571A1AA1A428663881880FD ++:805A0000A11224A058709824924C27412512B121448408884AF8484430A1A72841882CA2812242428F1133FF8C54244D22265442412C02444B24141014614449422C7641044012925829A84818327429324543024846924248C98102C012403845220081461492884374212412820121128A92222284218918041B28402AC1241A5A482C6A ++:805A80004498387068045F474A84041A3248448001C02210044E42122938181E21508825E1841174A2840A4E124885228451182811221120626330842C828211FA444CCC28B24194228628623820C12121328088818148162134282684544C486146A446442C230443A241BC38DB800118812904622130182351122C014001002A0822400A ++:805B000088111204140024004124000040082223B112022C0100800141400861904841638474110485041200880081806424005E82704C7214C61C460AB022231496343534127D124AD144823811484508871227448F22A28C3850222E481541E1446221112A16E224C4284321110427812B228C55413E52C18368244120A22C636141144E ++:805B800036285322C05289D264147841784138248332215614F244E4484548A824AB448F217424A8428C38D480840344290400688100142421415A22022C082C3118452A844554244A1214081304150600248200812D24468232242791B082824804282421004981220282444309414C58848123019246148281021E44F0EF6F1081528220 ++:805C00008084C1242830122A226418A180022011225111418B848440028285041D82004230124C642248B14632118CE442082243E181480818653A144A24180C441440B5626418421C03411B41278211A51A04108403414CC38E830A2144484002290145811482014B8223128494841861A28C1802409C24224486584200861821C28183E3 ++:805C800081224221285212142D4128464261234521848A2A821B082C81721102809845421728A9142581011E888C84282224A2848974C10D4B4612465462002A0449424248242294228880724894880021241C48428802160422A48C0384824411202802A02218248258217043611284494441C24A19C848490210247A948201121004105F ++:805D0000D2A84502814E248371483AE80081002A4144089088508124801402241222830457228F44B2444224C412195228001D2480A2428362284C02888C14044880848142A1128442281741288D944922C4928821464264141604284C2192443243C42420142281A8814B8E800400242C141884810528144822216024242622223231D08E ++:805D80001242932886081901805611005036849028214A928230A2890849C8281A48B29423088604AA61442A0212882442A2882E8448842F8C21328889A428A0282840A458C3214112848102162483614460124182444844864941411C180A0022214981188144C68842001C2881A8821504C01814A2E02452242424488182F04288214025 ++:805E000008148140481244061418C0622CC43200160884E09A4304240000411003108242224802252448C18280044400200100006414008223014284008013E49801008584041A0100101C2804411286C1427022A4420020C2180020E11234922C4484D441460266CA4243423132488443084581948483964412518614844218C1116CE8C0 ++:805E80008104444C083312918240C8982D14401248028E42702401114911314243111692248F22C12227118582524214281C88420123C8269E44824522A942888443025FDE0F3210187A24341141918B21A1C185922181608424818C528124C0284883912286486841A23122204822420A302424471822A04810213488224A0283481201BB ++:805F0000189014834464488212902280A81282208813A42346924CB0440474E3E1218475483C484416F1326A36732CC1422F2B5482142F2A1AD4327286B282E8A3F6482845E212F28B83E062C1C98742F72267287A52484A3282E79823C22237281FAAB8DAB89CF896821F229A9B22B21BE22E622D544E5B9F98F111221F43B215F1D2A186 ++:805F8000AE88CAE32BD8C2E252E2A4D7147B1BF36AA6CAE446FC54212BA12F586A462D138F83B848F718CAA6724A284D2A72247414FCB444AB9428174225E464734FC226166821C3E111732DFC3848886591E9431AB464F446424CF11232CD83E57424D825CC2C4585297288F18D158E2415F486218C64155D48A4456521E9D228B84174E8 ++:8060000061F22C49AF2AD4118CE84A4AF28228157212922587451C01DF81BA12E4244339461213D494D811FA44214D212F11F139A44F24B865DA4A7E34B24C29B416EE86B448A4A6A6F8287BE3FE44142374220245622442CB642F419216422E63DF8372485422228114DF487822B48993C88CF1666A8D6839D2B2C2488F42B28C414906BF ++:80608000E81DA923A2B214FC82B1492244121862482D9943F712A44B632D184F14E82E5C6C2F45D664BC4EB214F81E1AC74827834D28416D8261984F1815F482C21B254D12674121CB954D168BE2A3E12933188B544AF91C3E80048400800420C1484089280280088122890883441449142818490482810082148284821C0490821C948258 ++:8061000048881450144A11A4848098244228116024821324188192414018420848200222886C3B67682554461F11415411223FB15688BF35D644F261434942DB445A5545D65534842B444D2435EC21F928242B112691221D212F68E244F611146A063F3252314F42F283836566D927488B192AF22243E08181548949F81B5B4F51C9388EC2 ++:80618000916F28FD84882CFC12324F843E1489B242D17AD32AF12C6C6748CD18174C221F48F882A43B8CAAE868E848F29CC2242B882F8AE88C085E4886F4B13D444B4665F44E19B3D732F1156A8F35D1DBF219591745CF96D25B92A89DA6675655565E5F6CF2A758EFC6F22489E9F1974A6F84E3D7F2AD22CD29DFA1F826C9FB16CF41F623 ++:8062000062866DADDF3A746BF725A11D2D4971BFF214966F31BE22F2412AAB9287293F8AF5D9366FBBF4E92CDB2DBB91DF78FC82C4BB626F28F7966C8FCDE1897774F2162E7F9BF1125CCF61DCC2FC5B951CC8914F69F3F5C32F89FF54DAEF4CFEA4D8CFEAFC86DC4B3D1EF88F49B334B6C8B2A434D44F61D764744CF455734574136583AD ++:806280001F91F6392DFF77D54EF36343ED2DF46DE6377245FE47834F3EA8566FE1F3278CFB91CF46F25E3CEF525A6F5F52E1A8F26CE29F41E146E648F869658F36F625251F1A7824FE933B6788AFE9B122F841412722AFA1A1E8BFACB674FDB95F4F51FD1B284F9BFAC6D36F5DEB22FD9612CF24FDAC124F26F67A187FB2FB12168FE67710 ++:80630000C6F44DCE5B2C2EA11F4BF8B3A47F4DFE84AEFECE6FCAB68AFA96DC2FC9BDA2ACFBC18F85FFECFC1F8D8CF366466FE4D4FC755FD634F113628F35F54B3FFFF1F7552CCFB4F46B27DBA2DF6AFAA62155D676F4C3646FAEF57E3EEFF3FA8C3D7FEBF6663A2FF7722DF32E2BFF82FA2EEDDF1EF11D664F26D896FAAD63BF76F225A336 ++:806380003FF2FAAC93DFE9D8ACF91EE32F38B443E2A2FB9A233FBAFCEB366F9BFDED345FBBF32BA45F7BFFB3FE6B6B6F6FFFD66CDE8E2FC9F66E1EAFF1F33F3B6F83F63EC66DDD9F1CFB34A55F3BF986B75F3EFFF2B86FE3FDDEF6CFEFFDDEDCCFA9FDDEEAAF8CFFD86C4FC2F6E864CFDC36582C01461244022C811289428242F28224104C ++:8064000002219022106282250421261822024508E0244809142C1804408242A228A021400428F0922410021A022741450845014110044198412C11A4944189098B14A0144481AF5E8348648441404208463C12152861845045604248448A01A143B281445418448018181441042442402942B892C841002489C2121B248E82421A91292102 ++:806480001F42A244A01949B28A8402B01AE4425812496A141E241429AA446C1AB81498486D82008782126AF4919383F941242F93D448F3124946F41249622F9136242F99B46CF99249DB968E494F22E998F22492DE214F2279C8F4249A9B2C4DDA9B2C4DDB9F44D2B4F549248E4A9F447AB4F949A4271B9DA42F89F449B42F89F441B42FB3 ++:8065000099F449842F99B469F892495B962FD9F465822FD8F464928E495F2249F9259256F524D2874C4FA27DC9F424939F4CE232FD49243CF54B24AE439F44EA19F449A42F1BF449242F99D449F292498D262F8964442F8924F2926847222F89B624F81CBF1CF424229551246E414F22F14C6118DF46D622F849612CE854A68846B5D27866 ++:8065800068B59ABC21B29B58412F9D6C422F1DE842F2C348A634D3323F84F4B62437948E321F94F484261CF4A2168F14E42AF968494F2AF145614F28D118A698DF149682CD652B899F14B2D2F84C21AB1159F2CB8859F252C9413F8538243F95348437AD4B8117956B983F84F4A4921F94D424B941B42419F926928B464D92CB224D1287C7 ++:80660000442F28F94824EC38850012000040080000000000800444000000000000008002000000000000000000200200008004000000400400E03DC4343CC12450E140187219AC42381001441815A41144221EE818C4448D2484004081DA9C24E1C28142E241C11810618186022AE265148898182388120A411882C58C2413C2622853615D ++:80668000C1112849B21C912848190A852242887812428854286848AC35E287148E2812462A3112E02412721802569234AB942460226D41D028981427841B121A348A78A9C26A21460CC012114394212143A21444008885048E1D6622E21481D14821C11249822203B029240880F6822448A0424598386159721864412C058E181212434A74 ++:806700003318CFFAC6513CC224283F44D14211D292734222324A26B211A2518A44C13A414F54028AF288421E2C178143B5A64BB8227162C24695F488193825AD414B122586F214711844A682E8C287941E8B48AD321CA4612554C8E051A821C983072D28B0E238341E1C1F26C8224AE18261864F8203674899321A4B618562C12361814ADE ++:80678000024AC4E1E3D84862811884811008C11218484125582412701201A3915481008483048100224200902112814044080010A5288890181218212250840013041100434254840013248212042381281828D124982289F157E2142741001012011384614240088498C124220048B01311C41222154204442072410111214A140400218A ++:80680000442338410010440224C05200220048100840141804618C54421022C482422084C864FC3EB86022267244E18401896121A4603869721491221912311218F0142883F48421222E822F42094D421CD412041598183012819C91941C9157A918E21422446181265224D6931A1CB9142821B28431242B2141221249024362142E449967 ++:806880000428442A742862418B14478427412B14B04881236466A3D179443112299242152841486284211A084C41C229F0981218C01489D44852114C41A218441D423044106D1218313011421725462A08314E851442807411021B884981928248184C02004144304149044C0245062181433442202484210269F16475D30E4C02442C44AD ++:8069000021C111805225472215880245012C0222A0482C33A21E2423C24211250130184210493A94445901246840C2182642C682C9219112004CE162912220228122C428205618C4004A92282F41C418C11E46166228892524A42CA19F460B2D441E422C22C15A41161208001285A44216098CE211410C88811941A8812CA112554282612F ++:80698000882480012C0488481A1462180021844308892C52A3430141430A1AE84201E82C248142C41CA245C23218414054282E18CC218401894468B4A32F013028695114260A215082A5A4813364242415125821A0283048C122860116181802304147A34245082D84891176982192422604802198544210981113411298428961A24088D0 ++:806A00005285214860836088108281824216466882274280D2C94C11181204008007A12244845044221004502A184948C3448B412C0250410010C1221C9134910018218D4828C1414A110428882828A011866428801122018002C0184B42C82E24428AC44848802422C42483C133331AD34255421638123B14123032A1C01A8F41B84F62C5 ++:806A8000411D2215C2242311E8882268418928F34418789C1248B1840146732DA21427821965D28CC8562C2D19BA24544A444D184146081D221E861E21446B8289381684AC21A1341E421426E24462C9126331E243E542846946A3B41CA4414A227224B24C4178174428814402418D28259248C02821410021C1180041250A9B1441B50199 ++:806B0000251214028400125064B092019029211784208228A41949220880A211A0C12823392425A82884418042B82452881A0A218400255288188784A0627C35F560E4218400819018604A8008860280245882188301282849020047241C3342C682821AB44212618CA01420182104428A011058822E122004181848228301246084A08102 ++:806B8000502442102504E081A224814048E843CE4900400810032AA814912648180144289524A44230223C440485344881A58958828C032005288218248438422813E121D24884F24414281280C1281289022824C1228A420241901426881AA4861218422280E2248521D2E431E44818152444B42214C118441641784885044C420960247B ++:806C000042CA92418210D412394659168412781274414818922144413C21012424342CC284412441C82449082C0849382824ACA181124D12874843084908808611B14822160442428A0220E1830C43022A1102CF210331844082A1122F84012F2222D88802648130128129048B81005012AAC244860888262808418110184402805288A0EB ++:806C8000411285041A8144048014840428188C048A0144004B28184302604148C07B932508282200C06423511C53022210448105442C021227422182101201282A0141268412331250852488400A81C0A80016C428A025E4830223811A9824211881261284B88802004C528426840828186041224E812F4B0B6CD4210144230381449082EB ++:806D0000181F12012284469124887044522522113051422074E811388113242931C4601823244802004711162884E124019014104206100148002829044818484C124291421B1821837442082528F4424845C882631F8242089012441029085082421D22004E822480220848288302811400008502434901488604006028121A04822018BF ++:806D800066C820C81410B484860110042A08608120021820112424028810F2BB3C6411441511428142512A22246C111811012A12B38162414021C82114D0160126524484494895825682381285B44291828002160282430C82C6223884862438888662482D22449A244882848A0C4C0480051222212400881A08788C3594223220C132C0B5 ++:806E0000141230140042A333584D42401A4801E08843984219811A8407244D3810921828412280022504124121861404904240284105204112C22288C05CE06104481A04250898441A825142204214F61D678CF4228E2A31254C1112711218D841F1142885936613F11A744B22457211622A6594882F16E218B8227422215A2CCCDA28F8DB ++:806E800026286D191C7113B21169A24D26144F6252261A812881D412A1514CF884244CC1484D8487C81AE829F4128A9E14C9E83962452B484AB88883F1122429A82C814CB84CE1419446C64CB81DF122948391122A93A2AA2454813C355D27421F4154A7AF12117A72F21B281E122D2435D915E9937189B863E428D11BF2A122139EBC2FFB ++:806F0000247612A4792B11942F56F149614D491D658F84D494A4882BC64D288D9C8EC81F31F9D68A8EC9CEC42B882483A2314594B22CD56882BC24EA61C1A247244BA345CAF24112216F63F94416291332826B248AA69C1AB368EC81322446B695BAE469444F418425B448F184168B744FC7F1A7F2541B642B21582147814B211D271FC48D ++:806F8000F31AC88AF8264C2E126E1817A291AD44413BE48B244D6D24BD248FB862442F64F392786B415C42E142F2398CCF92FFC6662B742B834B221CE492514B4FA14452A287283DA1FD5289FCD8C24B8123E524DB2C918C49D1848A11BE2EF334888F226346A3D484B46CD24EF484144F8424C8225AE133B23166244364261E6885A21664 ++:807000008F24E348522C2F3C3AB54528440845081001201801421240846448488504824880044800884898A08480088B84003028A01230686026302820022608008C0441C04880048C042110821802218121812181F0BD3414DFD2F57F1ECF71311685F71B222F227458D47C732FF68414DD281F92F14337B7119D331F51F48736EB412E03 ++:80708000289D26C971B8BC6EF99648F787EF91D2AD7C86B834E148D711D141F1245A1EA55D1B9F2112E649F1148223B82892326D9ABBAB2E24A849E86EBBB2BA82A3C82F4EBAA2E2E87A92B121AB882E8A6BA8414CF2248C8EC48A89732422F122122FA2F24C928B5D2FA2D4AE7888C628AD822FA87888A6E22F8A387A5D2F9FF1F716151F ++:80710000DFD14378177F18F9717955F5BF2B6F42F82F2F1F12F43B637F3355911F93F167E76FFB712CEA36F6851F8CFB4C2E6F6FFB4CBF8FE1F17D5DBF7AF82D1F1DB14F1BF1F8D9AE34ABC53F1AF39999C7EE3F372EF986A6AC62622F62F2BB9B8F8DFB52F26F6E7EA6F28CE84F48FBA6BAEADC77FA86A6EF3B7B33F39692CABE88FEB2D3 ++:807180009225A2B7CF26FCA6B65AFD74A6AFA494627E429D6F7FF9F476248FE1F7DCCE6F65F53A18AEE6CFEF7536F2BAA4AF36CB2D5FC2F772264F72F1261C4D1B7F31D1B2F67A357F72F1972FCF4BF11D7BBFB3744B767AF72B37FF73F6A7567F4F74245654D9F88A447BD62F99F7FF19EFD3F675CB77D87FC2F9887DCF8261CACF6EFD2F ++:8072000036A57D18CF53F8E58FFF4ED124F886228D18AF53D1E7FB8B86E6FCEC149EA62F4CF9F488AF6BB99EFEC2847FCBF9B8BE6F59F137942FC9FFAAD86B394F2AF1126EEFE7F8A6C46F4AF91478CB361E764F43F43629EF93F57C324F86F17A9CEF88F55C2A8F86F9DA9CEFECF56CBCAF8A3567FF76F61B51CFF37317D54E711BF53287 ++:8072800021BFB5F53F2FFFF9F92394FFF2F33353BFB1F43F33FFB2F237367F76FEBE964B64FFC6F6B73F2FABF964265F6DF9673F9FE5F76D7DFFFAFA3D2C5BA8DFCFF6DBF2EFC8F7DAF87F5AF3BDBDCFDEF2DAEB67692F6A7822FA1C3A4F63F19FAB8F8DF97EDE6F27BDD4FF9E9E8F8AF9A6962F2DFF9697EFEBF9BFB65F53F1B696EFAF12 ++:80730000FF9EF64F63FA1416CFEEF3ECC24F6FAEDDEFCFFB6A584F62F64474BFD2F37A784F67F21858EFC9F95A5C8FA3F39CD8EFCBFC7E4EEFCFFA38B548291201301230122638124322419112264862128822242246A222404442344844814C029634481A1278821451423092001032242B1141184382114412C4122224498241C41200B6 ++:807380004C02442089A421F01224197412041248A042124B421EC573AC2843C112610050924125B121490C4845420546542420624914236432124332412281450125818AD4412198281C44048128188631284C94844CF428822188284919E2824994142B242E880042A44A0883341238704804886024164862882C41D838F15C429CF424F0 ++:80740000128F84F424169F84D424F149212CF149642CF949658E829F44A6999F44B292D849B292DC45F2D2D84D24AF9D5C44AF9D24F2D24943F2524B4B822F94B424E994F4A4924E494F2BE914F4B4928F84F4A4929F84F484929F84E621F949648E129FC466299FC436929FC432929D242B491D242F89C424AF9D44F4DA4926F4DA494BC5 ++:8074800022AF95B424F84A494B928F94F4249287944F2A7948F1A49283F4A49287844D928F84C2928FC4C2128FC4E2F83E9E9B342F81F449246F81F6492427D11376123D642799537692B96C61194F22E499F4248A96ED327CD8F1244A97484DDA1F4DC25A8F44CAD3BF4483D569EA29F449A429F449B423F841B42B414EB42F99E244FA20 ++:8075000082456E9627994B862D414B96944F26C9414F22CD494FA269144F325D184F222DDC349D294DD21BA44F22DD49E128F54126BE429D246B4119BA12F441A42F81C4A42B618F447A927C28F49248C3F292484B82FFBB0A80012002002004004004100800008100000021004004002002410000000000001114000018102401210000D5 ++:807580000000220000C04BB11544190A168801424393C226C48EA01226051AA21410282895141532111150A15C1208C011109A13112239288101244D18A3115A24838141082042869A141818412613410C7024684343822214C86882F01248428C8108CC921270DF0D292841721446029551A819011112222D128C3214611502165A441985 ++:8076000098494554228D16404291848F8212D588132121F2421E4A4144628480044314247184C814254464421A0849D248423482899D441A818236883048504488D08466214362488B81182A88041D228F213A5C1576115882436321435118871447A32345558622387B24874147231C55838147A813D14151251673816841178114A59588 ++:80768000A84512D881836121257166E81268414D12107258D484448E918412231494284C7381C22436C4342F4118F89441C661C11AB228584A874626942444E0C2A4692D242F86E9C1B48CA312824784C01A4F8E0C0024844502408188820924202102800148418B48442450224C1202942A1141521822421E12004608C01240528412857B ++:807700002C4104448810089024290100422A018084180881000082282C81C2AFA303142001100900200121002C28988428888741222126124809802212184424E92488E4440888218D12100800220010A42826A22122C01825E482018C31480041422E48190110C4126B41444818004870C944117A340831144216C11988C391A8C5BA21D7 ++:8077800059248F4811D22421424228C281C993445D242F61E21442D611685486446922D658128D8432A9E184314220C2124C3288E37C1C5C62160865211842C44C4843B2220A45A223802254842A22E18188D242D12A74810C2400A011212D1A4F643A5B2569428116011C14011D181614E8884113348841C0124129024C91AD45A2428B0B ++:8078000021C12861A844811D2C8882824CC64242A4212602D0481A1894242C012141A224288C324421244781182E1883241244A8424283C1228429848154424820012324F1ACA200134102C018108118C824288D9224182D8249222848281A8822514725316215011F14221884F4161A348B94448B18489284122C1148B4C251A844844445 ++:807880001C0829829144412E281243EA22020042B024C1281A188151164728C91106188011426E64E3BF22011245180284910027CA2C93224548C22A842C018424A742814C0392001612D24844188811788244F24228284314044A2112E342741834142141528B811149D182044B1456218AA82C12128C6212852402844241A01238904488 ++:8079000081281860448B91144D1845242241014012B911018885C144811D82C14044448141E8C898811528913145131401118524B34804302884635528104401408CC4288441142841148141F0229220E241088184416958421238884934A8469488105228243C356981104A8101200100841664211200C014208248461252246147228435 ++:8079800022809482110081442118602A8C92182823012A989118452222011241218C1294111008004260144C140224A421C4248021A414845F3BCB3E19D16C528818008D1181A11F21318CA534B835C2218821184508269912ED841A585916F21C2421442A14C981844CC344AC0447A2445A714AD2880785F122114FC2014B911818A742AF ++:807A00009E11184D124145F348458942C2122222884362424CD238C482CD124149F2128487228524344238F0584212CDDAB30E80F114212C42011001221A4262C1C951824123014445E24802A95224211071241A113448259811848D82704802002A18B2240146022A58D2414422008B2460412A61482E91428C0184918C04414248002C2A ++:807A8000A149818489180260245F4505004332241418109881101142684894440028D0924234222032260030851A08841C5442604526314648112B2620021628E58822011AC1728880085814488302284100C08820012303128E1830A84485088D228D4DC3D32441622156A1242304608223032A0116249284908122A504441180042C5B74 ++:807B0000243028190483615420028100001821882A081618421441048186011E8189B84488111148011748181742184480E425922444C821C224498222E16A092001441F8201F0111484200110018044044C4282011555821309112240788498844C4141D48844440A1A0191550219D18242921113C228825F2101875429552CC022972883 ++:807B80004F12D1828158820016521C7021A181481A52C24841234102E051383B1351C12430180024462834241197414216092C61212321A28190812898002821C0211B1200002429618144650868909146145142106222212CD848840888418308810000288904211821894292588A84F1882412301286F4986E14400416142273120231DD ++:807C0000212522182458824542048C414238141012D2421278A45224824011C268A44889120414400810C42429024196D82404648C54A4C01100901470841659148141002986818262441811885084614DEAA32D8401800280014C084F814212C2249884848400148189024110129111851402148042019044A421246C21036041224858BC ++:807C80008504501249088422008C180289068C42323C000045082B82400110F23D5A2C024A741184044629344849625542C01483845211A0446D8228492882810814426084008904A33481491202008608006C810470181422A4234A0840126828124B38004220182404401408890812408206228629014114893213261112215141292208 ++:807D0000184111211254148A048C01A4111741819184151444425641442434444088843428162152482800004140181182512444852221415682003A88D14141A2A18142234482229412811841289F83044589C6421187A284512C6482E0119414812991184A91118D182A3141184CA11421181B126718A033D01602881A1234182A9443F5 ++:807D80003038124381A461299C2245014324724281981850854082419284A324482C49180642008431182012981C2420C1659363511E133D143B17853222ACB513F163128F85DF77E1125E5E57444F82B38463514744C5D288F834288D23E59B136D52C41783557124F438B1447F58487988752E43F528124B24C189F54A157E2A81241F83 ++:807E00008AA6438B24B3C24C5E921D1A29F282725A41C2148AD584F588585F49CD3E6351E44D848E8C47C28D6D4FF1511CF03222256883EF81D184C9281A68A8484FE2F332243F964A3132893642CF72F114583735D08871481207618CF89A1819738D9B122CB3C4332669319C4B243B124D262974120A1B82457D11F82A424F31E41CF86A ++:807E8000142216B56C7144D1245414211AF318323664492B284B914D1421444D89CF4161988BC84FE86868CF2821B886D28A42497811DB48F421192A22A1186F13E282A455272A23959445F8968AAB13444B138CE89135EA69D44DF414214D414E491D2887118D434D2543AA637F89F111182F1154619149F181534E382B142B1853B2B146 ++:807F000031181F1AF819B1ED25AE26372475882613DD84A164DD2A23742BEAA455849E48A13F1472447512F6C2357F21D484B32BF3262523737432616768ED48157A187389F61221A972D6C11A236E28818A3154A914B29241FD28514B24EEE28B442B4F42AD14A722A14D822FA1020000000020082328220882200848A048288AC424486F ++:807F8000808488C494808184014C11011904480088000000800888E014084E8140011482141214001220018220190142E0743A8CDFD756AA6F76766BA8449F11F6594887816F12F48BD26F2CFCDADAEEF18F3AEA8BE318F89E821F45E58DF7C8E8C7C2DFCAFD85C4DFE6E42CF8E144AF67F669681F2AF8A8F84CFCA9AA2F2DFC8A9AAF899D ++:808000007B12FC436D1F45F743522D125F18FB4121371435F51BC95F52581157511F94F5E7B1F5F92D153F12D9265144EF31D1B5DC6CFC21615DD59F36A4111F5554555F56A6985CE651F42A281F39F817453731124CDDEEF4126846E888FD68682FAE7C38F86BCBCCF66C5BAF75F7667AFFC7F5565D5F84F54958DF14F76DD1FF5DF182F4 ++:80808000FFAF5DF6FCA2BF5AFFFD8CDF68F1DA133F31FB33588FC6FB8F2D4FF5F1466DCF65FD92ADBB196FE2B47FFE46A9FF1DE9DDFDD7954D8ABFA9F9FA144D78AF57F66A67E767EF51F9BD611D6BB7414FE3B1787A12F622311F92F46BD42F8DD138D319F211831FC9F88E1A6799BFD4F95F38AFE6F8FE6937BFBF81B55CF886EFFF9601 ++:80810000F9893CF7267FD4F33D829E2D7FB6F23328AF82F97CC26B856F19F4928AAF8DB22EF9BA2E8FF2348C5F14F4283A6E76EF95F744498FE5F4484ABFA1F126599FADFE54C39FDCFC45CCDFFCDD44F4A9996FB1F8D5546F3DFFA2BA2F25D5BBF146369FBFEA31F629ACAF73F329381B4E4F2AFA51159F9BFBC3CEFFEDFCC7F53F54F781 ++:8081800042648FD2D2C8D3D9F1889C8F85F653597F53F23FC97F53DE11F52E1B4FB6F4A7E3D5DBF6E134FCC4D1E5FED6D2EF85FD5DD9EB7EEF44FF4CEE15F34C5CAD8ACF66FEADB58D6CFFE5F42E2C1F3BFA372CBF85A427AFECFB8C4CAFC924BC927D3AFCB8B8EFADFC41EF5CF5517FEF27F7665AFFC6F5475B5FB5F45B57BF54F76DD7C4 ++:80820000FF4EF123DFFF6DF45BC7BF4DEBD7FA99563F51FD11B63F2AF23AF52F9FE8E9F537E99F7BF1772DFB5B7FF5F66F236FD2FBAD6DCFFAFEE581CDDFFFB8FCFB6DDFA7F46E767FA7743AF717BACF8DF76873BF57F3253F9F7CFBA7173F67F3375CFF57FBF739FF63F337567F44F9978CEF68F5D647BFCDFCD2FCAF77FCF75DBF27F1C5 ++:80828000124C4F95F887EDFF46F9943E4FF7F5563DDF23E95BF56E5B8B572F66FD56CCCFA5FDDA5AAFA9F9DA58EFA6FBB8ECAF8E32E97024B14111B44101247041C2241D12289144111E241144F012248427412661411C14B22414F22441D014044D4924266124266124008081C2128E242CA121F0122460417012042308274920518421D2 ++:808300001012044140C812F048122246028724D028088542D428F1DCE18CA81150228400129112856421220023118809214D244244872440382433018400C048254218441884141418B248444204478400242848448210088F248422594483815888003242288001988118008460422C31261D242F81C4242F9144F41249222F9134242FE6 ++:8083800091B424D892F424929CF4249225F9249246F1249283FC249293FC249ABB2C4F22F94B244D129F4462289F4432949F4433929F44B392D461F396481D342F99F441142F9924F6924943F29249CB822F98B424C9494F2269984F22691C4F2239C84F2239C94DD39B2C3CFD49242E139F4462389F446A199F447392D149FA92411D3421 ++:808400006F89C4B42F89C4942F89A4922F8936242F81B424F8C8441CD42411F8241213D624B14DD624D149C2129F44A6181D6423F8292423FD4924A3D941F2D3881D242F15C8242F95EC42F21249A6F492493AF8124B4F42DB92E42149F93492144F6B7948A19387166F23D91CF684928FD4C2928F54A2884E651A7848B552E8D2B2D2CC75 ++:8084800024BF81DD41F24AC8443F851CF4D3484B2A3F8D3434378563D883F4B4B6114F6A3841B63649BEA683F49482C3F694928D249E928D24CC32120000284004000000800400140000008880894402000000810000000000000040010000000040120800000000004001DFFF4711446C84152C21011E1849028F2802424141128240542D ++:80850000CA205412321C2152485018412860913E42D430184858412C24482C751808A41628B414C214203422444654428992321D4481811098112828CC831CA212812616A81118307248124F743A1A83622913020089824242427498358482872A81167714C22228A291148186538414265812C0851D884084313245924A2C413258181F38 ++:8085800084388134283B298A1241488B1291148483CB1138148C4481D21C24024CF248111E4A14418561224112591402882F4442C128CFE345042B618D28844F41012AE261012948A1C190C4AF82C18E6C41F12228211480F12982181170AC4A66418638228C22F1522185EA2184F212142F442164188378D4A2211427822718CC8552CB40 ++:80860000266144D0C8B2C111E52312B17138418F4255812428489F22C61C191854A126C42416E561818116B2243411C93831990215440110088128C12FC812241804190140F42488834403148D249440114191811215046C11148804844E1248919481922AC1480018E022011821450884850481221143816181282994281228252804206B ++:8086800069242076EE4B0940C24110080022508450448290D21012140286081B15222541042624B42401200494404102404102504121000030124912A8228914A41449120848203414841A1189C148002420C14460821E51A336621D2E4D19C100932151844D82BB1C16B2123C98298101244CD28211D8B4166843A11485552C31156C8148 ++:8087000046613A1E4226DA24D1E122F14412C7248C01128968421781811A1248D481711241018C2261412C6481A9416851414792288C134868446145E8C29414214F84180820318C44CFF14F69E415450442841180A88281254A88110488460645C84A418E34482541541161441538141F1429724202C4335228EC54A1000023529118413D ++:808780000011310047822E248C24125C824C12D9149248228181448711E54CEC82042568A81800A8CD18CC3E94298232182518418821115C421D5216243D942988119212288D1224131218381938251858618922C424241889666130111E4480011893486481602284448381419112811818214AE181C41418100472164488240158160430 ++:808800004604004C0541DF264F4261441C81429C12268852121E28C4D0840400C5072816D4423211D01118CA264C51122415082C410840921822221614021E241880911880D44461881445018F8401562821CA2813B1341108847024C48420D288D284263124C484828081D2A43AC6454822425684494122110C40929280E1C1628168115F ++:80888000494428088C8244E218240161193824101214137186C12A21C12608214541C822102C0581B011022E4444112120081E218465210520A241860144290143223228201478C80813C152406211849012302238C0212502218228569812C013108621628124008414416081418041041848850881C02410411832142224001544886459 ++:80890000414004414C62881887A40020058145020081418E2DE3DDE121944639518487218D322CF112281992284F2211964823D14821D86126C45425641939C127378826F214418556214186312C25140A94A1867118C214A112834454498423C3348112CF21486452128D4247871C5585A688D184232102415EA444C3D12C8225B828C140 ++:808980002C4C111428CA28814E14CCFAB2C4401261432223110185C41200819632214662421228162A32184342084A81120214108811C1141016313610C228188C9212008150450012280010642160144C4259448501852822A42894444A64218124840000153CF13514024D12D08106428CA21C23C881411A8889011816F4284280912634 ++:808A00002606411059285488A81282102142D8212921A129224B8189240312C4000036A82426841204804244041812504820C128C4B0184404208162C483F18D934848846D484C011002102812121204478C2F48042304144250812521110498222415C211414C881818041514011188238101984410B1482801008001941CA12881850907 ++:808A8000541601121800C384913850443044682C312C40085420021144314488884551241412888C2621018800122C6121001008884388028C026088A0818C483184488684A429A0383084200190288058481388288168829880482801006082100886E5D80E22128100212480828184240184442291A888216081482092442241A08449A8 ++:808B000014A11210120487224100890220942323044442418480140112189024401438A40081432234944242B0681418346820C1FBC3273C441632111158111119221801519C51418119D54201450218C12382480420E24AB11862C218160284A2411A489411123015124D212A044800004923912414410014201141018714484400004746 ++:808B80008100400888C9D21D021212103856484C9448851401830482853411C012403842201108E04856A8000061A0428419461128888802001A011B1241114E1828418C0228184280010052459421402101400880824184A14449E1983711004C04400221248148101222834862848284A8A0424C14880A000029042813C8A44214429CAA ++:808C0000E188120200C0884420C491200148802582321441112A04848CC214220041808184232102448074638C411224440111114C14014612914121111051C118867558281488210412508142813048458644C2411042022C01814815822441648144261108A0152016414828412504811842814098214110744888031291CC377744A002 ++:808C80001229C462C02440B226440162408A14448862140015023C12C8A1A034E03204288110684100A90A4C92842642091C0213128105CC0214100800801A8901268288A2821214181280064624148849F13625284ECA1E548FB2741E6214237241D4C2F44821D7124F12A81423149F8E1E92E391434B228F8B648C19C24C2AB282BA3485 ++:808D0000A261A489A8431FC8F4A6214DAA4752248E9226752C381A4F187314029EA4BB8A5C9B44AB851F42F474951D111ACB142EB48B411E2518169414C0249FC1D2887228AC284D289213F1D818208811394CCD484A048B72C346B899E6C83E6F124F41D4420516B36A24D212C4212F244151A2545BD9EF1B51184D215B918CF91E424FD4 ++:808D8000B9A1552F6C61322F84541425D158C523561438824AB5149192CF4C944C8F16F413215D1827189A19FA18145E121829981486E144034D6454904810A8668450491C611D1FC4D41951819F447218F12584421789188B3489C1182E38628149E111E44874DDC1447351822D141F54B41451112D418D236D8CCABD42F481E724145C1B ++:808E0000F18C41484FE4B342CC22C01C9722C5F811184C11B42AF2442C1B388B269D12A11B884B229F12328C88CE9A35B888E2123B249499F461311F22F74418407489B8186A814B222AF574612AE111A21243E1187124051D94814F42F38864223AE1C1F2144C4C81E544D184E18441E481F56CC44D1C8F4331E800140000009880084AAE ++:808E8000088880280100114811411110A148114B4811502110088911D428012C4884488428810888288844481604440000008688210882008120040000002B3D44186B242F569119CE113F27F6634ADF64F64FB5BB9DDE8B9BA85F8AB889FBB187BF6858273DA22B892F4C76E7127B35D911FB922CDB221D2D5F96ECCEB885F9B1A5DB9A45 ++:808F0000BEAFF73A3BA8CFB6B57FF8EDC3177CDF98B981EA22F3A2AC47828F48FEC5EAAF3ABFE3E64CF985899F49E819F28125C78A8F42F224799F46F1742115741488F13469CFCEF8C484CFD8F895CD5F93F1A139DB195CF9841999B264C118878487862E784E4CCF44F54C841D3D33F834242B41EF47F6556F5CF811772F32F24B4F6F73 ++:808F800056F4848B1CF8CBCB4F16FA8D9BAFB6FF96976FB9FD43437F73F34CDEEFF65FBACF15F52D219FAFF9ACBD2E151FD2F7C3628FB8EC9BF3A5AF1F19F6BAAA8E849F5CFC5A5A4F4EFCDBFBFFF9F89D9D2F22FAB2B2DFDADA88F8E4F5BFB6F775751F16E919DD99F124385D814F53FB78784F53F779694F47F721214D144F48F8383C76 ++:809000009FC6F74D4DF5FFAD9DDFFCF361E19FD2AB8957C11F11F1282CCFC457C45E3C8F83F3787CCF84F55C4C4BDE37D64CF132124F54F23F568F56F141137F35F6634ABF64F64FB7BF3DF5D1CBBF5CF2A5CFBF4DF2F5859779FF31FD83F45FA9F3F27E6F2FF54A136FB3F442BC5FCFF3BC313E6F6F87FC41AC6F5AFF74ECCFBEFFA3BE70 ++:80908000EF6AF882ACCF3E3DFFDFF6F4ED8FDF99B91DEA2BF9B2AE4FDBFB3D745FEEF77E777F47FF7415578D9D34CF12FA15A45FC3F62C744FD3F56D344F56F3251447C15B282E6987C7C7D4FD9DDF53F5B4351FD3BB3DC1854FD8D149F374588F46F14418CB256E386E5CCF44F5DCA4CF6626F944662B45DFF7F7565E4F54F173533F3613 ++:80910000F64F4BFF16F6DFFF2F15F5CBCB4F16F6CDDBFFF2F78D8D6F3DF147476F7FDBAAF877F6AFA4F47F76FF66F6FEF7CFC2FA3134BFE6F66E67CFCEFE757CFFDEFEFC64EFEBFA23A7BFFEF6DAF25F56F6DFDD7FF9F91A972F2AFA32B2FFDAF2BD3D4F57FFFDFD5F17F7F5715F51F98D9D4B3357184F4BF36C6C5F43F77D7D4F457735E0 ++:80918000F51414CFC1F93C3CDFC6F64D4D5FB8F8A931FFC4FB5D79DFDBA1995D1CDF91F1242C5E584F41E48785F63C58CFC5F15CDC4FDAFFF1C4482381148234121C048C14E2120400C01200A0842004248041044C22048002218CE44882244829088294822A848104430241180022A02240844114490444914C12098416446841481220C8 ++:8092000061821A48E8713FF228214C518440410270120500165521C445621943128A3118ACC424478200894212188442C834C02448D09694118081824195114CA2121211B024016045604560413011188D241C044392191E4844006044404438481004414BBA944F227149F1241297844D129B242CF149242CF949249E92DF46A2899F4479 ++:80928000B292D849B292F521242F89C4242F994CF4934926F4934B43F213494B823D494F42D991F4A49215F9249217944F637949F8249697844F21F949291E929FC4E628F94D252F28F94D2C9AF849242B899F42B292FC21242F89D544F2D24945F492494B22AF9934242F91B424DA93B4A4D998F4B4929CF4A4B64E494F2AB948F4249261 ++:8093000083D424B948C2928FC4C2128F46E23833D24CF232411D242F81C6242FD164422F9136242F98A4128E6547268E214F22E598F6241A4E214F927948F124928F4CD234B188C2532BA43CF9483486D368C34189FA92414CE219D448F282496CF2926189E2D934291E486AE81934218AB425E118F42C528E69DD12CAE2B261112EC24298 ++:809380003CA9243CF949A42CF9483445F349B216FA49A423E144FA16419F44FA92494E242F8946F4926C26F49248C37612B824F8414A80080000000000002004001100000000000014000010080000000000002002004441008200000000000000410011BC3A5F48C0188D5489C4511098283E448C2104114C728104172424901A64411BA8 ++:8094000021484884448541B8882162118C81F82C12902448242981E2228178425428121E443018A286C18112882011942866281308148C684E465884181A8CC41848845210381883941C944F4B024F817842414365812D119823E281D812B48693289EC8341A21B2148994146A9894305989F1221255765151682E44174817148F41CC4350 ++:809480008E149581FC1B499E14296481489611A891896211812F221A4411A211450469912441524B11C41504114D241581A2512E44BB2885A22244A329D184813482224918F122FEB36B448E4A12A71315DC2C812183324E922018B85612D148C1412924621145D248D181E12231C38D12167C2112BF187821B811D818B4887116F81142A0 ++:80950000D422424D1828932368852598112D14225618D11891911D1400224331381AF2241945A88115F48629CE258C952C4D4189B322C4284B418B1212C1848741CC741409CBB9204149A4441217142C58881AE9D294128B261A78418139242C498445B48A091324A2144574414194488634411624749254112A9848BE1642272148960201 ++:809580001E82492291682C18C4822282412C58441A1124143448400100A01246B8922884413882484981348222888CD212337C000018000012400412002444881224420040040044414C08182501414A51840020118424524222441844002C015048404402842012084A22514880220100000020F4441224004D4244104A4A048642A2118F ++:80960000811141251421818814B4187814888122416A128160814A328181182C1808482D18200816684184241E28508426644150648C23C41A49D288012A412884F824388002704204812281499428481245E842C2DA831702004421401A844112828111144284018230484C19888102248420816412161881318A40048C0112128CC124EB ++:80968000C132850484121052243841182218901883044C220240044C024048840442448446F4CDEE0044B042410C008840245118204411DA14081A9416000043C138502145C48841822440840581274420480442242460421247C6505412704808E5588421A21828A486A86138844821188902408C8201A022BC3B81314428642031189077 ++:809700004A810010021508490648811824A21C229312226C0293014C420222831414081721812E1210440812C98182024263A84385B441182181820415D8845284198A522124644343044456E4A41902188922D8A98801109418002418144142A02585283124822484410044290444841001001184461A64819012001C042281114C1823B3 ++:8097800008A81024820824812A216441288014711404129B6288C0484B18810040044145379F8C62842120040022219741504849011004008A34441D249014C484150459C44420E483C82411100125210860A41B12F024182210C4144136024160414054249544080000444E1418804202001A84262401DBD718BB428167C25800160227DC ++:809800003489341C8447A5454854418A342490C4817027041B2387A11E2499D241C44491B025B288C622C18711850A39088D221F257428149928242E1C824D241AE862E1241864438F481511A35365381149D2C84238445564721E1D2F62C124124372C294481A31CA23015E18228E5B830C4110021281B028411401A021188C02403248FC ++:809880006045B082924444415024111280C412451881440418271100A02111169C9520024128224604828444224644180111B200422A8408852441044268414441CF6F07004411002004808114020000403458F012410000418400009A0198111800001D2829019021293128102401001210024800001800008304C0128088028001BC3A61 ++:80990000D24811121A04581048884816882122018642847114C82218848826646444130440143513471250410053C81220C19A524B284B81004112169284107434E8426844414152415D222304C14218298402224F129888C12904248800249FD18104111A321420048508442951284222400240C8484112124A52444A8811011004882A6E ++:80998000419184114C41C22418D081E344811114912212444C0844208314544420D1241201848001008110818112A22800001C3B1D00E016A2224743459444200880015AA4448F84588C97111D151F2102259881E028B884B8948571125A2265C1134D110018B021AA324742444FA841A228828052485AB452F4481885581995B595022133 ++:809A000020A48C8E849E521A7112D62215C2422848224CCA888F62A26247426594842041C22D10040000002004812601821A011002002002410040044400000023410110019800412048041244001800214160420000200248400A0000008EDE430B8C048CA2244C52415400822081A14148AC4448C91114004221A888881AD224414222FE ++:809A8000024200E0848282124404180018A0418AD482444E4B41014428A0828898182C51242400000028288D24444400F0CA1200006A62821141480080089042C210489181000020E81852441224218002123058901126241184140180480129344412854411018004806818492251242100884604812022024180045C39FF001001440023 ++:809B0000000000484048421122010000800124001004000081C504128004840048400814C084004480081840020000000040040000DFE506001001104801003014001818440000100822004400000080018904301821802802002011041042041008000000110000008218841002A84C3B984824202232244512040000402234488191119A ++:809B80001124182220A84892301A2121400400202A722544144428018812102234488191131141042200C624293112212100008120A2124312140482F0419FA041008521221214840800242021243488811111002841448292C92111128284041820082222251404820000163244428181115100800A8A24381812312100000020A242418C ++:809C00004100EC38B4104801181142248480A821800132261204800100400400201201880010180112420010212138128032228241441042044302004008402428012008000081006F82030000180000148888002480010080020040240444118800C44E481820011818002001414400000000224004440028000000400840020040342C99 ++:809C800041211481521210228428881884F18212901249082009000070444504004143AA14488F8425118851188130414A29019A183116B644161214160444222147424400C11902200241428286280121218028FAEC37C048811481949442007081089012882B3124800112E0824272241414C4244440012004C1E011D18B04A015121847 ++:809D000028921634142928D14202000018263824412AC4240040018858820084C018844280048EA313A641486014141421111528042AA1B9130132241A111602241868A02242228185D44502A24448206188CA011B112311430886918880411234121E8425C4148654644148280046352C100444005088400200400870114591494A54817E ++:809D80008F84D41851191F21B111D122719242B212A88829A1991E2225F222242B224D24474244430249A2224CF424244F84A4448D4987841579494191494AD481F858488F18F889811F21B99151222729242B818A98129AE9217216B222B222D244722404430249A2224CF424244F84B444D4987448589197141499A4448CF848488B98F7 ++:809E00008B881E929AD1227192C22A531781A4448C754868B49D11871117213F21189212888A88AB1986F6123226722274261494244084A622CCF224446671447C4858189D411111C84AC4488F8468BC9F18F1981117213D822121888A88AB198E122F21622327426742412800682AC22C4F4264564784C78485D119141181AC448CF548B6 ++:809E800088C6BA88B19861212F2118E25F0C00000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE13000000000000000000000000000000000000000000000000000000000095 ++:809F00000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B83301000000000000000000000000000000000000000000000000000000000B ++:809F8000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000A6 ++:80A00000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B130000000000000000000000000000000000000000000000000000000055 ++:80A08000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE130000000000000000000000000000000000000000000000000000000087 ++:80A10000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000009 ++:80A1800000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B01000000000000000000000000000000000000000000000000000000A4 ++:80A2000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000053 ++:80A2800000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000085 ++:80A3000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B83301000000000000000000000000000000000000000000000000000007 ++:80A380000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B010000000000000000000000000000000000000000000000000000A2 ++:80A400000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B13000000000000000000000000000000000000000000000000000051 ++:80A480000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE13000000000000000000000000000000000000000000000000000083 ++:80A500000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B833010000000000000000000000000000000000000000000000000005 ++:80A58000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000A0 ++:80A60000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B13000000000000000000000000000000000000000000000000004F ++:80A68000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE130000000000000000000000000000000000000000000000000081 ++:80A70000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000003 ++:80A7800000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B010000000000000000000000000000000000000000000000009E ++:80A8000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B130000000000000000000000000000000000000000000000004D ++:80A8800000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE130000000000000000000000000000000000000000000000007F ++:80A9000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B83301000000000000000000000000000000000000000000000001 ++:80A980000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000009C ++:80AA00000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000004B ++:80AA80000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000007D ++:80AB00000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000FF ++:80AB8000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B01000000000000000000000000000000000000000000009A ++:80AC0000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B130000000000000000000000000000000000000000000049 ++:80AC8000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE13000000000000000000000000000000000000000000007B ++:80AD0000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B83301000000000000000000000000000000000000000000FD ++:80AD800000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000098 ++:80AE000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000047 ++:80AE800000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000079 ++:80AF000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B833010000000000000000000000000000000000000000FB ++:80AF80000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B01000000000000000000000000000000000000000096 ++:80B000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1324250200100400005044101111191101001484500D ++:80B080001221212121004002400200000000101818181808114008402841311210020018121E1221251214040000F08EAE40420245040000000050440000000015511185495111000000255222242425020000000000000000855888841E188F8151223503000018C0125064000000C0B313050044451404000000405D9481400100405139 ++:80B1000011A4955211112400002425022125120200000084840094141100848508818F81B118D132512324000000004544440400008F5203251202414400000040544444940000000085588124110000000021100200000000840040010000811283D113D112414202001A817112421246044400004C3A18241002214504000040044501A9 ++:80B180008549410100005029404342020000100224000000008440484808150100100816083301210080814162211261610000002F6E0200504400000000005504000000501114B5185111000000254212125222000000008100000000854818B818F11818255233000000005044000000C045F307004441000000004014041001004051F1 ++:80B2000011848114112100002425024012020000000000810000848508181E188721251303000000401404000000FF5D022424504410040000005044118115410100501150982150222400002502240000000000100885480811008508841AA11125721303210080012C014506100400803CFB24212100444100004004145541180911002A ++:80B28000001124A55211211002001002502200000000848508811048110110087018082311110200181A4172120261410000006FE708251202414100000050444554CC81101101005011855888002121000025020000000000000081951101008508001217113D11212400A0111A71125222214145440400C029E34752222110544400006D ++:80B3000000105454C18509151101005011851B4802251202005022240000000000844008851859110050888418E0217111512321008021E121311225564241410000F0711C502224004004000010145458400914000010484B410224000000242400000000400884508140010040C818D0216111242100A011122D1221644441410000EC4C ++:80B380003A7F2425024444000000405444C4C508141400001415481808242400002421000000000000008494150100848100181C417311022100181AE121512225424414140400F04BF3502225024444410000004444554C1849511100001484A508212425020040020000000000100881848549110140082081F1121115532200001A81B7 ++:80B40000F1121224655244440000C0689346121202004100004004C411100911000011151812110221000021211002000000008110481108110081813018F0121150220080A111242721105644440000F03D325022211014040000004514548C81101101005011818100212100002502000000000000008195110100850800121391132112 ++:80B480002400A0111A71125222214145440400C0CFF341522221105444000000105414C1850915110100141185134802251202002421240000000000844008851859110084818418E02131113512020018121E12235162251414040000778550222400400400005044508840080000004041410100000040424202000000000050114001AA ++:80B500000040484808121002001AA1112D1225420245140400C051D30C101212040000000045551500140000148551A8A502400200404202000000000084850840080040480820B11151133502000000125046000000F092850021215044450400000041C55C88850800001018588800000000000000000000000050111551110000001178 ++:80B580001B11155122000000121052444504000048A306250244004100000041105111854101004041111152322424000024242140020000000081854848081001848481188CC11224241230121022A1112125460400414100CF6741446444004C011222498464834D4984008C42014A28A2849842188582411204001239E44992499023B5 ++:80B600002932483028240084419467284D48344063444A386881881189817821024328286911B01346544323912229426C48832292444848DC38F4AB213CC2624B42C1198212A742495268688674C1D681941B39C54285C14899F8411C87121FA1F826811C58211A7CC4D2C2E881D812B8189A2216F2122C4E245143685851A85CB244EB21 ++:80B680004826F6C834481F81641881178428854394C18F14E984F185129D8216723194322C44A24896E282C892384E285B244C5448009829B216E242D884F2139F248113044444809221C0584025C4481470220228428E5140D841024032144186489112994151AC4226912442844032215A028420588240C8421425444988041214AA6107 ++:80B7000042241882148A38234E1419148446140818001A24C219238202236646841981110222255484822C0823F1481130418881412A81816818244248C492004E822828134432881918A12830848604F247241628480322462CA28480512C804164228A044A01812A49C228535442608847828821218281BE9110440400004180024214AB ++:80B780004008508184206418894818C211C0820018A800124121224410044122288110114188048034881842111C2148122108211840022A8102281004902441C0FFA32E3126002022024994448012D884440180041041881CC211218008212018221222410441800200484C141438441304111100908183988185120212008824180021D1 ++:80B800002400002228484466F49FB100200400000000000088001004000000000000800812000000000000002001000000000000420000000000007C295982B941A841257412011E43250C4088082C484184A1122C9488481604430430488184497811B414E242311611498901301222AB842284C01452C423624218CE1126C25484858607 ++:80B8800001884B14184052C180B288A1831144126088636188182480051F950E12484420C162850826CAC222161872484C42311288C0144E1184441551AACC116122208406851AD1899246648C3144402AE4C2444688183924364C728804498842A24A1611726972240141204878341964A48883014A1B2815088F88024F81D262C58432B8 ++:80B9000025D821011E444116B328E4B41146A8828484D0A4084D12183842181B141614D56904608460844CB81492281F21C21E49E249041A041622C4E88354848117C14304228C9814C68528658847851512E1289211430123487C141894182B821C18A4418292678180912243817514F2DF1220D18804301210C22824482901233848240D ++:80B980001501602844830C81404A341922A1C0414C4118549121701614088C52224C420288281A712C5C2243828112B2245222E08164424841001428942A68841A11088432838458888281248B42CC321D10140124161808308211447012010082220023011280124404004C03184312D1848452941002800122251838124110440421844F ++:80BA000027488002608250841324181984781208848304448200208171734FE322C1144423F11142A0141416C814229A52C340E441282205DA52C48ABC14D448E16274184348D144C69141F08184C8EC21C2148825128411FA118861CD184143D1448858482B1120F144D48143E98251441A781AF41914428100C564863E168B428A591CB5 ++:80BA80004F2183794862218528D8880F85D8F232D81922411112B2120418142918C414271289014CC1841822D844CB1886C418326654418115C444441644E148614890481E243544443218114B81C1435342412D8441411014F4441816C82243311481144B42406414412E4D28494A084781181E482D14831818A884818CF19C91506244DD ++:80BB0000124F1101891488018D3188401205A082428042025A0441A31112042E91202288C623C31184181842021618028D189018F088124412124A5842862418A89225EC814108818881301CABC123319C1D6289081022881328D1723E1A8CC14429E224125424241C0684275C16E441649C113426185425B042014B1217821788C3117327 ++:80BB80004CD11A420115483412182124248C0A4724304238828511D48134A4C2504848152432842256081044A4418B242146618660284A9246A4212148434228A4488470940A3032132482D48402122200502249810489C4110054400212484B11882449023442504140052A4184084414128220A1414D25A781234241048F410845448489 ++:80BC00001239121361282001181941882208444C23C81828218CC12BC35B42108C612418428592521250288410E641822102C3422401122D44460100904952818484916E1C882114402241128CF422888612AB12884024A14140018E1258462242048992A818166B8241004A283988811632223086887F664892182D4C2A15A21427A44EC2 ++:80BC8000512D421264172C85F844842B1434121244274185249125412F234464215E4581971A9CA4121077127811518C442358122CC4822C44B42259158658821F9DA2219E3228214744125E94281D5845A44116D12871248566888CB1A19518392261478BA4E02441744888D1AAA443448D88CC394E4CB12454214006228C226281604182 ++:80BD00002C4159254C26E24402282C248111D99439494501244430498C1408246B431186880120814138488E2424274841861D04C0248486042318F442A4204488828442D829184452822C28882809E0223882189FDC4581314418431432522064644400442840C8448084C2445448C041184820840C12004498102891248188511031846A ++:80BD8000E084C11410288819C41825C9842D2116A4224143466A824C0841828781B02CA148C912B21CC828A01120E1D834B6006214402804C0491AA212A0148B142D4841141E221825042C11CC121800A460218225346141812152A11227193012820029116148841220982100184A014880312848860486482AA82419188808A85E2812CE ++:80BE00008334A48243F2BB690010441401108901001240A24540548160818001A41C42044648440A12412110183421122242414200874442860844100180820448141A34224904221C84014188008800008281C0157303805182902118214144123D184C4219062C91244840180121484012084684E2484118080016082840844214124872 ++:80BE800021D114021489C1282C7488011068282E12003088132801F021421C0242628394282084221528F4E558400440C494100210A244414345210163018B212011241124211152413042144C0144C01CF08114811190114212424A281425B41118F4818484002D4286C344D06604481014D4C40425711806124922D94444C81840440483 ++:80BF00008532E24428455161212444811C34182504504921811418400A160210011884242816420C1D2822241B822902C113F88214238898842480081018286142A941088220010040429212008C7142244204124486440C006FE70F621002460126215212405132890380420318240011240024280042421821A183044160825241110011 ++:80BF8000842311C2841818431408494824A1118800120084809228608848904888290241424818DC1B05A4000016632222223444268234212200002223134401114C92664094242880819224412C4802412C1168612528280800434841AC182331252644440885021308811608A2446022C9286121240088901818CD9D20412102328441D1 ++:80C0000094A064404122C21146018F83121231447042221111240C438118022512145133145085172248530842260A2E125011B061941295C88411561992810070820812A8290324144A840384A0825A145484E042D4E83BB3144E14446F44D154F14C1233A22425D4567112F413444D1446A4418B114FC1C1451E142AD544E141F5141460 ++:80C080006F21B513F11151481D2C65D8C4B254C138A7614B25899224C3C1394B214D152A61184F2135844D48A7288A755681D411B199D21171A4E4DAE8C9B83A21F48DC2EE824B624E1632628B82144D188744878A55E441721AA4DE4E8C2B651EC416C828881A27B88CF26DAA60678D579435C223112D2A9D4946792831121B31BD3C87CC ++:80C100009143F329231C414858822762B71213944C314D3236BE42B422A4246EDD441E2A1F61521367143C5422A548CD122F24183856D0AC34A84F44634886F498C4CF1CE1496181122FE8F3234247411D42824C74329D484EAE47882C31E93E2ABF9D8A7823C4A826E88838182E181ECCC7C54B188B158D7FE34A84E212022C24B158512A ++:80C180002126E125B464D62C92633D6127322562344F22F3622B16B83204251201A45522C444218E842D8450E144A5F882BFCF49D8597111F892EB1B941F52A8853DA2C817211D92975887C154872114AB2465D294D4C169118B111E16E712298458C284BE8449D122A8212F94F464C88FC1B214455E26CBDECA2442982C4E541FCF8A21AA ++:80C20000D44221446414608650844001450884302448904841190448004C124804288130484C628460144446091C0668C028C061889C024581042C283241414A08422004000011828400210028C068826C3BD23E248FC4E447F3431169B144F5633B1F16F2232B1D736D334E5217721F14E4B5D322F222763F36F722224849F6436213B447 ++:80C2800041A45557544CD71B52426E741AF25165212F13F642626FA4B6CBED42F642425E48AFB8F2B262AF8AF222628782CEE88FA4FE6422144B25CBA86F21ED1EE7CFBF58F138569782AF8DD988E146712C6C6497D14658CC2EA4CFC67588D25CF274546F46F44CE44F48BF8AED88B8D42E7198F87444CF4CF6A464FF84C7744FA6F55A6F ++:80C30000451CF435451F45F47451BF31F42326B772376737666FB5732FB411F47B133F12F27E673F3734435E1EAF27F46654477179F111D55F38F347793F2DF222626F47E759F6C51AAF41F26568CF94D2DDFBB82D1FE6F56B5DCF14F93C932D9B9F29F2A22EE5EA82F5E8B53F4AE252B96DF8B927FB8F1EB41FEBEDC17176FC289BB7C9E7 ++:80C38000CF21F8169EEB194F91719D7888FC96284FCBF65CA8A7C35F73F11E728749CF4FF8FC5ECB1FAF48B12CA3B22E74CB948FC3FF346943E24657C82E653D334F44F511153FB3F72A6B3FE6F25B3F6F73F361535D379F94F4226B8D3A6D1F3D237E718F81F166261B355D54112CF147874CF76F77AFE4E466A6E89FDEF62624FFD7D282 ++:80C4000063F62E2EBD182FCFD2F37718F45ADF2D43AF9DF4B4568F84F6CACA2F86BD54E15EBF14FDAD8165EA5AE25AE287F3B2F69FA6F47E2CAFAEEE47F26CEC5E169FD4658EA6E24AFAFC5CAF8DFC3FAD4F4FBFE2F28CC44F49FF8EF64FC8F8C8D42E68EEE84FC4FC2C9C4D64EFD9C3244FA3F66E37773777717F11F75533BFA7F24B666A ++:80C48000EFF6F57F267F36F2537DFFD7F55932BF97F13B457F71F753323F83F2387EEF137535F553173B413F75F597337FF5FE376EAF42F766F49EFDDFA7F33E7BFFB3F24C63FFD6FBB4FD5FE2F15B1DDDDB1F1DEEB6FF69F46FE5FCEECA8F8CE67DFFF1C55FDDF99DB89F79FFB7915F49FFF4EECFEBFBF6CDBF7FFFF7EEEF2FFDF64AEF30 ++:80C500002EF756E9DFC5FECCBCCF88FBBCF8CFA5FDDA7FFF7FFDDEFA8FCFF7D834CFEFF9DED4EF8CFFDCD88F88FDD854CF4DF7DC5C4F92324B0010040020044A6141114C120140040027417012443112101204801844028552148D1241890124C0928283244902002009002309122021022210048031244A31244A088D92800118A0148FFC ++:80C580003A042A425124144011924824DD21E08444424912512219420281501150114421304826648440616291295A114001148242304423482178448558181241244742890C9D42412D4243C2484C08A889A4A18558221784406841802884588810544153F341366F91F448346F91F449142F9134682F91342C2FD1B42DD892B42CC94DDC ++:80C60000CF2249FD249246F524D287444FA27D49D4B4BD49C2DA9F44D2B4F5492447A89F447294F8492427899D246F89D449F292481D246F9954692F9934212F9934252F91B42DD8D2B42DC949DF2249FD259227544F22394A4F2239494D939F44C2939F44D234F14B2486FA492496F1492467199D242F19D449F292498D242F8944F692CA ++:80C6800048222F89362C2F89B624B85EC2416F6291412E169F126422D9F414121B222CF1652586B249A6195B242B1C53B68AB125B2C39125279C4742379D22278DAAF2D3481E843F91B4269A421E8217144F236B942C7948F1249487966D82DF14E221C9252CD19162288F54A2991D2D2725CD2D9E425D249FA95D41942AB29308379147BE ++:80C700004AB7293AF813496B923D484F6259112E1217844F2A7941B8242BF42692CB642CD9CCC6928CC2C5830E0080021100000000484100000000800818404208000000280000000000480012000000800818000000000028400488001F774498121742A39144212044C292241823D222C1114D1A2216062E12844B1428428568845534CC ++:80C78000418417C42624E141A1141C56182B1523448891521432898258C444001D8E908C47214722A24B81C98852222AF878116485D841145A4460418C1825D8263C2422127018C218268229E4C831FB4C4208394104211D4860444448441BA4831225A21452222423542541304250240042459122952211549497615014B448424D5889B0 ++:80C80000B11168828D3643812181024128D04232444E946181220017828B28D3C22842443018464C68AC8682014021F4F8F52885D148C121637144444248C2C425867422C241829711CF8263442711222743181C56848C841C95142548921C4951233683D538D4947416D489C21245BC51B521C4244E84857C91AC3225D4215C4C8F811A22 ++:80C88000F422238E142E8485E448F4223486E28D59214B1285523CC3E21853C82E841D84442D846E2485E82158482B133841A08C4A33DA643285022420C441200112412B21433212208405AC3442244410CA41441C848244944489611218C01210110284892101102C810118444100290223742408841148702448048304701228044286FF ++:80C9000048424822019F28CE480041460920E112044112418A41052818284612C488C042308350120028148881419548240494244200249012941A5114884440E428052BC1288308850283010080123122114048024048C244A0622FE833FF55C21D23C11440CA4B2314C8884AC82899514288A12368428286D8844486D294B12CD4583404 ++:80C98000112147A4C49CAC494944884417F1122585748462812C32488D221E288751C1637288C228252C614C1882A2E414A992328052846C68848912F84884995848221901B046888195288223911CBF474D56194B11614658218D183F2422644498842638814C1811A82A49CC8821644063916F58C412142C1488E61801C7889C4451186B ++:80CA0000467413445A851A824408A72347418415165881210043A9842C7488612828A12816084146280262158D02108808E02552484E2212CD82132314084C010010398842411247211012828142944C8C287244A842811121414558814A88140461442884882C441298221099186B12928CC28449B1840496E22211648289224142186474 ++:80CA8000288140D81CE8A802C01140D22484410882B052FA38AE10C1118502442C42528125044381532412846489C44144503286628126243488185012411C521446181442F4121A4D48B06198822521117A240921A0422484211641841A46C228828C61428C117128E284C518002304476248904838208A041EB8CC3E3D47A2898182022C ++:80CB00004D1148482E146E122792A42D4944168142A81231850241130211C844328B422518049022501400242992151018541240085CC844848F484111D128011100218281123022820041C552828698244C034825885124C318F41B3B20556410282144084608001C444201901440044841421021140110998810018C424124381400A81B ++:80CB8000008018210112304462184C4239146144002C0451444CC11181324800828160814220C47643FE21544D18FB1281E0119422312427C681A14D682D552D111D2825A44148644552341725481CC449441CD22842545817C28A542540F52214C5D22C2C35928287112263521824884D214483E148C145502C6C52412D114D2A214F8281 ++:80CC00005184918D221F4234D816285186257824788A64428D8483A41416628169E444D984DA12C9882140023248F0486C1AC1252341311220043024278180C824842604200446090015682200852141111611423C821150189840022981A21420694289080000420045C4411E3410A24418008C222804811E7AE3C442844731142494A46E ++:80CC80001124E0614401141C2152824001403844114241118624242401004410180240011821294CC2118308404202818038848226144821028A0286C8A2251802122123098489B81884684146A84177D71CB12493426420840283C494112448888D24208488053F4294112B3210082C240844D014341827888290226041164186021B186C ++:80CD0000184482803411829B8300444C9112463C221241214043290A8820022B884A820400A0247084C68623BA82044E222AC12242C03629618C2D8181B8412348A16846712816240246022466014840080026444C042D2485110424A122850121414112301414818214142068412824172180C12481006344018424984682029086224F40 ++:80CD80003C09100443C48210C32410961844201D9118A0884AD619D812B38688628180E18858211E21444428C0421E213012100285084C0128481884208244524825082608360E25A811412241701221410B18830223110C60A18482884C344F0028D081C15984481D680084844014042E442246221248422252843029174481424B421004 ++:80CE000028528317262048848208441E228502C421122D281228335142404A886281241C02008440082044048C44024688028446F16CAE28A014558204284A0141002C2154812210418481E4114428524431211188AD2110082420382460621111211112C8419261A21A0A1EA210081182431821210A8C0187A810025B48E02C88088A08C1 ++:80CE80002488290441442FD12E8D410100240040925488220098222420480A436882422A810428482061898E2421409415481AA214C082E884A0211D12820044450810A412862604003021481AB8C9228208100840880482122C04CF6A0F1C088C548180415E911A71618811D4E20424D112414416084191C41352412B4321D19891150A2E ++:80CF000050881004248881218052448441502249088D2630842318021711822140624212220020022C0426828888420882287C296C182420E11102440084143B844508A11A5C34178216C289412091459212884138436124846200D01849818142514145810838283447988024C448289C8492215028281F81E271189112126C82D1418168 ++:80CF80005C42400444788125042280F8BEFD642B824E132742167A537842F21B4327816DCE94AFA4E84463C3CF94DA229834B3D346F612928B285E5269F8186D5CF6A5255D762F11A826A9C4188F444492228AD828E232736DD2E41884583C9591964FC4FABC343E24CD921E42A97A32C264160488A551822AB981584A1E122F42A2122536 ++:80D00000889139CF13741931821145A241A8A729E7248BC98B3C528B9447C31D822F653EA31B4782221F656481218B42326F12F11146274D1E93A13B1C4F51F21928C24B462D248F42F4C82F4F12F16CE4ECD388E42116B1449869DC11C4753EC82F88F244269557281B224847511C8462194BB235622821CD815F1119F4313A882B228F32 ++:80D08000C27848F414A41DCCA5FE1614AF2258812761BF12F182A62889B8B8D218A26C23C848882B218212A572CA622CD062EC46F2D57BF0112B7F417455F229411C1569C2DF143168974B1711C93C4E1728857491C7811F8AF941442773948F2A11532127811217A4DDC65D2D6AFC15198D88265CA416D448E841F1131137112D3B29585B ++:80D10000A292296524CF18F53221ED8849E188C89A6F14547627618EA24CFB13253E69AAF12C28171113E152D2A1E649082F48D92CF28A442BB43F68384ECCC4C8008F82E248B288DC48E13831AE200410040000A08480088880088812C8A042120000000000001001190813040000110028000094401842514214444044412441265148E0 ++:80D180001244122412A0214602FFE3C1311E3318B49F81A1412B757AF77A381FD3F9131C43E9CDF89CB55F23F1B4219FD9F992D13E34BE388E948E827F1BF23B385AF88468DF26F663614DC3971A7AFFE8553F247332F42486EF58F224CC8F6CB1227DD39C582F87F44958AFC4FEEC565E1EEF28F314B4CF4BF99F6EEF2BE98A88E644BB06 ++:80D20000BA64C487D2121EE91F4DB9B2F1141ACF51F1242E8F8AF6F4984FC9FDED342B2363F6945ECFEDFFF8C24F8CB81CFC9C128B2522DAE56DA5F45EFC93BA1377235245BFD7F75815AF54F753512FE1A133DF35FD9D9C3F38F1841C5F17BFD3FFB1195FEAF773D34F5BFBBC2C4F4BF2341B5FFBFF363F2FA8F83FEB2E617EDC6F9CF807 ++:80D28000677AFEE8DFB4B418D144F28E8C5F42F2D4DA7F41E37F5FD85F55A7CC1F35F4E8EC2B9BBE94AFC3F1B4B74FD8F8ACEE9AFB965A4E424F1BEB24F42C2E95F8B7A6DFDFFF12B65F5BF93F1ADF82F922A54F66BE94B9F5FFB1344F46F65642CF88F8BA3C4F65F5BEAA4F8CF996FC7E728F4DFC44C4EFA4BDA4FA536F1CF512564F46ED ++:80D30000F36719FF97F15E417F95F551782FA7F759EF9FE5E5E9FC53AEE7F6DFACF24F877F53D81BE46CF377FA4F66FD5A533FF4FCBE595EE26FAAF7FF611F66F654EAAF1EF267F9CF1ED56D773EF62E82EFA8F22EECAF6EF224C3775E7D5AE355232DF46FEFFBBA1CCF29FBA4BFCF8BF99B366F87F1BA36AF23E624FBB5CAC72C27B227F4 ++:80D38000E3FFBBFFF19CAF8BF1BE1717512F93F22EC8AF4EE3C9F571AA4F2261418E4E8F2CBBA6FBB2C62F46E9ACF9C6988F8DF4C82CCF2AE544FFB64333FA71732F35F63567BFF5F71B5EBFB6F55B5BEFA7F72715FFB7FDDF9AFF94FD267C7FDDF53BDFBFB1FB65373F3EF636B6EFE7FB767EDFBEFE7D7ACF87F7FA9EDFD7F67373EFCE6E ++:80D40000F4CE8ADFF3F2FDECF7D5EF6FD3CCF28A8A65FFD6DB5F41F3D3F7749FFFFD898BBFB9F1F4F6EFAFFFB4B4AFCBFBB7B3CF99F994B68F81FB76122F26F4B6B6EFECFC26A6DFC2F3B7B3FF9FFF12B6DFF3FB3326BFAAF227238FCEFEB89C9F97F7AFA92F47F74246AFADFDAE3AAFCAFACAEE2FE9FCAADE6E6ACF8EFEBCBCAFA4F5A48C ++:80D48000E6FF9B0921114018C241C048214508842542C812412C114432241014C92499C124172428834434491E24F082248121400421100230242B814121412C21420288418849928849D2280124440081861458424044180223C8480082C0E4E32B18E424213141D0288192144CD62141042D4400111248C048122642440124501400D0F9 ++:80D50000820422816712111001249661248A02212C61982C319218441002212E13122444471260182847812814A8C0822288418123188832488E24347749944F2231484F2231494D129B242CF149242CF949248E829F54A2899F44B292D849B292DC41F292C84CF292C94CF29249222F9934242F91B424D892B424C9494F22D991F424923C ++:80D5800046F1349287944F227949D124F949212CF969252CF1496586F24965929F5432929D252B491D242F89C5242F9944F4DB4B22AFB934243F91B424D893B424D991F4249215F924B297146F2239494F2239484D928B242D928F44D622F1682C2748A3F6493427839D242F9186F2124D222FD134252F99B4647892B925E989F625D28E94 ++:80D60000694FA2E99CF22493871C4F22B889F224D2BB29581F44CA9A9F4443F249A616F2488427199F4413F241A425F841A42B219F44D9D2B229F89268D3F21249DB8425B865C9299F224DD8A569194FB2F518214DDA314DD329C2D3BF44CA998F4562B81D269E438D242F18F44124A661642F18E444F282684E248E4C26E6887444D282C1 ++:80D68000F66C82FF210100000000000000200400111002002008002100420000001024110800000000000000282008110000000000004180048C2A544B4E282E582581218492312F549142401504842845922160819841C7218541C1126410125518414440124C11183412461828018AE3215882C1122514C884441A94226CC8A424881877 ++:80D700009C1204158AE8C402288C6AA242165828496881860222428826F414B3282C091881DD181D512D48E04293488F22F148822E45214417114CE14C31422F444418823412A7121C4223F48428200CC6AC218B2825E2682112522C8A084C742256881C8C61A2860812232228820483716854914216722181A224111F41D2284104414C25 ++:80D78000B422A241A3013048A9D28856836C327637C2A3E1813238444F81A4428CF242341AE6829414494267844C53284F11D621B1486118A554C2BC94291651435E826C18DE1848A48487412F8278249881A1472216D42C4C889126874A8111388B814284A74882190723E8CA4162588F14F191282524612639BA5C62C229D2845A48429C ++:80D800004A6223F66C81614698288362A4C4DF3F0C284A4452911215B112714141124C324923280415854864244452A0115022281440212244040025024343180282482C012F2978484C429C1228104462424228830480521110091118C022C01685480288408284A8222C38A8A042B0141489042508000090182141422A044821842311CE ++:80D88000A4248410140110B2416182240084910030481A120418238941352490942818812280042A0484000010C2844388688100203848A086BF9244E934D1A8440246282124F522E819B428B428714644748204282D1424CF8289325472C366244B31463946192264548B84C12E414B214C419B8443B41268118F817A1122B284D95A417C ++:80D90000922488812A89B856849C262441128C9121A3D181D6122A94288ECC448B1117848E3285F218642301AB448162D0427298D2E8319C19A4218512C24112428C142208896641448D8600624B24203422686A61444923124305C0412538514D28221251838801994148A2838398112123C3184C8232844CF524C2402601830426B14AA6 ++:80D98000F2214881284449213488639312221887244828C048CB82424DAA50883B44445281834422A1229B24838414021612141462618B828741566881612CC4481E4841681146CC8428305125444A6414A1921CE38846C4124544242168184492232588229128001F21934800826088C6C811D082C88CD8618184A0842418248FDA39DFDC ++:80DA00002CC14400548F2104502884105281930284103111441016147A44E11245E24184D84274411418F22112240014D028924C8431C0236023141189C22483840180382256C512461222353484211E41C01449922818418412493128828128418AF2289194004726490549F148292F41A164253841C9884CE6112251C2362152281886E7 ++:80DA8000584224166C884993212411121C44044352452951288236D42203874122004C012399449E22C114E0254161A120D8841B042F21F2848260488712504810E227C8824392483881448C16C27E130D35688181A10000186902122414418004A041142A0500427048440820618810181142581400C04A8184006221150A411044CC48B4 ++:80DB000010880826C441E0440218A49240348218001062212304F049781895D64856688941E281E11452488B648FE164A2709971E24649C244128449C5156466D428E48154218F4486B8684434413C857189524415951270889845A9D29241F26C229028C0438E2A457C831234144849513E8FB485781846F836146E4219B28AB424A43154 ++:80DB8000142D8481412968821E96408832122D442AA2A41C2945C241182897648C0423C1122111444098511E64C0212A012423C8182145E14112141154491281C02622815029212C0189110294301259A121A021220012881A1214820C884C128468188574148863824CB116C482D048819488164852C2F0A4EF004B31C56221450848264B ++:80DC000044882358432285442851224C1482020040044124862405440084250C8482142382684188936424D011288458144582542822D044146821411F1204159162437124C14880410287864124818182858888C6A3638AE29284848483A4421480443284237886012E41184B589018744D2243241821041304001150284302602249041C ++:80DC80008884815E21C028124B822820018022018110941880D2243228204428714254484618213482424240024588F86464442384041829120181104258244002421849A114002D42101801452C0228400248250121C5C141602414142912D211440128418503446024411B4410C384309546141101268414491411840400004145E4E40C ++:80DD00003165161103260816022922022140F112241C04481440837118257221022224403419244E24110043022C0144843848C084461448481A92A5C04924A02440C318C05221841042B144418252422828224004424290C284CF5B0C4CA112610016284484B43441B822011821800420D414824181011D18230491E049C22A484446C2E2 ++:80DD80008242544482511C85810414B0424C02004225082536414417428C044A14A2445B214631227A124131128C04CAD42442220810C2AC632E120247222840021A44120482004D126541486258890345010000230481484C5442228400282D2842448042921228005021449028888840241441843824211004842C6121A84840388242A4 ++:80DE000084302440F2F67A14400140021602218A088604822882702201268208602222282C02284400003544412104A0881724AE84C024902428122224301A4E624149C21800000022004501881782105944200200A902EC3A6A414226411104211601001019111111C8214C21024295324281589043540014861151815018C4818348DAE5 ++:80DE8000128612128118D26844C9812488151404488512021213819181100887242841280028008224822122814F24450281102C921841872430288921863248C1A7141281C41184C01844261A644A8416D84452A21668812AC82112803842130341C01426422442042842228130812840022908434824251242911240E421115442212292 ++:80DF0000484D482184E08238A6E022F326612551623B142F2176489322C8236842AD124DF7C95118341597453A7132A722FCF3D32A1923E4225325971445B81CF24146213D4826C62381A5752DDC98D189BA11B4C17ED5F2B724125F61324B1F8864225B2A17124CC42681702CD946E111516747187E1567D42F32F424214E44D7124E433D ++:80DF800026F91124A5E145E282328685B428C48282A57422E444F2696F3CF1634A5F14E181C4141E18295438184E6425F4129F66F524AB144D212FC2C1765861222636914A52413D374F64D42432482931114D241D4CD1267149761895312364444D822CFA213215F215482F28F6214A4CB26D34342E1823583415744874C27464F24649D7 ++:80E000004684A16147554A625A4F82F4562148EF84C3564AE851F5222C9784F08642C042ACC42429FC88888FE43D4E4742578187444FE2032688E1835664AF81B218CA8A8E81842D436F81B943A17829F14C8EC971493E4781261818E854D2C6D848269A381F2952686B2C97422FA854842F1CB883FC4443872489A1221CD46C6C1286F20C ++:80E0800028833D8425D526E824316A2B2F2F24B84142FA432E849F2118D22164841391242B213D3C1D3667A2AE1C314F64E484F4844223EC88C44A84CD2223F287E70000120028122880828182812288220882A018B0810118000012800118111880014008A081842311A481411A081220011241810010880200304800800484820000AC70 ++:80E100003B3C342F24E612D6D34494223F12F223673AB3E2FE82A42F8EFF85AD4F56FEA3A31F9AFB84F24F46EECAEB4EFE86867CF48C869B5CAE225F5342E64414E142A2A89F11F293911F56F6CBD41D18DA4DF449518CD924F29A92BF19B886B852D159FC1B411F13F26D61FA31314F5B42F1561E8F85E857F261618F61F163791D1B9798 ++:80E18000D51F57F231AD3FE2F26D6915F151118F24D291F2312B9FBAFA5E38ECE62C0C2B6C4AE42CFC24288F82FA68A4AF45C2311E732F37F37337DF44D144F314799F31F665321E726EA64F6AFEFAA59F1AFF73631F1CF22B2ABF36F6A7F67FC9F66C166F41FDD5CE4F98FE73A22F52FFE548AF4676FD912E6FC3FAAC3D7FF2FFFB657FA8 ++:80E20000B67CD3F716DA9F1DF1156BF3F71CD5DFADFAC3DA377D1D4335FB451B3F14F5213FBF43E757E342B36EF11157FF81F5C8B65F9AF669113F31F77913DFA1F88F773F52F63F61BF92F63B1517514FB2E172F53DF3DF5AFB8A534B41EFA4F668424E464F26B4427C86F82C2AEF8AF2A8F933FA1F191F4152BA3D39ED1E2F61A1139F90 ++:80E2800093F738186F62F28884AF8EFF959FFFF6FEB9D92E297FB1F1F4662F32FB7474CD1CDFE8FE1D16DF44FD18BF1F75FE12369F42532DCFE2A2999F55B683F87B7DBF6C7C17FDC6C25FD1D15DF2554DBF5CFCF8D8AF89F842552F7DF58E8AFD195FF2F27DF16F7ADC77F9A6AB4F1545D3AAD964F21731F754DFB756E8DFD5F97531BF97 ++:80E30000F4F76F6B9FF6E642F2787C1E12D7D6EFC7F3AEBCAF85D1E4F2C2E227842FCCACC42F2CFC2E2A8F82F26E22EE2EFCF75C736FB7F55F57FFE7F11E126FA1F41A6FBFE6F55E764FE6F8A4EEAF17F9BBFB9FD7F1DFB3BF2BF53BF37F62F796FEE7EFEFD1F55FFF7FDBF6F73AFF1BF7E71AAFF3FE6F4BEF84F32C9CCFB9F765EF9FFEA3 ++:80E38000F33DCB3FFCF12FDEBF7DF44D4BBF46D1ADFDDFA99FBCFDDB664F75FDD7EFFFFCF45F45EFF2FEEBB63F7FF891E72F7AF4435C7FE7F4DEE76FBEF77B4FFD7FD7D6FD4FFF3CF7374DFF96D2DBF72D751FD7F66D5BBFF6F77FFB9F5EFBA7731F43F66ECA8F2EFCCCE2CF2CFCC28E87E8CFE2FAAEAEAF6A36C82414151244024E12406D ++:80E40000022486542144112504258464481002274845110221141004432254142414851234498008154244423441002514514248250425042514044B42214D419044E012E424115428455128400287244082023F138BE841F241410016820419044112E0215111001A146121A01147421D128004124524042091412D221784258204118AC3 ++:80E48000C8482911016E48302525322C000020E28C0415091601125018221568429469A94422484F42C84810084E28244D481F9837641D242F81C4242F91F441142F9124F6126943F212695B822D694B929CF62492944F2269144F223D484F2239494D929B243CF949244D129F4462289F44EA19F4492423D949B2B2D441F2B2494CF292DB ++:80E5000049442F9934282F99342C2F91B62CF882494F22C96DCF2249FD249246F124928B244F2239494D929F44E2A2F94B242CF14924A6FA4924929F4432929D242F89F441242F89E444F2924885F49248222F8934642F81B464F839589C54248C7434F221494F23D18554241FC6C4921FD244E2C6A4881FC2B242F84124AB819D243B4561 ++:80E580001D24AF1D48744A01B37C8474CB21B14A3486B7144F287148F1A4328B444F6A33494B9A93D626796DD824F141248E829FC662281B242F21786DB1D2F84C24AB491F42F29B4817422F99C42427194B22AFBD34A41E414BA3AD496B922D494F2249F124928F14F4248289F4349287824D924B264F28F148642CD948C62853070000B2 ++:80E6000080010000001008840000004100901100000000000000000020024904482814822001000018400200000000400400F01D23B048C33158A0418D22403844118183548142902127112A8402588532411744C448134254C1428C8111496312466148ACA114D0212588B244D24244D148F14212410049A611212E2C8449A24515A312CF ++:80E680006A011D484C0849021490842D42433A1218812160254B44128535EA2D248E44C72410C41112187018825F12283392138482582B81A91432862816A41248A1C1460817455127448D1183544A27448111D39412841D42A1831C882682481664285D8241124217246C782C7244584827844E2425D18184321C6E812333684618382492 ++:80E700006068884221818F5862485F7B066B462E229B35441E1DA012443C9128837841E182D42124D189B1A2F431C12F8114C2482B4935B11481DCA8F42118414D428D55184D52852931414334C28CD24151411E128714426F267868E494E224E64191424145F886E11E11290326933C21AF42C2B84B442B1147B434821867128213324C32 ++:80E780002F2CFC24242B21846C88044CD4C8A3888D97318143418404482C0183044A518290221100002824442242434204C04944105914702258294551482B418354128821811008418224002514044D4842497C41C44B4098214887444312A8422C21124808C096002B412448419F92054C52980000D0594202400889028041140287246B ++:80E8000028A721E084048100C0414C28049186F241488E8281888110C182474212448A082B11C082201CA481A09C400217844902F048494C32482A5188824AA418488E92008129A9441C196CC11B142934424781812F8421568242BB144734984E12122849A8C2526CA421184C94291783184724F9C44919D29411147912915223219813E4 ++:80E88000305216427A122841F1A2488CB112444EC4A6AE172247212B1E4AD28452166B244283723812D14A74811C41C491886C28B624D1A4E124781402424A694826E888F2D26FD014B14C14120218E0465221424423F4881823244184E421C44425088C724458932A044E4848898281D45144522183141281082D82165812A11A8AF852DF ++:80E90000184C1412FA12221A612244292AE44242C3A24364842127124564428285B841A42118003E1E48F04292C04886748288E2683F2989215281484781848D421558827059422101222288A84C016AC1122C81223518455A251411D141892831111A38C21FAC51285881800165D148021A9884414CD861A8824AD942A11486E8448801BA ++:80E98000229B1484A9443941448F5882788CB2A894448AB482C1942084019A96484F7704CC04288417A4412E432210B1414224E42151842722241CD4820149C44C15D821CA81281C054728112014110C281C88411254248E2293119282008348845188C08141250889042E268338264D3491248480F212812123322445062642E48128C48E ++:80EA00008280C68683CE18E01211024C0510243414311C212204813011C0228A228131158638188CA221218963536B241C7848C44AC04A4642180410048391182F415224231496285C31434445522185025018200125C9858C018903298CB1186846C4430C80D44822F874F6502270484804301283112243885A42211444284314B442040D ++:80EA8000C02421004150414E4110082B14F0154821268811012260884200285A2822228821026E444416180238428C08203224414CA411842A0220011A1908D0183EC6166AE49C43DA1CD4823422BB1445B2616151A3C2571E262D143C4272626424A9C5262A7C49B429614A94CC7121C8A14CF428118F12344286FD481465C92AAE485214 ++:80EB00001D1290A23B212C384A8B81842F8162256B28C382082EC224ACD483441EBA24183D549CC288148E214C912436F8542249A312E31244AC85832818922C8CF2A16A00482082011222800419220870480485240142602141338182444401424F4192412148124651228782430250480018448243C21228185524D14402415222A5A234 ++:80EB80002A8241844485E8224131824827488192422381A41189248864B8E387810448841C0500899158A60148A02129230516189249481221781221004E144A828142F4421C00188100230480480841162862181984011890828A3212C0441D428811202432882214002314242882844445F46CDF24C026464221022190884480840A1076 ++:80EC0000094C92C2292841A288184002C3D4440140AA124100814482A2101208405221481301202101C22001488C3414A60845D844CC1C2098144E12478222182C0142411818C07DE32F412204C0288481C08128C8265838260C818C0A008881CDC2481210C148838C6418436439232C01306A2912111211942225A1244D8288828912029B ++:80EC8000C1254482440400400220C1811AC421294222CE444918084824444681F23BD64C82120810982225D211123442A4440028452498411F21781404304412260141B012012556182214160182D041E12814F8C4848C86946900128D2610110484114581E29584E41881E441682220042002C01420022E18D0C40112C0696363C8400279 ++:80ED000045031C8292225C32786014422800290148742414460881131404A4498243084684441809508210018228130C70842A1858418634882664684331811C08211B41C7142C244435884120428228918482884825944422AF5E49E124040000108401218902221112002A02449100A111A444D0845182452211440248224820028841CE ++:80ED800089082148008521388812154A88880220444C222171860AF0C84812434484084A048440028DC163CC22C44342022110012400248004008602A840021004821840028004CC08A05881408548C214004C14A42100200442004004410041801405418100008082028149D4284B0840184149416814002124B440A9B8C81800444A781D ++:80EE00001991B281425B848414842C1581742122012508B514221C818A944261A08C00644098414164422312141404102801860988214A0830428122100611CC394E20024828405C244144442C548144258904E4402165284444808229C4128226821884888888FC4481A02140D4241498241422400248E08408341D880042148888C011B4 ++:80EE8000C012904428848181488012C84428217048F1E444186DC82B666A548AA42B2125C72449FC866A628FAA64121C72222161124F2DF325C685D5A478C454328AA21146B61474C4CC8A4744CF942CD638FD54428A6C24C67828654286191251224F12A58286F862468CE44C03884C64C48A3446C48E8243C8164887414A58493911E18B ++:80EF0000299C8597438BC283354A3AA85444C934484E684F4584B455D228377C6D48212542514215D18BE222D413B22161811F24E4C274E845F93C212B88A2982E42BA5C21AF5449FC5AAA4E1456511C272417816A6341DF2183BA9514328813E488D822B4C2B483F444C4CB4849D42736422C5444A913711994815E14844F65C843472454 ++:80EF80006AE658EC48644117242D8C6FC43584885D848D444CF226258784412F28C9429862281245A144DFFBC2293A524C45621499165881D5C81E15F4168A1435F26A48499838CF2195422961292F41D419F848DC23C52917124E82A1C5E489C126BF29D64412F1161CF319F8C55A3F85B91C12D8B298218FA8B28ED611B281F98493886F ++:80F00000EF8872A8B68359118D8E8E2A9D5249E313F88D414C91612D3E4F94045847D48F85A6A41FA8D382E421BA8416F444881E882A6862A5721652C84B32D30A000011100119094908590851102408400120480100822008840083049141890911100811001281106141842130121400129400189460822C21024118008009A0283FADEB ++:80F0800044D5E57444DE1C7641768693219F22F6672A3FA2FB22A44722EEA48F1AFE67E4FB222EBCAAF664246FCAF6EEAC8F1BFC8AD467D959E5567464F91848CF24E818F84138EE7C4FBE7923F9A98AAF28D826D8CAFAA4D88B9CCF28A1D32F2DF887248D1627414D4346C4422B3427EAED822B481F4C4198A827CACD1429CC854F48F800 ++:80F1000044222B66EE414B4449E89198884CF46CC44F8DC4622B626AB652B448A8484EC22F2CFCC6CAEF4CF8885CF37615BD4A54883F36D6FED8E2A2228FD6F62E23FF29F16EAC2F24FEA4E38FCAF6E666DFD2F2BCE82F66E7BBF3E8EACF8BFB49C4CF79F9CD458D2A4F55FA581CAD9CCF48F8C91B8B3F9F16FE1989FFF3FFCFCBEF2C79D8 ++:80F1800082FAA5E43F3BEF48F85A7C3BDDCEC54B46EFA7F7E6E63F36B686FCC2C67EE265DEF6E414EC1DFC4CC46F22FA484C6F2D7C41F144444F49FC72669F565FAC45A2DC9F4C6418CF4EFECAF2EF46F6EAE24F46E628FF444C4E644AF4C2D66F2CFDCECA4FCAFAF9A81477E1C55E3C3766659B2F9F22F4432E7FA2F3A7222FE3FA6422FC ++:80F200008F5AF4E324FF4EBA34F2B8146CFAA7F64F6AEF5BFC8B546FD1B89DE55774F4FD184ACB85653DCF4F96F82DBD5F33F6E7911B99CF2CFCCAAC5FCAB9BD7CCC92C41F2CBCC3F2ACD2DEA65F3CFCC2C64F2CF4521667EFED85CB481F4DF5514A8F44FEE2CACF4DF996A15F52F884444F2DF25269DF35B442D446F914DDCF1C6E84CFAA ++:80F2800082EFEDF74EE66F4CFEC4D66F6FFDC4C8CF8CF448522F24F1424EE7448782D3F1556FEFE4D4A8F24363E57F23FB2928FFB6F62E27BF73FB6A3AEF4EF6AA69DF92FE2BEB9F9BE187BB74F7DAD22F2EFAF6B2FFD4F8DA9FDFDDE529F96575DD1C8FCCF44AC6DFD5F85414DFDFF77FFF1F52FED7D5CFCDFDC2CA5FCEFE57FDAFCCFCD3 ++:80F30000EAC83F3CFCC4C1EFE2F25E5A6F7AFC43414F48FCC2D6EFE3FF868E5F5CE814FDD4D4EF44FC2EAAAFC4F596B61F5EFEC4C44BD52F27F5E945CFA4B444F4D4D4DF4D78E9FDE8E4EF6DFF7E6CAFAEFE64642F2DFD5E4C8F8EFCA8C86F25F51456AFA4F42C2C7F360923012110420826183224212A5422800924222C082C082C18A484 ++:80F3800014440040041E241964413082208834821082044121222958842002003048204424440444834424C4244AE448820440C44821002A044D48CC34C38993440011844001163148304950281400D82858464419C812281C14D28444E48204842427118502932441C44846521283A42813044A28493282418681654C45328218C041A042 ++:80F400005211242011681889128213843A124C0814122440F1BE23144F2331484F22F149414D129F14E221F1496D2CF1496596F24D6592DF547292D25DB292D445F292484D242F9944F4934B222FBD34243F91B424D89BB424E994F42492944F2269944F227949F9249697944D929F94C2929FD4C2129FD4E228F1492D9AF9492D2B199D7A ++:80F48000252B591D242FA9D544F29A5B443FB925F29B5943F21B494B82BD494B9A9D494F235B994F2B7B49F1369693F4349283F414928B241E928F44E221F148249E15911D342F93F449246F81B641E2D1F461162F81346D2F11B465D9C2B445C96D59DDC2F6259A46FD245387544FA2B958D234B848D214F54BA4BCF1483486FB49269E73 ++:80F50000419F64B292D441F292484E24471B15B496D641F2124513F2124453F282495B922F48B425E898F421D28E485FA268144FB279C2F52482BB242E91274C4D83BBA43CE94463389F646A398F447AA2D149EA1BD468FA84414E262F89C2A42FC8F4688423B12CA84847223F1B0A2C0800221004001800000000002800008220011024BC ++:80F580000400002002000000002004000000440000800200002008001004003C392D4A21B1184202462A82342A2B14A170417644612155084C62252034628C440C56F8641887528CA42476912984004D81A18D421481CA112288D18201818B842D848751222A0818E0C32C582531418056484048588484282852212D442486288808288ADE ++:80F6000031A49F89072E81C76248161488D4280817C130541B14848A029044C04C8447821C924229046392421441414812D42C51A870C4446241508A4E41A4882AD81444C441894A2451244E824C0C8049E4A88412876224A6B4412298612F8815B14A18A82C85181484412A388819C1CE23A225471A16AA1685D42834682D841E2B2B41FB ++:80F6800046C24139B54468278511BC44925146344866D82862A448478F87223E49857122E413F4214881D4A351C2861A323344678C29A484242D88433841478C178CCE2D1A728884D42128F438C4885D822758CD428E23421E482E8225AD28D4AB8487128B2483E52874627C246A4888822D848B28884CD38F0D1881472200004250CC123E ++:80F70000441009410025C8242430414124445245A4440012001486E484144488410815A8112210481224912424A081410012004902438204812848160282008400128118E0F83F2185041901891142B212449242421A949410459C144002416012850400230480141804A0846549220100704442A814489F26489881844312825442490483 ++:80F780002C71480450A42143524941855414608A46B624D44878140884201828087F4C4AB21151262441259158B028D4C8026788713FF2022A7212A14A1AAA214E4812E7648E126E82415F3544742978610D501150CA299249481F885417656A884AF1822815A6811D34912455DC427832A2184F240887A44CD212E224022231288193C88E ++:80F800004819C4488A712C255188868264481E1242482CC8248D828F6233E5162D711112165812568244CA2C2D441E4C2D312625E2C1B2112284A12489015B8243021381447241482554181481A12E4115E234B81914348289C482CD43611C7C145912A44D8B1E842E8224231C145C241F21622240128252411091481B484C416C848D443E ++:80F88000A18E48188C0148A3D84828F8E88D502241406281402A63244A48D142485258D0428801234AE4E40429F41A842D44D05396288400442490848534482445111288012A11A8618C625C4038224524C548252224E284142452C190AA8558C5424598248DA11692842AD844410423840860228FC23F9721441941C214471490112961C6 ++:80F90000122759404501C0242C110323E4224CE222181204002D411E2160521302142440581443012E4840224404860D81812213082A018421348D41444B24302688260800430844288514A678248082F4CA3714C1222054412124428D482528048C28362875C2295422424514014041F48824972445C6485024504860C46604C0842334BB ++:80F980008824490260488AA1544554821C71441102144746802462229081262A84884601704124C8122216048189F81442888DE12324D3219424602418A40000212169514228120080423848C018269242008100008B144518411102942B419048C880611300C0142C28D1480118181608104858A4829140324800282B2188424224A842D1 ++:80FA000041F0A2234C7218722424F142141D1123C4124E12942D89272524BC69A4471223323415064AF42661A170A272187421F2482150568528D2240297C2524678625481211C381A2B25468C2224E411B124314145D248C11615A218406184F012221444A1CD28CC4851882829148808472A45A25960842B2E4CC9442AE864343615C286 ++:80FA8000411982E22402854211881604514C824444F21228220086C44A0021418F448121E41104450150494501281D2448894868242308868468C8184C04CA8251482AE1419214811CB44882B841F384124A22888A1401174480038514827182281412F8D9CF00490110A5412841114C219842822504842400241181002B1148482F210A3E ++:80FB00009890914898444A0C98148DA4819826A9547D81F0228190C4410022304289841424A48246420123089243B1C1025318644846348230822800C0548388B21282D21202494201463484422800826423262A0420482108198248084E143042210010C1422C04002120184C492418082448114146140181460AA0410040021082A44124 ++:80FB8000280000104888F41154106144290422481462250523B12114B26813424471482221C44120113144204164210061421526042180840440648180044002464C51425028222214416042860A16044891254144418444C44428402E18043433C34440C11414115421142301C1142541C121004A420370412204C4244308194802001132 ++:80FC00001B841054148D8425019411F01142001440084002424002841140048D822412468884840800884426240421D0AA8AC2112A034084024B2124002880022890161B22422C23048148C0441128A044112C8104128148C01220D2A46284B02404414604882200818318889421860C004183128801004A146A814284E024446242422FB9 ++:80FC800094332210021C35443425C44242144210C4412434608640394611814211166645246601444031411016954289921340C1214C0881490221D0244486628461112029421122044200285028142200C0221042088318F49B1444104888C148501440A822242008440092212892821C211802008441290126089021100590882140027D ++:80FD00006018215088402414040084800420040042110021448110B84218AC42818CC884E34DC141644400244026411244010041604824008E4421860421501480146C2136761421110243F1144240E22164215223514A1018524381842C08214840042461230245014062444652241283C122C1602241442187227B16001480250245086E ++:80FD800068444824601249B248584A8381924128AF21814121412448A2411821962124184284328111221354450011421502190442508E1041440414A0428A1834121E182531888521081024883422844344A284C0ABD3E912F214212AD341D24494222954A1597482C85415964439B2A1B2227226F4A1542F275622488E492F21B4913531 ++:80FE00005414127FC81171448625B4119148443F11C124881E18DE4548828F4191441B58EF24914A411548489884244A4898638312C2218BC22D662194272415A4114E224E48426394424F84F5289C84E78CACF4A2288B6463D22888F4D121F044428D1529B41A457114C1264356427EA42D2A4E812F88E2245152E1222328E94662A9A61A ++:80FE8000AC4913F8843464522F2434851364D81724372A1F29A1CC4E42AB485F1472C7E831758953223F28F7155AD11C348D79D887544431C5445AA843147841B49464341B2244442351C4811C6184B413FC42845B12484E242167248CC4266F88D46CC82A7C38B6511F2255524F11D411D19464365671627531375249726261344545D150 ++:80FF0000A8BC5612356827341F27714111DA33E1E46164424F22B28863452F61A9441F65F245134554157D224354A78D2626B12576894AF2B14D4F223283486F28544AA7223F46567445F24886468454CD848F14E864F442E4888E328D88CD993F3168421D8546D24238142DC4E042C842842CC4484FA4F819ED10311214C0416012212E7A ++:80FF80004123A9422368124001418800221908190800800A888018811881488148896812402968928214820022245028220091282444248881889188112D84C084482D84482122214829C8CF43AA22DFE3E2447429CD44E5F942618FB585F2198F8AF8C2864D243CF42624DF92F2AE8629F4246EAF86F6D496B5FB861685D865F844542FEC ++:020000040001F9 ++:8000000021F145448E828F8CADC897884AFC2DAC2F2C48F429A82EA18F8DD894F4D8F88AF84245AAFAC74827CC912F48F8CB4AC658992B884F44E4A87848EA4EFA686C9AF921288B8CCFC4E624B424F2C4C69F12A3918F96FA9A92C7D88EC42BEEAFAD7D94F4A28E8B88A9E28EECA4F4242CAD484F42F2FD5C285FF2FF6C425FC7722C55B2 ++:80008000A5EB424E5A9725ACF58D869EA44F7834452F24F443288DACCF4CE667FA7768AF667DD6FA284DC7919F41F556C62F29F5121317291FC2B45AEDDDDD2DE7CEF2ACC73F1979D5FAC8244F9AFEAFC87F98F57C232CFCD33ABF77EDE4F82CCD9F28F885CBAFE47C4ADD69F88C464F463CC7ACF88648CF44E9D9F228E89FE8BCEEF44435 ++:80010000724F4FFCC6A57F8BF198799F2BF99ACEF7142F64F664CAEF88C94A87C2CDCA4F88F662424E2647624F48F26632A3BD65F63F3E6F42F2496D4D44AFD4F42221AFB3F56664BFBFB522FC62464F4EEE3EFCA4E4DFB2F2A48E9EC44F7FFF48686F6FFF7BCB6F69FCDB597F68F844C425F6435427628FE6A64C9F81FD4151DFCB23F5FA ++:80018000C585FFE6F2A627AF85F3DED95E5D2D223F37F6E4A45FB4FD3C1DFF8A5A44FFB4DCEE5CF94FAAFA64446F7C7C4CFEE4A4CFC6F2D4949FD6F6C888CFC26A644F46F74646DF7A2AF1E821BFA9D1FFD842F46664AFA9F154D42FE4564CAF64F4E8C88FACFAE4ACEFECFCECE47FD8C6655FF67F7CF63559DF56F4456BBF14E6B6F379FE ++:80020000275FE6FF7D66DE666F74FEE5E13BAE7FBED26FFE8E764F6EFFF668AF66FFB6FBBFFFFDDCCB9F6DFDD6562F69F516C57B657FC6FFECD44FD5F5CD722FD7FB7DD73F7DF5574ACF14FA65CFFFEFF55F7B1F35FAA2F33FEFF77F5FBF6DF33D2F1F62F8874FB7ECE7BCFDA62F6AF664C62FECF44AEE6FCEF62CD44F19F66DE81FE8F6C1 ++:80028000EE426DE24F67FCC63DDF82D118FF699BAFF574CFF342E64FAEFD1E1C4FADF4488EEFA8FCC2682F26FCE2EE6FEEF4C6AC6F6E3FC67024811104200400183041219022B01202298234128C04101214521400002C41C1124012B4490124E02441D4284144524240040044C024402412120400008446122404811008421048042D23E2 ++:800300004845021A7141011425428451412502400419024123042904B9053915140213C41442B04104D044B241041121001508130413445281244448D0A2044840889241C042004185216114209412100465C228201282D4D231691D242F91D461F3124915F612491B122F917425F29249DF22F9824DDF22E991F42592945F22E954F2247E ++:800380009283F4249293D4B4B949F22493BF44C21B9F4462A89F446A199F443A929DA42F19D441FA92491DA42F99D449F892499B822F99B42DF89249DB822F98B425E998F42492945F227942F12492A3F4249ABB244D93BB242E9BBF44D234F14B2486FB49A447899F447AB2F949A46F19D461FAB6494CFA96486CF892482E822F89762400 ++:80040000F212484F22F8C2EA94472317944B131F9634241569214FD6E421E8D2A48147921AF9612D2B851F14B21ABC29B2131DF11AC126F41BC84F42B21B34849B494B23BB416B189D416F2A5318AE1293F4A41217144B1A6679A4F24D419E122E2D8E9297D68E828F56A6891D252B8D87D42F29FC21249FA9DC41F298D32E243FA88CF22A ++:80048000D94B8AF29B424BA11F11B486DB83E428DB19E4293B416F28BB41B482B928B4A6992C2B98CF46B48239282DE6630F820000008482000080040012000000880000000000000000800200004800000000008880010000000000000042F0F9EC9C2D624318214B118C01231502121028D216024502E06447614148442C01898124227A ++:80050000B211C12289B484C211E044418141082D32644626D1A9285424C34448024E12CA36881694A888460846483124E24024028100E8502C241A88044E68F0243A43018A24440124282843A184490418188081F141242C258288041D1489C5484822448489724441042148267342612442521C842432484B41908A88C5424294240041BC ++:800580001A1C823222CC03812534444A024502244D21899414219888C012418682F4FEBE9CA1B6803213442885222481240180D414C21C7CC41129C2343051544483341A89A32824811E5149D24AE82482E134C4522CA214CC01681E42455618CF24C88A45984681A59C2247142F85AC124C74888264288C3614188F28F864424822412539 ++:8006000008144382E26C9218641A082524B48AF4244691806444C0142381A12145A2484190181A4222012848422C0C41521842489044282609410011221544218474411222A241188C048A542400800841122A88628240D841024480120421C0484C012C28081A0468D08789A42148200442B0480244181118401204444A08008F81041595 ++:80068000110449A244889024301414121004904190418248884400001A0184C08880285228450444858151888ABA411442188224B248044072280826C468334B314879D14A7141DC21B1429211488F2422CB2217485BC28E1588438967286638D2AD458E424D32482C11D11A5496418F542131552AB41946D269F41142839C482334188BB2 ++:8007000081A183D16841788A918BA1AB92614004A74C2636EC8C24CB481CF24128296E844CA842414D88A843B81832822469C91842904220F869D41819944833314E8F249141233241248B8247118035A415E248014821CA45F1481A38450165C14925124418F11441229400FD43884210038B488AD1A80182B3388A6048204188784C789C ++:80078000867844285628302111948C894E91C429C886812C022C2814C8222C8482C8D883242412844185048C218624E2219285141E8444886AC1848CC28225A4848724481901442E4943E44C0116E446A1521721484941C848481E48195182604484411425C83A2C01444082828AA8298744414E286F88261414A84AC428C038C82D484935 ++:80080000812144180844CFEB49C248504D101164138222211C024A12581240C8411A06858904EAC248885A01862222A1411C91184AF218168C0816D2410428A3810440C221601218AD421425844A4A0800842B14112F680E81244F42A12230154B1441274A4C0116183228B8D8D30C2C410270153A4824A04246921E811CC4244618322855 ++:800880001918848241085914242A11591288C012410080C2228C51A42211124041189188428C988888134852481A08D0416B817028B21812C21112B0810422260228844182328223082F39069B212083B4180429C818468528C2830000221B240041294114D21272120124C04922C521528280044285048C1502829844A04824282800847A ++:80090000184C94211A021C82020020081181008015044E224880054DBBF3C41B83B32A412464A12F84038335448A761498431314548129A2426A29D2845229526E824F12F42C512A0129087E89181642AB41E02194A824C92174786293001B188486B3693822893AB2C2235824478A5E8332F0A11426C9688732848E4496217121D28485C5 ++:800980007214616249F14294A0141E2238A6A84849FA62BF4062144126293341241942322125722128B828120210811484018141250213049521429824133414856843481885712212480292421004001124400816181428820123881A22124844210A22424018048632482C011A3E1249A11480E61401100848E08894140028001200114E ++:800A00006140638823042314A44300A0428A0440C2428823144202A698228E4A41828100463288867284C8825028902884282A180CE84489C4A888C012A094808B08F027F7000020024D2144B82842198208361288188824011C2211C84169C241260181205182460214302242818100248944685C841829088A0C4004A04489C18189653A ++:800A80001845A845E11249811208248008800200A0729374410884121A26E281424428688150818D4484A0215082842F410281304880048124282862288119E2A1048485018004124113021D468410028280441418A1484A022A280849C8489113880A282210528221842D2882881FE18B42124808589141281485442208101211132902FF ++:800B000018838206121418812084110800C21111118233644287220000111A021111998104144A01122011E2147212011CA14240024100200216264648C488F30B80A624002A842292211C32112814221A1208A01412206421188800200D21304200241813041420A442800141114611C28214218861811504222C0400221029AA42821C48 ++:800B8000022008C30484D08242F1BCEF00241814AA010018A0242C840214212E5181A0422125011C5822112B4810016028442C7211C4582C146821248B444D8215842AC4422C22042262480011002084C2264287828252602212498498422022A68629522CA880C43FE383130200404101002120018820223282222008220011000020287C ++:800C0000742208A800412100E084028448800160141291C80081108824048316021088018A018C08802801121F1B8F94942004A0124446054625611647412260112B11002684734126341548100100A0144211151388119882001064141882890887A124701102168A284568811ACC8816440184A0584145C812C0182290428122448429D7 ++:800C8000A924EC39858024018A42C1448004208184C11148608289511240824122048880216821A88008001968822828440012001829C8918C04848146013081A0122498411C81E125028024128208182902A5042082E8E385E48408383E411F84914115BD24B424299A44424D543826621113538181EE42242E21411AE55414AA448714C8 ++:800D00001D14A024482EC245E1A2F268188D398E1A19483C822D4441E089A124468EBC121748611910F888C460E889F1111283B4B2B32AD22824E842B258E123A64459DB688892882AE92198889E322B22AF2BAB9213D8543BF343E128B44283A4181B127822F069111B443EA26B61AE312128A1111256E261F1511A2B842E4E2D928A7828 ++:800D800022D3118164A4A014121D885E42177829C16A1558322F149462A1457218624625EA285CD68E238B1A824A7483B2885123CD441B488384F28841467489E1187458634457C4DB91CB2227242A8824A3828F24942C84A18C58821AF8123928DF2325F1484818482A13F84125814E349FB3F81161978145F118393B3829EF23E223F28E ++:800E000018242AD2C1F153139417221F1484428AA83C3E92872A2B244E2A19E418F443821B612F847488B12884FA43624AB241F8B8C92E61DF9161B496532A3D8219E52564844BCD9931918F84EE2957E85E444F96F228248F8DE9AAB241A8828784EE192B92234A32422C744AC8C445D882A2A66EAE4311140889011810489498448928E9 ++:800E80009188128938128812884CC2881A42B81202288420882108864822C8128215024200800124101102100100000010521400200240221228422241A2212400F036428CF3381AAFA1F37A388B854E144E288F86726CF8489CD7859FE8F4CF8AA78C9F8EF889A89F8ABAF2F6C1A18BE8EAEBEBD6EFFE8C6DADC88F19FA61211D788DC91B ++:800F00008B8C1A8DE42AFD928DCDBB9F43F2E4928BE81BF68375C87121C2A1176A4D5117848782ADDCDFCDB7FE31999D183F29652DAF8C711AF6864D9F5CF19D188F81F518D8AF83F11C3CC56988CCFD9CDD9F3DF887A88FAC7998B32135582AA7454AB572A98989F138422F8CF7585C73AB632F21F132322A2251513AF34165484F52EC41 ++:800F80001DFCC6577F6BD515ED1DCD112FA2E716FFB1917E522F37F766777F6BB925F1A3B31F1AF623431F1EA1C42CA88DDAF632B27F76FAF3B1DF7AF25BCA8BE7BFBFFF894B1D252B663F1CFC26641F1DFCB8A8AD4ACFCDFD7DFD3F37FF3B311E9A3F11D9B2FCD89AEFEDF945455F51B158F578188FABF71C761F5AA9A28FA4F5DCBC5F4A ++:801000005B7B43F72848AF89FB11B1FEF89AB952F7CACA2744AF8AFAB21A2CF27A5A8F87F52325CCF67C5AAF84F3781887979F94F14D299F967269DDDCF5DD2CCFF6FB3E8AAD989F83F2E81BBF12B33BAF251FA8F64A6CCFF7FFBF4EEF92D58A7FB8FBCB49BF92F479498F8CF4CA788F82FE385AA7F9EFBCF55986DF26F5D962BF3F7D7936 ++:80108000F3C9C3FB8CCEA1376E4D511F857AF8F8CA1EDF5DF37BB3BF1FF88912BF39F5D3523FADFD5ACEEFDCF5DC55CF81F548D88F8FF5BA1E8FD1F67D89AEC8AFC4FFFC5DDF24F136CCCFAEFFD8AB9BD283ED22B462F558CAEF2CE8A8FA28328FA3F4CAF88F8D3E7CCD4CAFA5F43A3A8F85F7D8498F95F53838DF9456CDDFDDF53CEDFD9E ++:80110000BFDF87F5CD598F83FF89B93F36F3E1713E918FAEFD6F7EFFFEFF1F3EBFA4F5CBDBAFB2FE496B9F94F648488F8C74F8F878D8AFA1F18F4FBF9FF527AF3FA5E48BF2D3FB9FB8F4EBCB2F2AFAC3C36F42F651418F8BDEA2FC1E9CDFD6F7B3FBBF99F912923F35FD5AD2AFADFD9E9EDF55FD5D158F85F5D8F88FA5FE5E7EDF9EB6C876 ++:80118000FAD848CFCDFF7D7DBFF7F3ECACAF2DFB99BBFEF83AB3C2FCD2DAAF8CB8B2FBBA9A2EA2AFAFFDF8D86F960B0040210112000000C01200004002198142020011000028191492411214008014A242124898260140024E82004198A0142800C02442924AA42180020000822220C2FD814A012C812404C061221A344129A2121A042809 ++:80120000E01122A2212E42230546C442130442002AA414704102C0482425199942420090882B28C36418266288241410D2A414C8C140B84A0215E48A14284864128D84C082823082D08204258848E814F8EF9F946F227149F8241293F414129F84E221F1692C2CF94D2C9E92DFC4E229F9692C2F29D949F292D21F42F292C84CF292D94F30 ++:8012800042F29A5B26F49A494B222FB1F42484AD494B9A9CF4B492944F2A7948F1A6B287146F2BB949F486929F84C2929FC6C2129F547292F24D2527299F4432929D252BC91D242F89C4242FB944F4924B223FB97424F4134B4F42D893B424DB91F42492944F627B41F126B283F426928B446F21B948F612928F46F212128FC46278D19DD7 ++:80130000242F13D44992628D142D4D8D142F11342D2F58B42CF19245D3F29265DB422F19F4241A2F99F22441871C4D1A174D47A23B2DBCF949A42E9A3F44C31A9F244AFA49B4278219E981D421FB32481DB68CE6647B92BD29F892649B822B411F22E991F425822D484BD21E495FA2688D4F327858F12482B385B84BC293BF44CA91AF44B4 ++:80138000F384139F24623B9F447292D868F2A4418F24F3A2414E169E686C63C96E129E6C4F26C148CF22F92B3E8008400810040080080042108811010000200842000000004028020041000000000000008002A220011004000000800400C07E53DB21022816A114A1B04282A414C12022932422A021415A1A842411C8522B4112482190EA ++:80140000144A8284113414CA4384A148162841B2240822A2884024220829290A6684864224044822C26084882E811453C6822B434842484E28924C018B966F6B8D8418A48542481E122E118C130410C544241244271170A28449C8282188404C1184048A11110A21428180414288B14181B948450118635812D01201448B84221652484ED2 ++:801480004218818115728418A424154828851838488C682110E8A122A4C2113C3F232B248262BE4148890517464F8423154881A216432612961157A86AA818481A4238D29A84614124292449314A502449E48A04121AD42C32181C65411A28B12128483242139288113338E82A48342240820419DC42FAC21860128C38A81449C28A2B42C2 ++:801500003ACC42C3C4282B9641C886F89771144420011682F2121200441004412301122A82514484100A24448D410044483220011A0141A018408222B84806805944002901124158228B4447424E18100810E484041C24C149824212818024912812681EC522008280080088000000000000000000000000000000000000000000000000C7 ++:8015800000000000000000100100114001F033C3241AA3424250CA141924A42184A7444888178A8931142C5812A04A124D188A48B14221B12862485D822084B2285144172282685284A5C4411B28225285D842A2424A3881184781242F142C28A251452844B112098B224455024A88B2280115B2A4822445584A4882A02585D86236E429A4 ++:801600002282754454A850114AA25281A4454198A1C28F41014817248A7A18E844815C221F8AA121818845B542748808B0924AC324224A25D8A81854114AA252C0424529B4810A1E1481281F2A08524CD92824B8432141C8226F540420CA28164491A6221848A4C1884AA25250A8CF1D0A8008200800820000000000000000000000000022 ++:801680000000000000000000000000000000000000001400400110013C33C3608111218180C14850824A4188281101180000812200A14004608280145112209191255828001E411812002E12004441230400D0A44444912220048004002669642004448A848102006F428FD71A84028113413822188982328165522426E4AAA1A24C8201A1 ++:801700006A8A928249B28CC2214412837241651447581C48A824124E8141421A044AB14148F441482C83511D8C572183321280A1148D5E441268A14F8281D38892422A12B428C4412E54822331185E2212602489081A17C8225EE6D3AD421E412221123028848951828E41E48824F012282A081862282486B488821292148942218448C47E ++:80178000411122E058415182005819F844118B141847112F11420824400281A449213448118D121A6226420090414C79113A5A48760246B482240132A0418FB68A115A18841481241242A022122449C3814302124302A028812604148342844445312C19885418232104DA01AB4414184280121288F3412A4C41044A05124345CE242D2490 ++:8018000060828420F2246820A44260421800408888831488D2623A51458222111844110250212591122351282100841311982890122002609940B21814C5818321929A208811B44802318D244288223011322518041301841E48C0421222167834410221101488443522209422418283A2812284EFF94B088122201504A02100D0184925D1 ++:801880001381721881230410342A349098002982D22804002074284808002021C2441442CA0482E0740812860141C82D18008449440B24260188814220614400704282A2A45303001881001301006226040090414240125881C0C82222480000442248001420012138804118880A41E022018002608128444221008023638D432311220157 ++:801900008502422C830158882BE244218B221844835521141A411291612B2181AB1845011CA24418812782B447812906112618018CE241D26148A8412E1A828822448331482D21100481881F166448222768488841228D19844B214AE884C41A5085411CA231E827418363459D1242245622E42462883A8122F1687F231508188C820200D5 ++:801980008042024D1216F12142482081A1248400288C982284420048811C84028014E981024430128B121A86C86C208141E88241C81212884210D224A1A18838244284508411C08222C0280018E024984288FFF1811311040022608243A22410B122624420121214A823D01222011230118181282840280189842224512460294029011876 ++:801A000089081641B218044220014860112416511884121E4218848081A4224C0145840223622444DC342100421004461104434831366018221E471B42962132848A118118210240840110011152268402802462422A2884D4422581C212448C042C42A2212902A981218401822C99C110113212124400E08102201828AC42CF350A00C4C6 ++:801A8000102861120089810641480000004112610013112402108418022117218984044200418046048400409318191288341810C1480072200200A01266021602422218422218EC393B0000400829014341052D11281C91421741844B414011282282342C2C0858181692140082200214E099044242218CE19104C082000014100240027F ++:801B000000182124801231428043428422050012F0397820A2220000188C424824044828E0220419822152A41092918441101C08A255C858189016839C11800925219A48A111D0985442132911210123858401E0110446621200428D19241410081800004B648A22F143F7E322018002C021800122468914411201412544210A1C014541D0 ++:801B8000C1111002248006668C44018031224E14200200488A014CE2420421001922C45240E212016AA141181A023230212002122984260248289BFE20440114424048112442348210644586246112124388828838240022108104148A928484002217882281828988A122219143031009221248848445C848844028410800844A01008125 ++:801C000000104802C0C13301404141410140C11112B0210411200200230181102713341119014130111036431412AC04490400404182041CC214181440BA4A6221214092821582344200112912C141B042C112002842291812C2124F5403000043024501004244004142288110217421A484008CA22C821626D1823282898482011005A260 ++:801C8000484322348C22414200214601878141152581440200C27112222B549041200200442210042884CC31733E3128142645C431E0A1D218625A322F11F434644D4156F2322345A4212CE242C2142E197D94AEA115C61C59D74162A4444AD365FA81228D58BE3647641F3492212F144458A5424F84B86898114F26B541B114C14A47211F ++:801D00001B13278215E221E18452268362248D41236588121E264E431628A4148F12011E531A81C6321849B442032922643826F6549D20C4412254912815D11581147814F4AA43882E2552483E2419A2111E9127222297444CF5911C26D2844391114C081D181B5857E2CE298F842BE41119E8A8AB85EAE842C878A73287E297848D1A1CFB ++:801D80005244C9C52213D7A8B312C652469E18F042181F34F42329172CAE4833EE95316126B91366426E222D1281611A82065AD822C24A7E25130741108814B841827124BC1CF1456117463413C6255D843F3374817455BC84B8245C29BE221122171236D9841898122634384608422F1141E85684B154A4A42B132E438C94421625A16687 ++:801E00008E912F1859185D11126D41E091D7A1A1512F2491183724582F8411A112122437212F85167121A81522437118C4448CF6E482AB625A27F1822A2034144220044200002309926028A04880041D422819449441808482C42411285042114001002220125294182224479260122422181008245029102918081121910021814481101D ++:801E8000088123D8F831984B445E541F41F561415F44F441612AD4C85454D7D94F46FCDCCD5F59FC21C17F7DF98595EF4AF965D46F67FC74D46F6FDBEDF48CCC1B443592758B72DFD6F623224F46E74EBE31FBC8C8C5FC182CBD219A58DC2F2ED488F412D22F25F5D9DD4F41FD387A4F43D7AA54C41F95F9989E2AD244E516F674462E48FD ++:801F00006D141F15F156141AA1119AF1591A6F65F4EBAA8AF818187AE625F711718F8251994AF41A388F83C118AD2A8F82F2484A2E488F81B99AF9D47B4CA3134F11F37561171615B5257241F94D219F12F91925AE5FEF54F74761CEF76F1D7235F65F251F6BB3AFFFD4F667DBDFE4F8CEC14EC2675C178F4F97F4D16B3F46B236FBB46D74 ++:801F8000EE981FC8F22C1AED1D4ED8CE4CCF347F73D8E8B57EE191F999B4CF2DF362313E4BB744CFB4FCD9D9EF5DF3212DDF25E646B44FF458666F13F639566FA1B15AF152D23F9DF518677FABBC8AF882488F14E6B6F559227E298F13F6614A87262E143E54C7A5EB222E226E228FA6F1B8DA8E96111A1234451D6155545113F679381E9B ++:8020000015DFDBF274D4EFD4D713F2B1517F72FE253767D147586F7BF1F4946F6AFC89823F3D19F15352DDBC9F15D1DDF14B4A45E64AF831B58F8CFC8C8C2F6BFE6B7D9A58DC3F39F758582F65F452429F9DFDB4948FA3F336752F32F62C2C9F9DF19EDF8F92F2343C6E316F77F1385AED141F35F55614522F21F159D89FA2F36F7FBFAE5E ++:8020800072C8FA18181F17E621F319398F87F479697E522B211E348F41F1424E2AE2263428FE5A2F83BF528767465C7621F1614DDF94926D1D7D9F13F221B11F53F2A58FFF5FF667F11F75F287A57F6BF727A45FE2FD56F44F69FAD6A91F6AFC86C11F267997FD3D484FD37C4DDB4B91F44FDFF6E5B81F4AFEE4F26FDEF37CD997CCCF36CF ++:80210000F973188F21F316722F94F9D9B4CFA9F77A374FF3F66F24CFB7FDD9BFEFDFF32975DF31F7317E6F81F65A4E6F91F77B566FA5B55AF1525BB7BDAFD1FE6FEAAF82FE68488F15E6B7F11B7BBF97F778711FA7F77A1A8F42E1C1F55462AF84F668A22FACF642F2AF25F7A8CC9302411004002811281981128112410428C0244044497F ++:8021800044012601140088A014224226A11400E024088800288121200121482148124800C041800448184824140000830442284230486F910F12141001115081125D44244420C4122604111A818291242991248A51448501814C42211848162808181D488A01296182124E48215112662C1101115A0118905A508A7012A182A122858123CD ++:802200008432481E32814481121011981283D2733F631D262F91D448F21249442F91A4122F917464F212494B822F91F424921E494F2259924F2269144F2239484F22394B4F32B949F22493BF44D234F1492486F2492443FB493427199D266F19D461F292491D266F9954412F9924F2926957222F91F46D822FD1B424D992F62D9225FD25D5 ++:802280009227144F2239584F2239494D9ABB243CF94B24BCF1492486FB49A496F9492427199D266F99D461F292486CF29648642F89A4122F89B424F112484F22F9D29C1CF426229F84F414121F86E422F14D681E121F44D222D9C9A2881B242F29F849249E829F44F298C29D243FADDC41F252CBF0514A26F4D14BA6F4D34B2EA45E492DE5 ++:80230000942F84E462F141492F4A58812F627141F9A29666D122F96D294D924E2121DF9436924D212F28F84D2956F244218F29942D1F899425AF1814F49B4A43F29143474ABB4943721BB1A6BB4BF4249295F126969B446B9293F42696622F22B84CD226E844A2984E242F693C7C000028400400000000000000008084081800000024002E ++:80238000000000484200004888800200000000000000002004810000007F13045A9129B0442114C861588CA1242120929423B2130800288841184A82021604406112C0418EC68568884883014A01844223041A9635461C012A01E0812244088822304448A0C28187111826682A902812962204248B19222E22288DAF239A28221008128026 ++:8024000001824CA5244001811843A2211068322B5281274C85228694218480C94480820486D1584418082C42F8184243D42848AC2463711418A2942328D148219C121934C4AC5228835282002A01181A262C8494148C11826224D018AD1497833846012A16EC441188A112C887412B4300596688278196C4210026652816E821A8A2402449 ++:8024800044621126011CE824AAC481D08802441248A3E284D442C16FCC64422A1142A8451E914887C2848E121C6842E8C12955A826B2C8C121182287283688A1468A3342442572A82266822B3F4EB2C31968830018001C2404422822C012148082018429A242424914AA52601281809944508440B841D914344884008522212488C14941F8 ++:802500001E2C24822412184220841C42880240880138484A081841890118120081EFB7032C01104882229148124322212418F11282002A12022042038244246014008246818984827412C24840A8111954224F84941289826182000018D088018B154CC218222082048450984C02861481190800848881DC393F23C36556022416081723D5 ++:80258000A4151834252D1427431D8412164232144E32AA64442CB228E58483A212844D21C3B21458141E278502214E1C41D123286124828418C02423511C6B1285842AE224E344822242346450424914048D249334244E14188D1227821E22669C44CD1248582CE624F244322E424D726011472100212870280811490445F4121141211A15 ++:8026000092221A222522962223218A121472411894845D2442311E4248CD52D02408121482A146F2481C604122C51824AA122324772868836843D1845144284064848C82048781224C024A598823814422942825E2E435C523B2422245088D12182D1123752488615223C9218682490264214A488432495688224198241322092711848201 ++:80268000A01244159A48B01A248174140222297211B82201002841004305222C2244048992414447811427418DA23C312C4614842481E224B24C89F26DDDB0141114D112314CCE122221674130132524042813A1441425A444484811682D2216B2281C8694120022224A934424424C53419A01292401260424608286142291138C11C248AA ++:802700004830284C0142488532182881284448007014ACB840C48483D5F83DBAA42C440840044210889A1440814184259221AC22024C424A41A814B60845524847822554818442A1848981128EA242C182480089A4149088439421C144844410B188220480124228140221274122C022412002228AF461D5400148122008C04216180484D0 ++:80278000001002C016289A1108004082022A11512912650800004A08202815C126400222002082820183614184444822882A41843968424AC2441A110820741802C02A534E44042CD58485843342218D566D3916924484121F4122012CF2244A522AF54835A413E281D228D7681482923447933352836481469242121CA1942AA8424B14B8 ++:80280000D8424426364229C2A8414B1426125CC2848F41C4188B21414A6144428334188311E4A4A8244D422CB444225124846A983824CB1289F8AE5F842F217141092621026144122018041100A93428C024290800272400224841814481328B4443538810582481164228C82100102801231888212221820415684283A821122A0A28838E ++:8028800024034C0312813A081244884AC4D9E30E23071A4424A341A04112255424280000200420C42226542421102204808411A42138240020247224C85481C012208281224194C1284B42C812482AC4442AC41424ACC128414842A50480024248004021F6DECD44160121602311209144200344442512311281176112001280954C6110B7 ++:8029000052442011048C04C72449618400184688A835824E688E885247884282812A14082914088183B29884084A88A4929088288842890A0012A042449C38E48D119142D08203182123448281344211004C4218A6412140C44141142644148404450128232414246282422781502488245048422800004424238102800146342818C0143A ++:802980002144412242444C24952400846011F0C4322422E0220268814C0414001143A144128430418118110020011A06281911E222080041482441410028400444128410F4244489C1244008EFC4024180888422080022448A1148088212201184E82437EDC0441246440424200111261611114102226024C82429464141D3129422C022BD ++:802A00008254146061AD14804201642824230148122001225A022A0148874430488008008001C028001088114818089084818EAB5024142C02621440211202A0514422C12741124428001B5188100410C124312820150193128281419214482800224420014944082445028004412883A111A0148304490100102402414F4106C0FD430A65 ++:802A80001002A0414448002994114024C111808401A018444C22810145314241421A1404C0214884120016A8822880B1486883814116888843243138820083022638448130282022144C8402A01420011828821FC68B92838311214118141312611128144214004004244E42140011421146011C02B0216211D012034A04800180A5222865 ++:802B0000412024220180948C442C5A144400C02848002222A02468484CA21444428D44C04813EA6231DC48B01414B5821662421311628443A6142524015843C2384081E118212C2104A89034422C35224AD114344410C214441E24486C24348641411014149844818C13481308C024E082C484A014266C644B81441C084844494AD84882F7 ++:802B80004144A81444C5F1C1F614ACBE57D541D466C814281D545E225541D412E465D44411714426511A425F4184B182E41DF224114354344A4445C5445D314551444B194D6167157627F4321C114694323A93324BEE6BB7448DC447468B94C11A88B5147B4C2E4332CA4984E1842A94BC6AB688322C472A41478C4E14874843B4D4A42C3D ++:802C00008FC9A81584444C66421BC2CE7611653C813D542D31241B661F21011D124E121F1256441F3127741551914D344B168129B42114D11429F2118156F413412746277423E214E3227311B1444771146ED467C24A7218B41824F4C47441814D645A2831C84B1287C356B42484C2464F84798CE425FC25244B22C44B2143048B444B42FE ++:802C8000CB2549A3A24C24BC64722C9824128CA4118D544CE15AC5245BC7783B138992324A755CFA1A422439E524F148524F213323144F25A2112D32182E164AF116421E922D522F4474316645BF4132262B26426E844E541B242F16C216ACC6382B424267451E421652AAACBC12011E286F87B218733448E4C2226BC21B618D3A6B66EC39 ++:802D000052888F84D44CE4826684C7A14AF912588B21DAC245C5B8226282F024584B44CD44128991184AF4882C8D949343A11440224802240050212004112100100221480021100280044002240045C812842C488848884884A8218812003012308200411004821843084308823084891104280040F426213CE313E751F655457F45F5561D ++:802D80001C8D221F1291473D6897424E346F17F377211B478CF328246B321A914C5AFAF2411F5CE84BF361911F199C211F127621F527455F117D95F161111F1772657161F5611387C68F9153C91E1289E382F3FC2849B188EA88FA88A8878B8BAEAE888F88E245E655B358B512AD494D464F98D281E2C2FC6824CCA484AECC4F48E9C97A00 ++:802E000048E458B68129D94464488B7A4C388899B669E242E48494281F92372C1B13EFE7F174553F52F74848EFC5F1232137511714BF9612F337751F47F771611B55DFD2F22A3A1A52D44AF4A2E23F34FDF5335F13F791917F7DF955335F15F947265F64F181841F13F711511D453F41F71727BFF5D644F12175C3F1524CA781AF81FD6A25 ++:802E8000E65EC84BA98F85F41C4CCF81FDC4F48FC9D8C4A5545F93F57C5CAFEFFB68ECE5726169448F4E9E288FC48FF24C4E9AFAA86CA89DADBAFB84C44AE844AAAF4D1485ED16F628284B46CF82FC64ACEB537CF264636E277F77F1674EEF8CF14E621F33F453433FB1F76B443F66F677173F557141F4452ABF42B21E277645B642FBF22F ++:802F0000411F3DFBF2611F57FD91451F39F277677F17F467617F56FFC5415F57E156F2216377D35F37F1486CAF93F43954CF24F45468ADFAABBDCD944F87F6E8646E688FC3FC6C34F6F418A4CF4BEC4DFFD578AF613FF2E768CF9A76616844EE2447C247838FC2F6269CCFC5F6CC444FD2FE2D1C8BA14F4AF44484CF84F52CD483984C87C7 ++:802F8000848D642E68CF86FA885AF3FC37776F57F776773F51F65C5CAFE5F563317F15F55151BFB7F635367F57F755555D555F41F52D3D6FE1F36464CD544B552F2FFF53D35F7FF771711F1DF947971F74F7E5753F24F675651F5BF861715F53F435553F47F71F27BFF7F664361F55D6C4B1527552B2F2FFA2AE4F49F718B8DAFD1C5CCBD8 ++:8030000059CFC2FF341C4F4EABFFCF5FBD78F5EEE68FE6FE4EE2DFD6D64CF46CEC8D288FCCA224CFCEAE698FC7AF249F58B2BCFB24646AF6E86C8FCDFA141487814A7418B824F64CCC4FD6FC184C48441D4125041220812481941245014118800110A49400441D124C3241281304424C92414CC2482381440412481222124322B124044514 ++:8030800008411024342483A422839424830442100883842284120848400820812461824C29A21436885212182D48501240A1122D41A0414045820252241344E24502001B2447227034014B41112211214C0342211022046041E08102128082A121244426821214084C828422C1244142224CB22414084E14128190148243F446E21CF426F0 ++:803100001293F4341297146D129B242D129F44D222F14D2586F2496427299F547292D259F292421D242FA9C4242FB944F4924B222FBD3424AFB1B424D892B424C9494F2269946F2AE914F4269687846F627949D826F949282F21F9492C2D929FC4F282829F44B292F96D242B999D242B491D242FA9C5242FB945F4925926F4925947422FBC ++:80318000B1B424D892F4A4B49CF4B496944F2B69946F6A7948F8B49683F494928B242CF949242CF148249E72A3F6412425C9341E6915F4124D621E49C12FD1B425C8484B9425B92D9D421FA27942FD24D1A71C4D92B39494BB282CF54BA48CF94B348E129F6462299DA42B499DA69AF4412627899D224F89D668F2824D8F22E191F42C8205 ++:803200002F99F46C8286D924E9D9F624C29E694FA2689C4F3279DAB12431DB49B159C2939F45CA82BB348E129F246A2A1B94278999EB18D469FB824889BB82C6B42FC924F2926C4392424B92BFA9098800200200A10000000022000000000010018200000000420020021004200481100100002008000000008200000010C18F53E24401B4 ++:80328000008429E18592284C8312446285122634118A222491288B414518062812006249822294242883A221901452636414284242838224B314F418444C6283B0828282A4814922362862C904498284A4241C3128220010480A89912848CC921845F81757148DC2881AD1420146C24212C012202D08124410A1484C022A74287428042A4C ++:80330000A122C7244848281984C41288CD480018841887841A31868E14A68292285048001E44282984C414862451242A0242281484A284822AD184014819088041A14819C9CA63E15124282962C1472589B71A9234226123E1818C614613F18824141B188CF4182447828596284C2289B25CC22227424A924146A442A9E2418A34142AB121 ++:80338000147444A9218CB496B48862412B125E242E1C84CC81B4A27125A8429226A424366842468AA283422B2413349981A628C21418849F2204C3C128588D848D11CCE8F2464822C41200102204A08142001280042022842214042212A044002A021884100842218C8401802648084E2420026024A044449241424382140428A0220000FA ++:80340000810082001C02421A2E0C4004000020110400180020020000008002000081004844004800200148004180418408008002002800000000488800120000F0A7B82880422231141A02200224381481414C0210A224C01484A061000022A0848011C282008100841120149488800200443E48883288001218424285280289488C684486 ++:80348000402432184301225A82042EBF438902221612040022184420021880022848282001184880020042400880440400400818444288302400E042288409822818802142480881408C084826440880822102F0CF1A0044800112220000211609411004210044848002002002888011C282400848001148008100800141128902000020AC ++:80350000240422800860448008124321810448E0C2395A100800004200A1160200008008001508180000002022014830481028810128869841001284211821801408806492000030281014084622021008C28008D07E8E81810112008011C814281122408401128001A2200180243224114B16486428418C42840400008048A41184008043 ++:80358000820812A02224184110041008A083424B22A051890524180042A24E3FE3042004200100004411240040222481140810080042810090482002000000000080420400002041A48100280000428011010020080080A118EF6A071A1128248101202481D17A432112021890C280C4A88418188180223464914382C61C214822CC0484C3 ++:80360000800128107841041287814502160248100845A219D120025088A0148C68552E22421A14C88824488220AC99FC3A6B001800001008410000442001121840010000004818203424608280041200208828012800808228011A222224024100200243020022181A0480018022F42B820000000000000000000000000000000000000032 ++:80368000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100200241000000004210081100000082200121000000002210040000002004811001000020081210020000002002410000FC3198000000000000000000EE ++:8037000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B8330100000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000070 ++:8037800000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000000000000000000000000000000000000000000000000000000000000000000000B833010000000000000000F3 ++:803800000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1300000000000000000000000000000000000000000000000000000000000000000000000000000000E03B0100000000000000008D ++:803880000000000000000000000000000000000000000000000000000000000000000000B833110200000000000000442100002001000000000040010000004001001200000000000000400800000000000042F0B61E5820021840110812008AC42482890220010028800210840400842210288408200481184684810A4A02818244000074 ++:803900008C040000004800404102450800408804841C1E0430124183042C0184141A240312200122182321E4221198144418830200681846848502E0210412808C42022904A0182021A81820012022A924B04C0280128868441A84828862252029240160421AF4E4CB482824124921C41181841211388A842A8102202121012B218128182E ++:803980003024004822842A0183228421084210682246042BA420241B28684800008C0420841404280048A021112564821218008448448CE4213259180010082400A014004481128002214828604141400848001849240400460218A08480011800001220091200229222608200C048884142800846028848180028F06EDC2001002120113E ++:803A000048820222200241124400001F815144182284002E2400C012421815881109000042128C020080084244830113414408114111828528081A9248002748812168184820E45934FE6C1429E521244102621B61289A34114D42002B214121181A84442A84A2124428190260144AB1146295228B614C9442412C2151818712331118A4AF ++:803A80008348AF41C8111EA21CE16264416F812264EE4C5484121E26322D284C22B254A24326B868486428CD311E482149A8418C29E4218A11B2A14506A044008006522A2824120260430000248914B12CB2140184228012E444019B244AA6414F81C4114112008352824C014824C0A216E12128449214812A34114584A2212C1204224E8B ++:803B000028422A3418818A52816485A2188C21863822182D36824A518112239112211884131282C311438402258411624152488081014C2242012813248122612184142184241294141981041A6A824789160190244B148B214674C8461428518616119825824D389884A226944287411EC2408424A8414A8185F8B94F2C53484A118801DE ++:803B8000B181228D1148812885016082141CA2318CA2881901001921782C82048062182661818C8404B44742F820C3214AD88102B0126112A460118A411418A825B088F28814C08425D4110845128D4498211E182223F5544488002081392A4001001E44002024022504109448481100281424209182480038447082040000D0140842419D ++:803C00000000009088441181A662428444411308003012488A2201882100244185A22129A824285BC2C0221A04008001100242C02240022100004160A22082120499024304284524312281124280082860918E81C0281826030010414812114404408802902138206484008A051841214ED9B3CF1827451A04D01814A8128439C42848C31B ++:803C800042014450212A81328822454102B3C1122AD42482B41812C4644F283211478247852A049721881AAE52821C64182A31811C0917829E626D11008F42D818C218222798CC12046C18C4114E24FC9A11228D214A31288D426B41828682C1862B242AF4858BB022528120E223010018480021282162290418281C0812288042381400A8 ++:803D0000112A48010010322841130444A022508824281200E088012141465844142031141681180800429E22481A21024E4812221A01E4B32512011280221301A8C0114A612449440724284E12181C014004C01210012890434A914246C8144A4182632447148218201408441D181998822642721224D42168231662241448483A344130A3 ++:803D8000342100E26041412CAA244C38324443716346014820041B4420074A280288122084081280181241012524C14188424F15C814889084448880684221409244912512A1485123084B1144C26828411E418CA224812C1231124004421A11A415200326042024085C3BFF00108182018042014800904212251128029012114051241306 ++:803E0000841404423022504200D04228329125444132811A381C88800848808C084914C42880442618094830944D8813482248022A2108232801DFDE8581018C021A0244C01810014618311142400180651882852318044513042E84142604142E114901800498004400903800211116021C1242085CD812B182011303282C48A86229324C ++:803E800014100420C43210042E4FC3312213120200212C021AA24248602480018002A0242440C42422466428446014A09444D2A084424A412224A88498412F120449118101744C54842A914C141AE268851412C1C6285925A2618124304160418A3444622021A2214FA40EA01400C430142001000084490681A01111214221182112210042 ++:803F000040440422400220420224222522C422862A4442177848A8221171001138283880A1880025224214128294120025A42C10E4B43242000068124484A084823A288221E1120800848280088284908890484384811408140000120012418A01490524410020210444A1144143010028478441421222A67434022488204184045754184F ++:803F800019134202100212324800129014844200222122160218242880814268111858A041902248128811311B8159A41148298811B4210888B92AC48124424081220454424302828414821120188418148282D4D4327E2181290228D0420200118D21001C82844108142215281491128018810116C2245228C024199144838192484C61CF ++:8040000085462464128220E112C8C412C4124D118824824954411288874C5C21480230C4AA044C21089A1242042001CFB58B7212314125014C012332181A61171B7C284E4A421D321146D3826122429AE11C2DD439085514E411FC41441AC2241E118CF446444F54F542514F24BD44D568F942422AE414F844219A98C43B641E4486B54AF5 ++:80408000E9594992134E1A8F647752B2C2F4444727141F32F1A4324F1EF446344F64A4D29F4EA74443E4C3A2A96E425F7376A2F61486E02CFCC4628A72543232121E57D3B212B232B242B248213163214228930E1DC820985449B1380126A11217238F2EC181244D844D221AF34E47448DC543F151E149B192AB318A5A142C8985A8522F3D ++:8041000011F9121927585867411319A21C37528D14DF4859261F48A1285B1CCF3262514F25E48241B12293128E47441F48827292F65262C41AE84185EA417114848274C2F214844B614B232DC114118B112422428B731E372A038A2EB231E511F1123145B18E84088C214273217212033FA161212D81261282F4748849F46524112C72153D ++:80418000684128481AD11ED842F482542FF4F5832196F2C3B8EF85718434223B1A1CDC4576A2B884F32483888E2ACFC1F44345AB111D49371A8E21121D2C4CA68CCD5E2F598A98B1F042821E242B812E148A8A9244475463030018488004480011C082441D82C082C0824021480100142008860123082718308220081001118A0292201810 ++:80420000211961492048414421410141400180089845810918A084800918F0A2F62CF2234AAB462F22B352E5A5757AE2A7B46AA626AAEF8FBEE8E222E844FE2228AFA3F882A22AFA2228AF23EA9ABCCAB882E828F11228E3F21668C3F6828889F8C458972C2FA8D82828F992522F2CFC44CA83FD92DA8F24E4ACFCC9965BA86EA65F46F115 ++:8042800054188F89B228BB847281EC58B111E58FB2786ECECF526A8A5E8F6BE84E456FC472ACF586644F5AFDD448AF24FE66ACCFA2FCDA144F15A9334BD34BC44F4CAC464A8CE242E646F644578125F15A5A2F24F232721AF11E3E2D62AFA6A776AAFAB1B18F94A3BFC6F2A762BFD9F982C8AE222F3AD2A8B3A2F8E8983F1DB981F8111192 ++:804300008FC3EA63F279BE1F34788E6E489FADF3C582CFA2FAA6763F5AF3D4C34ED6AFAEB782F1989C1B5C8FBCFC94D43F32FFC4D57F45FD56948F86F367D247136FA1FD14134F75DFE8F546C2DFD4F2A6E29D4E1F29FF61E14E42AF86F3C5827F7AAEBF8FA6B2D2F12A28AE341F51F586963E342F6FF6C4542F68AA442B5D2F4AB374F7FF ++:804380006454CF9AC4232FB2B46AF422122B1716DA2EE4A3B17AA3F3DAEF9FBFE922F2C2245FA67AB9B218B2A2F221EA8B7E2F97B18AF882813F48F9962CE3FA122BDF235882ABB82EBDDF12F2262CEB9A7CFE24112F41F486DA8B822FA4B94EE5BCF989961F28FBB2B65F2EF953962F68F276B67F6F3293CF39F993F63FEED468EDE9F2F5 ++:80440000AEA76B6A1F17FCE4464F7AF4644DFF45FC46446DD14FCDB42CFF44B44F63FCF6144F15EF27BB96FD64D66F2CFC46C22F2CBDC2F3A2744F46D7B435733F11F15B5B2F24D222A644AFE3F16222AFA2A633FAFFB1F18F97A7FF2BC45F62F3191FDAB922EA22F2FAF87E529FBFFDD3D33F28F89393AFC3F336369FEEF7C547CD8E4FA8 ++:8044800043F35FFC1F47FEAE2C6F43F361B74F11FD8614AFA5B742FDDACA372DBFB9F917917F73FBB4E53F37FF44984FCEFF27F3673B7F7DF994916F6FFAD8DE6F25FD6DEF5F7EFE7B7FBFEDFF47677F74F76B6B5F3AF245471F5DF94E2C6F2DF83EF2EF69F797D77F7DFD32362F6DF6D6562F2EAC442F2FE76AF154544F46F33BBC0011D1 ++:8045000000122021222122A142240000802142228248840140044440845442482381248124810410521412412918840824412C1824B42472419224242817242004424C22F492244844000048201292441C351C38322400210022A014160112114CC212218042A2291C145214214129C241881A84EA11842B92816188C082821D12A0941462 ++:804580002CE848A414842A419511122A0C1886642289C25116044426D141084CA242813219A84298124E8448888A86A121414F594AF126128F94F434129F14F414129F14C6129FD4C6129F5462289FD422F9492523D95DB292D541F292484CF292C9443F9924F29B4943F213494B823D494B921D494F2259914F227941F9249293F42496C8 ++:8046000093D424F949212CF9492D2CF949248E929F54A2899FD4B292D959B292DD41F292C84D242F9945F4935943F293494742BF91B424D892B424D999F42492944F6A69144F6B39494F2BB948F414928B249E928F44E229F148249E8B529F64322297442D6897642F4134691E45D3B692342D2F18949D8AF629D28E495FA2698D4F3268C4 ++:80468000184FA23DC84D1B9B25BCF84984BCF941348E1B8F6462B99F447292D948F292491D242F19D448F29269812FD934212F1914F592414B822F9996852F98B425F592415F82611D47B2C6F5241213D534F9D8243CF148A4BCB941E328F1412616F349B427819F440A2CEB98E424EB89E264E189E422F9924C4B9627814B92EFEE060079 ++:80470000000000000000844200001001000000100200400400220000800100200400008400004004100200000000000048FC3C848B2126A121002C813212008B18B01812840180024B61824042D14331229D141534489CC8494B8280984286B111E28238811E8416D821092C15C4846788202A6248132AA8488A848C1244A1A160844470AF ++:80478000AC8188220A17821B8126810612A014008AC2447FEC04114E48A04429C41200241A44B44258138821436B315810023AAA412A4E4442288252449A44E488558250642C61A4128D41C0134219A1182D314A71247144C6211825012504441721132952422E22101141998419E1C4734134C22D1243044CA884218CC64249C1A2181355 ++:804800005D811926A242239446290220E1894472811834124398481119752402E02832618E318E2427515B2181A7585E844B2C882B482784199827ACB231189C441691131E414486D486065966445372881331C38E44C826514126A1384B28466811117F8842CDA1CAF328112D2913E154A224221E444728608221F064827FB10B328C2402 ++:804880000118E0210124004B242311A11822162282058A21224174420285084222914484129014489612A8199123289492B012D941A281282988A281008011349210821212048800484D84422F2801008248124E4498222C3CB3608285361211201212280840021100200248282E4929420984100441708401A288434114524884894108B5 ++:8049000040A248418A068021A8122301868424F1248128000010511418411863812301128882422B694AF89F646483E31122D18501121213A3254D149B1C3DA15A7413A2221B91386D124AB924E92289081AB834C33590482E882266F16C186E48508C433229A57814E228041B241B88A7919E182E153821181D1C80024588A5128D9A199D ++:804980005486188F44427422712C58448D886E284CE482F422848F127428B448C48842817A444AC4128D18F39B2236487112410118158221FA9844187223454121E161021AAA242113642217C11281816289A8421C9255814D28A6C41544A44C8824C5882388419AC51A027014082818ACA1244B81B14CB52148284294244100D14941E2BB ++:804A00004833384E24E08824218A7848F2122423F1F2E14483417C3244282121A243814115513286811222238832524192BE28821A22E852210249024D4C8CA84288848C42584212A55298F021181C18A81344298E11011AC8240016886C214489211674221851884D4183AA4222C7866417841A2144085242884E884E75B3A442248119DC ++:804A8000913542381AC25490224E226B482A9424C991582C54430014112489B88446342484B01182048440816118218C7284C12222A0122849211488213428F04134201A048884882850488429C21444842469628229843848439448424442C8AF458C813244842118412914085A3148204231188443D41146082322042215021A098A747C ++:804B00002208128964522B142388064125041242839242C01430114D442D8825460348181B244628856248385928C21A116A04AA04824BA18D18214410D22848023C3D46613032204408508263423418844901198218A41830144138844C42094611024194E2598861426400450148122D84481424224728808181022781122414105281A9 ++:804B800012484244C604928012C8428004828212A01222CFDB8B56646A521887114A112893184AF4141243F64A884B2256F815118968114D22C2852441E12352182C7245841211E246C2481D288AF28D441A5A43236144A4411B18285AF284421621D64661864082C226244F24919826B1525481C6D2888222F145C826C8186272828B227F ++:804C00002B844D4487812628958842AB448544A2A52C37352C012C91224C8144A261C59222811A622444224C123442490126724104F02488811846E488011689812454124C01199A22116026502828200127594961412C092A01484422121011849214444718444B4188D02832224E822B284A0288122C8822F448D1B01444447411023174 ++:804C8000222841904400002044C828473416A124281290284123C944281446D288C112411A210241C0828512741828032C41236231884514210A24154281D822825216224C2402195192848220A3414994528470C49812827C3F6A402C819414128002422A5884234928C22249C14B49880181008A01421121814243A183668102444345FA ++:804D00009226601428250400498848210122441A28B824483484139114C01457248200111004888C941244418636184008DFBD462112024008104114011424221400842302222445021811616AA43121243A4204A221101151137021558826023D8129021E841346822892884722808A4341014948E1299181264201182742604450844228 ++:804D8000201A2242E4F23B8B00504280048502850222641CD4C2D128B42248086712864CE21871494492448C718408111E8481100253128103B082112208144118C082248828841D421426948A81C044800100A024401494A1A12883022DA844414480F8213B881821225606182A02629051A904C143088A0422B024A4812B42D014641200 ++:804E000012818C840160C81141440082302228890121348816081E26404622823284401104811242428E1488136284412436088C0129B41802182D1285D8213ED258D4C0282832150210C248414588A112430149124161244332541A024C88CA423742902843148811C9148C0A1800892231A2C15084444C22821444280850488008124019 ++:804E80001104204404164AAC1A36088270523828460843F1A5EB348144135482228450A1288141A041C02818414C941200002084041098442118400242002142A0882914841404290441A8701804002A0128242800124024010000B0822102248830848C3D2D8592411091488C341284452A64121C83AE120023222241821802412150219A ++:804F00001D24849084842964229124400200402148F421824C2822E124C8818914022618012C9A281A284242242885E28188218222088042B48222812A19C4981F8A41044811602222D123E44422015031248D144210A844111E152611C8548B1820C8A51222210060111C5152221153328141000000004602878844114284432401202C1B ++:804F8000624188214841E08801108431283044562424E4323F9D9D142B48484311BA4A72189148C5B84CB481F23828A67448E841B11BA192228D32457E82E4155145265C445D5945F3C1289F4452FC4954528B19E72516DD15F1A224472250213121A6F114DC8145B283B1A2F181182D84172A23DA27E288684243B888E842F91C812F4831 ++:8050000048B212F5613457489ED48AB28B82D48482F828A48F25B224318825E44D9C88EEF4ED848D418E242B94641D15E5D411B65C541216B21AB22A241258645D14276C2F45624A8F22F844442E228F24C2142F4292A81392128B4D26FB3426448984B92432188A6212272327148F11F4219444113F1158A9CF2242F41C21174473F826AE ++:80508000341CFB41141328CA223D842662482E8A4ACA411F4222D244C8421B2C28488E1533C12E44897818B828F53ECC4A92C227C329CC828FC9F11896C3E8A37448F1413425D3C4E1A3B42152132F62F433264F92A4543F94F13121A56A624F219243574C5AF768913D662FA5F95471272C96A4478DD7273A3AB668B95CF4226A1D1DEBC0 ++:8051000082367414E14151332D44AAF868A25F21F888223D222D84844B812DE24F2413D26CE44AF94C248B812E6527F24D2A1D341AF11A114F22420147341E843E554654589E3E2F19A1825634261E1AAD382F837412E8A17714A482EF280111400100141004001400000084508140081110010040344130416014601460946084601420CF ++:80518000444241021EC2A0C1F01842904140021304201901810000211002210084B15F43F333227038F912522F25A513BFA656846FE2F2181D3E152B8C1F24F4868A2B21BA6F224FA57528F88CA89D3EAF4B7932EAC9F92237AFA47414F4A98A2AE14CFA486CAB9987A41B1515F4EAEC6E272B9F441BCCEAF8728C2BB32F84F4E6E1EF8463 ++:80520000A4918F85B59229B12CA9576F2BF328D84B515A7542F848787A7FC8B822E615B824E246F7A42487827A534C2F22A2466E784FCEF9CC884BC8AF8DAC412B474B452F2CFC44687F2CC2694FA7F76A414E3CBFE6E1E5354E9F21F46F28AD2AAD788F77F747E21F4AF745A2A78C8DB6CB6F2F42B11FF752E26FBFF45CFC374C8BD4CF80 ++:80528000BDF2BF662FD3F65CABAF28B656FBB478CF87F992492F32F616754FE5FDF9542F13BFB3F447C25F36FEA853DB718B4F8F44FAA49D9F61FB14488F75F736331F62FE9E442F4CF4C12CCF45FBF47C4FE57EAAFDB9345FCBF6AC222F15B395BAA4B676EBD1BB6D7731CCB8BAAC568F46FE8CFEAB5BEF21FC5C682F86FFDADC2FA5FC5A ++:805300008EE48F4F33D25FE1F1332E449FF57716ECC5B422B163B644F4EEEECF9BFB3C39EFC9D9A9B194FD182A4FEAFBA4A46F3D7D22B684DA69F2B19E32AF68F824B5BFA6F72E359F2CDCE8A2AE8FC6B2BAFA2E6D3F29FBC7E7AFC8D834F493B54F5454538F12761AB97E7526FAA4A1DFB1F154F6CFEBFB36F596F3249E4F42F8E6E78F1A ++:8053800081F8C4B4CF2CFA1ED89F8A92818FA6DA42E454B581F4C4C64F4FF759A85F47F31C1C2FA3A8B3BE984FCFF9DAAC2F4DFC92C42F83F652C84F84FC56DA3E1C1F89C41F7D7ABF56F4441BFFC7D1A4F55E1B9FF1F469646DE22F4CFBB4733F76FFB57DDF657B92DE6ABEB6EEEAFFF678EFE5FBBA4F2F74FB8F644FE4FDD66DDF77F6B8 ++:8054000036675F76FEC67CEFC6FFF86CCFA37998FD67AFCF7BFAA5FE93FF5693776B7D623F34F26817BFC1F39E66AF64FEE69FBF69FFF6BCEF7BF3F6B75F62FAB6546F6FF2A6188DE44F4BFE8616EFDDFAB9745FCFF63E222F17FE75C14ED44BDC7EFDDB7E5F83E1A1F9A2BAEB938FC8FE8CDEAF8BF44EDA8FA1FFE2DAAFEDFD525EEFC997 ++:8054800073BC3B892480116424502840C224913048102801445042301250424123211212044F828411C412412C21C2124124C082282CC924248644E24802447082048E24E04802442011044188438208182220024189088110684818BF89C88844111AF14148C021128C041CC2124584514125E24202412B144F426211281822424433A41C ++:8055000022914008944342C114001190212199622185014424E021B821024410445A4489A1221728402102411460844542B896C948002F21A8441A2812E284D2813DDE1D242F91D461F2124915F4124913F2126953F2126D4F22F882495B929CF425928E295F2269144F2239C84FA2B9C9D2B4B9C9C29B9F44C21B9F4462389F4462199F06 ++:80558000447A96F149A42F19F441242F99F441242F997441F492499B162F99346D2F91B465D9D2B465D992F4259227915F2279D2F124D2A3FD24D2B3D5B4BD4BD234FD4B243CF54B2486F3492496F149A427199D262F99D441F296494E262F8964642F8964262F897424F212684B823F8D8B941495D92661164D12DF14D424714881F94DA9 ++:80560000652F28D858B212F868252B8D9F56B21ADD49F2918815F45A8844BF95AC22BF8134A4B7894B833F95B4A651916F2A7141E92A5B814F2A59194F2A7928F1B482DD291E92CD2D2C59D816F2282D86D259E22DD158F298921D24BFA9D941F298134417292674932BFA994A4B833D4969F843484F2A59996D9295F12696912B92839287 ++:8056800096C9D22658482D128F44F28259E30E0000004002000080048400008001488800602200000000280040024200004800001002000080010000000000400400C0A170352846911E45C211D012A31417141883C8542001702404228B32C1121B821476946A4144C02D8447126C045E88282C21288584813414221682921481696142B4 ++:805700001823229212A0812D114943C84128D5B1A25281C4124BCA36E2885146A2A5A211208886312485E2B2114922B813868534114E224E1140F6146225A18233AA826CE1210A2A014470C284111A14512887428904C216324A1D188656245B411424AB84122128A14E8453C5884E229815A4211944222244D8148322E4126422240028DB ++:80578000A64143A5521C129254488E44A931688CA1484E1116F44966285F8164221B32496144121713184E574413B39AA8522B488E1460431C912C8C9224CD8249C28A5817827D7C2F48D228044442A37343F4114492AF48C2229A6164CAE124817124AA12C623F184625827182658147681021AD118F922142AE112A826C43D8326B231F4 ++:805800001278B1B3A4B845F432125D824B122C2265641E6828CD14CE58F036B2D34E024AD19244541246B2123421602414C0252A11C282282200125813014400504890A941812D4824411B14142484004210C4448362814116A4122126128204411148813C8402008504388289028764C09486081A2402F031BC481815F81212004AB41266 ++:80588000011E8211169228884D242C08002C092C0114418B154C024142001008195444850885D822081248248418008541420430124D24878D414A8142A22246A82248224228852132489A18410420042608842DDAC31C427C2114F5164883D118022C1494441554211021B111FA1462AE4428CA7321E451AE24285D221B411C12219858C4 ++:8059000016C8454F226C64261A9162868484018AC58144239445364866823621A141F012282426E2216232578549111D551C814CA1434E91C4537844F25228837248721248B81834426BA1436A4E4EC82C4451681562C123B418234462248246582188002351214A86A13242582E2419613248171210018190254394218354842324B84A1E ++:80598000081A8C78410481196241218712233214421AD28C0229C4219C4454824352412A62446816681147821F48E12835298146A2418C0127644484EC38AE30148953411842252921419514612611342588B81E24499882823637854889943416342448885889314829784254429422C4901220012146E2444148482101182129F114C2DE ++:805A0000C9E22231124CA32146912C918152B0C14298442C24885286818142283E88A82F42FCEA5B24244605146B154714002E428843A2128240A442144D8348418821A38308184C28249822128543022D228247A1F0424226A49418984B441D8852304A24701808148470242205C04112400824162894822381031284E0422825425422B8 ++:805A8000F044E6B36D814C11C811400CE081048734115C1284532189245441182C521420418124648A2124461184120C814830344143114A12C214218841190D428D224B1417422124448F4481412638444B424130C3448C05466418814C268C14846482898424F2EB3244842400004225020043C141A381288102904843081952A8765449 ++:805B0000211001462848041240A28280811881149828212A36183A0280381418441A213421860C11C903001902004112412112841218211A4928D8183B1F164C5624800414244A22C4AC1961414E1818430A4E2582CCE44812F31229848D714511C24D2988E49C4154416781248AE222948847214B145E81242965842714AB2C8BA51E6468 ++:805B800048217034624541416B251F229188895152DCB1143244854491B1C3E48451424A615289313483E481A44824222B49898CF6E3BA901287941817126B138B44407812C241214F12622859C21211409412B042188421B2820452321228842C0240D84201214221849285B4923124128429392118832488E2A101484524158404C2327E ++:805C0000122044029604968284288281A611854C42CC71F2400211C01140118241C2842786814400152481284C21685280E4420110338819822968224832834C0800448041D84102C0228711244132181D121344221228263188830283F212444E344481360428418416086081288D221FCD85038041A1232C81422484211C2201C48282F2 ++:805C800026C13280A12889881A062D64144B212004905D28414E2212A0811880E88118214AA2DA818768224F282834828CE42828221364137024822CA1822002A32C4202414C3122A011284692486C3A9E1822C0282D644E282C8112611444C6B188942198111604A02483124406400A16E98831148C914424308190822D88484C543810DB ++:805D0000410440D484018480114529344C44462441829182491212061160261820012A01002243B42451C21B8510042221109248A1851228140842002A6522847C81B188C1CC40A1424302262814072460123028241721384E224989E4610449128A43248106218419028810A882D0110116B1881342224A062044921426028508008A35C0 ++:805D8000BF0085516116314900684218414100860A43048C0C941160884644481101804422084248502860284024080012B124855212001E28A014412001E041B2246483148982054001800528001880F189844440240222271141424584A24819034AF12C110040C2D42C0212180021B05404005B484722C141693414124382114405ACA2 ++:805E000004109614400881484C01242638228144101209CB41004883210450288112C421890D4F221D98220010082A440411C0122182108443A21E182440A842433428200217484280D18181A51A1222881A22413438602128884890244C0C224220D82882410480821402201124210218120048204404484ED2D02312982B16041C44128C ++:805E80008C191C1408A641C282412D4600222D8241212420C488460811919582181102B06484142468181441A41608214041C12E0044C011420011804114114451488A924428008C02204128C8A5618400848C42444441411281810887281A048C0814204401230489B84CE122A182242514A41445A8814308A028C0242C021026A4244BC0 ++:805F00002442484CC22848142812C22464CD2198911D145124882CC824004568412428400C22218AF1B6591CA3222293C21293747A912B4CB64B61554D838E248CE61AF2881D3D346522C5288F8CDF625759497A6918E2C226F438254D3195F1486D35B792F82826A9E4E2F342C8AFCA321A6CB31242E458D151883A486AFD2C44FBE28F42 ++:805F800023D18A5A211FA4D888C1CC8F28E847D4427624DC12F2841615D6E636C14F82F2845C235182A78C2F5222375A6CB13CF11228528B114A62A5BEDA4FE831C86542584993013335622D6B4457943E424D488F290C8F48E188A11855F234522B2919D82878128AE8487D4262614C74C8F94C42806449AF14F959858AAD984C95432D60 ++:80600000149B4423F131144C754A5126ED882D5223781C165D4117424725182F41752CB11251812B211CD241F3382815A6115B11544B5113F694144443D54442528E1612187A547834C2285D7D84472129D222723FFD142C19E1D55414AC98C69E587F21F438814E14253284AAFE24421B4827614F17E881FA91464D668C724DF2287D1192 ++:806080002B8E4F8A3495419D156B847E3479F42432D84CA58C82BE828B828A7116F824316D2C8C6325F0A4562F42B822B261B648B22195A64FAEB1127218A8251C34918FD21ABB29E22EFEA4164B22830438124230284C7218B824F848242F85252302100111280000201128018A021A0240010000148800800118009088800118284A0972 ++:80610000811289289188211918C2884430128421009C14629818C01226280418400280026024281F18C62F5F82722A742CD28BE5B4744B92433F46C4B6AEAA8F4AF9959CCF8BF37813ABB19F4BF9B672DED46F2DED25E515F66128AFC2FEECF8EFC7AA2245D12DD61E7654C84CCF24FDDBBFEF2EADBFFE626E6ACB7E5AB5D4A59DBE9AAF9E ++:806180005BFFF5731F4FF3B4A82FEAF278E13FC63D2A4F41F8F2C12EE4EB626E9CCF8CFEE8C46F18346B2E89C71254CD82AE818F4A69C28BCE2F1C7889E411F8A548CF44744418CA588B252E622F47D484F1283E8FBC34D9DD258FA2F22D2DCFC2E315F55A4E17219FA47445F5FFE9EFCAFED4D7CFEFFB78787FEDF5BCB9EFEAFF76F44FB2 ++:80620000F9E925F774661F26FFAEBECFCEF6BC3A8FCEFE22225F87FFA2AE1F7E5E11CFD4F4D2DCBFFFBFDAAF9D6F46F462242FA2E741FD42D69AF99ABA4F53FB33B33EB82FA6F4C6F21FDCF5C6726F88F9A4FB7B6C4F7EB628B6D4FDCA884F6CFC4961AD129FC8B821D26DFB48239D26CF18F348AC2F4DFDCBA58F42F1E1E58FC4F444442F ++:80628000AFC1F2121C8FC507AFE56581AFA9FA6CEC1F15CB2D5FA3722AF42E167FA2F54A5BFFA5F27B4327C6FDB76F9BF7FD9ADF69BDBE7738F24ABCDF4BFBBA74FEE45B7E3E566F517F67FA2EE8CFAEF77E462B6E6F16F67D6AED68EF8454989DD6CFFDFFFCDB3F45FDD6226E68CF62F9F6D26F25F516922FABFBBAD51F3DFC41B6AFE3D0 ++:80630000FBB86ECF17F6E31CEB86A6F62E415F6EB667EECED78CFE68A22F9CF64F282E28DB381E69CFF5F4442DED9D8CF4EC242FDEFFFD5C7E851F8AB668F4441CAFC2F11858C7848D42AFC5D6CCF75CFA9E35E1FF72F12A2ADFF2F21F2F5E419FB1F16978AFB6F64C4E7F3EFF2DFDEFDDFDFE2E8F87D3E6F43CB96FECFB7496CF6BFB58A6 ++:806380007A4F66F3EDF6FFF8FBE4246F23F342A66E26DFCEF7AB2B5F5EFC4545D5FD57DCFFFFFFCAD6DED66F67F26A6E6FEDEF4DF552529AF9BABA5F1DFCC7474FC9F1565CEFCCFF71FDEFE1D782F2E6A37F16FE46468BAECF87F58E4C6F6EFF6B67AF22F3298D5F42F2CF66BD639F4AFAB9158FC6FE76B2FF7DBB7CF7E1E58F87E64474C8 ++:806400001EFE161E8F87F428286FA7F7746CAFA7F7EEEE4F184818022544184219429182841AD8849482942C1844024A08B02482D84472484224441448144994412F499241274848924812100210941249542241200241182004424902444014C124111E2442444844400400001A18C4EE936F4822952211311280344821534481A1212004 ++:8064800031241220D1A424D1B438822440286418881C344821853212105248612C21C812121384B46801D082941C211827141088711284B81242081C912284288420592812281228230112403824F06C1387C8144F237348F1241297144D129B242CF149242CF149248E129FD4A2199F46B292D959B292F521242F89C4242F9964423F9994 ++:8065000024F2935943F213494B823D494BBA9CF4B492944F2369944F237949F9249297944D929F14E221F9496C1E929FD4E229F9492C9E929FD4F292829D252F29DD41F292DA4CF29A5B45F4935B22AFB934242FB5B424D89BB4A4D999F4B4B215F936928F14F4269283F4369283D426B948D222F948241E128F4476821FDF41F3124919C0 ++:80658000F21269174427D1222FD134242FD1D425F812489B822F11D424EC99F4258AD6683287144F22B948D234BD59C2938F45CA93AF44E118F14986A6F249B423DB49B392D461F3924915F412681D842FC894194CF44C922718DB922F1914F592485B4227985D1A271D2E1BAF1D127452D4B4B812D2949DAB583F44E3B8E1646AB99F4428 ++:806600007BA2D161E399D461E219C43623DB68E2C944F68248CF22E181F42482FFD504000000410000004024040000000028400411A1008412000000000000000000000000008200000000004002100400BC3382196215601481258814A2349243C2AA89148A02152224B82828085881258811924510C8414288C456229C424518841C014B ++:8066800083E4440130482CB42221022C911123751802424B14411826B641C1242880734178280424237222A482CC4124912246A2168921F2F323448F219848162261141C81230498A0844D241149180810048C48E412EC4388D48C04AC2408821D44160247588CB284A184A1241846022CE1C4C1127014F449143111414440441128A241FD ++:80670000290125E14404808A64814C41048124508218C084811B184FB43C725C7252A9413A344861181E4258928E3468C6DC21624488858114C128888938148C3E824B1C463A558F24588219CC411E44646B814B842DEC8C64CAC8611038542B14414A3152ECB54643711CC2115F24C1184493E444211172227452A18128212AD1186EC32A ++:80678000846C417428A682E34294143246A2128CA834CEA484124012019D41A022002C1808C9028121448A0880E21441548800000088846014004721001964214240682185041712000024002810A415C04147424200200430228001218121CCA41844A4838F0281841100002850422C288101C0241880284101450214401801448418AEF6 ++:806800004846840414111C04B068D19204441127C111160128222301854443441148694400008631482124411884508280C48284229F8D43EA1152221B12008D381121A301D71283D1A8028D242721133112262261224B224E1D421F42457824581349C24843C225122A91129C124448069C0123182368812E126062A4641514D2441498D3 ++:80688000262F41E2114232284B3114A546D4489228C564454CA4421E2A96A844828B4430322181E04437622D2825C1298C414128028C019CD25A41C81A83819311122A91122249E11244843244D12511C1214D48411E25222B4243D4C10650524283416234178412281C618115825143472222565842AB211C415121C35181A714648181F8 ++:8069000083F21144C12986313452488429C42223648884687F570212222100189502294204B082024425C22241008A12C2481761111A028518840284A09189010091109181B0381802C542265214A1400461902465A42281381004414742884810F4428A84888944081210026C32232229921842214422104802001362242F120150612266 ++:806980008012985811A02443083428122141805418008C521426081A1288029442464815C8141922745448C818A034131328514845B812121458C18CE221B44402584A924460841022F495E20028210041784422989D2183111264834602154158823448155422A6B42191A93D8C1002141E12B012C234210026341238A024100826944166 ++:806A00002284141C0121275212602288181820C4428608001651882183226842A0122C014CE3C8315B1021C41289810400458142A2210010C4242A8101122B1200240021818591444111281604668834128120148EE171F44412290429881102824921E82204418504230480041845820C0000C012290400847F87032AD222B25895122183 ++:806A800042221E248512F4B8292B31103132A5C221F0341A50182D7A15324C86D31457582D82813029424721512D648CB12432484227912189A611AD281665264A7242F44182891154421BA1444C5552A784122E46F0314A1250C84AA11A45C68C428D51A9942A81924E421E422A951821B88F6434C840012889028006141140C224E011D7 ++:806B000012444482021A0212268302384911094C511218321825011028210243068D121614092214001823E582A82140E48201004904488184113230248004000021413FD60713528821008181321028018942B12C012C81420200508890211081C2218140F864152B264C11E215226425207448E2429118002A2241921880012843318149 ++:806B8000402202882480B2118682880345B2419148004004009C31D2008084422313A82182848992418E180024822489111101411882449014001538181281412844002031224842441C0240024081921680250418484211888220111281C84212242188008C0390444E6D40010026048100132143C8218400004072280883322185E44222 ++:806C0000518841245942147224C1281480012120448101598254481482146488428904641814234272210250542880E28882C661002608284226B244E12424C1B2A210924826093270220100A05220D1188241C114141890141813081428801981128A04888026C1C41681869144002B122C51A4490181846414241247244422184A018037 ++:806C8000121109400200881A1862842222A0165B941C08201181011B118400182244151401002592180015814291344444141004441D5214254181047032C24222A01844000049C154282420011AA81221221042048E421AC444182412C682024A0412250225D6D137CD83012302000013A11240C1118C11828122C1241C018341423882BE ++:806D00008CC182100884222041042E184932114410614149081182412A512519554220E1162124028C01142551583116622153621123422242018062C1440042842FEB8402144800002850488182800113082302430200C2002881440018280010041880081002800140222814F845840028400100881282A088A0890020098028A28420C9 ++:806D8000C18A53D648811161A184841481850122402484722804100124B01888C2410018848302842884200214841098224521012225C12220810112842226466C22191141062C12110810A141402121A218128230980036D8960E2481002228411128118C814204A014B0284154418D111418A091262188321250428220485412200822C9 ++:806E00001005189015002146240481105121268498840082E0130221866224A014242098482248C13052D0723AAD8F433283245E298193D291D2A15388BA91241A725CC1554CF1182C8042D244D1284148FB29858AF1291545649385782101CD2818178525071F21B241DA11E2482172C1F11E116C361C1C712801E362515F41288511C2DF ++:806E8000A227672F7165661769222D1513D52352121691311DAC171C2FEAA2942E623B453A7128AA4148833228524E41C49FCF4D11C819830618E3C1181D31229D282893A9B68F12D31AA2312CB112B214D128D11121B1847138B922C12927C1404C195C84CFC2F2B5788F7438229D1419F55214421E223A7442A4414CE172C4246B122EB3 ++:806F00004627A13761E3E15CF7281643F111A42662C1323713265282416D854B385830821F29C9161115828DEC499F1A8F26FC18822B1127612EEFD11C71185A12B904B03821C21199E28111F82118D1CD211C981213BA17722AD28452189B31421EC94BA81E214C7224E669E212F222813682943426F524142E54844237A52CF42124235A ++:806F8000DD417921E421BB12D121090053D548A1464912B814E612B813E82284C4811B8AAB2286F1A2512B635AE422B641E128F188A28800C24F618616F27852BF36050014006012402108821C2428222862284002112819811201801AA18180082918814881889482142100142B1860286028200CC602860219082C01112820183112006B ++:80700000204828010000C09EC39D349F11F16A68AF35051E3820A2221AF99CB49F19E94BFB3CB46F69FAB4A89A8CF834B6CF8252EC8D18EF68F9ADE5AD125F49D122C1282FE8F881BD8F89EB89C1B8DFC5FDD1D92B138FC1EA55FEE8D84D148F88AACC3F51A5D98A8CF283914F49F924145F7DF981818BC81AF1B4989AF99494CF86B86478 ++:80708000DB8DF222225F75A315CFE312D199A3115F45B581F884B42F2FBF71F7D2D23E383AA1DD8F85F79898A5A8C84E522AF572FC5CF135131FA1F3397A33C714CF13B231D281F229399FC8FAA4291D345FD1F6BDEE7F4FF329188B242F4973BF5CECE5F9199FEFD9F144322FD3F91C376FC3793C529EEFC3B9BCB918F1A8798F7EFD9BA5 ++:80710000B55F8BB19DF5D5C89F4FFC944AED424EE25F4EF446544BB59E265F41B316EB6979D67113F61E944F49BFF5F112522F85F6CA7667BFAF2AF2B3D57F1FF5533DE77B45BD3FE851F754E22F6EB2A4EF3FB751ED2DB338A1939E98CF8DFAA88A8F2CE92DE525B2583BDA5D393FB1F16B68AF3557888FC1F128381F93F321219AF33C8A ++:80718000949F13F17175CFCEF727E65F9363822B1B4F7BF3262647611AF193979FD3D6AAF135B42F71E182F3222A5D2F87884FC25A885FDFF6416D3F4B7919F8E4619F84F694D48D5C2F26F673516BDDCAFC24243F32D144F2B6945F3155334D1CCA7C24F152764F43F3CE5ACAD5ABD123F155D73F15F52C3F1722CFE2B291F955141F2D2B ++:80720000F894962F2BBFF1FF63732E288F89A3DD8FC5B5B8791AEA28FC12526F42E33CCA35DF33F11B7B9FA7757BD888F31C211B331B231F13FA392C4F99FA89245FD5FE7D276F5FBAA9D628FB12BC6FC3F324166D111F31FBB639CFB6F33B3DCF3BF11724CF23F22E99CFDAFA2D2CCFCAD1DCFF6DC7BF7EF33738DF43FE65C99F48F44448 ++:807280004AAF35FEE1F61F6DF542544F55FB85A67F49F336364F71F9938577696B414EE44BCF6F6FF776FCEF67FD56AFEF33F893657F3EF443ADFF32DAD2F32D919E555F25FFF3F64F2FF9F2D31F2AFF72228F82B988E989FDD8A88FAAFCC8D2DE525E66CFB3356E8114890181108812890228811A024C0212002041484408478210044747 ++:8073000082004A21827124A11480014A014286048E24F082241196048604803492481604234101418822182246024E922224200418200489F1724188211121130420112141A81154400D6021442C01814C5211289A011150182200812A1119460148801212B11249C1124488401281486425262429022A9243705102114392411021082A9B ++:8073800051810000188312C2683D4833D441F212481D242F9154412F917421F2126957222F99B424F882495B928E694F22F9822D5F2279C2F12492A3F424929B244F32B959F224939F44C2139F44623A9F446A199F447A92D169BA92D461FA92491DA66F99F441862F99F429822F99F42D822F91B66DF81249DF22D992F42C9225F9259252 ++:8074000027144F223D4A4F223D4B4D939B243CF95B242CF14924A6F34924929F447292D969F296491D242F89F448242F8944F6924826F2924843F212684B82AB83144F227348B1247168B134F14D2149F169252CF948252CF84D651E828B265E82D7568F217C29F4134A1B222FA9FC24241FA9C1243FAC34A41FB9B434F213496B1A3D4968 ++:807480004F6B51912B1A46F1A61217146F4AF168416F2AF145216B1887542F28F161658AD1587292F24124C6F241258F29D441F2D38A1D245ECB441B41223FB1A52A2D481ADA13B426D182E42258112F227941E122F14848472287866F2AB144F68212C5E428F168248E77A3010000000000002081048400000082800880040000000000CC ++:80750000448400000000000024000080084C840200000000000000D0420B1D182C32181E12480022121261114A321828514321A12224841210210185255244481501B02821F6441A284B81A014808461246A031A014480A84168282C082F22011112902281A058221230817041C224242442168281A512811E79232D6218113110A1141920 ++:807580008192A228183849D84222982222218348248A260287111A0421150884214615289A4148424124100A8841868832442826D424928186024A924462224694311941B1424814C8812B848C744C72826C44A081430928286378C29522FF5D845211289F31224124E4118321C224211172CF2174247481382216E38202218082C1891204 ++:807600008B115552E4704149C2441B124A7684F249241A0E474421304C4AE846038922B144C4248CE112E8141C42E22294442B23E01169122B11972286B28422711122A848416F2484826368DE142C026CE5C814F232E5F1608124C0121442002B2920018A022849810282418B292A140180840211001068822021042001211821200930FC ++:8076800024D024082228C8281091440080048C8488344925988941442100A0212292F0EFC948213012141248800246084488004186024A280240022410524411A880188919018161200812482442302824221652141602002784608190124001006042114B2A19045022E02888842184914C4C336F495121421612226121242119A91C49DC ++:80770000AA28267282542114862448022E82C9C62C3048844E2142A8C93584486716C148C0411321B418240C1A988C544C38125B8127588222882361284062522623F94428439124B3D648B821C4C158873446988A833238874C81107228A2292CDA24FA33FA244721201412A311422880385843185442001338828A1A8258824316CE488C ++:807780002502474442302C84C6714418054875810820018E484318318412573A805121821042024341A24843E3115214218A4221EC44F84221842328928889988821248B812CB928F864E1D32D1431121218104212E2180522A8A2294807444800222002403821118AA21C4C4831229248848081E481840C582441261892124C79822402C3 ++:807800002C21682481267129821148044E28C14681C2151D2883241498322D44002C24A6214424EFA3034814801194144812C12F2462D4800A1C01E0518E03A94102A908706908108282821588180424822A81A84112455249244388B484C6281788481525212312082688480822A246AA1241121D5288E0818224C14448328088C8BE8317 ++:80788000042421182815362122299231830116012941D8286414118534141112904298008124560800410023189862430C244222252852242242100A1148B01108441344614C12101483421404146421811A328424A02440744E072800841124420010A1416B124280121102886830211443021005146014A04280014810880481214A01D0 ++:80790000185029126B8100006B480030222602002240B88324121404000084C048C07DF30A461282C11814662387A2251E2ACD1116A228508126F311428E648D2487611B2423414884D1814401E09124C2211E284C142421D8828C84A548833146AF145284274A16F64CA123F29124211364413AE468B2C101906911A1A02828C03495624E ++:80798000524664184721A3B218044276024A924841EF830328144071240212C425D211045C8621B412010018A01828158232C328844331188004480082104298826021420023010016122808008400431262424222484912C994482C014100A081008188E0B83CFF14304190441528822172417221041124103181244C682444144C12349E ++:807A00004825013C1262149022809122212519B2444884846421204208612A240123443542AB141002154C020000A0428826442162282221822682012504488FF7C22A704222D292A122004D198C21187281A84A44A37888243289218200871885348222802801C84188428CA8844240682C8A988418421304893488122388810181D0849F ++:807A8000112426C211222AC461611843429844AC14A4414112821A2881021A86D268181A8441C3412D312C041121008E229414002100200225881C0446024228188021041314B181420881224D4800A200242220482446022C144204C12194C041100400450110044280042486F48EA4180049032A0145EA820182214088342810415841D8 ++:807B000011A9D418024024442E24321461884CA148414122411120824244044E224A014CC4342744E045C82418835C441E123034188524A2286012C0118A0180015A3814282721782982C155E22B284812204482111404C042481094A42814442308142D442222A86122002A2101492224120419A44800121B784014848248023082841016 ++:807B800002121448801252413A441443142418F8881448002110242841FCEA9E5031800122224800100100002C128804200C8C44028242114B4A394804C0824022069024430848284042AC3100A22810318180081718B047964429181453249110051918A6442A08242290488E649142C04800504821D0C28111113482110000C0442460E4 ++:807C0000C4404401410042103828008400804408A284A924244204008025A19442004D12003835088CA812848332112C24024452228A41C444F0B37DA014602113021B4121400180C4481BA2250100214823120A28100111239243B011011542812402008002D1C14A020028CC11129826412264281092121100A021860119010042AA4402 ++:807C800008214110E4133A68441120D42422C41C83418286088888B0246488268848C581881188004B8287418E14C2862272C2048648C482174823C8248A440482148890844D42D02404AC44416144888C68241FC1A2244C18C318602818800141308280024484C2004BECAC92831D542423D6A224A2112543AC185F38C2488B8C253485DF ++:807D00008E8A2E212526E82CE6AECC2289BC8814C4476D2C2DC64584F944213AC8114BA22FC4E8847446A6C81F4CEC88B842C8182F91F18164228394822CB57458628CF912414F34CC5629F814C28F21F24242559552271137416F76F4AF581F12B11468545F4ADCD598121D856BC842414B4127252C1DF8225485EC6C3E4453B55271222D ++:807D8000EB15B148D121014D148F21F1134B242C64182F94FA2A4A156112254133424553315724C992465F7224D253C6221F15AA24439C968A548A3F6492211D2E318534646A34646AC54D4362824F62042B42260269F128422E4C47274721184F22E9C1F22129E74217962AE44AB424F22F84219B111E2549F112481E842A25C4882AF307 ++:807E0000242447492E625E34AF3B01471627145E217CB145F34158AFB27248B4286C332A788165924AE8C27A24B184E882D8445886418F8C38255F84FA288222588D218EA247141AB1C2F1444C9A34241F28BA817A410C4282A28F4A58148EC8AE4E6E5A8E24AF4831344F63B2C47182342C3629FCC454C7188F227691965426023488F0DB ++:807E800031188982F41821C9C4222BC32F48E92CA912212D42D249DA883EB18440088400224422302100210011211002230100002100004042C81284428440080040028100212001811048114A114A11021894189C848294380041002C0118E0A54E7D24F3185317B59F84E4A4B562F15232CF23F771731F2DE929F663455F16F46B2C4F14 ++:807F0000DAB285A22A1F2868888FACFCC8189E182B6BAE4C4F5AF665457F56F2A7E55F16B661ED1D7B31D2D2F22DC46F9EFE217F5F4BF335AAA7884F84A4242EB88F12FF31619D2CCFE2FEE4A8AAE241F232242B226AB884F8AA28AF23BAA2B598F3382C8FF2FEE43CCF92F75A2D2F4EF8C889DB794BA74F23BAAAF8C8F58F1FF775931F99 ++:807F800029BBF4A9999E988F29E7A6FD58547EDC8F8EF8C8FC23F72D261F85F11919BFB1F34B53BF75F4387A2FC1F176653F3FADBB3F34FC85E51FB8F2EFE1D7529F82FA21822F18E828BCC2FCDBD18F2BFBE8A88F4CFAA7A53D271F73F3A3211F3AFBF5A55F5AFA1616DF53FFECE6FF5EFEFBD1CFFBF3CA6A8F44F4CCE4EAF2E8A81F1E6E ++:80800000FE6169CFCAF8EAE8CF6AAE226F637724F222282F49F8B2ABAFA6F7AAAA5E9A2FAEFAEDEBEF4EFEF7F57E52DBF72FFCFC8DBF1F5DFF813565F7316DDEDC5F54F48A9A4F4AAEEF4F49F88A8E2B67AFCCBD66FEECE88F8AFA6A326CD42FE7B3F7794BBF46D43C754FF2421A8F31F571111F1BE929FC434E7F96F463AD7FDCBA85BA2C ++:8080800088FA81823FC8F4C8EEEF9EF881C33F8EBAA8F8A4457F4EF6662DFF43FE42E53F16FFF1F11F23F986FDDF66FCE6A4DF72F6276CCF76BCE7BCCCF444288BBAAEB5BEE59FC8F26C6EEBA68FEAD248F372B42F4B722EB446B227FAB6AEEF6AE5E97634F921C7EF5CF3B7716F957256D598F66F751FD7FB38AB2FDAFC8DD99E19DD71D6 ++:808100001BD74F4DFDF4944FA1B99EEBA8B918F776F88F8EF1185783F1713F3F27F773712F31F5561F27B52F21F53E2A7F55F687AF3F29F9E3E3FFFCDEB9F6AFEFDFD2F2A1A91F3AFA86824F28FCE6E6BF8CFCE7EE8FCEFAA4A45F76FE6167DFF2F3E3631F1FF2F5A55F5FFB9696DF5AFEEAE27FDAFAE7E75F7AFACF4FCE4CEEC48F8EAE18 ++:80818000FD5F5BFBE1E9CFCEFE6A6AAEEAEF8AFEB6B24F2AFA2222DED28F2BFBFEBE6F6AFA5496AF2EFADDF76FECFE57F3CFE7F7EF763FF8F8FDED1F1DFFBD39EFF8F9F9B58F4F5BDDBFBFF746C6DAFF94D4AFA9A9ABEF89F976E6CF8FFB787CEF3C8914D21134124812842148234111C24940081400242024124834484413C4249120442C ++:80820000A4444448291241840448E092044D4820024382392410E42439241880D844E224C12413442444344144400416144104824882482145C8C953A62880511442160148609110C282F02482862102244460443CC424B0414292218E424081A349818012C4828E41428008188A121C82A84124C01240128264482C94212C0110419221B2 ++:808280008A943110017082018AC41429A4168088E612F8E53C944F627148F8241297844D129F14C2129F46C2129F566228DF4662299F467292D259F292425D242FA9C424AFB944F4924B223F9934242FB1B424D892F424949CF42492944F2269946F22F948486F227949D824F949282D929F44D222F149248E129F4432929F447292D25998 ++:80830000B292D441F292484CF29A4944AFB924F29B4B43F21B4B4B82BD494B929CF434B21F94F424B21F14F426B283F4249683D426B948C2928F44D222F148242F583D449D246B43811E618D262F5134212FC126F2926913D6D2B224D992B624DD92F4219A27CC4F1271C2F12418B31DB4CBC2139F44CA92BF44A3189F647214B2497AB230 ++:80838000D168E211D461FA92484E369E296CF2924D26F612494F22F812494B822F91F42C828E414F22DD92F42592CE294F327848D124B949D224B94AD234B94ACA93AF4463381F646AA84E342F9AE464E893F449862B4A444F89D668F2924487428A742C82F42492EF430C00842002000000002004810030210000822001840000000022A1 ++:8084000010044114000000100800820000820000C100000020024100C06D83DC12518252A0141860122F410240229924242CC2210024328008385184114C348190418818245813044242142117284C98228B18488828411A02AA25A8424812841442684200444232E014410243022041080060418B7FE014CC24484481A044E024860180D8 ++:80848000A411184081E24C02424868442B2424482448A0214038C44744C44C87D145088820044AF244A82D18448AFA13881D8644252234881C58282C1428528C67412C9688818BC8816181203A424784212522A14A2584DE2BC8F8F3374142438394444922E414B224944200984364242C43115181298201424AC2248E2425A8412394C320 ++:80850000126288866C64493548496556491C24F8418443B822D4483328824CB246F918216CF882643D888C2A7411588284624F88446441AB4265282C5B42178480E22204A4218D322246064A081F180327219904841A010023216221802122810228C2492204827052011444001480240144112A0110512200488E8246A8811C820818A0F7 ++:808580004480083C0420325A00828D4800160286841404122048447228F4925281441415420830488400898122025100122480A4254004000000000088840000248449094005148002C042526041264344A22410014200901100C084002122212A0141FF484EF2412870142165811123B23204272211A04481A4AA28216C48324998C817A8 ++:80860000123E11483B419B224210E844846518831934214C28416A2C838C8404C0182CF2448285011A11A411002C76812418614454488146C92483713C6CA9242AD485C242481261899D22876181822F9134A44C5418644818E0822402249721222210552812201804B81C14116134814200424242002E81E04108A9348820B414086081B6 ++:80868000261602000000A6912444484A42057048313C89921C2781D04164822C24150423A3211E2A8264BFCD033942E1910114812D1289042280C44800A28A4D8283D48484A23841121E214A02100849C98183110481808854228448004419C48815816241121AB14224C1164A58132444C0494800184948412202448224842968A41084F0 ++:80870000C1732347F1114464C07144002100818420028B482111242021A22446D21488240346421C08144461444142684A01162AA81489524248A02488A14815042412888C652186240521F0221C4604412C210A260841418A82022C62414FD3028184361832244D22A02228302461484078846C441410081C011C226818181092124043B9 ++:8087800028081F8894224612280283044992C20028594148A8842D81988C0250462214821800854208286048D04201184448481248823C3B5428000020811188914220A81823810128821A9282288314C41824288445082880222101100212849240420489054880022001C24501248374283222448D84684812420040848498484A48026E ++:808800004608484F264BB821453824A914859312A42A8112948681C21AB18C88028638328AC269121C7298841651A841462453282611E86148C82249840189146861302481EB441CB42401831A220892A74A17418A446A419F2264428C0883344C52442AF18224C01C428E14818AB242C448B022F144B4630B45C1128001800228464208F6 ++:808880001226024125044022014E242C1403280084408119149146422528A441982588B812A48612002200239494800424AF418214820145822253484800886128208484A821A048F06B9130245084421092282D4428442885048524C8142127422B44441AC4144800004182628422424991243018008800404846880C20021225062761EA ++:808900002CC5241222004A08000052502290481018F24A22302868A5C2FB938B1182221102D084012128488498400810082E822008241E2481214C014B4890282221184053C184212E48214A1804235A14114196414A0441120030418692212481242842912011094490480048A30141AF6709178140028C04902484000042002E41200821 ++:808980000025088C646883234204403412818424844542048984F148284D224E4848598444084982B2113188288FD882984814A5A8448538242222242442E10024481004282821A082F388040090248C066053001860A1442061814411201481112244C22212493744904248008081038028418182014C416282C6041008401289C1312483 ++:808A000060284460128100882110C2821244214120F1AA7C1C081008444008001042A818C0611C2204128240088D34002AC8828830284A02490118410020820244228488002840024C0228248A8104882210880212E0410120244404800229D821397221207211D24202222CF132412C712238182021B41284012371C22181012524823493 ++:808A80001210022427482418001824182896C28288C2502148200423180140410116838156424C13062222440022000014C024181A286242CF590440040081408884010088009042004400180018101404001008406482000048430110C4112A011654481D12A0112114430424C08281848450821022121308801D1A2244C83C632B621430 ++:808B00008484121144421C01168821018424340096421228215428846842A028E01428C912181086810484214E18B022988180C1188885122182088826C481212C889B848100814240020024210018444212428FC2082528026222424110522130443044B05808C5011120410241214318041002414B44B044041031242243282281041354 ++:808B80006148115524B4821489144141042A42018220032718009A82410182A01242432404421EAEA3B812F68842811C1492488B624825FA1931A722A92591588F8861213F14F2211425F246922911B4424153881E444F21714242E24882D98232D627814C614247216183220123642C30C86F14028AF5148C29F29298271518402859C4CA ++:808C000053C142129A7224A6A82C88C22823941A811A721854222C2C24B814A43E2394125641FC787D28339129CD72A14F41145C288D71172123A412811A995C86A41127292F96B8488931221A81447212FC184AC342742424E4C628B416B6529542A41C614147448D882AD882A1944F6C33444E151515CC244751F01E21558514E611B2DC ++:808C8000435A628F11F461224B481F26D28C62C229024332499A8238216C5428C44816A23423B424E246E29A3EF25122499218242603CF61C36443E2C1E14452484A5842A5684246E14581F481848B4186D48EB414F262A22AF434242B882B83474C1F46E882D444924C1E1858E41F3151482FA1B828CEB86E381D221FE2F8C8724AF84162 ++:808D0000511D8987621BAA6B24AF69B812F12FA42B31ADB51F16FA2A921FB4951AC572822832889F12642565DA22C11295018D4227248562A18D248F2F542A5E129F46890249022100104215420444404442454244420440022440820228108204842184002100842184188061822400100881100989410400888129088881291888D81836 ++:808D80008418181228D12C1FF8456485D844F2734B45F449698F86F67A5A47436D444F43F2664A1E1C8FC4FD44941E18AF6AEE63F5141CCA7C14F61C1C1AF14C444F61F16C2A4F42A36625C2144574CDBDDAEA46A6418FC4D48A7418FD7959CFC1F11A388F8EE68FFCAC28EFA3FFADADDFC3D4417C1DED5ACA159F32FB61636FA8F85C5AFD ++:808E0000CFEBFB2D3DDFD8F959389FA8F85F2FB7A4A5FE828A8F88B988FA45255E818F81F98A9A7FF3D39BF848C88F8C4CF89ACABFABF858582F89F84A4AEFEAF95E69143E4887C44FB27569D494F44D288FA2F748789D799FE5F2266EA3D58C74CCFCC41CEBB1DF1BF66556FF61B4C6E189F448544FA5F44A34CFC3FFE82AAB732396742D ++:808E80006F47FCC4EDDF8AFCB46AEF87F14C5443E425D117F4611CCFC1F11EE8ABF6CF4CF674744F7FFEA56557D48FDCFCC9851F1CF8813BBF1FF773963F69F552B66F5BF237A47F39EC2EFDF2477F7AF4261AAFA3FAAA88AF8B7888F54512BFA8F1989AAF7A79BF7B89E22CEE2EF8881AFF36D522BFF2F7384ABF64FA82D393F47969C71C ++:808F0000D26AF6536BCFC5F5494D8F86F67A729793AD684B672FE6A6554BCC9AFD141C3FBAFB24621E114F48E929D88881514C4F63F36CBE4FC4A7766F22F2E426FAF3F939AF8BFA282887818FC4F51E48D7D1DFD4F61C1C2FC1F1A8688F8BFE9C68EFA3FFADED9F9BFF11919F95F5B1F135F7258B7F3FFF9697AFEDFDBEBABF9AFA9BAB80 ++:808F80009F85F3F99AFFF7FB3B3B8FE2F38A8A8FA212F8EDAD9F15719AFA1212FF4A5B83CE422F24F6C8C22D4C2B435AB5BAFE727A6F4FB92ACC3BBFC3F64D686E5B9FE4F55E499F84F2287A8FA7F71B7FFFE7F7726AEB575E54DE9C4F89F11AA23F7BF7735E67212F297192DC4C7114DA6AF33E7EEFAFB23AF676866DF44F42FD94F9DFCF ++:80900000AFFBFA7AAF87F14C5CCFE5F15A1FFD5D9FC5F11C9AEFA1FA2ABC8FCEFF787EAFFFFAEDADDFDFF19DC99F1DFBB1BD9F7BF7BEF77F6FF996DAEFEDFBAEABDFF9FBBFDFDFAFFDFB4FFFF7F15D2EEFA3FAAA188F82F228EDDFBEF51B9A8D922FFB7125D3A9FC4AC22F8EF44222AFA4FEEAF22FAFF75272BFE5FF8824738A412104425E ++:809080000028004AA121200821A02120010000702408418841884B422C01108401813048008E241384324844112514B1920244E04142311222212A1422822802482C01181442200480022842BF4ACD8130492A012185C8124E412483068420A411C04211C89012A044282B5445140221224243D288848114149816914D8280E982044421B5 ++:80910000818A98298895A411D0820925C8242F98082795401814021440682160221124C01240222461442D5733D161F236488D262F9144F6124926F2124957222FD1F42C822D4D4B922D4DCF2259D25F2279C2F524D2A7444F22F9CB244D92BF45C29BBF44C212BF44622A9F4422FB492423F949262B4B9D262F89D468F29249642F99646C ++:80918000222F99742DF21249CF22D892F424922D49CF22F982294F2269144F2239484FA239494DDABB24BCF949244D1A9F447284F24924929F4432969D262B499D246F89D468F2964887542F8934282F89742CF2124CCB866F3342D1267348F9261487162F62B14992169F54D222F1492C23F8492427299FC4E22DF84925AF21DC48F2D1FF ++:809200004A15F492C326F4185A22BFB934A496BB34FA52496BA22D484F21D991B4A64BD126A9446B9213F62682DB246B919F5452221F44B292F141242F28F14924CE829F46B21AD44132D31D242F1D44F4D24226F4915126F482494F43F812492F42D992F4A496942F6A69144F6A39482F6AB968F4A492CB244B988F44F28282CB641E7A99 ++:8092800053020000400400000000400800000048001800000000000044000000000000800400008884182002001A02200428000014F06F5E18001642094880028C08AAE148021F810120AD848B118440681823762801008011F84A1488008241008A1448A4142376A888A883281A188822842881E8420244325044A0E8A03249028F220421 ++:80930000E0440120888B24626CE0742C6814EF1875418821E184612116088CE4213244B08A445A149221922074C2C45A46311C23A41487444394C8899561411489914869E224084829016E122140622989044002A01A4284442B48C3068CF22A41873445081C6484CD82408134824A5A12148D82E02188E2118CF29947481E53841F212251 ++:8093800051814284494228E44A04448FA245A811489E418789825668A81E818F8495A28714C44A447298E881F611482D114528E124289224E04418C2621E44B052DAA801F28A446A88482E912282E022B824922C4B8126EE32318C2C2AC4284AB28252284224821E2340B48A28A28F2C15E5323CCB114528048921E1242101D028A12898E4 ++:809400002B48115488212001274448702411820541424810048281414E82001283042428248281A0120000528486842404811C247484082E414C5184402184E4440A1C0818216282429F4E02418C0481002480010060441A0100008280048A0400000040020022812448200414882824288881234184010082002200A022148240028281D6 ++:80948000248008A02282C07493912812C042188315688100602443018825490286044381058181206484B0482A9548491808114819C85482886088901E40C211432888028A04880022160A27811884151814E48285618A1E84660123042C088A121244B6C2F2B43BA0126024811252100AC0421848881611082008004889888404428C8A83 ++:80950000018304812160142A041082043018112941062283222188010022122001109924281B1C88812521542840028824308488CC32AC8504844222C48418200110044129450A44C0941A041008B08801422C04860440018887418A3284488C08612098218288888D4242458108805882F08228188901282534182032948A0242292238AF ++:8095800084282822614E22FE6F28008100242A0685A481C90481222632214188F044288280840281200420080025282111291461A44221832434458A549156044B18414400601180419821818182B0850942001A61428524850182E04528D44836C100008004156224000000C440321410226A2130114A02898208805481002248002100D5 ++:80960000001902200A222288441230184268128248120000443084008888881880048240F418742C5118480000841200442006418829021022F41848228944840110E28202482024A1242C84018D8198400400A4441008A0446041608830C60000428100182A02000080012480E1263E2A2E18C0480048216E1A4632144388648422411316 ++:809680004242B28411D428941823153811C3222132822222100112892792421A44C8415E8240E4128484C8E88B4126882A9144521212581145A281848302421024012082211B64441280048A6548CCF624AB10120100285081400849022824C52428C242288AA8228984A244C048008889048B442480619440918284248C045440115245AD ++:8097000050448244409488288BD4C041608188848811432834B400848A0918200921421ECF1314084200002142822220A42140041200000024281002200840022C08000030822221000088860440820282884002000080082048260912003012884818E79D581442408281024044280881800A10022818581800508842200E414688128226 ++:8097800002002B1413A4121D44C0886601CA110288418888B08441E4424A4804004E816048288A0821130886042984822288084C35B2841480021800000042224888204108000000864822012C084220328200B04202221110020080CC84001430849084882008200180088882208188312248808308126FE28E2124A4242E222E244574E3 ++:80980000249442448A328810A8414E644E48855A9880021A051229A88A8E985AE12173C2121204A502208222E2427255D444B182324448831AE12C81A4444E48C7888D893D21138828217224CA84828AA9115E1327282768882224B08708284B222E2445742434824882FC347A200421000080240812C01282002400002820020000002039 ++:80988000040080140140018800004082080000000044100400220088824888008008D0630A840022224742100400002024344881950111000082824749121221210040024828302441410022208833424287841281111100229081202931122121000000A2224392844120C429230500846884440000800880C4128C0114000010A488A070 ++:8099000031400200888005138202454401482088C181498824411852120000E0488228A211502600002005212850440080F87AC100006250840000100888421008112008121022081210060040040022100480080000421088180100122420081222210082A0844100224A180400C0BCC30700000000800200240000210000000000410070 ++:809980002004008200000082208122820824008200000000001488000000008200003FCB0E81422889C2244D44440000001A84C448849414160120028888984AC1124002200242C021E042624144218002828084C448854C091448200288A0D84D182C41420200008082CBA41674C204008C39510000381A424406802821180229C442CC4D ++:809A000058841414481008284A88C8182C414202000000A02244440000882180C44284864D4111028012048A88C11824248004A08400282844860482281F960442818100100288008212202122020010022865041004004420042420081219140200001C28210182800100280011420010018084280400000082C07EB30B00000040080073 ++:809A800000000000000000440081000000481440010020188101308286020000000028000028400482002008002400827F6B0F460848A11884008984228801121A0A40028084E1820265844444040000488664248890510000008200984B838221888200806222904128404801100400128AB8820C8E82008A844A366E844E480042811089 ++:809B0000028890888A08234952224B814129010010624244463428000080044E4220445111483180488121E12812022321180688800228413044818012A188A04C8AACCC202421082B8882003EDE00508818402204800812122121380080082100222200C44400416200121D8180410214C8A82AA88896B1913282218E16402281941200B6 ++:809B80001C3224902444440028424400008A01C200828E94A35C914A64148D4883741199192B1117212F2119D222A18886A291922F22F112224F227222F42424414D2440A4222A7244D444F4484446F8484885D19904944A64148F88F448881F99F889112F197911F2129221188AE828A831122D122F21F2242226D44412D44402442A22E8 ++:809C0000F244244F42F4484446F8494885D1991441A8C4428D488F84E889B888B11269212F2119F2639F14814A34418F859448B5F91118182D12272824128A3882BAA9816F21B122D322D26452442002A02622CD244B464D448D4C8415691410A84C13F458488BC83D891B911D112D13272824128A28A891926F21B122F322224556444489 ++:809C800022006A22F22C244B645D448D4C855811171414814A24F458488BC82F88A811182D1227283C3AE3000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B000050440040444404000000000000000000000000000000000040480884508885588800404808000000000062 ++:809D000000000000C0F7D1410040144414044110040000000000000000000000000000008400841008508800005088001008000000000000000081843FDE0100004144410000404404000000000000000000000000000084008481008100008481004008000000000000000085083C2B08004014040000004441000000000000000000008C ++:809D80000000000000000000000000000000000000000000000000EFBD08000045040000005044000000000000000000000000000000000000000000000000000000000000000000EC3D8B000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B00000000440000004100000063 ++:809E000000000000000000000000008518180800840000008185088100000000000000000000FC3551000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B000050440000000045040000000000000000000000000000000000000000000000000000000000000000C0DEB30824 ++:809E8000004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD0800004504000000100400000000000000000000000000000000000040484808000000000000000000000000305A000044410000004014040000000000000000000000000000000000000000000000000000000035 ++:809F000000000000F0DE8B000050440000000045040000000000000000000000000000000000000000000000000000000000000000C0DEB308004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD0800004504000000100400000000000000000000000000000000000040484894 ++:809F800008000000000000000000000000305A000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B0000504400000000410000000000000000000000000000000000000084848400000000000000000000000000A3150400104414044110141404000000000000000000000093 ++:80A0000000000000005088008100005088001008000000000000004018088F3E0500004144410000004400000000000000000000000000004008401808100800401808008400000000000000005088C0C26305004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD08000045041B ++:80A080000000005044000000000000000000000000000000000000000000000000000000000000000000EC3D8B410000004014444404004100000000000000000000000000404848081018181858888548088100841008000000000000000000CF944904000044100400004400000000000000000000000000000000508885588885180886 ++:80A1000000848181508800000000000000000010D878362F000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B0000504400000000410000000000000000000000000000000000000084848400000000000000000000000000A315040044414441100441414100000000000088 ++:80A1800000000000000000004008400881008508000085080000000000000000000081846BF500001044140400004444000000000000000000000000000040084018081008004018080000000000000000000085082C3D75000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DEA5 ++:80A200008B0000504400000000410000000000000000000000000000000000000084848400000000000000000000000000A3150444001004444100001004000000000000000000000000008484840010588881818100818484841008000000000000000040F89CE94400001004414100405444410000000000000000000000000000000071 ++:80A2800050888558888100400881818100000000000000000050888D86130C004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD08000045040000005044000000000000000000000000000000000000000000000000000000000000000000EC3D8B0000444100000040140400CC ++:80A3000000000000000000000000000000000000000000000000000000000000000000F0DE8B0000504400000000410000000000000000000000000000000000000084848400000000000000000000000000A305004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD4804004066 ++:80A380004404101404454404440000000000000000000000000000818181404848088485181848080040080000000000000000007C33340000400440140400444141000000000000000000000000004008400810088100008485588881840000000000000000005088574F000000005044004014040000000000000000000000000000002A ++:80A4000000508850884008008181810000000000000000000085C8D77302004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD0800004504000000100400000000000000000000000000000000000040484808000000000000000000000000305A41004014441404410010040032 ++:80A480000000000000000000000000000084008410085088000050880010080000000000000000818487F60000104414040000444004000000000000000000000000004008401808100800401808008400000000000000005088C0F3C30F004014040000004441000000000000000000000000000000000000000000000000000000000020 ++:80A5000000000000EFBD08000045040000005044000000000000000000000000000000000000000000000000000000000000000000EC3D8B4544040000504400004004000000000000000000000000004048080081818110080084848508850800000000000000000085F8B153440000414140140400004100000000000000000000000004 ++:80A5800000008100404848088100008185184808000000000000000000848D73D303004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD48040050444400440040040000000000000000000000000000400840080040181818084048080000000000000000000038431B0400102A ++:80A60000044144411004504400000000000000000000000000000000508800810000508884008100000000000000008481F02B5B00001044140400444004000000000000000000000000000040084018081008004018080000000000000000000085089C364600004441000000401404000000000000000000000000000000000000000021 ++:80A68000000000000000000000000000F0DE8B000050440000000045040000000000000000000000000000000000000000000000000000000000000000C0DEB308004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD0810140400100400004400000000000000000000000000BA ++:80A70000001018180840088400008410088184000000000000000000848D3A72000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B000050440000000045040000000000000000000000000000000000000000000000000000000000000000C0DEB3080040140400000044411E ++:80A78000000000000000000000000000000000000000000000000000000000000000000000EFBD0800004504000000100400000000000000000000000000000000000040484808000000000000000000000000305A000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B0000B0 ++:80A8000050440000000045040000000000000000000000000000000000000000000000000000000000000000C0DEB308004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD0800004100440000000000000000000000000000000000000000848484848181810084000000000075 ++:80A88000000000000000B4F308004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD08000045040000005044000000000000000000000000000000000000000000000000000000000000000000EC3D8B0000444100000040140400000000000000000000000000000000000000AA ++:80A9000000000000000000000000000000F0DE8B0000504400000000410000000000000000000000000000000000000084848400000000000000000000000000A305004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD0800004504000000504400000000000000000000000007 ++:80A98000000000000000000000000000000000000000000000EC3D8B000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B000000000000004444000000000000000000000000000081818100840000008481810000000000000000000040C8C373040040140400000044410039 ++:80AA00000000000000000000000000000000000000000000000000000000000000000000EFBD0800004504000000100400000000000000000000000000000000000040484808000000000000000000000000305A41000041444110041014040000000000000000000000000000000050880081000050880010080000000000000040180877 ++:80AA80002F710900004144410000004400000000000000000000000000004008401808100800401808008400000000000000005088C0C26305004014040000004441000000000000000000000000000000000000000000000000000000000000000000EFBD08000045040000005044000000000000000000000000000000000000000000CF ++:80AB0000000000000000000000000000EC3D8B000044410000411044040000000000000000000000000000000000000081818100008100000000000000000000F907000010044141000044000000000000000000000000000000001058888184810040181808818400000000000000000084AC38A800004441000000401404000000000045 ++:80AB8000000000000000000000000000000000000000000000000000000000F0DE8B0000504400000000410000000000000000000000000000000000000084848400000000000000000000000000A31504004441444110044141100400000000000000000000000000400840088100850800008508008100000000000000001048D8470206 ++:80AC0000000041444100004004000000000000000000000000000040084018081008004018080000000000000000000085083C3982000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B0000504400000000450400000000000000000000000000000000000000000000000013 ++:80AC80000000000000000000C0DEB308101444040000004004000000000000000000000000000010181808001008000010180881000000000000000000F02C5C000040140441000040040000000000000000000000000000000010180800008410180884000000000000000000812C181B040041411004410040040000000000000000007E ++:80AD0000000000000084854808810000000000810081000000000000000000F0251100001004450400000000000000000000000000000000000000008508000000508800000000000000000000845018F2410041004441440000444100000000000000000000000000000000508800100800848140180800000000000000008481F013D52F ++:80AD800000000044445044444444444445040000000000000000000000000040484848180800000084104848480800000000000000008508C893010040140441101414145444414100000000000000000000000000000000000000008100818181000000000000000000F027FE44004004414054440000000000000000000000000000004C ++:80AE000000008518184808000000005088508885080000000000000000003C36B300004004100400004441000000000000000000000000000000008518588881810040588885588885080000000000000000405888CF1A0500000010040000400400000000000000000000000000404808848181818100008450885088000000000000004B ++:80AE800000005088AC34CE00004441000000400400000000000000000000000000000000000000818181000000000000000000000000C05A000041441004000000000000000000000000000000000010081008001008000085081008000000000000000000853DB5000044414441440044000000000000000000000000000000000040187F ++:80AF00000884810000848100000000000000000000848184DF310E004004414100000050440000000000000000000000000000004008810084850884810000000000000000000000003C3C2E000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B000050440000000045040026 ++:80AF800000000000000000000000000000000000000000000000000000000000000000C0DEB30800400400000040040000000000000000000000000000101818080000000000811018080000000000000000005F1C040000400441000044000000000000000000000000000000810081400884810040088110588800000000000000000027 ++:80B00000D0883932000044410000004014040000000000000000000000000000000000000000000000000000000000000000F0DE8B00001004004400004544040000000000000000000000000040484808000040084008004008000000000000000000CC327B410000411004410040140400000000000000000000000000000000850810FD ++:80B0800008000081001008000000000000004018083FCA020021104414040000444400000000000000000000004440044400845044C4C100810000848100002424242400001002100244008508DC38720040524241000000401404000000000000000000004445140400000041104414040000000000000000002425121212020000F01CED ++:80B100003100002552440000000045040000000000000000000040544441414100000000450400000000002121000000502221244552440000C052430C40125242410000004014040000000000000000000044441014040040145444400400000000000021000000002400410000B0C9020024504400000000410000000000000000000028 ++:80B1800000444004410000414144444100848484000000211012020000400240140400C0DED31F044012061044140440044400000000000000000000405444410000848484005048C14008400810184848020000004012522224000000F031AA441004651214440445040000410000000000000000000050444504000081000084450C000B ++:80B20000000085588800004002000025120200004008AC3AE54100242141444144410010040000000000000000000040544441441004001004C54808810000508884004002242100002421100244008481842F4101004012441444040000000000000000000000000040044440044008455484850441810000848100002512420200004035 ++:80B280000240024504508840343600242552424100000040140400000000000000000000404404450400405444450400000000000000400200002421405444000000EF1F020024255244000000004504000000000000000000001044544450440000454454440000000000001002212400004012124244140400C0A8F10045125442000000 ++:80B300004100400400000000000000000000004150441004105848C504410000000010180881211002000000504221100400B0444804105222440041000040040000000000000000000000414144410000455444418508850800400881104808002100005022004514040010C8FFE305002552424100000040140400000000000000000004 ++:80B380000044504441444100401454444100000000000024400221000010021054440000E0770D00105244000000004504000000000000000000004004444144000045144404000000000000244002000040420245024400008C3AF4002424504400000040140400000000000000000000404404450440084445544400400800000000005B ++:80B4000040020000242140544400000017CA004042524400000000410000000000000000000000414445044504005044444504004048480800001002212400005022104244140400C0F27141004004000000400400000000000000000000000044000040544441C1100C0000100881000000000000504261100400F052A3444124246512BD ++:80B480001404400400504400000000000000000000004444411004100800C44048080000840084502221000000101202000000C05CE30B24242425044014040040040000000000000000000000401404000000C48100000040088184000000000000405444451404405888EB6F000000000000401444040000000000000000000041414121 ++:80B50000104404C440445C8C101C088508004008818424242121000010522200400400C0F5B3024082041A82932244403448812384088312C24848E088A24127C821103252488088892842A8144372242208101122044A435441441001118CA42880A242257882691112239146218081ED22B124011008414902C0244442BE5AF032228C2D ++:80B580000226088190244AF4246829DB4468C43048AD4220C6882E488AC58818988999221EA4648E8A1A341829F122825E16226722942845D844B1216A1143B236342449AA452C5511C21AB431625429D48C7481F9D4981D118E142C4AC744AAC8184BD82CC82389082D166E216572242426A8211E26882B65F0264B638611428842480867 ++:80B60000430230448384084850822C024A4288068A0180024881008051A4212871282061132C8201184922C412421222422004144E28181F419892402298825888C82A0121282608400424294144F2CFBF200220041A62214840826841812B8424200281828800690823813614411A149892C88014048B8250582058214480614814881518 ++:80B68000011371213D42478A442220884284342467C4001612092242314143A618202122A8448C270620022002604243024C221448182884840460814A0189212811128288A81810228342044441280020E24204800480040042481918130818880082211829483634000000C02422F0964F242810020000488C0200410000844882708827 ++:80B70000480210222818220123220212210000D044A44280041504000050188AB8184148021583012001288001442400412A428404284D271306000000000000000082000000400100000000000041100100000000800200000000000000800100000000005FF8C145481218144381818103AB228A44843148430812800482382029AA31BC ++:80B780008CC4888C94241628024849829112182142402202200280022841218800204882E4223148409844146602AA2853242249084324A818C012C018838C52824400184842241248006082818022081AB4849482812D14422110024842214181C4824411B041281131E49628F181484913110120832895A44611662D811128422C8298C4 ++:80B8000084200CA9842829820412A0488442419F3C89D424240116B11481041E12248B638A04584C0A81200242124D12AE188E862AE42161822483182C3148508449C2128247314021C4224CA814812601160122108488A4A948112F28440A153852004DC414428A88321A604A22A014001224424DBC239621844400808124020041848118 ++:80B88000800188802C0C80012004422A8412024885042021248841212288E18834241001222B2100411024094A222264228908282984A2484C3812A0484482888A1428016FEC0F180081C0484048028815484281110410021692241426442112021C04483684A422A0224A8418018008E042A689854412080020084A14A4984021528843EF ++:80B900000288A088901410024008C01200818E5D83210323C242871148C0181A842DC8188012E22822A821A02929E2832464A12E481226A424844372414468229C69D19E44882951421998488C892409E011C4C81941B41438864B822931428A2263464D426245D824048B424C98245781496481297A31741832142C29A88188421328A4B3 ++:80B98000528FE30100008110A811204401503288128236822801830221CB162E2220924844002A785838255A4662114908460842822A5114CE48142144824922082B846A22D424992446086120825214C0148912D28201240012B01208E0143CD538122C7242981148428483B412886889842290260020E221D242A5428F1102114142900C ++:80BA00002519B468119621124B8282482C4841282928016AC8184C688141122C48E421083014E842902589D448C2484C28F888144B48209935214CA1188C288888149148B8ADAF1859A42280E1421401008840C24150228E28501182882A426C8120A664482608B04A042C88E11484A44100430280518246248292184243D2888182143188 ++:80BA80001830981881CC0944C0881C1864842604448498244A08288C42041AF148B673428A911490241004248364232A840843E242544841114E28432488840222A081002C23121808498202801204008882406288422281421C8B2882A21820211862814358241628488408868A041A88020042001FFE03260284809112304246020083BD ++:80BB00000412A0484812000012110048200420220290282B989088522911088C9142209892448221414524A248004D882248004880B21405122820480C1AA118A088A1C04F13C7261E222A1128715122813442842096C813E441E2280251D88B428A064C2582A42480C248425222899288182E451628AE8144D8248C2191C88383C422AB67 ++:80BB80001C2A61C8124C664A89A3281A2C991C8A7118C442308449D894E94CF144384908472283A4818B418212182E886F880481D79F9412424110042440A22423092110D244A248004488228D182811284A0480924800232284221442080010423482848244822221A08541842280120884418C04200212848A086C081A88028081F411B0 ++:80BC0000E382853282244512322224000000200212B0142266528800452801C332241084821528841264434381282481012024024A81322210A29446A41C488B1C188883044A024880240C00889018800830144449B13E03004800488440284448444A44684415661830882CC44440018742201418081241109414850142601A2684864585 ++:80BC800001481028084880414448841C0441184D88128C081880082021442828041588042C3FFD2E18A232814420341430142084818488A32C148688028322981920242181022A490280082001200120412808CA03186022400200892488A128400884128A0328800280882822B21102E012B4CC4482440212228724201444044142000040 ++:80BD0000005112184CC2144400CCC4442654424E84442FC2014822448524024888002442414488308445119C45001302004308182A0420024C0884484410014266A4811C3CC800100443842881810412494134844414482001A012B0112801440020882104820000160824424C01806142C02800304826844224828C93122002322220A2FD ++:80BD80008200188001820048B83F6309A4848425422251249092E0280821004A0913A341881A01C82608441A34214CA2184C81E28801182E44C0428AC182184896C4424CC9B4460482701202A512440142008002874289524C814D14884145E4420141450418C01440C494530210842104C4508440088412842400C224C1445012103248E4 ++:80BE000010028D8200A02848800414A04828148200904112408401144024614412000000001810182884A4244884180081CFCD092A28B73804001008C5249188902C4AB82CA2244C428802001A440884608860228322B221A1444938322212124A080041B0148A9284491104884001894288C614428880044881820000800120210A19C460 ++:80BE800045532F0800285048502830484C714882911848608181164548244808C0A88021440A20442201430428E04482028822002082EC8841184801280054C0A146941470C422112401826183A1814A329186058212F0A7CA8CE12219722868412F6414925818C955448328714C823E3C2A85B321B384C8184112CC712A21CC689CB2546A ++:80BF0000BC2842283232A6218282ED1164221220064C64844B28F074A4CA9735AA72B40A462A681448228B5118C2837B2464C18B42CCB468A49188222A78282281AC4D144E118AEA4131141DA4CF68328E26A86816F4124C2189A444AD1865D28C49F44E8C2B84CFC101CFE2E152B3C3714CF17C7C494BA8C11C19FC1C1A4C117424F48813 ++:80BF80004C4D142F417484B448B4C626DD4422319445B142B921634B9AA21C415E821684788424F984A24145734C34A489B48CF288E48243C2118F82CA848FC3E648F138444C6B4386E44258C48D5C16F488448238422816A1243F494392628D2A2F41148261A22544084E481AC11C2B41C48AC881C249383829D269BA44F8346118DB21D0 ++:80C000004E14897428D842A4B28FC88AE365D3887194F4742A4E244F85B444A19989ED2C24D761E114ED488264C36216127A14B212B94C81F545248D7147444CB611B54492424304188A684242128684A158844CA1798A981826E84CB454E1153EE1D048010000000000244022512140224102344022410200000000144001141814400152 ++:80C080001400110080011811221100008008000000004008844284BFBC4FDE26F4621EEFA2F64E426F24F1124A2FA4755ADAC8F558DCCFACF44ECECFECFDDC1E8FC1F19C3A2F3BE169F6CC68CFECFAB262AE529E693EDEEFEDF44E4AE7175DE22F8C7678D888F42AD44FF9F13F1EAF45E363F9D2114F73FB96D44FB5D11BE333BFF6F1142D ++:80C10000133F51E21CE245EB5BF275A15F9AF23B1E6F6DF11686EFC8F14C344D6DDFC2F53C5CDB911F5BEF27F33368874ECD68CF82D1CCF72E844B284F42D84472243616C979889C548F96FB18B88F49F91C4CCF84FBAC47722F23F34242EFE2F24E6E6F64F45676AD4AAFE1F51A1ACF8DBDD8FCCACAEFE8FC9ECC6FC7F72E8E2FB3BB4317 ++:80C18000FD62F9AFA5FDBEBA2F46FA76B4FFFEFADEDACF8DFD5C7C5FD1F9A6A6CFEEFEA8888FAEFAD6B6DFD4F2FEFA4BFE6F68FA45647F69FED545FFF1B331F7B3B65F5CFC97135F4BFF81D4FAFB81F51F5EFEBB3B6FE95D666F79795CFC7424DFD6F25D1DCFD5E911BF75FF3223CFC7F72C2CEFE6F2B4ACCFE7F2A4A44F4AAAAA4F42FA8C ++:80C200001E1E4FC5F4F43CC7484FCDAF3BBEB44FC9F11C1C4F4FFE2D1FACF33A5EEFA7F12A5EE7476D1267A18FA4F15A1ECF81F5589CC7ADEFA4F8D49CEFCDFBFC3AEBB3CF19F317F45FADF6DEAC8F4BF622F44FFBF63EDCDFCD719CFC34677F47FEE46CAF86F9BC588BF34FB9FBFF9EAF4DE161BBD6F335D62F5FFC415AEBA51F23FFF2A5 ++:80C28000115F25F552341B695EA15B2E6EA44FEEF23A16EF69B9D678C7FC5C244D7887139FC2F678B14F5BF3B4167F81F2382CCF82F22E68CFC6FFECB44B2B4F43FA24244F62F11618CD9CCFCAB114B54CABB3BE9C4CF55CB44F4E34292FA3F37E7CAFA3F35E566F64F47256AD4AAFA1F51E16CFCDFD9CD8EFA9FD9ADE8FE9FCBCFC8FC312 ++:80C30000F1B2B71F76B7ECFF7CF8EFA9F974364F4FFBEDBDEFFDFD5EDE8FC5F7E7774F4EFEECEC8BBBAF87F2F6B65F5BFFBAFA4B556F6FFF74652F29AC4DBFFFE51BF7D6F24F49FDD7534F5BEB4CFDF5F54BEA4F48FEBE3A6F6DF982C26F69FD4C5C4F46F67D7DCF82F66CF81F43FF35346F71D2CCF32C2CCFE6F6FCECEFCFFEB4B44F4B5B ++:80C38000FBA4A44F42FA1E1E4FC5F4D47CCF49E1CBFDB8394BBBCF4DF5545CCFCBEE910D215042004821008019841884782401224A38248082094228403448001684A42881168464414812482022188431248800438208422024A2148001423048304812428200840000008249C477B3A528902823014881218186344821811A14280996D2 ++:80C40000041A628244981F411224558428807A2488288211A4A42200888218124296048E24421E244186D4240124440084C2494114942840044CA841444188C0144381089880A141F0A2381CF424128B444F227149D824B149C2129F44C6129F4462289F4422F949242B199D252B491D242F89C5242F9D44F4DA492AF2935943F212494B81 ++:80C48000822D494B924E494F2269944F2269944F227948F8249293D424B949C2929FC4E221F969248E829FC4B292F849242B899D242B591F42F292D84CF292D9442F992CF2924943F21A494B822D494B9A9CF4A492944F2A69144F2A39484F2A39484F28B948E628F948642CF968248E99C39B2121282F91C2242D4D2AD192342425B924F1 ++:80C50000D892B424C9494F226D915FA228F4249387114F2218D924B941E232F959842CF848348E139D26929D2423D948E219D461E281C4A69E696CE25964228E4D4D129E694F2668984F22E918F424528E484FA2E915F22483836D2293ED2238C92CF14B84989F44E328F1498696F2498423D949B812D449E889E464FA12284E8427414E89 ++:80C58000842339442B61417F6A038004003014000000182004000000002008000048000040081004000000200400110000000012100200000000100410C139B30630588061146214604426081822200843C184441844438432141A22B42D1484220228812288811242418988014A4802F2AA0122C01480C848004A028C420448829182807C ++:80C600004808888182C0884898228C199818DF87859491424464004800821A41AC481243AAA1884AA211850483A4114184381160824A64814682C418422A2188810180A128128B1900A015002882728AA38800A0288100A014002820A41228888B411890418A1231D16E17B303488C25829144221904418B12F014884A336418898CBC214B ++:80C6800049381449E44431344CB188A3251E6D2223A21484608483A1288C88216741452821A8682921A182221AA4349018821B438C8C024A02A88B282005B9210188844282128283A2484325293EB88DC1228FE4CA4118400461190480288401008A8882514418418400001041C44828482C0228421800800818A08181184292004420227F ++:80C70000089A080081418088840800222012A89284400114188CE4D11B25044A11022521042C81D428018144812002004812244083024441008820242114220442144282886024000028100280240D0050844200484A38A430820044009088800824EFF803A94486E421242191482185B4820886E281082C584848822A1D84584460821A70 ++:80C78000E48121A4448166084A84428C2912E812C8869098281D52411B884F92C8424DC32A088AA88228462221886D422A3864112A5252202888A421604496BC81F8128685B1CA047A22B8646142EC384A8C046442121284C018889628482848082282224C25241104142281400881C24248A04825881631828492A86BC1B0268418A68269 ++:80C8000088A082218001D8D8604411263C624182488A24068642046C588411A068A88812644EE810A2441E1224461261244642724402241618442A182484083084212A914A1AE144841424060026B41803804824146114001B8884114E42118822A048222924082A92A400400120C81482224AE1989814882D42832834184CA224C0AC63E6 ++:80C88000964929044221448015149282422881002082410248004848832185144882A48190218148C9042847848118200A18218C2109833121271140C811822200381694A4701279540842822418221841182C284184A1C3AFBE09000022418004008D1429240A8C2104159814185810088009002B288001124002604224004A8428034D45 ++:80C9000024174C188E8A0011324C22082186A84A182268248880022094144860421C01347082C87B530E3042811800241218224C0110C418A8482031842280A4214120020014244304008800A01800002008200258402808126041400442A08400121004008AC4421312381940F4DFA470410246C812007042042B812E4489D28204411216 ++:80C98000AAA412C42311A441128B1446C418A04200821F26C1546082C0848100818381046A0940A91449217A82612616480819011882833254482A069EC412288810024024F85212188558261AF9247B531A8844820400124A01241249A12840880100984A022022044210082008160148460280C48212202822D124E84982081812A02121 ++:80CA0000889E2488291204224C3284C04981A01460444381A34142A08280217848E1DD8C050048C0482441121A0418828100204808821292A048413084B04C84911410A41449291484094B544004441F2444044644420464E04421C42488448A24A2E490224C0123043E14002B8841002C024480C294134748022120812101248229012130 ++:80CA80008181004308218180180688424508883084928004A0411440040000588028089448308142C24A02800B2842808202002228920020220849F4AD35284B443044844E42A044191112A444A0141888188095184880149444121884240014481C0200008818001A088800001E819821421285A88280880200100400A088614028082424 ++:80CB0000002820DA31345F1068815844400C000090440020242264414A014220582840081242402201202842A28290C42C44040040411448424805C0638041046012442C44C491C428CCC214004410880818C8DF69854838443820210442488484521028114424416C9210381820018820082C01181880C1411C61141C4961181C4161111C ++:80CB80001414864102354181088E41A01400A812228248821A810141800126149214801182018DD4C3030043840244100880C892C2884880848284C844248A948814A0144A81688548162832488882001E444848004242484242008248A0149880C8442148C8A01841444AC2842608C02112828848904100928F73038100108401124002FF ++:80CC0000418014B8181112081143811804004181801804E0448804448800000000000080081041048024080042000016010040080020018C1ACE2418890487214400811212828984018888122F44212214648460840000006086488400882004821811248840018601212124840020A22412211AD6240482495924004902414160188641CC ++:80CC8000049C28F243DD10825186608212650884200888802104819811204814088F8221A8421A04A512088114214A14032214614A24018841100442508C1001820011309120A14A318088280243280122301440041ECE23364492121E124744414E124484482B8484B01EE881288128F8981683F18584836861824148184AD888044A01B0 ++:80CD0000A096CE1413A8141C0886C1441D831AF18251121C2C781121E421B881C88B2504419BE44998428AB894A842A046674C4D24DE414F425245474A1B384554644FC8B184588413488B0A26A124EFA7CC2887874D482B214AB152E181E114218111F248842925F858484C28B11284E244EE82E144D5C4A8444F8821642249E8420C1885 ++:80CD80008B481F81239D114A24A5C46BD41F31A53913A9451541B2410413249C8515D622C841372C8E488B88124AA46B6AB462A5311B148E212A684C4B418EB21882638801248011A2194AB12499198F5935AA644E4A4D4C465C884E4A844E4AAB114D188AA1D5AB58C2188D88124B514B248CB542C1584E98C9F4C298D97818F81C4821AA ++:80CE00004F8CF48844EF217444B81E568845A28951684C242C9CC4561474816464468454411416048FE1846551C2174A4126B184E224A3282C24061E52988D3843E282B2A1ABA34C614848282584C894AE44BFF34D0664842C48484248424C42844114421402100400901841814110044311D82412582470144241424142015440055440E2 ++:80CE8000044440044414401144011440011440018110088501915048C08653F776245E424F64F41E466D44CF24E625F45A4612EF65F5C6D6CAFDC29ACFEDFD16962F21A9514F4DF5F65E8F8FFD54D5CF44F4CEC64FCCEC45FD353D4F41F13464444F4CFDD4D44FE4F5D2566FEBF5D6D67F58ED29F584C72F23D945F514B24E135AD576F42C ++:80CF000016164F5CBC84CCC54E446F6848F289871F587846F4D8984F45D555F811B15DA53DA64E652F34F3332327286F1AEB5DF9F1712F2AF2BD291F5888F2B92987C825B284F8D8FA87AB2F6F65488FC9F884858F55C1526AB552F442766F66BD54B456F512522F65B116E545F8D44EEF4DF5DC58AF6DF5D6166FC9B99CED35FF7BE88F3A ++:80CF8000CFF4DD5CCFE4FDD6C44B5C4F5DBBB5A1317AF884C46BDCDAB552FD14F44F25FDD2431BD52F45F8C6D22F6FF156D46B8D2F21B982E82CF152C44F4CA84C4B4C4F747CC67486FBC7817FE8FC8F5CCF81B559E444FDF4411F32BCE6FEE5723F37F733C37DE47BD65F59FF77B37FCBB32CF8842DDFC2F98C144FA3FAAE8CCFC8BDFE6E ++:80D00000DBA2BF5EF91498CF48F994ABD3F364665AF4464CAF85F744468FC5F452488F8554228F85F5D4D44F45F5DADAAF8DDD64DD44D9A2F1D4D46F7FFD18D88FC5FD44446F64FC5C5C4B559FD2BA18A17241CEC6DAFD58584B7D8FCFB6D2FD91D34F41F512511F157F17F651D52F15F151512D433F39F984811F58E814FC45413F285C12 ++:80D08000678E8A7F3C7842F39C9C8F8888A8915DA46F32B874FD63722A73A7F7E4C65F4EFFF4747F7EF4AC2C4F48DACCF2BD2DBE246D26C5FCDADE2F3BF2F27287884B894BCD5FD8CC446FC6F55446CFE4F57C5CEF85F548528FA4755AF8185CCF25FDD24AAF85F5D85ECB1D23FD9896EBC99EFE7FCFF4DC5DCF4DF154526FCDFDDC5C8FF9 ++:80D1000099F2AD1C4F81E647E888F8C4DC4FADF558DC8FA7FF7EDECF1DF153D44F35F9D1D33F5DD115FDD5D31F31FDD3811F7CF9D7C51F1CF8C5411F5CF44187772C3F38F48BC73FE8FC86D88F99FDD8455F54FF95212EE63F4CE73FF772611F63FA26E44F56FFF4F75F67FFD63CCF53FAA5255F42F9841CCF62F8A6844F28FFD7BAAF6282 ++:80D18000FF72B88F43EBC2F9C94853B64811840100180080210892818220094440446849000080480800A08480014A0142202428040000200880042A042A04004984288299442002008008880010F8743420A2441810248421044528314412C3841984942484A0CD200142E0810480A1448024031A087041A188A011150100192458112411 ++:80D2000020183142A08800A0182024822402492904844DA4841284494188E18282018E5E63D161F216486CF21249642F917421F2124947222F99F424822F91F424929CF42492944F2269144F22794AF4249293D424B95BD224F94B244D52BF447284F2492443F949B4671B9DA46F19D441F296484CF39249442F99A4822F99B424F8124D2F ++:80D280004B822FD1F424929E4D4F2269D94F2269554F227948F42492BF4CD224F9D9244D929F44C2129F4462289F4422F9492423D949FA92481DB62F89C4A62F89C4142F8924F292484B822FC1B42CF8C2A8146F4231486B1213B626B14592164E6429D14192129F4432829F4432D29F44F29A4219F291484D249E49449E512E2486E24AE9 ++:80D30000F2514B1E841E492742483E36E06229E46238493E9683F62412CB244D128B2418CB242B19CB242F28B14CA214DB24A995253F8815F4925B43C25B4742BC24EAB1B434F812496B922D494B32146187146B1383B426B868F43692C9961689D222F14C288E8643028200280010880200000084000000008800000000800400401408A6 ++:80D380000080088004844001000080081400000080088002440014F022C10060244C41180100402281918424432111642898844A216684200142800118816848445E18001A088A8C24422808212400482C0880081A02822412001160218CB3854124092A8C01208602E0E839E184AB1813329820812244084C893C14818181492242040070 ++:80D40000A554829820120122420024000088836414808381845141127A8838118AB111281128094A4281E141A22446C4824A92A828288028041424848DD28120E49221F27B7180B818C6A8235144206284C09488234598C48D18842644011886E8647168088A092A254802521881284A84418802832584B784054648011A8444216119D6DB ++:80D4800071980892182A92811E843E522A31848E2217842A22F122285B188A28C1216821812325964418118EB923111812011816090000901412504249819284210030428C011001280040029044188260188820029844249AC282004002208804002044028200186044008218861808228C22F2DA3B004608008588A144884A024198D081 ++:80D5000022012100418E12282410028042088304A01181214821936421809121884A0289024D21001024A4222062A12A5229502B10880222A01A112D2484259248861228118868823C39CFC3C2214F2421D1842441018B128C2164231E8824908460294A8118984887448F49222232482241100483C548241C16618343111ED1836C2A21D6 ++:80D580008D228D8510C19A842C8888031886C8824A38144994447246818262841E4947848C64828C8821245882C028A22F8B14A814DF5F8C022A04848C0120A51182442322388244219840840821CB821A828214284288140C4A61841E42111D428C546190418817210085083082152288820432222B481AD11E12D836062B2428A0464800 ++:80D6000088942CD848612283C482812931282C18084ECDF34E9C4127C1124C0494B048C2486818168841224912228548C85848EC4202004C020089411822028393148C11C28B2922F28268A6052671186482203814008388228892444283114108849B21C1898603002D884284C0A84A638A16F867EE80A124200125041642810880830142 ++:80D680008608421341388415482A3A1481182A14C2482748421008142181864434488521158808418421862989A411115E1220088422524D1924A0423E18C022812C0800E0823C1490188922714835431E44100228C428302418226C12E284089048C0414242C82114482E44709812B824743122126219902810042A3184230322190422EF ++:80D700001848129048118E21840088983024421A42A84829082114322004898812B422084142181F210822C440442101488526024001388D12208121820148288248414100C04182141A08528400880040286221221A0229014100C021C08212190344820010A18100B02C04008002E0D219AB2152411004227044B227217A2412828421A4 ++:80D780006B21124AA134CB841C1CF229C2484588742452284994E14C3242190180118C88618C8B29409841814C92128925DA2188C151388C3512881982A8384F1481D381928A2A2C9C183127913A280826344880A8822083A7125FDC841444B822012C1189C12800009893028148008001814CA249264408422A91488815A81815682A1331 ++:80D8000004814190121B2480A2182824A01181102408008A01A126244404380020022146880818831452C8C048DC3C98442AA141125100124084A21428485818122B14D0866113230623012D1442293825284D185D4217293283C8929126E28261218C6121855428602883014624019E644024452534244481129028308A00843012828A0C ++:80D8800021810816A21882382588F87CA59048142210C811C90219419188D04162A1842D211C22A84488818C474488483821450A111528382800112634114242204405A0C16112702241D11222048C681180480210210110622400002B8400E8814AF2428828CAC4F7430210648284122A01902448A041001A48021216044302C042423204 ++:80D9000028C04400424028A41415024B1442898104128188C21C2108A028188248828A85AC49848004481880A1828CA812602218006082A012222FA1840600424440A4240087286088220080041C041A944288121D4C4001B08101C47819020011004968A24E481145415488A24588148162882A82022A124821244152482A0283221828A0 ++:80D980000440028002130182EC3D9140E8110216012651281E21522601144488412C1894884828463811441180A1850000A219810422464441840100603830848444B094A214431938942008002842A20080582848800488423882184248F08E92142848890148800324824420A91110028305008044021284B0120410C8248348863148AE ++:80DA000000220083C98840921811218B9142142821842112211F8159828429022926E82161881A01160D1283B81831822CA44120A1114D2480110410440200808864828281118D113440A281244002241CD8241214518415D45A012199581218412918914221151493445301448AD248044450244045112C62224854141486C129664161BD ++:80DA800012002A01008C0288B048F2ECC7482A0884880020048B5244001082027012081014924882241460C8004624048400263478100A1324A444114E4888604411108614A48443B11402444A4408858812A84C118A183918820022422018022D26630E46412884224104160800893448904C508481144682110114469184A0148816221C ++:80DB0000016012222094828C22420CA0A18428111B61A0C1248618681222278214200489091B1212244400100220A2688844200488FB1F1CA7E28F94A2118B812CB144C1446E1144CB851E14698933A4878C8F81B222911442C3B1238383E124A41C381F82E53888F241188F91F582B19641612D8F1543B514D2499D548B124E18C5DD1CCF ++:80DB8000A4C496FC8B8D46286A8BCDC6373C1F463A228DD437874A54128F2FF8B2483994638787BD4C2B1C2EDA8B121B1A18124389A8918E12684822422A85F148BB639C4486F444688B6484B021A1118B222B8228489B44818F21F114831CF841624E8887211F8AF8482618C526E924BC4C445244D14545541A89F322218D842F14E515AF ++:80DC0000F2584429159A1A2F18B442D49A581CCE34DCF9245563DE15C9144B8C1E944F224294361F5A5144424884B081E28873A188784138281B283628698326A24816B232F4D822122CE622F2EB3584B03111C11D5116F82122811B112E699BCC289F4B745842D234E1617811F812464A65655E43BF2444517B1711EF71BA24B24B74844E ++:80DC800061489F45F46EB4CD488DA137828F22F242873618B211946A82396933EF34A1541C9D1AC9C9312A32148D584F8CF288B15F48E18ACA188B14CF8261974D221C021E214F84F852838F8874CB9942272DA28B418E88FAB898E289FCD2A89EC48E5F0085445148148114811C1244114C114411044121412952841942088421450941E1 ++:80DD000000404902244124412460224426022244244002008412000020410100145012282588528210221402250884CF164CDDDCD5C5F54D5997D5CD4FA7849FB1F443194FF1F55E58DFD4F55DD54F7DFCC6144F71D1A7FBE7775BDDCFCDD1ACF98C46FFC4F57F17EF82F9CB599FB5B57CF72ECECFD6FCFD85DF91FC5E4B3BA5CF1BF5F19E ++:80DD8000755F5FF55D355F92FCDFC95FCDB45AE213BFF5F268ADDF8CF928DD8FEAF9BB33AD3BFF92F999922F39B883F57A6AAFC2D7FDBDDFFCC757FBF7F6DF9FD5E9F766498F96B4F9F5581CEFB3F73A988F91F2222DFFABB992EB2AF912922F69F132488B51678B2FADE94DFBB632E3FC5D3C9F17F378791F97F71D14EF74D598F15B5370 ++:80DE0000DF43F1DEDFCF5DF85D555BFB6F7ABED4FD95975FFBFB75D54F5DFD5C5CCFDFFD474EEFB5F7166FAFB9FCD1D91F97F7723ADFDCF6CBEFDFD8F1CD5BBFB8FDA4A41F1FFFB5BF5FD5F53537DF97F5D9D58FC7A5111F5DFD296BDFDAFC9C6EDF1DFBBBBB9F98FAF5F59F99F9BBBA7F3BFB515B2F66F47623BFF8FB85A77F75A7FF7F65 ++:80DE8000FEFA7B2BEFE7FFC8C8BFBEFEE169CFC1F75A12AFABF31812DFF1F99A9AAFABAB399AF996F62F2DFF58FE8F21BF9AFFECEE4FE1C6193E599F93F7385CDF87F1114A6F95E6A7756BD8E1F55EF9FE5C5F4DF6F1E6677C37646DB3BF7AB5F77DD3DCAEF9824EEF55F65E7FEF25FDDB51BF7DF55F49AF51FE6AECFF5EFC59C9DFF5F5BA ++:80DF0000773F6F33F6736FDFF7F57F3B9FB3FCFF8F97ACE7253CFDD32FCFE4F8FF9ECFF1FFDF9EAF9BF7483CCFF6FABF948F39FFD3F47F2FF67A744FF1FFDBE57F7CF7377227F3EF9DF7386FF7B7AD49BF8CF1187DDF93F7389BBF91FCC88FDBF8FE9AAB193E888F88F15C1AAB53BE928F2BEDCFFFFE1F33F61D34DFD5F37938DFC5F31805 ++:80DF800019AFE4B569F77B6A8752EFE7F5F9FCDFC5ED12FBA6EE3F39FC868E1F7BFB47F72F6D794EFEBB96EFE7F1371AEFF7F5D2DBBDDBBFB7F76B3A7FFEF6EDEFDFDCF5CF4DFF7DFDA7A73F3EFFEEFFFFF5F53A7BBFF5F7CFCFAFA5D522F4F7FBEFF2F4CEFFEFE9FD7F5FFFA3FB8B6FCFCAFEBFBF4F8BF3F3F3CF37FD6A56FFEFFBFFFB9C ++:80E000005F7CF657772F26FE6FFEBFA7F3EF7FBFBAFAE9EB9F99F17D7DBFBDF1A9299F1FFF9F9DAF27FF98988F89F19A9AAFEBADF1CF8DFFD2F82BFD4F6FF7D41D484008002041A88122988008881488220042224A014230414C02860410898224884484048C0448884589499182412082084A0881411B9441421009423049924892000001 ++:80E08000488248A04288223C3CEB8A02288C042006004AA8696284181628022C341A002412246022274422811C84B1A6C4122781914352282788891182518250D2411A4482941844984C82E14482A129A021A0249C11210A941B34B0486118428A84618118128882181214BF8348F1241687844F6231494D129B242CF149242CF169248635 ++:80E10000F2492423F9492423D949B292D441F292C84CF2924B2E242F996C422F997424F412494F42D892B424C9494F2AC9494F227948F1249683F4249693D424B949C2929F46E228F16D2486F2692496F26D2427299D242B491D242F89C524AF9944F49249222F9935242F91F424842D494B929CF424B2946F226B146F223B486F22B948E9 ++:80E18000D426F948282D928FC4D222F1482C2FC83A688D226D41386D698B34167528F6124147242D29CF22D912F424922D494BD29CF4249856F1248383D424B153D2A438414D1A1BA545EA44F3841A9F6422F1492423D94832961D246F88C4346F8956412FC954412F9194142D4D49D99294942D455BD225F8249827144F1239524F8238A4 ++:80E20000434D983B2449F95BA44B823B1443F8492247291F4422D969B294C4269E486CE289F44826967C28A649C7221AD428F8F8D10048000041000041002004001100000082200100001008002200000000004200100100002008002100002100200200005C3E822B4180324841003284843C8846943700102482544848492104E014110B ++:80E28000144828111408D6188424210487381811108819888111022848884A614142002B121C028488403828484220648128C8181648288C714822F2E99744890D210011228849043259218A31A48506001A21022063812800304150481200100A16044098126248431212422418048002B0218C82084E1822421C049215082A85420418FD ++:80E300008004222881116C362B4D424A8132284180E241429448397A64E141DA24E145421818342148C98324A12418821AA681812714109C18100848182A11348612A478841A562829816144418984142146B4212428A21ACA42688182118969B283A442122A440818B01CC228C883C34A281F42432801214210018C082001302182442179 ++:80E3800080014084018410114488014480295424812004911001448200308228008A011220042581A24180040000424C012A2824210400C0FF724412812B411180810482424813E6811201002C0100260822502425049044882230122849441406120060484200448522012002000010280200842028048902882004800240F2322370523F ++:80E40000382413890512130419A4829D1418482544042812184392446B122883016E41228D244400CC84112C22C1281A4C4C0822828361821AFA1213CDA812AE2C183882828A28E383A12823281211982488192481B43813A111C28E28420084EA3482421E885EC753068113C9421C041C844421EC98945426612114442041C214C066261C ++:80E48000B81802C02545424424044B24412921426442274C84840030845698826D114F8118420CAA8188A821802928528122801261818038111248C028002094820089B462CD124B344588011A8101800280213468418082814204208182622442812244209818812A81048341041A82C81828806281A0828B22121220820836C8220010A8 ++:80E50000180482428CA4432284B28A0C20C4882A2224E421C9BEA342A4142842286400480026064222A042353441814684849288814C24A1811044C2488B84200122848400284018249284306C5283388848188122402426292201282C0281881836E488044880260D281243088FBA0F818181A7412698246022008011241154C84A8412FD ++:80E58000A1111400A02480338D42582352254961882126082260428901508425480812484058441219C114A0294A012632883880D88B01128C22081C648188604A1882918D42487C375E1E4100001C042508A078482840882301928042984A4C11415848509481001004460820D1140140083812C0A41A0824280022421048122841440130 ++:80E6000000D048048001001800118A84016EB618D18992188110410A80AC432D1422448782F03444292C03148B44268C8404859449D588634446A2988C9142002A5148178100448D242B21888978140CB082A81280E24122A1484B428C4132284111221F8241084F8CAA118885219488885A242898188D4460B4E324A4419042442D48223B ++:80E68000284602C024A041A021400183B12405A492948D244981024410D98444048962828180022A410884894124A269188441468411882441B812A282121828908880410843A2141242001218284A3892F0A19F809128100C812814000048818121522504250826A842444C14810528CC012185424822821144860228002CD8840143A2A2 ++:80E70000C1844881200222002210880189128814A8188E8800124880014420024EF9937C140884400CCCD448C42E41C57228421A1244188421324C701A6111451811928A0091001008000060818582416861C0428E1268360800412843044034A430288E2841002841200120440888489A0440F826B33800190124285082804204800200E8 ++:80E7800010881244440116A81210224211742604222418288432222484C4448100508800A0888C048C624812CD180089080022288D1800002260882A0481006C3438804488448A440CC04A80342424122A2422241184614481284421889427884C6828462858348AA181831822C882861208008C110418411812448021492408000020C1E5 ++:80E8000082210048608841820000400C8B5BA8004D2444112CC232003200001818412982012800111845112848081008002880830120028425A48281860428208902A018180020018C4808890212220049011A813418B09803321D6A8321A4245242524A61114528247441B458C21136C419001F82852492281A8494244A4321044E14004C ++:80E880001AA44118400818C14400AB218022A4244688482208004C041094181882888022081904B088A4588907400885048084F88FBE800122000020420A2D2200D082028504211601155218A1D0865121150421009024841608108808184062282C8282090044A01262200200430812B01601002E2400822002324088C1C853098418128C ++:80E9000020220112201214C4242832800228002081041A0448222A2122426841871100411812004100104C04843084821A48C8482228100800282A58280000E04822822818082022F2251B48212A148304214148904220018311240489A1141180B14494228D68448EC6301D901213A814534A84823282848421413820A12460814222761A ++:80E980000481108D21021A9828608922128618824888012048A8188504414212C078914AF19858769448469C48871216FA61164887242B4249D1AEB21C83F318244E338F4287D788B164F1214849F21C4E2E18A9C5884C0447817B141A541D45088C9296CCE249E1817188EA83712C64418E88C9F618F88F81AA198383F584842885E8CA96 ++:80EA0000FA48A8382E1443C1382A21922883A8212D6A1281188684AB81B018B9347818D848AC218F11A684DF688B2126F2431447611B1423F23828418F864176452C926749022128482849B224D1C1E481D11566214CD5A2C14725041E18AB42418AE1817B2888B1226161242A42028D28812D22A5C4244D28811880EA4888C1244C49D447 ++:80EA8000882848186C4289F128A8288C88E18BBCC8C1184E644BD28888484A11A821289C366AC722629D386283314223B546127862E682E2E5B12AA211D4A3B324B512341467A1123D6816F5634A1CF24D6715FCC1578DA98FDAF221842AEC82F8323E4CD863A19326B82C58A88D822189A2116D126F47A485276A4AC5E68CDB840845E4F5 ++:80EB000047A7541A61428B212E1883088F8829A882CC3859494AA82168862CF82888848D5822CA21528483F15BBD2440021001190411821110111211121102211002150211008880082C082C082C08880022000000000000100440922410044110044B21100400000040041C35D2AFC1F4585ADFE5F47959EFA4FC1C581F15F45351CF96DC ++:80EB8000F77E3BBFF6F46B4BA5FA181AFFF751BB65F451516FA555AAA7929FB4F55D5BBF14F47F1DE46F61F549CFBFF8FC2C2CCF81FB75F9DEF2BFBBF39B9FDFDBFABC8E4768EFCBF88A9EA5FA8A8A2FA1F118182FEAFAAC8EAFA1F1363EEFE9F9DC84CFC81A24F8A48CC7C289F248481AF33A2EAFE85ACCCF41F32C2C87C8CFCAFB8C8C16 ++:80EC0000DFF56741CF4EF61C14DAFD98984F4BFF98D88CF9C8E91CF4B8FC4F43F37C7C4FDAFABE1FACF55C78AFC7F75F7FEFD5F5597BFF87F55873DF45F67976BFE7D6FEF74B2FBFD2F33B1EE7959D2CEF36F733777F87F3381CFFD1F45F5DBFB5F44D7FDF35F1BF47FFF4F5CEABFFDAFAAF1DDF5BF7EFD2FEADDFF3F11F3F7FE3FAAC8C81 ++:80EC8000ED3CEFC1F11CAEEFAA52AAED388FA3FAAAAEEFA8F31A3EEFE1F31ECC4FC8FBBC9CCB8D5CFAA558CF85F371F88BBCBE2AAFA2F8AE9CCF89A1338F82FA2CACEBB38F99B77BD1C4FC441CCB717EF88BAFEE3883D548FCEC118BB5FAE383F648A4CF5A33D9CF65F65858FF45F15971FF75F55A562F21F41B59FFE4F5DEDEEFAEFC6F8C ++:80ED00004BF557CECF62741D55D52F25F55443CC61823F95F5575DBF95F67F4FEFE6FC4E4EBFF4F56B6F9FFAFA353DDFDFA77FDFD3FB121CFFF3F3B818AF81DBCEF21E1EAFE1F1AAAAAFA37218F82A2A2F2EFCC2D2EFA5F55A5E8BCA8BB84F810145F5CCDC8F83FD68488F83F32828CF88FA28A48B338F82F3AC288FEAEA88FA51714B99E7 ++:80ED80008F4EA6DD4F4CFCB8B8CFCBFF98F88CF9C9CC488F8BAF338F87F7ACA84F1EC65C6F87F7787EDFB7F57ADCCFA5F75A399F65F3584FEFC5FFFEEFBFCEF7422E6D2A8FF352EDED75D9E767F7553AEFD2F31C4EDFF5F15D5AFFB6F74F7BFFE7F55EC7FFB5FEEF2DDF52F33DFFDBF73E2FFF4BF11EBDDF8BFB381A8FCBF13E9C4F29FBF8 ++:80EE00009628AD3EAF83F3383AAFE3FECEA46FEDFBBE7EEF87FAC8B88F4BBD9CC8A45FCAFFFC3DCFCDFFDCB88F8BF2288CAE38CFCBF33C288FC3FA28B8CFC2FBBC7B9FC7F998F84BD78F4DFFF47CCFCFFBFC98878F8F88BFDCF158F88B3F2E6CCFC6FAA932830D0041000089018100160412006041002641742431128C14628230241826B7 ++:80EE800008901822184118901890188AD228E14122644881282008442061820012844088688200888009189088100800F083F290344A0440E284064C36128C52224A82E142028024022A82015E18F04841105844930448415044114088014181218D24C064244922480820982488492254448C210210088041088D4880A483844100281225 ++:80EF00004212481C11DA61F212486CF21249642F9124F6124943F212494B822FD1B464C9494F2249F9249256F5249283F424D297444D929B243CF949243CF1492486F249A4929F443A929DB42B4B1DA42F89C4A42F99C4842F99A4822F9934242F91B424D892B424C9494F2249F9249246F1249283F42492974C4D929B2C4D929F44D224C0 ++:80EF8000F1492447289F4432949F44BA96D449B296D449F292484E242F89C4142F89A4822F89B42CF8126C4B82EF3B47F12614463122667126F244614D128D252CF848251E12CF54A6184E2523ED54B29AD544B283D441F2D24145F49248221F9934A43F99B434B812B4A6D981F4A48215F1B4B246F1849693E42A39694F2AB94DB284F98D ++:80F0000069242D129F4462289FC462291B24C2DF44B28AD449F2834819F28A4945F452492E242D4986F412491E842D492544E8627A41E96269942E928B444D828B424D12CB244D128F84C482C18EE6F302820028400400000000408802000000888001240000000028000000000048408842010000800818C0120000000028400440019F99 ++:80F08000C30F188504120010C11810022289721CD4281804204212180430241C02002042E421C42810821118024AC134182880210C8482102498A880012228C190880080E14805682005D08888818C0222DC38514482222441581A6221418062111604003821288447822021D22411010049825148702832181084029018008002812604DA ++:80F100008901004110244464811A0218230200221098484028E2840811420094444F99028889022391542A4351460022441289568C844341E182C224812143414621823181244B128422B03CB14802411881448322A41149820289348418848668445482852442C4281AA1A2418C2348022898C44220A425A8811C081084129154A34424C5 ++:80F18000410400200116486211228041E4221802008180824104280040042421812128402201202201A0121008000088421800811821820000188C8442084881844AA1482284F0BB918062840000608440088421C0120020018518D42201A44008000040022120528900008A08902C001602202284428842820244480000288364412081EF ++:80F2000004004608422311C85A33981C442A218448A8C28190186C24028D1240042E1286642541588D8441C122814D410089611289311276A825288E4890C220A42483352823611283C512102441021624013014842C83022143C2949244C02248288CB1882145E211E882998860813F66021E442A122824084242A041819018A14421282F ++:80F28000214B11278420358E235124841C040085410884241AC2A8502182800281605100290118280041126022418B122B2241428091841E484B12901442B0481828C511901886885168735A48200140A88284818445821202800112821054484044982850480018281229E1228506428483044842CA618A2189E2818601250421421822EE ++:80F300008480010040922482009022802221012994882A4D0AF0AA9418800160826984C214C42028280961262224C148901620113824821881260C21008C410A2A1158484429081A9118428518A2648BC18821414122188212281A89081842882184184F2288B1828284121868428428888B24289C3F38808142824244880100444480929C ++:80F380004889010080024082CC1416513840A2122141002D546022308423061084952482E084019842100430581032A88D241240266141428B43100412804304428025F17975240080110821248001239118200110A411180019618400000040280141130142828418840080810100812008402C1284040090288C0E1008224244008C8460 ++:80F4000009894204CC3AF11220438211482A13442878846249126361822CC11418893112221158A902128591220030124044C166122C0883A84A84005847231A846188814919841224B92C81012301284884821E288361842F81A6184B42B024112811388826E882E444A121DF83022901404882043012411A4108280000484418608144D9 ++:80F4800048440095180432814951882B118C04814722B01241A8114784102838681E82800C0040B44821628C261408B02428D444038E22004608004212428222A4C38F0226C43844418C23518488188841252892824922119488448908128144811A18389810082024012602898414088148815849325818811823014398888A8408182C74 ++:80F5000001242E481008A012250C10221422989210C22870730B00850418008942928C248488800129982450A4C0382548D284C13200C0288286682882901842808101200520018604222248203A22128460C620B2224294824A884C2492864C4422D42C883424502482001EA2430300002810044128842824418148000042A0121822C096 ++:80F5800084004120012001208104000000004004000000100820043848248440088400810048A04222FF77028C0100218120124204222100180012002504800184881A4248240289010081801818142838181A5828128841882444120018008001204888A21800522A012E19C0384A5245891212C4EBC30E2844891124210120518412856F ++:80F6000004C7214004414A015048811014040060410081481210081824180041C04441430880880184108821B28211A828A0848A822602602112002412800884F0233A1880221124012200242606441A2412A611C1224F2243044418400A85288401400812A9025AE4A10186088440081283A141814A041A488211420200602830680018E9 ++:80F6800018612D64812941A4518031223946028DFF835D84160890880000232888088C08F825880823089224A028210029A8288882829200000000808188088038121A280826A21820890188C08600C0124CC182100482A6322A44A18918A818122AF138AAA08122008480422412C8281A01128C1204182D2285C4120040024C04001088F4 ++:80F700000181A024120089C38489018150882F8268848C8801000000286082480000902800162804188842484112428C3B118543440289036484008400008044184881842401009880056421180048282082A242442229A81821828A049054608844462118228891128009981266822104120092002244184608817EAE388D882E14D0C805 ++:80F780001144F8222487A14125F494122781188236C4424362496FE3B49812D248A21118872118A78148828D944C1348B88821A1212AB11AC14A8B1186381884896881A968888FC1E885F1AE984B4886A289236381008116EC2AA3132866A84C10C8B2876225B8188351888AC3442D18182A388416CA388752E3554186C826897382083A55 ++:80F80000014196B828B224D844F2841266E8C2D12411042249F5468244C1290281C42CA4982A48A69924D082A4412AC448B048038F41A2118381B958E121229114181848474227441E8829A5813A6482702A1C12A6528B2FEA9C1C3E3446C2488F2C7136C21E1E5C2F8662A847252F216483189F5941F812341E284C11E481331C842A6226 ++:80F88000E24F28D888782872185A486D9A2F8AA1944993886722C9E9A5912A87418E34EF21D244EC89982826D88C2898981E488D5848122AA2114AF84822C88B812B488F48018DE64B4CCBC8448B929829A1882B8A2B818E882381B11218B2129CE28B9282CE124323C4164F687434A2843E4A8682E82D62A98F84EE4224C643A2213022E2 ++:80F900001002290280C1244084982288808882488448848802284984020010022528548210221482180223082004001002A11008850485048584D44881542800A08400602480014B14E0F2CA1BD781E5782ED64AF818142D382D18CFA1F116AAEF4BFA84988F49F194981EB665F414826B894DA2ED48EFE4FAECC88FEC7B1CB828BBB8326E ++:80F980002E8F43F32CEA2FAAF8189CCFCBF93C9A8FA9E9A97112DAAAF32822AC731A5ACA8BB3BE126B8227281E8ECD1AAF49F9963C4F6BFB363C8B9A9AC1344F43F6EE9AAB198F89B19AF1189AEF4BF22E2CED36EFA2F88E8CCFC9D88CF53A9AEB3BE7E3ED266F82B848E223FA82866F78E125B441FBB434CF63F266244FE237D3BFD1F115 ++:80FA0000181E8FE3D3E6F21E1E857E28F23A1ACF41F1AEBEAE8827232F29A1194F47F9AE9CEFECFD94147F73F9ECCE8F9BFF4858AFA2D988E389F91A8E8FA1B228FBAAA2AFA8F898BCCFE8FA8A182F89F9121287812F83B732F372728781AD7EAF2BFB12269E9A23719EDCA8F91294CFCBF7B676CFC2F28888827FDBF36C6C8F99F188887E ++:80FA80008FA87818F8BABEEFEA7A2AFA2ABAAFEAFAEE36CFC9F2D8328FC9F8181CE5FE26262F2CF522322B8A6F48F9F3F44AFDBAAEAEA82F36F7242CCEF49C711FF8281AC7C38F6211FE143A87828D2EEF82FBBCB44FAAF99A1CCB19AF69F366844F68318E4F69F337CAEFECF2E6484E2E6D888FCB711CF88C288FC1F434CA2F88FAA29C62 ++:80FB00004FCBF9BC982F89F9921A2F8191388F83F22A1AA7838CF99CB22B9B2F23A8981E94ED1AAF49F3B63CCF63FAD63C4939988E145F437662BA8AE981B33AE3E3BBBA73B6B82AF2328CAF88F886988D7C4FA7FB9A14EFE1F22E3667C7CF4C7ABC7A2AF2421ACF25F662F88B3F7E12AF45E1F23FFA9FF1B138F33A3CE5DAC408AF82F256 ++:80FB80002A2ACFC2F2BABE6FEBF23E2ECFC9F11C9E8FE3F72C3C6FEDE141F93637AFE6F6BD76CFCDFD3E1ECFC8FB3C3CAFC1F13C1ECF4CF2CA828FAAFA9CBCEFC8FA98928FA9B918711AAA773E328F85F71A5A8F8BADBB4F29BB82A889CFE9F8189A2F43FBF8F86F6BF93C1C9E982F28F89E376FA7F71B9A8E888FA3EB83F3BEBA2EBEEDC3 ++:80FC00002E2FA6F28EAADEE68F8BF27674AFA9F91C1EEFE2F26C78EFECFCA6BCED2CEFE4F4FAD83F2EFEFEEAFEC26FF57514F8AA65841604160400008841401842880118412C11240418C01228008182200900124800122028028008184118800188419800C012002800402424011260411002928420C28933091228126081220029322475 ++:80FC8000842444C024002A21815442604140044400C014128908A0424A638142861808401828B124C14888CC028240840120210220044A0228C02441874400418004482A8804AF5349F1263283F4261293D426B149D222F169242D129F446228DF4622F96D2423F929242B491F42F292482E242F99D444F2D24B4B222F997424F412494B46 ++:80FD0000A22D494BB29CF424929CF424924E414F2239484F22B949D424B949C6929F44C6129F4466289F4426F9492423D949B292D441F2D2484CF29249442F9D65422F9D7424F412494F42D892F424944E494F22E994F424924E414F2ABB48F424928B444D928B242CF948648E12CF44E6A83BCD6CF232486CF212616CF2124D642F11F6D2 ++:80FD800024122F1186F9126D2AE8D196C49CF224982F14D214E914E222F951242AFD43242AF941A44D129D34AAF14126B21F4432929F6432921F64F292486CF292694E262FD8E4667112F9641227916E9225FD64922D494F22CD494F8259924DD38D214BD2914BD2B14DC29F44FA24129F4431849F64BA94F449A42B499F44A2491F447ACB ++:80FE0000B4B848F882288F4468C987461E484B8625FC6C82DFE2028800000000000000421028110100002008120020040000200200000000001008110000000000210000000022104408117C0B414200402802903828C03484228412002088048400008C12048042840198800118A041A01418E04821389200808808208102288002812049 ++:80FE8000024028220C8480018400F083AC8059484004804304008100430120914400244301124A01411008002054844248218400401C42084889420820141428B4480824208414084248400842100800814001914C3FCC44D2412241C1281034284048044C13B818241121041006188212128C120A800218B0880424902C8004AB4112814F ++:80FF00008284CE32818148196888488C2428028A0483032D48200281830483080028400414D033041008008021828102281281004004A0486081800410044100102494148021840118004140A4814200400400200121224800800400202204811881101811C87CE308000000120000C11034120041804104214100108402100440440800DD ++:80FF8000840042200400408101A02148A0D21200008420820228840044008289891408F033B9442001002084011298411A81215224220043B124F14212454402250481400420E145840941428C1101562814121424724808124B8818C880881184880528002810688112422688A4188183598820E418018B184E31930C0000000000128127 ++:020000040002F8 ++:80000000124B1216420244184B212F44D124410224440022440058604180041781841A24944290444008908180011A220C4A82A114800200830281428484488504102821183888121FDA0F49010000421A810188452401442800100400451402841004C014C04420180C00008110840242811604924882C01420290800102882A112202297 ++:8000800082081A381889C8C8A01411E0D4347E00CA028C62C420830100209422182021014902448042021200A428004C410400222008A0410018184212000000001882221230288400121100124220014216A814124F220955012418224100381884212221412446088C810100222088019058214008002A2104422140022200C04422B02D ++:8001000084841901901241802882018001001044C8842608002008C02FC30C42820024000022181280012022060000243012000044180083084082A114A081842041124A88410244100412408802000020410C005884128C2124010022BF1D42448142C218AC04281A818361822B1148291104211A263118004128212C01408801221608A5 ++:80018000161428221422A5816021001225E281C11422218E448810042091182222002818188041018CC424182081018248122E9593188124040000000022602212C028004B120028100200C04844004188808102290482811A06100820110418002311040022008184508410041289C948811A04488901186DE80012004140840200004515 ++:8002000012440218441841000018108201403442608400002C04815048528001000052432121010000200C004280018C05001842482012C158130F0044004C242604222E1422002B122043322200480000814C01444220012304244444002025C812588021012008882084A185208401004800004228288B418A0400489A84F11DE6284093 ++:80028000040020021084011820028002812A010040028420010044800420048004004008424218004814400812000048002001420000000010C12A3341448422222444141424158492144218413614120410321280014812298124011212126041000080012400000000481008492C080018A081002828C08800804808841028F29AA500F1 ++:80030000444C0828000000180000002200001A010044004F21412424A41142128B44304820242104426044001A850480840480044812488004481A011884000040082A22C4BD2212800100260480241204412238224160222444104486C18427880000000040444424046021448116049220088244420086C44400802882024210813261A2 ++:800380002AE4810889C51883018C0C8C73C20A414A0400A04422421A04C042242410642252124280820421234822241422141212420221250240022041822188088880085B98008008420012180000009A42280810214808CC37C1128A210186440400000000200141400412184488000000004624012200280000400444100800410012DE ++:80040000440080840200220000880080018814F0B557008084A4421004408444042061A410081901414141A011432824012118304200200422304442102224848C8128058112190400580082481210A24828821800A0118F12044100128D3BA31264491A844214044B244C26D544F414244D1449C4364942E421D264818202004E16602566 ++:80048000AF2C71462624B142341648128123C16221454C8284345847498CB4120156844488A14946A4481385044F4D250480A52400A02711181D683A81C8188B859F859111814AEA187538F8648B381A2864414EC442286AA244A02528002824282544A222CF41544225E2441184781214548860454180D56214B45294448D44414A84847C ++:8005000024E12484F4124441D29AA199928A24A81843A84CCC3D94A04D4A85A4284AA1564A24A4148AA4921AA8848F828C3858188988B84817E951124284712444046A2444044128581AE26431123E12EB31227225E241C1144B113843219112001218124E56298125855142482168812391122C014816B8840420054B11439418008800E4 ++:800580001882200888182A02428F84222301486084228128AF7202420000200200220020022248222C042C8482140441100441108414964861890489048934828D44828D448289841888084A084E8820044A0942208428842884088024088248008024C87F13E649F154444F44E4444414A4464E444F44F454546AB444A4556576265666F2 ++:800600004F42A1446F23F14E48EFC5F542426F66F242524F4495144F44F554464F44D444F1444445F256566F44F15414EB111E184F46726E5ECC6084AFACF98E864FC1E84DF8DE9E8D1C4D94188F81A911884D14CD5C1CA599CFC9D944A4411AA1111AA4C8AAAB998AA4F11F13AB339F99F92848888F8161818F81F118188F88A8A28F8B74 ++:80068000E218F211194CF114544B151A64464149A6464E444F44F554242AE4457454D222F772122D38AB654E759FC5D2E8F11D466F6477327612F414C4476C6F81745E54266D544F45F1165667246D544FE1B154F1582A8FE2762ED6C6346C8DD8CFC9E94CF1CC9CCFE8FD9E144FC1B55CE185F118188B4146F51D8CC7859F81FDD8944FBC ++:8007000049B94481A51D1A21ED22B622AD892B149E111BA9BE299B735AA1333AF1D85CCF87F11888CBA8EAAFB73E8CE3F3545445F444444E64444E446AA446485AB574B574B544F456524F437526F6243E2D126F76572265F654144F41F532224D14984F44E564F54C4E4E464F44A4116F65E544F556542F81D446F47E7CEFE456444E44FB ++:800780008B44AF24D5A6F49656AF84FC4E5E8E944F44FD98D81AE989A9814F59F948CC8F8D0DCFC9F944D4DAADC41AA1544AE426A21D4AAC441F1BA3339F99FDB8D82AF898B89AE545F518188AA8E28F87AF11FFB1C9D44F45F114144B4146B444A4246AE646F444544F45E343E647E465F442366F67F32674EF63F6762E7B333E572F6591 ++:80080000D462F152262F43F45454CE144F81744A9C4E2F44F554466C7546D262F5541687254E364F6374669E6A4784ECB552F1489667254F68F5569CCF49FDD4988B899AB998EDCCFDD5C44F1CE989B448FDD4D44B9D9AA4141A2CA5E22BDA1E42CAE111B911EB9BF779F88F8DFAA8988F8BF9D878CF85D1C8F888888F8CB7F8F331C3A30B ++:8008800001000000200418002110022148801482044880040080014602004A11042004004212002001008004408404004800A04218228901000089018828F05925A0114200A024200400228002281849820124458401001200000018481018140883048904811289841808818A049E98418C04008A04004822800122482A0B88811A2124FD ++:80090000418831488A38EC1D242F83C4246F9144F41249222F9136242F91B624D892B624C9694F22E991F224924E214F22B948F22492BB244D929B242CF949242CF1492486F24924929F4432929F44B392F441242F89E444F2924946F4924966F292494B162F91B464D892B464C9494F2249F9249246F124D283F424D293D424BD49C2D28F ++:800980009F44C2529F44E228F449249AF449242B499F44B292F441242F89E444F2924846F49248622F8934642F81B464F89C361CF4243689D46431294F22314D4D129B262CF16D448E12DB629A312D2B1DDF46B28AB429B293F42524AFB9E542E2B9049E49436A914B8387956B9246F924824E494B931CB424BB48B424B929B426B94D1645 ++:800A0000D449A6119F4426D84926F9492423F54924AB419D2437854CF25259442F9421F25259437A42B934F842496B9227944F23E984F42492484F2291484F22F168484F2299644D928F44C6928D6C84C303820000440000000048C02A400100008008180000000000284004000000120084400100008008184002000000800244001470F9 ++:800A80009B881804002001280000002100104824010000000000100400488130180000001200184142000048008002000000904100008004001D8B230C820000220000200200210000800118C4004004000060844400004841420000000041481820011281000020048004000000406111F03F2190848002A02110240200801442184201D0 ++:800B0000441200E0C10800244301000084424902448301460442001248C01C4854000012A0818001240042000080024400468111C1DE730500000000002002000000001800000000004400008C04000000000000004218004210082800000048114800000000F0FCBF000000000000280000002100400800210000000000000020040000FC ++:800B80000000200800000048000018000000000084005C35432800000020020000002480010000200200000000400200001004008024280200200800240060880000818400220000248084F253272800000080020028000000210000810021000000002400000046040000428A020082200800210046080018000020020010024A423C7182 ++:800C00000000000000000000242001000020020000000000000000000000000000000000008200008184000000008100FFC60E00000019040000120000000000001002004005000000101808008004200100000081608810020000000010080000005C3E14000000210014002200188041140C2480010010080082002100001002009A44F6 ++:800C800002000000200144810000001008400800006081808401BF270F22000080022002000018200200100480020000004800228800008C020000008001188002002004448008484001420010080020C2256326020000312A0400200200182210084084011002000082201422020081002608122448800100802121028182890400008431 ++:800D000042108904814008004822F011A80000000000130220011880410441240000280085024014010080084018028024080000180000448100104204880000000000841280014C1B0D008400000000001008000081000000000081000000000000000000000000000000000000000000008001F06FF400830200000000000000008400ED ++:800D80000000000000000000820000000000000000000000000000000000000000C011C30300000000000000000000000000000000000000000000000000000000200800000000000000000000F0F99B800200000000000000004008000000000000000020080000000000000000800800000000000000000000C0DD31400800000000009E ++:800E0000000000000000000000000000000000000000000000000000000000000000000000009BD90000000000400800000000000000000000000000000021000000000000000000000000000000820000004C34F80000000000000000000084008188000000110040020000000000000000000084004400400800120000000000007F4AD0 ++:800E80000E00000000000000000000000000000000000000000000000000000000000000000000000000000081C051230D00000000000000000000000000000000000000000000000000000000000000000000000000000000BE13000000000000000000000000000000000000000000400800000000000000000000000000000000000009 ++:800F00007C355C0000810000000000200200000000000000000000000000000000000000000000000082000000000000001FCB0800000000000000000000000000000088000000000000000000000000000000000000000000000000C054530A004008000010080000000000848200000019080000000000840000000000001008000040F1 ++:800F80000800000000000000F0A7480000000000000000200200810000000000000021000000210000000000000000100400008220010020080010081C383D00000000000000000000000000000000000000000000000000000000000000000000000000000000E03B010000000000000000220000003081000000130800210000002181D0 ++:8010000000000081000000810041001008822001002008120081C05C6344024058481840028D2840044885082840044800C08180D1884402C0814418400280480440428802448004842840044840088844800484804884012400884418404288028FFD0C000081000084000084000000000000150800000000000000000000000000000064 ++:801080000000000000000000002001EC3F61440000000000000080020000001C080000C0810040024002002484000000840084004008400440440888841800008880014008F0C6BD00000000000000000000000000000000000000000000000000000000000000000000000000000000803B13000000000000000000000000000000000016 ++:801100000000000000000000000000000000000000000000000000E03B012001210010240121200241200400100442000020211402004112000082410000221004420022100442002008200400100410020041002D17930B00000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300001B ++:80118000000000000000000000000000110000000000000000000000000000000000000000000000000012C0C1130300000000000000000000000000000000000000000000000000000000000000000000000000000000BE1300000000000000000000000000000000000000000000000000000000000000000000000000000000803B1396 ++:5B1200000000000000000000000000000040010000000000000000000000000000000000000000000000008001F0C131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_FXS.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_FXS.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/FPGA_FXS.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/FPGA_FXS.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,651 @@ ++# ++# $Id: FPGA_1131.hex 7107 2009-05-18 12:35:20Z dima $ ++# ++:020000040000FA ++:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF4000C8130A006AD6FF4000C8130A006AD6FF4000C8130A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B51111551111551111551111F ++:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200000000001AA1110000000000000000000000002552222552222F21F11211 ++:80010000122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F112121AA111002F21F112122F21F112121AA111002552222552220000000087 ++:800180000025522200001AA1111AA111255222255222000000000025522200005F51F115151F1AFAA1A1000000000000000000000000001AA1111AA11100000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000000004AA4444AA44402 ++:80020000000000004F44F444445F55F555551F11F111114F44F4444400004AA4444AA4440000004AA4442F24F442422F24F44242000000004F48F884846F69F996962F21F11212000000CAACCC2F2DFDD2D22F21F112124F48F884846F61F11616455444CAACCC6F6DFDD6D66F61F116166F61F116164554446F6DFDD6D66F6DFDD6D66FA9 ++:800280006DFDD6D6000000008AA8882F29F992922F21F112120000004F4CFCC4C46F6DFDD6D62F21F112128AA8882F21F11212004F4CFCC4C46F6DFDD6D62F21F112122F21F11212006F6DFDD6D61F1CFCC1C17F7DFDD7D7006F6DFDD6D66F6DFDD6D600000000CAACCC2F2CFCC2C2255222000000CFCCFCCCCCCFCCFCCCCC008F8CFCC8DC ++:80030000C8255222004F4CFCC4C44F4CFCC4C40000004F4CFCC4C44F4CFCC4C44F4CFCC4C400000000CFC4F44C4CCFC4F44C4C000000008F8CFCC8C8AFACFCCACA255222CFCCFCCCCCC55CCCC55CCC4AA444EFE4F44E4EE55EEEC55CCCC55CCCEFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F8CFCE1 ++:80038000C8C8AFACFCCACA255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCACA255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE003C ++:80040000000000CFC8F88C8CCFCBFBBCBC3AA3330000008F8CFCC8C8AFADFDDADA2F21F11212CFC8F88C8CCFC3F33C3CC55CCCCAACCCEFEDFDDEDEEFE1F11E1ECFC1F11C1CC55CCC4F46F664642F27F7727200EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA8889AA9991AA111000000CFCCFCCCCCEFEEFEEEEE2F22F222228AA888C8 ++:800480003AA33300CFCCFCCCCCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE000000004AA4441F14F44141155111000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F3333315511100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F559591F11F111110056 ++:800500000000CFCCFCCCCCFFFEFEEFEF3F32F223238F84F448489F91F119198558884F4CFCC4C4FFFEFEEFEFBFB2F22B2B955999855888FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4CF55FFFC55CCCCAACCCFFFFFFFFFFFFF3F33F3FF55FFFBD ++:80058000C55CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220000008F8CFCC8C8BFBFFFFBFB3F33F333334554444F42F224244554448F8CFCC8C8FFFFFFFFFF7F73F337374554444AA44435533300455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AA222000000CFCCFCCCCCFFFFCD ++:80060000FFFFFF3F33F333334AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333332AA22200FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4CCFC2F22C2CC55CCCCAACCCFFFFFFFFFFFFF3F33F3FCFC2F22C2CC55CCCFFFFFFFFFFFFFFFFFFFF24 ++:80068000FFFFFFFFFF000000004F48F884846F68F886862552220000008F8CFCC8C8BFBFFFFBFB3F33F333334F48F88484255222008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000008AA8882F28F88282255222000000CFCCFCCCCCDFDFFFFDFD1F13F331314F48F88484255222008F8CFCC8C8B7 ++:800700009F9FFFF9F91F13F3313100009F9FFFF9F99F9FFFF9F99F9FFFF9F9000000004F48F884846F68F88686255222000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F884846556664554448F8CFCC8C8FFFFFFFFFF7F73F337374F4FFFF4F4BFB2F22B2B00455444455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F44F444F8 ++:80078000447F74F44747355333000000CFC8F88C8CDFDBFBBDBD1F13F331314F44F444447F71F117174554448F88F88888DFDAFAADAD5F52F22525455444455444DFDAFAADADDFDAFAADADDFDAFAADAD000000004F44F444445F54F44545155111000000CFCCFCCCCCEFEFFFFEFE2F23F332324F44F444441F11F1111100CFCCFCCCCCCF7B ++:80080000CEFEECEC2AA2220000CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444444F47F774743AA333000000CFCCFCCCCCFFFCFCCFCF3553334F44F444441F17F771714AA444CFC8F88C8CCFCCFCCCCC4AA4444AA4444AA444CFCCFCCCCCCFCCFCCCCCCFCCFCCCCC000000004F44F444444F47F774743AA333000000CFCCFCCC3A ++:80088000CCDFDDFDDDDD1F11F111114F44F444441F17F771714AA444CFC8F88C8CCFCDFDDCDC5AA5555AA5554AA444CFCDFDDCDCCFCDFDDCDCCFCDFDDCDC000000000000000000000000000000000000BFB7F77B7BCFC1F11C1C00008001000000000000000000000000004001000000000000000000000000DF8D074800000000000000C8 ++:8009000000000000000000000000000000000080020000000000F01B24000000000000000000000000000000000000000000000000000000000000FFE40F48008001000000000000000000000000004001000000000080020000000000F089A2000000000000000000000000000000000000000000000000000000000000FFE40F28000013 ++:800980001400004840012800484001280000002800480000108204140000484001002148000010F26B52000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE808401800200000010020000100240010021001400000000283E ++:800A00000000808802000088280000F04EFE000048180000001200000000000000200100001400000014000000148002000000002F49054818148002800414182810820416012810A21140012810A2414001002B11484001280048408188022148008828108204F05C65808401800200000010020000100240010021001400000000280086 ++:800A800000808802000088280000F04EFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000002100140000000000000000000000000000000000F088630000800200000010020000000000402201200100000020020000880000008228000070530D000000000000000000000000C2 ++:800B00000000000000000000000000000000000000F04FFE00000000000000000000000000001200000000000000000000000080020000EE32000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000000088000000BE3F000080020000000000008B ++:800B80000000000000000000000000000000000000000000F0D3E80000000000000000000010021001400200180000000000000088000000000000B0130A000000000000100200000000000000000000000028000000000000000000F0FD1C0000000000000000102201000011000000000000000000000000000000008200FF770A0000EF ++:800C0000000000242400420000002800000000000020020000000000000000000000D7E7000000000000240000210000000000000000000000000000000000000000006F9F030000000000240020048001002840010000000000280000000000000000000082003F9C02000000000000000000000000000000112002000000000020080078 ++:800C80000000000028F08171000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000800200000000002002000000F01A8C20021840022602248002000080210100000080210400000000200228800800000000000000D50400000000002800000012120000000036 ++:800D00001200000000200200282008000000000000001FB90822800124602240020000000000000000004200000000002200000000002200000000CF560700220000000040020000000028000000000000000000000000000000000000FBA100A0180000001200000000228004000000002C020000000080010000000000280000F02B67E1 ++:800D80000020090000000000000022002002000000282100000000000000000000000000B05C090028000000120010020000800400000000000000000020010000000000280000D03B0B00000000002820420100000000001800001800000020060000260200202202000000F0FFB3002800002002002222202108120000100218002100D6 ++:800E00008005002120840100000000220000420021E0850700A0210000000000800180810200222902000000000000180048000000000000000042FFEA0F80022A01002800282210212101128002002400400220014A0100002A810148002C0200002200000020F4E5250000000000000000820018000022280000000000240000000000C8 ++:800E8000000000004800009F6A060000200380012120020000800200222022011220812201000000000000000000000000F0F8A500002824001A428202000022001218201202200100000000124848A02122200200000000000000483FC50F0000004002000020820128000000000020020000000000004822000000288002224222F022C0 ++:800F00004120810200240000C022001800000000258202A012400224242C011220820220020000000000000000DF8D0D0000000000000000002001000000004200800280026212000022000000000000008FB80D222A01200222002002001880030000298202000024400200000000000000000000004200F0412900800180012902002869 ++:800F80002100220000A021180000000000000000222800000000000000000087D320010000000000008001008001000000800200301200200100000000000000004001AFC10728A041802282020028002800220000233122242A0188001880410100A042002022820400802202004081241402DF3F053280012602223200222C82023A0101 ++:80100000382021C1121238B0220200002122242823810122322A03208204000000002214424021F4C9C88022222182A231282D22242428000038222880012A6122228001002E22C01260210028284A022A02284228000000220080246412F068A380A1210060220012222012022003002880022C0228181A82818501290120810420012A81 ++:8010800002200200800200002248005F3E0BA01200A012B02201213022008022010012288002001220011A02281828002A01000024000000222002224222708406383A03C0A23AF312322F22931225D2229222001A21230200122A22423222181AA1115A65212B3238283E322B32A0262AA2322AA2333AA3224E422F22120222002AA222F1 ++:80110000002E212A86042AF2376C20A1448044A2112B1118182552222982021A210200401282E12331228A09885A65212B321D311A43B322026AA2226AA6223AA3332AE224F4222221A02280A222A0222AE21242B222A62229E2E20D383A27012CA23329A22316022B222E2229A2111AA1333AA3111A011AB12222C2122F229282005AA42F ++:80118000322A6233211E122F23B32282A4223AA3221AA3332AA2662A028002A022002AA2224AB442A4222A32CFA0213A2621E428A2332D222B231602212E22211AA1112AA3111AA1111AA1112B222AE122F322222B81A0195AA4322A62131AF121222F21B13283A4227AA1333AA333226AA622002820022A02002AB2424482F2ED3F000009 ++:80120000000000000000000000000021000010022110020000220000000000000000D0E70480022002182800800212002800001228800200002800000080021A82010000000000004200F03157A0421B21221B2166B211F262121B212F2691212F2699212B94112B94222F142BF242B1222DB12AC4B12E421CEA22E411E222E519E22265D6 ++:80128000192CA5292CB591C2421B2926B29122B49132421B282394612B8419B24218B14228B24228B24228B242A8424AE822F46456A05219A6421B2166B211E226B111E22611E12619A1B419B242092F142AF342A1D012BA22D412CB521CEA22EC11EA22E51DC2529E212E539E212E521B282E421B692E421B28421B2923B481722292619C ++:801300004A98212BA4112B84222BA4222BA4222BA423B2426A22AF570D208804000000000000000000218001880000400100800400000000000000000025018F5E0B00800200004082010018000020028002000000000000000022008002000020024200F07D55202208400222120000240026220100005210822424848283222117A216DA ++:8013800020021823024A018004000028A0288002194681F2E3DE00C22002001800102202602112000020113222CA01002822192102322002482820010080220280022828282C84428192782002002420020020410220020000224200208484820120152204001221208402480000002008001C04F05238000000282081810200000000009B ++:8014000080020010021810020000180000000000000000200400AFF90A800100000000001880011812210000280000212200002302002004000042008024020000001EDD000000000000001880010000200228000040020000000048000000000028000000F08341001200800218122200000020C11200000040023012220040220212008C ++:8014800000000048002004002004009F5F0A000048000000200214250200000021808324041002102201004022020000002002000000001F5C0400A04100002100A0122021022001002A11021880028008000000620000000000220000264202004FD40E0000002002200100000022200200000000000000800100000000000000884800AB ++:8015000020F48D350000800400210020011621022001001800802402100224000018222400000000000020C8420080F45C79000012008002800100241002288002280022800420080012000080020000000000002200009FA10200000000C022182240021222322006322002002C01000048480018800100000028000000004880F499F1CB ++:80158000000028122302182112808122014818A04124422001001828122848322081A11618222A012001200200000082002400F0E1F280040024004210422251228021922210021A0222214022044280248414820429041002000000000000004800F0C4352021820100A02100000010020000214002004220042800800100222A242222CA ++:8016000022A8282A042088A428200A228002BF8E0C2280022240020021002001002382022820124202242816828201404202240000000000000000004200DFA40842000000001800800180012C812101180018120000000020011200000000000000800400F0C34700002A21014002483842202482012A2524041880840220C112428004C1 ++:801680001A1202A0212212200180022882200882C200828288824FBA02202A0120522222182180D222012122104202000020418202296221241682420224C042200100000000200200002603DF8E0318A042200E00002800280000282C01D02202388088848681021442180048202222A242228A242A08682200A0281388022188DFE9042A ++:801700001A21A8212898223032184220811132222422282216326223022302004E22215AA3457AA7415A8525042682A22212180022AAA82A28488242202C0222481CA8847F780328AAA212222E222942C2222421122D222C622490421E226682A6741228282CB4222291422B427E622F22A42240F2222256A21321282E42A0223A02A0E86E ++:80178000200480028A02601828422E21F075DDA04400125210A214213E122B326A11A2111AA133181AF152122382A1113E1228C0121AA111180025020025A2512B111AB11221042AA62280028880082A88A8A842C8290823B8A90B12002A0142202461241242124622212481028004482800000018281828800200E02401422004422004CE ++:8018000042224222200222F06C9FA054121A81E324FD22222F24A4442F25F412122F25F542422B451E121AA5633E322F24F752522F22D622A4777AF53222212CF112121AA3442F26F642124E622F22F3626227222CF212322F21F332722F27F762722B646AA2622AAEE68A8AACC84AA4A86AA6EEAAA8ECA8EAAE888AFA56EBA0546AA72287 ++:801880002AA7D42F221212F242422B552B11242B645AE521F532722F27F732322F27F7626229B562A7572E3223E228F912127EF227242F267642F241232F2242D322D622F652722F22F332323E322F22B262A6262AA6EAEAAEEE2AAEC84AA4CEA0226AA48A2CBA62A6AAAAF8319AA0453AA6133AC3122F2416A2221E122F25751252222BEC ++:80190000315AF412122F27F332322F27E727F5424223B432A5136E722D222D822F25B522C3424E622F25E136F412322F24F442426E422F23E523F332322B233AA3262AA6226AAAAAEA8EAA8C8AA8CC8AA88A8AAACC2AB8A2A8AA82CFA80E5AA4722AA2371AF16262217AE725F512122F21F152722B551AE121F172322F25F732327E722FA0 ++:8019800026A6263AA7336E622F22F212822F25F5F27227212F26F652527E532F27F571722F21F422422F23E523F332323AA3757AA3622AA28EEAAEAAA8CAA8CC8AA8AA4AA6E48AA8C62B648AA8882DF320022200482448A04180044880448244A2412880020080810200420029012280012200822200000000200420F845440028002220D7 ++:801A000082420222001221903290322200382602002B42522722420048802401200200220000000000200440F1838280B41122B21122B411324219F262121B212B9419F2429213B14229F34291222F142BF242912AE414E922C4A12E4216E12264192E4296C1429AC2421B292CB49142B29122B49136421B682394612B8419B64298412B91 ++:801A8000842AB442A8422B842A94822AA4842E42BFF90E4819A64213011B612392612396214A99212BA419A294222F1429F242B1222F1439224E912CC1A12EC21E812E4296E12264183C64182C34912CB491C4421B29B081061B68211996821B6829B28114A248218A14A248212B484224AFD10A2088040000000000000000000000880094 ++:801B00000040010080040000000080020000001002FFDC03800120022C014824220024008002223880022230124810220400238102803122480080040000002084242804149F24052008602824B081128282A1212582810122241A4202C2201AD2120220042971422284012C011082044800000048004001200414484FAD07A01C00004011 ++:801B800002B0128222622112204282C1222442221642E228024224C042172460210021F012426842480000200200100142244220F43D850000602AD02291A1422820512200002228802308A2281112204422014220A11200000000480080040020044A0800CFDD052200C012001022094022011224002220810200D0220180120220512246 ++:801C0000B0220122A0120000000000008002009F780A0000283011C01228233282003422182C031221001001003012120018A0121200238101202202420024208284064820025F5D082200C02280012721A2100218242A2101A021000011000023E1210200122D1216029032A012002220040000A0428002007FC701000018100160212884 ++:801C800082101201242E1200211228004062210000200128200380018002000024202204200428F0AE2710210100290116120140228A84C18280012422002180012028844A4202400100008A444202280080440240012C0240728701008004002302200132800880020000230182400210020028282302422424002800242024028002409B ++:801D000002004FEA06002022010028A08222800800802122882801001848001242A82028018081020042420000000014622100D0EB434121012021011229023A888288848918A2211222230212008001238824032221221E21228081022B48D02206222400002122C0222800D01C02008042022428140090128200000088820000800424B3 ++:801D8000822C240882240040020080040068420000480000AF240C13018002002C0228201282582122A018240012280021248061210000000010022100002840020000800228F043CE002800000080A112000018212218224A011222422602200400004212888E4220B212A88121210000C0424248429042001072A1031800000000922064 ++:801E0000082081410221002228888602160221AA018221008001002021088004222822000020022448EFEB45410120042880210110021800800110828158220020020000004622040048880025021082022420C442003022F025492002182002002220022800883800238188022048820200008828803112214221120000000000220020A5 ++:801E80000442F04839140048201122012311021890222A0140022400211821001200200240220482000000000021240021280000425F640B004840814201142825011601258102004002480080051220042094422008002728264222280229044E2248422124002110026F2E0C2842001A022D118002112912810160222818002001802123 ++:801F0000022124A028212002241002000000808404A042804201421C04FF710760121A041400181420012128000020810127288880822801400214200180040080CC822CC4422C0429220200000021F027DA141A230422282818C0312AF83221102268213A68221AA11112422A81D322D222E82222A21180829422212420447282324224A7 ++:801F80009828882B88002142A022242B6448C041001C26F44D3B50112AA211421501171118311A51212B921712302324182722212993921AE2222C218CE12151224002A280A665169212880027292C1942D222C6422C044A642448202402224814F01852201201A01323126223322982C122182B111C8183A22824241602928A08212986FD ++:80200000B252A119212C280824589A0C24232234928E42002324D622522229344222212D6221290666D222F4B6C620213211B011241201112A18A1821188800A88808884A248808482044882482848281800002084A2842800000020022234222022F491CF141B311D311AE111E51DF741733B113CF112311F3BBB93E932F212111F29F111 ++:8020800092912B122F23F192122B99F0D282CAA8992F2DAC8C623E124EC22365248AE826BEE24EB262A6458E828E82486AF492A22BFB2BEA2F2CF822622B662F26322227244E622F24F622222B226E626E626A86A2622E62AF6F49F111111F15A71113E135FD53733B1115F212133D133B991BA82F38FA92132F19B9B2F992922F28F1925F ++:80210000921E122B8D2B9CFAED2DBCC2F8E2922F25E424BCD2E92CA8C41F3EB6C24E7342F242422F2CEC2818B262B4D2BE92ACC82F2CF822622F26F662622B6423F442622F26F622222F22F462626E426AB662A6222F22B42442F131312AF61111121B331F22F31211243B311F23F3B2B32F2ABA13F3119227192BBA2F23F332B29AA19901 ++:80218000299412DAED28A9C82AEA2747B212E429F8C2C22F32BA82EA26B672E625B592ED2808222BED2B8923FCE2A22D422F24F442422D2223E424F442422F2236222E621F22B46216A2666E426F4648F111112AF71111F011122F33F31211243F21F3B2B32F31D32252232F317982B132F312122F23FB92129E922B512AA19BCE522BC893 ++:802200002F23FA1212CE422B511E122D822F3EB682F841422F27F642522BD18E82212B462BA12BAB2B8C2F2EDA22E424F442422F247442B222F442622F22D622F422622D422B664AE622E224F4AE1440010000000024001220010012000000800118100220048008002C082440022440824402800400F02CCC20020022100226022280011B ++:80228000218022130220820888220000002022152281010000880048424800244800424842F0A3C4A0421B21221B21621B21272619B262B111B26299212B94112F2429F242B1222F3429F242B1AAE414EB22E414FA22425E212F22E41DF22242DE212CA42D2D421B292CB49152221B2923B491B642B181B64298612B8419B24218B1422870 ++:80230000B24228B2422892822AA4842E42AFC10C2AB41124321122137162922123B681B26231812B341B282F2421F84231822F3423EA1433A22F14A3124EA129E8147A22E215F222825E213CE815D222B881C2421B6929B49112B29106198698612B86112BA4112B84222B84222B84224AB822A48426F2CD380082480000000000000000FB ++:80238000001002180021000014000048000000000028000022200825016F1A0780011C018061211602C03100602360210000A0424200181221202111324228222190522081280200804402204202420022FF590F200850218A4502702122088A0182A0414840222282092130122984C8321A48828AA1819082222341810240220822004034 ++:8024000011028002E214F0195200D26011802941022D218226210B8092421821242228822B25218622B142C192222919C18212290CA8222D42422812888008200240022890222C844281F2BB1500004083442281012112008812184800001820040080012CA1212061221022C11100602200288044420100008A04F0FA93200200000022F9 ++:80248000008028011100A041208832210080040021802801822282002420820200002228482120242244F26CEC8001402123313225622116226231402288A112128A3121221B41002944C2112991E212E8121AA2122048C213204322020080042414008A0229242204F01CFD000014182C8102280011212C8128218101001C0826830412B1 ++:802500002142124220232901002118902221282880040022A02C80048044F232D7A0210020022C4162211223228108408102981B16281A84024042E121840A8A321220028286C231822800000000100328101222A62400CFF903008004002180012002000012800218212CA438808248024210A22400008002304100420048004A420224B4 ++:8025800000427B2F00004842220040218822022082242108800221A01800808401132408000000002842200242000080842404218FEA031280C12100C0320012488200200811004800222411422140012200480028008022280800000000222100709B0912204121240224C01192280020A284128E11202284012229521280882421A4428F ++:80260000A0420080020022AAA4848002000022242C0400425FA60D00800240A2210080840800000020022004E0220424140029084800002800140048286842004820228404F0355200002A012C022724A03460281223D42251214A01422C2812011B4280B622848281220121304212211312A225181011416114143C0411424240220488E1 ++:80268000A0828731001110219141100117289041228280042E811422484848800C121681E411043800142800881D821B84314A7882221C4202824220622C4200482124D74E000020029022008002002815021880011824002821400228122842222422181820010000C043140040020020F44CC1C041280012181C0124C0110028001011A7 ++:802700001202222B481100D02104001C044880440100E014081304144200002220020024F098A6208402004220044AA11242304220A4241214424223C11280422184A82428004A01400100228002282082020048800448428820F8FBD20012A041421800122004181242112028318122222902481200002B421200142410010042200442EC ++:802780002002210000108202F0168D2002002480042018223B418220C281002A21E81418A22423280432125A48918280082908881B18828A05238C28048815024888290448200829082F2F0C20084220120221002C011228802121188221C122002260280018242052224A48420248200122008004000022140014F0AE9280021C043C0237 ++:802800001860148012022C82012302236431203882A012112C29642282282B84344A284141814C02800A008004282800008024140247C420240B80E222E725E122C4119A54212AD321A24116023F11F48291297431D222E118ED265111CA7811E1229242B042F222322924D122F452432E3235C283182F268BA92114AE818651112C944168 ++:802880004691432004481429284A8138E780A428206116231521042B1462422B14272C4AA1664AF311221F11A11C1AAE279AFA2242284AA641DE112B711B121CA436584A18A1C41419B211E818243C61297C4182A4244A6A248682A2442B424E422C3242424A4821E45441B1214241E116E5214111521223E432B812E3392C81992215A39A ++:8029000082E024D8122A1681A4242B42222B141F222AE6292CE13918A22A708301233A82121E438ED1C6826624481426116214882882624848482CA8288F590F1110011984914190418819A4821A8488840A30812048011C0214C0216018A028A028A028800219921219129221211982188108882288C0A22024088F7348A1445E11141D0A ++:8029800041111F14D113F4111135F293511F39F142A23F387C8272827263F2D2D339A1111F1CF493131D911B9D3F38DA33F443433F35F473433F19FCD2432D822F22FAF2D22B7F1F16AFE613EA32FAB2A32F2EEE3AFAE1611F3EFAE3E3EE431D811F1AFAE1C13D833F1CEC2EBAE2AAA2EAFEA2E12A82A42A2CF83BE81417141E51141D4105 ++:802A00001128211F1151232F29F132B23F32FA82B227282D922F22F2F2F22F28B953F5D1512F19F183911F1DF9A1B32F36F643F32F35F573E32F1FFFD24327293F32FAF2F22F2FF7C1736EE26EE22EA22F39FEA2A21F39FAE1E33F2CFEE3631F3ED61118F121213D823F1CEE26B422A282EABEE1EE26B642A42225F2A82BF041411A153190 ++:802A8000114E432B144E423B1546F352C22F27E52EF243E32F25F952522BAE2F24F642C32F24FCC1431F18F9C381CAF8A1B1EEC33F14FC52513F37F2D2633F35FC12132F3FB7D2F522A23F14F7A2222B482F22FA93A12F1ABE82FAE1E33BEC1F1E3EC23F32FA23223F347681F343C16E422F22F2A2222F26FE4242CAB842ACAA82FF354570 ++:802B0000A1441A1331414E432F24F543433F25F542432F25FD73731F3EF6D2522F25ED25B5E3FE62632F2CFD52D33F3EFD82911F1AB991F9A1A1EEE23F35F452523F3FF672F23F17FD12132F3BB372FD62E23F14F1E3223BC22F32FA53912F1AFA92911F1EEE2CFCE3E12F1ED433F8E2A23F14B6C1F463C1CEC22F2272A2B262BE42B4C22E ++:802B8000BCC2EC2A6A28EF8F01000000002021224122011120011A049220880242800242292104421C0114008009880000480000000000BFDA0DA200A0161221482148214880041AA4244814B042024A6228A0424A8221914128001842211012818904488024064248230480248434428028F8BAC8C0511B2126B11162141B212F16912133 ++:802C00002F1691212F16B911F24291112B94222F143B212F142BD212A9421CE922C4A12E4216E122E419E22264192CA4292CB491C2421B29241B2946B291F242131B28273419F2428119F24281112F1428B24228B24228B242A8424AE822F4FDA2C051682E111A4281F222111A7222012F1229C1B1199292E0143B212B34222D112B421C71 ++:802C8000E922C5B12A6C112CE419E22264191CE419C2421B292CB49186B49162249AE234A1284683E23488E2148AF24283224E82224A28B2421AA22448D7C1008004000000000000000000210080080000000080040000000000000000002501FFDF0B8A010000B01224810C4812808136112A140128202408902220820324202101169117 ++:802D0000823012581800200A0000880000A024F04993144AA21A1200258221127212A221A2480086021502111C2908228A120130128822F2323022622B829012282842006834280086E218022826912242688601CF99014AA2140040022B1623A11422627220C12211241470A102481A2A283822B0128282B28137223022625621180262AD ++:802D800048004AA228200290218032212848288611E2F304182818400218402298128200A048181B4210812108801201009800121812248A1222B122218101003428002C2888082400484A42F2B3E60000128002120046020025022C984120A824A0242242221002218009800200122148002220820200001082840228F0BBBD202602220F ++:802E00002C021880B14182224302121928031023890240022A248226C56200212B412522830113280362A0422304004228200800284228A7CB2002A02128211880E11482342224C01213A82142908352A0242242212A342220818401801282812161181800602662280048284002422002F0E917208402002220018082011002883100A8F2 ++:802E800022002002A0242984928224241A0429022480062A8402000000800820026222DF77074001480000211800320018482820020021208823015218901180840180220200288002800A200420040042271B8024012A0422000020220218262228218101422221C88A012888408111011848188200004221230411A02400104202A02424 ++:802F000021281FAD0211001880010020420200000020088084021100008004241022810182122842004A0224002004800800CFC10A1C140118A0124002188032128021B3828483210142002A08A021824816218101484829818801202184042226012C0820344224004A02D09A0320012800000022000000002288808224041E21001800FB ++:802F8000422091128081222208282722488004480000808408A042373800001224180060222400602100241828220020442284220266022C04236428201842110128286200A0848888428008304220F4CBCA80052800001220880260281422B08284828C81621619084022082400A0488622044042A2218240328120682200C08200800485 ++:803000002270E80F000040022C228241020040828322421301181C8118420129028092828220082308250120044800A0848008A0428002001F2D0614802282824623044214686014808484042092132224208228092A2CA241801201008681A88400002028880242602860248A04003F6F072200C212204142820200212422002C213211E4 ++:80308000008046012004212C04000010011C08800219020000288004100214EFBB060000002800200221282200211420048A048810028004219042244221002A01A20000420088802404001002CF9B070018000028008018011188002004289082148028041800C21242188001200229020021004022180288218A0482FF880348228004D8 ++:803100004A1302502220841322218401482400C0222440012522020000282480020046011021068082044800208828B8F50B001C24C2216022481C820428C07121182AE4220118481825021880280200881490822088842828250140012088020086622882821082F468F60020A324C0226024142B2E13322213A244366124124AF4621163 ++:8031800034112581B68298427042819462282031822CE218642B2328D82158329ED1A828204CA1C8284A28A88425022CC8822B868A44A1884FCE0A682828E01382B5318262222C044ADE226128312B422C0212237C72A1321F2318215622112F2A022227222C642429249482B01268181328062B462CB22184222428882AA8CE23AC4A827E ++:803200008E424288485F81041B1440A152247225B2329422182D220037112CA1A16AF5B222283A862721E432E138C821A081222F2DA4242BA4C8DAD822A8442490221A9A218A1121421191222C880448C0C2232404298822F42DFF301110011162114A11A194116A094A28812A81A841A81B41A81A041904481A029A021A021A021A82A87A ++:8032800021002B143042B0420823042304212220022242A2424F42462161141E111F11F511523F35F553513F14B311F731F13F3CFC82823F19DD33FCD1832F2EBCF2ACC61F39F8C2423F3DA444CAFC62611F1EF641111D412F23F392922F287882F273F22F2DAD846AA65F2BB1242F22F21252CED2481F34F462621F36BE61EE26FEE2C201 ++:803300004E428AEE26F6C2C24AEC2AAAAA8A28A2286E622E681417113E71141D411F24F232322B551F14B151C1C2DED21F34B652D311FC91C327222F25E426FC93833F3EF6D3612B43DAACFB4AACC41F11F522822F25F572722F29F343C32F2FFFF2F32F27EF2EAC751E122F2BFFE2E2EEF24EC23F36F662221F36FE41832F2EFEC2A2CEAC ++:80338000424AEC2EB6E2AEEACEC2AAEA2AAA422CE226F649D1D01185B411B111E331E323F352123F21F61221EAF242822F25D533F2C3133F35E926E727E72CF553916EF23F15B7A2AD54AEF11F16DE13F841412E622F23E327F782623CEC2DED2FFF62E24EE22F29FD32B225B212F1F3F13E223F16A6263F1EF6E1232BEECABAC2EC28BC5B ++:8034000062A6EECAACCCEAA6AA2B48EAACECCFA14EA1543A93211B351E337E723D433F21F61221FAD333FE91B325F2C2133F31FDA2B22F21E52EF553D33F36BF52F7B1911F15F5A1B11F347C41F14141BE522722EEE22F28F632F3CEC21F2CFCC2C2DEB22F28F422A21F2DA9483F1FAF411F3696223F1C7681E12EBE82B842EC24BC42A406 ++:80348000CCCAACEE8AA8882B486AEC2CFE24582002002200602200001220C1221A0413813211001002214A024A029082422908002E81E01201002008000082A0482028044FEB02A02180024082822101282C21412101322100322082182205124890525A4282C25228981A022822000000822042A2424622222402A6F193DDC0411B21144C ++:803500001B2166B111724291212F1491212F1699212F1439112B94322F142BF3429113D312AB431CEB22C4812E421E212E429E212E429E212CA4292CB491C2431B29241B2946B291F242121B28272419F2428219F24282112F2428B24228B24228B242A8424AE822F429ED60121A46A1216E11F04211282F1481F26291282F14BB11B24212 ++:8035800028F342A113D31238111CBA12C4A11D52B81F22AC212AE419C2429E213CE419C2421B293CB411C6421B214692214E121B2866036E8319E2249A214E822242222B84222B842332422AE4C3060048000000000000000000100200880000000000480000000000280000000021F0891F80220218200200821222202801112C8104217B ++:80360000800880148202221032D22C88216113009011882A6822201C61280020840628A02420F66C64000000252281214242C252901229D42224021B1222C20042112828800213A5C1204621022958214A085200822002144800824642220C1470670420061224268221012C882132222C894512612178288E4220A84111C6022880D22136 ++:80368000B1819552241CA1211B25002344218C88122268122225210442E2422662282A04227FF20D220000002002241A44022448284001210000222880024220A8C2009082118812182820280488000040024200482FD70D2240012603272200100221001134121C020014801202000000001021020088004002148008244002002822DF82 ++:8037000096064200221011210100258191131B496A21022CE4241181A12126812492221818E021C212301223012948838811C21226022220120290828200222004F01A2580048052211413321200218091121B184A81826124422100224E22282081012CC212001220088224A01828200200408208211002482228EFD808224001281002AA ++:8037800000241121144219420326814121611311002302001240622140126112211800212100291203888008200200F086930000C88021011180412211128209C013200148008A41024812114211A014584A08002400800400200280040010023E8100004800000000222004000000382591428A0100420013181201421A02800110016015 ++:80380000220022100200201482F4CAB800001C080028281810110112000000000000220012800500210000408202000000000000005FBD0E00100118206212181834128025087011021280430200003011488A1592411A84280240028022042800002148008004B069058200008001000034102201000020142104302242580000122480C1 ++:803880000120015012001002000000008074430414001122C021281062220020043828001A040080242188220412800148200100142400282004000080848804F0EBC700281302804242018682C421C0211CB12101001100302118226026002082042137221220A4420040028042020000100200483FC506820028243022108202001800BD ++:8039000029042002381821422400420024184246020023040000000048682008820000F07F3E0011000000100130122092122420818128044682810112C082204102C0810080C81234821140010020880200218240F2D6AB1001224A02002128284214214200232102226222A01421C0128021D122016011200100000021008800000000A1 ++:80398000005012DFF50F281912011C82921200C023280020A242000080212222A2822E822221004A012180611110C112000000004820280821218084F4D5F614428004202144C141422011512219046011280046316240E22408000000681242212C024842C2AA2404C221484002400288424800EFCA0A200814140010621414800118218E ++:803A00001082038A2121028001290100142400000000008888800211220000288008885FA5038A02481848398421820221121C84030024208102230462A0820029418108884218C0C14081448244011120880682008A06C29042F05D821071818102B01104112A622E112562114E1117161361212812282AAA244622354282182C1932425D ++:803A800025B121A111124212212C3842CA842498622D81302188881110024082944240015FB3042A264A21D7117222F252122B221542F142233601121E1229B262511229B211A154483A81A6625AE723B242E222A4111240B2428BB4E225014815A1141724C6724102004A24A4628A8888B842A88280A84442EE9714142813D21162262816 ++:803B00002E21342394612A94313B142129E42281A6122A2122E91381762142622221B21A6228241AB842D42174125231181F1103221652128820E814B82242822404A2A02825A28CCA44E228F42173200400481C0980848844A248144001344001144001000082A028A028B081021B28B081429221100182211002212A148244022008AB69 ++:803B80008D141F1AF6212115E113F121E12F23F252511D2121272E2B2A1F1EFF93922F25B452E537F773711F16F633111CF391D11F17F731112F13E216A6662F23F332322F2B3B121F11E921FBB2B22F3FF7A3F31BEC1BBBBE333F3AFE83A23B33EEA3373C1F2C9C812F34F682A2237443F342422F26B662E62EFC82A22F26B6828CA444E8 ++:803C00004EC2CF250E1F12F661611F12F231511F32F622A22F34D433F22321272E2B2A1F3FFFB3B11F34F553717E733F17A7553AE111F3B1F32B557AF562612E632BF63E322F23F3F2F22BDD1F31D922FBB2B23F3DF552515E611F1BFF91122D432D233F1BFF61222F3CE43CDC11B843A6A8CA7A43B342A6CCCAEC2EFC82A22F26B682B88A ++:803C8000C2A44C2F24FC98C4141F14944115F131111F3C7413B373752153332F26F862C23F35F513332F25B552F513322F15B532B332B191EB19B932A31319B141A6C41E122F21A155DEC23F11E13BE128E221DD32F162419E723F21591226F312323F2CF8E2A1CEC319F8C2C1AAEA247241B14204242B8A4AF262622121E024F813A31407 ++:803D00001F1E54111F12F271111F367413F373723F32F263632F26FC42C33F35F553711F25F573523D122F35F513132B131BB9BEF13F15E523F4414235B252E621B112A2DD5E523F31B1A2A1381F27FF52523BCF1F28F332B323F4A1823F2D7F42A1EE1F2CDC11F8C3C22BAACE8215F1624223E82ABAA2A8AC2B662BCCCAEC28C882DF91DD ++:803D800004000034200234400320010048202824010000002190129012420018100280840800008004000000D0810E00000021003042403211421022018288000021008004002C01000021100221002800000000214840F1D11880B41122B21122B491324219B26291212F2499612B94112F1439212F1439212F143B212DB11B421CFB21A9 ++:803E0000421CE82264152E4296E12264192CA4292CB491C2431B29341B2946B391F242111B28271419F2428119B24218B14228B24228F242822229A842882E425FB20F26A1412611A112704291612A11B12229E11483E61439112F141BE1143B111C9B431CDB21C1B1881E212CE119F2215292348E212CB191C2511B69341B29341B284E81 ++:803E8000111B2825932125B381D2220A2F3428FA428222252288BA22344222BF83052008000000000028000000000018800800001400000000000000800200000000F0BF9B00120080460480A12883C411203112618200120080420250422C22111202212C0122201488C24800801481440420D18486016046285F2A0D7182442C581460B9 ++:803F000021284CC1221824482444130428815048A6911422234428024A0180E58106184218008001242001148289E82188CA848400804989F4347340A11C410042442382A121298AB4414182335261220047211CC21422218E18219016241237215A0220B44281024884288C0418002621C8168A2228614640A21826AC24ED8E10068058E9 ++:803F800016281810041884214014018281102808A0248002422280144822810100200110029041888C840844848112004270D202001800004002218A9212C012122902290914D018424214021850241AD224082A092911212201A0821A02842001120000200200F07D8E901211103812AC21123212C8962201A5028CD44101112E128D1480 ++:804000002008425028701CA22190222C1734224B2C2B212181299221274180A8246022A04841227018220246248682F25F122418140090182860214A28B812181202524711241C08147028418214421862C143C1228A223294F082242B21211228349E2422904800214004402202432402F05E450080418A4102250290122218842D128127 ++:804080002902181A72160888400420012392124123752222A2411428A42002188822A021A0492002830128802422F2111E004094D8004C11C4488525C82884818951480090188001A522A418450243017018644D144189341487418941B48802816047441608412A11082A4144642C3E444189F17C6500219148464805A140024A71220206 ++:8041000030222022015084831442A21800821A240840018142102244B4188212049E44608860822200A061250280F138DA00008221A10022006011404432541230248820C14443422C845222200126824142220200003022000010821124840184C018221FF8040011872183541250868C462D28721A12C81443321220D14801C93118856F ++:80418000746252484924B284019889418601212D34165C8242CCAA2122233254C88391884582A112A034436163825A22019F170A24100C409C140050421E4C145028844624032288208444045022905210A42D4084042011048184412818001048480480344841856482CF320B288128901290421008290684A424841004242A11084008C2 ++:80420000260236086D12002441004148230820216481C048828449412808440000214FE20C40C21444428118A14A4188012584824192141084011800430284812001262421022220282204442222002A2124012863B16431429022184B21124F38064724422827248128269824412884810040E482448A01224068C28427214425048100EB ++:80428000444100448D2645084140648216EC8148C9114C61884508A02141891826B824F4FC72004C429828404401222544812A152C26022B82422E48A0124002478215284A280A8618A229A02C1282608840018604450181140022908484411E48008731209A281606504A41441818438202618425182482528230244C02822228269424A7 ++:8043000026E861C22824C08400409224200200800144000040A42429C442141B17401802288C032381022C028008142A01182321420842222184310021844100241048128414081248004883014449812482840130224CF4763C3042104A044002406821100121411309002088182846810813840590141D4842840040084400428A044BAC ++:804380008483C482506848C0421810044F99490218800518414002ACD82888011240BA8C810A002800004292888B2888A2612332828614284A942481A22082210200280028284228006F3608C41448845CA62428248D2512484614881224912200421618F84212482C914149480A0024148A21C4481E212A44481128427498C184C084C06D ++:80440000A18F12011888828C4118B412A4A1BBC910749C28711AD4843134E422CD31672291211F8148E662441A78949252872428878147842122155549C35818812D14442CF211864A82721C84D24C364A49B228A2214E15C9B281F8482113795898A4E3226D424F45782CB88C312A144B342F83074E422B6227C245F258418D2C5B234422 ++:804480002E4A89C11A2E2A85149C12C9D1B4E182A3211283B1248293282D882E22212B224B413A96288DAA6391462D4221C0848414851C55448D48184E1C1A911445F11819444CB142A2225246F24444DE14447FFD47F2222415D22CE386B622D22294526D2827411E286BE78BC829558293F132242F43DE4AE842F822682E18982AECE204 ++:80450000D468F61A484FB2C24EAE3A8E9847AB63EA48E18A7384A4CE1B38C7AA272A4FC80E44AAA1AAD62CE18AF448C81F486148AC332C9E428AC4162F82A6114F22B6B2F49D4520841181B1818411411201190413088400A048852401100842009880082A082A082A598129180111881321A248148220088C5442822D248002815F93456C ++:80458000F2F43677F2C57E2EFF1C4DDF9AD2C4F224296D25DFDAFA28689F99F11B1BEFE1F113194D2E3F98D8E8F93232EFE1D34EF188B84F42F22626EFCAD8DEF16D65ED8C5FF3729EFE222AA7C865F4E84C4DC46F447425FD981C4FD2F6EC6D5F547428FC3425CFDDF45C5CD7999F927281F55D51DFA8F32E2C4F26F67E2AEF8FF64C4E95 ++:80460000AF84F51C18CD5CCFC6F6BA16246F67D377F42E3AE7F2EFFA742FD9D553D4AD2FBFD8F82F6D1E1AAFE3F31F1D8F81D3C4F2A7A58F41B132F71C7CCFE2F38E9CCFCFFB4E5CCF4EFC899D9FD6D6ECFA33236F45F42828C7F245F64C4FED4E6F44F4454D4F43D17EF66A6DDFD6F62D2D4F53F23C1DDFD474C8FC69691F1AF25555DF76 ++:80468000C9F33C3E65F438288F8FF6584AAF85774EFC1C7CCFC2F23E9F246F66F61656F7F1EFE3F15F4CCFC7FB15256F42F2173ECF6BFB797F8F8DD9AA5A2E3FB1F1163E3F39F914B6EFAFFB5A3AAF81F18A984F42B224F3AC8ADDADDFD656CCDF7A7A96F6AEAEEFD9F3B6B4CFCFF7A4AC8AF2B4F45FDBF3A4ACDFCE56C4DFD2F2B4A4DF88 ++:80470000CDF76CEC9FDBFE28E8CAFE55D15FF9F92E2CCFC7B774FBD4F2EFC2F26858EFC3F324544F46FFEF59246F2EF61612FF73F33E1E7F67F5771F6F615366FFE1F39F8DAFE7F7F89AFFB85ABFAF83F11E287F3BFB9494EFAFFF5A7AAF83F38E9C4F6FFB4C48CF8EFC5DCDDFD6768CFEB7A76F4DFEAEACEFEBFBB6B6FFECFFA6EE2BEEC1 ++:80478000CF4BFF9DB7EF6CFAEFECDFD2F22C2C4F4BFAF9F85FD6EE8EFE61F91F19FB55D5DFDBF93C3EEFE7F776F44F6FFF7E6C4FC7F7343C4F43F724A46F210918004042080084400840024058280000004014120810060041008421480041001648A141141608001A1408007FF30818442D12C4184C8441D42C01189A141A9412C0144319 ++:8048000019829412844C414A1414582480092E82122A48A48216B42408C90822442A68882AA1282048742488318481418D24478128471ABF7D082CF4112487221FC132681F41366A1D6CAB161D64AB9419B64A9945AB944B42AF14BB24F44A914F83D412FB24488D914FA2C4A14FA264114FA264192E5A96C54A9E24ACF491242CF4912460 ++:804880008D121FC9324A1F49324A1F48B24AF18124AB941B28AF143985AF2439A4AF2439B42F6479A4D842F9A4484AF9A44AEF7C0A2E421E448732167C686141A71216FC281186F46A1544ADB14B212D915398BA41AF142BD152FA86488D314FA8C1B159A82555AA284D1A8E213CF59825841FC942F281648D131FC9726A71917442F181D6 ++:804900002CA5D141D25AC9242F141BB54A3924297114D8427924F842144782AB144FA2F1ACE9402A0800820000400428000000000000880000000000480000000000280000000021F0B97F8031232E18442D594861501246C84182844825A1218182CC45480800684427228711212A882146A682183AE823C88C1249082E881644283838AC ++:804980008A91118221A8836888182128484A62886E7E0082112B188093184E24422B81122925A181D0A184934A282A8424028486044904850625222821810214224782A422248099244042224148241224C24423348416014D6720216C818634587283B1247442E28C91148889E128C1218712239288363868468202126A7884E2443218D4 ++:804A0000252E0819CA12388B211AE226982C1A420484128E1849DA84A38127132C19882ADA482832422B42A0432F81F83EBF4092212623511210061460341A0448A0418D124846048100844400316022122944840888138148DC2888E22248040040021014081841B08404F0FEB5002800E50143528143028100102241048502384180042E ++:804A800000184424121800C012284100000012810012442A0443110A83241148F27993902419912428A012A02416D22409844018B421941230142C4634211E292A3844B046B222842222064827215880E122816B21361826431238822B12154208844428B094222304D0170F4962122828812A816286381042088502132501C16843332402 ++:804B0000226249046148498222064825820429C23428902A25840312A4221489012A04431328E881824148F26BAD0012412415044411648E1481004064224160211012711821082096320029810118181818249812180024A482181042444804214C238404F0F8D440220248184058123E4C4421C1427048823814248210420C8249DA41FF ++:804B8000B114C288902229B214962B27C8481B1423488C488801842160481A2201434482285448708822A41489F2F778201154848B688C144CC43C25114892348713444C614242404334C46841834148088860818D818148144400304412224800814C41B94298248121400A958454244C42F47E38242280318347122122001A42082410E0 ++:804C0000018241A01280A8144429048128814200200122808A0282844180024290421283D484C41418140080F4C766A0216932142D28CF1512166891DCF41824818C63A4414E142B821A44748262414C8C2204231AED829128243A342B47A48F22149C441C1262C2494AA81A8354A480A2811C33124964C48D42C6D824D14851488A14246A ++:804C80007548F4F4D730821018018447224CB2220125021C018511C484402112F286482D144788874440048184822A0198848C25880818000084C0484E82282C01448C041088C424223FA907222889226464284042583484248C1448444261224460187024021185A2213214482611029421001022848444121121648110B816080000411D ++:804D00002008DBFD1420014490411140012881808288A884808808100220C24A00848283AA21128E411180042140E21804421448884E34201498488C18D2820858F053A1200C32101894222922C228482888216F84424408004C6244246220444302901800182004100118A49041508146C24880044A082905521242F0E959604245429263 ++:804D80002800425446040000302844C16668C2608A82848444B0984428428604464152410082A110A21412448885353181818594120084D048449848DBD6001841284012CC2181281C426848A47034312110212214688413A22483A22489049D4242C98408421041142254828354C190424A5112E0114498461002488004483FC80A30243F ++:804E000048236442269541811240088410088041140440140444812006200142000046014800411800001A02A04145781202814481FF8B0D10120881A1001125814402824A38821A2488C988D042234208C084C01429A31A8849044719884190844508008C480212184161181E44C49885140840F25568008200809824412845189122415A ++:804E8000211214C35242A1D09487B51884F4214448186C42241108002448848001350A84424450224A024225420223242494141C014F820F4568144C44AC2C84304A21250246048A02A724828B2D282008330818169284E02412314112564116C88880048844E02128C181864854A4282051481A08141288A748F0F8BD0013DD2412D2A84A ++:804F0000EC587226521A2E4144148C12D48258C649681C4B83C352888F42D4C8BB8814C8694CF23332872827848F25721923AB52498434814042D28AD48214E8A4F581154F147183F15A1B9378492A384EC33442828F34F1584489C1D1F0AB43D044E24A72185C8445F42B4A1561628D2857229126F2888424587CF327482CD3D2025B2C1A ++:804F8000324F169A264654844E445E381F6154914BF48FC421315825425481F08381884686541B1093C8198402EB121E149E1487814FA199422B1816785849FAF4351466D22421F268646A12F448645D683D16AD292FA696482D4A83F8E882BF8AD468FB884C8AFDA4A43CB944C41E6E4913F26852C5B826B424B222658A296C4C1D139F23 ++:805000005DF842C14444566464997142EA49B85AE448E4A4012FE7F514545E4E2CD4A2F48452AB444548F8C44447488B442F6F0A10028004480080044084049A04122482200810088011988210044110449884100424008200248400448244008228BFF44AF111376D26B57F2644FC642CCD657F52F215354FC2D28EF4A8AA85FE8A8AAF6A ++:8050800089FD85A42BD94F69F8951FEFA8FA56D2CFCFF9C5D9FFD2F26541CFE8127464147469AA894FCCFA84E447414F1DFD8685555DECDFD9F18CCCD5D528F48E86AF81A455CF8854118B11BF95F518185A7418721E7686F6424765FE5C1C8F89F1682A9F1A49F115154FE3F73B3F67C28D244E26ED6C55F51333C5F42A4C8F2AF8282EFD ++:80510000AD86AFE9BF84FAA6E84F6AFAA5AFEFA8FAF2F2EFCAF9555DFFD1F165414F4CFB747EEFE7FB447617161F1DFDCCB59AFB5457FF85FD85851F9454EC9F99F58ECC9F149448EF7CFD9E9D5E53AFC9A5548F42F54B513AA3448B45A721EF68F15256EFE4745EFCD858AFA7F36D111445F41456B57F22FA424E67C4AF44F666266F4135 ++:80518000F32C26AFC4F4EAAAAFA8FA8E8AEF8DED2CFADAD8EFEFFA9791CBA85F9DFD96BC5F54F76D354B46DDAFDF51717D7727F14B29BF29FBDEBD9A7F14E4EDFDC6841D4145F691934FE85477AD4A6FF8F98E9C1F15FD88C7A1AD2A3F15F5181A5E42AB455AFC94867F24F41E1CEFC5F994988FA4F1B2CF144F62F23E36BFF27226FE6ED8 ++:805200006E6FC6F24E6E67447F61536DAF86F4EA8AEFA8FA8E8ECFEFFD44AEEFCFFFFE8E7FDBF98CAC1FDFFFA6BC5FFFDFCCF16C48DFF1FA777FFFFFF17F5DBFB7F3F3FBEFCDF3D4F45F65F5D2DE6F48D85D54645F7DF98A4ADF74944A5F5CFD8C9D1F35FD93D3AFA5F51E3A7F15F5385AEFA4F55A184FC5F894D66F25F55C5CEFC5F9D8F0 ++:80528000DA8FA4F1563E000084254248421804348400508124844C1241048912514800218131890200501200400240581412348460814484641E48200100F07B46601A124038261914841448344240628846024A088908892808410081182820882184011C0820180A2091828604C013001220081221C094F0748BC0421F417228F21124F2 ++:8053000083F49164A3D641B66AD141B66A9961AB9459B44AB9A4F44AB14B422F14F9A4482DB14F8AC4914FA2D418FA244A5E214FA274D8F1244AD6E5A2FC9824ACF491242CF4912485F291248F14F89164AF24F18164AB141F48B24AB981F64A9253B84A79A4B84A39A42B94478A2B944F8AA4944FAAF4B1F9C01A1B61E732174183F4114F ++:8053800024A37611742A5141AF463981A9B311F24A8443F94AB553D2227894E8147AB3A8944D1A8F14DAA1A82517A283FC241AD6F1248B87594DCA1FCCD2A4E149D634F4912CCD938E64ED1319D62AD1C1D668D941D62A9364AD134F82B44A31242D944B422F4431262B944F22B1560B8440010000004004280000001018024410010000AB ++:805400001C040080040000000080020000200414F0DA2500148411124916C45127514280482844B3255828AC0219120418191218054501432462416145182281611861402262211E41A22D829041008A8428914424C184001FB24C41A52816312887281032248392A466F8411211448961241448436184114F822C146428B041C128B1850A ++:80548000126D8448682CE912143234221D1214C0418841A0482D121CC84B8416242881045342016FCD4651411B24818561892B24441F44D185B2C492241C581A43C4312F42181B381289422226E14122684813415381853423160247148F21A841121F68C3641023C2112B1C2C9884213F2164189D228924011E4450A2154421B1570B00AC ++:805500001C8102442128290183A44100811944A242441944758428141118237424084885D4846444260A2603001C012148144C028A042024C884928044648200AC0F0045012112222062881882140022291304480010141804C024209144120024A0124001242004001448402804002011F884484FFB0329C31322281A228221331D531159 ++:805580004288F11841218B41C078437328024C01802274226481122E416356228CC2142A9114182441C413911290148341E88681D822C9852A514A1A084AB1380444F07BBA24381431A02118281283822181C8118511A212E081E24221040020022342B824A12421422E1818224502001124109214816081112532848C61848A01188C0427 ++:80560000444CF45A7A00184C22128222217211D41C18120852C0482B124904891232141044C844411210F16412412144181818386145C811188084112886A85811222504202483419888EFA1052422F02844204218441834114322124864419011121604441504238201004200144312844402AB2444182820A8424C4842B8548254221299 ++:80568000468C8A476848439612DFFD490211A5848441582480045084842D842822406C58282581111888843118CC2C02C0861B6127811D48472A504846410A4C144211483C1288288D14608440480620D12AF1112E800200C400844302202101160840421208221228419025004414120012000028221200414001112019240190942284F9 ++:80570000F0A66E2092228181163C2844C14D6820C1188C918485342450341887423128D9712882024F81D248242214E12188453C5522248127928722181E6440F1284483D8224138158F6461298B41CCE188C2468E1C4CEA444372490D2111614C025028004414282484181260817C280163110246041400411084B222014DCA10044128E9 ++:805780002480081081880440840432008184AFF80280441288843218441A446444814604134281041098248381110881131308814860811412A029864844082D1841846088408C41282201200412008FB60C1944311141272384191251A4288942C4224184004C152CA24822852382B12451486044302116480430214420343188882C288F ++:805800000180841942821404100420027F4B0410362C288148422800804648218124A1432384042711C0144001184E14221800D14C0400181212004084E1180486E418C41244929830848488C19F740310884501144902004005601414811482163554414B24A05829241444813C642B4226A8122231D021C1CA1144881C04A4414470415D ++:80588000EA221184784412C44A8C418412F241F22417482414810000002260828089911421282118226044450100184081010000410029290144110000180000C042834418B8F307180013049011181902902141818145082812002100806241004C074011088282200144502420314200291324044121100221247F6405108164221301AB ++:805900001012A828D082181135448602440017882038828C28810210084B488048C42445A2284C08242687A81A252421A34844828322132218024C5142412FB60D41418C92444110180454110000401C01644024012848C0441400810020440800401103001828482818290481448901C9014F6E4AC21A2448211C5441B01182018C444427 ++:8059800011088482A04A1A028221A21880381250424C71216452274283C21CC0474042C844844C38128444122829049042248C120421F02B64D013F183463F63E142F614131374217C21149D81662DF62421118B8142AFC1F144648147459A531426B2A4A9286A821214E48CC2214F4746B82EC2424F4AE3E87814B116C4112CD914523379 ++:805A000043B8147118E4116844AF1598A6872243B1447C881254644CF4882284F77D20551481D374420887112F11E2214214D8895848855195C598442D12AA991A2D48AB1ACB518D441C1CB811B518F54155A3F364568CB1287291FC24241C04CC6864163A163FE57944CC3C85F482184AE5A881F451482D5462186B81622B1147812E14DB ++:805A8000C5F24C65244516C82925BB2164D27849C1584B22682D211D4A45AC741D918817134E642E214F74E84192812952A41E55C7422524D144341193D844419118114B121F28B2883921862CA8882F21582342283AD864E12AA1252F685162D0EAF4884889518444AF7C4D211122011A1402219082482908298854128C44C14814844213 ++:805B00008442A4402A442A482248225924130511E1191288168C168452288A1428081A44A44820023244DBC4D045F1131D95DAAAF3577B5FF1D211D3B952AA5F62F2CCC81F38FA838715B3C1FE84833F1CB865F1D1D8CFCBFB195BCFCAFE149C8FAEFE4FCD8F867532F85E4AFFBDE96FF9FFCFEFA4F6AEA2AEA2EF72F386B15F78FABBB8E9 ++:805B8000CD1DCFFB792B42F9636F2F2FFF6F6FEFA4F16222AFECD9CCE12DF9686C2F6353468FAC784EED42F27C6C45FC1C2E3D18242CF1135E1F33B312D2A6D2F5D375D3AAD2AAF1A5A68F68D833722B5B7D4FDA58E52F78F836133FBAFBBFB91E127F5ADBD5F9AEBE3F38F8E7F57FD1D1AEF85F1B3E149FDFFDBCBF6FE3E3C3F3EDFD5FF1 ++:805C000062F3B7FC8E877F53F7BD9E97327FE2F2A72FAFCDFD4557AFE4F572322D627D17BFB5F166666F63B312F51818D5ECE6F6766CCFC3F22C1C8FFD4B7112F11345EFF1F12A2BEF94F61F2C9D1BE7C285FC8B8C8FE67422C1297FC8F8595BFB888F9CF8E4B58F4DFDB59D4F4BBD82FC1C944FCEFDA1836BC4C7215E4A5F11D5CAF615E1 ++:805C8000558FFAFE3C3C6F83F3242C1F4FFEA5666F3BFB9696FF697B17FC3623FF75F59692F7F12F467349F9C1F327212F2DF86E7E6D166F65F5DA92CFA6A211EFC7F52C3CCD1EEF714C7317D77A51FFEF62F25F79FFD4D7DDF33C3EAFC3F32B2C8BEE8FAEDE9BF28E859FB5F54E458FCDFDF5F49F6CFDE6D8DFDFFDF5F5DF77FFE4CEBFA2 ++:805D00009AF875E1DF37F7D45A5F11F5FAFC5F7FFD7E7E4FC2F2A6AC4FFEFC7667EF4BFB8586EFDFFB9CB57FF9F15746FF7FFFBEBC7F51B162F7D9991F3DFD9F9FFFFDFD74746F47F796D4EF6DFD6C6E5E5C2FC5F71C1CC5FED343100223020022841482264108921412208802002048042800984AB224094B82908480084502490841005D ++:805D80001A041224000012460485041F5D0223181108218C14281158411448890844484651812D141934421280841804589044008170C1148452145012124663410042A08482463414284B414A094A01003F52052D421F41522A1F4132681F41364A1D64AB141D64AB9419B64A9945AB944B42AF14F92448AF14F92448AD915F82D418F99E ++:805E0000244A8D815FA27418F1254A87191FA26459ACE449D2A4F591242CF59124CD121FC9324A1FC9324E1FC8F24E111FC8B24AF98128AB945788AF1479B4B84A39A42F4479A4989A4F8A84F9A44A6FDA0465DA41562E4C726CC224E5D241F22A1215F44A968E24AD325B28AF2471A4F842154782AF146989AD251788AD3455DA18FB277D ++:805E80008A8B8137A287493FA27498D4B2E459D2A6F4912C25FA9164E11D2C8B941FC912CE2CEF14F9112C4E151D2C1C5B844E914783A1228D944189B116044D5A3F2A0600000000004004288002000000800188000040014008480000000000280000000025014BB24081121842044E11482E492612882A884484948883B4442178C40190 ++:805F0000588002183AC4468146841148248454341270484541B34821014008838CC41C4C1124E64804121241CFED4593248681712856218C524845592445A11846711851488141129654211E4116081054124004124912B2229414224531A5302445816821122414456322468145052440CA155084481489F496FD1427526661218D242170 ++:805F8000A9721451148F547224139881C485C42C430446DC4131C18F31044841218A31142A711472286244184781144D41137444CA2445C14934D08234114553248D41324E8DD02821419651C654A41A641183F1F77F001008450183C448248089C691480089296924124C0818C02100484241B0220443024B8211189084121C2111022238 ++:806000002004424144844C020090442B1B4082120422400100002484A14850812D1200001110021882219200002C010018008C041118686088400884212244108874470341642284C426CA2A248D223811187014612885548343011CE686913112441F8422626428149304278112A5E444186151212141441D5413711C824481E11518334D ++:80608000444682E4483458208431444972FD0B2424002800C0282B211100AC8168C4841418143A04403528103412863143202111043013250218441311711802A0215A788A01844283440846044844CDEC40C4242644189C28B72224008041421518127314189262812E1112603428422810A818A12484436C114100449044561894411C2D ++:80610000811401496424D02488850212C4681F4508484484483014208201903484148429414822B152528142D022022C416242844820542218291448044644128404424A410416981C2A14464C24314E844332242D14EFB8022004236A418382012148101C92442841418100001821488E31124212811211388441C7256216741388848172 ++:80618000F1261859782842A44100C3A218C2302230228423C1185F9B4F42150282890426482844880200002B21144024024183C4288454850228260449042400002D24800218412800008934124A0140A481002FB90765514280F218448323C1225848288D22D0414428C13891212D141322C41487264294214D62128C6443F042348321A0 ++:80620000A414254442E222041E621859FD6418225816C81CEC344C85D4246121C46782CBA12E14C44FEB078A04850240342884400812814012544280A14281009028221655828122800425421486921417C1411604CC0210020020B9428984820400F0DC3E0010821404248446224144480420419119121502842081084244188014024965 ++:806280000125820181181820440180842881048D1426041200D042F467E9242684424484C224830444C02117211251212624322431478248324C4244028322D3840226644218841E44260850412602C944C11612890424412604884210448804842F4A068244C4A18504001864480000C0848128304844828140C41248414912124D2414CA ++:80630000924464818CC1484100445112148414A6644140F8144840C21810F2D6DAC0238582241212484114C22189A3210018901200901142322334412E4A665128224A21218404130484126041423014890488444828890168008198412901DF3C4C024022422843D4A4A112231148D8C20860132CC22112198209C0414055421C52214ADE ++:8063800002121841301149112511011B14884289914190411219014418A021184260121F16098022220400004912912180A1284410144288628321A447122608800128844048085028008311089110480485110881800442853444A0C2008004280021106128D021D1244242023084247041A4144902422035C2114230822942C14282288F ++:806400005C480826D442A41248B02244A82424408204EC1404218CF4272200230800295842122224005018431101704518444A6184312E4870111485541827C81A442C9412149431245C34891483011CC4158114C11481301818004008ABD240088F1244C68184460846014A5142143800182100145012901480184262411C013490844C03 ++:8064800001490440041110844895944A8218A48441844888F04214447F214C3224A245C2428632A87018DA14E422F1288C8931164921D241F12422B3F2671187A2584D6C8D2235E81A724AF852351B214D232E2163E583B418D1C854435671935A1C18EF357188F81C21479987C455344C148591188FDBD18231CC1E6C45A812CB116D4411 ++:806500001CF146486B855022CF283228E3D418721458234594326751313F82D21171134FB41212E1E1E241D855F2238917128E514F6234454F6206E9F51A5415E652D64461282D32C7142E46CD1416541DC44981F443445F31E31464194A64C45741494204A3A445CB45488F84514885F4BF6C9021212D2D2E2467C228CFC49412769221C4 ++:806580005E7316D348082B9147322B1945110887258B1576F448118D4414DF226476E26F85B588714AD34434449A9517D0A362C91B42174517C418488B111DD83D281F28ED9494C1413ECC499118C42B88F0544222DF8B041150817081081D488004482001008424400220810200001084128402284128801282128212A228218221822177 ++:806600008225042182441244EF8143F184226FB252BE9D4915F89B3B3FB414E377F62727FF9EFF293B9FD858F56F486A332F13F11416DEDBFFE3F3B2FADF92D394F23A2C2F92F22C7A17B12FD5FE9F999F32F3929FA7A22FEBD9F8F1B2B72F22F4F39FB5FABEF787A29F7B794DFCFCA6AFB3F331328F8DFD2823AFEDF94C13CF89FA1C1616 ++:80668000AFEBFB1E166F45F13C26AB884E484F41F53E2AAFAA4AF325236FB2F626237D453F4AF21A366FE4D467F162777F72F2DBDE9FA2F3B8AB7D1F6F69FB37173D294FF3F3D2DBFFF3F3BAF9FF96F75549CFC5F56769DFFAFA313F3FD2FEBFB9BF76F7F3DFBFF6F4B29EAFE6F7BAA62F66F4F9DD9FB3F3BEFECFE6F4F9DFDFF3F3BFB6D6 ++:80670000BFF5D5A9F19D9EAF22F2DAFAC7A1CFA8FB2A22AFCCFC18184FC5F17C3EEF49F844484D46EFA6F7121A50732F62D6AFF2292AC5F11E922F64F44F5C6F57F766673FDDFF797AAFB8FA161E6F29F93717F752FD138FDDFD393AFFCAFA7F7D8F92F2697CBF92F22DE95D2B2FB4F6DBC9DF36F49EDFCFB1F7DEDE8FA7F7D7DD7F21F754 ++:8067800097D7BFE3F38B8F9F81F2DFDDDFE7F79E9DCF95F5CFD89FFFFBCB899F89FB9F8D9FA8F99A988FCFFF5C5C5E52EF4AFE8494AF84F41C144FC6E7CD4F73A2F42A267D22FFE6F22E25EF63F34B4FFFC4F566577F76F6DBFBBFB7F79BAB6FE1F1B6927F73519BED1FAF9DFD393BFFD8F87D7D9F93D4CCF76F69DFF6FE577F7FFBF7BF28 ++:80680000DFFF72F7BF8FCFF5F6DEDEEFE1F1B7AD7F75F69FD5DFF1F1FFBFDFD5F69F9DDFD5F5FDFBFFD7F3DF989F8FFFC9CBBF9DFDCFDDDFDBF8B8BAAFEDF95A1856FAFEAC4F4CFC5C5CCF61F1646E9FEA01411042084042282241020020810228C0242004426044B04892124A02420029011880819414001A04000012004430483048E0D1 ++:80688000DF0121288052228C024C041D44A39241895184184014D432011C3131442414242800154284614418155422445041614C04111817483081308518824604189244430194DB79D032F41124C5F3112C87141FC1724AD1C1F64A111D64AB941B61AB9451AB9443FA4A9343F2429347822D914F8BC4914FAAC4854FA27418F1244A9647 ++:80690000F1244A96D5A4E449C24A1F49D224F4912485F2912487241F49724AF28124AF24F18124AF24B981F24A9253F84A924B4AAF243924AF647BA498924F83C4944FA2F43EECD0A2F5116445F2112843F4812C2B141FC1B24A7181F44A141F49F24A2243F84A3353BA4271A4C8114B4A4E116B4B148E525CF125C28B815FA265414FA252 ++:806980006C114DC31E212DC21FC5D224AC613CFC11244AE841F242811D642B941D242F44F911642BA45994924B422B94F04AB44994B26F83C494ACF53B8C0082200800000016042800000044000000200400140084000000000000000000001002DF23052140487C238CA2412426F4261218AA91184531114948D214B222711234144400B7 ++:806A00005184144C6241418D1145829412246622312D0014B0488152941A5883100C8422424C43240144F0E12C4035824D128A022F2914DD48551848869842144886B419B46C81644815222265485304464234492D814220B424289442141B821692112D432AC849513C244628C8439048437C5472889448824443FC281186F47AEB40342A ++:806A8000C283D16862C2B289C4168CF21226921AF22814548AD1488972222718F216224E1482521534C8F028424C6844997141E44278528214F27388BC711182A4821D48C98426F2148A85A142C489148C94443A147414024961411FB204250145224883D416C148458154288A44814495418F4481C4345301401405245451160140220433 ++:806B0000E01204430234113011341D4C204803A0486C63888524084B488922F8F6E1800100008034420010088004100200140000484008004904200130481240140818502841180090120082508497FC10C12115184468268415044614B22804244D1888304418C123041848C0224012218244A484A9C2245B1420C2216044A126621142AF ++:806B800021C2C082848A04C844860C2083F21537002611411408904421418006240010145248429011002260241180442418188424810280159A2483210482D02408880025C484202851486FCE0A1301814820161A81C4424481817018840C4218100220048221008C027041E24284921D0066314841401241C2144885028B1242208C116B ++:806C0000089022382FC90C8011014100C034830440180420642490488055844800691438282D14814A0120042028024004202488C1122C048C21024614041A0888FF450E4046341230191A024888008224004D28514014410441A46884274411425024C82222C0821485B4144481165952200450482C041284803414444141DF6E034420DD ++:806C800001151882440C502240C2481C14420244800C100840014410048412411004148C120820040084130810344480210222F0FF9600411123518433A121C41AB64818124272489241214C1613C2488AC444444784842D425C344A1922418841084480681885C17C8149046D41428860A1471C25022244415212164494841F95044112DB ++:806D00006901148442100400891804109844444114128100228141859446444D42C22AA1244014C22410215281004212402864814CC14842414C2288021FC1064004100400008800004844481004004001800448004248420000420020B2110220B48114022120040000AF9109240014184842424531C130410019C484008C84988140440F ++:806D8000882424044211802402406412801A012DC48AA148888A824C1192C1C8A2C289880C00F06DD240120448444220041B846014004242440000101408828024042024044004206C1430441A08A84C88C84320CA822A8808C80000BF880985B84884641418800454708454444302148604484668481D82001213A48C8A0CC04150111D2E ++:806E00002119D48854888F1486A424402208CA62114D2446B424B2217E42210448830C242552221AF1E551000000000080880420080014488E41480000001004000000220010420200210042808408220040F8831E104828840400004044E448A242280048100435022921818188280440414161828184424800000048414428A80048429F ++:806E800084101292122FC30DA48004400420044245042848881C040000214258828A082004F0812120482886041001001046248C02421004008421F06AA840A4440000000044800600004200218001C81400001400C441484004002848C084882800100282481002189F27018001140000000000000014000000004880040080020088401A ++:806F00000210024848A084800800814008B02504818B442004000010D48438242262001304404252244B4112D2488200302119125188818304424004282018443CA420220841A0422424241AF1DBBA40C848A044000011004CD4488882022008001012A314188888000014144048084A840200402188D86C86A2284200008C082121E768EC ++:806F800050221004210000824A080090411100200442000000000000008800002111004200480010080000EDEA200100000010012004000048428800000000004220020000240000000000A048201C0400F0F86760210011000000A044890C60184001421BCC00200448484241800290244122820025052982D421088BC88308004841C8F4 ++:807000004F8642081078C506200124000010A18C8842480048424844004904484800200420820200308428102212034E8242488AA448884AC8448688841808F0615B24412144004100198488142808CA245411C81714483041F04441201401800448A8A082002200244002A048A084214AE82C048242814008F0434B70227212A2122B1145 ++:807080001221C0122592811E1317119BC81F99D888F888418F8424D49154111C548885F844488F44544449F22424C02480524445A4222F2292222AB19281B88229C8122592832F11F111119BD81F99588889F44848428C0448855C884E48BFDD0A6F225226181A213112C0112592829CF1111119F881888D888B48CA244459111C54C19579 ++:8071000088F4484445B4443624224480425444286F62C2A22A21A3818A28E818512229D8B2F1111319F8918885B888AC444200488485C8689FF60800000000000000000000000000000000401808000000848100000000000000F0AC5C40588885180810181808000000000000000010080000848100008181000000000000001200122FDC ++:807180004609000084008110080000000000000000818100008481508881008100000000800180018021A111CF2708000081000081000000000000000084848100008450888400001018080000001200120018F081420000000000000000000000000000000000848100000040180800000000000000CFCA05000000000000000000000062 ++:807200000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA0500008481400800000000000000000000000000840081000084000000181A8101001200774B0000000000000000000000000000000000848100000040180800000000000000CF1C ++:80728000CA0500000000000000000000000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA05101818080000000000000000000000000000848100000040080000000000000070F90500000000000000000000000000000000401808000000FC ++:80730000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C008181810000000000000000000000000000401808000000840000000000000000975F00000000000000000000000053 ++:807380000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA05101818080000000000000000000000000000848100000040080000000000000070F9050027 ++:80740000000000000000000000000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C0081818100000000000000000000000000004018080000008400E8 ++:8074800000000000000000975F0000000000000000000000000000000000848100000040180800000000000000CFCA05101818080000000000000000000000000000848100000040080000000000000070F905000084008100000000000000000010180800401808851808101818080000001800180018121AE1F10B00008100000000003C ++:8075000000000000004048180800400885480800008181000000200120018001EF9E0B00000000000000000000000000000000401808000000848100000000000000F0AC5C008181810000000000000000000000000000401808000000840000000000000000975F1018085088848485088100000000000000000000400800810000000048 ++:807580008100008081810120A1111A21B1AA0B00008548484808000000000000000000401808004008400800508885080000000080A1111AA1111AF1D7140000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C0006 ++:8076000000000000000000000000000000000000848100000040180800000000000000CFCA05101818080000000000000000000000000000848100000040080000000000000070F90500000000000000000000000000000000401808000000848100000000000000F0AC5C5088854808814008100800000000000000008100000081810096 ++:8076800084401818088100008081810120212101ABD4000040588885184808000000000000000000100800404818080000848181000080018001121820F1CE59008100848484810000000000000000000084810000400800005088000000000080210118121EC7000000000000000000000000000000000084810000004018080000000028 ++:80770000000000CFCA05101818080000000000000000000000000000848100000040080000000000000070F905000084008110080000000000000000818100008481508881000081000000800180018021A111FF6F0E000081000081000000000000000084848100008450888400001008810000001200120018F08B2200000000000000BC ++:8077800000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C100800848548088508000000000000000010088548080040081008004008000080810100121A21012F8E0B00008485480881000000000000000000811008008484847F ++:807800000081000084000000180000121A218171AD0800000000000000000000000000000000401808000000848100000000000000F0AC5C50888484008181810000000000000000000000004018180800001008000000200120012001BF8C0500008484848110080000000000000000851808000081101808100850880000000000180071 ++:807880001212AF4A0A000081000000000000000000004048180800400885480800811008000000200120018001BF560500000000000000000000000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000045 ++:8079000000401808000000848100000000000000F0AC5C00005088008410080000000000000000008184840000400800008100000018181800121820F1EDCB0000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C49 ++:807980000000000000000000000000000000000000848100000040180800000000000000CFCA05101818080000000000000000000000000000848100000040080000000000000070F90500000000000000000000000000000000401808000000848100000000000000F0AC5C000000000000000000000000000000000084810000004018C7 ++:807A00000800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C5088848400810000000000000000000000000040080010080000000000000020210112D78A0000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000008A ++:807A80000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA05101818080000000000000000000000000000848100000040080000000000000070F90500000000000000000000000000000000401808000000848100000000000000F0AC5C00C6 ++:807B000000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C0000508800000000000000000000000081000040080000008181000080818101200100BF7E0B00000000000000000000000000000000401808000000B6 ++:807B8000848100000000000000F0AC5C008181810000000000000000000000000000401808000000840000000000000000975F00004008100881000000000000000050888100001008851808008181000000000080012021F14CEE000010080010080000000000000040481808004008854808000010080000001200120018F083AA0000DF ++:807C0000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C00818181000081000000000000000000000000848100008110480800000000000000F0F5AD000050884048088100000000000000008400810000848440F2 ++:807C8000080000810000000000181A01A0114FE10B00000000000000000000000000000000401808000000848100000000000000F0AC5C008181810000000000000000000000000000401808000000840000000000000000975F00004008100881000000000000000010180800401808851808101808810000001800180018121AF179CCB1 ++:807D0000000010080000000000000000000084848100008450888400001008000000200120018001AF9E0D00000000000000000000000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA0500001018081008000000000000000000008181841F ++:807D8000000000008400000000121212000012EFD60400008548080081000000000000000000840000508800840000100800000000808101005F960D0000100881100800000000000000000000008181008100008400000080A11118200120013D2900004018080000000000000000000010080040084018080000000000000080218101AF ++:807E0000E0F80F81000040481808000000000000000050888100100840588881000084810000000000180012F046320000508850888181810000000000000000848481000000811008818181818518080000202121210100F09A8900001008818181810000000000000000000000401808100881818185181808000000000000F0897100F6 ++:807E8000004018485888851808000000000000000000000081840010080000000000181A8101120012F0616F10080084851848588800000000000000000081848100008484811008004018080000000018121A8121F13F26000050888140180800000000000000008440180800000084000000810000001212A011188001ADDD0081818167 ++:807F00000000000000000000000000000000401808000000840000000000000000975F0000401808400800000000000000000000008410088400000000000080018001800118DFDE07000000840000000000000000004058888100008481848518084008000000000000001818124F4E05851808850800000000000000000000000000004F ++:807F8000818440080000401808000000001A0100F059870000000000000000000000000000000000848100000040180800000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C000000810081810000000000000000000000400800000040080000002021210100003FF10D00008551 ++:8080000008404818080000000000000000000000008140080010080000001800182081011AB1E80F00000000000000000000000000000000401808000000848100000000000000F0AC5C0081008100811008000000000000000000000084000000008481810000001212120000F087AB000000008110080000000000000000851808000043 ++:8080800081101808004018080000000080012021D1A308000081000000000000000000004048180800400885480800008181000000200120018001EF9E0B00000000000000000000000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA05002E ++:80810000000000000000000000000000000000401808000000848100000000000000F0AC5C008181810000000000000000000000000000401808000000840000000000000000975F4008400881851848080000000000000000000000100800810040088400000018181800121212F095D90000405888851808000000000000000000100829 ++:8081800084404848081008000084000000180000121212F03F3B0000404848180800000000000000000085180800008150888100008100000000008081812121F19D990000100800000000000000000000848481000084508884100800000000002001200180011DE600000000000000000000000000000000008481000000401808000030 ++:808200000000000000CFCA0500000000000000000000000000000000401808000000848100000000000000F0AC5C0000008181811008000000000000000000008181840000000084000000001212120000D08F06000085084008810000000000000000008400001008400800008100000000001812A01112EF8E0900000000000000000095 ++:8082800000000000000000401808000000848100000000000000F0AC5C0000000000000000000000000000000000848100000040180800000000000000CFCA050000000000000000000000000000000000850800000084810000001800000080F12592008181810000000000000000000000000000401808000000840000000000000000E5 ++:80830000975F000000100800000000000000000010080000840081000040080000000000001212F0ADAA000000008181000000000000000000814008404848088100004018080000800100001212123FD6010000100884000000000000000000848184810040088440180800840000000000008001B08B0C848100100884100800000000F7 ++:80838000000000401808000000000000508810080000200120810118F0633F1400C0499C81C41841100440218818011544A548828200801401882024044541258402949C88C48826883C242282144424286C424604830882213FCC0B46E19441092D444598444638441B48448241414344148444186114814A88C8841908131831811CE848 ++:808400005228ACC210D1815481884344BC44C2442D2427145321C2A4902445026828272A22A948C88C7FAF093011602481814200884100A0484511C441C111488400410000884021AC28006601821038448D224E2241206A180024243022281002828F1944014019B845219414484251201881080010214421280C2004130814E04402443B ++:80848000441008811D84448C0849382116014004004944028C421858845FD104480014008484410010040040040000800800820082100142104181240448002210046042442220880886023FF2091483040044400442004014040020880820081C480111B04108204411018140082241201404289024212810042182005FAC080000000009 ++:808500000000210000000000000000000000000000002008220000000000005F8A0C172400250210883441584248114D515048415C058C91814810440124128021188612D441285421116042416110B8878172A22AA4184A28682262CA2298344B2888E02D4D116411835281241689C21CC1441378818208130422218449141481422812FF ++:8085800018140850C150841A84621300868C0883572848421442822954422001448B2423188821F8966A70411452283480312843148981289483430444284D11F048141C1821128402442D188061186126C4541DA41305504822444D1881A3B4455821661822810826A224E84AB816CA2C822CF87C7600132142485281608143C444463122 ++:808600008130114641488614084448404841080050481008201251128249082306241222824E828A74422488014426088218F07D940060120050141524D481561A1A74480110D45281A4145341240122400258444800282C21451201160415382484432248212924492148042C1244A449D084F4875950144712C9312933316B812A412863 ++:8086800001260184414A018C034A9A12835618832406430181DD324562A681C32622048129D822C636C843C5591A6424142146A4482AA458DE248DC440088381F883FF0044002411453111817603420060441321A441C2121A1488040048844916C622814B414248148129214632C442938639413C09D81182493114830C411A6881C9FC66 ++:80870000D9A91095218F5192292D114E288426841458181B2193141824514236084F1251428C4261824A42321412448D112489247228A22124006C48D25823D284C11448242014A484624AA8862616448804F0C5A3101466C26485841146024784235824241A188418C24286844184084441184C84284254824446EA1811244C2294AC4428 ++:80878000C01200648B1827842016742C024100A55248899118CFAF43810400422824201462844B422251182850142014114815021D1C1129182204245018204148228504841021C24440880A88446282284C084129F9E85B002001101108411312410842504343141801001242842522916420C196000014615100852408821041A2481038 ++:80880000088A458201120044BF16014225F414282054216450261D28271C2C064C61211F4218524967181814C015491458A31B14438662244B8125062518E411445414EB1243444418928145D2283C48A98C5C84282D4443B212C8228319C41CECF8665210044014AE218120C4448184241B4844604448804464880044414425024911089A ++:80888000838409AC08218240880980C211000047889848004484005F1F08101A08811448189024168811C841841899511430444241190424483248A01246848444614131C4281148462824112224242864684A416A84A4602148818A15B4C541423114D0810227841942D18262284481602849114362881437821CC118818460A2400445C9 ++:808900006222501421842840F8142240114E311844814C9188004A024210C4884880E4E74D61442601846284A711492211286412121890242CC41828004A818696428084D18222810429042714AC85420430442084E424886827124A68882384B84A8158820040F816A64048425142A02100421800274441002126E284012524221104000F ++:808980002638158C34114568114D48C08513C142908800411484404142C824411084014C2101184F66488214419821868841B4442292448D1110314183414E4822E422A424208154422A041CAC4125819248123D488004604246024228421246A482174C241324A11450821281424C68AC3F870322C3018A212104B424A0422C440224905D ++:808A00003448160200218022B8120A40184A4101002A810612124118410064004002008C28048324B251079400C0412210C24110D28308109291481C0213499821860124842449521242342C0216221102142C4111612A1042221201202838282A0820198401EFB50F9022124414118F2104B44E212428550211222004602300224400A916 ++:808A80000822842884414C6241274490424002481841124218318922283282268818A2128312F452E9C02C801482024489048119C24489C1381038244C219218002742442A05C812431682084712984284D0140CC71121BC521454988A52C2A02118296248128E1421401882F879F7244E447FD31368918D63665A4127611AF28C1A2F9545 ++:808B0000F532611F81C41625F62522C3D182E326D1287811A2341F46A4622B444AD422F5D8E22FC715E422F44248EB444E546B144B4343D444E823F5CA524F85F4E4434E114F44F154422BECCEAADE4283F478E82B6C8BDCA7C48A184A8814D844E5BC0741409A2D56F819618FA5F42C618F34A44285D28148F2C14185619117A4DF3654AD ++:808B80008117174F86671289094524A2226742115A93138D26121D881E44C6D39271211266111513781722D148C9121C9492276827286427A22E82A7C18E8E6BC4224F84FDA8821FAD47F1232385921127421382F12411178437823F44F221248724ED1527811E18AD942F4267492B612D7C2187411E21C7642E22AFA822C5194D23AFB2C3 ++:808C0000F4CC2913C236E731BCD243E143C2295C5285212D2C4CD693247824B83151851B8159E182C9249AC5321AB198F15C189A6284BF3B08000040420800C08280081C081C18C481411C4808840000442182228222139C121318224802830281100810044128430100009F55063E342E2EA7A12FA2F222221FB3E3C6B642F54B12BFBBAB ++:808C8000F177F8EEB88FE9FD16DBEFA9F8A8ABFF9FFB3FA4FEB3EFF8F8EF8D5F16F3E8F4EF46B662F66878AFA7F57FFF3F12F721473F76E62CEC2CFCE468DBD94F5BFFC5A337487F6AEE9CFC42426F4FFD6C58AF85E565FDF2F81FB6F77141CFEDF5CE566F47FDFCDAAF64EEC97812F816C68F84A6266F65F4C9DAE027F7636327212F23CF ++:808D0000F74B4A97B4CF66F64C52BFB6F3FB393FD7FF61388FA7F756DBCFA9FB3336FFE7F71E9F3F3DBD23F37352EF85F5F995CF47F76262AFA6FD7A58DFB495648FC6F662668FBCAC9F4FEEF6595B3F43E7B8FE82271F71F2414A2F28FC7654EFC7F55A58CDDE6FCDEFA7FF98B83F1DB5CAF766C4EF2FFD4AE62FC9D9C6F852C26FC5E7F9 ++:808D800082F246DE1F5C042F25F53656BFB3F32F2D8FA6F66B3A2FE2F23217BFA777AFFF5B9CBF95F3197BFFF9F51E96FD12FF86F1FA396F67FB7B1ABF87B5E6FF717D4B54CF84E626BE52F57F7FBFB6F76F5B5FBCFC624BEF6FF44ACA2D4A7F67F7B677EDAFDFA1F2584FBF64F4FEDE4F67F75656AFE5F5F2F6BF37FFD3F18F8DB5D8F515 ++:808E00007C588FEFFD4A524BA9AB11EFC9FD4A78FAFB44DEDFC9037F75F51757BFB3F37F3D9FA6744BFA6F2FEFF3F17B7BFFFEF643C99FBDFD1A7BFFF9F53E96EF79F95E5EBFADF57EDFAFBFFD7654FF9DEDC5F54454CD4C7E422F23F55F5F7D47EFA6F6A7EB2FA6F4DA52EFE4FC574E6F7FFEBE36BDAEBFD1F2DBCEBF6CFC7E7C7F47F330 ++:808E80005E5E6F6CFDF2F6BF36FBDACA3F39F1FED4CF8EFAF8DEAFACF994B8EFE8F99A986FC4E7AFEFA4FCAC58501290145022843C0126A3412440E281440720418204120000901200282110044901004048234123612292244834164842582882205948825F79054D12118582D21A81244698184487141114844416088C142A0320542492 ++:808F000042A02418874429014D4A834562444582E2224184C1446148419A346220A4414A084A2AC812124280C2419F5A072CF4112485F2112487241F41324A1D2CAB141D24AF249921AB9451AB9453F24A9153F242955782AD955F82D458F9244A8D814FA264114FA264194FA264592D5A9E24ACF4D1243CF49124AD131F49724AF39124D7 ++:808F8000A3F4812CAB141D2CAB941D28AB9455F84A9443F24A9443F3429447822D944F8284F9244A8FB3072E421FC1D438F411248726174143D441B24AD141F26A1617418B2459B24A11F54A35112F547321F84A153D48AD354D5A8DB14FA27C18D125A4295F8224F8225B9E252E4A1FCD42F991642D511FC9724AF391248B1417C8AB145B ++:809000001D2CAF44C92CAF145B81AF4429F24A94222F446A82AD946F8294924FA2F571A3008004000000400428000000000000880000400140080000000040042D2800000000004F820B181499117418412866D4284581038D1115384C00268CD5425441008D249413922100D0229414006066601229021A12912348A7225829021A8464E2 ++:809080004124C04222C4CC9118848FCC0A422D3429128A0416A821CB412889641210442218485148002E45924841A4903418414189721418864101109449A042B086311484811319D828487244384896642112221C94246FD404423F44D31813EA8104382E451E44158447F12914D181218187421E4C6354344D41125E2445612A2241182A ++:809100006024414D1A14124827843C125481221994232B8465CA4A81174A8B14424487248C245822ACC13C588F41F28A9F8001214414848364818382128802604482100100228884811548A1125024442E1810044712002842122290141A828182018D821225044E14324410086FDC0A43820284148C02CC24C26426C14814E0143125813B ++:809180004800148002448480D548522210044142008042421804811A4222D13828098668240022008D1448DEDB34165134C4342870289522464C4902188D4441212681D24172627538C474132466824A9216A5044E2447842724484A58264604214D182F81E464D828044CD42CA4488E434284572464824CFC94421624F244982289F236D2 ++:80920000EAC024445038118942946847821534216011C146C5218442261484B344014845C848418F4164C24D62464E048A042D4400CF21628484A7442146DC488348D118141A5486A0484DC241288E482A11D8B84D921113120E2270215842428B24D08204482C1134212215E2145249221B24222822231142028094424562440021C012F6 ++:809280004E84002034422F2528886914882F24188481034C11CC62CF8F4C9241268208185C084D2116758902494258524314048608441048942228F0261289C81210128B24188402414644D4143282142A8454C185826C2648C3C882A084482442428F22F14DF40018C1392184125828882213D1142502602243110483522812501445C8B1 ++:8093000014C084250400814E19200423352148001074284404842220022480D124584812589FAE0E41448826048B1843018A4404848068219148B0840125140448424081024284105662424502208102128410222102404812448C4288221A0C6F520971405816525C524887122F544142F12118A417484F24312D2315285948414311D477 ++:80938000148216F4221187424981542AA44D48164EB444022741362566729281432466818D220025F8288488E4288C25EA84B24C31287F9101481E24611A02168841041FC8828104004034844422A184805448405422100200296C84A4001004106122C414B04888240425064A084443082CF45F38B0252458812284133444C1569851007A ++:809400008440014A88A12471842A042C012694168021240844422112455224411041B2C1A2583D14AC88890C242021381480E18428017FBC0800400425242101B028A12429D48521160290148961173011460442422422A041181C5112492244818191444C0241250812488488487088220241A200F041851422966142814410414162814D ++:80948000281C41021C41226122223612442412881228922400688D4400901229828156A22456024368216800248C6B232C12C48283224484D848F1851D40D8420219C14218A128403442202114420443051440C8482284C084583028C4166212111828182B4200895118202248012D1241100C902288212880F2F9C51458850422A11485C5 ++:8095000034442094114842124284521064862A81011012848442026082421212411200122086944842A04898455182009A0444988066146F65074119518290414502702358144054834460442748224890484014482412418854242C081044082A84442802C184004014A214248A72420443315885D4825842818FD20C8428802181A51272 ++:8095800011002C440181A381111102414004221100702A254221A421233221004D481E25444C011A022242A302892A08128C328828283A04228F5F0A2127A838149888484845722842AE122400403244211013E8448294242981824844382410125422428480742802418901248E14100818101C14488214C488411BDF6081C044255852C7 ++:80960000902128111041341128418A11041D1840243712418C3148884664A44AC11863D21484344445188414BA4291682B124CF82411C36C8285859478428DD4888F2184944245889112F0778C142AF4852389F21839AD494E164CF1546189F243534B333F16562AA7C439D12481E52433561FA7F31619CCB47161824458222E6CCD432DAA ++:809680002426E227F124544443B71632522F41D34D51A28D4E62AF22E415F3949659F448888CF8569A2B18584F2ED82EBB24B142F842288F48FA8C11284FD70C4F15E2CA61B25372C1B413F86A6926ECB1F4182C142CC1594F31F118678375947514D468564C9B228B344D4864EF82F2242C69012FC2B168D4889B245E2256D16982712433 ++:809700004CE287767434141FA1E6C4F8AC8E4E482CB213A64C448F23D8EC8261C423F9247A4F69E483A1C28F82F425EFD062311A6D14244F21D1143415117141BFA42431512064482F24B822E41241E14434344CB24C47314A4E654F25A824ACF1D445AD4C217D6229E144C433C12592782F12D34EF19431481CF2FA9886B21AB189E48417 ++:80978000B4B2781AAC4B8FE458488B924B44124D167F8906000082888001450200540000400400001032180061008100000090412E821122602200400244004004819E94242F287211FA3A28B7326D46ED4E2F87E332F36A3C9B377B65AF95F35A584AB514D18CF847454B635F16F63F398F93F338588F83558E7F56F6EC4ABFB7F572D2E0 ++:809800003F97A61457528FA8F9587CCF87F717155AA532CF41F139717E7C6F43F35858CED58F94A6ECFF1BFDA193FED49F1CF5CC7CAEB64F44B562E385E936F6B8FACF4EEF8EFE56463F68457212B451F43C2CDF52F64446EFA1E587F22132AFC6735BF13626B7A4AF82F25A59EF95877847A7337F17F73E3CCFE3F31A183AF71A187FD66B ++:80988000F444CABFB6F666E63FF7B64A7513FB849FCFE5F75C5FFFD3F374742F82F72E3A5F73F3787E75F1494BCE878F9DFDC1C1EFEEFC8393DEFABF1CF4CCE6EF6AFA6C7CAF66F7F2F8AFE7F7BAB2ABBACED84D167F3344F342635F71F422252F62F24F4A7F75FD7E3C97733F67F27535BFD5F74131BF25576575F24CCA7F55FD16125FFD ++:8099000094F4373FBD31FF12F12D594D127FF4F424881F16F46C2E5FF7E684F5859D8EFB4AB676F7174F7E721F33F63923BF13E3C6F77B37FFD5F4CA5CFF66F64C12BDF51FBBBF9AFFCD47EF4DFDE8B66F46F74C8E6F64F8D4D7CFCBFFEEF4FEE8CFA4F5ECED342F7DF61747EFD2F27D25DF8CB415F57E3CDF77F27A6FFF55F57A7E173416 ++:80998000AF34567DFFB6F444D67F71F932367FD5F7666E6F42D3DFF1797BCD1E7F74548C5F56F6FC7E7FF7F64E5E7F79F98E9E4F65F173727FF3F66466FF33F23F2B5F73F3787EA726AF24F4DAF6FF2FFFFD73AFEDFFF3FBAFA5FDDF57EFEFFDF2A2EFC7FFECF66F2FFFF6F6EFC7F5CE5C4FCD7D2CFA57E2003022501680012621410324C4 ++:809A0000483448641A54281B41441008831422048D24218149016322840169014D12842416089E48240082641608C024928B24924624F8CD2BD0249421C582E22411312C48C34434421311381400184302B048028F44312442244480028E24C84E242C41140424C422482AE1480416344A122C48A814828D869098D042819428A4FF4C052A ++:809A80002CF4112485F2112483F41124A3F41124EF24D141B26A9921AB9451AF543924AF1439242F147924D852F924481CFB244A1CF8244A1E216FA265194FA26559ACE449C24A1F49C2421F4952281F4932481F49726AF38164AF14D941F24A9319B24A19F54A9243B24A39242F44792498924F82D448F9244AFFBF052D431D6C8D431F3E ++:809B00004132481FC1724AF21124C72419F2689415BC4A8BF24A955782AB1453B2427924D852D98794B25FA285D9A59C287F222DF8251A122D4B8F59C24A9E2C2E4B9E6485E3497448F19124A7341F48F4489315F44A8744ADB141AF341B949A222D94478229F92248AD944D52EF2D0A848248000000000028000000000018000000400108 ++:809B800040080000000000000000000014F04F75D03451412881814825A224658A628480141A5824008984A42989157944C2444829A543448745444866A2C2822A044C32288D41421068314B41C6A821131544D248B216A282708498848D348928FCFE2214204A4801444008C6B42121C61956644419429C24186C82442131882226245246 ++:809C00001C5827128463624185C4124512941200241A042924888164884A1832C188418B94462225E81344F8D829147C31E58C1249C844212356422D244D59221E4A4B148976245182498224F682624E1816F9488429A2181A345841831598614F23D41834884674422492281C044281469194CB414AF328D18A4472A92213A448C6EE21BC ++:809C80009CB45EA983BDF60A0000004018A84822481484444004891184110160444F2284322552734214064B821223026901814829012D12488800412149C484A289014484009FE508008280080088000000000000000000000000000000000000000010010011400170E74511211452441881544A1254A2181E411B8282428C1416E112AA ++:809D0000016C08281E4842827C0287921341B88214C8124695C21B214961488881344A32421D4843C22198828C32186B124821244C2A22E481E4FA411271421814E842011C2244D48452132AC414246F8498481A33A27C889125126217884DC4142E2240F1514830824CD498314439C82218C564812AC28187842D224F4134214E118F48AD ++:809D80004818D422A2112AC482F08224126E18A9F4937C002008880080080000000000000000000000000000000000000000110010011400775E70220314D01401418C1444081A4601215B41002880022811004441901420024190964C225281242842122B82822B1411AF1428D8320146628142800210F4E9B600286125092D2A85414263 ++:809E0000898D62283011517034731469448B1646A925524B86811CB418E41174C128FA1628439C525249042140B42549A1128904271326E28E01A384E4685484431CF8244243E548419C48FFF344122112115A142D284450168A01DA42C111144817621D184924314880E44A44681481003AD8480242436524184C02C11312028381DA1213 ++:809E800012D282171A2AC1824784AB41833464684100DC0E2C022514814152188914C84828100225341518412866C8215A824301E041C455871C4522F1A4421240D4240822114B1813228714A2184A93811B842C6C14630443082443A181857444D89703840048501400162422694213024B14A84C5114174224C08243031A0A4992488130 ++:809F000045988560984C0651A0848718814698C4100340041604823226C4244190882B248D823FFE4E420C8149154882014242C015881883028A021281301681A041A0581602901846061C089800624A021A4235482694134C028847A230440081244444281FFD054004282B61222664811400840050420000138242210484005128212204 ++:809F8000264408484400201A08204418810812288223A44142212061443949414444686183651218834104C01914181E444C9814702104314B218F5221A4C2C02410CB221D9C26D648684470911484B88822B4286C411413A44215C8212041883A2443B4245548C08849D348FC352910028022423426E01481868982088522821A8541883C ++:80A0000022080084528C4554848084E28248C848001183028B8644A14429018843C816E02429024821414222BF620200223258418CB412841404811988A492C9880588962485648482621A448122848282644650411944021448D02828B21828028A941A46C23483081A86880CA624C1287F250D16542840C2218344952530482220941496 ++:80A08000141285A4860082846D33462848792448688856A8498C42C81C9AE282012244C3389C284230482280188804A84118200388F0D9E960241411A5451A48021688A8683411888C244C01A9B44802148CE841521A412E1846354114A1411242008B58A084212F2422842464A19E6C127011247814A25282482628A81400EFBA0C30447F ++:80A10000812032211181008901181111288245C111002E9424008601E081025C464201004400860482EB182117480042400890122598162312D88412F4B8BEA028751224042A014712228512A4410044244481284C528244688AC42164182411494C01205114284328111211CC44411A048E1284481D8249148841042E888283041CF15BB9 ++:80A180005924451808151472443244524501D068A84146825148114C3111604146C8141006544C84081694992605838709481921E111A2120029044A48D88234282DC2000084492A98242FC10C12C01821418002A1232104812D11468222AA28412B18192202282440225124AC02904841885C7411624A0000228E2C2840024C22082036AA ++:80A200002642430448826F2943012218124221006823031A02251404489082257884021015E48244826222130812928609244881CF2A641160818800241812006684088D22181A84B12824F4417D6084184C145848148942684141896144C0288522342815984C422218009880C818430180541242488C28B284048482612C81C2968C64F2 ++:80A280004288A818184829E84815548290128CF8BCF170147484F91F1A2F13D1A4E4567424B57CD5EDD54414F218811D435F14F5823ACD241E414DC9CF64B128514483F1851C1D468CC8124F4371167421FCE3A42E1C17218E3449B145F67122DA762E34146F18F8EB92DE664D828B298F25F522B8DAA9C99F445D884F2CE92942B62252BC ++:80A300002C8B6F4F4CEE18FA2482DF75052CD4634244F648343D289FA442A4258BA1EE384AB1C8E1C1581923F4A48497222B824F41E21CFB24E88B65CB2CC6D1C414E9A4B7480345E1C4713CE881E859C1D4C9E129FA414E99D5C492942F4EC5144F922211B84A11A6B18313B23663A92FC35B868F82D184D1C8F6EA97244AB31824724D7B ++:80A380007822311C29D49332222D18CB41AC3612214F45E48BFC4B288E341F99F4C2C827A34E1526B222F927269F16C82B87124F39DCB8B553BEA8B442F448458B8286D161088EA1162C712AB818F262C82F48F8C8462D628486FBE6442D4C6AADCCCF44AD4C98128B4792BEFF002B12005024400247222002644006444006100180124249 ++:80A400001403000041302230220000002002004C020081003048FFD843C1424FC47128F631441E141F11F129216F47E345F588A2CF2CB982F8F8D61F9CFCC9A97F52FB69F32B3B4F9F4BF2D1C1DFDDFC91993E48173275F553498F83FA37398FB1F693A1BEA26FC3F9E4A88BBBDAF5513B8B911F19ECDFFF51413E222F6AFB621818CF8C53 ++:80A48000A5EC8BC9D5F155B18AFAC4A665F266D6AD1A2FA8A1AA8AF93A4A7F174EE164F43171A7A233F35A5A7F41F129241F96F34858CF43F35C763BFB9BFF5FC5F15D785F12FF69F3EF43E31FDF8CFC4DCF8F8DFDD49A6FEFFCAF8BAF8BFB6559CFC2E28FF3D9EBFFD1F2782BAF87FDECE89FD7AE455FD3F71C366F4BEBCFFFD143A7CBEE ++:80A500008FEAF2DA48CF64FC86846AFFE8F2FF5DF5D1F95ECA6F4DFDD4D26F4CFC46CC2FA8B822F984946FECF51329342F25D557F529335FE2F21957BF91B52AF26E26BFD5F786E62F6CFEEBEBBF3CFFC3DD2F4DFDEEF4BF3EFFA2EA6F8FFF5656BF95F1DFDD1F19F921D63F72F82EEF2F37F478627F33F33D773F33F23A2B6F43FBF4F852 ++:80A580005F81DD65F617778F61F3B1A72FBFF7F7E7EF8BFA2274EF66F3E6E6AFCDEF2CEF8DFFD193AFADF9CEF66F4EBFA2B2E2FBAC8E6F49F99ECC8AFDA8FAB7BF342F66F63735EFE3F3252EDF75F51F7CAF66F66F4FBFB7F7A6E6AFECFE6B7ABF24F7979EEF8FBDEEFD6FF7EFE9FDFEFFEFAEFCCF8DFFD7F55D1BDFE4F5A783EFE3FE7635 ++:80A600005AEFE7F6D73FFFFF7717F73A3AEF47FFFCE85FD5FC7163FF73D32AF2B5B7EFDBFBBDA7EFC3E34AFBDAD84FEDFDFABC8FA6F7CAFAFF7DFDFEDCCF65F4F6F44F4DFDDAD84FCDFD9A98EFC1F1CCDE4FECFCD14E901430228041382416480160892048444802206844924C2278481461441008814B12B024089800D01441B824E88123 ++:80A68000A48212404842480124128D24001008EF57088A05C513215241850224168C9841241309488DA543FB482312108179210821146D1A1CF2259286A15216E4823841450249086E921224B06468882724E02421E1646881252408F04A34413845F1BC93C0421F41522A1F41324C1F41B24AD141B24ED141B24A9921AB9451AF443934DB ++:80A70000AF5439242F547924D852F925484E914FA2C4814FA264115FA2645D2E4A96C54A9E246D4A1F49C2421F4952281F4932481F49324A1F48B24AD141F24A9119B24A19B54A3924AF443924AB94478229F9244889F9244A6F27032D411D4CAD431F41521C1916D241961619F44A9415D41ADB85F44AB4328D852AF442951782ADB47F32 ++:80A7800082C4914FA2C5914DCA1E811FA264594FA26459BCE45D52A61F89D2A4644D3C75917C4AE249724AD141F24E924CF24A951748AB3451AF242BD84AB124949A4F8AD442F9A648AD144F82F15AE3400848000048004001280000000021800188000000008C08480000000000280082000010026F430744D01441D858C14447244088D0 ++:80A80000A282842788D6014323C2444502ADB54629481C424548C811872428584446C22455622328443F24612842234812742232888364418F3C11143844893C28006604671424425B1826D82481F2182299E3248155268CA42452245D488734849E2A26F1441130344CA3424168167124A1482216C422A69A888242867111C4818143D154 ++:80A880001862449B4186F81148248A21043094898891D4432C661989F83C4660444E1115C818D4CC648525B2187424F2A4482CE68AE12469948D2626E8A4117512F4A6194E35182D4AF08411122624C94863333167A24638A817641D821CC246871549B1495242569184EB618338EA4B148F1512E281286485C88E42488A26D1DC0F214474 ++:80A900004B12442B121A7226A1412400844211441B4130A4281904844C3A24442A5418156814228024C88244A0214931812482218A542884348001884144478888478344224C61886F290B4302262211120184C11F8104482C11041200281A948890188CA42448441187548082012A081001005018302200124A89A41448B09404820030B0 ++:80A98000249F2F0CC011C7184782C48F64C2144B414A221A2211D8A1E141C44C7364D54354364CB145C1644712534818E24221C21347114AE846E8441162148061428937424E12437188B2A4818458834C9182C7284905CC4318FA14E14B81884F8D084CC2111D824542CC281218899219A01412ED1163C414174446AC424E144149C174B3 ++:80AA000015641424F0211422244498A6A438211904124124A014122C280888131D8461446048262C084F168838249FBF0D00C992386074414D4846A4A421400818AC04195124112F8168148189E642984841D09464111C83249444001480B22825444BC6284B21481825E824219C882745521884A1124921F8D395141508A14148845822DE ++:80AA80004C744144480C8414441242C044212B1452441A028641981212A7112240042E44162816614422448308722F12042008214C0E0050824888FFB302461E249142A01289023821E04512022E4813984424A283311124442416D4483834502546C4841E478A2448213128468CC82A418A42664A818A916400222A484224462424564A05 ++:80AB0000E04E0B283211221047440C104101809122508441220083A28490212428222800182820480400881222004081984243C81C188112830420024BE5144243C31A490226C818444C1346E81201814691261A542C43B82C84A11489636C43D2813234815B124C938726248C183154163428148C94A444AC6A48221B481B4230C249685F ++:80AB8000439A1224152824C648821F740C473A50126024174143C628421944C1482190181348848422511260440041142722904283C1521243022A8812247824022A4924E281B4220188406288464688924440C824F0D248101268111228001068828400608250484902544F2221248148113261411841004200001418B01402106488885E ++:80AC00002B38D024440218C89042124044F85288A04329022883649154224E164325042400411E2114412114221502C04D181444221258442A21012A1142344120C621624242114A69115222208222824208283F650623381400124048048C048C843444D081833448482326644982460218009041142818304442410059021014911428A2 ++:80AC800086025A288828E84128CF4282A6A41882EFE7084481A4008E2246018021018901432504881CC8822A0825F22481181C82C4411412863482828A04211190430020911480010000230421450840041713204222120C846248001081048C342410840849081C3324804C0448421388654844181E445141442443245414E044981246BF ++:80AD0000612415B4442284684400404818F8BDCB40A84248402204002043849111004811521618135542C05AC0814B1447112004581A020000800180030000241AC222308A8883222229F14D522091121217218A224314C2242284214048024F81E221322419820121242E1480022841261404408442E2310280823242802284138112033D ++:80AD80004100144384A542F09EEF106428008448220090242A44084412904813028001128AC41C80A34280050048128091114242004608826011A01846B422054200D01824F4E854D081149448A3E624C187B044325844428D14F0582412831481084E9424139622141D18221A08211A226248146B4828CC82C1444A62424084011228460A ++:80AE00009482291AA581441249C1AC29E84138224B82CF4D4C32324B392F8152818B8187C32D45224D1CCB464D188B644299E141D65AE114E148DA41F181835C91164B1327314E488579156156424F12E646B7840A6B9C4F24B2447621D766F216155B2447414B2254C3578429B3115B124B441F64E121A4664D122F46FA29C623CB24BEEF ++:80AE8000C54F89FE9A4BD06476C85C28AB626E2A3CAC2267448F2462C18B2516B818344449E181F21D648F94F166614A9166A88E215B22573223A5524D125CA11517315E144F41A423441AB114F111111B442E4458487B151D6492CEC22CB411FC11912BCAB827485E848E1A45C8888B5A94F0ADB7E0147122C2111E16583B345784681A48 ++:80AF000084A34231ACE1C17448B86464825B428E826FC3F6B1821F575421CE84A9F8A5744AB211B43546B48488A49C4CA45126048042B162222482E1442F631ECE122768471163BE14B982A641CA92644F81B84C3328BFF807110040080010423822842184211518020020098244804202246022E022010041100225413822122001001216 ++:80AF80002011088120F4CA61342F54F41138945F51F47868FF73F353332B118F26E626B648D531F34A5A8F24D159D67DF1435FEF4CF8D455CFDEF896856AA7455E412CFCAE7C3E314F77F816515E526F28FC86C26F68E827FA26322D643FA5F221367D441B755E362556222B668F6EBBD2BCE1FBD3943F24F9D2F22B942BD94D84CE949F3D ++:80B0000082F2E2C2CF84FFBCB8CFCBFE75D5342F34F57774B4FF53F2786A6FF7F753753E722F26F67C6A4FE5D7B3F36A7A4FE4F5516B7F77F17A5EEFCDFDD4D5CFECFD83151F17E737A5547F54B4C3BC31F574466F53F41155DED41F34FC92D2CEC5CFC5F654467FD1F522263F42F655522F65F342441F14A5778F6DF9D6541F1FFAF2F61E ++:80B080003F6DFDD7F26F6FBAF6FFD494CEC44F46F4E2C26BB34F8BFF82F43F494DF243641D7285F935258F27F66F2F7F7553468B772B768F64F563718B75A7849F71752BF5584CDFACF8D7D6EFCEF996946F4BFBB5954F58F941C3EFC2EE16F664654F75B552F5C5D14F39FDC4C42F4FEEC7A3676F23E663F316176D266B314F43B334F2E2 ++:80B100003D2BEBBBDE942BBF2F2CFB57D22F7DFD52D22F2CFF46E44F4CFB6A682BCEEF87FF38B8CFCEDF494BF277767F6357B8FF73F2626AF7F63F55D764F47A7CEFC5F1787C9FB6F35278E7C5DFD7756DF7774D9F3FF9D3D7FFFEF9C7D55F5667134F6AFAC7CF7FD6FE65555F46F775677F55F6D5D76F7FFFF4F43F4DEDE7F67666FF5390 ++:80B18000F337277F77B347F654326F65D717F37D7FEF4EE94DFE73B17F3DFE57D67F7FFD56966BED4F47FFFCFCEFD6FEEECCEFC3EBEFFF68EC3F470B2E11501240429814206281200100C02417814413810210811241140118901480014B12F024115032B024014522011A4401541244C024E044028504CFF307236841858222022601C0A9 ++:80B20000248100848D14C011C0A48225B43584181418C2245816045C822888441404800244241644014E82402201A02443512A10888403CDF3C0421F4152281F4132481FC1324A1D6CAB141D24AB941D28AB9455B84AF92548AF147924F8429147822D914F8BC4914FA2C4814FA264514FA264192FA264592D4A9E242D4A1F49D222F591F6 ++:80B2800024E5F2912483F49124A3F48124AF14F11124AB941B21AB9451AB9443B34A3934AB944783A9F92448984FA2F4726440F3116CCD421D2445F11164211F4196181D648D941D448DB149D418BB2584B924D418B924D412F9A648144FAAE114E8A2ED51D8A4641D2E4AD6C54B96C54A17CCACF49164C5B291F648121F4954288E24870E ++:80B30000341D4C8F447881B44AB385F44A324B4A8B1443BA4AB1A414BAA694124F8AF184FD00800400400100002800000000210000000000008480040000000080020000005012F0D29EE06874240116286223814781E45681C41884428450844368414B21111841288082018A214481083014511C9122244811602136B211C4622C024633 ++:80B38000954A0012C8818923E4C854284F534302821568488C44684428902816888201F04C2111141C481108124890443424114120C24C48241004163411181E44856444808181918A1164422132128240014F6609616644E1C1B44892384934146456911C1E28832244689254444F183134A418492107CA2241C2914614B1815284428901 ++:80B4000011E1448142E21134119018499542498231324394483042128AC118AC82F4884516FA2AE5C04211818800A18C12C828428001904481130811140000411421000042401416116241004B14442332114E1228241788251144024A029800D0C70E0000801208002115080043020041000010040022004448800400008128C024230467 ++:80B480008084012909009800D07A0110044410051D242D11499218C01848001180912816C128442A042229110442219012C014182544C224482624041A04004A01294414085028904C44F0637B004400C0218149C21128A194844230241400451801442280321244A0424002200121C0244228832482C52423041A044A418409403882466E ++:80B5000018049F930A001004414011122401120000808122C128800444000021901442444A11440240040000004602248400201104F0245C00008410280443C14182000041180089041008004044048112224084221104000080418201008012C28281818281F0EFD124400280210114000040810441200A51181048020080020044400446 ++:80B58000008902288501200C00800838001004287DF22002000044004008502800304881000000508420410400004022029022800121220000801108120020B8B14102244088311843044C91418100150841448364828480014002C141124484180041281632240020D2184122612212000026B218022781818881D0590222000000110018 ++:80B600008800304280018848541048080040240280120441007028820200A0840000821880081004A23FF6080000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F80040000004004280000000021800188000040014008481F ++:80B68000000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000045 ++:80B70000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000006B ++:80B780000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000010140100000000000000000000000000F0481E00412885621181120000B9 ++:80B800008114C01483011822400811141009524100000010043081100480881202002008200800E0F60D142001200420220C4602830D1004304122188904004A120160824C2264412002602200114260841484301816A64128818442412024F8A44F008053281641280120048944B1484134184400488C826194115081A041003024000014 ++:80B880004460221110240490212110084AA18281A0480080F8FAD5404104004800228200218218001228110000004A12410489024249012200800814008E484008126C010081400442F05C7B6022448901211141200422840085042880322440384851811088846282859444838824010084811D24A0488384E2242189011416088A941859 ++:80B900002AE4440810F4CCDC20642143024B2442E0C2E442914189A41E184D48235849146AD8483441C32222824245E4144241442526A942444014348443B82464244F3A61812CC21CAB2848149698C2883E842981AC818323A881C2BF94034A028942322410C4484C8214E8880481A18511210C1B4284222811148024445414684A0141CD ++:80B9800010049084412419A881D02A311858D02888042223C8C85A688A8288F0671340C2142D1420344130244A4121A62112499484412828CB24412644984843421C9429142226584849B8482A2401444948B84862563636488B244CE22C22C811128661894B815218221E4480B184F456D57011E81204144130422220064C41C18449247F ++:80BA00008204268105002AC4881857882AA44A2688384CAE4146084845684660255485A2124828124CC2C22A945420028E6848B048088197D4400CE0419442004100C04D220000488822400A0049A118182441804101228884601480824A0141248505228082081220213212F0813B80D4425141001008480028211008101C040060180095 ++:80BA80000084408112042002912C0281411009000081805424800218C4D0D50C552242441744C248268424048C1113C44C28D04824880184601E81444581E4284698814B2549688480424458215845E1421843092C619230424D18222A4C8288022A9918846A065817411412420000289061200820045CA24200008830182A11382440A811 ++:80BB00002480820C471228248C12A821424C02A084200410B4488384C14844F0182310C122000028004842221004411302C0648501114C228414E148028544081A4408E014018149724259822412153424C018403842610088C490348E129FBD0D2481162821210483914C202841081C282118CC48830828008400804862224A4984C26468 ++:80BB8000C888A02848184C1121848828021819C884184981B824058044F4B3BF80840100131288024281008141228C82482184028488008488C02110180811828450948448884484281A0248120089086189881104F0E9C94014459425301862004140041183641844220088438C9818C0884AC818005C094219880443C25418902442722A ++:80BC0000114281182A1825810B281E48308E2E488CB828F4915A148A3428102422024C0444A866480884848012014444288C164104221490284840140120084224006789281618081450248483285242214440F14A9410C241488714521481C0648284001DA40094004148424890484222904842484342810241800647181014817414686C ++:80BC800024C6D284344491812081014A6184412AF83AE1C021121301841220028C03001819A8246081833A98004B81128222880088A081185860824B4880C2228BA12A7188040028188124222226A4486222AAA1424CF4BD663026415382810200818480942481601420880490A8448210518140081C044548A492494441814448C14918D7 ++:80BD00001183018B1840E841C8182284612588823918F04FB3401882A42400484222884A422CA82842840022222A0C29026081A881488B124951941C824164822AB1A8C4918841A26220044684A824001A88688280082948F83F791427241799B028912895816681464438488B422259D818E48218EC48EB9284B428B844B621B4980B49A9 ++:80BD8000C4418DA8E082D44A94324D4491AE4443FCD1348674357945D4A162CD8E768759CD448AB348B2C8528889E86242C8886F8364A98BC33A7894A1E48FA844C26147443F81D14524A612624A926CCB348C62818885D884C8458E218528A436E08AD8844294881F863821A644D91CE2167854A4258A2144D41464138AF7A8228F1451D5 ++:80BE00001ED334418C7218A8416B411D111771CB51AF42B9A8F348144BC265C84C6E24C76ADFCE025742AB3247525E211AA16185E84264828EC4AAAC2485EC5831C19B2517822299FA8C8C5B6C448E942E484E4989D18822B148AC185F81F389C88D184F43F615212ABE2898A889C8C86F4BA4F236D182E51F61462F8AC9984F45E488F1E0 ++:80BE800082889A7214E628FA4A248E34CB3C8DD88CF1A65B00000000188001188218C01480218801890120082005100688429800100488102401840044480000004624A124474E145F717566FE1F2DCFC1A5559F95F32949CD148F87B794F99C988AEB81F194148B9D5F52F3343D3AF37131628F81A11185A86715F185157E597EF81F9F20 ++:80BF0000FEE5DB7F39B9DBEDCFEF9BFC21416AF6E5294FDAFAA5C58F84FC1A7FBF9FF7A9BC1F9B8BF948EAA3F4188855F5D1C32F44F48E8EED8A2F2EFD66922F85FD6478CF81FD584EDFF149F373722F22F613311AF158781F15F36969CF46F3583C4F44DA48A8B83E3C828B8CEEF88F89A9A21F1EAE138FA3F1F6144F4CB472FE81815FBD ++:80BF8000D3E612F228A89F9FFEACFAFFB9F9FEFDCFCBFFB8D8DFDAFCE4645FDAE218AA8A6EEAAFB5F57B598F8BEB86D388F858FE2F2CBC3A5E5D8F8DFE4ADCEFE8D926F8F2D26F24F5B2B2EFCDFD24D46F64F55BD5341F21F5165437115D154AF578389F95F55C4C6E7485F4C8CC5AB2885B4C9B44DF5DFC84BD9F12FAE1A14F47F34C4C50 ++:80C00000EF46FC18188F86FFE9E1DF547C2959881F1FFEECDA5F7AFDD4D58FC3F778781F9BFDA1655F53F7351D57528FA5F5DBFFBF9BF6B9EE7FDFEF8EFFC8CEABBE8ABB85F9CD92EF4FF2BEBEABA34ED2AFA7BD52BDF2BE94FDACFE4FAC43F373763F43F31B1D9FD1F168787AF35979CFC7F6483C8F45B3887818F88CB8DFD9F1CDC5DF45 ++:80C08000DFFE8C9D9F13F9E1E12E28CFC7BFEEFCD4D28F86FFE9E1DFD6F669698F8DF57969CFA2F77DFFCFC7FFFCFC8F8FFFF1FD5F5CF6BDB55F58F8A5858FA7FFFBFF3F1FFFF9FE7FD7F2B4BC8FAFFFFAFAAF89FB9D98CFADF9D684EFEBB9BEEA2FFF747AAF8BFBBEBC4FEBFC646EDF890518B02201802442284208842008824088024C27 ++:80C100002208200489028B24208419981400C011B0240945024D8182262201860816C82416C826128D24B04802CFC80D4388424124024E118441286A880286E8445885281302824449A424261838216082425D888A52821E248442148E248551414E821781A322981812818E6842C015222522028C84B184A4144738CF590A2CF5112485A0 ++:80C18000F2112483F41124A3F41124AB141F41B64AB991B24A3915AB9443F34A9543F342955F83D412F935481CF9244A5CF8244A56F1245A96F5245A96D5A2E449C24A1F49C2421F49522C1F4932481F49324E1F49B24AD141F24A911D28AB9451AF443924AB9443B24279A4B842F934484E944FA2F435B1C0521FC1D628C42C8F14F1113D ++:80C200002CE39421A11D64AF44D841B2429A24AF143824AF5428525A5F8294827B422D815FA245E4A26D541FA268584F8264592D4BDE25267A11CC421FC9F62C421B2987241F41B24CB881366A1D642F54D9C1B24A9B21AD844B4AAB1443BA4271A4B8427126F842844FAAB1740C28800400001008000000002008001880080000000080C6 ++:80C28000040000000000000000002128FFC40C48901A2601128484A058228A938846282422EC1295C82814178185D18184D2412244898898CC40A2A12888431214E954084D884EA4178221811EC21460244810088400C2A86F240861431A11362227441B214F119248E3F24882114827189414C484418D1528868406548426041446D12128 ++:80C30000E28804C1644C12B121C884225522418151251B28148CD4282858248301B24723124C792449F4A9A710C624259B6180C4391F8281C46449C291229314611283CC498C7C2144F31481111618F18C212830811CF829C49348227A2824E254524187184B4A74C42E451D3845D114E815386286B88274449218811AC21A2443D148BEDC ++:80C3800034F8D6BC8004184427221604448562898F2488F24882828304443244168842B84892414C02465481800429044D189086A082441480294802A30285012400803824188200AFDD0B2D111D2414304810C86881848F12288961888182A151AD942244414480825418225081C2000022501400000070280225224803A04818B24A6AD6 ++:80C400008242416F5D014B24211A024D21A3952111424B144284941C11E5457214A21846F141841CD21894484669CC941AC4488D4112E3E22AA5188B128846B114084D813E4A47232E4283E629B48133118321CC41188B85837212D2A40630848F49A2844FA248C244251501854238211481CC94E1109881542225F482111EC85948D4811D ++:80C48000C444894414B1486184943CE1CC8228A81282481260482C2191428B24582912711288BC8304C28121CB61828AD248B824A548CF460F198322035CA614814E284212818B8119C118814E9489512451621C124418618E8344218244081E621284C0214C1815B128C4242602821E8189032160112781224A19323248228C48F43D4AF7 ++:80C50000D08492464062412AD182041146045D486A810523147454CA212C0430144E812A240481142015841288424408430540A2421422AF29562196D412218292940045024A82C242AFC8068CA14190254E2881282842283024224D8111143830888150A419020082400C8810011524162422AC1485010000CC0281324E848480A6822CD2 ++:80C58000844804875700606118001245C222A021002041424881614222800444815122888454286048901210018443638A14821880088240982270140286180841AF494CE121C214642CD24874288293243CC224388F14024F115C211C648387218F18C36A10C8454621221484D25848E848614290845D225A0230148C353D836A1419A8A9 ++:80C600001229762278926299124E2CEB21E061248A846A4246F416D610041817412A213148304248004A011850425904412841388246444841086014804248184464128200242800893981002088082841A9C84800EFDA0C1724174150294848850246C1C812232A1418E88826229864C219358828190A220040A2242781181B8466455193 ++:80C6800041868C622822002ACC41C083289821E229381818298804899188CF8D084312084410942419128C4191181502808111681126C2242A048410D4484261221412248042724408219944042552181125BC18021341994100288B82008820F2D8BD00404818C74140481404204328047018048100C0442004841904B0419224242002C4 ++:80C700004184203128608100328618C281252471180281121A2A089B7A10C428111883A2211A140426411449E224824192212C4212041001414061421290210011121229863412255441C022201202008301813028322B8248C04277FFA0692AC412400210044A581850418882818948062448408108832212618813C811822D882E14A288 ++:80C7800040245843A6A2818622382426A4122F840812425880022100281CF2D73A14151A81C641409845808282883888A0126A0988A88C08C82A3C634833048C122432C8407482B84481AC2828381240D18131812F210415621886022243830882290192922FA10B00212884448C827441D24881C214E021D2844411312185911422508233 ++:80C80000842200442818B0164441023542180A20120848501828006048810022421008BF3C0D6021841844941884818001124F112402901230321428400441004C254448080010012426483452128C114182C11A80C81244881818228428F0319C6081442E5144141811130614702124841A51211211181198304AC0B111199842148B18FC ++:80C8800021821E21290186086882406118248021440C192211A2822048C8884A1362842F424EA141FF28C133C553411752126E411D28CFC1F111161F19E121B48191948F88C4A243CA9EDB895A29D8283E28C8842641F1C1492CFD83118755B6F851842C41C14426DC58D64EF28116308AF81FA1F148281F23B112CA82F036D2A93A88A2DA ++:80C900002A98621AF488895E88BF320B1F24629323E2C4D28AA215CD2D4D288F54F421E1A82EA8CF14FA528827913E3233D2E8B113F4223623826A124EE82E211B629962423E14279B8F83A6182D24ACB394E428D637728662A386F224218F984373D37C66F42212CEA11D182B191EDACA32148CEA21F89A2A83A2881AE228F4B6E5F02410 ++:80C98000154E2497811B114D41ED481F26554941235C188119D12CB468F641818F11F111A12E218CD451B668744178855524475444FD68491261242DEA4D12271A2F56B25738A889BA83A18323F143821F837128C36113518A87381579C341E4CAE123D18883A19D6E382AB128F275C4200490168C342210421822182208822008824C2299 ++:80CA00008822684486424412881888288418A88242888449082A488888240222822008842880228802428F1D0A485795DD249D615FA6F66B772F15F76343F7E4E5579BBD81B7F6EFF4F54537BF32D88AF12A8261FFF2F82E698F845E117FE2F46E4C5F46549F2FA4FE59582F24F412496F62F62E2E27284F72FC16555FF6F22A2A3FB2E63D ++:80CA800021F11E3FBF97F7232A272CEF46F251733F2474925229AFA4F7EABA8F8AFB88888F2AF822B2ABB24AB468BC3AE8CA49C1425F73F61F259F12F24E4CCFD5F55C7DFD4FF7D45F9EF71D1DBD19BFB5F7C25BFFF4F12B63AF83732BDA8F722DFD6C7BAF84F64941BFBBF36F4F7F4EDD9FF266EF5F51F543C23FB3F12FEF2F23D266F29C ++:80CB00003F1F7F57F3256D8FC2FA31311E92EFD3F35BDBB5FB1253FD27FFF4F42B2B2F7B7A8BF3DADBEFAEF5AEBC8BA88FABF92222AF23BF32FF58D8AFA2F1EBA9E043F735758D323F31F36D6DDFD7F758739F54B66BF629B99FF9F929B39FBDFB4E8FDFDDFC3193AFA8F92EA66B9C6F76F8C6C52BE41F98F825DCCFECFC238457624FA6DA ++:80CB8000B6E1FEDA4A2F39FCBE6D6F6A7A8EFEB6FE2F4BF7A5E7EF2AF2B7B7BE36AFF9FADB533F29F9CA1AAB368FE4F763F2AF88F319822F24FDE2E2ABB28B9B8FABF92AAAABA22B3A6AFD48D84FF20E5E727F71F21B2B3FB3F3276FFF53F7586B1F54F6636ABF9AFB999F9FB8F9D8DB2FBCF9DDDD1F3AFEBA9BFFEAFBCFBB6F7EF9E6F593 ++:80CC00002BEE1FBEFCE5FFFFDEFC71C45F72F2E46B9F99FDDBCA3F3FF9DEDFEFEBFA9EAE7FFBFFF3F5DF5AFA8EAE7F7BFB9696FFFBFADBDBBFB9F9EAFBFF55F35B57BF13FB9EB997392F3DFDF6E6EFCBBBA8FBA818AFABB3FABDE2FE58DA8FAEF6555EA0124041F824134826437824A34120414148072C6281811B41460481114E24218179 ++:80CC8000A024298192123022C0110090144021210214864802A041002800128182CF7A0F471812C0244E11C44F140181682641582A48188CC4312254499422A02441284B42142146054651821A02463422442184C024AF221151284CA41419D22261812D81A2218688618329C848A81C748C022CF41124C5F211248B161FC1364A1D24ABC3 ++:80CD0000141D2CAB9419B24A19B54A3924AF1439242F147924D852FB25484EB14FA2C4854FA27418F5254A96F1214AD6C54ADE242E4A1F4DC2421F4952381FC97268F19124A3F4812CAF16D141B66AB981F24A9153F84A9143F24A9247822BB4478A29FB24484AFBA44ABD17001FC1964A19921A1F4136481D244AF18164AF44B181B24A58 ++:80CD800033852B14AAF4481143EA1461888D116B4A4AF1A45A8D152AFC58814F2234582E8A56D4B4B858E2A27851ECA2EC41B624ECC1A28617C129C86CAB961D44AF466948AB344B282B1426F842B645A8B4478829F3864829FBA41A7F660F480000000000000000000010021880080000140000000000100444000000000000AFC403451F ++:80CE000082822252124AD1141564444142888441C389A1481116C48C1266AC382840781491412F442194444084BA24159111443039124E88D0A12A74288252831425F284184624A158A28C882414F4A785206119818CC16834B0239418588420D8128494452A91C811467345284808152846021C728459818E2868004A1132282C11447E6B ++:80CE8000213421444D212B4913AC1C2998812CB288A18227828422881621F4C454C0164E318183D381643415742661414B144528382854CB484CA168137811D421D82194C8823291A241139451C6C4441DA846E418325813B14211083885E284C22155F846216F897261E2A38C788252A4C90189BB2868A8421A64453F8D040022302212AD ++:80CF00004A81344820042C88849141188C044D488D14439238008C641125C22415581880024C8214312412E561414D81A082602482141114B24A283B42802208F0C9684002002212204101189230811420D484044B4A4282421100283114208438186049221A1282120422482724481C2108842C084A0318003242848E8F304217222E1D0A ++:80CF8000C5E18114E48254844F81B645D883326899D482C1C89D942684C865142A91553248484F12041AE24214546816E84452823C24183114889C7A14217832213A992AE81241897911A4C32C887A442234B48CB88832849DA700205384830248896145C899C288871433F848811CB844C288684CAC1219AD4220144182C341C04296D846 ++:80D0000028012C2C7A11C2144031142CB211A26856B181321185A18115A621CA02448083AA84F09EF790422D21A545216541894294295429A134608160C130441534214241181304668412614244850443167811042880CAAC14824825928818A24088A9482CA1822C25C4841698284D885F5705B44C74187418820141610018442218A03E ++:80D0800018E064420119C12287424603441822111082541280422562112B246904442541487412821892448B4266C4C420040040F49A94E0C28424822284A142141304903413028413820912250424002AC81114A048A0282245618813811C1428A4214D1188448822441C22B12208C0228942048A82A412ACF83E32104202004501222582 ++:80D100001834888934828988414408004918941180046044214344C1148042028028012522210223110182140018B028898891A84C84F4D5E22419048392384AC11528241C1494981E28888B188C614B1E884E241721448249D21C32412B84411C61423B484829EA4611C4A81C91C5448D813249D124E121088C3822163221211CC44826F1 ++:80D18000C4F4A1CBA188B84E284B418F24F828A37024429416100247241D248100482501100110025C01188012014810444102C0282588C21270621211D44102165412822C398480042242008228419F9A0514448445813135891422A4C14D881444118129E4148122A4C3C691418631C2480080881221040082228C2884C811882A088869 ++:80D200002B211032C225C24424828E42808104423F930B43114181A224103214AC4128A2841E828846C495C0C44B81548028410122811D444326897A13644A218749131228B112E244624C211426312513E84804001A2A38244B12C934242E8C1889F8FCE820A42100A12041011562141A8254249226110820088A02281328C411A0214A35 ++:80D28000981228211A44D184A481D0810800302620842201429012100222886022DB3F201202299131008C12624818008A018088081418101224042013052844162122221884044428D60218814114C244821800412D22430888F08DFB60282E53180083843441208491412661144AC158421E488218208514014812800848880010511481 ++:80D30000200312C01425082906618681082192A01821852488E89E061781C041484412140023216822902226C182B2800282111C084111271242292541028E2280C8288CA969341621982242824C11812AC16418214BA4308222842812D06E4E221494244C033512D46281C32A89D2828811441402444931242742222A21C828602417427B ++:80D3800085C222874180318843471802802844244281C88A184603C0841092488084C5288D429FA805001A522246726418C9484800A1C621114128C228172280012A34248222281280848804144248422952824270142265441A02181F48022B24802201000018AF7E038C12C84481C100228C5241136441E024B22898248561114840214A ++:80D400001182C435E024081141482225255B81C422896428124468868119C1125480022812411843B88825712248F4766A141D235F1952853E21D0A656113F82F138225F49B833F158A88E131B181FBAF584591B8587818E141C37F31F12A2BC2E2122685AE511E7849844CAFA8271982F13989C48C3CA822B833BCCFE821E122F4DFD311E ++:80D480008183F922C41CF9A3C44AB442F51682321E822F2CA8882B444694882CF43AE9A05527821E224E183F64B2186124E084D512A7482F1AD541DC4288B2726A8A6AEA2626822969124C98C414157364E431A2171E5E6447214AA369536C412F89D3B1664349E14CF6212183D4746B2D3F217244C2842CA238CE922D144B612F42F4948A ++:80D50000B88F888FB3C4F8CE722443E264E1525166CF837561F51A4CCF75167248FA48AF1123F75443EF455849AD715F48F514815F4958144ABD11B4C7F4C12D66B22852235F4AE5283A2343F6A224867861ED72FA41B883B28891145CB42648F2863413D219A34A1E1177288AE84294264B28CCD12C73283434B6F818289F440810044178 ++:80D580008C14C4482248418C4482048C44D28184022411004411508228252844088440211402802482242241210192200812289214102829F4FB8E343F51F7543E6D3E7FD1F71971DF31F17979DF51F15F1DAF24F2DF39AB353F5F5833BF15931AE754CF13F175514F46F644471F17A5772F42F6E8A91D63872289E413F73C3EAFE5F15D86 ++:80D600007E6F69728CDD45C2643FD5F1381A3FB174677726F626646CF94252FD3EAFAEF722122F2958776F6DDD22F576D66D36EFC4F34CCC4F41F94C148B5D8F27D6334DF353576F627622FE151FDF75F27C3ECF43735D775FFF1A9AFF79FD38BA1F35DF33F88B938FB6FE5CF5CF91FB71F14F5FEF3DFD72F17AFF76F54F56FCC9F9BF116A ++:80D68000F43AD2F7FBEFEFF572566F7DFF96A6EFC1F38DEC1BE87FD9F7A81ABFBBF8E6166F6BFCF2B41F7DFBE3563F63FB6FFE3F33F9733277746F65FD96466F67FD96B6EFC4FB5C59CFE1F15E5C8BDCEF67F7323D346F51B514D571F317359FD5F57F37FFF6F63F35AFA5F14ABABFD5F9521B3F34F3C747BFDDF18B12BF9FFBDCD15F1ABA ++:80D70000FD67767F58FDF3F11F1EFF6574DF96F661E33FB5F12463AF9BFF94962F6DFC4643EFE193225FDDCB671F7BFD38B8BF11F875A76F4FF3A4641F78F1D172FD3D8FFFF353111BFD5F74E42DFD72722F2CFD2634CFCFFF7C7E4FCBFB5ECC8B198B7E1F6F49F376677F23D377F31436CFE5F17F3EEFE7F77F2FAFA5D5AAFD73FE9FBFF4 ++:80D78000FBD3D36F71F9CFDF9FBEF6FBF9CF91F3B5F17F76FE37F57E71FEF35F5EFFE5E59FB7FE53497F3BF5F7D7EFE7F7FAEE6F6EFCBEBE2BA85FDDF781635F7BFB38BABF9BFAF5376BEF7E741F7DF5D3763F59FBD99F3F34B9D1FE85872F25FDF6764F6FBEB6FB76F44F6FFDFEFCEFC5FF98824F6EF58D42D01201228434844D128422BF ++:80D8000092148C44017091C82484309128824211421128201424B4240141E0120988F02691E02229A1821226A349244844122C22C1266044928902FF190B8E421F4112487C2AD14134484CD218C144218AC2121B484CD18544F494484E21E054A2424E11824E2520A142542C88C282122A28541412C028C04423F21144811594921120289A ++:80D88000348421D0488994B88082F44DE6D024F41124C5F21124E3F4116CA3D6C1B64ED141B64AD981B64A9945AB945F82F44A914F82F442B157822D914F82C4915FA2C4854FA264114FA2E41DF2214A96C54ADE24ACF4D1244D431F4952281F4932681F49766AF19164EB141F41F24A911B29AB9453B84A3934AB9443BB427B24989A4F03 ++:80D900008BE444F9244AFFC2092CF4116889B411921C1FC116D8C1961A19D6629961A99B45AD925F82949A4F82F4429157824E916F82C4915FA2C5954F22EC11D826641C3F2261493CE45D42E2CDC2418AD638F59124811F49541A1F49B44AB111F64A951F88B24A3285A71443BA4AB894B44271A4989A2F8A14F2A41A9F6907000000006D ++:80D980000000000000000021800188000000008400000000004400000000002501EF2103544911420127172302174149B48145324810012B421304181398414684143441108191412C4144524810212139141418222814281C8C631C4842212964889AA2284B284281F0459C24488601B01104C421812284850119C94846412D025984943B ++:80DA000024822824223682D22104C82C6D42C04442C02424422651413C813384166284123447183094244887241345E4116842FFFF4AC241461112A1411B2449021D1C2E444F9C51382688D88124946C429041C63324C6244334E332224641817D91C62681C1132445242114C12417223243F2154289E25284F44186B0127888A22D46F225 ++:80DA800051224C7418E141F23443106441003412A502000042130111253121301490418004003112290429044142002A4954121A4221412188A841981121604400A6C88480088B3B2002A021811932484800872282108441981222281228114284851104841A02D084042A28A5424400188C6222480042486088AD82104288428822A884EA ++:80DB000084CF5345210184E11AC2482213C244837452314116E8116C981B94141BC1845C8E848C4A8444F822414D21D4881F862808898422C111E0411225447111A8818398292371917812048C68812962494D41C2818382F8ABA21422400289B249B248822684B421A484D0141C681119A181224B43688E418A140C4442449302A2490488 ++:80DB8000CA02504120921426C8211384C1883C021592982C0818268848A48286B8284CF859D62001811E2C1200144481A951128921C1918E4A6016841C0880028714842D212669418246698810A8615A22014341814432188830485889495482835882214B121D484200884F910846E82184024C0485222231418841821884124811004BF0 ++:80DC0000428CF314412714324581B5480250424361918301A440220C1BC38628621630822558222280FC844841A21E888C81084813018148814112122521744104702401612A6412842068448842D082828C211A348412904811001D483018478642C014400400A024002A0120140210F27C9B14130210011144112022018448160222425D ++:80DC80000000840010032289928100498882021908180010D28421018485041220250149222414F8E74C141B2418A952144CC513C123E641A424121942985485C2218C32418820A81617C59CA6C26419756834A48B213378482461499041218B812D24421AB21468224E25C371825228816304988E1844828F24014242817EFB0000004074 ++:80DD000011411181082C084A21210490444E24840010810200441881842822406188181B48810080014008484E241A8423D8482308487F5203226238118004460810447881048188124E8180822684488898414222843C820412802204118146188834421A3C5814161261191082A82128123058244AF838491034148490682219041128E8 ++:80DD8000C01148B041C8152646484144441181A44280021322681146581212001528881E013018C021908942813142412420089088F017CA800426050011146829282481031321B3849411A888222A51282624021D280039041180812818581800205818008904858181CC144281285082214881DF3E4E011448441021A22400801A34417C ++:80DE0000502817A28140C2C20000807442884108C0412F881442189242254101814A18EA64880888104102218882C84308417F260D820022484088018B128C0183C618221400190110038880041A44E828748122281801402139188481482592484062182C890882A90148812120011FF601281250812814248C2241A182841414C8881235 ++:80DE80002C2868218A31282B87220012B04108224081A2854A218124A8181F28814121281168818184526508D22001434182E423044084018446082084C44320E128026502003141884041031088331812182781461842190225022304182C421801402208C8002188482184DF8D084222800422621281160811408801152831288C01D8B8 ++:80DF00001982048C02388042123948A6A14212822A3121126081882222180010E881088200184041E48D0A94C04881248410018819E24826A885848B248828244B8211704238888A011D88802421A25814405182488904C220081244246424280020824981042B4824FD1E80A26B845944628283E293C211DE8819F112F91BC18F8CE884B9 ++:80DF8000B4B8F1A18913C18227218ABA32B64842E432D881F44142183E1113F2B2229CB512A155A018848D111AA698B3B1C89982A9E893788129C1199E132D418F298538722AEB9188BC1CE81814F2D4BB144B424CA1239CE284B24996218B4468224893FA64141B51BB114D23AD242BC23B2ADCFB4452948E528F8C82022AF228481FACE0 ++:80E00000F4D88A119E8287AC8E833BA65E4296E32A782B32114216F851436E18AF2485D49299422D88994134C82C2B88B18291523C51884FD7034651149D14818B42144E41393148B9F368A5F0882114AE813DCC4F21F588198D11437A22B5C1F921892EC1C26287915A92281CE714314B489F82A24931B37411E898F8484986D822F4883D ++:80E08000189AD644D2287189F2898281CE826D882D5483287482628446B448F8C446CFC3024200438214421862812116186281218C041AC422122001124224282C018842888019A81242988001180000922009122089220912811281EF52085F54E4C752445D452C58311F16F661523F36F6EAF26F1EFE61722F65B543FC416B6F46F7B1FB ++:80E10000B63D1335DBD9E124DC88956177716D249FA47542FA12C81D43355BBB9D485E922F27D639F213411734B7919FA2749A5A138F85FCC98B8F26744E579A95FBA98BBFB8F8D381CF2CADC48F86A6C68F98F8C8C8CFCCE88CF89C8E174BF045451FD1551115E12EE634F2612B3F24F463611F1EF6C1C73FB6FD6293BF14FCE94BEFF6DD ++:80E18000DF57D111F88189D7D81F1EFE48C91F98F8FDFF7F7AFACBD84AE4245E138FB45EBBADC91AE427F6A1EB29D491D4B878ABF3CA4B3F34B442F44343AF26F47E66E57419FB29AFBFA8F8CBA8EF2CFCC2C22F23B2E2FE98888E826F4DEC8CF8DCDEEF71477247F434441AF22121F063411F34D48BF579788B988FFDBDE3FBD8F89DCB44 ++:80E20000BDC9CF44B5D5FBE2333F9AD1DDA9D5AF8EFD21789F94CDC2BF92FE71517E481FBAFEE34BBFBEF8C2432F2DFDF2621FBFFB91C33F39FD9B291BB38F2DF413115EC89FBCF4ED6D5F54F4191D95FB99BBBFA8B8D3FD4CD6CED48F8EE6277F8AA89D6744CFC9F98C96CFF5497247F41D159F13F321218B663F16F269699FA6F77B7A9F ++:80E28000BF1EF7D9D99FB7F3DAF19F34FC8BDBEFF7FFDF953F37FBB3B9DD9D1F15FF78F91F9BFB697B3F1AFC39E91F37F7F262BF9BFAE9EBBFBFF8C2C22F2DFDF2FA1F3FEF21F49B93BFB9FAB3B3AFBDF4131B2B453F3CFCEFF7FF7FFF9B9D9FB9F91EBBBF21F9F9D8EF6DFDD2D62F2FF7F2F2BFA9B992F9D6D4CFCDFDCCD6CB316012005E ++:80E3000040426832480034408244A148E0881438814A024A128112022142118B24184200146012C08248E081E422083482140082400882422024F8EF7C1024110C800640A368228AC411909813C214112441904189282804142E4812254A01528428C8008414842C0846418C08248658184B48A3248208A1418918F4F8F1C0421F41722C36 ++:80E38000F3112487141F41364A1D24AB141D24AB941B21AF1419B54AF93548AF14B924F442B147822D915F82E414F9244A1CF8244A1E215FA2641D2E4A96D5A2F498242E5A1F4DC2421F4952281F497248F19124A7241F48B24AF18124AB941B68AB9459F44A9243FA4A9243BA427B24989A4F8294984FAAF4514740EA41D6282411F811C5 ++:80E400006423F4112C23F4112C2F44E881B6425B85ADB25F83D428B914F4428147832D817F83B442F8241A1CD9A4CC815FA225E5A268512DC81E252F82FDC12C29D5C196DA8E24AF14F18124AB141F48B248F1912425F4916C2B245F81B64A38B4833494284F8394826B4B884F2AF5292600820040080000002800000000218004880000B0 ++:80E48000400100000000000044000000000025018BC80041002D21372215023B14119B1448816021162431458810C81140081CC44814165218214D222065181100882852A88E214641082111348C4898188440A2243014F03F67142AE4386241144A28044D2880348283A2852F4138814E21875C21C126BB81C42899C4413D422818126BCC ++:80E50000824B241999421002421C69522E1246053D4824183CA458248C344419442264228C2884496194F052E380647C1850231B24159228196124CF1C312883CB141C39311D8617448217A28662921C34592D43E6818591A647943F21D82542C211871813B44199241A024E12871C1F280287144B81212F1234442F1844B2483128A908A4 ++:80E580002F24091C7112F2C8AF20821214210E21442314014846224892448B1450487048211108008111122302488004001482671620024E1130421018114808004828148744F05A920000121C11C1111028782822480224134242084100146014100810228148040080094A115122118882213042100800200A8240F86BF53042251414C5 ++:80E60000CC68188C344C23F4225996215381824D4847819D444A32194EB32661142AD441124429E2C11242593636E88124E146D8411A64C2821592841E212418629E23CE1116731132152C0A2C2AC11283323886045F234D821402C42E511981C448B0629981A8113044AB124619CA1116024246119444008D142424248C4888A128411020 ++:80E68000288871832213B18281CC8142130435042122202862888644F89DF40044441281D01841744218F928121885221858414462846E85134221C2211485912822219117412AC15490441B8244490B1C14542100282D32199912271189A1822098122E128132005FD24122A4121826210411296284A30267120000924E288CA8411901E2 ++:80E70000502A1A42D1818442082D1181147248C9411465942306422236092C71445828208248880164800246F87151C02840040048100192472414E022044904144425AC188F113622888C2101A2834484141124621484A024818052494848934824989822004A28CA2826081221BF9F011004182A51828901224122124051811440418615 ++:80E780000200484688C224211601A0212A0100208801418A813482003821801108228301488308F05898A0421E24182E1162A11E4A282E424D28822E1211149724301428199842F301918B246AC828DB1621928439E184021A82D441159484368912A469622F1205248B12232821618881B0287128261408F026B81002418001145018E00B ++:80E800002291410010A1841D4885343420A93424811120D218824484A1214984024001A30450C18988D418895428860800BA840889228AC1486F3E03582800002860448004863418862801005A2A284101486015422926042A81E41883A4181E848A62121828188CC82142282B14192124210480842C91A2003F9A47222211243114232133 ++:80E880001131282882000088224C0C30422A084051144143126141802408C38842C81288443088001DA260324648220642824B121800272A41D71100303451486084802214A14A481A0883212C823C121423250860244484402288C1244C011819420418860634A8A08180CA11A82722242A014488884242FF854301111128C3714532117F ++:80E900002A91144D11181534191119C4A4448814848008222A0800882A1894218066124904284140218822842804C0280022442928082082F2334620AC120048203241C0842A044C848409E014C281A04A2800C84041984120188889C484682A0844E0181248282422840942214A2288222221818218F22B21801201405281448C029412A0 ++:80E9800011D081420880214292141064824125A3142531A216022308143880847C823224200711124358411B81A0812480289142860820782F4702005902220052004C010043942144416A08209282144180032624024488202881A12488212128002302488A22040043180800625F960C001621413818D442848E281CA8482E89821417B6 ++:80EA0000829813E1210243222481982623041418212E151C6812000000C01440822821A18220018228272100840049F86B9E1484412A041094428D1480013624912448424C0446144411D4161884018858E0140840011484904412230A3081100144B081020041482440180267B214489635141887818D318FC1B448F41C14CB821D811C8E ++:80EA8000B9AC711839889E48AE44384D511632A29245A4A85F3448E4447419B2532811B4A1B344C8341F45C8142A4A52162AB916E285C88228F82F22E3286E148BD96AA14822BEA42B192B442B91A08267426F964292221B222E315CB24455416E312E2C6E281FCCA22D1B2D5EC153E894F449A44D813E81AEA2EB885F54BD6678817124CA ++:80EB0000A84A7F2454244E282E617F6AE879EA1428B381649AC84911E441D24642225899EE8111439D119A7741B282F862228845E246C41887888E288AA6ECFFAC016A815141534376561AF71111481E11582A54C14A99914B124AF3C54417446A8782E72249C224143F11E15225A8742362818E247E8149A22FD6E94BEB2E28F9A185A963 ++:80EB8000A32A39643BC836D18148A161D022961249EA49082B822424DF180120024342184438241638241222846081441228124C22E144224104460428184218800118100418800100200148A041002081028160449FE74252115FD1D351F115115F35F539337F11F329613E24DB664B451F16DA515818DFD4FE21245F167E2474B4B122F8 ++:80EC0000F821A74215F11B2B3F18DE76D59EF468691CF122615F725A8B4F4EA44C1F1CF4E4644FCE62286F2274827692F6CB419F2AF2E3423F12A7CC3F14B76251312F21B322AAA82AFA72F2AFA6B2A2A2224AB4649452F061215FD656555D559F95F5797BBD189F97F73C3CDFDBE359F141819FD2FA5949DD8D5FCDF2A5255F42DA75F810 ++:80EC800032223F1ABE92F4A1A59FB1FB23A54F2CF94F4FAF867C61F1E2A15F5AF288194F4CAC54DF5CFE4474CFCACE246F6239824DA6BF947489FBC2423F19FDF4D43B75BD789FB9FCD2D22F22FEA2A26F43FA76D48FA7FFAAA22B28CAFC74546FC448F171315F41F715154F417319FB3B33FFD1F32935CFC7F76DF49E946E219F9C7689BE ++:80ED0000F1DD5DDF42F275F54F46F9BC9DF7B27F53F567E55F51F92C3E7D656DC72F74F46A6B2F39F9B2673F735BDE4F457564F4755D681D6115F7A3273F19F19517BFBCF5AB223F26F663F33F55FD63312BB51D133F1DA9A6AAFA24142F27FD4ACAAD88AF82A2444F66F5ED75141F17F33D751F51B144711DF9796BFFD2F33D3D8FC7F7B7 ++:80ED80003D99FEF11F16FACDF99F9DFDDDDD9FCDF9F5B15F46FB7DFFFFFFFBB7F55F1BF7B5B5CFAAFBA7E55EC67F75F4EA6A3F3FFFF2437F7BFB9E9C4F4DAD9F5FDFFF94F4DF59FA81A73F7BFB93115F7BFBEB7BBF3AFA63E33F37F773553B37BF85F559DB3F35FD22E22F2ABAB6B1F6FD58CAAD882F8AAA8A4F66F5A465C0115014808187 ++:80EE00008481342448228A44A14814134824488604823081427048040010042A08883024F02282E012083CA848200882200882448A048022F84DFB20982122503C11830289011C098911314880B22104D012AA4214800216312182488E2522426044489604100440581219A4161B484A014E1122219012901282D014F43A36F022421F418E ++:80EE8000722CF21124C3F4112CA3F6112CEF16F1112CAF169921AB9455B84A7924F84A9553F242B147822F14FB24481CFB244A4E815FA264515FA2E45DE2A2645DACE449C24A1F49D234F4912485F2912483F49124A3F48124AB141F41F24A9219F24A935F81B44AB924F44A924B432B9447822D944F82A4944FA2F45D11F0224A19F428D7 ++:80EF00004213217611386216B8626181AF4619B142FB15282B8436F84A8153B14A6A812F147A12D81AEAA2E514F923C81AD8A7A42C2F8275C8D5A2E158C25A8E2C4D5B1B498D421F48B248F18124A9F18164AB141741AF44C8244EB15F8194A84B42AB944B414A38242D946B424AE922F13CC4008004000000000000000000210080080086 ++:80EF800000140084400100000000800220080000A1F06B68800541601289012644084A8202002921142201284C24618241101802A6018032225B2100441113440310151302828810289814411008A0426B7E14227B1894212D5C253149312A04912058438E54289D1484974C14138812918437289B24174287122328D1832AC28485C4829C ++:80F00000200288E04278113428122A2CC221138111A328848B8283394A9A62429E41C4676C80F1421400ED6193314825C168702429221AE2218492412538CD1117284C62118F497283F482688722993282A693A11992A4A7524C0A66081C98411F62482592153B82411CB231285812892A78B8349C42A44C82791AF6FFDAA04211C5032C8E ++:80F0800001144C02200410C584128D148001284800104105801108001311024100804108482302200110082484B820A4429FA704189012601211410060221188121843D8420128481CCA48812A44114491441284100424201211444412A11210A82814002004218230A44C82F4481448594B91264302D08418BA62D892341819042400D0FD ++:80F1000083022F44D88574814444654644494431522B215B4213716CB11282441414A3128C01492CC2491C8416A8421C9413820028168291181A180883E23C0D284412205A234A58831618810280419288274140B1446842518F42942414144622625214283848412190214941C4C222203448821992411301002188214C3124848CA5428A ++:80F180006F7646C214260250C1844382044810938280912570C2C46C141CC848803444412711492535184D49250450241C82110841112E5911288C224402824220228131A81A88445428EFC2479245841121C01181456124221B826200223018431408824A2814CA4248422810C818C0838C021B8460244460514823121C144301212229DE ++:80F20000348524100C21488B421FED0B70128A9264101244081044085C6162224A02181880439562406819250442482C5214522601890242008214004849126218224782004100299814F0A72B000090680080028160A14884412140A1244484181482142034822886210420241116A112126281D022069628E484180882871649024829B5 ++:80F28000C8288C02EF670235C212284C7248C21185548448228B2826C812588447228336448C8121B8486915288E421D481D524C1692289B814AC2866698211381024C21E11582C8218902AB581C32C8A718B084D2849224416C2498A8853428DF770449043420021061224081141845061840A1424422441D480000824842248021C4C2AF ++:80F300004434284074480267244414482140C2484A082184004A83B4C106206481222242A014802402220020048D148914E854924522100560822618042220830260121CC241142868C8142C082144881280D8240200F017470084241602008082A21448805828422260144CC22184288C84842483941229642186081388A44828A11287F3 ++:80F380002C818308812D224612314830482481800230248642F4AEBF10923121158414011922110111102164881341140444A012411011011004611604145C98150020521211211194421241446068444C41480426CC42AE9D6094250410D848724201604425C1224A11B42291242110A2841229118408892252423424A05A25410A20C44A ++:80F40000424182444084818809402298844042228848088CD19C0700845022428984022100400224141884321881819041811528C3441008802202504245180140082528C828400B4782128422418084053FE70A108413082422242841212D82881E84862184C882884189B8818458488948048524024318788A6328C6A54225E4A221E833 ++:80F480004224688A209241848266081E88588410081A120881AFAB081002A082C01218122006110029A121482C128806522200232524A12121804208120000484C042904298601298C0229221A428268488249F89F67308492302283648218414518022242C02C60844A8804C084908284210000121485041845A12141629025414C1288BE ++:80F500000283A118448044B614D848885A482A4881FA6C726084282E411814182C024681032D948087B138086B121CC392422A511A1C94162AB44C98125CE4145118436131726081113A74113814805281006064E08428460884161289022B24487E4E342CE4391348F142485E4B8B422D712F16E2115621253311348B222FA2E321321490 ++:80F580006B452FC1F319281F4286D388D698E462942827875F64E24333148D18259A126E45542E6187821664241D6387842CE284A66CA728DE718FA1F146428F84F184868D1847212FA252492983F8E45129E4670D4147482CF11412AE212831444D1265A427E890941ED48F4594C18AAC22424B944F18B8447CA684F84F211E4B45B43865 ++:80F6000051282F18B117BA88C1A91B1857261E1463B1A6F52149C4571A4742A3437111094244A0442748274A86D486D248F8AC2C9CD28CF857B930412F82E493B22A12382E5E32328361262924BB42EE4954A38AF86A116E169D9DCBCA2B42AF857139FD41824644F86114582D413B44856E6C4F43F2A8422B219A5F256CD399F284B443D2 ++:80F68000CEA49549F22B824ADEA8B822FC89886F4AFE281847238D88CB91AE82438A84E84EF1F1E21001119041181124112211221308822882A0488D22822813088228314A1212880888802814021C48D812082148000000208802000028A7BC141F57F7353D9D1A85F9E823BF32F22A584F72F34C3D5F51A3153F147421F346423F34F7B1 ++:80F7000068429F9AE126F32B292AE226F62C488F8C55BADFB6762EFA724B2F267E5B7B4AF93F3DBFA3F326B86E436F66BE63F47325A7A3B97428F82B2EAFA6F62B296AE41EFC88C829F42AC89DCD8FA9FB5E5AAB11C7886FABFA2623AB138F8CA41167658D43E067F3676595CA212FB67263D39BF42427CFD6F615355F55B1C2C6267F3DF6 ++:80F78000F45A42AF26F72B194F6EF76B59CFC3E6AFF676659F96E7B1F5E5636F1AFF72496FE67F4FFB5A59BF93FB3A3F2F42F3684AFFF7B753D4D355AEFD8897C4B5FE4BCEF5FD484A3F16F4C544AB7AAFCDFD8DC3EFADFB5ADEAFC3DBC8F2B2AA8FE2F238B6EFCCF458582BDC7FB8034F64F42776AFB1F1181A9FA6F63A3ABFB7F6642656 ++:80F800009FC5F324343F54B552ACAD4F24F8C7DFAF27FCF8B85F56FBF7EF2BFA4F4FFF2F89DFDFFFACFFDFBEFE2F8A7FF7F6776577952FB6F2AFADAFFAFAA6BC8F8FF4E5FF7B7E7F13F43B2FFFFBFBBEA39F5AF8CE69D732BF92F4CBCBBFC8FC184AAFA5DEFFFC9E92EF8DF5981AEF88B8B4FB2C2AAF8BF3CE4C4F45F1ECBC7F5445F2475C ++:80F88000477F42D6B8F2183A3F86FE7173AFA5F57636BFC7F725372F64F5D2C25F1DF8D593EFE9FDAAF2AF8EFFE5F17FBFDDE6FFF6FCEFDBFAFDFDCFF2FFE5EBFFB7FE776D7FFFF3577B6FF7F7B7BFAFEBE248F9F8E85FFFFF97C6FF51F13B2FFFFB7B9FF78985BFDC5CFD35F143C33F4CFCE872EF8DDD9FFCFEDAEFCDFDACAEEFEABAB60C ++:80F90000FBACAFEFC3FBEE4C8FADF56CECEF3903004018C2488044220112A041248424124C22D1482241042821420018286B12B0220169016B1290148441008E4860882482649244504882448022F83B9C001A22026200A0142862004142C03148871400481C52241455A82184851142052884130428141142190219021952228218002243 ++:80F98000002D92008281F01FC3C0431F41523C1F41F24C111F41764AD141F26A111D24AF169921AF1419F54A9143F24AB543F24A915F82D412FB25481CFB244A1CF8254A5E214FA27498F1224AD6C54A9E24ACF4D1242CF4912485F2912487341FC9724AF39124AB141F41B64A9921AF1419B54A39A4AB9443B242792498924F8284F924F0 ++:80FA00004AAB62D096A461ED4328C583764441F866118CF26A958E24AF3423F84835A2AF5473A4D81AB1A5D412F3A7488B342F2AE554F121CA5EA484875D2F227458C5835E254D8A1F85C2881F49D622F4112C4E831E2C3CF8916C89F11164AF64C8442F14FB14482F34FAA4482B1445F842924781AB942B43AD942AF142F6202808000089 ++:80FA80000000000000004200001880080000002400000000004004280000000025015D7730142CB12C81D286041448C0125840714184941248812C1204188004200159C458184444122F32044921210862002418008C0820282262448D848200B0E84C0123482281B2126284413240288105160C532121A1425F840110181142D4848151F1 ++:80FB000042D1424A1112A4122651C359A11234244D28308496683140DF8134161186041AA421C6F4244146F4131614122F2CC1343692441A628420612147843061548934121745183823D6A1013058118218C114C991151D4441F02C41214E2516F884111234100644454831A28567A4881CC2A446C4CC224CE454B212F42FF8100485020A ++:80FB8000872240C1442280218181C414008410644412001042846145291408522D12A0121265012268C0282492981281403114002081290841EFF305000000621100814081240481101241010014481415084001120000804211911412008140018D810020040081227FD90916229128C5711C021443042400183C412215029914684116BC ++:80FC0000B12434211083845222852211024214146C230289259421106138143123188444C88824490140889A487F26022400400462140000121301182130429460114A02800417A2502A16028004C012001190311800502119081F840886084400804AF853568021C5289564A110C1440025081584F4422248815018D0141142943134145E ++:80FC80001C04001460111011916C28228B14131404141958F280120484002B140081812B34CF220D28002230222D44140020C218CC0820D4224288016012244881B424208401224382444482110400C028490246088846841488223824008C0417520024A4441884101414A828114011142202448085324442413034834504256444484055 ++:80FD00008408131202800110082051181281C012688190942889E24E0BA0124C03402112CA28421181118044044214702804C0219024402441242442043011444119012981941C13010021210082814508268406F0972500382B12250487322614CE24805A1899C181495442622724411287442847122C16C424264634164624A124222873 ++:80FD8000309430272D1500588D14164108461842A9411048624E4342A4C248283FE10D22108CC212201411C848142850840020521880034211428487118C05244614644441464441840124120083C224002C2148C448883618488832148942F8BD2B004C622200000000005100100100111424C0481411815100201201288911410100426D ++:80FE0000402148012D82000043422408F0A34310011244411117823822484011084248118304C5414118241208002120942289044B16158241E1612214118111D181084058149304006490584A01225F750680022504501828001041182124449148501450818002810084150440094C02001821001810180181D08114024024228101288A ++:80FE8000FFB80695B84CA456424411281228424554444B222E242200111048532235A611AB11D21434004237124631219F8154B88B655E494E251C44110113348145D444F824211F62220A0024448D46272C25A2114F220C20220200000000000000148120121848080000000026040014004011024A1102100100004008F0197640C848D3 ++:80FF000048480000001644C424282810422111043518925318988288000017421484C42E484848002110116148444C82822208008430422129A1AF5084800410148282012445043A0210010014242180818408401A14410140084A0640142182012145C4911922480200001022F46E7D0048000040025042A0210011001001290418148865 ++:80FF80000000C0410084800400000040158102000018448221C018BF6804000000000020010000001001000013040000410000400100000000180000001008F0D3761038484242000011101434242A240211111440CA422C2425212B28084130211419121838484242221008004149382426312100828481464AC242127F430D848448486D ++:020000040001F9 ++:80000000002400204154482868180000421421211B121888884800412815834248984448002134181C08C417C828281200000021614F190B0010815222841210010000110010098454440000004C01000012000000001200800400000041F0E516808111040040228501812400001008000000840000400220010050121502008611412220 ++:80008000040000222004488F6A0F20021110062400120052423C01151141048D48B0483429400140148222022843214154111042118181E8319C811252134C02002684648448C9D4A20F20410400A12312911100100211001281941B241C14046242008143414404222002004131701251211170895113148200008688140477443014200E ++:8001000002282480B15241C2128331180050114059911944111C410184800444424D222C12042002281512782203148A511888001880688185088120F4A5BDF022222F21C2122B11122B11C0122592832F11F111119B98179887848F18F44848421F945411488558884F84E444F4244449F22424222E2480524445E642F222222F21C2120A ++:800180002B111AB892093C592229F812111F11B189E998F8488889F44848424E4880548885F84448CF96026F22D226E222A113121240512229D8B2F1111319FD918887818D418B444246511150D185C8688F44D44CB444B264222202504245C4346F22D226E222A1131A2829082512D2B2F1111319ED89F818888B488B4C424200C485C883 ++:8002000068AF77070000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000000000007D ++:80028000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000A0 ++:800300000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000001F ++:8003800000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000009F ++:80040000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000001E ++:800480000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000009E ++:8005000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000001D ++:80058000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000009D ++:800600000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000001C ++:8006800000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000009C ++:80070000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000001B ++:800780000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000009B ++:8008000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000001A ++:80088000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE009A ++:800900000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04F17 ++:80098000FE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000D8 ++:800A0000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000000000000000018 ++:800A80000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000098 ++:800B000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000017 ++:800B8000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000097 ++:800C00000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000016 ++:800C800000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000096 ++:800D0000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000015 ++:800D80000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000095 ++:800E000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000014 ++:800E8000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000094 ++:800F00000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000013 ++:800F800000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000093 ++:80100000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000012 ++:801080000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0092 ++:8011000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE420 ++:801180000F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000000000000074 ++:80120000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE44F212404C048482C0445924526212242C4211544D4214282C621203112211981818191188191405148C021148C9444C042844122452108446CCA226061DE ++:80128000A021608100BF4908267111D892D1A154258564C2C72768226921D18501472483D222C21CDB1216A241A90142442D421D2211AD2135E416C1744678486214136684841552298D44263C64624B8429A2214D218211457824E282D468A3482B8723B818B812F85FC540013111259442818B122364241218C7119021151C14C91930EA ++:8013000041000080632128B01102429042281302890450282062244C028008844C424E28A4418308F0196FA02483210142C022442835C42120024384021844481281244A11C6431041C21CE04142485148428100253C42C024424318A138516018230242180023C188128FAB0110412804454804201284020060222082522220010011403A ++:801380004961848714904800001442452802442200400410B222512412288021F8DF4814200484912024140400100421214722901228180090121022010000111448850111C04446080080024C420480622A820021BF750600000000001100000000000040040000000000004002000000000000000000DDA920A1218144123607494284F6 ++:8014000062841982010011411884404404114818002061A44810012800C0243021811D148B48225841003024D880984449C1282F4F47023120420811B05812322248481512C1C427858423140484128449120483C251AC022061844428207811A442C048A0182220019012304224203414843044C34462211B128443021E251149420427C4 ++:80148000841322441102AD11451852844044044501122648410842234548218202174142260422924961842A8145042024B2822184C14C43C168CFCF0A0000890121F068122822481840B18424044A01408841889244005226224108484400882002831411982188009012101224044C0810F4AC88202201A012B028211108812004292167 ++:80150000110289A2421490284914382140420400004400C0240085011400402148229182920081261828BA8A06180049021844102444C24A6041918D44112B1411A52424544128191428B42231418457842B414935142E11196231C0112296C1161C24D218A5121C62881E418A21A821461438E842A02481F400188082034112444210082D ++:8015800012404823441168143025464429022952526094481A841101130151221359141334219B4110011309922142848924848206BF9B0F2A014004188903811098422314741A7154021883B2460242842842944212428141231144C43426012138008D120080839289482C092A3994A0288181812E884F390F464548110EC023471413D0 ++:8016000031242911C62213944C472187624285447442D484026181142118804292414C01488B24272280914220022688034B8124E04221C81429014C012480F8E1CB008C1422121401200644002220A8144D191200242012024A4162848112119042102814644226A461C0421800412120A22140A88548842442F0EAE2001564431410167A ++:80168000642220118181311418280090421488124689048712444118914C22021C911218400181811888808324290C1002001220099FA402113449932364C02531271747223C8141024B41A6A2524E1C458AD441F4842812466284112F8114D4C2B418C211624922E43124A3124115C42418841AF4128822281E82122384A11A50821AE44E ++:80170000416481A018884FFD04494444410C15044C061200185B41814351681118412100578218C021180081611221C04290421A32428C260222121848888244D0422181080042F0D92E005028000040148444484448E28281C44958804381418124C111002146024314180449020050822215B8411221022121240023440C4989012E7D0D ++:8017800040850283822182011233C211621014D6248402214B42902448494201241E28C02280C12280020028222031410010E14882880186822202186260A4AFB10948008004422800A190181008810000304100001004194142421308C042442005420000202188088882E8882901619F87048411003041800100D04204421A84011400EC ++:80180000100240024502001216090019051812008021C4844C082180048001202888F1654E1022048C0215028034223508842954A24446382221C44044410564AC24022446428A46CA324078146222002800868204000021230280220287326E83100189140110018119C1425AA21400001C0430640022491418644129140A601118420024 ++:801880002241842081220218488C81221982012902008C43D46C094B4241001A14B444114404001044042061441A041112100110080028142820030022001001140000004282901881003F3704180018844A4208128081012904C012410020022301A041704401C021811A0223A52138242003142820220C18100443081822422E82F0B595 ++:80190000B56082268844041214189014244421284810021128481002188008202201141160828084212124023021824CA24A2826020042200821481F950578C4B0131218F11A440045518924C50A8D482F61D6AA9451414E2C4B661504153544844B44453244227023B864312943322228F03434230218221F1382D2518938482C014B846B ++:801980002D1263AC65A816F812249CDA6EA1DA346665168538281A6412423AB144F122161E4223C6442B4447644228632484052AD211B43252111835B238C2438CF211121E12A33112AC24A1522644B218C332321B64F0418123AE62AA081E3220C88282422AE284E529213454108502C44AE145D611417418B611F242111E782B15451E9E ++:801A0000D284A11526FB1341432251145A118454241E182D1C2554222B4428ACC63B2B2178C7111E3221A0458C4241A842601C6C33928A5822A0222B8287418AA98A222E48BE6414424302004D1148414081044880044890413848181904190448800448800448000020064601148A04824260244002200800EF444BF2567445F824241F8F ++:801A800012F66C6C4F67F24E4C4F44F46C7C7F32F33E388F82528AA5FE4A4AEF64F6462CEFE313F23C3C4F67A7664F57F774646AF64C4E6F64F46C6A5F36F6682A2F267659FA627A8FB4F24A626AE686F234262F23F648485AA6621B444AF4C1C26BBB8AFCF8DE2CA9F54F4CBC92F96466AF86F4E8E8BEA28F82F848C8EFCDFEB9BDF055EB ++:801B0000514B44CF42F23931CFC7F67566FFD4A455CFE7F72726AFC2F22A38AFE353AAAFA4F64E766FE5F72A2B7F51F12C2C4F46B623F674756F53F76565CFE8FD52426F23FF61618FA6F67272AFB7F7627AAFA5F4123A2B544AF414266F63F75A384AA6771B446E211F2CFCB2B58AF8F8DA2D822D826F48A8DD6F4AF268688F8EAC8B2B4D ++:801B8000928F86FDCCFE4E1E346B114D4445F42129CFC4F47163E7C15AF45C5E7F72F35A1E3E2AAF2152EEEFE4F47A7AEFE6F27F3E33F428284F46F436745F54F425745F44D4ECFC5656EFA2F645438FA2F25252A7B12F25F722222FA2B262A6734D266F63F34A187A86F241614AF6C1C32F4FAD8C8FA9FB42522B914F48B892F964662B7E ++:801C000066AAA8DFAF83AA22CFECFFA54B247F51D34454CC9F93F35C4C1F27F71F1D4F45F55C5E3F63539B2F82F31E32E7E4E7C6AFA6F77E7EAFB6F61715CFC3F364645F43F345474F52F34545CFE1F85242EFEBF34345AFA6F25252AFA5F35A7A27252F2393123AF514366F67F33A387AA7731F16E616F2C1C32F17A5CC8FA9F352422FAC ++:801C800021F846462B556F62B262A6EE7AA7B38F83FBCCEEAF5F072B1200004800411260814008120044000040048001212012880118B02401002A0122822200120000A048280082CF460AAE510084806414D0244164165022484245F8482211904428114C12814252484140021850220028201102001440214802248224800A8B949240EB ++:801D0000F95B95E032F4112485F31124A3F41124A7161D64AB141D24AF149961AB9459B44AB924F44A915B432F14F934482DB15F83C4915FA2C4815FA264114FA264191FA264594D4A9E244FA2F491244D421F4952381F497248F29124A3F4912CAF14F1812CAF14B981F24A9151AF243924AF2439342B94478A2D944F82C4B44FAAF4EF83 ++:801D8000267024BA11B428E4417266E281322E1D48AB12CCF62A941996BA19D66AB924D418BB14D41ABB14D412FB364829FB245A8DB14FA2EC11F8244A8B292E428F59D2B4A4294D4B1FCD52A49AD628F4912483F4912C83E4C9B242E1C9524A1F49B642F28548AB344B43AF44A9432F4478A4F842146D484EB46F8A35D5000000000000BC ++:801E0000440000000000218001880000000000480000000000281800000000F0B1AD2052120018412190542044014825018D41901290218428542422100C7012040013011211400480C21817422450222018A8422A8908830481422F2B0B489A02236184625082842D428480041220011384086644284618911110224422210130413100F5 ++:801E80001D422C029042424822108864210012468221641124EF980F6862241283C5622481C442690422C01180452281683242221B2524AA3111C42142633111129018462144014D412D22001E4853964426221282542862321824AC04121E426739403211004004E0240181114248215018601400478281418111000010021041321100F1 ++:801F000000801202240084881220888884811408BF9F0200008541140A00228A240440884208001028028042484422014002218048082881800118008AE42421D128492834848800F01B5AA0244147223848211F2996488C14121148385219C4249C084888184C01004644AA248153483448400480410811181123084117A4E0885422113D ++:801F800000608320812429F4728380022CA2214230C38944021182802484C22820248811042810048C4248156284002100002002238811C44121882938422381186A8488888088F41751204414049125B42811324880628487241214C113180800128400488D224844884901400421188318182151180090183048481C0189013244184823 ++:8020000018F0F666004082A424001410922241800214A9040025B4140A20C4112440460891002C014724840000448308490800B222402C6462416440F86EFE248F42A1528114C0224242005249224862812290124841130B1214839218860842105141447022412A240220021C1122118401142A044100002CA21C2CFE36D90010343416BF ++:80208000410828214301422301901888461102008488002200002301000088119014128C1401838144480824882049288808F064A5902410CC313289227461024129C722982412872246784203444B832816888844C822204418311A001B211062880028124F141129112811482889928441C2EC0243A818ACFE68FC90121A4242641410B4 ++:802100000224128084028113812821042531941091281181401402414424104234221160414098828089041142104288014C2822043F990A00804412180A202422928214810020316423110C47A2891244410A45A81824100B2C0821490110E482811888A121409311182128801982682488ED1A0000000040918923D44118C4A82F12A152 ++:80218000821882A90846A882818846432A01C60A806884424246048E4220688989082041840818008001484100412FC84312016081C0114601148432250825081491143442888A7488C1C18014C841898154842AA428140044255418C6024334824608428331428111822031824381A88142E8BF8108004800301451420088000022100824 ++:802200004400404601400100858498821001008C84381498288004A0488448142E420000F04BEA20185428481111A1108839881028044949820838840036E88208B0124811328147210000804812644828008001182001408401188041F161E62004004008815052424461883912A8811002220080C11240080040412808409244008180D0 ++:8022800081110282382001828840022121AFB60700480020C4444148544214C04848001C8888018A0411B0140C60C8184A887642C242C21008004088028182C41CE88822042142480040F4B2242400118120111121841123948111888C518181808108400132141200E0510282008644A428440010888282024002822D82502400007F892A ++:802300000D848004004941480212156C244A021B422C420186184258428011988831828884814D810025084881A180828C82048584B28886D428AC412002803182485FB50C218285E38445C21A7F51419C481B59BB4125B2CA6888429AF119288A082F23F742188BAC8D84CAFA2E224618A41D8D126F8C7894F854522F82924A869246655A ++:80238000948485A1C82B184F4AD482A141E0421488B589F4E811923014CAF784446C21E814B584F2B4CF00008111156184C174AD87888F8E5824A724AF82FA4D812643739AE88C388CE0887439E984781852A2A5F18388818D91CCF24844144A24681887682FA812DA48D888BA1CE888A1532B11CE1A411E191BC18DC829C812214A2188B2 ++:8024000049D2427C2A4D924144003018897441314146F864311D4115D5117C11E1828659831D81443A481C4154112F52F1195115681444B0A1F884821FAC98824A4812F24414456484A04A8BA28C12A8A38B822C48E224E124B582AA82272121128842FFAA09130415088688011484149648C148148A0413091914B8140449045B4880056D ++:802480001904588143020088844948384230422046286489148420492201122049F424FB501157D415924A1549BA4E041B44B7286336E982AD42A14F52F6A828A5D292F424644FC67BC43C844FEF7465E62653664EC942CE8C17589BCC4F8EE414A4C44D4247E44D8A2F22E244FC8C822D662D762F86F6482A6F84A75C669C41CEFA2F25D6 ++:80250000B4C2F464D42F26FC46966D828A81B482F4369D34D0D554213D41E021B15AF441414E427F71F456163F3CFC22A23738B9F234249FB3738A7382F312822F25F84E8C4BC42FB66536CFEEFA53532FA4FD41834FC4F895154EF72FCCF648488F84FCC4424FE454646F62F646466F6CFC2E6C4F4AEF8EF5482A2D34A02419F4C1D22F99 ++:8025800024F442424F4EFE62E26F649C86211CF41456CF680E2B444D4585135A19A1AB558F84F44942BF2CF1CAD59724AF34F68AC2BF9CFCE4BD9FBAF38B8A3F9CE8AE92D267888FC4EC9AF1A9C18FA2FA5E4E27B1BD43E5FCD54587994BC64AEC8CFC44444F48DCACF8A2A2AD86EF24FCA6A44FC6FA48A81E7AAD3C2AFBC8B81F19F588BE ++:80260000D92F2CBD92F964F62BFE4F6CFD869429A9D84CDDBA49F24141C555B8B7948D88BF81B15AF449419FB4F4DFCFAFDDFDC9CBAFB4FECB4BBF8EFCF4C49FBBFB8A8BAF94F4DCDE6F417D8EC88ECECB6F7AFC2EAE2FA1F1C25A1F38FC8C8CDFDDF52C3E4FEEFAC8CACEC84F6CF48EC6AFE8F8EAAEEFCCDCCCF82C2EEFEFFBDA18ACD705 ++:802680008AF3F8F88F8DF989589F84F5DADA2F21F9F4F62F2FFFD6D66F49A9999ED14F48F9F83740010014008C14042482000060882482811008891212088169088883948290841002004B82160884000080044828824400F06ECD10021440021C414421513240038521C123112412288018013542C11214004B1240024904611046542246 ++:802700008222841828004E9350224012948220046F9D0E2D521F4152281F41B248F11124AB141D24AF14F11124AF149921AF143915AF143935AF1439352F147934F842955F82E454FB254A4E854FA264555FA2651D2E5AD6F5245A9E24ACF491242CF49124C5F391248F14F19164AB141F48B66AD141F64A9219F64A9259F44A9143F24A95 ++:802780009243B242792498924F8284F9244AEE2DD0A2F11164241FC1B642F1112CEB144CB242D1C17662D48194B255981A43324A43D21A29F2429527822F44E9A261442E9A46F4248AD2267AC8752423C94B1FC9C24A1F41F624421518F49168A11F48B62AD141D642F9116C29D285A69447838334B44E844F8384F83648D0A6F5DE29608E ++:8028000088824800000000440000440000100200880000000084800400000000000000000014F0DF960018811440221481048D11184A088014CE8210110280622A112541612824A8002800405A284191102112688982124003690146021882C8A6F93A9E1412271A24124816210231222B2C141814860819820228CA62818B84841140088E ++:8028800049111811348412497D21C2A1111C69228847114988513400001A98248126244124624414423EF4142C611F8413214483148164221F8E61117644412854832C0A1D228E42188483D321681821149825AA821149A821CB8411271A15FA18C3443D88D014885294C98128021C39262741268451422CE344C8818BA51DAB0040022023 ++:8029000021022501008880084C020028844A08285018400414410012220020024D118001290818001008420020049EF3002825A1210010011221400140080043A124002210011180A421490100002180415422112A2108820081502200A0848628047F5B4A828261824151611694484068122B1C00314A81EA8811B841081AE48421240600 ++:802980004322112CA18410948411621464850146C1414E3A88A381824423311516081C65282C25A11486C888778B2480118341118201800129184112A1142289084A2182240440312450481A246141001128244480014227850080488101189042881829AC81C882BF4C0C222883C224414441990485C22152004028284178842124C11825 ++:802A00002AA424001301200E444C084811249170411433212B1AA329224402CD11A46011304218464848F8FF7A90188092216604D048028B14C01141001880010046844484D8845114402A419121480084C084424480AE249210041008508246880422248C21F4919DD02882142801CF180114112448284958212006274448302260413C4C ++:802A800004189200001100471626086014000066A821411042250242128018E2A208881FD503604200168218243448210048008C884821014C180880441102416088874441490811902228A014444542C1848E188908100800120000F0B6F72032268932312CD21841944C894422E411825C21A01E826581012B28831444225849671110CB ++:802B00000499E882044CC84114403421A04182436695228B188C184241082D488B144810C28883A1842FA80D1800B04441041942E3810480820284A041424014A414592404008129014146044C22022B82100443062B829604004508008021882202F0F6950060421C447418342840C1914E218191841021044388E8C104908DC024224884 ++:802B800049A1684883A841838424342411112692141388DB24644214221885444A02181E2C4444C018F0737B1447124002260811114122002AC18183826C52004904C849012440080041001308A81628886688282161281844124002B2508400230448F0934320440440141144C41C4420022858410048000012800443524184838114283A ++:802C000002008C02460241901234208142082784A20088C08C001F5708001100800422482668144441881449280410448848314181400800884C024C4A1C81247821144108A4508182A504431414A82842420045027FB80F10010080411A311818841942982110091844008008188018A8484214418A11048282454848A82C00248230D229 ++:802C80002148001200108442F6DFA1C01510185828118045084E8832C0B1C0C8428814188888CC044C0828A04883214A6418544008482028088A818181110818384B381881258481811122F8118B2428459834A021C14648014B2811A0414A824424126446C82E4820423828C08828008084048984084901422CC4185084882400A8008049 ++:802D0000B2A86182C90C8914F8C89F2028080012701824548120412861882008001844E60845B1482234441022120883A128F0441118190A4581810245481808648C8874244884440425E828018F984542081C5484008024230446044A221108C28A42282214839478121D8220312441441442608422CC0420155484211B82C084841A0AF1 ++:802D8000A48288A081818821702C05597284F4382184CCD211A14147958795CF48E114E211D58CF1D11470C564168AAC12C6F4381CC338641BC82E6C4AF14828874C586B482E388B8845B8D932244C7485D4487121C4E64744C96328ED524CCA11272245D86CF826DACF489A9847824634444EDC8D184B5469F87FCF1423328155C44183EB ++:802E00005146875619D544E1879A8930318531C1814B28414D844D48E84287484CF141811A6612685329348415E44AC5558F4824C2214D888895F8A3511E8641267416518A98AB2425081E4A2588F83A381A189C848F8348F2B85B24561508A5342487818485B423D211E482F568284E218CFC38F89CDC492CE41C863944C81EE985197CF1 ++:802E80002A0C6342FC38A84E444F8424C4884AAA8C7E189E218F18267E1872C2E9C36B811FAAD1417898A8919A31482B16AE248F4993C4AE1E24864442F869F9A021E08112A428212825A1411482221E48200113422442246A44228117284082820888802804429800C09200503496088220496281448285A54BA04A8197A6243AF1351C56 ++:802F000028CB624F437124D66ED656B628F2AD744B7719F6114C17189AFAA4A58F9EEC44F651718F8BF734588EE81F58F29C634D29AD3A3D2B4FE2EE43F376F4CD6C9D8C1E449E418B484F487C55DD51F885C5DFDA7831F349CBE7E1AFCBBBA95387828FC5F58C1E6D244D1C85483A86CF48F16422EE281AF55E441F894C7223F4517C1F35 ++:802F800011A37387E26F61D3EED283F3393C9F43E357E784E7C2B388B988B9ECFEECC9EAFC91B1CFC3F73C1EAF8AFCC1A96FE6D55CF6CAEABD2BCFE2AE77EFC7F72C6CCD4DCFC1F15C1C4FCE76C4F41555D5FDA5A54F4EFE7735FFF4F43E3EAFEBBB2D524A8D12AF8617784CFCEE8EAF887814B25615F46C286FC3A7734F46F7C982242868 ++:803000001F41B538D14CF214B665FF3E147E43AF87F6A9DD8FC7BF61F619681F1CBCD8FCEC498F9CFE84441F1FF5A888CF81FF8ECC5F9AF88CFD4FF4DE88FA4B29AFE4F4FC7CEF8EFEAC6CCE854F41FDB8F84FC8D444FCB1C19FC2DBDDF8ADAD5F7FB6EDFF9A9EAF49FBA93EBFE8398A8F8CFF8C1EEFECFD8C7A4B188E8E6B198FCEB78423 ++:80308000FDB63C4F4FDBECF5725C243F45D749742DFD7C1CCD2CCFD1F17C5C5F76F57B7D9F5DFDF8D99F97F55D799F1DFD99D1DBE8DF9CFEC4C45F57F598BC8FCDFBCECC5FFEF8E5CC5FF8FE48E8BF96F2CE4E4F4FFFFEF84F4AFEC8CC4F49FDF8F84F4A56445F5BF9ADBC5F5AFAEDEFFFFFFBEFF4EFEBFB9AB6DFFBFB9A93AF28F9CAFA4F ++:80310000EFE9F9DEDC6FABFF1E184F6AF8DED89F8FFF94D84FC9F9D898CFECF846549016800141844941581440C14800A048448A0410283848400483048F44024200430241702441D83448681216484208164802248E484C42089028124482FF370D10011224152444941A1A22168171819818C0812024C1148A044885D12224542412183F ++:80318000854458485886B42454411813386415D424614829D9C102502A40441838244A1104412886D229062CF4112485F21124A7141F41324A1F41F24A111D24AF16B911B24A7915F84A9453F24A9143F2429147822F54F934488D915FA2C4814FA264515FA2E419E2A264592E5ADE24ACF4D1242CF491248D121F497248F29124AB141F37 ++:8032000048F24E121D64AF16D981B24A19F54A9243B24A7924F8429647822D944F8284F9244A7FDC0BACF4114445E281344A1741A344941ACCF26A141D24A95A85AF4418B44A49F84A954578425582AD844D52814FA2ED51F224CA1E212E4A5CD2B424C54B1FCD42FA11448D429E24837411344C1B68E9E1C1644415BC4AB315B44A32340A ++:803280002B8426F84A14435342678289F126121F65092088040000000000000000002100800800000000000000000000000000004001C783004008844484000020481408008845A818688228604420028984810100204108844951282046981A11294404800148802404229C4401824001001410849D211001A0412003402481041044146B ++:8033000001114838814712002009004118471A20124802288082C12240C411F0AB9414204C48410884141094541122518480041A484C021212A048412211481111188187122045280900214AF22C816126336864800228C0222CC4441CA1219FAB0F00004004008088820800188002984B42882A04411004841258284004001068418144A3 ++:80338000189018000080014A0100002BF900108282012001281840010018114200224644481141141118040000001470221151246022001240088400004200F02D3B20247288114122B644218291121CEC2401814D188C83A22420E14542413841460A6848268285A22126C2121419422202001B218011C8212A588100E0810230423634BD ++:8034000041A0849FED0A4828141982B1422285021A0200402C0326810418263148156884144944C1224A011A022C011C02113021D0411282118882411808818C0180248204C8DF6A0C4092880010248111E2156825118112811A8204124B42108444032842844128602210019022101221012221148A4201002800214B141100AFB308167A ++:803480001444443818890138408204458821D24203601222120021241824008C221203009C042006001E218032841100830200C2904124B058F874E3C0484830114042482814081014241208C11210D44848188284D11204001293E42241A4128C021A3241444C2102848145C8228449B1240841402842C46A22F0FDE210020044440090BB ++:803500001400001921142204492122122104840000844004201144040041004440080060888100144024F213CC241A04418321C11E8483024981041014411492482E1141124C4A01249043008982314A2420B211422401C0144CB221112822C828814311048C088C2C226482448BC26FC70F414410110C202144180281122CE1830441205E ++:80358000C324848148428410029028E04112248104439221410000C48111219088404408408484025F2704112983C161116240118182418221844115542140019014484021231444834112A84100100111181144114442241002C028E082B41222824408D7D8A042242480228102402824025120244468142890241C0450844D4260114017 ++:80360000011284807211042800202102A24A22211192848222124A881424047FEC0C0000420028124110222401145128181C1181110415C2212512140420011218442813011128111C52411C024008C0120084960250A4843FD205402241024222008C410420C428488481808401D02241081400260800902100241391281400002088A293 ++:803680003820028B1840088240D2780D00000000800224400420011400C04100808411082D21100A0041800420020020048428A014A024602242007FA502200184001852220018800284400100142921148242014081011426C8288413A64200471260122628624844240022801282029082819F45061100B0810200162104902400002841 ++:8037000048800328001602480010011120120800000049A841184381822828022C611448444288CFD9048282102194149021003A142205124419041258408112513818184008281290221114211226210222102448280A81211282840021407542F2692D6084284824C028428C2484051D348063C4848021824291322180418438149028C1 ++:80378000246011115084184800000000448C882A0220884828881822F8B81A304182004A8825E11487A1676A743132461E412614A5443682B451D4316141181185582F29E2445581A012181E182B261CC1211F14C231221CF22134144F1152144B2A582AB31C53282AA8994E98878A213B23A845C48125F8281540E12831122F32E412C667 ++:80380000246A62821715CD1818182AD544E18441D9544139511C021D31558614E351A245214D1497121131701881021811211508191291294C38E8CE422C2889828282FA589A4EC846227C482FF88746142AB4328211196387108102169622124283F148441598291CA31232227E614E12342AD171311481ACF212211612DA813129476213 ++:80388000C743121F1423422122624214498848D882196262A2182AF688122B42C849D428FCAE18140050183028488712484048028044140100130100211063441088011028024F1201146012E012014B1248608824922081A2488D2292462418F8B844144E221E1287A18D4B8784CF45E781C1691E188B72CF85F549797E544F44F11C384D ++:8039000087845E589CF311116AE322F324355F53F1124125F8243C6F23B1124448F3132317212F21711831291D2727853AB221962145849211DFC1E149F3CC88BAE3436128282ABAE8FCB8122F85F5419A6E124B4C482B4CFFA546D121F2525A2F21D133F44A48CF47E781E193F339383E388FE5F55B792B754F45F51C18D5FC51551D3105 ++:803980001F11B161F221317F53F175754E5385FAADAE5F37F1549485FC292B3F3243F3121A1E381D2815F327752E212E21285D251CC2318FC3E149D3C8AC738F8163A123A1A28F8E7728FA1A788F26324269344C8F8DFDB213142CF232722F215132BB464FC5A7179F15E787B378E747F711332B754F45F5145CCF94F45C599F97F77151BE ++:803A00006E712E313F53F371553C55BBCFD2FA34374B5145F821233F337212F3121AAF81F321291D277F4134111B22197225942113D38D83F2D8BC8ABA187B8AA2882AF2E8E88FAAB872FD9283BAF8C6448ECC4E5ADFBD4DF14162AF23F71212B7B4BB464FC6A6579F17F779787E787E723F11B352F55454CFC5F54D4C9FD5F579791F13AE ++:803A8000B531F611115F53F375554E4395FB2DAE5F77F7D454857429F3333327212FA1F112381D211F32F237353E211F1292215F52C2211F13F2293C4CF258F8DAFF98982FA9B992A9338F8FF7A88AAF8BFFBA322BBB4BC8CB8C8FACFDBE6D20022941382248222022218204484484B01184828412410481C024180028211002260122206C ++:803B000002220012200100824008200400DF740B8A041001121081212124112201514280312118E044D32104244611042648812141982140E41211014001144C8288068421222022648221492444FAD7A9C0431F417228F2112487161F41326A1D24EF14D141F24A9219B24A19F54A9153F24A9743F2429157832D914F82C4914FA2C4816F ++:803B80007FA264157FA27498E5A26559ACF5D8242E4A1F49F224521F49D238F19124AF16F1912CEF16F18124EF16D141F24A9319F64A9255F84A9243F24A9443F24AB24F82B442FB24488D944FA2F4C6C6C04A1F417628E241346C1FC1322A1D2CE9D181F24A96CCB2489B25A929F24A8747822F147924D812D986F442B14F82C5816FA237 ++:803C0000ED15F8224A87492E4A86C54B8F4D4263C84D481B48AD428E2463F49128E3E449B24E41F84A941D6C2B3457818B3443D34AB91494184F8124F426488F44F1261AD73C4008480000000000000000000000800800000000000000000000000000004001CF1F018200001D1400302400100410090080260160241941262114042200A0 ++:803C80000000800214602282220000214180024280F47F4B00828021044413028004008022542440040048140022001285820111100312400100148901000000000014F084660042202144011902414304224420521841002428181214C692112634124054211A02912413041200400126929C22220000418042824421F18BB600000016F2 ++:803D000014048002000020042141800448000080244108000000902100100100001002000080F4728F00448002000010020018000000410000000000820018288012020000001800100218120000CDC30018000000000012002211001081024618C148100410040014400100144001840000A01212000000423F3707800100000000800184 ++:803D8000182214004021028C44914810040080081190218002111001810018002A810112180080F4ED18004420020000240000000000100400000010040080010021000000000024000000002FC30E00000000000000901441220000420040081064818400420000004064820000000000004C8202AFEC0A000000000010080000000044C4 ++:803E0000286C820400840000800100001800100842001008000000F053E50000850400180000000020440841420000000000180000000000000000001048084800F0A8930000850400000000001604688440644448100281400889118801580000000081000000008184004128F0FC2F000000001200400800400400002843220400100494 ++:803E8000000000002001442284800400840000422200FF3D0800005011400800000044000000000041000000200800000050888002008002A0110000F0F3A6000000000000000000400200000000000028000000000000000000000000006FDF0D0000000000000020010000000000000000000000000000000000000000008FE607000039 ++:803F000000000000002001002100000000000000000000000000000000000000F0A936000000000000000000000000000000008002000000000000000000000000F07F4D000000000000000000000000000000000000000000000000000000220000F0CE41000084000000000000000000000000000040028001000000000000000000008A ++:803F8000F0529F000000100800000000000000000000000000000000000000000000800100007F5F0B000000000000000000000000000000000000000084000000000000000000AE3E00000000000000000000240000000080010000000000000000000000000000EFAA0E000000000000000000000000002400000000000000000000007E ++:804000000000000000EFE2090000000000000000000000000000000000000000000000000000000000F04FFE000000400800000000000021000000001200002120010084000000000000220000D0F103004008000000000000000000000021000000000000000000000000800100002EAC000000000000000000000000000000000000003E ++:804080000000000000000000000000FFE40F000000004005000040040021004400100218808802218001884008000028840000800200004FB1070014000048405588281082044480022100448002214818808802214818448828842148408481421882041E148002211A01445C030000400100800454000048400400004004000000800211 ++:80410000000088000000804208000000F0469900000000005400000044001002400400218001882810021880088400840028840000800200005FF90B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00210014000048E7 ++:804180000080022148008002000080028004000080044480022148400400214840040021FF18040000000000000000000000000000000000000000000000000000000000F04FFE000000000000400500004004000040040000280000000088000028004008000000F064A1000000000000000000000000000000000000000000000000004D ++:7B4200000000000000FFE40F000000000000000000000000000000002800000000000080020000000000F0D4270000000000004005000040040000400400000000000080080000004008000000F0FF78FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/LICENSE.firmware linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/LICENSE.firmware +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/LICENSE.firmware 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/LICENSE.firmware 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,37 @@ ++The firmware files (*.hex) in this directory are software for the ++Astribank itself and not intended to run on the Linux system itself. ++They are generally freely distriributable (see exact terms below). ++ ++/****************************************************************************/ ++/* Copyright (c) 2004-2006 Xorcom Inc. All Rights Reserved. */ ++/* Redistribution and use of the microcode software ( Firmware ) is */ ++/* permitted provided that the following conditions are met: */ ++/* */ ++/* 1. Firmware is redistributed verbatim without any modification; */ ++/* 2. Any reproduction of Firmware must contain the above */ ++/* copyright notice, this list of conditions and the below */ ++/* disclaimer in the documentation and/or other materials */ ++/* provided with the distribution; and */ ++/* 3. The name of Xorcom may not be used to endorse or promote */ ++/* products derived from this Firmware without specific prior */ ++/* written consent. */ ++/* */ ++/* Disclaimer: Xorcom provides this firmware "as is" with no warranties */ ++/* or indemnities whatsoever. Xorcom expressly disclaims any express, */ ++/* statutory or implied warranties, including, but not limited to, the */ ++/* implied warranties of merchantability, fitness for a particular */ ++/* purpose and non-infringement. In no event shall Xorcom be liable for */ ++/* any direct, indirect, incidental, special, exemplary, or consequential */ ++/* damages (including, but not limited to, procurement of substitute */ ++/* goods or services; loss of use, data, or profits; or business */ ++/* interruption) however caused and on any theory of liability, whether */ ++/* in contract, strict liability, or tort (including negligence or */ ++/* otherwise) arising in any way out of the use of this firmware, even */ ++/* if advised of the possibility of such damage. User acknowledges and */ ++/* agrees that the purchase or use of the firmware will not create or */ ++/* give grounds for a license by implication, estoppel, or otherwise in */ ++/* any intellectual property rights (patent, copyright, trade secret, */ ++/* mask work, or other proprietary right) embodied in any other Xorcom */ ++/* hardware or firmware either solely or in combination with the firmware. */ ++/****************************************************************************/ ++ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/Makefile linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/Makefile +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/Makefile 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,32 @@ ++# Install firmwares and initialization scripts for the Astribank ++# drivers ++ ++USB_FW = USB_FW.hex USB_FW.201.hex USB_RECOV.hex ++FPGA_FW = FPGA_FXS.hex FPGA_1141.hex FPGA_1151.hex FPGA_1161.hex \ ++ FPGA_1161.201.hex FPGA_1161.202.hex ++PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex \ ++ PIC_TYPE_6.hex ++OCT_FW = $(wildcard OCT6104E-256D.ima) ++FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW) ++PROTO_VER = 30 ++SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5 6) ++SCRIPTS = $(SCRIPTS_BASE:%=../%) ++TARGET = $(DESTDIR)/usr/share/dahdi ++ ++all: ++ ++clean: ++ ++install: ++ mkdir -p $(TARGET) ++ install $(SCRIPTS) $(TARGET)/ ++ install -m 644 ../XppConfig.pm $(FIRMWARES) $(TARGET)/ ++ for id in 202 203; do \ ++ if [ ! -r $(TARGET)/USB_FW.$$id.hex ]; then \ ++ ln -s USB_FW.201.hex $(TARGET)/USB_FW.$$id.hex;\ ++ fi; \ ++ done ++ if [ ! -r $(TARGET)/FPGA_1161.203.hex ]; then \ ++ ln -s FPGA_1161.201.hex $(TARGET)/FPGA_1161.203.hex;\ ++ fi ++ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_1.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_1.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_1.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_1.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,486 @@ ++# ++# $Id: PIC_TYPE_1.hex 9841 2011-09-08 17:00:23Z dima $ ++# ++:03000000A1EA4A28 ++:03000100C41C41DB ++:030002000390392F ++:0300030067967984 ++:03000400A03A031C ++:03000500C40C40E8 ++:030006000390392B ++:030007007797796F ++:03000800A07A07D4 ++:030009008008006C ++:03000A002072075A ++:03000B0064364315 ++:03000C00A11A1125 ++:03000D003213218A ++:03000E002C82C879 ++:03000F00D00D0011 ++:03001000A0BA0B88 ++:03001100CFECFE33 ++:0300120016116163 ++:03001300C01C010D ++:030014006046043F ++:03001500121121A4 ++:030016002072074E ++:0300170064364309 ++:03001800A1DA1D4D ++:030019003613613A ++:03001A002C82C86D ++:03001B00D00D0005 ++:03001C00A17A17AF ++:03001D0080080058 ++:03001E00C0010B13 ++:03001F0019A038ED ++:03002000743C0627 ++:03002100A26D804D ++:03002200C01024E7 ++:030023001CCC00F2 ++:03002400E03022A7 ++:0300250002C20113 ++:03002600C03030B7 ++:0300270018C901F4 ++:030028006432043B ++:03002900A4A03060 ++:03002A0020C901E9 ++:03002B007432022A ++:03002C00AE803073 ++:03002D00C4090102 ++:03002E00D80C806B ++:03002F00024FFF7E ++:03003000C00164A8 ++:03003100022C108E ++:03003200209FFF0D ++:0300330003015076 ++:03003400901D0814 ++:030035002046B9A9 ++:03003600030D10A7 ++:0300370090102204 ++:0300380020220182 ++:0300390003003091 ++:03003A0090190119 ++:03003B00C11204EB ++:03003C0019003078 ++:03003D0064390122 ++:03003E00A43202E7 ++:03003F00C22030AC ++:030040001909019A ++:0300410074380010 ++:03004200A46214A1 ++:03004300209E708C ++:030044001253084C ++:03004500A4930879 ++:03004600209308FC ++:03004700FFF308BC ++:0300480016502728 ++:03004900AE88007E ++:03004A00209C00F7 ++:03004B0014503915 ++:03004C00643038E5 ++:03004D00A8603F69 ++:03004E00C40C07D8 ++:03004F00D80D4089 ++:0300500002403437 ++:03005100C00C08D8 ++:0300520002203851 ++:03005300209219DF ++:03005400030E0791 ++:03005500901020E8 ++:03005600204360E4 ++:0300570003036040 ++:03005800901360A2 ++:0300590020236001 ++:03005A00030C1084 ++:03005B00901038CA ++:03005C00C11219B5 ++:03005D00190E0772 ++:03005E00643120EA ++:03005F00A64C109C ++:03006000C221803A ++:03006100190E7005 ++:03006200743743AD ++:03006300A86A7315 ++:03006400C44C0287 ++:03006500D801803F ++:03006600024E0740 ++:03006700C006438D ++:03006800022A76F3 ++:03006900209C03D5 ++:03006A000301800F ++:03006B00901E07DD ++:03006C00204643E8 ++:03006D00030A760D ++:03006E00901C04DF ++:03006F00202180CD ++:03007000030E0775 ++:03007100901643A3 ++:03007200210A76EA ++:03007300E03C016D ++:03007400743038AD ++:03007500C04A7509 ++:03007600190C184A ++:030077007480385A ++:03007800A8621962 ++:03007900C04E0F67 ++:03007A00FFF03D57 ++:03007B00150C0061 ++:03007C00643038B5 ++:03007D00A81C02BA ++:03007E002091804E ++:03007F0013EE0776 ++:03008000A847434B ++:03008100209A863C ++:03008200FFFC3F41 ++:0300830017E03152 ++:0300840021EC1656 ++:03008500035A9388 ++:03008600C14C0367 ++:03008700D801801D ++:03008800024E071E ++:03008900C007436A ++:03008A00022A8FB8 ++:03008B00209CFFB7 ++:03008C000300313D ++:03008D00901C18AC ++:03008E00204A9372 ++:03008F00030C035C ++:030090009010319C ++:03009100202C120E ++:03009200030A93CB ++:0300930090103C8E ++:03009400210E0F2B ++:0300950002709D59 ++:03009600C147035C ++:03009700024A9D7D ++:03009800209C0F9A ++:03009900030FFF53 ++:03009A0090115C66 ++:03009B0020411DE4 ++:03009C00030A9EB6 ++:03009D0090121CA2 ++:03009E002070309F ++:03009F00030E0F3E ++:0300A00090103C81 ++:0300A100C18C020D ++:0300A200D800394A ++:0300A300024C000C ++:0300A400C0003960 ++:0300A500022C80AA ++:0300A60020902483 ++:0300A700030C083F ++:0300A800901104B0 ++:0300A900204039BB ++:0300AA00030C0044 ++:0300AB0090103979 ++:0300AC00202C0005 ++:0300AD0003003A13 ++:0300AE009010258A ++:0300AF0021003EEF ++:0300B00003B02B6F ++:0300B100707C035D ++:0300B200AB602C14 ++:0300B300209C404E ++:0300B40013F0390D ++:0300B500ABE7D9DD ++:0300B600209AB5D8 ++:0300B70015FC0035 ++:0300B800643208A7 ++:0300B900AE8030E6 ++:0300BA0069B90120 ++:0300BB00AE8C8088 ++:0300BC0020920887 ++:0300BD001BF03005 ++:0300BE00C5090170 ++:0300BF00039C405F ++:0300C000799039FB ++:0300C100AC06D9B1 ++:0300C20020BAC69B ++:0300C300D006F96B ++:0300C400038BC9E2 ++:0300C500219AC1BC ++:0300C600E079429C ++:0300C700348C0274 ++:0300C80034818000 ++:0300C900348E076B ++:0300CA0034874335 ++:0300CB00030AE73E ++:0300CC0021AC065E ++:0300CD00348195E6 ++:0300CE0034874331 ++:0300CF00348AE789 ++:0300D0003487D39F ++:0300D100D05AE71B ++:0300D200031C0606 ++:0300D300C00187E2 ++:0300D400032743BC ++:0300D500033AD813 ++:0300D600C70C0351 ++:0300D700039AE5A4 ++:0300D800C50C074D ++:0300D90003918709 ++:0300DA00C1874398 ++:0300DB00030ADE37 ++:0300DC00C00C0154 ++:0300DD00031AE51E ++:0300DE0021BC033F ++:0300DF0003218773 ++:0300E000C0074313 ++:0300E100033AE4FB ++:0300E200C70C0048 ++:0300E300039AE598 ++:0300E400C502074B ++:0300E5000390275E ++:0300E600C40AF455 ++:0300E700039C0671 ++:0300E800369195B9 ++:0300E900C01643FB ++:0300EA001FAAF456 ++:0300EB0021CC0124 ++:0300EC0009A1C7A0 ++:0300ED0074309CD0 ++:0300EE00A1E70384 ++:0300EF0003AAF46D ++:0300F000C02CFF22 ++:0300F100FFF022FB ++:0300F20016B0271E ++:0300F300C02B5CC3 ++:0300F40023EC00FA ++:0300F5007436F36B ++:0300F60012BCFF3A ++:0300F70020B02115 ++:0300F800038C0175 ++:0300F900C44024DC ++:0300FA0003990A5D ++:0300FB00C406B385 ++:0300FC00039B83E0 ++:0300FD00C00C0133 ++:0300FE0002302F9E ++:0300FF00ABF2154C ++:03010000B006D373 ++:03010100000D806E ++:03010200000024D6 ++:03010300000217E0 ++:03010400000022D6 ++:03010500000C06E5 ++:0301060000019560 ++:03010700000743AB ++:03010800000B4B9E ++:030109000006D31A ++:03010A00000B4B9C ++:03010B00000CE005 ++:03010C0000015798 ++:03010D00000643A6 ++:03010E00000B4B98 ++:03010F00000C00E1 ++:030110000007B72E ++:03011100000C05DA ++:030112000007D70C ++:03011300000C10CD ++:030114000007F7EA ++:03011500000C02D9 ++:03011600000027BF ++:03011700000C10C9 ++:03011800000D02D5 ++:03011900000FFFD5 ++:03011A000001429F ++:03011B0000069744 ++:03011C00000D02D1 ++:03011D00000637A2 ++:03011E00000D10C1 ++:03011F00000022BB ++:03012000000C8050 ++:03012100000124B6 ++:03012200000C02CC ++:0301230000018058 ++:03012400000E07C3 ++:030125000007438D ++:03012600000B3992 ++:03012700000C05C4 ++:030128000001478C ++:030129000006438A ++:03012A00000B398E ++:03012B00000C01C4 ++:03012C000001814E ++:03012D0000074385 ++:03012E00000B3291 ++:03012F00000C10B1 ++:03013000000021AB ++:03013100000B3987 ++:03013200000C10AE ++:0301330000018147 ++:030134000007437E ++:03013500000B3983 ++:03013600000C209A ++:03013700000021A4 ++:03013800000B3980 ++:03013900000201C0 ++:03013A0000003092 ++:03013B00000901B7 ++:03013C00000204BA ++:03013D000000308F ++:03013E00000901B4 ++:03013F00000202B9 ++:030140000000308C ++:03014100000901B1 ++:03014200000C802E ++:03014300000FFFAB ++:0301440000016453 ++:03014500000207AE ++:0301460000016253 ++:03014700000FFFA7 ++:0301480000015063 ++:03014900000D089E ++:03014A000001228F ++:03014B00000201AE ++:03014C0000003080 ++:03014D00000901A5 ++:03014E00000204A8 ++:03014F000000307D ++:03015000000901A2 ++:03015100000202A7 ++:030152000000307A ++:030153000009019F ++:03015400000C009C ++:0301550000002F78 ++:030156000007D3CC ++:03015700000B7E1C ++:0301580000021092 ++:0301590000002281 ++:03015A0000020E92 ++:03015B000000277A ++:03015C00000C5044 ++:03015D0000003966 ++:03015E00000799FE ++:03015F00000B5E34 ++:0301600000021288 ++:030161000000306B ++:0301620000021484 ++:0301630000003168 ++:0301640000021383 ++:030165000006B3DE ++:03016600000D1079 ++:0301670000003263 ++:03016800000C0088 ++:0301690000003360 ++:03016A00000C7016 ++:03016B0000003958 ++:03016C00000C5034 ++:03016D0000003956 ++:03016E0000021577 ++:03016F000000305D ++:0301700000021674 ++:030171000000315A ++:0301720000020286 ++:0301730000003257 ++:03017400000C007C ++:030175000006B3CE ++:030176000002077D ++:0301770000003352 ++:03017800000C7008 ++:030179000000394A ++:03017A00000C5026 ++:03017B0000003948 ++:03017C00000C4034 ++:03017D0000003946 ++:03017E00000C0072 ++:03017F0000003944 ++:03018000000C0070 ++:03018100000C006F ++:03018200000ABFB1 ++:03018300000C026B ++:0301840000002F49 ++:03018500000C0A61 ++:0301860000002A4C ++:03018700000C0069 ++:0301880000002450 ++:030189000007D399 ++:03018A00000BA6C1 ++:03018B000002016E ++:03018C0000003040 ++:03018D0000090165 ++:03018E0000021557 ++:03018F000000303D ++:0301900000090162 ++:0301910000021653 ++:030192000000303A ++:030193000009015F ++:03019400000C1F3D ++:03019500000D80DA ++:0301960000002244 ++:0301970000020162 ++:0301980000003034 ++:0301990000090159 ++:03019A000002025E ++:03019B0000003031 ++:03019C0000090156 ++:03019D0000020459 ++:03019E000000302E ++:03019F0000090153 ++:0301A0000002EA70 ++:0301A10000071044 ++:0301A200000BA4AB ++:0301A300000B97B7 ++:0301A4000007D37E ++:0301A500000BC488 ++:0301A600000C1D2D ++:0301A7000006D37C ++:0301A800000D80C7 ++:0301A90000002231 ++:0301AA000002014F ++:0301AB0000003021 ++:0301AC0000090146 ++:0301AD000002024B ++:0301AE000000301E ++:0301AF0000090143 ++:0301B00000021832 ++:0301B1000000301B ++:0301B20000090140 ++:0301B30000021037 ++:0301B40000002E1A ++:0301B500000C1C1F ++:0301B6000006D36D ++:0301B700000D80B8 ++:0301B80000002222 ++:0301B90000020140 ++:0301BA0000003012 ++:0301BB0000090137 ++:0301BC000002023C ++:0301BD000000300F ++:0301BE0000090134 ++:0301BF0000021724 ++:0301C0000000300C ++:0301C10000090131 ++:0301C2000007D360 ++:0301C300000B8BA3 ++:0301C400000C002C ++:0301C50000002F08 ++:0301C6000007D35C ++:0301C700000B7EAC ++:0301C800000B58D1 ++:0301C900000C0720 ++:0301CA0000002F03 ++:0301CB00000C0421 ++:0301CC000000210F ++:0301CD00000C0023 ++:0301CE0000091E07 ++:0301CF00000C1011 ++:0301D0000000210B ++:0301D100000C0817 ++:0301D20000091E03 ++:0301D300000C40DD ++:0301D40000002107 ++:0301D500000C100B ++:0301D60000091EFF ++:0301D700000C0019 ++:0301D80000003AEA ++:0301D900000C0116 ++:0301DA00000029F9 ++:0301DB00000C0015 ++:0301DC0000002FF1 ++:0301DD00000C20F3 ++:0301DE00000023FB ++:0301DF00000A0013 ++:0301E000000ABF53 ++:0301E100000BE12F ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_2.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_2.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_2.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_2.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,416 @@ ++# ++# $Id: PIC_TYPE_2.hex 11078 2013-04-11 16:52:37Z dima $ ++# ++:03000000A5DA4836 ++:03000100C41C41DB ++:030002000390392F ++:0300030067967984 ++:03000400A03A031C ++:03000500C40C40E8 ++:030006000390392B ++:030007007797796F ++:03000800A07A07D4 ++:030009008008006C ++:03000A0002A02A27 ++:03000B00C04C04E2 ++:03000C000240248B ++:03000D00C00C0024 ++:03000E0002502578 ++:03000F0036536500 ++:0300100020A20A21 ++:03001100E01E01ED ++:0300120012512563 ++:0300130032A32AEB ++:030014002E42E495 ++:03001500A0FA0F3F ++:030016008008005F ++:0300170020D21DD7 ++:0300180062410B37 ++:0300190020E038AC ++:03001A00025C2065 ++:03001B0020AD40D5 ++:03001C0064312527 ++:03001D00A23C20E2 ++:03001E0032502439 ++:03001F00325C0050 ++:030020002C80220F ++:03002100D0020505 ++:03002200A1C0304A ++:0300230020590160 ++:03002400E03204C3 ++:0300250002103096 ++:03002600CFC9013E ++:030027001652026C ++:0300280064403001 ++:03002900A38901A7 ++:03002A00704C40D7 ++:03002B00A47FFFB0 ++:03002C00C40165A7 ++:03002D00150C02AD ++:03002E00743FFF1D ++:03002F00A32150BA ++:03003000C026B92E ++:03003100A33D02EA ++:03003200C01022D9 ++:03003300121C029A ++:03003400C03D01CB ++:030035001611623F ++:0300360020120590 ++:0300370012503034 ++:0300380020A901FB ++:030039006432042A ++:03003A00A40030EF ++:03003B0036590132 ++:03003C0036520237 ++:03003D002C8030E4 ++:03003E00D00901E5 ++:03003F00A3980083 ++:0300400020521437 ++:03004100724E708C ++:03004200A44308CC ++:03004300A46308AB ++:0300440002D308DC ++:03004500A4730899 ++:0300460002E03F96 ++:030047008008002E ++:03004800022C0087 ++:03004900206039FB ++:03004A00643038E7 ++:03004B00A50C07FA ++:03004C00322D4012 ++:03004D002C8034D0 ++:03004E00D00C08CB ++:03004F00A4A03832 ++:03005000CFE219E3 ++:03005100162E0761 ++:03005200C01020BB ++:03005300604360A7 ++:0300540012236014 ++:03005500206360C5 ++:03005600643360B0 ++:03005700A5CC1025 ++:0300580036203817 ++:030059002C8219DD ++:03005A00D00E07BE ++:03005B00A561207C ++:03005C00800C20F5 ++:03005D00C07180EF ++:03005E00166E70AB ++:03005F00743743B0 ++:03006000A65A702D ++:03006100C01C02BE ++:030062001CC1803E ++:03006300E07E0735 ++:0300640002C6438E ++:03006500200A73FB ++:03006600022C0366 ++:0300670020618095 ++:03006800643E07EC ++:03006900A6E643C5 ++:03006A00322A73C4 ++:03006B002C8C04D6 ++:03006C00D0018040 ++:03006D00A68E0755 ++:03006E00C0164376 ++:03006F00142A73DD ++:03007000743C01DC ++:03007100ACB038F8 ++:03007200206A728F ++:0300730090AC1836 ++:03007400205038E1 ++:03007500D202199B ++:03007600D40E0F96 ++:0300770003D02291 ++:03007800C04C0079 ++:030079000220382A ++:03007A00C00200C1 ++:03007B00024E072B ++:03007C0021DF027F ++:03007D0003074333 ++:03007E00901A8352 ++:03007F00202C0032 ++:0300800003003149 ++:03008100901C12BE ++:03008200204A9081 ++:0300830003020075 ++:03008400901E07C4 ++:03008500210F0345 ++:03008600E017433D ++:03008700643A8C4C ++:03008800ACBC000D ++:0300890021003122 ++:03008A00024C180D ++:03008B00E80A90F0 ++:03008C00743C00C1 ++:03008D00AB803114 ++:03008E00C50C1688 ++:03008F00039A9041 ++:0300900079903B29 ++:03009100A90E0FA6 ++:0300920020B08219 ++:03009300D0070390 ++:03009400038A9A42 ++:03009500219C0F9C ++:03009600E07FFF09 ++:0300970034815B56 ++:03009800348102AE ++:03009900348A9B0B ++:03009A0034821B92 ++:03009B000300302F ++:03009C00206E0FC4 ++:03009D0034803B71 ++:03009E00348C029D ++:03009F0034803971 ++:0300A000348C009D ++:0300A100D0503903 ++:0300A200031C80BC ++:0300A300C00D0885 ++:0300A400032039FD ++:0300A500033C0019 ++:0300A600C7003957 ++:0300A700039C4077 ++:0300A800C5003957 ++:0300A9000397D9E1 ++:0300AA00C04AA9A0 ++:0300AB00030C0043 ++:0300AC00C000266B ++:0300AD0003102716 ++:0300AE0020402BC4 ++:0300AF000320200B ++:0300B000C00C037E ++:0300B10003302CED ++:0300B200C70C2058 ++:0300B300039D802A ++:0300B400C500255F ++:0300B500039C2089 ++:0300B600C400245F ++:0300B700039C00A7 ++:0300B800C400225F ++:0300B900FFF2054E ++:0300BA00165030AD ++:0300BB00D2090166 ++:0300BC0003D20468 ++:0300BD00C0403010 ++:0300BE0002290113 ++:0300BF00C002027A ++:0300C000150030F8 ++:0300C100024901F0 ++:0300C20021DC40FE ++:0300C300030039FE ++:0300C400901C018C ++:0300C500202037C1 ++:0300C600030C60C8 ++:0300C7009012C8CC ++:0300C800204AC704 ++:0300C900030C0025 ++:0300CA009010375C ++:0300CB002066D9D3 ++:0300CC0090AAD027 ++:0300CD002056F9C1 ++:0300CE00D20B4D05 ++:0300CF00D40ACB85 ++:0300D00003D94011 ++:0300D100C1CC207F ++:0300D20002219573 ++:0300D300C0064321 ++:0300D400024ADFFE ++:0300D50021DC012A ++:0300D6000301DF44 ++:0300D70090109BEB ++:0300D800202703DB ++:0300D900030ADF38 ++:0300DA009017D3A9 ++:0300DB00204B486F ++:0300DC00030CFF13 ++:0300DD009010225E ++:0300DE00210B2AC9 ++:0300DF0002421FBB ++:0300E000C0390A1A ++:0300E100084C20A8 ++:0300E20060312565 ++:0300E300AE66D333 ++:0300E400209AEA75 ++:0300E500AE8C20BE ++:0300E600C00095C2 ++:0300E700AE86439F ++:0300E800187AF291 ++:0300E900149AEF77 ++:0300EA00643C4033 ++:0300EB00B17125CB ++:0300EC001A7C007B ++:0300ED00C5002427 ++:0300EE00039B1A57 ++:0300EF00799217EC ++:0300F000AEF0244B ++:0300F10020BB1A17 ++:0300F200D00C40EF ++:0300F30003810581 ++:0300F40021903D1B ++:0300F500E07C00AC ++:0300F6003480242F ++:0300F70034821D33 ++:0300F80034803021 ++:0300F90034890146 ++:0300FA00030215E9 ++:0300FB0020603052 ++:0300FC0034890143 ++:0300FD0034820446 ++:0300FE003480301B ++:0300FF0034890140 ++:03010000D05210CA ++:03010100031024C4 ++:03010200C007F73C ++:03010300032B0BC0 ++:03010400033C02B7 ++:03010500C70FFF22 ++:03010600039164FE ++:03010700C50C0222 ++:0301080003915709 ++:03010900C1C1244D ++:03010A00030B17CD ++:03010B00C007D753 ++:03010C00031B17BB ++:03010D00204C0182 ++:03010E00032FFFBD ++:03010F00C00164C8 ++:03011000033C01AC ++:03011100C70157CC ++:0301120003912432 ++:03011300C50B1702 ++:030114000392173C ++:03011500C40024FF ++:03011600039B1731 ++:0301170020CC02F7 ++:03011800743D0132 ++:03011900B8316496 ++:03011A00C00C8096 ++:03011B000246F3A6 ++:03011C00C05125AA ++:03011D00022205B6 ++:03011E002050303E ++:03011F00D2090101 ++:03012000D40215F1 ++:0301210003D030D8 ++:0301220021D901DF ++:03012300030204D0 ++:0301240090103008 ++:030125002029018D ++:030126000307D3F9 ++:03012700901B48E2 ++:0301280020421062 ++:03012900030022AE ++:03012A00901C50D6 ++:03012B00C01039C8 ++:03012C001507991B ++:03012D00024B2C56 ++:03012E0021A212F9 ++:03012F0094803089 ++:0301300020221476 ++:0301310003A031F7 ++:0301320020621335 ++:03013300743032F3 ++:03013400B41C00F8 ++:03013500C9F033DB ++:0301360016BC7084 ++:03013700C00039CC ++:030138006B0C50FD ++:03013900D20039B8 ++:03013A006D02153E ++:03013B00D40030BD ++:03013C0012BC00F2 ++:03013D00C80031C6 ++:03013E001AB202F0 ++:03013F0020B032BB ++:03014000038C002D ++:0301410020603308 ++:0301420002AC709C ++:03014300C0403980 ++:03014400086C50F4 ++:03014500703039DE ++:03014600B4AC4016 ++:03014700C00039BC ++:03014800024C0066 ++:03014900B4E039E6 ++:03014A00C04C00A6 ++:03014B000AAC00FB ++:03014C00C02AC204 ++:03014D00024C0061 ++:03014E0091702588 ++:03014F00C01C10C1 ++:0301500003E03D8C ++:030151002069170B ++:03015200643C0406 ++:03015300B570255F ++:0301540037EC0085 ++:030155002C803DBE ++:03015600B5491791 ++:03015700C60C02D1 ++:030158001500256A ++:03015900743C08EB ++:03015A00B6B03DFF ++:03015B0021E91780 ++:03015C001AFC008A ++:03015D0014F02675 ++:03015E00743C01ED ++:03015F00B830298C ++:03016000C04C2070 ++:0301610012402326 ++:03016200917A008F ++:03016300C00B636B ++:0301640002400056 ++:0301650020000077 ++:0301660094800082 ++:0301670020200055 ++:0301680002000092 ++:0301690003500040 ++:03016A00B83000AA ++:03016B00CFF000D2 ++:03016C0019E00097 ++:03016D0016F00089 ++:03016E00C030009E ++:03016F0008100075 ++:03017000743000E8 ++:03017100B7A00034 ++:03017200C01000BA ++:0301730002400047 ++:0301740020000068 ++:0301750094800073 ++:0301760020200046 ++:0301770002000083 ++:0301780003500031 ++:03017900B830009B ++:03017A00C00000C2 ++:03017B0018100059 ++:03017C00643000EC ++:03017D006B000014 ++:03017E00B80000C6 ++:03017F00B8300095 ++:03018000C01000AC ++:0301810012400029 ++:0301820091700079 ++:03018300369000B3 ++:03018400C01000A8 ++:030185001E6000F9 ++:0301860021B000A5 ++:030187000860000D ++:03018800743000D0 ++:03018900A5D000FE ++:03018A0002600010 ++:03018B00C0200091 ++:03018C00FFF00081 ++:03018D0016B000A9 ++:03018E00C020008E ++:03018F0023A000AA ++:03019000743000C8 ++:0301910012B000A9 ++:0301920020B0009A ++:03019300038000E6 ++:03019400C4400064 ++:03019500039000D4 ++:03019600C40000A2 ++:03019700039000D2 ++:03019800C00000A4 ++:0301990002300031 ++:03019A00AC200096 ++:03019B00B9B000F8 ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_3.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_3.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_3.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_3.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,374 @@ ++# ++# $Id: PIC_TYPE_3.hex 7107 2009-05-18 12:35:20Z dima $ ++# ++:03000000A0AC00B1 ++:03000100C41039EF ++:0300020003903830 ++:03000300679C08EF ++:03000400A03038F1 ++:03000500C4021919 ++:03000600039E074F ++:03000700779020CF ++:03000800A0736082 ++:0300090080036011 ++:03000A00C0F360E0 ++:03000B000343604C ++:03000C00C08C1095 ++:03000D0003803835 ++:03000E0021921923 ++:03000F00E07E0789 ++:03001000020120CA ++:03001100360C307A ++:0300120036018034 ++:03001300360E7036 ++:030014003606436A ++:03001500C10A1904 ++:03001600038C0157 ++:03001700219038FD ++:03001800E07A1873 ++:03001900120C20A6 ++:03001A00C30023FD ++:03001B00180A0AB6 ++:03001C00E70C41AD ++:03001D0074303903 ++:03001E00A20679BE ++:03001F00A23A1EE4 ++:03002000C01C40C1 ++:0300210003803920 ++:03002200A2277999 ++:03002300C18A226D ++:030024000388004E ++:03002500219C40DB ++:03002600E0F039CE ++:0300270002BC0018 ++:03002800C0003ADB ++:030029000386F952 ++:03002A00C00A7E8B ++:03002B0002C7D930 ++:03002C0002EA27BE ++:03002D00C4020901 ++:03002E0060C02C83 ++:03002F00D01C40A2 ++:030030000276D481 ++:03003100C16D019D ++:0300320020802704 ++:03003300030C00BB ++:030034002076D45F ++:03003500031D01A7 ++:03003600901029FE ++:03003700C006F40C ++:03003800D80A9B48 ++:03003900029C1610 ++:03003A00C00208F9 ++:03003B00208030F2 ++:03003C00030207B5 ++:03003D00209031DF ++:03003E0003191C87 ++:03003F0090121408 ++:03004000C63F10A8 ++:03004100090308A8 ++:030042007433080C ++:03004300A4C3084B ++:03004400C04308AE ++:030045001EEE03A9 ++:03004600C01208DD ++:030047001EC030A8 ++:03004800C02209CA ++:0300490008C031BB ++:03004A0074391CEA ++:03004B00A2D21529 ++:03004C0020E03081 ++:03004D0008B207EF ++:03004E00703031DE ++:03004F00A5291CC4 ++:0300500020B209D2 ++:0300510002E6D3F1 ++:03005200C08D80DE ++:0300530008E02A98 ++:0300540060321700 ++:03005500A5903043 ++:03005600C0220ABB ++:03005700D40031A1 ++:03005800A6A91C3A ++:03005900C017D3FA ++:03005A0003BA796D ++:03005B00C04C5046 ++:03005C0008E03980 ++:03005D0070379960 ++:03005E00A66A5D32 ++:03005F0020E2128A ++:03006000348030B9 ++:03006100348214D2 ++:03006200348031B6 ++:03006300348213D1 ++:0300640011B032A6 ++:03006500A6AC0046 ++:03006600C0403364 ++:0300670002EC7038 ++:0300680021B0398B ++:03006900D40C5064 ++:03006A0003B039A7 ++:03006B00C00215BB ++:03006C0002C0309F ++:03006D0002A216D6 ++:03006E00C400319A ++:03006F000272100A ++:03007000C000329B ++:03007100029C00EE ++:03007200C0103388 ++:0300730022CC702C ++:03007400743039AC ++:03007500A7AC50E5 ++:03007600C0F0399E ++:0300770002BC4088 ++:03007800C4C039C8 ++:03007900A8BC0020 ++:03007A0008C03982 ++:03007B007436D9FF ++:03007C00A81A7B44 ++:03007D00C07A2521 ++:03007E0002B21AB1 ++:03007F00C4AE709C ++:03008000A8B743DB ++:0300810020CA8A08 ++:0300820002BC803D ++:03008300C02D0F7E ++:030084000AB0348B ++:0300850032BC0486 ++:030086007030389F ++:03008700A8AC140E ++:03008800C802C8E3 ++:03008900129A8840 ++:03008A00C48C40E3 ++:03008B00208027AB ++:03008C00030C0161 ++:03008D002076DA00 ++:03008E0003112734 ++:03008F00901C00C2 ++:0300900020B02974 ++:03009100030C015C ++:030092002096DADB ++:030093000311292D ++:03009400901209BE ++:03009500210D80BA ++:0300960034802C87 ++:03009700348C00A6 ++:03009800348D0F95 ++:030099003480347C ++:03009A0002BAACFB ++:03009B00C80C0787 ++:03009C0014B15448 ++:03009D007E964309 ++:03009E00AA1AA0FB ++:03009F0032AAA8DA ++:0300A00012AC009F ++:0300A100C0177411 ++:0300A2001ECC80F1 ++:0300A300C12D0864 ++:0300A40008C03958 ++:0300A500743C00A8 ++:0300A600A6E03998 ++:0300A70020AA2567 ++:0300A80002B20998 ++:0300A90032B02C46 ++:0300AA00C5521428 ++:0300AB0016A03A62 ++:0300AC0016B21A6F ++:0300AD0034AE303E ++:0300AE0010BF1070 ++:0300AF0003130830 ++:0300B00021BD046B ++:0300B1000306EC57 ++:0300B200C02D015D ++:0300B30003902F88 ++:0300B400C00C0F6E ++:0300B500039208AB ++:0300B600C0003057 ++:0300B7000232070B ++:0300B800A2503122 ++:0300B90020591CAF ++:0300BA0008420FEA ++:0300BB00E3F20865 ++:0300BC0002D0303F ++:0300BD0020120905 ++:0300BE000A003104 ++:0300BF00C0191C49 ++:0300C00022020910 ++:0300C100743D800B ++:0300C2001ED02A23 ++:0300C300C05C001E ++:0300C40002B02B5C ++:0300C50020DC1C20 ++:0300C60008B20875 ++:0300C70060303076 ++:0300C800ACA207E0 ++:0300C900ACF03167 ++:0300CA00C0591CFE ++:0300CB0002DC0054 ++:0300CC00C0020867 ++:0300CD0002B0304E ++:0300CE00AD420A36 ++:0300CF00220031DB ++:0300D00064391C74 ++:0300D100B4221046 ++:0300D200C016282D ++:0300D30002BAC5A9 ++:0300D40021A60B57 ++:0300D500E70B6DC9 ++:0300D600D8020944 ++:0300D70003AD80F6 ++:0300D80020D02A0B ++:0300D90013AC0C59 ++:0300DA00C0020859 ++:0300DB0002603090 ++:0300DC0020D20728 ++:0300DD006430315B ++:0300DE00B0591CFA ++:0300DF00C01C0042 ++:0300E0000AD20839 ++:0300E1001E60306E ++:0300E200C8020A47 ++:0300E30020803149 ++:0300E40003091CF1 ++:0300E50020721076 ++:0300E600031020E4 ++:0300E700901C0D5D ++:0300E800C002084B ++:0300E90020803044 ++:0300EA0003020707 ++:0300EB0020C03101 ++:0300EC0003191CD9 ++:0300ED00901C0064 ++:0300EE002C620879 ++:0300EF00AF3030FF ++:0300F00021020AE0 ++:0300F10003B03128 ++:0300F200B0491CF6 ++:0300F3002C82104C ++:0300F400AF8021B9 ++:0300F500210C04D7 ++:0300F60003C2083A ++:0300F700B04030E6 ++:0300F8002C820750 ++:0300F900AFD03154 ++:0300FA0021091CBD ++:0300FB0003DC0023 ++:0300FC00B0420807 ++:0300FD002C803024 ++:0300FE00B0220A23 ++:0300FF00210031AC ++:0301000003E91CF4 ++:03010100B04210F9 ++:03010200210024B5 ++:0301030003FC06F4 ++:03010400ADC20881 ++:0301050070B030A7 ++:03010600B24207FB ++:03010700C0E03124 ++:0301080020891C2F ++:03010900030C00E4 ++:03010A0020720858 ++:03010B00031030AE ++:03010C0090120A44 ++:03010D00C01031EE ++:03010E0020891C29 ++:03010F00030210D8 ++:0301100020902517 ++:03011100031C14B8 ++:0301120090120840 ++:03011300C0803079 ++:0301140013A2072C ++:03011500C1C03135 ++:0301160020891C21 ++:03011700030C00D6 ++:030118002072084A ++:03011900031030A0 ++:03011A0090120A36 ++:03011B00C00031F0 ++:03011C0020891C1B ++:03011D00030210CA ++:03011E0020A026F8 ++:03011F00031C209E ++:0301200090102319 ++:030121002106ECC8 ++:03012200628AB935 ++:03012300B15C00CC ++:03012400C50023F0 ++:03012500039C0731 ++:0301260079902BA2 ++:03012700B26201C0 ++:03012800C0008094 ++:03012900030E07BB ++:03012A0021A08B86 ++:03012B0003164375 ++:03012C0021BA25D0 ++:03012D00032C3F61 ++:03012E00C0002BE3 ++:03012F0003320692 ++:03013000C700AB5A ++:0301310003921422 ++:03013200C50E07F0 ++:0301330003902D09 ++:0301340021C0AB3C ++:03013500030603BB ++:0301360021DA25A6 ++:03013700031C00A6 ++:0301380021E0269D ++:0301390003220D91 ++:03013A0021F64368 ++:03013B00033B5C27 ++:03013C00C70C01EC ++:03013D000390AD7F ++:03013E00C501E612 ++:03013F00039C809E ++:03014000C40208EE ++:03014100039030F8 ++:03014200C70207EA ++:0301430017A031D1 ++:03014400C1091CD2 ++:030145001FA2C630 ++:0301460031AB4991 ++:03014700308213F0 ++:03014800308B56A3 ++:030149003082C839 ++:03014A0018EB4D62 ++:03014B0064321506 ++:03014C00B50B569A ++:03014D00C002C825 ++:03014E00023B5120 ++:03014F00A2921663 ++:03015000C00B568B ++:0301510003A2C83E ++:03015200C44B5546 ++:03015300039217FD ++:03015400C40B5683 ++:03015500039218FA ++:03015600C00208DC ++:0301570002303043 ++:03015800A2520CA4 ++:0301590000003172 ++:03015A0000091C7D ++:03015B00000B395D ++:03015C0000077425 ++:03015D00000B6D27 ++:03015E00000C0E84 ++:03015F0000020893 ++:030160000000306C ++:0301610000020792 ++:0301620000003169 ++:0301630000091C74 ++:03016400000C018B ++:030165000002088D ++:0301660000003066 ++:030167000002098A ++:0301680000003163 ++:0301690000091C6E ++:03016A00000C0185 ++:03016B0000002B66 ++:03016C00000AC5C1 ++:03016D00000C0083 ++:03016E0000003955 ++:03016F000006D9AE ++:03017000000B6F12 ++:03017100000A255C ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,360 @@ ++# ++# $Id: PIC_TYPE_4.hex 7831 2010-05-11 16:53:41Z dima $ ++# ++:03000000A0AA0AA9 ++:03000100C41C41DB ++:030002000390392F ++:0300030067967984 ++:03000400A03A031C ++:03000500C40C40E8 ++:030006000390392B ++:030007007797796F ++:03000800A07A07D4 ++:030009008008006C ++:03000A00000C00E7 ++:03000B00000039B9 ++:03000C00000038B9 ++:03000D00000CFFE5 ++:03000E000002C825 ++:03000F00000A0ED6 ++:03001000000C00E1 ++:03001100000038B4 ++:03001200000C17C8 ++:03001300000034B6 ++:0300140000002BBE ++:03001500000C08D4 ++:03001600000038AF ++:03001700000219CB ++:03001800000E07D0 ++:03001900000020C4 ++:03001A0000036080 ++:03001B000003607F ++:03001C000003607E ++:03001D000003607D ++:03001E00000C10C3 ++:03001F00000038A6 ++:03002000000219C2 ++:03002100000E07C7 ++:03002200000120BA ++:03002300000C408E ++:0300240000018058 ++:03002500000E705A ++:030026000007438D ++:03002700000A29A3 ++:03002800000A2C9F ++:03002900000C01C7 ++:03002A000000389B ++:03002B00000A2B9D ++:03002C00000C18AD ++:03002D0000003898 ++:03002E00000219B4 ++:03002F00000E0FB1 ++:0300300000002E9F ++:03003100000C00C0 ++:0300320000003893 ++:03003300000C00BE ++:03003400000024A5 ++:0300350000002D9B ++:0300360000002C9B ++:03003700000C902A ++:030038000000299C ++:03003900000C00B8 ++:03003A00000021A2 ++:03003B00000C8234 ++:03003C000000229F ++:03003D00000201BD ++:03003E000000328D ++:03003F00000202BA ++:030040000000318C ++:03004100000209B1 ++:030042000000308B ++:03004300000901B0 ++:03004400000C832A ++:0300450000002296 ++:03004600000201B4 ++:0300470000003284 ++:03004800000202B1 ++:0300490000003183 ++:03004A00000209A8 ++:03004B0000003082 ++:03004C00000901A7 ++:03004D00000C04A0 ++:03004E0000008E21 ++:03004F00000703A4 ++:03005000000A544F ++:0300510000020E9C ++:0300520000002F7C ++:03005300000A564A ++:03005400000C0499 ++:0300550000002F79 ++:0300560000036F35 ++:0300570000036F34 ++:0300580000036F33 ++:0300590000036F32 ++:03005A00000C0196 ++:03005B0000012F72 ++:03005C0000020F90 ++:03005D0000003070 ++:03005E00000C0093 ++:03005F000000316D ++:03006000000C028F ++:0300610000003963 ++:03006200000C008F ++:0300630000003961 ++:03006400000C404D ++:030065000000395F ++:030066000007D9B7 ++:03006700000ACCC0 ++:03006800000C0089 ++:030069000007D3BA ++:03006A00000A6C1D ++:03006B00000D8005 ++:03006C0000002170 ++:03006D000002147A ++:03006E00000E3051 ++:03006F0000030883 ++:0300700000030882 ++:0300710000030881 ++:0300720000030880 ++:0300730000012168 ++:0300740000020186 ++:0300750000003256 ++:0300760000021570 ++:0300770000003155 ++:030078000002176C ++:0300790000003054 ++:03007A0000090179 ++:03007B00000C2155 ++:03007C00000195EB ++:03007D0000074336 ++:03007E00000A91E4 ++:03007F000006D3A5 ++:03008000000A91E2 ++:03008100000C016F ++:0300820000002A51 ++:0300830000020177 ++:03008400000E0368 ++:030085000006432F ++:03008600000A8BE2 ++:0300870000036A09 ++:030088000002C8AB ++:03008900000D0067 ++:03008A00000A85E4 ++:03008B00000CFF67 ++:03008C0000018AE6 ++:03008D0000014C23 ++:03008E000006D792 ++:03008F0000010A63 ++:0300900000002C41 ++:03009100000C1D43 ++:03009200000195D5 ++:0300930000074320 ++:03009400000AA7B8 ++:030095000006D38F ++:03009600000AA7B6 ++:03009700000C0159 ++:0300980000002A3B ++:0300990000020161 ++:03009A00000E0352 ++:03009B0000064319 ++:03009C00000AA1B6 ++:03009D0000036AF3 ++:03009E000002C895 ++:03009F00000D0051 ++:0300A000000A9BB8 ++:0300A100000CFF51 ++:0300A20000018AD0 ++:0300A30000015AFF ++:0300A400000697BC ++:0300A50000010A4D ++:0300A60000003A1D ++:0300A7000007D37C ++:0300A800000AC784 ++:0300A900000C50F8 ++:0300AA000000391A ++:0300AB00000799B2 ++:0300AC00000AAB9C ++:0300AD000002123C ++:0300AE000000301F ++:0300AF0000021438 ++:0300B0000000311C ++:0300B10000021337 ++:0300B20000003219 ++:0300B300000C003E ++:0300B40000003316 ++:0300B500000C70CC ++:0300B6000000390E ++:0300B700000C50EA ++:0300B8000000390C ++:0300B9000002152D ++:0300BA0000003013 ++:0300BB000002162A ++:0300BC0000003110 ++:0300BD000002102E ++:0300BE000000320D ++:0300BF00000C0032 ++:0300C0000000330A ++:0300C100000C70C0 ++:0300C20000003902 ++:0300C300000C50DE ++:0300C40000003900 ++:0300C500000C40EC ++:0300C600000039FE ++:0300C700000C002A ++:0300C800000039FC ++:0300C900000C0028 ++:0300CA00000C0027 ++:0300CB00000A64C4 ++:0300CC0000036DC1 ++:0300CD000002042A ++:0300CE00000E031E ++:0300CF00000743E4 ++:0300D000000AD350 ++:0300D100000C011F ++:0300D20000002DFE ++:0300D300000C001E ++:0300D40000002900 ++:0300D50000020422 ++:0300D600000D809A ++:0300D70000002105 ++:0300D800000C68B1 ++:0300D90000002202 ++:0300DA0000020120 ++:0300DB00000032F0 ++:0300DC000002021D ++:0300DD00000031EF ++:0300DE0000020914 ++:0300DF00000030EE ++:0300E00000090113 ++:0300E1000002100A ++:0300E200000E0805 ++:0300E300000643D1 ++:0300E400000B53BB ++:0300E50000020412 ++:0300E600000D808A ++:0300E700000021F5 ++:0300E800000C62A7 ++:0300E900000022F2 ++:0300EA0000020110 ++:0300EB00000032E0 ++:0300EC000002020D ++:0300ED00000031DF ++:0300EE0000020904 ++:0300EF00000030DE ++:0300F00000090103 ++:0300F10000020CFE ++:0300F20000014DBD ++:0300F300000643C1 ++:0300F400000AF708 ++:0300F500000210F6 ++:0300F600000AF805 ++:0300F700000C00FA ++:0300F800000025E0 ++:0300F900000204FE ++:0300FA00000D8076 ++:0300FB00000021E1 ++:0300FC00000C6392 ++:0300FD00000022DE ++:0300FE00000201FC ++:0300FF00000032CC ++:03010000000202F8 ++:03010100000031CA ++:03010200000209EF ++:03010300000030C9 ++:03010400000901EE ++:0301050000020CE9 ++:0301060000014DA8 ++:03010700000643AC ++:03010800000B0BDE ++:03010900000210E1 ++:03010A00000B0CDB ++:03010B00000C00E5 ++:03010C00000026CA ++:03010D0000021AD3 ++:03010E0000014DA0 ++:03010F00000643A4 ++:03011000000B13CE ++:03011100000C0FD0 ++:0301120000016683 ++:03011300000C00DD ++:03011400000027C1 ++:03011500000C01DA ++:03011600000145A0 ++:030117000006439C ++:03011800000B4693 ++:03011900000C7067 ++:03011A000001C71A ++:03011B00000022BF ++:03011C00000201DD ++:03011D00000032AD ++:03011E00000202DA ++:03011F00000031AC ++:03012000000209D1 ++:03012100000030AB ++:03012200000901D0 ++:03012300000C507D ++:030124000000399F ++:0301250000079937 ++:03012600000B25A6 ++:03012700000C00C9 ++:03012800000030A4 ++:03012900000204CD ++:03012A0000034887 ++:03012B0000034886 ++:03012C0000034885 ++:03012D0000034884 ++:03012E00000D05BC ++:03012F000000319C ++:03013000000C00C0 ++:0301310000003299 ++:03013200000C00BE ++:0301330000003396 ++:03013400000C704C ++:030135000000398E ++:03013600000C506A ++:030137000000398C ++:03013800000202C0 ++:0301390000003093 ++:03013A00000C00B6 ++:03013B0000003190 ++:03013C00000210AE ++:03013D000000328D ++:03013E00000C00B2 ++:03013F000000338A ++:03014000000C7040 ++:0301410000003982 ++:03014200000C505E ++:0301430000003980 ++:03014400000C406C ++:030145000000397E ++:030146000003258E ++:03014700000C01A8 ++:030148000001E7CC ++:03014900000C089F ++:03014A000000872B ++:03014B0000074367 ++:03014C00000B4F56 ++:03014D00000206A7 ++:03014E0000002589 ++:03014F00000C1091 ++:0301500000008725 ++:0301510000074361 ++:03015200000B158A ++:03015300000C019C ++:030154000001C4E3 ++:03015500000E0396 ++:0301560000002482 ++:030157000002089B ++:030158000007435A ++:03015900000B6236 ++:03015A0000020B95 ++:03015B00000D8014 ++:03015C000000346C ++:03015D00000C3A59 ++:03015E000002C8D4 ++:03015F00000B5E34 ++:0301600000020B8F ++:0301610000003467 ++:03016200000A642C ++:03016300000B632B ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_6.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_6.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/PIC_TYPE_6.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/PIC_TYPE_6.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,460 @@ ++# ++# $Id: PIC_TYPE_6.hex 11526 2016-04-05 13:30:04Z dima $ ++# ++:03000000A1CA5042 ++:03000100C41C41DB ++:0300020069969963 ++:03000300D50D50C8 ++:030004000390392D ++:0300050067967982 ++:03000600A05A05F8 ++:03000700C40C40E6 ++:030008006996995D ++:03000900D50D50C2 ++:03000A0003903927 ++:03000B007797796B ++:03000C00A0BA0B8C ++:03000D0080080068 ++:03000E00F01F01DF ++:03000F00022022AA ++:03001000C05C05CC ++:0300110002402486 ++:03001200C00C001F ++:03001300021021B7 ++:030014003613613F ++:03001500202202A4 ++:03001600E01E01E8 ++:03001700121121A2 ++:030018003223226E ++:030019002E42E490 ++:03001A00A14A14E4 ++:03001B008008005A ++:03001C00C0010B15 ++:03001D0019A038EF ++:03001E00743C57D8 ++:03001F00A24D40AF ++:03002000C01034D9 ++:030021001CCC42B2 ++:03002200E07D017D ++:0300230002C021F7 ++:03002400C07C138A ++:0300250018C024DC ++:03002600643C0433 ++:03002700A4C0373B ++:0300280020C201F2 ++:03002900743032FE ++:03002A00AC3204F1 ++:03002B0021A031E0 ++:03002C0090E2025D ++:03002D00C20030DE ++:03002E00D40901F1 ++:03002F00121C00A0 ++:03003000C1E037F5 ++:03003100024C423C ++:03003200C00021EA ++:03003300022202A4 ++:03003400201FFF8B ++:0300350003015074 ++:030036009016B968 ++:0300370020410263 ++:03003800030022A0 ++:03003900901C0414 ++:03003A002020374C ++:03003B00030201BC ++:03003C00901032EF ++:03003D00C11204E9 ++:03003E0019003175 ++:03003F0064320226 ++:03004000A4503099 ++:03004100C22901D0 ++:03004200190C0096 ++:03004300743037DF ++:03004400A48C0782 ++:03004500209D40BB ++:0300460012503421 ++:03004700A4B8005A ++:03004800209214EF ++:03004900FFFE7047 ++:03004A0016530842 ++:03004B00AC3308CB ++:03004C0021A308E5 ++:03004D0090E30835 ++:03004E00C20027C6 ++:03004F00D40800D2 ++:03005000121C007F ++:03005100209039C3 ++:030052001450380F ++:0300530064303FD7 ++:03005400AC3C07BA ++:03005500C22D4079 ++:0300560002403431 ++:03005700C00C08D2 ++:030058000220384B ++:0300590020121959 ++:03005A00030E078B ++:03005B00901020E2 ++:03005C00204360DE ++:03005D000303603A ++:03005E009013609C ++:03005F00202360FB ++:03006000030C107E ++:03006100901038C4 ++:03006200C02219A0 ++:03006300150E0770 ++:03006400643120E4 ++:03006500A69C183E ++:03006600209038AF ++:0300670013E21988 ++:03006800A6CE0F12 ++:03006900209022C2 ++:03006A00FFFC0098 ++:03006B0017E03863 ++:03006C0021E2008E ++:03006D00035E0728 ++:03006E00C13CFF93 ++:03006F000240311B ++:03007000C00C18A9 ++:03007100022A72EE ++:0300720020103C1F ++:0300730003003057 ++:03007400901E0FCC ++:0300750020403CEC ++:03007600030C0276 ++:03007700901039AD ++:03007800202C0039 ++:0300790003003948 ++:03007A00901C0FC8 ++:03007B002100223F ++:03007C00027C8083 ++:03007D00C3C024D9 ++:03007E00024C0829 ++:03007F00C00104B9 ++:0300800002203922 ++:03008100201C0040 ++:030082000300393F ++:03008300901C00CE ++:0300840020403ADF ++:0300850003002B4A ++:03008600901020B7 ++:03008700202C0327 ++:0300880003002C46 ++:03008900901C4088 ++:03008A0021003919 ++:03008B0003B7D9DF ++:03008C00787A8BF4 ++:03008D00A91C406B ++:03008E0020903986 ++:03008F0013F6D98C ++:03009000A99A9496 ++:030091002096F9BD ++:0300920015FBB4A7 ++:03009300643A8F3D ++:03009400AC367314 ++:030095006BBA9CA7 ++:03009600AC39483A ++:03009700209207AD ++:030098001BF90E43 ++:03009900C50C2073 ++:03009A00039121AE ++:03009B00799AC48B ++:03009C00A9BC57A5 ++:03009D0020B0345C ++:03009E00D00C4241 ++:03009F00038021BA ++:0300A000219C019F ++:0300A100E07121EA ++:0300A200348C009B ++:0300A30034802284 ++:0300A400348C0495 ++:0300A5003480376D ++:0300A60003020151 ++:0300A70021A03263 ++:0300A8003482158A ++:0300A9003480316F ++:0300AA003482029B ++:0300AB003480306E ++:0300AC00D0590127 ++:0300AD00031C0031 ++:0300AE00C0003758 ++:0300AF000326D352 ++:0300B000033ADB35 ++:0300B100C70CFF7A ++:0300B2000391981F ++:0300B300C5015034 ++:0300B4000391179E ++:0300B500C3C022A3 ++:0300B600030C42F6 ++:0300B700C0002165 ++:0300B800031C0422 ++:0300B90021B0373C ++:0300BA000322011D ++:0300BB00C0003250 ++:0300BC00033215F7 ++:0300BD00C7003148 ++:0300BE00039202A8 ++:0300BF00C5003049 ++:0300C000039901A0 ++:0300C100C40C006C ++:0300C20003903771 ++:0300C300369ADB8F ++:0300C400C01C80DD ++:0300C5001FA6F380 ++:0300C60021C12134 ++:0300C70009A6B3D4 ++:0300C800743B077F ++:0300C900A1C7D3F9 ++:0300CA0003AAD0B6 ++:0300CB00C02C4006 ++:0300CC00FFF12120 ++:0300CD0016BC005E ++:0300CE00C020222D ++:0300CF0023EAD24F ++:0300D00074321770 ++:0300D10012B02248 ++:0300D20020B20158 ++:0300D30003803077 ++:0300D400C449011B ++:0300D5000392157E ++:0300D600C4003033 ++:0300D70003990189 ++:0300D800C0020261 ++:0300D900023030C2 ++:0300DA00A8D901A1 ++:0300DB00ADBC07B2 ++:0300DC00000D40D4 ++:0300DD00000034EC ++:0300DE000002100D ++:0300DF00000024FA ++:0300E0000007D343 ++:0300E100000BAF62 ++:0300E200000C50BF ++:0300E300000039E1 ++:0300E40000079979 ++:0300E500000AE42A ++:0300E60000021203 ++:0300E700000030E6 ++:0300E800000214FF ++:0300E900000031E3 ++:0300EA00000213FE ++:0300EB00000032E0 ++:0300EC00000C08FD ++:0300ED00000037D9 ++:0300EE00000218F5 ++:0300EF00000036D8 ++:0300F000000217F4 ++:0300F100000033D9 ++:0300F200000C00FF ++:0300F300000037D3 ++:0300F400000C708D ++:0300F500000039CF ++:0300F600000C50AB ++:0300F700000039CD ++:0300F800000215EE ++:0300F900000030D4 ++:0300FA00000C00F7 ++:0300FB00000031D1 ++:0300FC00000C00F5 ++:0300FD00000033CD ++:0300FE00000204F9 ++:0300FF00000032CC ++:03010000000C7080 ++:03010100000039C2 ++:03010200000C509E ++:03010300000039C0 ++:03010400000C40AC ++:03010500000039BE ++:03010600000BAF3C ++:03010700000C05E4 ++:03010800000024D0 ++:03010900000216DB ++:03010A00000022D0 ++:03010B00000C07DE ++:03010C000001628D ++:03010D00000C08DB ++:03010E00000122CB ++:03010F0000036288 ++:03011000000703E2 ++:03011100000B0FD1 ++:03011200000CE0FE ++:0301130000016286 ++:03011400000201E5 ++:03011500000030B7 ++:03011600000901DC ++:03011700000204DF ++:03011800000030B4 ++:03011900000901D9 ++:03011A00000202DE ++:03011B00000030B1 ++:03011C00000901D6 ++:03011D000007D305 ++:03011E00000B4192 ++:03011F00000C0AC7 ++:03012000000024B8 ++:03012100000215C4 ++:03012200000022B8 ++:03012300000201D6 ++:03012400000030A8 ++:03012500000901CD ++:03012600000204D0 ++:03012700000030A5 ++:03012800000901CA ++:03012900000202CF ++:03012A00000030A2 ++:03012B00000901C7 ++:03012C00000C0ABA ++:03012D00000027A8 ++:03012E00000C4082 ++:03012F00000121AB ++:03013000000C04BC ++:03013100000024A7 ++:03013200000C00BE ++:03013300000022A7 ++:03013400000201C5 ++:0301350000003097 ++:03013600000901BC ++:03013700000204BF ++:0301380000003094 ++:03013900000901B9 ++:03013A00000202BE ++:03013B0000003091 ++:03013C00000901B6 ++:03013D000002E7D6 ++:03013E00000710A7 ++:03013F00000B4171 ++:03014000000B347D ++:03014100000C08A7 ++:0301420000003783 ++:03014300000C09A4 ++:0301440000002494 ++:030145000002189D ++:0301460000002294 ++:03014700000201B2 ++:0301480000003084 ++:03014900000901A9 ++:03014A00000204AC ++:03014B0000003081 ++:03014C00000901A6 ++:03014D00000202AB ++:03014E000000307E ++:03014F00000901A3 ++:030150000002109A ++:0301510000002784 ++:03015200000C0896 ++:0301530000002485 ++:030154000002178F ++:0301550000002285 ++:03015600000C009A ++:030157000000376E ++:03015800000201A1 ++:0301590000003073 ++:03015A0000090198 ++:03015B000002049B ++:03015C0000003070 ++:03015D0000090195 ++:03015E000002029A ++:03015F000000306D ++:0301600000090192 ++:030161000007D3C1 ++:03016200000B751A ++:03016300000C503D ++:030164000000395F ++:03016500000799F7 ++:03016600000B6526 ++:0301670000021281 ++:0301680000003064 ++:030169000002147D ++:03016A0000003161 ++:03016B000002137C ++:03016C000000325E ++:03016D0000020786 ++:03016E0000003658 ++:03016F000002107B ++:0301700000003359 ++:03017100000C700F ++:0301720000003951 ++:03017300000C502D ++:030174000000394F ++:03017500000C0774 ++:0301760000002462 ++:030177000002186B ++:0301780000002262 ++:0301790000020180 ++:03017A0000003052 ++:03017B0000090177 ++:03017C000002047A ++:03017D000000304F ++:03017E0000090174 ++:03017F0000020279 ++:030180000000304C ++:0301810000090171 ++:0301820000021068 ++:0301830000002752 ++:03018400000C0666 ++:0301850000002453 ++:030186000002175D ++:0301870000002253 ++:0301880000020171 ++:0301890000003043 ++:03018A0000090168 ++:03018B000002046B ++:03018C0000003040 ++:03018D0000090165 ++:03018E000002026A ++:03018F000000303D ++:0301900000090162 ++:030191000007D391 ++:03019200000BA2BD ++:0301930000021552 ++:0301940000003038 ++:030195000002164F ++:0301960000003135 ++:030197000002075C ++:0301980000003331 ++:0301990000021051 ++:03019A0000003230 ++:03019B00000C70E5 ++:03019C0000003927 ++:03019D00000C5003 ++:03019E0000003925 ++:03019F00000C4011 ++:0301A00000003923 ++:0301A100000BAFA1 ++:0301A200000C0A44 ++:0301A30000002435 ++:0301A40000021541 ++:0301A50000002235 ++:0301A60000020153 ++:0301A70000003025 ++:0301A8000009014A ++:0301A9000002044D ++:0301AA0000003022 ++:0301AB0000090147 ++:0301AC000002024C ++:0301AD000000301F ++:0301AE0000090144 ++:0301AF00000C0041 ++:0301B00000003913 ++:0301B100000C003F ++:0301B200000C003E ++:0301B300000A8DB2 ++:0301B400000C0735 ++:0301B50000002F18 ++:0301B600000C0436 ++:0301B70000002223 ++:0301B800000C0038 ++:0301B90000091C1E ++:0301BA00000C1026 ++:0301BB000000221F ++:0301BC00000C082C ++:0301BD0000091C1A ++:0301BE00000C0032 ++:0301BF0000003A03 ++:0301C000000C012F ++:0301C10000002912 ++:0301C200000C002E ++:0301C30000002F0A ++:0301C400000C200C ++:0301C50000002314 ++:0301C600000A002C ++:0301C700000BC763 ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/README linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/README +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/README 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/README 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,19 @@ ++This distribution includes the firmware files required by the Xorcom[tm] ++Astribank[tm]. ++ ++This distribution inlcudes just the firmware files. Be sure to use a ++zaptel distribution/package of a matching version. ++ ++INSTALLATION ++"""""""""""" ++run "make install" as root. (which will simply copy all the *.hex files ++to /usr/share/zaptel ) ++ ++USAGE ++""""" ++When the firmware files are in place everything should work ++automagically. Consult the xpp documentation included in the package ++zaptel (or the debian package zaptel) that you use for further information. ++ ++ ++For further information contact support@xorcom.com http://xorcom.com +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_FW.201.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_FW.201.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_FW.201.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_FW.201.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,582 @@ ++# ++# $Id: USB_FW.201.hex 11502 2015-12-03 17:01:41Z dima $ ++# ++:03004300021F0099 ++:03005300021F0089 ++:101F0000021E4C00021EA900021E9300021E640065 ++:081F1000021C3B00021BC4008F ++:101000001201000200000040AAAAAAAAAAAA01028C ++:1010100003010A0600020000004001000902370037 ++:10102000020100C0000904000002FFFFFF040705E1 ++:101030000202000200070586020002000904010006 ++:1010400002FFFFFF050705040200020007058802F2 ++:10105000000200001201000200000040E4E451110F ++:101060000000010203010A06000200000040010026 ++:1010700009023700020100C0320904000002FFFF2C ++:10108000FF04070502024000000705860240000039 ++:101090000904010002FFFFFF0507050402400000EC ++:1010A0000705880240000006040016001400120024 ++:1010B0000A00260004030904160358006F0072009A ++:1010C00063006F006D0020004C00540044001403C6 ++:1010D00041007300740072006900620061006E00DC ++:1010E0006B001203530065007200690061006C0020 ++:1010F0004E006F000A0346005000470041002603DF ++:101100004D0061006E00610067006D0065006E00BB ++:101110007400500072006F0063006500730073007C ++:061120006F0072000000E8 ++:051EF7000300000000E3 ++:1012BC0041E0370041E0BC0042E0B7000041E038BB ++:1012CC0000021BE08B0218E07F43E0B900000053E2 ++:1012DC00E03931313435313A31313435334D202028 ++:0512EC0020202020007D ++:101D8C008B538A548955E5581558AE577002155720 ++:101D9C004E6014AB530555E555AA54700205541406 ++:081DAC00F9ED12077780DF2238 ++:101C01008B538A548955E55A155AAE5970021559A4 ++:101C11004E6026AB560558E558AA57700205571471 ++:101C2100F9120731FFAB530555E555AA547002056A ++:0A1C31005414F9EF12077780CD225A ++:101DDC00D2B7E490E670F0F5B575B5E653B5E743C8 ++:101DEC00B28853B2FCC2B3D2B1C2B2C2B67F32FE19 ++:061DFC00121E22D2B622E5 ++:101E7C00538EF75389FB5389F74389015389FDE44A ++:071E8C00F58AF58CD2A922B2 ++:1018CD008C448D45AA06A9077556018A5789587506 ++:1018DD005900755A1C7B017AE07952121C0190E077 ++:1018ED006AE0FCA3E0FDA3E0FEA3E064D1FFEE649B ++:1018FD008DFEED644CFDEC6449FC90E06A120853DA ++:10190D007EE07F527D1C7C001214307EE07F527B86 ++:10191D001C7A00AD45AC441214E47D1C7C00AF452F ++:10192D00AE441211F57D1C7C00AF45AE44021C7116 ++:08185A008E448F458C468D473A ++:10186200C20712001290E161EFF0BF5004D207806C ++:1018720057E490E162F0A3F090E162E0FEA3E0FFA2 ++:10188200C39410EE648094805030E5472FF582E5D2 ++:10189200463EF583E0FF90E162E0FCA3E02545F5DA ++:1018A20082E5443CF583E0B5071090E163E004F083 ++:1018B20070C690E162E004F080BE90E162E07004E4 ++:0A18C200A3E064107002D207A20731 ++:0118CC0022F9 ++:020E31008F41EF ++:100E33001200128F42E4F546F547AD47AC46120F58 ++:100E43005F746F2547F582E434E0F583E543F005ED ++:100E530047E54770020546C39408E54664809480DD ++:100E630040D8E541600490E06FF090E06FE0B4C0DB ++:100E730008754400754508800675441D754536752B ++:100E83004600754708C3E5479410E546648094809F ++:100E93005023120F5B746F2547F582E434E0F5832A ++:100EA300E543F00547E547700205460545E545700E ++:100EB300D4054480D07543FF75441D7545197546A7 ++:100EC30000754710C3E547942CE546648094805031 ++:100ED30033E542B4510E7B007A007943AD45AC440F ++:100EE300FF120F67746F2547F582E434E0F583E55D ++:100EF30043F00547E547700205460545E54570C4DF ++:100F0300054480C075441D75453EE4F543F546F53B ++:100F130047C3E5479406E54664809480502FE54235 ++:100F2300B4510A90E06FE0B4C203120F5B744C2516 ++:100F330047F582E434E0F583E543F00547E5477080 ++:100F43000205460545E54570C8054480C490E06F39 ++:070F5300E0B4C20374C0F01A ++:010F5A002274 ++:0A19A3008E448F458B468A47894821 ++:1019AD007E00E5452DF54DEE3544F54C1200128FB8 ++:1019BD0049E5496451600BC3E5459410E544940035 ++:1019CD00503585444A85454BC3E54B954DE54A95C4 ++:1019DD004C5024AB46AA47A948AD4BAC4AAF49126F ++:1019ED00175B054BE54B7002054A74012548F54818 ++:0719FD00E43547F54780D1F6 ++:011A040022BF ++:0617E2008B418A4289439D ++:1017E800D2067556017557E075586F755900755AC8 ++:1017F800107B017AE0799B121C01E5432410F9E47F ++:101808003542854156F5578958755900755A0C7BEC ++:10181800017AE079AB121C017EE07F9B7CE07D1AA7 ++:101828001218CD7EE07F1AE543241CF9E43542FC0A ++:10183800AD0112185A5016AB41E5432410F9E435AE ++:1018480042FA7D1C7F197E1D1219A38002C206A2CE ++:011858000689 ++:01185900226C ++:101126007F03121D61EF2402FFE43EA9077541010A ++:10113600F542894390E070E0FFE50C2408F582E46F ++:10114600350BF583EFF090E071E0FFE50C2409F52F ++:1011560082E4350BF583EFF090E072E0FFE50C24B6 ++:101166000AF582E4350BF583EFF090E073E0FFE5D6 ++:101176000C240BF582E4350BF583EFF090E074E078 ++:10118600FFE50C240CF582E4350BF583EFF090E0D7 ++:1011960075E0FFE50C240DF582E4350BF583EFF0E1 ++:1011A6007F087E00E4FDEDC394085028746F2FF588 ++:1011B60082E434E0F583E0FCAB41AA42A94375F032 ++:1011C60002EDA4F58285F083EC1207890D0FBF00AE ++:1011D600010E80D2E5192404F582E43518F583E082 ++:0E11E60030E0047F0180027F0090E037EFF0E0 ++:0111F40022D8 ++:101B400090E072E02FFFE50C240AF582E4350BF5F6 ++:101B500083EFF0E50C240BF582E4350BF583E0FE12 ++:101B6000E50C240AF582E4350BF583E0FDEDFF90EA ++:101B7000E0B7EEF0A3EFF0D206121CD890E680E0BA ++:041B800054F7F02204 ++:10163B0090E600E054E74410F090E60174C0F0909F ++:10164B00E6107420F000000090E611F0000000900E ++:10165B00E6047480F0000000740FF0000000E4F06A ++:10166B0000000090E6187410F0000000E490E619FA ++:10167B00F000000090E61A7408F0000000E490E619 ++:10168B001BF000000090E6497482F0000000F000AF ++:10169B00000090E6247402F0000000E490E625F0D0 ++:1016AB0000000090E6957480F0000000F000000050 ++:1016BB0043AF017B017AE07914755700755806E446 ++:0416CB00FD021D8C73 ++:061E1C00D2837F0A7E0064 ++:101E22007C007D181207ABEF1FAC0670011E4C70D0 ++:021E3200F62296 ++:0A1A5E008E418F428B438A44894574 ++:101A6800E4F546F547C3E5479542E54695415036C6 ++:101A7800AB43AA44A94585478285468312074AFF96 ++:101A8800E4FBFAC2B2EF1392B1EFC313FFD2B20B69 ++:101A9800BB00010AEB64084A70E9C2B20547E54792 ++:071AA80070C3054680BFD3A7 ++:011AAF002214 ++:101E340090E60174C0F0C2B67FC27E01121E22D2A7 ++:081E4400B67F327E00021E226F ++:101EBF00D287121E1CC287121E1EC2837F0A7E008B ++:031ECF00021E22CE ++:021B8400AB07AD ++:101B8600E4F9FAEBC413131354011392877F027E10 ++:101B960000121E22D2837F057E00121E22E925E056 ++:101BA600FFA2B3E4334FF97F057E00121E22EB2518 ++:0D1BB600E0FBC283121E1E0ABA08C8AF0170 ++:011BC30022FF ++:061AB0008B558A56895790 ++:101AB600A2AFE433F55D121EBFE4F55CE55CC395A9 ++:101AC6005B5027AB55AA56A957855C8275830012D1 ++:101AD600074AFF121B84AB58AA59A95A855C82751E ++:101AE6008300EF120789055C80D2120036E55D247B ++:031AF600FF92AFAD ++:011AF90022CA ++:0B003600C287121E1E121E1CD2872261 ++:101E020075418F8F42755800755900755A4B755B35 ++:0A1E1200027B007A007941021AB049 ++:101CA70078417C007D007BFF7A1E79F77E007F05F7 ++:101CB70012070B30B415755800755900755A4175E0 ++:101CC7005B057B007A007941121AB0E5435401FFA6 ++:011CD70022EA ++:100B4E007541007542007543007545017546E075A7 ++:100B5E0047007548017549E0754A08E4F551FFF5FF ++:100B6E00527B017AE07900F557755808FD121D8CFD ++:100B7E00AB45AA46A9477401120777E4F550E55034 ++:100B8E00C454F0AB45AA46A94790000112078985C7 ++:100B9E004858854959854A5A755B08121AB0AB48B0 ++:100BAE00AA49A94A90000212074AFE5407FFEE54C2 ++:100BBE0070F55124E0602D24F0604924F060582433 ++:100BCE00F0606A24F0607C24506003020C72754160 ++:100BDE0001851842851943EF24FE600624FE70221B ++:100BEE0080738076E5192401FDE43518A905754159 ++:100BFE0001F5428943EF24FC6006240270048055FF ++:100C0E008058805BE5192402FDE43518A90575416D ++:100C1E0001F54289438048E5192403FDE43518A9FE ++:100C2E0005754101F54289437552048040E519244A ++:100C3E0005FDE43518A905754101F5428943755244 ++:100C4E0098802A754101851842851943EF24FE606C ++:100C5E000924FE700A7552028013755206800E75B5 ++:100C6E0052088009754100754200754300E5424502 ++:100C7E004345416022AB41AA42A943120731FED33C ++:100C8E0095524006AD52AE0580008E44120731C318 ++:100C9E009544120777800FE5516003B470047E010E ++:100CAE0080027E008E44744B2550F8A6440550E514 ++:100CBE0050C394055003020B8CAB45AA46A947744A ++:100CCE0088120777AB45E5472401F9E43546FA75F6 ++:100CDE00560075570075584B755900755A05121CFC ++:100CEE0001854858854959854A5A755B08AB45AA0E ++:060CFE0046A947021AB0EE ++:101A05008F4190E0B7E0FEA3E054F064607003EE10 ++:101A1500641160037F012290E037E070037F0F229D ++:101A2500E5417003308108E541B401062080037F5C ++:101A3500102290E0BCE0B541037F0122E4F511D20C ++:101A450006121CD8AF4190E0BCEFF024FF92B59090 ++:091A5500E680E054F7F07F002266 ++:04000E0090FC04F06E ++:1000120090E678E0541824F06008240870087F50B5 ++:0800220080067F518002E4FF1B ++:01002A0022B3 ++:0C0F5B00AD45AC447B007A007943AF4206 ++:0C0F67008F488C498D4A8B4B8A4C894D79 ++:100F7300E4F54EF54F755003FDF551F552A2AF332D ++:100F8300F553E54824AF600D047012754E00754F9C ++:100F9300017D018008754E00754F02E4FDE5486050 ++:100FA30051E54F454E604BE54990E0B9F0E54AA362 ++:100FB300F074B92DF582E434E0AD82FCAB4FAF4859 ++:100FC30012193D7551008F527F0A7E00121AFAE5FD ++:100FD30052455160107CE07D6E7B01AF481215963F ++:100FE3007551008F5290E06EE0AB4BAA4CA94D12A5 ++:0C0FF3000777E55324FF92AFAE51AF52D8 ++:010FFF0022CF ++:0C175B008F4E8C4F8D508B518A52895359 ++:10176700E4F554F555755603FDF557F558A2AF3313 ++:10177700F559E54E24AF600D047012755400755588 ++:10178700027D018008755400755503E4FDE54E6040 ++:101797003FE55545546039E54F90E0B9F0E550A372 ++:1017A700F0AB51AA52A95312073190E0BBF0C2B770 ++:1017B70074B92DF582E434E0AD82FCAB55AF4E121F ++:1017C700193D7557008F587F0A7E00121AFAD2B753 ++:0A17D700E55924FF92AFAE57AF585A ++:0117E10022E5 ++:10005600E4F531F532F535F53CF53DF53EF53FE590 ++:10006600AA5484600302063A90E694E0FE90E69570 ++:10007600E0FBEEF53CEBF53DC39405E53C94004012 ++:100086000790F404E0FD80027DFFED12085F00CECC ++:100096000102C30503080703580903D80B011E0E06 ++:1000A60000E40F019411025E130541250401310499 ++:1000B6005732046A3404B23504C93604E63703E518 ++:1000C6004503F647000005BA75310075320790FC06 ++:1000D600047481F0A37414F0E4A3F00205DD7F0F2D ++:1000E600121E0275310075320690FC047480F0E42D ++:1000F600A3F0753505F511FE74002535F9EE34F4D7 ++:10010600FA7B011217E2400690FC05740EF0E4FF3C ++:10011600120E317F8F0202BD7F0E121E0275310054 ++:10012600753205748E12000E8F3F7B007A0079407F ++:10013600E4FDFC120F67E53F64516019E53F64502A ++:10014600601375310075320690FC047480F0A37458 ++:100156000BF00205DD90E0BDE0FF120E31740025C4 ++:1001660032F974FC3531FA7B01C0038B567557E0C2 ++:1001760075586F755900755A2CD003121C01742CD2 ++:100186002532F532E43531F5317F8E0202BD753107 ++:100196000075320790FC047491F090E678E090FCCC ++:1001A60005F030B3047F0280027F0030B4047E0184 ++:1001B60080027E00EE4F90FC06F074002532F97442 ++:1001C600FC3531FA7B01755700755812E4FD121D96 ++:1001D6008C74002532F974FC3531FA7B01C0038B2F ++:1001E600567557E0755839755900755A06D0031279 ++:1001F6001C0174062532F532E43531F531FE740002 ++:100206002532F974FC3EFA7B01C0038B567557E024 ++:10021600755814755900755A06D003121C017406D8 ++:100226002532F532E43531F531FE74002532F974A4 ++:10023600FC3EFA7B01C0038B567557E075584C752A ++:100246005900755A06D003121C0174062532F53280 ++:10025600E43531F5310205DD7F13121E02753100DA ++:1002660075321D749312000E8F3F75381D75390057 ++:10027600753600753705D3E5399418E538941D5061 ++:1002860034E53FB4510E7B007A007940AD39AC3885 ++:10029600FF120F6774002537F58274FC3536F58337 ++:1002A600E540F00539E539700205380537E5377060 ++:1002B600C5053680C17F93121E020205DD75310029 ++:1002C60075320690FC047480F0E4A3F090F405E027 ++:1002D60090E038F0E0147071121E3430B31B75567E ++:1002E600017557F4755806755900755A067B017ADB ++:1002F600E07914121C010205DD90FC057401F00280 ++:1003060003D075310075320690FC047480F0E4A3C6 ++:10031600F0753507AF35FEC3E53D9FF534E53C9EE8 ++:10032600F53390E038E014702074002FF974F43E31 ++:10033600FA7B01AF34AE33121A5E5004E40204C2F3 ++:1003460090FC05740CF00205DD90FC057403F002C8 ++:1003560005DD75310075320690FC047480F0E4A367 ++:10036600F090E038E014705CE4FFFE20B411C2B2F5 ++:10037600D2B1D2B20FBF00010EEF640A4E70EC305C ++:10038600B43A90E6017403F07F647E00121E229058 ++:10039600E0BDE0FF120E317EE07F6F7CE07DBE1295 ++:1003A60018CD7EE07FBEAD1CAC1B12185A5005124C ++:1003B6000B4E801690FC05740EF0800E90FC0574B2 ++:1003C6000DF0800690FC057403F0E490E038F0022E ++:1003D60005DDE4F531F5327F02121B400205DDE44E ++:1003E600FF120E31121126E4FF121A05E4FF8002F5 ++:1003F6007F01121B40121E340205DD753100753275 ++:100406000690FC047480F0E4A3F090F405E0F53E59 ++:10041600E4F511E53E64016004E53E703290E0B714 ++:10042600E0FEA3E054F064607003EE6411600280A5 ++:100436007290E037E070028058E5116401600AE5C9 ++:1004460011700C121CA7EF6006853E110205DD80B7 ++:100456005275310075320690FC0474B2F0A3E511B2 ++:10046600F00205DD75310075320690FC047480F0EB ++:10047600E4A3F090F405E0F53EFF121A05EF24F12F ++:10048600600F1460152410701AE4F531F532020578 ++:10049600DD90FC05740FF00205DD90FC057410F08C ++:1004A6000205DD90FC057401F00205DD753100756D ++:1004B600320690FC0474B5F090E0BCE090FC05F0C8 ++:1004C6000205DD75310075320690FC0474B6F0A2A3 ++:1004D60080E43325E0FFA281E4334FA3F00205DD7B ++:1004E600853C31853D3290FC0474B7F0753505C303 ++:1004F600E53D9535F534E53C9400F5337400253536 ++:10050600F582E434F4F583E0648870030205DDAF18 ++:10051600357E0074002FF9EE34F4FA7B01C003C077 ++:100526000174002FF9EE34FC8B58F559895A85343D ++:100536005BD001D003121AB00205DD7531007532A9 ++:100546000590FC0474A5F01200128F3F7B007A0020 ++:100556007940E4FDFC120F6790E036E0FF0532E5D6 ++:1005660032AC3170020531142400F58274FC3CF57E ++:1005760083EFF090E0BDE0FF0532E532AC3170026A ++:100586000531142400F58274FC3CF583EFF0053246 ++:10059600E532AE3170020531142400F58274FC3E5A ++:1005A600F583E540F090E6017403F07F647E001267 ++:1005B6001E22802375310075320690FC047480F08B ++:1005C600C3E53D9405E53C94005006A37407F0800E ++:1005D6000690FC057406F090F404E0B48004A3E0F1 ++:1005E600701290F404E06405600FE06407600AE0AE ++:1005F60064096005E490E038F0E5324531602CE5A9 ++:1006060032FD90FC00F0E531FFA3F090F402E0909B ++:10061600FC02F090F403E090FC03F090E69CEFF00F ++:1006260000000090E69DEDF000000090E6957480D5 ++:04063600F0000000D0 ++:01063A00229D ++:02004100D322C8 ++:0800030090E6BAE0F51DD322DE ++:101EE50090E740E51DF0E490E68AF090E68B04F07B ++:021EF500D322F6 ++:08002B0090E6BAE0F51AD322B9 ++:101F180090E740E51AF0E490E68AF090E68B04F04A ++:021F2800D322C2 ++:101DB40090E6B9E0242F600D04701990E604E0FF6A ++:101DC400430780800890E604E0FF53077F0000008B ++:071DD400EFF08002D322C3EF ++:011DDB0022E5 ++:101E4C00C0E0C083C082D2015391EF90E65D740173 ++:081E5C00F0D082D083D0E03207 ++:101E9300C0E0C083C0825391EF90E65D7404F0D03C ++:061EA30082D083D0E03282 ++:101EA900C0E0C083C0825391EF90E65D7402F0D028 ++:061EB90082D083D0E0326C ++:101C3B00C0E0C083C08285120D85130E850E828590 ++:101C4B000D83A37402F085090F850A108510828518 ++:101C5B000F83A37407F05391EF90E65D7410F0D0EF ++:061C6B0082D083D0E032BC ++:101E6400C0E0C083C082D2035391EF90E65D740852 ++:081E7400F0D082D083D0E032EF ++:101BC400C0E0C083C08290E680E030E72085090D44 ++:101BD400850A0E850E82850D83A37402F085120F8B ++:101BE400851310851082850F83A37407F05391EF3A ++:0D1BF40090E65D7420F0D082D083D0E03206 ++:101ED200000102020303040405050300000000C020 ++:031EE200C200003B ++:0612F100011100010800DC ++:03000B0002137C61 ++:10137C00C0E0C0F0C083C082C0D075D000C000C037 ++:0D138C0001C002C003C004C005C006C007B8 ++:1013990078217C007D007BFF7A1E79DC7E007F0549 ++:1013A90012070B90E0BCE0F526C204752700E5089A ++:1013B900600415088056750805E5117004C204809B ++:1013C90043A280308101B3500B3081047F0080300B ++:1013D9007F01802C30B415755800755900755A2154 ++:1013E900755B057B007A007921121AB0E523540157 ++:1013F900F527701090E0BCE060047F0080027F0157 ++:0C1409008F26D204300405AF26121A050D ++:10141500D007D006D005D004D003D002D001D0002B ++:0B142500D0D0D082D083D0F0D0E032D5 ++:100D0400785C7CE17D017BFF7A1E79E17E007F04C3 ++:100D140012070BC203C200D202C201121DDC121E52 ++:100D24007C12163B750B10750C007514107515129A ++:100D3400750910750A1C75121075137085120F85CC ++:100D440013107516107517B412001290E15AEFF0D3 ++:100D54007B017AE1795BE4FDFC120F6790E15BE0D3 ++:100D6400FF90E036F0E490E0BDF0EF64C26059EF2C ++:100D740064C06054E490E160F090E160E0FFC394EB ++:100D840004504A745C2FF582E434E1F583E0FF609B ++:100D94003C120E317EE07F6F7CE07DBE1218CD7E6A ++:100DA400E07FBEAD1CAC1B12185A501490E160E0F9 ++:100DB400245CF582E434E1F583E090E0BDF0800D3D ++:100DC40090E160E004F080B1E4FF120E31121126CC ++:100DD400D2E843D82090E668E04409F090E65CE06D ++:100DE400443DF012001290E15AEFF07B017AE17970 ++:100DF4005BE4FDFC120F6790E15BE064C26007E412 ++:100E040090E0BCF0C2B57F01121B40D2AFD28C532C ++:100E14008EF8C203C2AF120056D2AF3001051209D8 ++:0D0E240026C2013003EEC203121D3580E727 ++:0B00460090E50DE030E402C322D3225D ++:1009260090E6B9E070030209EB147003020A602432 ++:10093600FE7003020ADB24FB70030209E514700350 ++:100946000209DF1470030209D31470030209D924C3 ++:10095600056003020B3A1200414003020B4690E683 ++:10096600BBE024FE602714603E24FD60111460275E ++:1009760024067056E50B90E6B3F0E50C80421200B3 ++:10098600465044E51490E6B3F0E5158033E50D9046 ++:10099600E6B3F0E50E802985120F851310E50F905A ++:1009A600E6B3F0E510801990E6BAE0FF121D61AAE1 ++:1009B60006A9077B01EA494B600DEE90E6B3F0EF1E ++:1009C60090E6B4F0020B46020B35020B35121F18E7 ++:1009D600020B4612002B020B46120003020B4612B4 ++:1009E6001EE5020B4690E6B8E0247F6015146019F8 ++:1009F60024027063A200E43325E0FFA202E4334F31 ++:100A06008041E490E740F0803F90E6BCE0547EFFF2 ++:100A16007E00E0D394807C0040047D0180027D004E ++:100A2600EC4EFEED4F24D2F582741E3EF583E49320 ++:100A3600FF3395E0FEEF24A1FFEE34E68F82F583C7 ++:100A4600E0540190E740F0E4A3F090E68AF090E6E7 ++:100A56008B7402F0020B46020B3590E6B8E024FEDA ++:100A6600601624026003020B4690E6BAE0B4010564 ++:100A7600C200020B46020B3590E6BAE0705590E6CE ++:100A8600BCE0547EFF7E00E0D394807C0040047D71 ++:100A96000180027D00EC4EFEED4F24D2F582741EDD ++:100AA6003EF583E493FF3395E0FEEF24A1FFEE3499 ++:100AB600E68F82F583E054FEF090E6BCE0548013A6 ++:100AC6001313541FFFE0540F2F90E683F0E04420E9 ++:100AD600F0806D805A90E6B8E024FE60192402701A ++:100AE6004E90E6BAE0B40104D200805490E6BAE033 ++:100AF6006402604C803990E6BCE0547EFF7E00E0E4 ++:100B0600D394807C0040047D0180027D00EC4EFE83 ++:100B1600ED4F24D2F582741E3EF583E493FF3395A0 ++:100B2600E0FEEF24A1FFEE34E68F82F583800D9080 ++:100B3600E6A08008121DB4500790E6A0E04401F03C ++:070B460090E6A0E04480F0FE ++:010B4D002285 ++:03003300021EFCAE ++:041EFC0053D8EF3296 ++:1012F7006080E0DA292E43C9A2D87C013D3654A18B ++:10130700ECF0061362A705F3C0C7738C98932BD92B ++:10131700BC4C82CA1E9B573CFDD4E01667426F182F ++:101327008A17E512BE4EC4D6DA9EDE49A0FBF58EBB ++:10133700BB2FEE7AA968799115B2073F94C210893D ++:101347000B225F21807F5D9A5A903227353ECCE78A ++:10135700BFF79703FF1930B348A5B5D1D75E922AD7 ++:10136700AC56AAC64FB838D296A47DB676FC6BE2C7 ++:041377009C7404F16D ++:081430008C468D47AB07AA06AC ++:10143800E4F548F549C3E5499547E5466480F8E58C ++:101448004864809840030214DFE54925E0FFE54839 ++:1014580033FE74DA2FF58274E03EF583E0FF7E00F8 ++:10146800AC46AD471207BD8C4A8D4BE54925E0FFD8 ++:10147800E54833FE74DB2FF58274E03EF583E0FF28 ++:101488007E00AC46AD471207BD8C4C8D4DE54B65D3 ++:101498004D7004E54A654C6030EB254BF582EA3522 ++:1014A8004AF583E0F9EB254DF582EA354CF583E002 ++:1014B800FFEB254BF582EA354AF583EFF0EB254D36 ++:1014C800F582EA354CF583E9F00549E54960030200 ++:0B14D800143D054802143D7E007F011A ++:0114E30022E6 ++:0C14E4008E468F478C488D498A4A8B4BFE ++:1014F000E54745466006E54945487004E4FEFF229D ++:10150000E4F54CF54DC3E54D954BE54A6480F8E5AF ++:101510004C648098507BE4F54EF54FE549254DF538 ++:1015200082E548354CF583E4F0C3E54F954BE54A39 ++:101530006480F8E54E6480985049E54F254D24DAE3 ++:10154000F582E434E0F583E0FFE547254FF582E5D9 ++:1015500046354EF583E0FEEF8EF0A4FFE549254DBC ++:10156000F582E548354CF583E02FFFE549254DF53B ++:1015700082E548354CF583EFF0054FE54F70AA053D ++:101580004E80A6054DE54D6003021505054C02157C ++:05159000057E007F0153 ++:011595002233 ++:101D0700120731FF90000312074A1207779000036A ++:101D1700EF12078990000212074AFF90000112078D ++:0E1D27004A900002120789900001EF0207891E ++:0811F5008E468F478C488D499E ++:1011FD00E4F54AF54BE549AE487802CEA2E713CEA9 ++:10120D0013D8F8FFC3E54B9FEE6480F8E54A648080 ++:10121D009840030212B7E54BAE4A7802C333CE3382 ++:10122D00CED8F92547FFEE3546FAA9077B018B4C41 ++:10123D00F54D894E74DB254BF582E434E0F583E002 ++:10124D00541FFFE48F52F551F550F54F121D07ABAA ++:10125D004CAA4DA94E120819C374209552F9F812D3 ++:10126D000806C004C005C006C007A94E120819A97A ++:10127D0052A8011207F3D003D002D001D000EF4BDA ++:10128D00FFEE4AFEED49FDEC48FCAB4CAA4DA94ED4 ++:10129D00120839AB4CAA4DA94E121D07054BE54B53 ++:0E12AD006003021202054A0212027E007F0157 ++:0112BB002210 ++:101C7100D3ED9410EC64809480402AED1D70011C1A ++:101C8100142FF582EE3CF583E0FB547F24DAF582D4 ++:101C9100E434E0F583E0F9540F2FF582E43EF58357 ++:051CA100E06BF080CBB8 ++:011CA600221B ++:101D350090E682E030E004E020E60B90E682E030B9 ++:101D4500E119E030E71590E680E04401F07F147E6C ++:0C1D550000121AFA90E680E054FEF02222 ++:101CD80030060990E680E0440AF0800790E680E04C ++:101CE8004408F07FDC7E05121AFA90E65D74FFF076 ++:0F1CF80090E65FF05391EF90E680E054F7F02212 ++:101AFA008E5A8F5B90E600E054187012E55B240161 ++:101B0A00FFE4355AC313F55AEF13F55B801590E6D7 ++:101B1A0000E05418FFBF100BE55B25E0F55BE55AC2 ++:101B2A0033F55AE55B155BAE5A7002155A4E6005DD ++:061B3A00121F2A80EE22BA ++:061596008C548D55AE07D8 ++:10159C00EB70037F012290E678E020E6F990E67884 ++:1015AC007480F0EE25E0440190E679F090E678E066 ++:1015BC0030E0F990E678E020E26BE030E167BB01C7 ++:1015CC000790E678E04420F090E679E0F5561BEBC6 ++:1015DC00603090E678E030E0F990E678E020E24583 ++:1015EC00BB010790E678E04420F090E679E0FF0537 ++:1015FC0055E555AC547002055414F5828C83EFF00C ++:10160C0080CC90E678E030E0F990E678E020E215C6 ++:10161C0090E678E04440F090E679E0855582855478 ++:0E162C0083F07F012290E678E04440F07F00DA ++:01163A00228D ++:10193D0090E678E020E6F990E6787480F0EF25E007 ++:10194D0090E679F090E678E030E0F990E678E020E6 ++:10195D00E23AE030E136EBD3940040260DEDAE04D3 ++:10196D0070010C14F5828E83E090E679F01B90E601 ++:10197D0078E030E0F990E678E020E210E020E1D662 ++:10198D00800A90E678E04440F07F012290E678E00E ++:05199D004440F07F0052 ++:0119A2002222 ++:021D6100A907D0 ++:101D6300AE16AF178F828E83A3E064037017AD01A5 ++:101D730019ED7001228F828E83E07C002FFDEC3EF3 ++:081D8300FEAF0580DFE4FEFF66 ++:011D8B002235 ++:101F2A007400F58690FDA57C05A3E582458370F9CA ++:011F3A002284 ++:030000000216CF16 ++:0C16CF00787FE4F6D8FD75815D021716E7 ++:10063B00E709F608DFFA8046E709F208DFFA803EA1 ++:10064B0088828C83E709F0A3DFFA8032E309F6088E ++:10065B00DFFA8078E309F208DFFA807088828C83F6 ++:10066B00E309F0A3DFFA806489828A83E0A3F608AA ++:10067B00DFFA805889828A83E0A3F208DFFA804C84 ++:10068B0080D280FA80C680D4806980F2803380105B ++:10069B0080A680EA809A80A880DA80E280CA8033C4 ++:1006AB0089828A83ECFAE493A3C8C582C8CCC5833C ++:1006BB00CCF0A3C8C582C8CCC583CCDFE9DEE7800C ++:1006CB000D89828A83E493A3F608DFF9ECFAA9F08B ++:1006DB00EDFB2289828A83ECFAE0A3C8C582C8CCE1 ++:1006EB00C583CCF0A3C8C582C8CCC583CCDFEADEFA ++:1006FB00E880DB89828A83E493A3F208DFF980CC5C ++:10070B0088F0EF60010E4E60C388F0ED2402B40454 ++:10071B000050B9F582EB2402B4040050AF232345FB ++:06072B00822390068B738F ++:10073100BB010689828A83E0225002E722BBFE02C6 ++:09074100E32289828A83E49322F9 ++:10074A00BB010CE58229F582E5833AF583E0225064 ++:10075A0006E92582F8E622BBFE06E92582F8E222AE ++:0D076A00E58229F582E5833AF583E49322C8 ++:10077700BB010689828A83F0225002F722BBFE0161 ++:02078700F3225B ++:10078900F8BB010DE58229F582E5833AF583E8F0A6 ++:10079900225006E92582C8F622BBFE05E92582C852 ++:0207A900F2223A ++:1007AB00EF8DF0A4A8F0CF8CF0A428CE8DF0A42E62 ++:0207BB00FE221C ++:1007BD00C2D5EC30E709B2D5E4C39DFDE49CFCEE57 ++:1007CD0030E715B2D5E4C39FFFE49EFE120885C342 ++:1007DD00E49DFDE49CFC800312088530D507C3E43D ++:0607ED009FFFE49EFE22C6 ++:1007F300E8600FECC313FCED13FDEE13FEEF13FFE4 ++:03080300D8F12207 ++:10080600E8600FEFC333FFEE33FEED33FDEC33FC50 ++:03081600D8F122F4 ++:10081900BB010789828A830208E65005E9F80208C4 ++:10082900DABBFE05E9F80208F289828A830208FE2A ++:10083900BB010789828A830208535005E9F8020936 ++:0A0849000EBBFE05E9F802091A22B1 ++:0C085300ECF0A3EDF0A3EEF0A3EFF02218 ++:10085F00D083D082F8E4937012740193700DA3A328 ++:10086F0093F8740193F5828883E47374029368603C ++:06087F00EFA3A3A380DF3C ++:1016DB00020D04E493A3F8E493A34003F68001F214 ++:1016EB0008DFF48029E493A3F85407240CC8C33310 ++:1016FB00C4540F4420C8834004F456800146F6DFDF ++:10170B00E4800B01020408102040809012BCE47EA0 ++:10171B00019360BCA3FF543F30E509541FFEE493D3 ++:10172B00A360010ECF54C025E060A840B8E493A39A ++:10173B00FAE493A3F8E493A3C8C582C8CAC583CAC5 ++:10174B00F0A3C8C582C8CAC583CADFE9DEE780BE7D ++:01137B000071 ++:10088500BC000BBE0029EF8DF084FFADF022E4CC57 ++:10089500F875F008EF2FFFEE33FEEC33FCEE9DEC20 ++:1008A500984005FCEE9DFE0FD5F0E9E4CEFD22ED66 ++:1008B500F8F5F0EE8420D21CFEADF075F008EF2FB0 ++:1008C500FFED33FD4007985006D5F0F222C398FDA1 ++:0508D5000FD5F0EA223E ++:0C08DA00E6FC08E6FD08E6FE08E6FF224A ++:0C08E600E0FCA3E0FDA3E0FEA3E0FF2285 ++:0C08F200E2FC08E2FD08E2FE08E2FF2242 ++:1008FE00E493FC740193FD740293FE740393FF2240 ++:0C090E00ECF608EDF608EEF608EFF62215 ++:0C091A00ECF208EDF208EEF208EFF22219 ++:00000001FF ++ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_FW.202.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_FW.202.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_FW.202.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_FW.202.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,582 @@ ++# ++# $Id: USB_FW.201.hex 11502 2015-12-03 17:01:41Z dima $ ++# ++:03004300021F0099 ++:03005300021F0089 ++:101F0000021E4C00021EA900021E9300021E640065 ++:081F1000021C3B00021BC4008F ++:101000001201000200000040AAAAAAAAAAAA01028C ++:1010100003010A0600020000004001000902370037 ++:10102000020100C0000904000002FFFFFF040705E1 ++:101030000202000200070586020002000904010006 ++:1010400002FFFFFF050705040200020007058802F2 ++:10105000000200001201000200000040E4E451110F ++:101060000000010203010A06000200000040010026 ++:1010700009023700020100C0320904000002FFFF2C ++:10108000FF04070502024000000705860240000039 ++:101090000904010002FFFFFF0507050402400000EC ++:1010A0000705880240000006040016001400120024 ++:1010B0000A00260004030904160358006F0072009A ++:1010C00063006F006D0020004C00540044001403C6 ++:1010D00041007300740072006900620061006E00DC ++:1010E0006B001203530065007200690061006C0020 ++:1010F0004E006F000A0346005000470041002603DF ++:101100004D0061006E00610067006D0065006E00BB ++:101110007400500072006F0063006500730073007C ++:061120006F0072000000E8 ++:051EF7000300000000E3 ++:1012BC0041E0370041E0BC0042E0B7000041E038BB ++:1012CC0000021BE08B0218E07F43E0B900000053E2 ++:1012DC00E03931313435313A31313435334D202028 ++:0512EC0020202020007D ++:101D8C008B538A548955E5581558AE577002155720 ++:101D9C004E6014AB530555E555AA54700205541406 ++:081DAC00F9ED12077780DF2238 ++:101C01008B538A548955E55A155AAE5970021559A4 ++:101C11004E6026AB560558E558AA57700205571471 ++:101C2100F9120731FFAB530555E555AA547002056A ++:0A1C31005414F9EF12077780CD225A ++:101DDC00D2B7E490E670F0F5B575B5E653B5E743C8 ++:101DEC00B28853B2FCC2B3D2B1C2B2C2B67F32FE19 ++:061DFC00121E22D2B622E5 ++:101E7C00538EF75389FB5389F74389015389FDE44A ++:071E8C00F58AF58CD2A922B2 ++:1018CD008C448D45AA06A9077556018A5789587506 ++:1018DD005900755A1C7B017AE07952121C0190E077 ++:1018ED006AE0FCA3E0FDA3E0FEA3E064D1FFEE649B ++:1018FD008DFEED644CFDEC6449FC90E06A120853DA ++:10190D007EE07F527D1C7C001214307EE07F527B86 ++:10191D001C7A00AD45AC441214E47D1C7C00AF452F ++:10192D00AE441211F57D1C7C00AF45AE44021C7116 ++:08185A008E448F458C468D473A ++:10186200C20712001290E161EFF0BF5004D207806C ++:1018720057E490E162F0A3F090E162E0FEA3E0FFA2 ++:10188200C39410EE648094805030E5472FF582E5D2 ++:10189200463EF583E0FF90E162E0FCA3E02545F5DA ++:1018A20082E5443CF583E0B5071090E163E004F083 ++:1018B20070C690E162E004F080BE90E162E07004E4 ++:0A18C200A3E064107002D207A20731 ++:0118CC0022F9 ++:020E31008F41EF ++:100E33001200128F42E4F546F547AD47AC46120F58 ++:100E43005F746F2547F582E434E0F583E543F005ED ++:100E530047E54770020546C39408E54664809480DD ++:100E630040D8E541600490E06FF090E06FE0B4C0DB ++:100E730008754400754508800675441D754536752B ++:100E83004600754708C3E5479410E546648094809F ++:100E93005023120F5B746F2547F582E434E0F5832A ++:100EA300E543F00547E547700205460545E545700E ++:100EB300D4054480D07543FF75441D7545197546A7 ++:100EC30000754710C3E547942CE546648094805031 ++:100ED30033E542B4510E7B007A007943AD45AC440F ++:100EE300FF120F67746F2547F582E434E0F583E55D ++:100EF30043F00547E547700205460545E54570C4DF ++:100F0300054480C075441D75453EE4F543F546F53B ++:100F130047C3E5479406E54664809480502FE54235 ++:100F2300B4510A90E06FE0B4C203120F5B744C2516 ++:100F330047F582E434E0F583E543F00547E5477080 ++:100F43000205460545E54570C8054480C490E06F39 ++:070F5300E0B4C20374C0F01A ++:010F5A002274 ++:0A19A3008E448F458B468A47894821 ++:1019AD007E00E5452DF54DEE3544F54C1200128FB8 ++:1019BD0049E5496451600BC3E5459410E544940035 ++:1019CD00503585444A85454BC3E54B954DE54A95C4 ++:1019DD004C5024AB46AA47A948AD4BAC4AAF49126F ++:1019ED00175B054BE54B7002054A74012548F54818 ++:0719FD00E43547F54780D1F6 ++:011A040022BF ++:0617E2008B418A4289439D ++:1017E800D2067556017557E075586F755900755AC8 ++:1017F800107B017AE0799B121C01E5432410F9E47F ++:101808003542854156F5578958755900755A0C7BEC ++:10181800017AE079AB121C017EE07F9B7CE07D1AA7 ++:101828001218CD7EE07F1AE543241CF9E43542FC0A ++:10183800AD0112185A5016AB41E5432410F9E435AE ++:1018480042FA7D1C7F197E1D1219A38002C206A2CE ++:011858000689 ++:01185900226C ++:101126007F03121D61EF2402FFE43EA9077541010A ++:10113600F542894390E070E0FFE50C2408F582E46F ++:10114600350BF583EFF090E071E0FFE50C2409F52F ++:1011560082E4350BF583EFF090E072E0FFE50C24B6 ++:101166000AF582E4350BF583EFF090E073E0FFE5D6 ++:101176000C240BF582E4350BF583EFF090E074E078 ++:10118600FFE50C240CF582E4350BF583EFF090E0D7 ++:1011960075E0FFE50C240DF582E4350BF583EFF0E1 ++:1011A6007F087E00E4FDEDC394085028746F2FF588 ++:1011B60082E434E0F583E0FCAB41AA42A94375F032 ++:1011C60002EDA4F58285F083EC1207890D0FBF00AE ++:1011D600010E80D2E5192404F582E43518F583E082 ++:0E11E60030E0047F0180027F0090E037EFF0E0 ++:0111F40022D8 ++:101B400090E072E02FFFE50C240AF582E4350BF5F6 ++:101B500083EFF0E50C240BF582E4350BF583E0FE12 ++:101B6000E50C240AF582E4350BF583E0FDEDFF90EA ++:101B7000E0B7EEF0A3EFF0D206121CD890E680E0BA ++:041B800054F7F02204 ++:10163B0090E600E054E74410F090E60174C0F0909F ++:10164B00E6107420F000000090E611F0000000900E ++:10165B00E6047480F0000000740FF0000000E4F06A ++:10166B0000000090E6187410F0000000E490E619FA ++:10167B00F000000090E61A7408F0000000E490E619 ++:10168B001BF000000090E6497482F0000000F000AF ++:10169B00000090E6247402F0000000E490E625F0D0 ++:1016AB0000000090E6957480F0000000F000000050 ++:1016BB0043AF017B017AE07914755700755806E446 ++:0416CB00FD021D8C73 ++:061E1C00D2837F0A7E0064 ++:101E22007C007D181207ABEF1FAC0670011E4C70D0 ++:021E3200F62296 ++:0A1A5E008E418F428B438A44894574 ++:101A6800E4F546F547C3E5479542E54695415036C6 ++:101A7800AB43AA44A94585478285468312074AFF96 ++:101A8800E4FBFAC2B2EF1392B1EFC313FFD2B20B69 ++:101A9800BB00010AEB64084A70E9C2B20547E54792 ++:071AA80070C3054680BFD3A7 ++:011AAF002214 ++:101E340090E60174C0F0C2B67FC27E01121E22D2A7 ++:081E4400B67F327E00021E226F ++:101EBF00D287121E1CC287121E1EC2837F0A7E008B ++:031ECF00021E22CE ++:021B8400AB07AD ++:101B8600E4F9FAEBC413131354011392877F027E10 ++:101B960000121E22D2837F057E00121E22E925E056 ++:101BA600FFA2B3E4334FF97F057E00121E22EB2518 ++:0D1BB600E0FBC283121E1E0ABA08C8AF0170 ++:011BC30022FF ++:061AB0008B558A56895790 ++:101AB600A2AFE433F55D121EBFE4F55CE55CC395A9 ++:101AC6005B5027AB55AA56A957855C8275830012D1 ++:101AD600074AFF121B84AB58AA59A95A855C82751E ++:101AE6008300EF120789055C80D2120036E55D247B ++:031AF600FF92AFAD ++:011AF90022CA ++:0B003600C287121E1E121E1CD2872261 ++:101E020075418F8F42755800755900755A4B755B35 ++:0A1E1200027B007A007941021AB049 ++:101CA70078417C007D007BFF7A1E79F77E007F05F7 ++:101CB70012070B30B415755800755900755A4175E0 ++:101CC7005B057B007A007941121AB0E5435401FFA6 ++:011CD70022EA ++:100B4E007541007542007543007545017546E075A7 ++:100B5E0047007548017549E0754A08E4F551FFF5FF ++:100B6E00527B017AE07900F557755808FD121D8CFD ++:100B7E00AB45AA46A9477401120777E4F550E55034 ++:100B8E00C454F0AB45AA46A94790000112078985C7 ++:100B9E004858854959854A5A755B08121AB0AB48B0 ++:100BAE00AA49A94A90000212074AFE5407FFEE54C2 ++:100BBE0070F55124E0602D24F0604924F060582433 ++:100BCE00F0606A24F0607C24506003020C72754160 ++:100BDE0001851842851943EF24FE600624FE70221B ++:100BEE0080738076E5192401FDE43518A905754159 ++:100BFE0001F5428943EF24FC6006240270048055FF ++:100C0E008058805BE5192402FDE43518A90575416D ++:100C1E0001F54289438048E5192403FDE43518A9FE ++:100C2E0005754101F54289437552048040E519244A ++:100C3E0005FDE43518A905754101F5428943755244 ++:100C4E0098802A754101851842851943EF24FE606C ++:100C5E000924FE700A7552028013755206800E75B5 ++:100C6E0052088009754100754200754300E5424502 ++:100C7E004345416022AB41AA42A943120731FED33C ++:100C8E0095524006AD52AE0580008E44120731C318 ++:100C9E009544120777800FE5516003B470047E010E ++:100CAE0080027E008E44744B2550F8A6440550E514 ++:100CBE0050C394055003020B8CAB45AA46A947744A ++:100CCE0088120777AB45E5472401F9E43546FA75F6 ++:100CDE00560075570075584B755900755A05121CFC ++:100CEE0001854858854959854A5A755B08AB45AA0E ++:060CFE0046A947021AB0EE ++:101A05008F4190E0B7E0FEA3E054F064607003EE10 ++:101A1500641160037F012290E037E070037F0F229D ++:101A2500E5417003308108E541B401062080037F5C ++:101A3500102290E0BCE0B541037F0122E4F511D20C ++:101A450006121CD8AF4190E0BCEFF024FF92B59090 ++:091A5500E680E054F7F07F002266 ++:04000E0090FC04F06E ++:1000120090E678E0541824F06008240870087F50B5 ++:0800220080067F518002E4FF1B ++:01002A0022B3 ++:0C0F5B00AD45AC447B007A007943AF4206 ++:0C0F67008F488C498D4A8B4B8A4C894D79 ++:100F7300E4F54EF54F755003FDF551F552A2AF332D ++:100F8300F553E54824AF600D047012754E00754F9C ++:100F9300017D018008754E00754F02E4FDE5486050 ++:100FA30051E54F454E604BE54990E0B9F0E54AA362 ++:100FB300F074B92DF582E434E0AD82FCAB4FAF4859 ++:100FC30012193D7551008F527F0A7E00121AFAE5FD ++:100FD30052455160107CE07D6E7B01AF481215963F ++:100FE3007551008F5290E06EE0AB4BAA4CA94D12A5 ++:0C0FF3000777E55324FF92AFAE51AF52D8 ++:010FFF0022CF ++:0C175B008F4E8C4F8D508B518A52895359 ++:10176700E4F554F555755603FDF557F558A2AF3313 ++:10177700F559E54E24AF600D047012755400755588 ++:10178700027D018008755400755503E4FDE54E6040 ++:101797003FE55545546039E54F90E0B9F0E550A372 ++:1017A700F0AB51AA52A95312073190E0BBF0C2B770 ++:1017B70074B92DF582E434E0AD82FCAB55AF4E121F ++:1017C700193D7557008F587F0A7E00121AFAD2B753 ++:0A17D700E55924FF92AFAE57AF585A ++:0117E10022E5 ++:10005600E4F531F532F535F53CF53DF53EF53FE590 ++:10006600AA5484600302063A90E694E0FE90E69570 ++:10007600E0FBEEF53CEBF53DC39405E53C94004012 ++:100086000790F404E0FD80027DFFED12085F00CECC ++:100096000102C30503080703580903D80B011E0E06 ++:1000A60000E40F019411025E130541250401310499 ++:1000B6005732046A3404B23504C93604E63703E518 ++:1000C6004503F647000005BA75310075320790FC06 ++:1000D600047481F0A37414F0E4A3F00205DD7F0F2D ++:1000E600121E0275310075320690FC047480F0E42D ++:1000F600A3F0753505F511FE74002535F9EE34F4D7 ++:10010600FA7B011217E2400690FC05740EF0E4FF3C ++:10011600120E317F8F0202BD7F0E121E0275310054 ++:10012600753205748E12000E8F3F7B007A0079407F ++:10013600E4FDFC120F67E53F64516019E53F64502A ++:10014600601375310075320690FC047480F0A37458 ++:100156000BF00205DD90E0BDE0FF120E31740025C4 ++:1001660032F974FC3531FA7B01C0038B567557E0C2 ++:1001760075586F755900755A2CD003121C01742CD2 ++:100186002532F532E43531F5317F8E0202BD753107 ++:100196000075320790FC047491F090E678E090FCCC ++:1001A60005F030B3047F0280027F0030B4047E0184 ++:1001B60080027E00EE4F90FC06F074002532F97442 ++:1001C600FC3531FA7B01755700755812E4FD121D96 ++:1001D6008C74002532F974FC3531FA7B01C0038B2F ++:1001E600567557E0755839755900755A06D0031279 ++:1001F6001C0174062532F532E43531F531FE740002 ++:100206002532F974FC3EFA7B01C0038B567557E024 ++:10021600755814755900755A06D003121C017406D8 ++:100226002532F532E43531F531FE74002532F974A4 ++:10023600FC3EFA7B01C0038B567557E075584C752A ++:100246005900755A06D003121C0174062532F53280 ++:10025600E43531F5310205DD7F13121E02753100DA ++:1002660075321D749312000E8F3F75381D75390057 ++:10027600753600753705D3E5399418E538941D5061 ++:1002860034E53FB4510E7B007A007940AD39AC3885 ++:10029600FF120F6774002537F58274FC3536F58337 ++:1002A600E540F00539E539700205380537E5377060 ++:1002B600C5053680C17F93121E020205DD75310029 ++:1002C60075320690FC047480F0E4A3F090F405E027 ++:1002D60090E038F0E0147071121E3430B31B75567E ++:1002E600017557F4755806755900755A067B017ADB ++:1002F600E07914121C010205DD90FC057401F00280 ++:1003060003D075310075320690FC047480F0E4A3C6 ++:10031600F0753507AF35FEC3E53D9FF534E53C9EE8 ++:10032600F53390E038E014702074002FF974F43E31 ++:10033600FA7B01AF34AE33121A5E5004E40204C2F3 ++:1003460090FC05740CF00205DD90FC057403F002C8 ++:1003560005DD75310075320690FC047480F0E4A367 ++:10036600F090E038E014705CE4FFFE20B411C2B2F5 ++:10037600D2B1D2B20FBF00010EEF640A4E70EC305C ++:10038600B43A90E6017403F07F647E00121E229058 ++:10039600E0BDE0FF120E317EE07F6F7CE07DBE1295 ++:1003A60018CD7EE07FBEAD1CAC1B12185A5005124C ++:1003B6000B4E801690FC05740EF0800E90FC0574B2 ++:1003C6000DF0800690FC057403F0E490E038F0022E ++:1003D60005DDE4F531F5327F02121B400205DDE44E ++:1003E600FF120E31121126E4FF121A05E4FF8002F5 ++:1003F6007F01121B40121E340205DD753100753275 ++:100406000690FC047480F0E4A3F090F405E0F53E59 ++:10041600E4F511E53E64016004E53E703290E0B714 ++:10042600E0FEA3E054F064607003EE6411600280A5 ++:100436007290E037E070028058E5116401600AE5C9 ++:1004460011700C121CA7EF6006853E110205DD80B7 ++:100456005275310075320690FC0474B2F0A3E511B2 ++:10046600F00205DD75310075320690FC047480F0EB ++:10047600E4A3F090F405E0F53EFF121A05EF24F12F ++:10048600600F1460152410701AE4F531F532020578 ++:10049600DD90FC05740FF00205DD90FC057410F08C ++:1004A6000205DD90FC057401F00205DD753100756D ++:1004B600320690FC0474B5F090E0BCE090FC05F0C8 ++:1004C6000205DD75310075320690FC0474B6F0A2A3 ++:1004D60080E43325E0FFA281E4334FA3F00205DD7B ++:1004E600853C31853D3290FC0474B7F0753505C303 ++:1004F600E53D9535F534E53C9400F5337400253536 ++:10050600F582E434F4F583E0648870030205DDAF18 ++:10051600357E0074002FF9EE34F4FA7B01C003C077 ++:100526000174002FF9EE34FC8B58F559895A85343D ++:100536005BD001D003121AB00205DD7531007532A9 ++:100546000590FC0474A5F01200128F3F7B007A0020 ++:100556007940E4FDFC120F6790E036E0FF0532E5D6 ++:1005660032AC3170020531142400F58274FC3CF57E ++:1005760083EFF090E0BDE0FF0532E532AC3170026A ++:100586000531142400F58274FC3CF583EFF0053246 ++:10059600E532AE3170020531142400F58274FC3E5A ++:1005A600F583E540F090E6017403F07F647E001267 ++:1005B6001E22802375310075320690FC047480F08B ++:1005C600C3E53D9405E53C94005006A37407F0800E ++:1005D6000690FC057406F090F404E0B48004A3E0F1 ++:1005E600701290F404E06405600FE06407600AE0AE ++:1005F60064096005E490E038F0E5324531602CE5A9 ++:1006060032FD90FC00F0E531FFA3F090F402E0909B ++:10061600FC02F090F403E090FC03F090E69CEFF00F ++:1006260000000090E69DEDF000000090E6957480D5 ++:04063600F0000000D0 ++:01063A00229D ++:02004100D322C8 ++:0800030090E6BAE0F51DD322DE ++:101EE50090E740E51DF0E490E68AF090E68B04F07B ++:021EF500D322F6 ++:08002B0090E6BAE0F51AD322B9 ++:101F180090E740E51AF0E490E68AF090E68B04F04A ++:021F2800D322C2 ++:101DB40090E6B9E0242F600D04701990E604E0FF6A ++:101DC400430780800890E604E0FF53077F0000008B ++:071DD400EFF08002D322C3EF ++:011DDB0022E5 ++:101E4C00C0E0C083C082D2015391EF90E65D740173 ++:081E5C00F0D082D083D0E03207 ++:101E9300C0E0C083C0825391EF90E65D7404F0D03C ++:061EA30082D083D0E03282 ++:101EA900C0E0C083C0825391EF90E65D7402F0D028 ++:061EB90082D083D0E0326C ++:101C3B00C0E0C083C08285120D85130E850E828590 ++:101C4B000D83A37402F085090F850A108510828518 ++:101C5B000F83A37407F05391EF90E65D7410F0D0EF ++:061C6B0082D083D0E032BC ++:101E6400C0E0C083C082D2035391EF90E65D740852 ++:081E7400F0D082D083D0E032EF ++:101BC400C0E0C083C08290E680E030E72085090D44 ++:101BD400850A0E850E82850D83A37402F085120F8B ++:101BE400851310851082850F83A37407F05391EF3A ++:0D1BF40090E65D7420F0D082D083D0E03206 ++:101ED200000102020303040405050300000000C020 ++:031EE200C200003B ++:0612F100011100010800DC ++:03000B0002137C61 ++:10137C00C0E0C0F0C083C082C0D075D000C000C037 ++:0D138C0001C002C003C004C005C006C007B8 ++:1013990078217C007D007BFF7A1E79DC7E007F0549 ++:1013A90012070B90E0BCE0F526C204752700E5089A ++:1013B900600415088056750805E5117004C204809B ++:1013C90043A280308101B3500B3081047F0080300B ++:1013D9007F01802C30B415755800755900755A2154 ++:1013E900755B057B007A007921121AB0E523540157 ++:1013F900F527701090E0BCE060047F0080027F0157 ++:0C1409008F26D204300405AF26121A050D ++:10141500D007D006D005D004D003D002D001D0002B ++:0B142500D0D0D082D083D0F0D0E032D5 ++:100D0400785C7CE17D017BFF7A1E79E17E007F04C3 ++:100D140012070BC203C200D202C201121DDC121E52 ++:100D24007C12163B750B10750C007514107515129A ++:100D3400750910750A1C75121075137085120F85CC ++:100D440013107516107517B412001290E15AEFF0D3 ++:100D54007B017AE1795BE4FDFC120F6790E15BE0D3 ++:100D6400FF90E036F0E490E0BDF0EF64C26059EF2C ++:100D740064C06054E490E160F090E160E0FFC394EB ++:100D840004504A745C2FF582E434E1F583E0FF609B ++:100D94003C120E317EE07F6F7CE07DBE1218CD7E6A ++:100DA400E07FBEAD1CAC1B12185A501490E160E0F9 ++:100DB400245CF582E434E1F583E090E0BDF0800D3D ++:100DC40090E160E004F080B1E4FF120E31121126CC ++:100DD400D2E843D82090E668E04409F090E65CE06D ++:100DE400443DF012001290E15AEFF07B017AE17970 ++:100DF4005BE4FDFC120F6790E15BE064C26007E412 ++:100E040090E0BCF0C2B57F01121B40D2AFD28C532C ++:100E14008EF8C203C2AF120056D2AF3001051209D8 ++:0D0E240026C2013003EEC203121D3580E727 ++:0B00460090E50DE030E402C322D3225D ++:1009260090E6B9E070030209EB147003020A602432 ++:10093600FE7003020ADB24FB70030209E514700350 ++:100946000209DF1470030209D31470030209D924C3 ++:10095600056003020B3A1200414003020B4690E683 ++:10096600BBE024FE602714603E24FD60111460275E ++:1009760024067056E50B90E6B3F0E50C80421200B3 ++:10098600465044E51490E6B3F0E5158033E50D9046 ++:10099600E6B3F0E50E802985120F851310E50F905A ++:1009A600E6B3F0E510801990E6BAE0FF121D61AAE1 ++:1009B60006A9077B01EA494B600DEE90E6B3F0EF1E ++:1009C60090E6B4F0020B46020B35020B35121F18E7 ++:1009D600020B4612002B020B46120003020B4612B4 ++:1009E6001EE5020B4690E6B8E0247F6015146019F8 ++:1009F60024027063A200E43325E0FFA202E4334F31 ++:100A06008041E490E740F0803F90E6BCE0547EFFF2 ++:100A16007E00E0D394807C0040047D0180027D004E ++:100A2600EC4EFEED4F24D2F582741E3EF583E49320 ++:100A3600FF3395E0FEEF24A1FFEE34E68F82F583C7 ++:100A4600E0540190E740F0E4A3F090E68AF090E6E7 ++:100A56008B7402F0020B46020B3590E6B8E024FEDA ++:100A6600601624026003020B4690E6BAE0B4010564 ++:100A7600C200020B46020B3590E6BAE0705590E6CE ++:100A8600BCE0547EFF7E00E0D394807C0040047D71 ++:100A96000180027D00EC4EFEED4F24D2F582741EDD ++:100AA6003EF583E493FF3395E0FEEF24A1FFEE3499 ++:100AB600E68F82F583E054FEF090E6BCE0548013A6 ++:100AC6001313541FFFE0540F2F90E683F0E04420E9 ++:100AD600F0806D805A90E6B8E024FE60192402701A ++:100AE6004E90E6BAE0B40104D200805490E6BAE033 ++:100AF6006402604C803990E6BCE0547EFF7E00E0E4 ++:100B0600D394807C0040047D0180027D00EC4EFE83 ++:100B1600ED4F24D2F582741E3EF583E493FF3395A0 ++:100B2600E0FEEF24A1FFEE34E68F82F583800D9080 ++:100B3600E6A08008121DB4500790E6A0E04401F03C ++:070B460090E6A0E04480F0FE ++:010B4D002285 ++:03003300021EFCAE ++:041EFC0053D8EF3296 ++:1012F7006080E0DA292E43C9A2D87C013D3654A18B ++:10130700ECF0061362A705F3C0C7738C98932BD92B ++:10131700BC4C82CA1E9B573CFDD4E01667426F182F ++:101327008A17E512BE4EC4D6DA9EDE49A0FBF58EBB ++:10133700BB2FEE7AA968799115B2073F94C210893D ++:101347000B225F21807F5D9A5A903227353ECCE78A ++:10135700BFF79703FF1930B348A5B5D1D75E922AD7 ++:10136700AC56AAC64FB838D296A47DB676FC6BE2C7 ++:041377009C7404F16D ++:081430008C468D47AB07AA06AC ++:10143800E4F548F549C3E5499547E5466480F8E58C ++:101448004864809840030214DFE54925E0FFE54839 ++:1014580033FE74DA2FF58274E03EF583E0FF7E00F8 ++:10146800AC46AD471207BD8C4A8D4BE54925E0FFD8 ++:10147800E54833FE74DB2FF58274E03EF583E0FF28 ++:101488007E00AC46AD471207BD8C4C8D4DE54B65D3 ++:101498004D7004E54A654C6030EB254BF582EA3522 ++:1014A8004AF583E0F9EB254DF582EA354CF583E002 ++:1014B800FFEB254BF582EA354AF583EFF0EB254D36 ++:1014C800F582EA354CF583E9F00549E54960030200 ++:0B14D800143D054802143D7E007F011A ++:0114E30022E6 ++:0C14E4008E468F478C488D498A4A8B4BFE ++:1014F000E54745466006E54945487004E4FEFF229D ++:10150000E4F54CF54DC3E54D954BE54A6480F8E5AF ++:101510004C648098507BE4F54EF54FE549254DF538 ++:1015200082E548354CF583E4F0C3E54F954BE54A39 ++:101530006480F8E54E6480985049E54F254D24DAE3 ++:10154000F582E434E0F583E0FFE547254FF582E5D9 ++:1015500046354EF583E0FEEF8EF0A4FFE549254DBC ++:10156000F582E548354CF583E02FFFE549254DF53B ++:1015700082E548354CF583EFF0054FE54F70AA053D ++:101580004E80A6054DE54D6003021505054C02157C ++:05159000057E007F0153 ++:011595002233 ++:101D0700120731FF90000312074A1207779000036A ++:101D1700EF12078990000212074AFF90000112078D ++:0E1D27004A900002120789900001EF0207891E ++:0811F5008E468F478C488D499E ++:1011FD00E4F54AF54BE549AE487802CEA2E713CEA9 ++:10120D0013D8F8FFC3E54B9FEE6480F8E54A648080 ++:10121D009840030212B7E54BAE4A7802C333CE3382 ++:10122D00CED8F92547FFEE3546FAA9077B018B4C41 ++:10123D00F54D894E74DB254BF582E434E0F583E002 ++:10124D00541FFFE48F52F551F550F54F121D07ABAA ++:10125D004CAA4DA94E120819C374209552F9F812D3 ++:10126D000806C004C005C006C007A94E120819A97A ++:10127D0052A8011207F3D003D002D001D000EF4BDA ++:10128D00FFEE4AFEED49FDEC48FCAB4CAA4DA94ED4 ++:10129D00120839AB4CAA4DA94E121D07054BE54B53 ++:0E12AD006003021202054A0212027E007F0157 ++:0112BB002210 ++:101C7100D3ED9410EC64809480402AED1D70011C1A ++:101C8100142FF582EE3CF583E0FB547F24DAF582D4 ++:101C9100E434E0F583E0F9540F2FF582E43EF58357 ++:051CA100E06BF080CBB8 ++:011CA600221B ++:101D350090E682E030E004E020E60B90E682E030B9 ++:101D4500E119E030E71590E680E04401F07F147E6C ++:0C1D550000121AFA90E680E054FEF02222 ++:101CD80030060990E680E0440AF0800790E680E04C ++:101CE8004408F07FDC7E05121AFA90E65D74FFF076 ++:0F1CF80090E65FF05391EF90E680E054F7F02212 ++:101AFA008E5A8F5B90E600E054187012E55B240161 ++:101B0A00FFE4355AC313F55AEF13F55B801590E6D7 ++:101B1A0000E05418FFBF100BE55B25E0F55BE55AC2 ++:101B2A0033F55AE55B155BAE5A7002155A4E6005DD ++:061B3A00121F2A80EE22BA ++:061596008C548D55AE07D8 ++:10159C00EB70037F012290E678E020E6F990E67884 ++:1015AC007480F0EE25E0440190E679F090E678E066 ++:1015BC0030E0F990E678E020E26BE030E167BB01C7 ++:1015CC000790E678E04420F090E679E0F5561BEBC6 ++:1015DC00603090E678E030E0F990E678E020E24583 ++:1015EC00BB010790E678E04420F090E679E0FF0537 ++:1015FC0055E555AC547002055414F5828C83EFF00C ++:10160C0080CC90E678E030E0F990E678E020E215C6 ++:10161C0090E678E04440F090E679E0855582855478 ++:0E162C0083F07F012290E678E04440F07F00DA ++:01163A00228D ++:10193D0090E678E020E6F990E6787480F0EF25E007 ++:10194D0090E679F090E678E030E0F990E678E020E6 ++:10195D00E23AE030E136EBD3940040260DEDAE04D3 ++:10196D0070010C14F5828E83E090E679F01B90E601 ++:10197D0078E030E0F990E678E020E210E020E1D662 ++:10198D00800A90E678E04440F07F012290E678E00E ++:05199D004440F07F0052 ++:0119A2002222 ++:021D6100A907D0 ++:101D6300AE16AF178F828E83A3E064037017AD01A5 ++:101D730019ED7001228F828E83E07C002FFDEC3EF3 ++:081D8300FEAF0580DFE4FEFF66 ++:011D8B002235 ++:101F2A007400F58690FDA57C05A3E582458370F9CA ++:011F3A002284 ++:030000000216CF16 ++:0C16CF00787FE4F6D8FD75815D021716E7 ++:10063B00E709F608DFFA8046E709F208DFFA803EA1 ++:10064B0088828C83E709F0A3DFFA8032E309F6088E ++:10065B00DFFA8078E309F208DFFA807088828C83F6 ++:10066B00E309F0A3DFFA806489828A83E0A3F608AA ++:10067B00DFFA805889828A83E0A3F208DFFA804C84 ++:10068B0080D280FA80C680D4806980F2803380105B ++:10069B0080A680EA809A80A880DA80E280CA8033C4 ++:1006AB0089828A83ECFAE493A3C8C582C8CCC5833C ++:1006BB00CCF0A3C8C582C8CCC583CCDFE9DEE7800C ++:1006CB000D89828A83E493A3F608DFF9ECFAA9F08B ++:1006DB00EDFB2289828A83ECFAE0A3C8C582C8CCE1 ++:1006EB00C583CCF0A3C8C582C8CCC583CCDFEADEFA ++:1006FB00E880DB89828A83E493A3F208DFF980CC5C ++:10070B0088F0EF60010E4E60C388F0ED2402B40454 ++:10071B000050B9F582EB2402B4040050AF232345FB ++:06072B00822390068B738F ++:10073100BB010689828A83E0225002E722BBFE02C6 ++:09074100E32289828A83E49322F9 ++:10074A00BB010CE58229F582E5833AF583E0225064 ++:10075A0006E92582F8E622BBFE06E92582F8E222AE ++:0D076A00E58229F582E5833AF583E49322C8 ++:10077700BB010689828A83F0225002F722BBFE0161 ++:02078700F3225B ++:10078900F8BB010DE58229F582E5833AF583E8F0A6 ++:10079900225006E92582C8F622BBFE05E92582C852 ++:0207A900F2223A ++:1007AB00EF8DF0A4A8F0CF8CF0A428CE8DF0A42E62 ++:0207BB00FE221C ++:1007BD00C2D5EC30E709B2D5E4C39DFDE49CFCEE57 ++:1007CD0030E715B2D5E4C39FFFE49EFE120885C342 ++:1007DD00E49DFDE49CFC800312088530D507C3E43D ++:0607ED009FFFE49EFE22C6 ++:1007F300E8600FECC313FCED13FDEE13FEEF13FFE4 ++:03080300D8F12207 ++:10080600E8600FEFC333FFEE33FEED33FDEC33FC50 ++:03081600D8F122F4 ++:10081900BB010789828A830208E65005E9F80208C4 ++:10082900DABBFE05E9F80208F289828A830208FE2A ++:10083900BB010789828A830208535005E9F8020936 ++:0A0849000EBBFE05E9F802091A22B1 ++:0C085300ECF0A3EDF0A3EEF0A3EFF02218 ++:10085F00D083D082F8E4937012740193700DA3A328 ++:10086F0093F8740193F5828883E47374029368603C ++:06087F00EFA3A3A380DF3C ++:1016DB00020D04E493A3F8E493A34003F68001F214 ++:1016EB0008DFF48029E493A3F85407240CC8C33310 ++:1016FB00C4540F4420C8834004F456800146F6DFDF ++:10170B00E4800B01020408102040809012BCE47EA0 ++:10171B00019360BCA3FF543F30E509541FFEE493D3 ++:10172B00A360010ECF54C025E060A840B8E493A39A ++:10173B00FAE493A3F8E493A3C8C582C8CAC583CAC5 ++:10174B00F0A3C8C582C8CAC583CADFE9DEE780BE7D ++:01137B000071 ++:10088500BC000BBE0029EF8DF084FFADF022E4CC57 ++:10089500F875F008EF2FFFEE33FEEC33FCEE9DEC20 ++:1008A500984005FCEE9DFE0FD5F0E9E4CEFD22ED66 ++:1008B500F8F5F0EE8420D21CFEADF075F008EF2FB0 ++:1008C500FFED33FD4007985006D5F0F222C398FDA1 ++:0508D5000FD5F0EA223E ++:0C08DA00E6FC08E6FD08E6FE08E6FF224A ++:0C08E600E0FCA3E0FDA3E0FEA3E0FF2285 ++:0C08F200E2FC08E2FD08E2FE08E2FF2242 ++:1008FE00E493FC740193FD740293FE740393FF2240 ++:0C090E00ECF608EDF608EEF608EFF62215 ++:0C091A00ECF208EDF208EEF208EFF22219 ++:00000001FF ++ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_FW.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_FW.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_FW.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_FW.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,578 @@ ++# ++# $Id: USB_FW.hex 11452 2015-03-29 18:21:13Z dima $ ++# ++:03004300021F0099 ++:03005300021F0089 ++:101F0000021E3400021E9100021E7B00021E4C00C5 ++:081F1000021C1F00021BA800C7 ++:101000001201000200000040AAAAAAAAAAAA01028C ++:1010100003010A0600020000004001000902370037 ++:10102000020100C0000904000002FFFFFF040705E1 ++:101030000202000200070586020002000904010006 ++:1010400002FFFFFF050705040200020007058802F2 ++:10105000000200001201000200000040E4E451110F ++:101060000000010203010A06000200000040010026 ++:1010700009023700020100C0320904000002FFFF2C ++:10108000FF04070502024000000705860240000039 ++:101090000904010002FFFFFF0507050402400000EC ++:1010A0000705880240000006040016001400120024 ++:1010B0000A00260004030904160358006F0072009A ++:1010C00063006F006D0020004C00540044001403C6 ++:1010D00041007300740072006900620061006E00DC ++:1010E0006B001203530065007200690061006C0020 ++:1010F0004E006F000A0346005000470041002603DF ++:101100004D0061006E00610067006D0065006E00BB ++:101110007400500072006F0063006500730073007C ++:061120006F0072000000E8 ++:051EF1000300000000E9 ++:1011F50041E0370041E0B70042E0B2000041E0388D ++:1012050000021BE0860218E07A43E0B40000004EBD ++:10121500E03931313435314D502020202020200057 ++:101D9A008B518A528953E5561556AE557002155520 ++:101DAA004E6014AB510553E553AA52700205521402 ++:081DBA00F9ED12077180DF2230 ++:101BE5008B518A528953E5581558AE5770021557CF ++:101BF5004E6026AB540556E556AA55700205551498 ++:101C0500F912072BFFAB510553E553AA5270020594 ++:0A1C15005214F9EF12077180CD227E ++:101D7000C2B5C2B7E490E670F075B5E653B5EE4370 ++:101D8000B28053B2F4A2B53390E0B7F0C2B3C2B69A ++:0A1D90007F327E00121E0AD2B62236 ++:101E6400538EF75389FB5389F74389015389FDE462 ++:071E7400F58AF58CD2A922CA ++:1017B7008C428D43AA06A9077554018A5589567527 ++:1017C700570075581C7B017AE0794D121BE590E0B4 ++:1017D7004DE0B4C20374C0F090E065E0FCA3E0FD07 ++:1017E700A3E0FEA3E064D1FFEE648DFEED644CFD43 ++:1017F700EC6449FC90E06512084D7EE07F4D7D1C4E ++:101807007C001213647EE07F4D7B1C7A00AD43ACF5 ++:10181700421214187D1C7C00AF43AE42120F367D76 ++:0A1827001C7C00AF43AE42021C55CA ++:0818A9008E428F438C448D45F3 ++:1018B100C20712001290E15CEFF0BF5004D2078022 ++:1018C10057E490E15DF0A3F090E15DE0FEA3E0FF5D ++:1018D100C39410EE648094805030E5452FF582E585 ++:1018E100443EF583E0FF90E15DE0FCA3E02543F594 ++:1018F10082E5423CF583E0B5071090E15EE004F03B ++:1019010070C690E15DE004F080BE90E15DE070049E ++:0A191100A3E064107002D207A207E1 ++:01191B0022A9 ++:020E0C008F3F16 ++:100E0E001200128F40E4F544F545AD45AC44121482 ++:100E1E00CE746A2545F582E434E0F583E541F005AC ++:100E2E0045E54570020544C39408E544648094800A ++:100E3E0040D8E53F600490E06AF090E06AE0B4C00C ++:100E4E0008754200754308800675421D7543367558 ++:100E5E004400754508C3E5459410E54464809480CC ++:100E6E0050231214CA746A2545F582E434E0F583E2 ++:100E7E00E541F00545E545700205440543E543703F ++:100E8E00D4054280D07541FF75421D7543197544D6 ++:100E9E0000754510C3E545942CE54464809480505C ++:100EAE0033E540B4510E7B007A007941AD43AC423C ++:100EBE00FF1214D6746A2545F582E434E0F583E515 ++:100ECE0041F00545E545700205440543E54370C410 ++:100EDE00054280C075421D75433EE4F541F544F56B ++:100EEE0045C3E5459406E54464809480502FE54063 ++:100EFE00B4510A90E06AE0B4C2031214CA744725D2 ++:100F0E0045F582E434E0F583E541F00545E54570AD ++:100F1E000205440543E54370C8054280C490E06A6B ++:070F2E00E0B4C20374C0F03F ++:010F35002299 ++:0A1982008E428F438B448A4589464C ++:10198C007E00E5432DF54BEE3542F54A1200128FE1 ++:10199C0047E5476451600BC3E5439410E54294005E ++:1019AC005035854248854349C3E549954BE54895F3 ++:1019BC004A5024AB44AA45A946AD49AC48AF47129E ++:1019CC0017340549E5497002054874012546F5466A ++:0719DC00E43545F54580D11B ++:0119E30022E1 ++:061831008B3F8A40894153 ++:10183700D2067554017555E075566A755700755887 ++:10184700107B017AE07996121BE5E5412410F9E453 ++:101857003540853F54F555895675570075580C7BAB ++:10186700017AE079A6121BE57EE07F967CE07D1A7F ++:101877001217B77EE07F1AE541241CF9E43540FCD6 ++:10188700AD011218A95016AB3FE5412410F9E43514 ++:1018970040FA7D1C7F197E1D1219828002C206A2A2 ++:0118A700063A ++:0118A800221D ++:101126007F03121D45EF2402FFE43EA907753F0128 ++:10113600F540894190E06BE0FFE50C2408F582E478 ++:10114600350BF583EFF090E06CE0FFE50C2409F534 ++:1011560082E4350BF583EFF090E06DE0FFE50C24BB ++:101166000AF582E4350BF583EFF090E06EE0FFE5DB ++:101176000C240BF582E4350BF583EFF090E06FE07D ++:10118600FFE50C240CF582E4350BF583EFF090E0D7 ++:1011960070E0FFE50C240DF582E4350BF583EFF0E6 ++:1011A6007F087E00E4FDEDC394085028746A2FF58D ++:1011B60082E434E0F583E0FCAB3FAA40A94175F038 ++:1011C60002EDA4F58285F083EC1207830D0FBF00B4 ++:1011D600010E80D2E5192404F582E43518F583E082 ++:0E11E60030E0047F0180027F0090E037EFF0E0 ++:0111F40022D8 ++:101B240090E06DE02FFFE50C240AF582E4350BF517 ++:101B340083EFF0E50C240BF582E4350BF583E0FE2E ++:101B4400E50C240AF582E4350BF583E0FDEDFF9006 ++:101B5400E0B2EEF0A3EFF0D206121CBC90E680E0F7 ++:041B640054F7F02220 ++:1016140090E600E054E74410F090E60174C0F090C6 ++:10162400E6107420F000000090E611F00000009035 ++:10163400E6047480F0000000740FF0000000E4F091 ++:1016440000000090E6187410F0000000E490E61921 ++:10165400F000000090E61A7408F0000000E490E640 ++:101664001BF000000090E6497482F0000000F000D6 ++:10167400000090E6247402F0000000E490E625F0F7 ++:1016840000000090E6957480F0000000F000000077 ++:1016940043AF017B017AE07914755500755606E471 ++:0416A400FD021D9A8C ++:061E0400D2877F0A7E0078 ++:101E0A007C007D181207A5EF1FAC0670011E4C70EE ++:021E1A00F622AE ++:0A1A3D008E3F8F408B418A4289439F ++:101A4700E4F544F545C3E5459540E544953F503BEE ++:101A5700AB41AA42A943854582854483120744FFC7 ++:101A6700E4FBFAC2B2EF1392B7EFC313FFD2B20B84 ++:101A7700BB00010AEB64084A70E9C2B220B002C396 ++:0C1A8700220545E54570BE054480BAD339 ++:011A93002230 ++:101E1C0090E60174C0F0C2B67F967E00121E0AD204 ++:081E2C00B67F327E00021E0A9F ++:101EA700D2B1121E04C2B1121E06C2877F0A7E007B ++:031EB700021E0AFE ++:021B6800AB07C9 ++:101B6A00E4F9FAEBC413131354011392B17F027E02 ++:101B7A0000121E0AD2877F057E00121E0AE925E09E ++:101B8A00FFA283E4334FF97F057E00121E0AEB257C ++:0D1B9A00E0FBC287121E060ABA08C8AF01A0 ++:011BA700221B ++:061A94008B538A548955B2 ++:101A9A00A2AFE433F55B121EA7E4F55AE55AC395E3 ++:101AAA00595027AB53AA54A955855A8275830012F7 ++:101ABA000744FF121B68AB56AA57A958855A827564 ++:101ACA008300EF120783055A80D2120036E55B24A1 ++:031ADA00FF92AFC9 ++:011ADD0022E6 ++:0B003600C2B1121E06121E04D2B1223D ++:101DEA00753F8F8F4075560075570075584975595C ++:0A1DFA00027B007A00793F021A9480 ++:101C8B00783F7C007D007BFF7A1E79F17E007F051B ++:101C9B0012070530B41575560075570075583F750A ++:101CAB0059057B007A00793F121A94E5415401FFE4 ++:011CBB002206 ++:100B4800753F007540007541007543017544E075B7 ++:100B580045007546017547E0754808E4F54FFFF50F ++:100B6800507B017AE07900F555755608FD121D9AFB ++:100B7800AB43AA44A9457401120771E4F54EE54E4A ++:100B8800C454F0AB43AA44A94590000112078385D9 ++:100B98004656854757854858755908121A94AB46E2 ++:100BA800AA47A948900002120744FE5407FFEE54D2 ++:100BB80070F54F24E0602924F0604B24F0605D2438 ++:100BC800F0606F24406003020C50753F01851840A7 ++:100BD800851941EF24FE600624FE703B801C801FAF ++:100BE800E5192401FDE43518A905753F01F540898B ++:100BF80041EF24FC60092402700A75500280527586 ++:100C08005006804D8011E5192402FDE43518A90528 ++:100C1800753F01F54089417550088035E519240371 ++:100C2800FDE43518A905753F01F540894175500463 ++:100C3800801FE5192405FDE43518A905753F01F560 ++:100C48004089417550988009753F0075400075418D ++:100C580000E5404541453F6022AB3FAA40A941120B ++:100C6800072BFED395504006AD50AE0580008E424E ++:100C780012072BC39542120771800CE54F70047E52 ++:100C88000180027E008E427449254EF8A642054E28 ++:100C9800E54EC394055003020B86AB43AA44A9450D ++:100CA8007488120771AB43E5452401F9E43544FA29 ++:100CB80075540075550075564975570075580512D5 ++:100CC8001BE5854656854757854858755908AB43EF ++:070CD800AA44A945021A9489 ++:1019E4008F3F90E0B2E0FEA3E054F064607003EE39 ++:1019F400641160037F012290E037E070037F0F22BF ++:101A0400E53F7003308108E53FB401062080037F81 ++:101A1400102290E0B7E0B53F037F0122E4F511D234 ++:101A240006121CBCAF3F90E0B7EFF024FF92B590D4 ++:091A3400E680E054F7F07F002287 ++:04000E0090FC04F06E ++:1000120090E678E0541824F06008240870087F50B5 ++:0800220080067F518002E4FF1B ++:01002A0022B3 ++:0C14CA00AD43AC427B007A007941AF409A ++:0C14D6008F468C478D488B498A4A894B11 ++:1014E200E4F54CF54D754E03FDF54FF550A2AF33C3 ++:1014F200F551E54624AF600D047012754C00754D30 ++:10150200017D018008754C00754D02E4FDE54660E1 ++:1015120051E54D454C604BE54790E0B4F0E548A3FA ++:10152200F074B42DF582E434E0AD82FCAB4DAF46ED ++:1015320012191C754F008F507F0A7E00121ADEE5C9 ++:1015420050454F60107CE07D697B01AF4612156FFC ++:10155200754F008F5090E069E0AB49AA4AA94B123F ++:0C1562000771E55124FF92AFAE4FAF506F ++:01156E00225A ++:0C1734008F4C8C4D8D4E8B4F8A5089518C ++:10174000E4F552F553755403FDF555F556A2AF3344 ++:10175000F557E54C24AF600D0470127552007553B7 ++:10176000027D018008755200755303E4FDE54C606D ++:101770003BE55345526035E54D90E0B4F0E54EA3AE ++:10178000F0AB4FAA50A95112072B90E0B6F074B4F9 ++:101790002DF582E434E0AD82FCAB53AF4C12191C42 ++:1017A0007555008F567F0A7E00121ADEE55724FF1A ++:0617B00092AFAE55AF56EA ++:0117B6002210 ++:10005600E4F531F532F535F53AF53BF53CF53DE598 ++:10006600AA5484600302063490E694E0FE90E69576 ++:10007600E0FBEEF53AEBF53BC39405E53A94004018 ++:100086000790F404E0FD80027DFFED12085900CED2 ++:100096000102B905030007035F0903C80B011E0E21 ++:1000A60000E40F01941102541305312503F13104C4 ++:1000B6004732045A3404A23504B93604D63703D578 ++:1000C6004503E647000005B475310075320790FC1C ++:1000D600047481F0A37414F0E4A3F00205D77F0F33 ++:1000E600121DEA75310075320690FC047480F0E446 ++:1000F600A3F0753505F511FE74002535F9EE34F4D7 ++:10010600FA7B01121831400690FC05740EF0E4FFEC ++:10011600120E0C7F8F0202B37F0E121DEA7531009C ++:10012600753205748E12000E8F3D7B007A00793E83 ++:10013600E4FDFC1214D6E53D64516019E53D6450BA ++:10014600601375310075320690FC047480F0A37458 ++:100156000BF00205D790E0B8E0FF120E0C740025F4 ++:1001660032F974FC3531FA7B01C0038B547555E0C6 ++:1001760075566A75570075582CD003121BE5742CFA ++:100186002532F532E43531F5317F8E0202B3753111 ++:100196000075320790FC047491F090E678E090FCCC ++:1001A60005F030B4047F0180027F0090FC06EFF07A ++:1001B60074002532F974FC3531FA7B0175550075EA ++:1001C6005612E4FD121D9A74002532F974FC35317D ++:1001D600FA7B01C0038B547555E075563975570087 ++:1001E600755806D003121BE574062532F532E43540 ++:1001F60031F531FE74002532F974FC3EFA7B01C0FC ++:10020600038B547555E0755614755700755806D00E ++:1002160003121BE574062532F532E43531F531FE5D ++:1002260074002532F974FC3EFA7B01C0038B5475C9 ++:1002360055E0755647755700755806D003121BE5ED ++:1002460074062532F532E43531F5310205D77F13D0 ++:10025600121DEA75310075321D749312000E8F3D22 ++:1002660075381D753900753600753705D3E539942F ++:1002760018E538941D5034E53DB4510E7B007A00E4 ++:10028600793EAD39AC38FF1214D674002537F582A5 ++:1002960074FC3536F583E53EF00539E5397002051F ++:1002A600380537E53770C5053680C17F93121DEADC ++:1002B6000205D775310075320690FC047480F0E4AF ++:1002C600A3F090F405E090E038F0E014702A30B026 ++:1002D6001E121E1C7554017555F475560675570089 ++:1002E6007558067B017AE07914121BE50205D79052 ++:1002F600FC057401F00203C08056753100753206A4 ++:1003060090FC047480F0E4A3F0753507AF35FEC3A6 ++:10031600E53B9FF534E53A9EF53390E038E01470FE ++:100326002F20B00330B42074002FF974F43EFA7B0A ++:1003360001AF34AE33121A3D5004E40204B290FC0D ++:1003460005740CF00205D790FC057402F00205D77F ++:1003560090FC057403F00205D775310075320690DE ++:10036600FC047480F0E4A3F090E038E014704530AB ++:10037600B43A90E6017403F07F647E00121E0A9080 ++:10038600E0B8E0FF120E0C7EE07F6A7CE07DB912D9 ++:1003960017B77EE07FB9AD1CAC1B1218A950051229 ++:1003A6000B48801690FC05740EF0800E90FC0574C8 ++:1003B6000DF0800690FC057403F0E490E038F0023E ++:1003C60005D7E4F531F5327F02121B240205D7E486 ++:1003D600FF120E0C121126E4FF1219E4E4FF80024C ++:1003E6007F01121B24121E1C0205D77531007532BF ++:1003F6000690FC047480F0E4A3F090F405E0F53C6C ++:10040600E4F511E53C64016004E53C703290E0B22D ++:10041600E0FEA3E054F064607003EE6411600280B5 ++:100426007290E037E070028058E5116401600AE5D9 ++:1004360011700C121C8BEF6006853C110205D780EB ++:100446005275310075320690FC0474B2F0A3E511C2 ++:10045600F00205D775310075320690FC047480F001 ++:10046600E4A3F090F405E0F53CFF1219E4EF24F163 ++:10047600600F1460152410701AE4F531F532020588 ++:10048600D790FC05740FF00205D790FC057410F0A8 ++:100496000205D790FC057401F00205D77531007589 ++:1004A600320690FC0474B5F090E0B7E090FC05F0DD ++:1004B6000205D775310075320690FC0474B6F0A2B9 ++:1004C60080E43325E0FFA281E4334FA3F00205D791 ++:1004D600853A31853B3290FC0474B7F0753505C317 ++:1004E600E53B9535F534E53A9400F533740025354A ++:1004F600F582E434F4F583E0648870030205D7AF2F ++:10050600357E0074002FF9EE34F4FA7B01C003C087 ++:100516000174002FF9EE34FC8B56F5578958853453 ++:1005260059D001D003121A940205D77531007532DD ++:100536000590FC0474A5F01200128F3D7B007A0032 ++:10054600793EE4FDFC1214D690E036E0FF0532E574 ++:1005560032AC3170020531142400F58274FC3CF58E ++:1005660083EFF090E0B8E0FF0532E532AC3170027F ++:100576000531142400F58274FC3CF583EFF0053256 ++:10058600E532AE3170020531142400F58274FC3E6A ++:10059600F583E53EF00532E532AE317002053114E1 ++:1005A6002400F58274FC3EF58374FFF080237531D8 ++:1005B6000075320690FC047480F0C3E53B9405E5B3 ++:1005C6003A94005006A37407F0800690FC05740662 ++:1005D600F090F404E0B48004A3E0701290F404E018 ++:1005E6006405600FE06407600AE064096005E49052 ++:1005F600E038F0E5324531602CE532FD90FC00F044 ++:10060600E531FFA3F090F402E090FC02F090F403D1 ++:10061600E090FC03F090E69CEFF000000090E69D71 ++:0E062600EDF000000090E6957480F0000000FA ++:0106340022A3 ++:02004100D322C8 ++:0800030090E6BAE0F51DD322DE ++:101ECD0090E740E51DF0E490E68AF090E68B04F093 ++:021EDD00D3220E ++:08002B0090E6BAE0F51AD322B9 ++:101EDF0090E740E51AF0E490E68AF090E68B04F084 ++:021EEF00D322FC ++:101DC20090E6B9E0242F600D04701990E604E0FF5C ++:101DD200430780800890E604E0FF53077F0000007D ++:071DE200EFF08002D322C3E1 ++:011DE90022D7 ++:101E3400C0E0C083C082D2015391EF90E65D74018B ++:081E4400F0D082D083D0E0321F ++:101E7B00C0E0C083C0825391EF90E65D7404F0D054 ++:061E8B0082D083D0E0329A ++:101E9100C0E0C083C0825391EF90E65D7402F0D040 ++:061EA10082D083D0E03284 ++:101C1F00C0E0C083C08285120D85130E850E8285AC ++:101C2F000D83A37402F085090F850A108510828534 ++:101C3F000F83A37407F05391EF90E65D7410F0D00B ++:061C4F0082D083D0E032D8 ++:101E4C00C0E0C083C082D2035391EF90E65D74086A ++:081E5C00F0D082D083D0E03207 ++:101BA800C0E0C083C08290E680E030E72085090D60 ++:101BB800850A0E850E82850D83A37402F085120FA7 ++:101BC800851310851082850F83A37407F05391EF56 ++:0D1BD80090E65D7420F0D082D083D0E03222 ++:101EBA00000102020303040405050300000000C038 ++:031ECA00C2000053 ++:06122500011100010800A8 ++:03000B000212B02E ++:1012B000C0E0C0F0C083C082C0D075D000C000C004 ++:0D12C00001C002C003C004C005C006C00785 ++:1012CD0078217C007D007BFF7A1E79C47E007F052E ++:1012DD0012070590E0B7E0F526C204752700E50872 ++:1012ED00600415088056750805E5117004C2048068 ++:1012FD0043A280308101B3500B3081047F008030D8 ++:10130D007F01802C30B41575560075570075582126 ++:10131D007559057B007A007921121A94E523540141 ++:10132D00F527701090E0B7E060047F0080027F0128 ++:0C133D008F26D204300405AF261219E4FC ++:10134900D007D006D005D004D003D002D001D000F8 ++:0B135900D0D0D082D083D0F0D0E032A2 ++:100CDF0078577CE17D017BFF7A1E79C97E007F0406 ++:100CEF00120705C203C200D202C201121D70121EEA ++:100CFF0064121614750B10750C00751410751512FF ++:100D0F00750910750A1C75121075137085120F85F1 ++:100D1F0013107516107517B412001290E155EFF0FD ++:100D2F007B017AE17956E4FDFC1214D690E156E08E ++:100D3F00FF90E036F0E490E0B8F0EF64C26059EF56 ++:100D4F0064C06054E490E15BF090E15BE0FFC3941A ++:100D5F0004504A74572FF582E434E1F583E0FF60C5 ++:100D6F003C120E0C7EE07F6A7CE07DB91217B77ED5 ++:100D7F00E07FB9AD1CAC1B1218A9501490E15BE0D9 ++:100D8F002457F582E434E1F583E090E0B8F0800D6C ++:100D9F0090E15BE004F080B1E4FF120E0C1211261B ++:100DAF00D2E843D82090E668E04409F090E65CE092 ++:100DBF00443DF012001290E155EFF07B017AE1799A ++:100DCF0056E4FDFC1214D690E156E064C26007E4CD ++:100DDF0090E0B7F0C2B57F01121B24D2AFD28C5373 ++:100DEF008EF8C203C2AF120056D2AF3001051209FE ++:0D0DFF0020C2013003EEC203121D1980E76F ++:0B00460090E50DE030E402C322D3225D ++:1009200090E6B9E070030209E5147003020A5A2444 ++:10093000FE7003020AD524FB70030209DF14700362 ++:100940000209D91470030209CD1470030209D324DB ++:10095000056003020B341200414003020B4090E695 ++:10096000BBE024FE602714603E24FD601114602764 ++:1009700024067056E50B90E6B3F0E50C80421200B9 ++:10098000465044E51490E6B3F0E5158033E50D904C ++:10099000E6B3F0E50E802985120F851310E50F9060 ++:1009A000E6B3F0E510801990E6BAE0FF121D45AA03 ++:1009B00006A9077B01EA494B600DEE90E6B3F0EF24 ++:1009C00090E6B4F0020B40020B2F020B2F121EDF39 ++:1009D000020B4012002B020B40120003020B4012CC ++:1009E0001ECD020B4090E6B8E0247F60151460191C ++:1009F00024027063A200E43325E0FFA202E4334F37 ++:100A00008041E490E740F0803F90E6BCE0547EFFF8 ++:100A10007E00E0D394807C0040047D0180027D0054 ++:100A2000EC4EFEED4F24BAF582741E3EF583E4933E ++:100A3000FF3395E0FEEF24A1FFEE34E68F82F583CD ++:100A4000E0540190E740F0E4A3F090E68AF090E6ED ++:100A50008B7402F0020B40020B2F90E6B8E024FEEC ++:100A6000601624026003020B4090E6BAE0B4010570 ++:100A7000C200020B40020B2F90E6BAE0705590E6E0 ++:100A8000BCE0547EFF7E00E0D394807C0040047D77 ++:100A90000180027D00EC4EFEED4F24BAF582741EFB ++:100AA0003EF583E493FF3395E0FEEF24A1FFEE349F ++:100AB000E68F82F583E054FEF090E6BCE0548013AC ++:100AC0001313541FFFE0540F2F90E683F0E04420EF ++:100AD000F0806D805A90E6B8E024FE601924027020 ++:100AE0004E90E6BAE0B40104D200805490E6BAE039 ++:100AF0006402604C803990E6BCE0547EFF7E00E0EA ++:100B0000D394807C0040047D0180027D00EC4EFE89 ++:100B1000ED4F24BAF582741E3EF583E493FF3395BE ++:100B2000E0FEEF24A1FFEE34E68F82F583800D9086 ++:100B3000E6A08008121DC2500790E6A0E04401F034 ++:070B400090E6A0E04480F004 ++:010B4700228B ++:03003300021EF6B4 ++:041EF60053D8EF329C ++:10122B006080E0D5292E43C9A2D87C013D3654A15C ++:10123B00ECF0061362A705F3C0C7738C98932BD9F8 ++:10124B00BC4C82CA1E9B573CFDD4E01667426F18FC ++:10125B008A17E512BE4EC4D6DA9EDE49A0FBF58E88 ++:10126B00BB2FEE7AA968799115B2073F94C210890A ++:10127B000B225F21807F5D9A5A903227353ECCE757 ++:10128B00BFF79703FF1930B348A5B5D1D75E922AA4 ++:10129B00AC56AAC64FB838D296A47DB676FC6BE294 ++:0412AB009C7404F13A ++:081364008C448D45AB07AA067D ++:10136C00E4F546F547C3E5479545E5446480F8E563 ++:10137C00466480984003021413E54725E0FFE546D8 ++:10138C0033FE74D52FF58274E03EF583E0FF7E00CA ++:10139C00AC44AD451207B78C488D49E54725E0FFB5 ++:1013AC00E54633FE74D62FF58274E03EF583E0FFFC ++:1013BC007E00AC44AD451207B78C4A8D4BE54965B0 ++:1013CC004B7004E548654A6030EB2549F582EA35F7 ++:1013DC0048F583E0F9EB254BF582EA354AF583E0D5 ++:1013EC00FFEB2549F582EA3548F583EFF0EB254B09 ++:1013FC00F582EA354AF583E9F00547E547600302D3 ++:0B140C00137105460213717E007F0182 ++:0114170022B2 ++:0C1418008E448F458C468D478A488B49D6 ++:10142400E54545446006E54745467004E4FEFF2271 ++:10143400E4F54AF54BC3E54B9549E5486480F8E586 ++:101444004A648098507BE4F54CF54DE547254BF50F ++:1014540082E546354AF583E4F0C3E54D9549E54810 ++:101464006480F8E54C6480985049E54D254B24D5BB ++:10147400F582E434E0F583E0FFE545254DF582E5AA ++:1014840044354CF583E0FEEF8EF0A4FFE547254B91 ++:10149400F582E546354AF583E02FFFE547254BF510 ++:1014A40082E546354AF583EFF0054DE54D70AA0512 ++:1014B4004C80A6054BE54B6003021439054A02141F ++:0514C400397E007F01EC ++:0114C9002200 ++:101CEB0012072BFF90000312074412077190000399 ++:101CFB00EF120783900002120744FF9000011207B6 ++:0E1D0B0044900002120783900001EF0207834C ++:080F36008E448F458C468D4767 ++:100F3E00E4F548F549E547AE467802CEA2E713CE72 ++:100F4E0013D8F8FFC3E5499FEE6480F8E548648046 ++:100F5E00984003020FF8E549AE487802C333CE330A ++:100F6E00CED8F92545FFEE3544FAA9077B018B4A09 ++:100F7E00F54B894C74D62549F582E434E0F583E0CF ++:100F8E00541FFFE48F50F54FF54EF54D121CEBAB91 ++:100F9E004AAA4BA94C120813C374209550F9F812A3 ++:100FAE000800C004C005C006C007A94C120813A94A ++:100FBE0050A8011207EDD003D002D001D000EF4BA4 ++:100FCE00FFEE4AFEED49FDEC48FCAB4AAA4BA94C9C ++:100FDE00120833AB4AAA4BA94C121CEB0549E54942 ++:0E0FEE006003020F430548020F437E007F019F ++:010FFC0022D2 ++:101C5500D3ED9410EC64809480402AED1D70011C36 ++:101C6500142FF582EE3CF583E0FB547F24D5F582F5 ++:101C7500E434E0F583E0F9540F2FF582E43EF58373 ++:051C8500E06BF080CBD4 ++:011C8A002237 ++:101D190090E682E030E004E020E60B90E682E030D5 ++:101D2900E119E030E71590E680E04401F07F147E88 ++:0C1D390000121ADE90E680E054FEF0225A ++:101CBC0030060990E680E0440AF0800790E680E068 ++:101CCC004408F07FDC7E05121ADE90E65D74FFF0AE ++:0F1CDC0090E65FF05391EF90E680E054F7F0222E ++:101ADE008E588F5990E600E054187012E559240183 ++:101AEE00FFE43558C313F558EF13F559801590E6FA ++:101AFE0000E05418FFBF100BE55925E0F559E558E5 ++:101B0E0033F558E5591559AE58700215584E600503 ++:061B1E00121F1880EE22E8 ++:06156F008C528D53AE0703 ++:10157500EB70037F012290E678E020E6F990E678AB ++:101585007480F0EE25E0440190E679F090E678E08D ++:1015950030E0F990E678E020E26BE030E167BB01EE ++:1015A5000790E678E04420F090E679E0F5541BEBEF ++:1015B500603090E678E030E0F990E678E020E245AA ++:1015C500BB010790E678E04420F090E679E0FF055E ++:1015D50053E553AC527002055214F5828C83EFF03B ++:1015E50080CC90E678E030E0F990E678E020E215EE ++:1015F50090E678E04440F090E679E08553828552A4 ++:0E16050083F07F012290E678E04440F07F0001 ++:0116130022B4 ++:10191C0090E678E020E6F990E6787480F0EF25E028 ++:10192C0090E679F090E678E030E0F990E678E02007 ++:10193C00E23AE030E136EBD3940040260DEDAE04F4 ++:10194C0070010C14F5828E83E090E679F01B90E622 ++:10195C0078E030E0F990E678E020E210E020E1D683 ++:10196C00800A90E678E04440F07F012290E678E02F ++:05197C004440F07F0073 ++:011981002243 ++:021D4500A907EC ++:101D4700AE16AF178F828E83A3E064037017AD01C1 ++:101D570019ED7001228F828E83E07C002FFDEC3E0F ++:081D6700FEAF0580DFE4FEFF82 ++:011D6F002251 ++:101F18007400F58690FDA57C05A3E582458370F9DC ++:011F28002296 ++:030000000216A83D ++:0C16A800787FE4F6D8FD75815B0216EF38 ++:10063500E709F608DFFA8046E709F208DFFA803EA7 ++:1006450088828C83E709F0A3DFFA8032E309F60894 ++:10065500DFFA8078E309F208DFFA807088828C83FC ++:10066500E309F0A3DFFA806489828A83E0A3F608B0 ++:10067500DFFA805889828A83E0A3F208DFFA804C8A ++:1006850080D280FA80C680D4806980F28033801061 ++:1006950080A680EA809A80A880DA80E280CA8033CA ++:1006A50089828A83ECFAE493A3C8C582C8CCC58342 ++:1006B500CCF0A3C8C582C8CCC583CCDFE9DEE78012 ++:1006C5000D89828A83E493A3F608DFF9ECFAA9F091 ++:1006D500EDFB2289828A83ECFAE0A3C8C582C8CCE7 ++:1006E500C583CCF0A3C8C582C8CCC583CCDFEADE00 ++:1006F500E880DB89828A83E493A3F208DFF980CC62 ++:1007050088F0EF60010E4E60C388F0ED2402B4045A ++:100715000050B9F582EB2402B4040050AF23234501 ++:060725008223900685739B ++:10072B00BB010689828A83E0225002E722BBFE02CC ++:09073B00E32289828A83E49322FF ++:10074400BB010CE58229F582E5833AF583E022506A ++:1007540006E92582F8E622BBFE06E92582F8E222B4 ++:0D076400E58229F582E5833AF583E49322CE ++:10077100BB010689828A83F0225002F722BBFE0167 ++:02078100F32261 ++:10078300F8BB010DE58229F582E5833AF583E8F0AC ++:10079300225006E92582C8F622BBFE05E92582C858 ++:0207A300F22240 ++:1007A500EF8DF0A4A8F0CF8CF0A428CE8DF0A42E68 ++:0207B500FE2222 ++:1007B700C2D5EC30E709B2D5E4C39DFDE49CFCEE5D ++:1007C70030E715B2D5E4C39FFFE49EFE12087FC34E ++:1007D700E49DFDE49CFC800312087F30D507C3E449 ++:0607E7009FFFE49EFE22CC ++:1007ED00E8600FECC313FCED13FDEE13FEEF13FFEA ++:0307FD00D8F1220E ++:10080000E8600FEFC333FFEE33FEED33FDEC33FC56 ++:03081000D8F122FA ++:10081300BB010789828A830208E05005E9F80208D0 ++:10082300D4BBFE05E9F80208EC89828A830208F842 ++:10083300BB010789828A8302084D5005E9F8020942 ++:0A08430008BBFE05E9F802091422C3 ++:0C084D00ECF0A3EDF0A3EEF0A3EFF0221E ++:10085900D083D082F8E4937012740193700DA3A32E ++:1008690093F8740193F5828883E473740293686042 ++:06087900EFA3A3A380DF42 ++:1016B400020CDFE493A3F8E493A34003F68001F261 ++:1016C40008DFF48029E493A3F85407240CC8C33337 ++:1016D400C4540F4420C8834004F456800146F6DF06 ++:1016E400E4800B01020408102040809011F5E47E90 ++:1016F400019360BCA3FF543F30E509541FFEE493FB ++:10170400A360010ECF54C025E060A840B8E493A3C1 ++:10171400FAE493A3F8E493A3C8C582C8CAC583CAEC ++:10172400F0A3C8C582C8CAC583CADFE9DEE780BEA4 ++:0112AF00003E ++:10087F00BC000BBE0029EF8DF084FFADF022E4CC5D ++:10088F00F875F008EF2FFFEE33FEEC33FCEE9DEC26 ++:10089F00984005FCEE9DFE0FD5F0E9E4CEFD22ED6C ++:1008AF00F8F5F0EE8420D21CFEADF075F008EF2FB6 ++:1008BF00FFED33FD4007985006D5F0F222C398FDA7 ++:0508CF000FD5F0EA2244 ++:0C08D400E6FC08E6FD08E6FE08E6FF2250 ++:0C08E000E0FCA3E0FDA3E0FEA3E0FF228B ++:0C08EC00E2FC08E2FD08E2FE08E2FF2248 ++:1008F800E493FC740193FD740293FE740393FF2246 ++:0C090800ECF608EDF608EEF608EFF6221B ++:0C091400ECF208EDF208EEF208EFF2221F ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_RECOV.hex linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_RECOV.hex +--- linux-source-4.19/drivers/dahdi/xpp/firmwares/USB_RECOV.hex 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/firmwares/USB_RECOV.hex 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,421 @@ ++# ++# $Id: USB_RECOV.hex 9760 2011-09-05 12:33:27Z dima $ ++# ++:03004300021600A2 ++:0300530002160092 ++:10160000021580000215C6000215B00002159800F0 ++:081610000213F20002137B003B ++:100A00001201000200000040AAAAAAAAAAAA010292 ++:100A100003010A060002000000400100090237003D ++:100A2000020100C0000904000002FFFFFF040705E7 ++:100A3000020200020007058602000200090401000C ++:100A400002FFFFFF050705040200020007058802F8 ++:100A5000000200001201000200000040E4E4511115 ++:100A60000000010203010A0600020000004001002C ++:100A700009023700020100C0320904000002FFFF32 ++:100A8000FF0407050202400000070586024000003F ++:100A90000904010002FFFFFF0507050402400000F2 ++:100AA000070588024000000604001600140012002A ++:100AB0000A00260004030904160358006F007200A0 ++:100AC00063006F006D0020004C00540044001403CC ++:100AD00041007300740072006900620061006E00E2 ++:100AE0006B001203530065007200690061006C0026 ++:100AF0004E006F000A0346005000470041002603E5 ++:100B00004D0061006E00610067006D0065006E00C1 ++:100B10007400500072006F00630065007300730082 ++:060B20006F0072000000EE ++:08164300584F52434F4D2000A7 ++:100E650041E0B20042E0AD0000021BE0810218E063 ++:100E75007543E0AF0000004CE036393734364D207D ++:060E8500202020202000C7 ++:101517008B2A8A2B892CE52F152FAE2E7002152EBC ++:101527004E6014AB2A052CE52CAA2B7002052B1450 ++:08153700F9ED12019280DF22A0 ++:1013B8008B328A338934E5391539AE3870021538DD ++:1013C8004E6026AB350537E537AA36700205361468 ++:1013D800F912014CFFAB320534E534AA337002052B ++:0A13E8003314F9EF12019280CD22B8 ++:1011FD008C2A8D2BAA06A9077535018A3689377574 ++:10120D00380075391C7B017AE079481213B890E0EB ++:10121D0060E0FCA3E0FDA3E0FEA3E064D1FFEE647B ++:10122D008DFEED644CFDEC6449FC90E06012026EA5 ++:10123D007EE07F487D1C7C00120CFF7EE07F487BAA ++:10124D001C7A00AD2BAC2A120DB37D1C7C00AF2B8C ++:10125D00AE2A120C387D1C7C00AF2BAE2A0214284E ++:08099F008E2A8F2B8C2C8D2D6C ++:1009A700C204121567BF5004D204803BE4F52EF54C ++:1009B7002FE52D252FF582E52C352EF583E0FFE574 ++:1009C7002B252FF582E52A352EF583E0B5070E0591 ++:1009D7002FE52F7002052E6410452E70D4E52F6485 ++:0909E70010452E7002D204A20496 ++:0109F00022E4 ++:020875008F32C0 ++:100877001215678F33E4F537F538AD38AC37120FFB ++:100887001474652538F582E434E0F583E534F00522 ++:1008970038E53870020537C39408E53764809480DB ++:1008A70040D8E532600490E065F090E065E0B4C0C0 ++:1008B70008753500753608800675351D7536367529 ++:1008C7003700753808C3E5389410E537648094809D ++:1008D7005023120F1074652538F582E434E0F58350 ++:1008E700E534F00538E538700205370536E536702A ++:1008F700D4053580D07534FF75351D7536197537B4 ++:1009070000753810C3E538942CE53764809480501F ++:1009170033E533B4510E7B007A007934AD36AC350C ++:10092700FF120F1C74652538F582E434E0F583E582 ++:1009370034F00538E538700205370536E53670C4FA ++:10094700053580C075351D75363EE4F534F537F548 ++:1009570038C3E5389406E53764809480502FE53333 ++:10096700B4510A90E065E0B4C203120F1074422537 ++:1009770038F582E434E0F583E534F00538E538707E ++:100987000205370536E53670C8053580C490E06541 ++:07099700E0B4C20374C0F0DC ++:01099E002236 ++:0A12D3008E2A8F2B8B2C8A2D892E7A ++:1012DD007E00E52B2DF533EE352AF5321215678F8D ++:1012ED002FE52F6451600BC3E52B9410E52A940074 ++:1012FD005035852A30852B31C3E5319533E5309551 ++:10130D00325024AB2CAA2DA92EAD31AC30AF2F12FB ++:10131D00117A0531E531700205307401252EF52E57 ++:07132D00E4352DF52D80D100 ++:011334002296 ++:020B26008F320C ++:100B28007F031214ECEF2402FFE43EA9077533019A ++:100B3800F534893578367C007D007BFF7A16794359 ++:100B48007E007F08120126E532600464017054E5D6 ++:100B58000C2408F582E4350BF58374B4F0E50C2415 ++:100B680009F582E4350BF5837404F0E50C240AF5E5 ++:100B780082E4350BF5837413F0E50C240BF582E45D ++:100B8800350BF5837486F0E50C240CF582E4350BFF ++:100B9800F583E4F0E50C240DF582E4350BF583E4E8 ++:100BA800F0806C90E066E0FFE50C2408F582E435FF ++:100BB8000BF583EFF090E067E0FFE50C2409F58280 ++:100BC800E4350BF583EFF090E068E0FFE50C240ACC ++:100BD800F582E4350BF583EFF090E069E0FFE50C72 ++:100BE800240BF582E4350BF583EFF090E06AE0FF23 ++:100BF800E50C240CF582E4350BF583EFF090E06BFF ++:100C0800E0FFE50C240DF582E4350BF583EFF0E405 ++:100C1800FF74362FF8E6FEAB33AA34A93575F00217 ++:0F0C2800EFA4F58285F083EE1201A40FBF08E25E ++:010C3700229A ++:10145E00E4F532E50C240BF582E4350BF583E0FE62 ++:10146E00E50C240AF582E4350BF583E0FDEDFF90E3 ++:10147E00E0ADEEF0A3EFF0D20412000390E680E0B0 ++:03148E0054F7F020 ++:011491002238 ++:10105A0090E600E054E74410F090E60174C0F09086 ++:10106A00E6107420F000000090E611F000000090F5 ++:10107A00E6047480F0000000740FF0000000E4F051 ++:10108A0000000090E6187410F0000000E490E619E1 ++:10109A00F000000090E61A7408F0000000E490E600 ++:1010AA001BF000000090E6497482F0000000F00096 ++:1010BA00000090E6247402F0000000E490E625F0B7 ++:1010CA0000000090E6957480F0000000F000000037 ++:1010DA0043AF017B017AE07914752E00752F06E47F ++:0410EA00FD021517D7 ++:1015DC007C007D181201C6EF1FAC0670011E4C700A ++:0215EC00F622E5 ++:1015670090E678E0541824F06008240870087F504B ++:0815770080067F518002E4FFB1 ++:01157F002249 ++:0C0F1000AD36AC357B007A007934AF338D ++:0C0F1C008F398C3A8D3B8B3C8A3D893E1E ++:100F2800E4F53FF540754103FDF542F543A2AF33C3 ++:100F3800F544E53924AF600D047012753F00754023 ++:100F4800017D018008753F00754002E4FDE53960C8 ++:100F580051E540453F604BE53A90E0AFF0E53BA3F3 ++:100F6800F074AF2DF582E434E0AD82FCAB40AF39CC ++:100F780012126D7542008F437F0A7E00121335E509 ++:100F880043454260107CE07D647B01AF39120FB5A8 ++:100F98007542008F4390E064E0AB3CAA3DA93E1245 ++:0C0FA8000192E54424FF92AFAE42AF433B ++:010FB400221A ++:0C117A008F348C358D368B378A388939DC ++:10118600E4F53AF53B753C03FDF53DF53EA2AF337C ++:10119600F53FE53424AF600D047012753A00753BD7 ++:1011A600027D018008753A00753B03E4FDE5346075 ++:1011B6003BE53B453A6035E53590E0AFF0E536A3D3 ++:1011C600F0AB37AA38A93912014C90E0B1F074AFF0 ++:1011D6002DF582E434E0AD82FCAB3BAF3412126DE8 ++:1011E600753D008F3E7F0A7E00121335E53F24FFD2 ++:0611F60092AFAE3DAF3EDA ++:0111FC0022D0 ++:10054300E4F52AF52BF52CF52DF52EF52FF530E5F1 ++:10055300AA5484600302071190E694E0FE90E695A6 ++:10056300E0FBEEF52DEBF52EC39405E52D9400404D ++:100573000790F404E0FD80027DFFED24F570030293 ++:10058300062524E6700302064F24E0700302062CBE ++:1005930024FE7003020649243960030206B3752A58 ++:1005A30000752B0590FC04748EF01215678F30E5EF ++:1005B3003064516019E53064506013752A00752B5F ++:1005C3000690FC047480F0A3740BF00206D6121597 ++:1005D300678F307B007A007931E4FDFC120F1CAF8A ++:1005E300311208757400252BF974FC352AFA7B0146 ++:1005F300C0038B357536E075376575380075392C52 ++:10060300D0031213B87400252BF58274FC352AF538 ++:1006130083E531F0742C252BF52BE4352AF52A02DA ++:1006230006D6E4F52AF52B801D1215678F307B0063 ++:100633007A007931E4FDFC120F1CAF311208757F8B ++:10064300C0120B26800012145E0206D6752A0075AE ++:100653002B0590FC0474A5F01215678F307B007A8C ++:10066300007931E4FDFC120F1C052BE52BAE2A703B ++:1006730002052A142400F58274FC3EF583E508F094 ++:10068300052BE52BAE2A7002052A142400F582748B ++:10069300FC3EF583E515F0052BE52BAE2A7002052C ++:1006A3002A142400F58274FC3EF583E531F080239F ++:1006B300752A00752B0690FC047480F0C3E52E9414 ++:1006C30005E52D94005006A37407F0800690FC0501 ++:1006D3007406F0E52B452A602CE52BFD90FC00F019 ++:1006E300E52AFFA3F090F402E090FC02F090F403FB ++:1006F300E090FC03F090E69CEFF000000090E69D94 ++:0E070300EDF000000090E6957480F00000001C ++:0107110022C5 ++:02004100D322C8 ++:0800460090E6BAE0F51DD3229B ++:1015EE0090E740E51DF0E490E68AF090E68B04F07B ++:0215FE00D322F6 ++:08163B0090E6BAE0F51AD32293 ++:1016180090E740E51AF0E490E68AF090E68B04F053 ++:02162800D322CB ++:10153F0090E6B9E0242F600D04701990E604E0FFE7 ++:10154F00430780800890E604E0FF53077F00000008 ++:07155F00EFF08002D322C36C ++:011566002262 ++:10158000C0E0C083C082D2015391EF90E65D740148 ++:08159000F0D082D083D0E032DC ++:1015B000C0E0C083C0825391EF90E65D7404F0D028 ++:0615C00082D083D0E0326E ++:1015C600C0E0C083C0825391EF90E65D7402F0D014 ++:0615D60082D083D0E03258 ++:1013F200C0E0C083C08285110D85120E850E8285E4 ++:101402000D83A37402F085090F850A108510828569 ++:101412000F83A37407F05391EF90E65D7410F0D040 ++:0614220082D083D0E0320D ++:10159800C0E0C083C082D2035391EF90E65D740827 ++:0815A800F0D082D083D0E032C4 ++:10137B00C0E0C083C08290E680E030E72085090D95 ++:10138B00850A0E850E82850D83A37402F085110FDD ++:10139B00851210851082850F83A37407F05391EF8C ++:0D13AB0090E65D7420F0D082D083D0E03257 ++:0E09F10000010202030304040505C0C2000059 ++:1007120078237C007D007BFF7A0979FB7E007F04D1 ++:10072200120126C203C200D202C20112105A750B74 ++:100732000A750C0075130A75141275090A750A1CDC ++:1007420075110A75127085110F85121075160A75CA ++:1007520017B41215678F217B007A007922E4FDFC21 ++:10076200120F1C852208E4F515F52774232527F8B6 ++:10077200E6FF605C1208757EE07F657CE07DB31267 ++:1007820011FD7EE07FB3AD1CAC1B12099F50387483 ++:10079200232527F8E6F515652260277B007A007984 ++:1007A200157D01E4FFFE1212D37B007A007922E468 ++:1007B200FDFCAF21120F1CE52265156013751501B2 ++:1007C200800E7515FF80090527E527C39404409B19 ++:1007D200E5157059FB7A0079227D01FCAF21120FD9 ++:1007E2001CE522752900F5287B007A0079227D021A ++:1007F2007C00AF21120F1CE5224229E52964E47036 ++:1008020004E52864E470267515C0FB7A0079157D2D ++:1008120001FFFE1212D37B007A007922E4FDFCAFC5 ++:1008220021120F1CE52265156003751501AF151223 ++:100832000B26D2E843D82090E668E04409F090E61F ++:100842005CE0443DF0E51564C06005E515B4C20303 ++:1008520012145ED2AF538EF8C203C2AF120543D256 ++:10086200AF30010512031BC2013003EEC2031214A2 ++:03087200C080E75C ++:0B00360090E50DE030E402C322D3226D ++:10031B0090E6B9E070030203E01470030204552465 ++:10032B00FE70030204D024FB70030203DA14700383 ++:10033B000203D41470030203C81470030203CE2407 ++:10034B0005600302052F120041400302053B90E6B6 ++:10035B00BBE024FE602714603E24FD60111460276F ++:10036B0024067056E50B90E6B3F0E50C80421200C4 ++:10037B00365044E51390E6B3F0E5148033E50D9069 ++:10038B00E6B3F0E50E802985110F851210E50F906D ++:10039B00E6B3F0E510801990E6BAE0FF1214ECAA70 ++:1003AB0006A9077B01EA494B600DEE90E6B3F0EF2F ++:1003BB0090E6B4F002053B02052A02052A12161834 ++:1003CB0002053B12163B02053B12004602053B128F ++:1003DB0015EE02053B90E6B8E0247F60151460191A ++:1003EB0024027063A200E43325E0FFA202E4334F42 ++:1003FB008041E490E740F0803F90E6BCE0547EFF04 ++:10040B007E00E0D394807C0040047D0180027D005F ++:10041B00EC4EFEED4F24F1F58274093EF583E49327 ++:10042B00FF3395E0FEEF24A1FFEE34E68F82F583D8 ++:10043B00E0540190E740F0E4A3F090E68AF090E6F8 ++:10044B008B7402F002053B02052A90E6B8E024FE0D ++:10045B0060162402600302053B90E6BAE0B4010586 ++:10046B00C20002053B02052A90E6BAE0705590E601 ++:10047B00BCE0547EFF7E00E0D394807C0040047D82 ++:10048B000180027D00EC4EFEED4F24F1F5827409E4 ++:10049B003EF583E493FF3395E0FEEF24A1FFEE34AA ++:1004AB00E68F82F583E054FEF090E6BCE0548013B7 ++:1004BB001313541FFFE0540F2F90E683F0E04420FA ++:1004CB00F0806D805A90E6B8E024FE60192402702B ++:1004DB004E90E6BAE0B40104D200805490E6BAE044 ++:1004EB006402604C803990E6BCE0547EFF7E00E0F5 ++:1004FB00D394807C0040047D0180027D00EC4EFE95 ++:10050B00ED4F24F1F58274093EF583E493FF3395A7 ++:10051B00E0FEEF24A1FFEE34E68F82F583800D9091 ++:10052B00E6A0800812153F500790E6A0E04401F0CA ++:07053B0090E6A0E04480F00F ++:010542002296 ++:0300330002004E7A ++:04004E0053D8EF3262 ++:100E8B006080E0CF292E43C9A2D87C013D3654A106 ++:100E9B00ECF0061362A705F3C0C7738C98932BD99C ++:100EAB00BC4C82CA1E9B573CFDD4E01667426F18A0 ++:100EBB008A17E512BE4EC4D6DA9EDE49A0FBF58E2C ++:100ECB00BB2FEE7AA968799115B2073F94C21089AE ++:100EDB000B225F21807F5D9A5A903227353ECCE7FB ++:100EEB00BFF79703FF1930B348A5B5D1D75E922A48 ++:100EFB00AC56AAC64FB838D296A47DB676FC6BE238 ++:040F0B009C7404F1DD ++:080CFF008C2C8D2DAB07AA0619 ++:100D0700E4F52EF52FC3E52F952DE52C6480F8E546 ++:100D17002E6480984003020DAEE52F25E0FFE52EF7 ++:100D270033FE74CF2FF58274E03EF583E0FF7E003B ++:100D3700AC2CAD2D1201D88C308D31E52F25E0FF7D ++:100D4700E52E33FE74D02FF58274E03EF583E0FF85 ++:100D57007E00AC2CAD2D1201D88C328D33E5316578 ++:100D6700337004E53065326030EB2531F582EA35C2 ++:100D770030F583E0F9EB2533F582EA3532F583E088 ++:100D8700FFEB2531F582EA3530F583EFF0EB2533BC ++:100D9700F582EA3532F583E9F0052FE52F60030286 ++:0B0DA7000D0C052E020D0C7E007F01DC ++:010DB200221E ++:0C0DB3008E2C8F2D8C2E8D2F8A308B31D2 ++:100DBF00E52D452C6006E52F452E7004E4FEFF223D ++:100DCF00E4F532F533C3E5339531E5306480F8E56A ++:100DDF0032648098507BE4F534F535E52F2533F5F3 ++:100DEF0082E52E3532F583E4F0C3E5359531E530F4 ++:100DFF006480F8E5346480985049E535253324CF75 ++:100E0F00F582E434E0F583E0FFE52D2535F582E545 ++:100E1F002C3534F583E0FEEF8EF0A4FFE52F25335C ++:100E2F00F582E52E3532F583E02FFFE52F2533F5DB ++:100E3F0082E52E3532F583EFF00535E53570AA05DD ++:100E4F003480A60533E5336003020DD40532020D5D ++:050E5F00D47E007F01BC ++:010E6400226B ++:1014920012014CFF900003120165120192900003A9 ++:1014A200EF1201A4900002120165FF9000011201E7 ++:0E14B200659000021201A4900001EF0201A457 ++:080C38008E2C8F2D8C2E8D2FC8 ++:100C4000E4F530F531E52FAE2E7802CEA2E713CED3 ++:100C500013D8F8FFC3E5319FEE6480F8E530648077 ++:100C6000984003020CFAE531AE307802C333CE333C ++:100C7000CED8F9252DFFEE352CFAA9077B018B3252 ++:100C8000F533893474D02531F582E434E0F583E01E ++:100C9000541FFFE48F38F537F536F535121492AB53 ++:100CA00032AA33A934120234C374209538F9F812E9 ++:100CB0000221C004C005C006C007A934120234A92D ++:100CC00038A80112020ED003D002D001D000EF4BA1 ++:100CD000FFEE4AFEED49FDEC48FCAB32AA33A934E5 ++:100CE000120254AB32AA33A9341214920531E53101 ++:0E0CF0006003020C450530020C457E007F01BA ++:010CFE0022D3 ++:10142800D3ED9410EC64809480402AED1D70011C6B ++:10143800142FF582EE3CF583E0FB547F24CFF58230 ++:10144800E434E0F583E0F9540F2FF582E43EF583A8 ++:05145800E06BF080CB09 ++:01145D00226C ++:1014C00090E682E030E004E020E60B90E682E03037 ++:1014D000E119E030E71590E680E04401F07F147EEA ++:0C14E0000012133590E680E054FEF0226C ++:1000030030040990E680E0440AF0800790E680E03F ++:100013004408F07FDC7E0512133590E65D74FFF033 ++:0F00230090E65FF05391EF90E680E054F7F02203 ++:101335008E458F4690E600E054187012E54624016C ++:10134500FFE43545C313F545EF13F546801590E6E3 ++:1013550000E05418FFBF100BE54625E0F546E545CE ++:1013650033F545E5461546AE45700215454E600513 ++:0613750012162A80EE2290 ++:060FB5008C458D46AE07DD ++:100FBB00EB70037F012290E678E020E6F990E6786B ++:100FCB007480F0EE25E0440190E679F090E678E04D ++:100FDB0030E0F990E678E020E26BE030E167BB01AE ++:100FEB000790E678E04420F090E679E0F5471BEBBC ++:100FFB00603090E678E030E0F990E678E020E2456A ++:10100B00BB010790E678E04420F090E679E0FF051D ++:10101B0046E546AC457002054514F5828C83EFF02E ++:10102B0080CC90E678E030E0F990E678E020E215AD ++:10103B0090E678E04440F090E679E085468285457D ++:0E104B0083F07F012290E678E04440F07F00C1 ++:011059002274 ++:10126D0090E678E020E6F990E6787480F0EF25E0DE ++:10127D0090E679F090E678E030E0F990E678E020BD ++:10128D00E23AE030E136EBD3940040260DEDAE04AA ++:10129D0070010C14F5828E83E090E679F01B90E6D8 ++:1012AD0078E030E0F990E678E020E210E020E1D639 ++:1012BD00800A90E678E04440F07F012290E678E0E5 ++:0512CD004440F07F0029 ++:0112D20022F9 ++:0214EC00A9074E ++:1014EE00AE16AF178F828E83A3E064037017AD0123 ++:1014FE0019ED7001228F828E83E07C002FFDEC3E71 ++:08150E00FEAF0580DFE4FEFFE3 ++:0115160022B2 ++:10162A007400F58690FDA57C05A3E582458370F9D3 ++:01163A00228D ++:030000000210EEFD ++:0C10EE00787FE4F6D8FD758147021135CB ++:10005600E709F608DFFA8046E709F208DFFA803E8C ++:1000660088828C83E709F0A3DFFA8032E309F60879 ++:10007600DFFA8078E309F208DFFA807088828C83E1 ++:10008600E309F0A3DFFA806489828A83E0A3F60895 ++:10009600DFFA805889828A83E0A3F208DFFA804C6F ++:1000A60080D280FA80C680D4806980F28033801046 ++:1000B60080A680EA809A80A880DA80E280CA8033AF ++:1000C60089828A83ECFAE493A3C8C582C8CCC58327 ++:1000D600CCF0A3C8C582C8CCC583CCDFE9DEE780F7 ++:1000E6000D89828A83E493A3F608DFF9ECFAA9F076 ++:1000F600EDFB2289828A83ECFAE0A3C8C582C8CCCC ++:10010600C583CCF0A3C8C582C8CCC583CCDFEADEE4 ++:10011600E880DB89828A83E493A3F208DFF980CC46 ++:1001260088F0EF60010E4E60C388F0ED2402B4043F ++:100136000050B9F582EB2402B4040050AF232345E6 ++:0601460082239000A67365 ++:10014C00BB010689828A83E0225002E722BBFE02B1 ++:09015C00E32289828A83E49322E4 ++:10016500BB010CE58229F582E5833AF583E022504F ++:1001750006E92582F8E622BBFE06E92582F8E22299 ++:0D018500E58229F582E5833AF583E49322B3 ++:10019200BB010689828A83F0225002F722BBFE014C ++:0201A200F32246 ++:1001A400F8BB010DE58229F582E5833AF583E8F091 ++:1001B400225006E92582C8F622BBFE05E92582C83D ++:0201C400F22225 ++:1001C600EF8DF0A4A8F0CF8CF0A428CE8DF0A42E4D ++:0201D600FE2207 ++:1001D800C2D5EC30E709B2D5E4C39DFDE49CFCEE42 ++:1001E80030E715B2D5E4C39FFFE49EFE12027AC33E ++:1001F800E49DFDE49CFC800312027A30D507C3E439 ++:060208009FFFE49EFE22B0 ++:10020E00E8600FECC313FCED13FDEE13FEEF13FFCE ++:03021E00D8F122F2 ++:10022100E8600FEFC333FFEE33FEED33FDEC33FC3B ++:03023100D8F122DF ++:10023400BB010789828A830202DB5005E9F80202C6 ++:10024400CFBBFE05E9F80202E789828A830202F342 ++:10025400BB010789828A8302026E5005E9F8020312 ++:0A02640003BBFE05E9F802030F22B8 ++:0C026E00ECF0A3EDF0A3EEF0A3EFF02203 ++:1010FA00020712E493A3F8E493A34003F68001F2F3 ++:10110A0008DFF48029E493A3F85407240CC8C333F6 ++:10111A00C4540F4420C8834004F456800146F6DFC5 ++:10112A00E4800B0102040810204080900E65E47EE2 ++:10113A00019360BCA3FF543F30E509541FFEE493BA ++:10114A00A360010ECF54C025E060A840B8E493A381 ++:10115A00FAE493A3F8E493A3C8C582C8CAC583CAAC ++:10116A00F0A3C8C582C8CAC583CADFE9DEE780BE64 ++:010F0F0000E1 ++:10027A00BC000BBE0029EF8DF084FFADF022E4CC68 ++:10028A00F875F008EF2FFFEE33FEEC33FCEE9DEC31 ++:10029A00984005FCEE9DFE0FD5F0E9E4CEFD22ED77 ++:1002AA00F8F5F0EE8420D21CFEADF075F008EF2FC1 ++:1002BA00FFED33FD4007985006D5F0F222C398FDB2 ++:0502CA000FD5F0EA224F ++:0C02CF00E6FC08E6FD08E6FE08E6FF225B ++:0C02DB00E0FCA3E0FDA3E0FEA3E0FF2296 ++:0C02E700E2FC08E2FD08E2FE08E2FF2253 ++:1002F300E493FC740193FD740293FE740393FF2251 ++:0C030300ECF608EDF608EEF608EFF62226 ++:0C030F00ECF208EDF208EEF208EFF2222A ++:00000001FF +diff -Nru linux-source-4.19/drivers/dahdi/xpp/init_card_1_30 linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_1_30 +--- linux-source-4.19/drivers/dahdi/xpp/init_card_1_30 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_1_30 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,617 @@ ++#! /usr/bin/perl -w ++use strict; ++ ++# Make warnings fatal ++local $SIG{__WARN__} = sub { die @_ }; ++ ++# ++# Written by Oron Peled ++# Copyright (C) 2006, Xorcom ++# ++# 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 as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# See the file LICENSE in the top level of this tarball. ++# ++ ++# ++# $Id$ ++# ++# Data format: ++# - A comment start with ';' or '#' until the end of line ++# - Blank lines are ignored ++# - Fields are whitespace separated (spaces or tabs) ++# ++# The fields are (in command line order): ++# 1. SLIC select in decimal (range 0-7). ++# * is a special value which means ALL SLICS (only some registers ++# accept settings for ALL SLICS). ++# 2. Command word: ++# - RD Read Direct register. ++# - RS Read Sub-register. ++# - WD Write Direct register. ++# - WS Write Sub-register. ++# 3. Register number in hexadecimal. ++# 4. Low data byte in hexadecimal. (for WD and WS commands). ++# 5. High data byte in hexadecimal. (for WS command only). ++# ++# ++ ++package main; ++use File::Basename; ++use Getopt::Std; ++ ++my $program = basename("$0"); ++my $init_dir = dirname("$0"); ++BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); } ++use XppConfig $init_dir; ++my $unit_id; ++my %opts; ++my $eeprom_release_201 = 0; ++ ++getopts('o:', \%opts); ++ ++my %settings; ++$settings{debug} = 0; ++$settings{fxs_skip_calib} = 0; ++my $chipregs; ++my $ring_registers; ++ ++sub logit { ++ print STDERR "$unit_id: @_\n"; ++} ++ ++sub debug { ++ logit @_ if $settings{debug}; ++} ++ ++# Arrange for error logging ++if (-t STDERR) { ++ $unit_id = 'Interactive'; ++ debug "Interactive startup"; ++} else { ++ $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}"; ++ open (STDERR, "| logger -t $program -p kern.info") || die; ++ debug "Non Interactive startup"; ++ foreach my $k (qw( ++ XBUS_NAME ++ XBUS_NUMBER ++ XBUS_MODEL_STRING ++ UNIT_NUMBER ++ UNIT_TYPE ++ UNIT_SUBUNITS ++ UNIT_SUBUNITS_DIR ++ XBUS_REVISION ++ XBUS_CONNECTOR ++ XBUS_LABEL)) { ++ unless(defined $ENV{$k}) { ++ logit "Missing ENV{$k}\n"; ++ die; ++ } ++ } ++ logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'"; ++ if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/20.}) { ++ $eeprom_release_201 = 1; ++ } ++ $chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}; ++ if(! -f $chipregs) { ++ my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER}); ++ $chipregs = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs"; ++ logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc" ++ if -f $chipregs; ++ } ++ $ring_registers = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/fxs_ring_registers", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}; ++ logit "OLD DRIVER: missing '$ring_registers' -- fallback to hard-coded defaults" ++ unless -f $ring_registers; ++} ++ ++sub set_output() { ++ my $output; ++ ++ if($opts{o}) { ++ $output = $opts{o}; ++ } else { ++ # No subunits in FXS (everything is subunit 0) ++ $output = $chipregs; ++ } ++ open(REG, ">$output") || die "Failed to open '$output': $!\n"; ++ my $oldfh = select REG; ++ main::logit "# Setting output" if $opts{o}; ++ return $oldfh; ++} ++ ++sub mysleep($) { ++ my $timeout = shift; ++ select(undef,undef,undef,$timeout); ++} ++ ++package FXS; ++ ++sub gen { ++ my $fmt = shift; ++ $| = 1; ++ printf "$fmt\n", @_; ++} ++ ++my @SlicNums = (0 .. 7); ++ ++sub write_to_slic_file($) { ++ my $write_str = shift; ++ ++ open(SLICS,">$chipregs") or ++ die("Failed writing to chipregs file $chipregs"); ++ print SLICS $write_str; ++ close(SLICS) or die "Failed writing '$write_str' to '$chipregs': $!"; ++ main::mysleep(0.001); ++ ++} ++ ++sub write_to_ring_register($) { ++ my $write_str = shift; ++ ++ open(SLICS,">$ring_registers") or ++ die("Failed writing to ring_registers file $ring_registers"); ++ print SLICS $write_str; ++ close(SLICS) or die "Failed writing '$write_str' to '$ring_registers': $!"; ++ main::mysleep(0.001); ++} ++ ++sub read_reg($$$) { ++ my $read_slic = shift; ++ my $read_reg = shift; ++ my $direct = shift; ++ ++ write_to_slic_file( ++ sprintf("%s R%s %02X", $read_slic, $direct, $read_reg)); ++ my $retries = 10; ++ my @reply; ++ # If the command queue is long, we may need to wait... ++WAIT_RESULTS: ++ { ++ my @results; ++ ++ # The time to sleep is a tradeoff: ++ # - Too long is a waste of time. ++ # - Too short will cause many retries, wastes time. ++ # So the current value (after trial and error) is... ++ main::mysleep(0.013); ++ open(SLICS,$chipregs) or ++ die("Failed reading from chipregs file $chipregs"); ++ while(){ ++ s/#.*//; ++ next unless /\S/; ++ @results = /^\s*(\d+)\s+[RW][DI]\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/; ++ if(@results != 4) { ++ main::logit "Failed reading from '$chipregs' ($read_slic,$read_reg,$direct)"; ++ die; ++ } ++ } ++ close(SLICS); ++ my $reg = hex($results[1]); ++ if($results[0] ne $read_slic || $reg ne $read_reg) { ++ # We read obsolete values, need to wait some more ++ if(--$retries) { ++ main::debug "$read_slic RD $read_reg -- retry ($results[0], $reg)"; ++ redo WAIT_RESULTS; ++ } else { ++ main::logit "Failed: $read_slic RD $read_reg returned $results[0], $reg"; ++ die; ++ } ++ } ++ # Good. ++ @reply = (hex($results[2]), hex($results[3])); ++ ++ } ++ if ($direct eq 'S') { ++ return @reply; ++ } else { ++ return $reply[0]; ++ } ++} ++ ++# TODO: rearange arguments ++sub write_reg{#($$$$$) { ++ my $read_slic = shift; ++ my $read_reg = shift; ++ my $direct = shift; ++ my $reg_val_low = shift; ++ my $reg_val_hi = shift; ++ ++ my $str = sprintf "%s W%s %02X %02X", ++ $read_slic, $direct, $read_reg, $reg_val_low; ++ if ($direct eq 'S') { ++ $str .= sprintf " %02X", $reg_val_hi; ++ } ++ write_to_slic_file($str); ++} ++ ++sub log_calib_params() { ++ for my $i (100 .. 107) { ++ my $line="Calib Reg $i: "; ++ for my $slic (@SlicNums) { ++ $line .= " ".read_reg($slic, $i, 'D'); ++ } ++ main::debug($line); ++ } ++} ++ ++sub init_indirect_registers() { ++ return write_to_slic_file("# ++* WS 1E 00 C2 55 ++* WS 1E 01 E6 51 ++* WS 1E 02 85 4B ++* WS 1E 03 37 49 ++ ++* WS 1E 04 33 33 ++* WS 1E 05 02 02 ++* WS 1E 06 02 02 ++* WS 1E 07 98 01 ++ ++* WS 1E 08 98 01 ++* WS 1E 09 11 06 ++* WS 1E 0A 02 02 ++* WS 1E 0B E5 00 ++ ++* WS 1E 0C 1C 0A ++* WS 1E 0D 30 7B ++* WS 1E 0E 63 00 ++* WS 1E 0F 00 00 ++ ++* WS 1E 10 70 78 ++* WS 1E 11 7D 00 ++* WS 1E 12 00 00 ++* WS 1E 13 00 00 ++ ++* WS 1E 14 FD 7E ++* WS 1E 15 77 01 ++* WS 1E 16 00 00 ++* WS 1E 17 00 20 ++ ++* WS 1E 18 00 20 ++* WS 1E 19 00 00 ++* WS 1E 1A 00 20 ++* WS 1E 1B 00 40 ++ ++* WS 1E 1C 00 10 ++* WS 1E 1D 00 36 ++* WS 1E 1E 00 10 ++* WS 1E 1F 00 02 ++ ++* WS 1E 20 C0 07 ++* WS 1E 21 6F 37 ++* WS 1E 22 80 1B ++* WS 1E 23 00 80 ++ ++* WS 1E 24 00 08 ++* WS 1E 25 00 08 ++* WS 1E 26 00 08 ++* WS 1E 27 00 08 ++ ++* WS 1E 28 00 00 ++* WS 1E 2B 00 08 # LCRTL = 5.08 mA ++ ++* WS 1E 63 DA 00 ++* WS 1E 64 60 6B ++* WS 1E 65 74 00 ++* WS 1E 66 C0 79 ++ ++* WS 1E 67 20 11 ++* WS 1E 68 E0 3B ++#"); ++} ++ ++sub init_early_direct_regs() { ++ my $lbv = ($eeprom_release_201) ? "20" : "10"; ++ my $vcm = ($eeprom_release_201) ? "02" : "03"; ++ ++ return write_to_slic_file("# ++* WD 08 00 # Audio Path Loopback Control ++* WD 6C 01 ++* WD 4A 34 # High Battery Voltage ++* WD 4B $lbv # Low Battery Voltage ++* WD 49 $vcm # Common Mode Voltage (VCM) ++* WD 40 00 # Line Feed Control ++#") ++} ++ ++my @FilterParams = (); ++ ++sub save_indirect_filter_params() { ++ for my $slic (@SlicNums) { ++ for my $reg (35 .. 39) { ++ $FilterParams[$slic][$reg] = ++ [read_reg($slic, $reg, 'S')]; ++ write_reg($slic, $reg, 'S', 0, 0x80); ++ } ++ } ++ ++} ++ ++sub restore_indirect_filter_params() { ++ for my $slic (@SlicNums) { ++ for my $reg (35 .. 39) { ++ write_reg($slic, $reg, 'S', ++ @{$FilterParams[$slic][$reg]}); ++ } ++ } ++} ++ ++my $ManualCalibrationSleepTime = 0.04; # 40ms ++ ++sub manual_calibrate_loop($$) { ++ my $write_reg = shift; ++ my $read_reg = shift; ++ my @curr_slics = @SlicNums; ++ ++ # initialize counters ++ my @slic_counters = map { 0x1F } @curr_slics; ++ ++ # wait until all slics have finished calibration, or for timeout ++ while (@curr_slics) { ++ my $debug_calib_str = "ManualCalib:: "; ++ my @next_slics; ++ ++ for my $slic (@curr_slics) { ++ write_reg($slic,$write_reg,'D',$slic_counters[$slic]); ++ } ++ main::mysleep $ManualCalibrationSleepTime; ++ for my $slic (@curr_slics) { ++ my $value = read_reg($slic, $read_reg, 'D'); ++ $debug_calib_str .= sprintf " [%d:%d:%X]", ++ $slic, $slic_counters[$slic], $value; ++ next if $value == 0; # This one is calibrated. ++ if ($slic_counters[$slic] > 0) { ++ $slic_counters[$slic]--; ++ push(@next_slics, $slic); ++ } else { ++ main::logit("ERROR: SLIC $slic reached 0 during manual calibration"); ++ } ++ } ++ @curr_slics = @next_slics; ++ main::debug($debug_calib_str); ++ } ++ main::debug("No more slics to calibrate"); ++} ++ ++sub manual_calibrate() { ++ manual_calibrate_loop(98, 88); ++ manual_calibrate_loop(99, 89); ++} ++ ++sub auto_calibrate($$) { ++ my $calib_96 = shift; ++ my $calib_97 = shift; ++ ++ #log_calib_params(); ++ # start calibration: ++ for my $slic(@SlicNums) { ++ write_to_slic_file( ++ sprintf ++ "$slic WD 61 %02X\n". ++ "$slic WD 60 %02X\n". ++ "", $calib_97, $calib_96 ++ ++ ); ++ } ++ ++ # wait until all slics have finished calibration, or for timeout ++ # time periods in seconds: ++ my $sleep_time = 0.001; ++ my $timeout_time = 0.600; # Maximum from the spec ++ my @curr_slics = @SlicNums; ++ my $sleep_cnt = 0; ++CALIB_LOOP: ++ while(1) { ++ main::mysleep($sleep_time); ++ my @next_slics; ++ for my $slic (@curr_slics) { ++ main::debug("checking slic $slic"); ++ my $val = read_reg($slic, 96, 'D'); ++ push(@next_slics, $slic) if $val != 0; ++ } ++ @curr_slics = @next_slics; ++ last unless @curr_slics; ++ if ($sleep_cnt * $sleep_time > $timeout_time) { ++ main::logit("Auto Calibration: Exiting on timeout: $timeout_time."); ++ last CALIB_LOOP; ++ } ++ main::debug("auto_calibrate not done yet($sleep_cnt): @curr_slics"); ++ $sleep_cnt++; ++ } ++ #log_calib_params(); ++} ++ ++sub calibrate_slics() { ++ main::debug "Calibrating '$0'"; ++ auto_calibrate(0x40, 0x1E); ++ main::debug "after auto_calibrate"; ++ manual_calibrate(); ++ main::debug "after manul_calibrate"; ++ auto_calibrate(0x40, 0x01); ++ main::debug "after auto_calibrate 2"; ++ main::debug "Continue '$0'"; ++} ++ ++sub read_defaults() { ++ if(XppConfig::read_config(\%settings)) { ++ main::logit "Defaults from $settings{xppconf}"; ++ } else { ++ main::logit "No defaults file, use hard-coded defaults."; ++ } ++} ++ ++# Try to identify which slics are valid ++sub check_slics() { ++ my @slics; ++ foreach my $slic (0 .. 7) { ++ my $value = read_reg($slic, 0, 'D'); ++ push(@slics, $slic) if $value != 0xFF; ++ } ++ main::logit "Found " . scalar(@slics) . " SLICS (@slics)"; ++ return @slics; ++} ++ ++sub overwrite_ring_registers() { ++ write_to_ring_register("NEON 0x33 0x12"); ++} ++ ++package main; ++ ++main::debug "Starting '$0'"; ++ ++FXS::read_defaults; ++@SlicNums = FXS::check_slics; ++main::debug "before init_indirect_registers"; ++FXS::init_indirect_registers(); ++main::debug "after init_indirect_registers"; ++FXS::init_early_direct_regs(); ++main::debug "after init_early_direct_regs"; ++if($settings{fxs_skip_calib}) { ++ main::logit "==== WARNING: SKIPPED SLIC CALIBRATION ====="; ++} else { ++ FXS::calibrate_slics; ++} ++set_output; ++while() { ++ chomp; ++ s/[#;].*$//; # remove comments ++ s/^\s+//; # trim whitespace ++ s/\s+$//; # trim whitespace ++ s/\t+/ /g; # replace tabs with spaces (for logs) ++ next unless /\S/; # Skip empty lines ++ main::debug "writing: '$_'"; ++ print "$_\n"; ++} ++close REG; ++FXS::overwrite_ring_registers(); ++ ++main::debug "Ending '$0'"; ++close STDERR; ++exit 0; ++ ++# ----------------------------------==== 8-channel FXS unit initialization ===----------------------------------------- ++ ++__DATA__ ++ ++# Flush out energy accumulators ++* WS 1E 58 00 00 ++* WS 1E 59 00 00 ++* WS 1E 5A 00 00 ++* WS 1E 5B 00 00 ++* WS 1E 5C 00 00 ++* WS 1E 5D 00 00 ++* WS 1E 5E 00 00 ++* WS 1E 5F 00 00 ++ ++* WS 1E 61 00 00 ++ ++* WS 1E C1 00 00 ++* WS 1E C2 00 00 ++* WS 1E C3 00 00 ++* WS 1E C4 00 00 ++* WS 1E C5 00 00 ++* WS 1E C6 00 00 ++* WS 1E C7 00 00 ++* WS 1E C8 00 00 ++* WS 1E C9 00 00 ++* WS 1E CA 00 00 ++* WS 1E CB 00 00 ++* WS 1E CC 00 00 ++* WS 1E CD 00 00 ++* WS 1E CE 00 00 ++* WS 1E CF 00 00 ++* WS 1E D0 00 00 ++* WS 1E D1 00 00 ++* WS 1E D2 00 00 ++* WS 1E D3 00 00 ++ ++# Clear and disable interrupts ++* WD 12 FF ++* WD 13 FF ++* WD 14 FF ++* WD 15 00 ++* WD 16 00 ++* WD 17 00 ++ ++## Mode(8-bit,u-Law,1 PCLK ) ++* WD 01 08 # Disable PCM transfers ++ ++# Setting of SLICs offsets ++# New card initialization ++ ++* WD 03 00 ++* WD 05 00 ++ ++0 WD 02 00 ++0 WD 04 00 ++0 WD 01 28 # Enable PCM transfers ++1 WD 02 08 ++1 WD 04 08 ++1 WD 01 28 ++2 WD 02 10 ++2 WD 04 10 ++2 WD 01 28 ++3 WD 02 18 ++3 WD 04 18 ++3 WD 01 28 ++4 WD 02 20 ++4 WD 04 20 ++4 WD 01 28 ++5 WD 02 28 ++5 WD 04 28 ++5 WD 01 28 ++6 WD 02 30 ++6 WD 04 30 ++6 WD 01 28 ++7 WD 02 38 ++7 WD 04 38 ++7 WD 01 28 ++ ++# Audio path. (also initialize 0A and 0B here if necessary) ++* WD 08 00 ++* WD 09 00 ++* WD 0A 08 ++* WD 0B 33 ++ ++#------ Metering tone ++* WD 2C 00 # Timer dL ++* WD 2D 03 # Timer dH ++* WS 1E 17 61 15 # Amplitue Ramp-up ++* WS 1E 18 61 15 # Max Amplitude ++* WS 1E 19 FB 30 # Frequency ++ ++# Ring regs are set by driver ++ ++# Automatic/Manual Control: defaults but: ++# Cancel AOPN - Power Alarm ++# Cancel ABAT - Battery Feed Automatic Select ++* WD 43 16 ++ ++# Loop Closure Debounce Interval ++* WD 45 0A ++ ++# Ring Detect Debounce Interval ++* WD 46 47 ++ ++# Battery Feed Control: Battery low (DCSW low) ++* WD 42 00 ++ ++# Loop Current Limit ++* WD 47 00 ++ ++# On-Hook Line Voltage (VOC) ++* WD 48 20 ++ ++* WS 1E 23 00 80 ++* WS 1E 24 20 03 ++* WS 1E 25 8C 00 ++* WS 1E 26 00 00 ++* WS 1E 27 10 00 ++ ++* WD 0E 00 +diff -Nru linux-source-4.19/drivers/dahdi/xpp/init_card_2_30 linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_2_30 +--- linux-source-4.19/drivers/dahdi/xpp/init_card_2_30 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_2_30 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,467 @@ ++#! /usr/bin/perl -w ++use strict; ++ ++# Make warnings fatal ++local $SIG{__WARN__} = sub { die @_ }; ++ ++# ++# Written by Oron Peled ++# Copyright (C) 2006, Xorcom ++# ++# 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 as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# See the file LICENSE in the top level of this tarball. ++# ++ ++# ++# $Id$ ++# ++# Data format: ++# - A comment start with ';' or '#' until the end of line ++# - Blank lines are ignored ++# - Fields are whitespace separated (spaces or tabs) ++# ++# The fields are (in command line order): ++# 1. SLIC select in decimal (range 0-7). ++# * is a special value which means ALL SLICS (only some registers ++# accept settings for ALL SLICS). ++# 2. Command word: ++# - RD Read Direct register. ++# - RS Read Sub-register. ++# - WD Write Direct register. ++# - WS Write Sub-register. ++# 3. Register number in hexadecimal. ++# 4. Low data byte in hexadecimal. (for WD and WS commands). ++# 5. High data byte in hexadecimal. (for WS command only). ++# ++# ++ ++package main; ++use File::Basename; ++use Getopt::Std; ++ ++my $program = basename("$0"); ++my $init_dir = dirname("$0"); ++BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); } ++use XppConfig $init_dir; ++my $unit_id; ++my %opts; ++$Getopt::Std::STANDARD_HELP_VERSION = 1; ++our $VERSION = '$Id$'; ++ ++sub usage() { ++ print <<"EOF"; ++$0 [-L] [-v verify_file] [-o output_file] ++ -L: List all available opermodes and exit ++ -v: verify opermodes and exit ++ -o: simulate: output to file instead of astribank ++EOF ++ exit 1; ++} ++ ++sub HELP_MESSAGE() { ++ eval {usage}; ++ return 0; ++} ++ ++getopts('Lo:v:', \%opts) || usage; ++ ++my %settings; ++$settings{debug} = 0; ++my $chipregs; ++ ++sub logit { ++ print STDERR "$unit_id: @_\n"; ++} ++ ++sub debug { ++ logit @_ if $settings{debug}; ++} ++ ++# Arrange for error logging ++if (-t STDERR || $opts{v}) { ++ $unit_id = 'Interactive'; ++ debug "Interactive startup"; ++} else { ++ $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}"; ++ open (STDERR, "| logger -t $program -p kern.info") || die; ++ debug "Non Interactive startup"; ++ foreach my $k (qw( ++ XBUS_NAME ++ XBUS_NUMBER ++ UNIT_NUMBER ++ UNIT_TYPE ++ UNIT_SUBUNITS ++ UNIT_SUBUNITS_DIR ++ XBUS_REVISION ++ XBUS_CONNECTOR ++ XBUS_LABEL)) { ++ unless(defined $ENV{$k}) { ++ logit "Missing ENV{$k}\n"; ++ die; ++ } ++ } ++ $chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}; ++ if(! -f $chipregs) { ++ my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER}); ++ $chipregs = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs"; ++ logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc" ++ if -f $chipregs; ++ } ++} ++ ++sub set_output() { ++ my $output; ++ ++ if($opts{o}) { ++ $output = $opts{o}; ++ } else { ++ # No subunits in FXS (everything is subunit 0) ++ $output = $chipregs; ++ } ++ open(REG, ">$output") || die "Failed to open '$output': $!\n"; ++ my $oldfh = select REG; ++ main::logit "# Setting output" if $opts{o}; ++ return $oldfh; ++} ++ ++package FXO; ++ ++sub gen { ++ my $fmt = shift; ++ $| = 1; ++ printf "$fmt\n", @_; ++} ++ ++my $OPERMODE = 'FCC'; ++ ++sub turn_off_leds() { ++ # Turning off red LEDs ++ # Warning: do not send WD 31 20 A0 ! ++ foreach my $i (0..7) { ++ FXO::gen "$i WD 20 A0"; ++ } ++} ++ ++# This data is manually taken from utils/init_fxo_modes which is generated ++# during build. ++# Running this script with a single 'verify' argument, during build, ++# compare this data to a (possibly updated) utils/init_fxo_modes file. ++my $OPERMODE_DATA = " ++FCC reg16=01 reg26=C0 reg30=00 reg31=20 ++TBR21 reg16=00 reg26=C2 reg30=02 reg31=20 ring_osc=7E6C ring_x=023A ++ARGENTINA reg16=00 reg26=C0 reg30=00 reg31=20 ++AUSTRALIA reg16=40 reg26=30 reg30=03 reg31=20 ++AUSTRIA reg16=00 reg26=C2 reg30=03 reg31=28 ++BAHRAIN reg16=00 reg26=C2 reg30=02 reg31=20 ++BELGIUM reg16=00 reg26=C2 reg30=02 reg31=28 ++BRAZIL reg16=00 reg26=30 reg30=00 reg31=20 ++BULGARIA reg16=00 reg26=C2 reg30=03 reg31=20 ++CANADA reg16=00 reg26=C0 reg30=00 reg31=20 ++CHILE reg16=00 reg26=C0 reg30=00 reg31=20 ++CHINA reg16=00 reg26=30 reg30=0F reg31=20 ++COLOMBIA reg16=00 reg26=C0 reg30=00 reg31=20 ++CROATIA reg16=00 reg26=C2 reg30=02 reg31=20 ++CYPRUS reg16=00 reg26=C2 reg30=02 reg31=20 ++CZECH reg16=00 reg26=C2 reg30=02 reg31=20 ++DENMARK reg16=00 reg26=C2 reg30=02 reg31=28 ++ECUADOR reg16=00 reg26=C0 reg30=00 reg31=20 ++EGYPT reg16=00 reg26=30 reg30=00 reg31=20 ++ELSALVADOR reg16=00 reg26=C0 reg30=00 reg31=20 ++FINLAND reg16=00 reg26=C2 reg30=02 reg31=28 ++FRANCE reg16=00 reg26=C2 reg30=02 reg31=28 ++GERMANY reg16=00 reg26=C2 reg30=03 reg31=28 ++GREECE reg16=00 reg26=C2 reg30=02 reg31=28 ++GUAM reg16=00 reg26=C0 reg30=00 reg31=20 ++HONGKONG reg16=00 reg26=C0 reg30=00 reg31=20 ++HUNGARY reg16=00 reg26=C0 reg30=00 reg31=20 ++ICELAND reg16=00 reg26=C2 reg30=02 reg31=28 ++INDIA reg16=00 reg26=C0 reg30=04 reg31=20 ++INDONESIA reg16=00 reg26=C0 reg30=00 reg31=20 ++IRELAND reg16=00 reg26=C2 reg30=02 reg31=28 ++ISRAEL reg16=00 reg26=C2 reg30=02 reg31=20 ++ITALY reg16=00 reg26=C2 reg30=02 reg31=28 ++JAPAN reg16=00 reg26=30 reg30=00 reg31=20 ++JORDAN reg16=00 reg26=30 reg30=00 reg31=20 ++KAZAKHSTAN reg16=00 reg26=C0 reg30=00 reg31=20 ++KUWAIT reg16=00 reg26=C0 reg30=00 reg31=20 ++LATVIA reg16=00 reg26=C2 reg30=02 reg31=20 ++LEBANON reg16=00 reg26=C2 reg30=02 reg31=20 ++LUXEMBOURG reg16=00 reg26=C2 reg30=02 reg31=28 ++MACAO reg16=00 reg26=C0 reg30=00 reg31=20 ++MALAYSIA reg16=00 reg26=30 reg30=00 reg31=20 ++MALTA reg16=00 reg26=C2 reg30=02 reg31=20 ++MEXICO reg16=00 reg26=C0 reg30=00 reg31=20 ++MOROCCO reg16=00 reg26=C2 reg30=02 reg31=20 ++NETHERLANDS reg16=00 reg26=C2 reg30=02 reg31=28 ++NEWZEALAND reg16=00 reg26=C0 reg30=04 reg31=20 ++NIGERIA reg16=00 reg26=C2 reg30=02 reg31=20 ++NORWAY reg16=00 reg26=C2 reg30=02 reg31=28 ++OMAN reg16=00 reg26=30 reg30=00 reg31=20 ++PAKISTAN reg16=00 reg26=30 reg30=00 reg31=20 ++PERU reg16=00 reg26=C0 reg30=00 reg31=20 ++PHILIPPINES reg16=00 reg26=30 reg30=00 reg31=20 ++POLAND reg16=03 reg26=C0 reg30=00 reg31=20 ++PORTUGAL reg16=00 reg26=C2 reg30=02 reg31=28 ++ROMANIA reg16=00 reg26=C0 reg30=00 reg31=20 ++RUSSIA reg16=00 reg26=30 reg30=00 reg31=20 ++SAUDIARABIA reg16=00 reg26=C0 reg30=00 reg31=20 ++SINGAPORE reg16=00 reg26=C0 reg30=00 reg31=20 ++SLOVAKIA reg16=00 reg26=C0 reg30=03 reg31=20 ++SLOVENIA reg16=00 reg26=C0 reg30=02 reg31=20 ++SOUTHAFRICA reg16=42 reg26=C0 reg30=03 reg31=20 ++SOUTHKOREA reg16=00 reg26=C0 reg30=00 reg31=20 ++SPAIN reg16=00 reg26=C2 reg30=02 reg31=28 ++SWEDEN reg16=00 reg26=C2 reg30=02 reg31=28 ++SWITZERLAND reg16=00 reg26=C2 reg30=02 reg31=28 ++SYRIA reg16=00 reg26=30 reg30=00 reg31=20 ++TAIWAN reg16=00 reg26=30 reg30=00 reg31=20 ++THAILAND reg16=00 reg26=30 reg30=00 reg31=20 ++UAE reg16=00 reg26=C0 reg30=00 reg31=20 ++UK reg16=00 reg26=C2 reg30=05 reg31=28 ++USA reg16=00 reg26=C0 reg30=00 reg31=20 ++YEMEN reg16=00 reg26=C0 reg30=00 reg31=20 ++ "; ++ ++my %opermode_table; ++ ++sub opermode_setup() { ++ main::logit "Setting OPERMODE=$OPERMODE"; ++ # Several countries (South Africa, UAE, anybody else) ++ # require a shorter delay: ++ if($OPERMODE eq 'SOUTHAFRICA' or $OPERMODE eq 'UAE') { ++ FXO::gen "* WD 17 2B"; ++ } ++ # defaults, based on fxo_modes from wctdm.c . ++ # Decimal register numbers! ++ my %regs = ( ++ 16 => 0, ++ 26 => 0, ++ 30 => 0, ++ 31 => 0x20, ++ ); ++ my $mode = $opermode_table{$OPERMODE}; ++ if(defined $mode) { ++ foreach my $k (keys %regs) { ++ my $fullkey = "reg$k"; ++ $regs{$k} = $mode->{$fullkey}; ++ } ++ } ++ foreach my $k (keys %regs) { ++ # Our values are HEXADECIMAL without a 0x prefix!!! ++ my $cmd = sprintf "* WD %02X %02X", $k, hex($regs{$k}); ++ main::debug " regs: '$cmd'"; ++ FXO::gen "$cmd"; ++ } ++ main::debug "Finished Opermode"; ++} ++ ++sub parse_opermode_line($) { ++ my $line = shift or return(); ++ ++ chomp $line; ++ $line =~ s/#.*//; ++ my @params = split(/\s+/, $line); ++ my $location = shift @params; ++ my $entry = {}; ++ foreach my $p (@params) { ++ my ($key, $val) = split(/=/, $p, 2); ++ $entry->{$key} = $val; ++ } ++ return ($location, $entry); ++} ++ ++sub opermode_preprocess() { ++ undef %opermode_table; ++ foreach my $line (split(/\n/, $OPERMODE_DATA)) { ++ my ($location, $entry) = parse_opermode_line($line); ++ next unless defined $location; ++ #print "$location\t", ref($entry), "\n"; ++ die "An entry for '$location' already exists\n" ++ if exists $opermode_table{$location}; ++ $opermode_table{$location} = $entry; ++ } ++} ++ ++sub opermode_to_string($) { ++ my $mode = shift or die; ++ my @params; ++ ++ foreach my $k (sort keys %{$mode}) { ++ push(@params, "$k=$mode->{$k}"); ++ } ++ return join(" ", @params); ++} ++ ++sub opermode_list() { ++ my $l = join("\n", sort keys %opermode_table); ++ print "$l\n"; ++} ++ ++sub opermode_verify($) { ++ my $input = shift or die; ++ my %verification_table; ++ my %location_lines; ++ my $mismatches = 0; ++ ++ open(F, $input) or die "$0: Failed opening '$input': $!\n"; ++ while() { ++ chomp; ++ #print "$_\n"; ++ s/#.*//; ++ my @params = split; ++ my $location = shift @params; ++ foreach my $p (@params) { ++ my ($key, $val) = split(/=/, $p, 2); ++ $verification_table{$location}{$key} = $val; ++ } ++ $location_lines{$location} = $.; ++ } ++ close F; ++ # First test: check for missing data in our program ++ foreach my $location (sort keys %verification_table) { ++ my $mode = $opermode_table{$location}; ++ if(! defined $mode) { ++ printf STDERR "Missing from $0: '$location' at $input:$location_lines{$location}\n"; ++ $mismatches++; ++ next; ++ } ++ my $verify_mode = $verification_table{$location}; ++ my $str1 = opermode_to_string($mode); ++ my $str2 = opermode_to_string($verify_mode); ++ if($str1 ne $str2) { ++ print STDERR "DIFF: '$location' at $input:$location_lines{$location}\n"; ++ printf STDERR "\t%-20s: %s\n", "program", $str1; ++ printf STDERR "\t%-20s: %s\n", "verify", $str2; ++ $mismatches++; ++ } ++ } ++ # Second test: check for extra data in our program ++ foreach my $location (sort keys %opermode_table) { ++ my $mode = $verification_table{$location}; ++ if(! defined $mode) { ++ printf STDERR "Extra in $0 '$location'\n"; ++ $mismatches++; ++ next; ++ } ++ } ++ print STDERR "Total $mismatches mismatches\n" if $mismatches; ++ return $mismatches; ++} ++ ++sub read_defaults() { ++ if(XppConfig::read_config(\%settings)) { ++ main::logit "Defaults from $settings{xppconf}"; ++ my $o = $settings{opermode}; ++ if(defined($o)) { ++ # Verify ++ $o = uc($o); # Uppercase ++ my $mode = $opermode_table{$o}; ++ if(! defined $mode) { ++ main::logit "Unknown opermode='$o'"; ++ die; ++ } ++ $OPERMODE = $o; ++ main::logit "Set OPERMODE = $o"; ++ } ++ } else { ++ main::logit "No defaults file, use hard-coded defaults."; ++ } ++} ++ ++package main; ++ ++FXO::opermode_preprocess; # Must be first ++ ++if($opts{v}) { ++ my $verify_file = $opts{v}; ++ usage unless $verify_file; ++ main::debug "$0: opermode verification (input='$verify_file')"; ++ my $mismatches = FXO::opermode_verify($verify_file); ++ die "$0: Verification against $verify_file failed\n" if $mismatches != 0; ++ exit 0; ++} elsif($opts{L}) { ++ FXO::opermode_list(); ++ exit 0; ++} ++ ++main::debug "Starting"; ++ ++FXO::read_defaults; ++die "OPERMODE is undefined" unless $OPERMODE; ++set_output; ++FXO::turn_off_leds; ++while() { ++ chomp; ++ s/[#;].*$//; # remove comments ++ s/^\s+//; # trim whitespace ++ s/\s+$//; # trim whitespace ++ s/\t+/ /g; # replace tabs with spaces (for logs) ++ next unless /\S/; # Skip empty lines ++ main::debug "writing: '$_'"; ++ FXO::gen "$_"; ++} ++FXO::opermode_setup; ++close REG; ++ ++main::debug "Ending '$0'"; ++close STDERR; ++exit 0; ++ ++__DATA__ ++* WD 12 02 # Full wave rectified ring detection ++* WD 03 01 # Polarity reversal detect mask ++* WD 04 00 # Clear interrupt status ++* WD 21 08 # Disable PCM transfers ++* WD 18 99 ++* WD 06 00 ++ ++# ----------- DAA PCM start offset ---------- ++ ++* WD 23 00 ++* WD 25 00 ++ ++0 WD 22 00 ++0 WD 24 00 ++0 WD 21 28 # Enable PCM transfers, when offsets are set ++ ++1 WD 22 08 ++1 WD 24 08 ++1 WD 21 28 ++ ++2 WD 22 10 ++2 WD 24 10 ++2 WD 21 28 ++ ++3 WD 22 18 ++3 WD 24 18 ++3 WD 21 28 ++ ++4 WD 22 20 ++4 WD 24 20 ++4 WD 21 28 ++ ++5 WD 22 28 ++5 WD 24 28 ++5 WD 21 28 ++ ++6 WD 22 30 ++6 WD 24 30 ++6 WD 21 28 ++ ++7 WD 22 38 ++7 WD 24 38 ++7 WD 21 28 ++ ++# ----------- DAA ONHOOK -------------------- ++* WD 05 00 ++ ++# Set tip to ring voltage to 3.5 volts while off-hook ++# instead of default of 3.1 ++* WD 1A C0 +diff -Nru linux-source-4.19/drivers/dahdi/xpp/init_card_3_30 linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_3_30 +--- linux-source-4.19/drivers/dahdi/xpp/init_card_3_30 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_3_30 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,475 @@ ++#! /usr/bin/perl -w ++use strict; ++ ++# Make warnings fatal ++local $SIG{__WARN__} = sub { die @_ }; ++ ++# ++# $Id$ ++# ++ ++# ++# Written by Oron Peled ++# Copyright (C) 2006, Xorcom ++# ++# 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 as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# See the file LICENSE in the top level of this tarball. ++# ++ ++# This script is run from the xpp kernel module upon detection ++# of a new XPD. ++# ++# Expects the following environment variables to be set: ++# XBUS_NAME - bus name ++# UNIT_NUMBER - xpd unit number ++# UNIT_SUBUNITS - number of subunits in this xpd ++# UNIT_TYPE - xpd type number (from protocol reply): ++# 1 - FXS ++# 2 - FXO ++# 3 - BRI ++# 4 - PRI ++# XBUS_REVISION - xbus revision number ++# XBUS_CONNECTOR - xbus connector string ++# ++# Output data format: ++# - An optional comment start with ';' or '#' until the end of line ++# - Optional Blank lines are ignored ++# - Fields are whitespace separated (spaces or tabs) ++# ++# The fields are (in command line order): ++# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) ++# 2. Command word: ++# - RD Read Direct register. ++# - RS Read Sub-register. ++# - WD Write Direct register. ++# - WS Write Sub-register. ++# 3. Register number in hexadecimal. ++# 4. Subregister number in hexadecimal. (for RS and WS commands). ++# 5. Data byte in hexadecimal. (for WD and WS commands only). ++# ++ ++package main; ++use File::Basename; ++use Getopt::Std; ++ ++my $program = basename("$0"); ++my $init_dir = dirname("$0"); ++BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); } ++use XppConfig $init_dir; ++my $unit_id; ++my %opts; ++ ++getopts('o:', \%opts); ++ ++my %settings; ++ ++sub logit { ++ print STDERR "$unit_id: @_\n"; ++} ++ ++sub debug { ++ logit @_ if $settings{debug}; ++} ++ ++# Arrange for error logging ++if (-t STDERR) { ++ $unit_id = 'Interactive'; ++ debug "Interactive startup"; ++} else { ++ $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}"; ++ open (STDERR, "| logger -t $program -p kern.info") || die; ++ debug "Non Interactive startup"; ++ foreach my $k (qw( ++ XBUS_NAME ++ XBUS_NUMBER ++ UNIT_NUMBER ++ UNIT_TYPE ++ UNIT_SUBUNITS ++ UNIT_SUBUNITS_DIR ++ XBUS_REVISION ++ XBUS_CONNECTOR ++ XBUS_LABEL)) { ++ unless(defined $ENV{$k}) { ++ logit "Missing ENV{$k}\n"; ++ die; ++ } ++ } ++} ++ ++sub select_subunit($) { ++ my $subunit = shift; ++ die unless defined $subunit; ++ my $output; ++ ++ if($opts{o}) { ++ $output = $opts{o}; ++ } else { ++ $output = sprintf "/sys/bus/xpds/devices/%02d:%1d:%1d/chipregs", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}, $subunit; ++ if(! -f $output) { ++ my $xpd_name = sprintf("XPD-%1d%1d", $ENV{UNIT_NUMBER}, $subunit); ++ $output = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs"; ++ logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc" ++ if -f $output; ++ } ++ } ++ open(REG, ">$output") || die "Failed to open '$output': $!\n"; ++ my $oldfh = select REG; ++ print "# Selecting subunit $subunit\n" if $opts{o}; ++ return $oldfh; ++} ++ ++package BRI; ++ ++sub gen { ++ my $fmt = shift; ++ $| = 1; ++ printf "$fmt\n", @_; ++} ++ ++# Turning on/off multi-byte packet reception. ++sub multibyte($) { ++ my $active = (shift) ? 'M' : 'm'; ++ for my $subunit (0 .. $ENV{UNIT_SUBUNITS} - 1) { ++ #main::logit "multibyte(): $subunit -> $active"; ++ main::select_subunit($subunit); ++ ++ BRI::gen "$subunit W$active"; ++ } ++} ++ ++sub read_defaults() { ++ if(XppConfig::read_config(\%settings)) { ++ main::logit "Defaults from $settings{xppconf}"; ++ } else { ++ main::logit "No defaults file, use hard-coded defaults."; ++ } ++} ++ ++package BRI::Port; ++ ++sub new { ++ my $pack = shift; ++ my $port = { @_ }; ++ bless $port, $pack; ++} ++ ++# zap_xhfc_su.c:995 ++sub init_su { ++ my $port = shift; ++ my $portnum = $port->{PORT_NUM}; ++ my $port_mode_up = $port->{PORT_MODE_UP}; ++ my $port_mode_exch = $port->{PORT_MODE_EXCH}; ++ my $bri_nt = $port->{BRI_NT}; ++ #main::logit "init_su(portnum=$portnum, port_mode_up=$port_mode_up, bri_nt=$bri_nt)"; ++ ++ # Setting PLL ++ # R_PLL_CTRL = 0 (V_PLL_M = 0, Reset PLL, Disable PLL_ ++ # R_CLK_CFG = 05 (PLL clock as system clock, output it to CLK_OUT pin) ++ # R_PLL_P = 1 ++ # R_PLL_N = 6 ++ # R_PLL_S = 1 ++ # R_PLL_CTRL = 1 (V_PLL_M) ++ ++ BRI::gen "#--------------------------- init_su($portnum, $bri_nt, $port_mode_up, $port_mode_exch)"; ++ BRI::gen "$portnum WD 02 04"; ++ BRI::gen "$portnum WD 50 00"; # disable PLL ++ BRI::gen "$portnum WD 51 02"; ++ BRI::gen "$portnum WD 52 06"; ++ BRI::gen "$portnum WD 53 04"; ++ BRI::gen "$portnum WD 50 01"; # Enable PLL ++ BRI::gen "$portnum WD 02 05"; # Enable PLL ++ ++ su_sel($portnum); # select port ++ if ("$port_mode_up" == 1) { ++ $port->{CTRL3} = 0x01; # A_ST_CTRL3: V_ST_SEL = 1 ++ $port->{CTRL0} = 0x10; # A_SU_CTRL0: V_ST_SQ_EN = 1 ++ BRI::gen "$portnum WD 34 0F"; # A_MS_TX: ++ # (multiframe/superframe transmit register) ++ } else { ++ $port->{CTRL3} = 0x00; # A_ST_CTRL3: V_ST_SEL = 0 ++ $port->{CTRL0} = 0x00; # A_SU_CTRL0: V_ST_SQ_EN = 0 ++ } ++ if ("$bri_nt" == 1) { ++ $port->{CTRL0} |= 0x04; # V_SU_MD ++ } ++ # ((V_SU_EXCH)?0x80:00) (change polarity) ++ if($port_mode_exch) { ++ $port->{CTRL2} = 0x80; ++ } else { ++ $port->{CTRL2} = 0x00; ++ } ++ BRI::gen "$portnum WD 35 %02X", $port->{CTRL3}; # A_ST_CTRL3 ++ BRI::gen "$portnum WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0 ++ BRI::gen "$portnum WD 35 F8"; # A_ST_CTRL3 = set end of pulse control to 0xF8 ++ BRI::gen "$portnum WD 32 09"; # A_SU_CTRL1 = Ignore E-channel data, Force automatic transition from G2 to G3 ++ BRI::gen "$portnum WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2 ++ ++ # zap_xhfc_su.c:1030 in init_su() ++ # A_SU_CLK_DLY ++ my $clk_dly; ++ if ("$bri_nt" == 1) { ++ $clk_dly = 0x6C; ++ } else { ++ $clk_dly = 0x0E; ++ } ++ #main::logit "clk_dly=$clk_dly"; ++ BRI::gen "$portnum WD 37 %02X", "$clk_dly"; ++} ++ ++sub su_sel { ++ if (@_ != 1 ) { ++ main::logit "ERROR: su_sel() called with " . scalar(@_) . " parameters"; ++ exit 1; ++ } ++ my $portnum = shift; ++ BRI::gen "$portnum WD 16 %02X", $portnum; # R_SU_SEL ++} ++ ++# zap_xhfc_su.c:281 ++sub xhfc_selfifo { ++ my $port = shift; ++ my $portnum = $port->{PORT_NUM}; ++ ++ if (@_ != 1 ) { ++ main::logit "ERROR: xhfc_selfifo() called with " . scalar(@_) . " parameters"; ++ exit 1; ++ } ++ my $fifonum = shift; ++ #main::logit "xhfc_selfifo($fifonum)"; ++ BRI::gen "$portnum WD 0F %02X", $fifonum; ++ # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 ++} ++ ++# zap_xhfc_su.c:295 ++sub xhfc_resetfifo() { ++ my $port = shift; ++ my $portnum = $port->{PORT_NUM}; ++ ++ #main::logit "xhfc_resetfifo()"; ++ # A_INC_RES_FIFO = M_RES_FIFO | M_RES_FIFO_ERR ++ BRI::gen "$portnum WD 0E 0A"; ++ # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 ++} ++ ++# zap_xhfc_su.c:1040 ++# Initialize fifo (called for each portnum, channel, direction) ++sub setup_fifo { ++ my $port = shift; ++ my $chan = shift; ++ my $direction = shift; ++ my $conhdlc = shift; ++ my $subcfg = shift; ++ my $fifoctrl = shift; ++ my $portnum = $port->{PORT_NUM}; ++ my $port_mode_up = $port->{PORT_MODE_UP}; ++ my $port_mode_exch = $port->{PORT_MODE_EXCH}; ++ my $bri_nt = $port->{BRI_NT}; ++ ++ BRI::gen "#--------------------------- setup_fifo($portnum, $chan, $direction)"; ++ # my $fifonum = 0x80 | ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first ++ my $fifonum = ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first ++ my $r_slot = ($portnum << 3) | ($chan << 1) | ($direction); ++ ++ # channel order workaround, swap odd and even portnums in $r_slot for PCM (chan 0, 1) only ++ if ("$chan" == 0 || "$chan" == 1) { ++ $r_slot = $r_slot ^ 0x08; ++ } ++ ++ my $short_portnum = $portnum & 0x03; ++ my $a_sl_cfg = (0x80 | ($short_portnum << 3) | ($chan << 1) | ($direction)); # receive data from STIO2, transmit to STIO1 ++ ++ #main::logit "setup_fifo($fifonum)"; ++ $port->xhfc_selfifo($fifonum); ++ # A_CON_HDLC: transparent mode selection ++ BRI::gen "$portnum WD FA %02X", $conhdlc; ++ # A_SUBCH_CFG: subchnl params ++ BRI::gen "$portnum WD FB %02X", $subcfg; ++ # A_FIFO_CTRL: FIFO Control Register ++ BRI::gen "$portnum WD FF %02X", $fifoctrl; ++ $port->xhfc_resetfifo(); ++ $port->xhfc_selfifo($fifonum); # wait for busy is builtin in this command ++ BRI::gen "$portnum WD 10 %02X", $r_slot; # R_SLOT ++ BRI::gen "$portnum WD D0 %02X", $a_sl_cfg; # A_SL_CFG ++ ++ #system("/bin/echo \"----=====TE\" \"short_portnum=\"$short_portnum \"portnum=\" $portnum \"chan=\" $chan\"======----\n\" >>/root/xortel/test_init"); ++} ++ ++# zap_xhfc_su.c:1071 ++sub setup_su { ++ my $port = shift; ++ my $bchan = shift; ++ my $portnum = $port->{PORT_NUM}; ++ my $port_mode_exch = $port->{PORT_MODE_EXCH}; ++ my $bri_nt = $port->{BRI_NT}; ++ ++ BRI::gen "#--------------------------- setup_su($portnum, $bchan)"; ++ #main::logit "setup_su(portnum=$portnum, bchan=$bchan, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; ++ $port->{CTRL0} |= (1 << $bchan) | $bri_nt; ++ $port->{CTRL2} |= ($port_mode_exch << 7) | (1 << $bchan); ++ su_sel($portnum); # Select port ++ BRI::gen "$portnum WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0: V_B1_TX_EN | V_SU_MD | (NT/TE) ++ BRI::gen "$portnum WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2: V_B1_RX_EN ++} ++ ++sub xhfc_ph_command { ++ my $port = shift; ++ my $cmd = shift; ++ my $portnum = $port->{PORT_NUM}; ++ #main::logit "xhfc_ph_command(portnum=$portnum)"; ++ if ("$cmd" eq "HFC_L1_ACTIVATE_TE") { ++ su_sel($portnum); # Select port ++ BRI::gen "$portnum WD 30 60"; # A_SU_WR_STA = (M_SU_ACT & 0x03) ++ # (set activation) ++ } elsif ("$cmd" eq "HFC_L1_FORCE_DEACTIVATE_TE") { ++ su_sel($portnum); # Select port ++ BRI::gen "$portnum WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) ++ # (set deactivation) ++ } elsif ("$cmd" eq "HFC_L1_ACTIVATE_NT") { ++ su_sel($portnum); # Select port ++ BRI::gen "$portnum WD 30 E0"; # A_SU_WR_STA = (M_SU_ACT & 0x03) | 0x80 ++ # (set activation + NT) ++ } elsif ("$cmd" eq "HFC_L1_DEACTIVATE_NT") { ++ su_sel($portnum); # Select port ++ BRI::gen "$portnum WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) ++ # (set deactivation) ++ } ++} ++ ++ ++sub zthfc_startup { ++ my $port = shift; ++ my $portnum = $port->{PORT_NUM}; ++ my $port_mode_exch = $port->{PORT_MODE_EXCH}; ++ my $bri_nt = $port->{BRI_NT}; ++ #main::logit "zthfc_startup(portnum=$portnum, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; ++ ++ # PCM <-> ST/Up Configuration ++ foreach my $chan ( 0, 1 ) { ++ $port->setup_fifo($chan, 0, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM ++ $port->setup_fifo($chan, 1, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM ++ $port->setup_su($chan); # zap_xhfc_su.c:194 ++ } ++ ++ # Dahdi chan 2 used as HDLC D-Channel ++ $port->setup_fifo(2, 0, 0x05, 2, 0); # D-TX: zap_xhfc_su.c:205 ++ $port->setup_fifo(2, 1, 0x05, 2, 0); # D-RX: zap_xhfc_su.c:206 ++ # E-chan, Echo channel is ignored ++ ++ ++ # enable this port's state machine ++ su_sel($portnum); # Select port ++ # A_SU_WR_STA: reset port state machine ++ BRI::gen "$portnum WD 30 00"; ++ if ("$bri_nt" == 0) { ++ $port->xhfc_ph_command("HFC_L1_ACTIVATE_TE"); ++ } else { ++ $port->xhfc_ph_command("HFC_L1_ACTIVATE_NT"); ++ } ++} ++ ++package main; ++ ++debug "Starting '$0'"; ++ ++BRI::read_defaults; ++ ++#------------------------------------------- Instance detection ++ ++# zap_xhfc_su.c:895 ++sub init_xhfc($) { ++ my $portnum = shift; ++ main::debug "init_xhfc($portnum)"; ++ BRI::gen "#--------------------------- init_xhfc"; ++ BRI::gen "$portnum WD 0D 00"; # r_FIFO_MD: 16 fifos, ++ # 64 bytes for TX and RX each (FIFO mode config) ++ ++ # software reset to enable R_FIFO_MD setting ++ BRI::gen "$portnum WD 00 08"; # R_CIRM = M_SRES (soft reset) ++ # --> WAIT 5u ++ BRI::gen "$portnum WD 00 00"; # R_CIRM = 0 (zero it to deactivate reset) ++ ++ # amplitude ++ BRI::gen "$portnum WD 46 80"; # R_PWM_MD: (PWM output mode register) ++ # PWM push to zero only ++ BRI::gen "$portnum WD 39 18"; # R_PWM1: (modulator register for PWM1) ++ # set duty cycle ++ ++ BRI::gen "$portnum WD 0C 11"; # R_FIFO_THRES: (FIFO fill lvl control register) ++ # RX/TX threshold = 16 bytes ++ ++ # set PCM bus mode to slave by default ++ BRI::gen "$portnum WD 14 08"; # R_PCM_MD0 = PCM slave mode, F0IO duration is 2 HFC_PCLK's ++ # (C4IO, F0IO are inputs) ++ ++ BRI::gen "$portnum WD 14 98"; # R_PCM_MD0: Index value to select ++ # the register at address 15 ++ BRI::gen "$portnum WD 15 20"; # R_PCM_MD1: V_PLL_ADJ (DPLL adjust speed), ++ # in the last slot of PCM frame ++ # V_PCM_DR, C4IO is 16.384MHz(128 time slots) ++ ++ BRI::gen "$portnum WD 4C 07"; # GPIOGPIO function (not PWM) on GPIO0, GPIO1 and GPIO2 pins ++ BRI::gen "$portnum WD 4A 07"; # Output enable for GPIO0, GPIO1 and GPIO2 pins ++ BRI::gen "$portnum WD 48 01"; # GPIO output data bits ++ ++} ++ ++my @port_type = ( ++ { 'BRI_NT' => 1 }, ++ { 'BRI_NT' => 0 } ++ ); ++ ++# zap_xhfc_su.c:175 ++sub main() { ++ my $subunit; ++ my $subunits_mask = pack("C", $ENV{UNIT_SUBUNITS_DIR}); ++ my @direction = split(//, unpack("b*", $subunits_mask)); ++ ++ #logit "main(): UNIT_TYPE=$ENV{UNIT_TYPE} UNIT_SUBUNITS_DIR=[@direction]"; ++ if(!$opts{o}) { ++ foreach my $var (qw(XBUS_NAME UNIT_NUMBER UNIT_TYPE UNIT_SUBUNITS UNIT_SUBUNITS_DIR XBUS_REVISION XBUS_CONNECTOR)) { ++ die "Missing mandatory '$var' environment variable" unless defined $var; ++ } ++ } ++ # Turn off multi-byte packet reception before initialization started ++ # Otherwise we mess with registers while the FPGA firmware tries to ++ # send us packets. ++ BRI::multibyte(0); ++ ++ # Port initialization ++ for($subunit = 0; $subunit < $ENV{UNIT_SUBUNITS}; $subunit++) { ++ my $is_nt = $direction[$subunit]; ++ ++ main::select_subunit($subunit); ++ if(($subunit % 4) == 0) { # A new xhfc chip ++ #logit "main(): Initializing chip"; ++ init_xhfc($subunit); # zap_xhfc_su.c:1173 in setup_instance() ++ } ++ #logit "main(): Initializing subunit $subunit is_nt=$is_nt"; ++ my $p = BRI::Port->new( ++ 'PORT_NUM' => $subunit, ++ 'BRI_NT' => $is_nt, ++ 'PORT_MODE_UP' => 0, ++ 'PORT_MODE_EXCH' => 0 ++ ); ++ # zap_XHfc_su.c:1186 in setup_instance() ++ $p->init_su; ++ $p->zthfc_startup; ++ } ++ # Turn on multi-byte packet reception when ports initialization finished ++ BRI::multibyte(1); ++} ++ ++main; ++ ++debug "Ending '$0'"; ++ ++close REG; ++close STDERR; ++exit 0; +diff -Nru linux-source-4.19/drivers/dahdi/xpp/init_card_4_30 linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_4_30 +--- linux-source-4.19/drivers/dahdi/xpp/init_card_4_30 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_4_30 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,419 @@ ++#! /usr/bin/perl -w ++use strict; ++ ++# Make warnings fatal ++local $SIG{__WARN__} = sub { die @_ }; ++ ++# ++# $Id$ ++# ++ ++# ++# Written by Oron Peled ++# Copyright (C) 2007, Xorcom ++# ++# 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 as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# See the file LICENSE in the top level of this tarball. ++# ++ ++# This script is run from the xpp kernel module upon detection ++# of a new XPD. ++# ++# Expects the following environment variables to be set: ++# XBUS_NAME - bus name ++# UNIT_NUMBER - xpd unit number ++# UNIT_SUBUNITS - number of subunits in this xpd ++# UNIT_TYPE - xpd type number (from protocol reply): ++# 1 - FXS ++# 2 - FXO ++# 3 - BRI ++# 4 - PRI ++# XBUS_REVISION - xbus revision number ++# XBUS_CONNECTOR - xbus connector string ++# XBUS_LABEL - xbus label string ++# ++# Output data format: ++# - An optional comment start with ';' or '#' until the end of line ++# - Optional Blank lines are ignored ++# - Fields are whitespace separated (spaces or tabs) ++# ++# The fields are (in command line order): ++# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) ++# 2. Command word: ++# - RD Read Direct register. ++# - WD Write Direct register. ++# 3. Register number in hexadecimal. ++# 5. Data byte in hexadecimal. (for WD command only). ++# ++ ++package main; ++use File::Basename; ++use Getopt::Std; ++ ++my $program = basename("$0"); ++my $init_dir = dirname("$0"); ++BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); } ++use XppConfig $init_dir; ++my $unit_id; ++my %opts; ++ ++getopts('o:', \%opts); ++ ++my %settings; ++ ++sub logit { ++ print STDERR "$unit_id: @_\n"; ++} ++ ++sub debug { ++ logit @_ if $settings{debug}; ++} ++ ++# Arrange for error logging ++if (-t STDERR) { ++ $unit_id = 'Interactive'; ++ debug "Interactive startup"; ++} else { ++ $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}"; ++ open (STDERR, "| logger -t $program -p kern.info") || die; ++ debug "Non Interactive startup"; ++ foreach my $k (qw( ++ XBUS_NAME ++ XBUS_NUMBER ++ UNIT_NUMBER ++ UNIT_TYPE ++ UNIT_SUBUNITS ++ UNIT_SUBUNITS_DIR ++ XBUS_REVISION ++ XBUS_CONNECTOR ++ XBUS_LABEL)) { ++ unless(defined $ENV{$k}) { ++ logit "Missing ENV{$k}\n"; ++ die; ++ } ++ } ++} ++ ++sub select_subunit($) { ++ my $subunit = shift; ++ die unless defined $subunit; ++ my $output; ++ ++ if($opts{o}) { ++ $output = $opts{o}; ++ } else { ++ $output = sprintf "/sys/bus/xpds/devices/%02d:%1d:%1d/chipregs", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}, $subunit; ++ if(! -f $output) { ++ my $xpd_name = sprintf("XPD-%1d%1d", $ENV{UNIT_NUMBER}, $subunit); ++ $output = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs"; ++ logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc" ++ if -f $output; ++ } ++ } ++ open(REG, ">$output") || die "Failed to open '$output': $!\n"; ++ my $oldfh = select REG; ++ print "# Selecting subunit $subunit\n" if $opts{o}; ++ return $oldfh; ++} ++ ++package PRI; ++ ++sub gen { ++ my $fmt = shift; ++ $| = 1; ++ printf "$fmt\n", @_; ++} ++ ++sub init_quad() { ++ main::select_subunit(0); ++ ++ PRI::gen "0 WD D6 20"; # GPC6.COMP_DIS=1 ++ # (Compatibility Mode Disable) ++ ++ # Tuning of clocking unit to the 16.384 MHz reference frequence ++ # by setting Global Clock Mode registers (GCM[1:8]), same for E1 and T1/J1 ++ PRI::gen "0 WD 92 00"; # GCM1 ++ PRI::gen "0 WD 93 18"; # GCM2 ++ PRI::gen "0 WD 94 FB"; # GCM3 ++ PRI::gen "0 WD 95 0B"; # GCM4 ++ PRI::gen "0 WD 96 01"; # GCM5 ++ PRI::gen "0 WD 97 0B"; # GCM6 ++ PRI::gen "0 WD 98 DB"; # GCM7 ++ PRI::gen "0 WD 99 DF"; # GCM8 ++} ++ ++sub finish_quad() { ++ PRI::gen "0 WD BB 2C"; # REGFP ++ PRI::gen "0 WD BC FF"; # REGFD ++ PRI::gen "0 WD BB AC"; # REGFP ++ PRI::gen "0 WD BB 2B"; # REGFP ++ PRI::gen "0 WD BC 00"; # REGFD ++ PRI::gen "0 WD BB AB"; # REGFP ++ PRI::gen "0 WD BB 2A"; # REGFP ++ PRI::gen "0 WD BC FF"; # REGFD ++ PRI::gen "0 WD BB AA"; # REGFP ++ PRI::gen "0 WD BB 29"; # REGFP ++ PRI::gen "0 WD BC FF"; # REGFD ++ PRI::gen "0 WD BB A9"; # REGFP ++ PRI::gen "0 WD BB 28"; # REGFP ++ PRI::gen "0 WD BC 00"; # REGFD ++ PRI::gen "0 WD BB A8"; # REGFP ++ PRI::gen "0 WD BB 27"; # REGFP ++ PRI::gen "0 WD BC FF"; # REGFD ++ PRI::gen "0 WD BB A7"; # REGFP ++ PRI::gen "0 WD BB 00"; # REGFP ++ ++# PRI::gen "0 WD 80 00"; # PC1 (Port configuration 1): RPB_1.SYPR , XPB_1.SYPX ++} ++ ++sub read_defaults() { ++ if(XppConfig::read_config(\%settings)) { ++ main::logit "Defaults from $settings{xppconf}"; ++ } else { ++ main::logit "No defaults file, use hard-coded defaults."; ++ } ++} ++ ++package PRI::Port; ++ ++sub new { ++ my $pack = shift; ++ my $port = { @_ }; ++ bless $port, $pack; ++ return $port; ++} ++ ++sub get_pri_protocol { ++ my $port = shift; ++ my $subunit = $port->{PORT_NUM}; ++ my $xpd_name = "XPD-$ENV{UNIT_NUMBER}$subunit"; ++ my $pri_protocol; ++ my @keys = ( ++ "pri_protocol/connector:$ENV{XBUS_CONNECTOR}/$xpd_name", ++ "pri_protocol/label:$ENV{XBUS_LABEL}/$xpd_name", ++ "pri_protocol/$ENV{XBUS_NAME}/$xpd_name", ++ "pri_protocol" ++ ); ++ foreach my $k (@keys) { ++ $k = lc($k); # Lowercase ++ $pri_protocol = $settings{$k}; ++ if(defined $pri_protocol) { ++ $port->{pri_protocol} = $pri_protocol; ++ return $pri_protocol; ++ } ++ } ++ return undef; ++} ++ ++sub write_pri_info { ++ my $port = shift; ++ my $subunit = $port->{PORT_NUM}; ++ my $pri_protocol = $port->get_pri_protocol; ++ my $xpd_name = sprintf("XPD-%1d%1d", $ENV{UNIT_NUMBER}, $subunit); ++ ++ if(defined $pri_protocol) { ++ main::logit "$xpd_name: pri_protocol $pri_protocol"; ++ my $file = sprintf "/sys/bus/xpds/devices/%02d:%1d:%1d/pri_protocol", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}, $subunit; ++ if(! -f $file) { ++ $file = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/pri_info"; ++ main::logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc" ++ if -f $file; ++ } ++ open(INFO, ">$file") || die "Failed to open '$file': $!\n"; ++ print INFO "$pri_protocol\n" || die "Failed writing '$pri_protocol' to '$file': $!\n"; ++ close INFO || die "Failed during close of '$file': $!\n"; ++ } else { ++ main::logit "$xpd_name: pri_protocol not given. Driver will use defaults."; ++ } ++} ++ ++sub port_setup($) { ++ my $port = shift; ++ my $portno = $port->{PORT_NUM}; ++ my $pri_protocol = $port->get_pri_protocol; ++ ++ PRI::gen "$portno WD 28 40"; # XPM2.XLT Tristate ++ ++ my $cmr5 = sprintf("%x", ($portno << 5)); ++ ++ PRI::gen "$portno WD 42 $cmr5"; # CMR5.DRSS=portno ++ ++ PRI::gen "$portno WD 26 F6"; # XPM0: Pulse Shape Programming for R1=18Ohms ++ PRI::gen "$portno WD 27 02"; # XPM1: ...3V Pulse Level at the line (Vp-p=6v) ++ ++ # if (unchannelized) ++ #PRI::gen "$portno WD 1F 22"; # LOOP (Channel Looback): ++ # ECLB (Enable Channel Loop-Back) ++ # CLA (Channel Address) ++ PRI::gen "$portno WD 2B EF"; # IDL (Idle): ++ # If channel loopback is enabled than transmit this code on the outgoing ++ PRI::gen "$portno WD 1F 00"; # LOOP (Channel Looback): ++ #if($portno eq 0){ ++ # PRI::gen "0 WD 1F 00"; # LOOP (Channel Looback): ++ # # channels (XL1/XL2) ++ #}else { ++ # PRI::gen "0 WD 1F 20"; # LOOP (Channel Looback): ++ #} ++ ++ # only one of the following loopbacks can be activated in the same time ++ my $LIM1_RL = 0 << 1; # RL (Remote Loopback) ++ my $lim1 = 0xB0 | $LIM1_RL; ++ PRI::gen "$portno WD 37 %02X", $lim1; ++ # LIM1: ~RL (Remote Loop bit 0x02), ++ # ~DRS (Dual Rail Select, latch receive data while trasmit), ++ # RIL1, RIL0 (Receive Input Treshold 0.62 V), ++ # CLOS (Clear data in case of LOS) ++ PRI::gen "$portno WD 3A 20"; # LIM2: SLT1, SLT0 = 01 ++ # (Receiver Slicer Threshold, the receive slicer ++ # generates a mark (digital one) if the voltage at ++ # RL1/2 exceeds 50% of the peak amplitude, ++ # default, recommended in E1 mode). ++ ++ PRI::gen "$portno WD 38 0A"; # PCD: (Pulse Count Detection, LOS Detection after 176 consecutive 0s) ++ PRI::gen "$portno WD 39 15"; # PCR: (Pulse Count Recovery, LOS Recovery after 22 ones in PCD interval) ++ ++ # Configure system interface ++ PRI::gen "$portno WD 3E C2"; # SIC1: SSC1 (System clock ) is 8.192 Mhz, ++ # SSD1 (System Data rate) is 8.192 Mbit/s, ++ # ~BIM (Byte interleaved mode), ++ # XBS (Transmit Buffer Size) is 2 frames ++ PRI::gen "$portno WD 40 04"; # SIC3: Edges for capture, Synchronous Pulse Receive @Rising Edge ++ PRI::gen "$portno WD 41 04"; # CMR4: RCLK is 8.192 MHz ++ PRI::gen "$portno WD 43 04"; # CMR5: TCLK is 8.192 MHz ++ PRI::gen "$portno WD 44 34"; # CMR6: Receive reference clock generated by channel 1, ++ # RCLK is at 8.192 Mhz dejittered, Clock recovered from the line ++ # TCLK is at 8.192 MHz is de-jittered by DCO-R to drive a6.176 MHz ++ # clock on RCLK.*/ ++ ++ PRI::gen "$portno WD 22 00"; # XC0: (Transmit Counter Offset = 497/T=2) ++ PRI::gen "$portno WD 23 04"; # XC1: X=4 => T=4-X=0 offset ++ ++ PRI::gen "$portno WD 24 00"; # RC0: (Receive Counter Offset = 497/T=2) ++ PRI::gen "$portno WD 25 05"; # RC1: Remaining part of RC0 ++ ++ my $sic2 = sprintf("%x", 0x00 | ($portno << 1)); ++ ++ PRI::gen "$portno WD 3F $sic2"; # SIC2: No FFS, no center receive elastic buffer, data active at phase ($sic >> 1) ++ ++ # enable the following interrupt sources ++ PRI::gen "$portno WD 14 F7"; # IMR0 (Interrupt Mask Register2): Enable CASC_E1/RSC_T1 ++ PRI::gen "$portno WD 16 00"; # IMR2 (Interrupt Mask Register2): Enable ALL ++ ++ PRI::gen "$portno WD 17 3F"; # IMR3 ~ES, ~SEC (Enable ES and SEC interrupts) ++ PRI::gen "$portno WD 18 00"; # IMR4: Enable ALL ++ PRI::gen "$portno WD 46 80"; # GCR: (Global Configuration Register) ++ # VIS (Masked Interrupts Visible) ++ ++ PRI::gen "$portno WD 08 04"; # IPC: SYNC is 8 Khz ++ ++ PRI::gen "$portno WD 02 51"; # CMDR (Command Register): RRES, XRES, SRES (Receiver/Transmitter reset) ++ PRI::gen "$portno WD 02 00"; # CMDR ++ ++ ++ PRI::gen "$portno WD 45 00"; # CMR2: External sources for SYPR, SCLKR, SYPX, SCLKX for TX and RX. ++ ++ # Configure ports ++ PRI::gen "$portno WD 85 80"; # GPC1 (Global Port Configuration 1): ++ #PRI::gen "$portno WD 85 00"; # GPC1 (Global Port Configuration 1): ++ # SMM (System Interface Multiplex Mode) ++ PRI::gen "$portno WD 80 00"; # PC1: SYPR/SYPX provided to RPA/XPA inputs ++ ++ PRI::gen "$portno WD 84 31"; # PC5: XMFS active low, SCLKR is input, RCLK is output (unused) ++ PRI::gen "$portno WD 3B 00"; # Clear LCR1 - Loop Code Register 1 ++ ++ # printk("TE110P: Successfully initialized serial bus for card\n"); ++ ++ # Initialize PCM and SIG regs ++ PRI::gen "$portno WD A0 00"; # TSEO (Time Slot Even/Odd Select) ++ PRI::gen "$portno WD A1 FF"; # TSBS (Time Slot Bit Select)- only selected bits are used for HDLC channel 1 ++ # in selected time slots ++ PRI::gen "$portno WD 03 89"; # Mode Register: ++ # MDS (Mode Select) = 100 (No address comparison) ++ # HRAC (Receiver Active - HDLC channel 1) ++ # RFT2 (HDLC Receive FIFO is 64 byte deep) ++ my $ccr1 = 0x18; # CCR1 (Common Configuration Register1) ++ # EITS (Enable Internal Time Slot 0 to 31 Signalling) ++ # ITF (Interframe Time Fill) ++ my $sysfs_pri_protocol; ++ if (defined $pri_protocol) { ++ $sysfs_pri_protocol = $pri_protocol; ++ } else { ++ my $file = sprintf "/sys/bus/xpds/devices/%02d:%1d:%1d/pri_protocol", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}, $portno; ++ # The 'open' will fail if the port does not exist. ++ # (or rather: the XPD for it does not exist). While ++ # we only read this file to get the default E1/T1 value, ++ # if it does not exist, it also implies the commands sent would ++ # get nowhere. So we might as well quit now. ++ open(F, $file) || return; ++ $sysfs_pri_protocol = ; ++ close F; ++ chomp $sysfs_pri_protocol; ++ } ++ if($sysfs_pri_protocol eq 'T1') { ++ $ccr1 |= 0x80; # RSCC (Serial CAS Format Selection) ++ } ++ ++ PRI::gen "$portno WD 09 %02X", $ccr1; ++ PRI::gen "$portno WD 0A 04"; # CCR2 (Common Configuration Register2) ++ # RCRC (enable CRC - HDLC channel 1enable CRC - HDLC channel 1) ++ PRI::gen "$portno WD 0C 00"; # RTR1 (Receive Time Slot register 1) ++ PRI::gen "$portno WD 0D 00"; # RTR2 (Receive Time Slot register 2) ++ PRI::gen "$portno WD 0E 00"; # RTR3 (Receive Time Slot register 3), TS16 (Enable time slot 16) ++ PRI::gen "$portno WD 0F 00"; # RTR4 (Receive Time Slot register 4) ++ ++ PRI::gen "$portno WD 10 00"; # TTR1 (Transmit Time Slot register 1) ++ PRI::gen "$portno WD 11 00"; # TTR2 (Transmit Time Slot register 2) ++ PRI::gen "$portno WD 12 00"; # TTR3 (Transmit Time Slot register 3), TS16 (Enable time slot 16) ++ PRI::gen "$portno WD 13 00"; # TTR4 (Transmit Time Slot register 4) ++ ++ # configure the best performance of the Bipolar Violation detection for all four channels ++ PRI::gen "$portno WD BD 00"; # BFR (Bugfix Register): ~BVP (Bipolar Violations), ++ # use Improved Bipolar Violation Detection instead ++} ++ ++package main; ++ ++main::debug "Starting '$0'"; ++ ++PRI::read_defaults; ++ ++sub main() { ++ my @ports; ++ my $subunit; ++ ++ main::debug "main(): Initializing chip ($ENV{UNIT_SUBUNITS} ports)"; ++ PRI::init_quad; ++ # Must initialize all 4 ports, regardless how much there are ++ for($subunit = 0; $subunit < 4; $subunit++) { ++ #main::debug "main(): Initializing subunit $subunit"; ++ my $p = PRI::Port->new( ++ 'PORT_NUM' => $subunit, ++ 'EXIST' => ($subunit < $ENV{UNIT_SUBUNITS}) ++ ); ++ $p->port_setup; ++ push(@ports, $p); ++ } ++ PRI::finish_quad; ++ foreach my $p (@ports) { ++ if($p->{EXIST}) { ++ $p->write_pri_info; ++ } ++ } ++} ++ ++main; ++ ++main::debug "Ending '$0'"; ++ ++close REG; ++close STDERR; ++exit 0; +diff -Nru linux-source-4.19/drivers/dahdi/xpp/init_card_5_30 linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_5_30 +--- linux-source-4.19/drivers/dahdi/xpp/init_card_5_30 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_5_30 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,3 @@ ++#!/bin/true ++ ++# ATM this script does nothing. +diff -Nru linux-source-4.19/drivers/dahdi/xpp/init_card_6_30 linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_6_30 +--- linux-source-4.19/drivers/dahdi/xpp/init_card_6_30 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/init_card_6_30 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,1170 @@ ++#! /usr/bin/perl -w ++use strict; ++ ++# Make warnings fatal ++local $SIG{__WARN__} = sub { die @_ }; ++ ++# ++# Written by Oron Peled ++# Copyright (C) 2017, Xorcom ++# ++# 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 as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# See the file LICENSE in the top level of this tarball. ++# ++ ++# ++# $Id$ ++# ++# Data format: ++# - A comment start with ';' or '#' until the end of line ++# - Blank lines are ignored ++# - Fields are whitespace separated (spaces or tabs) ++# ++# The fields are (in command line order): ++# 1. SLIC select in decimal (range 0-7). ++# * is a special value which means ALL SLICS (only some registers ++# accept settings for ALL SLICS). ++# 2. Command word: ++# - RD Read Direct register. ++# - RS Read Sub-register. ++# - WD Write Direct register. ++# - WS Write Sub-register. ++# 3. Register number in hexadecimal. ++# 4. Low data byte in hexadecimal. (for WD and WS commands). ++# 5. High data byte in hexadecimal. (for WS command only). ++# ++# ++ ++package main; ++use File::Basename; ++use Getopt::Std; ++ ++my $program = basename("$0"); ++my $init_dir = dirname("$0"); ++BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); } ++use XppConfig $init_dir; ++my $unit_id; ++my %opts; ++ ++getopts('o:', \%opts); ++ ++my %settings; ++$settings{debug} = 0; ++$settings{fxs_skip_calib} = 0; ++my $chipregs; ++my $command; ++my $expander_cmd; ++my $ring_registers; ++ ++sub logit { ++ print STDERR "$unit_id: @_\n"; ++} ++ ++sub debug { ++ logit @_ if $settings{debug}; ++} ++ ++# Arrange for error logging ++if (-t STDERR) { ++ $unit_id = 'Interactive'; ++ debug "Interactive startup"; ++} else { ++ $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}"; ++ open (STDERR, "| logger -t $program -p kern.info") || die; ++ debug "Non Interactive startup"; ++ foreach my $k (qw( ++ XBUS_NAME ++ XBUS_NUMBER ++ XBUS_MODEL_STRING ++ UNIT_NUMBER ++ UNIT_TYPE ++ UNIT_SUBUNITS ++ UNIT_SUBUNITS_DIR ++ XBUS_REVISION ++ XBUS_CONNECTOR ++ XBUS_LABEL)) { ++ unless(defined $ENV{$k}) { ++ logit "Missing ENV{$k}\n"; ++ die; ++ } ++ } ++ logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'"; ++ $chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}; ++ $command = "/proc/xpp/$ENV{XBUS_NAME}/command"; ++ if(! -f $chipregs) { ++ my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER}); ++ $chipregs = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs"; ++ logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc" ++ if -f $chipregs; ++ } ++ $ring_registers = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/fxs_ring_registers", ++ $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}; ++ logit "OLD DRIVER: missing '$ring_registers' -- fallback to hard-coded defaults" ++ unless -f $ring_registers; ++} ++ ++sub set_output() { ++ my $output; ++ ++ if($opts{o}) { ++ $output = $opts{o}; ++ } else { ++ # No subunits in FXS (everything is subunit 0) ++ $output = $chipregs; ++ } ++ open(REG, ">$output") || die "Failed to open '$output': $!\n"; ++ my $oldfh = select REG; ++ main::logit "# Setting output" if $opts{o}; ++ return $oldfh; ++} ++ ++sub mysleep($) { ++ my $timeout = shift; ++ select(undef,undef,undef,$timeout); ++} ++ ++package FXS; ++ ++sub gen { ++ my $fmt = shift; ++ $| = 1; ++ printf "$fmt\n", @_; ++} ++ ++my @SlicNums; ++ ++sub write_to_slic_file($) { ++ my $write_str = shift; ++ ++ open(SLICS,">$chipregs") or ++ die("Failed writing to chipregs file $chipregs"); ++ print SLICS $write_str; ++ close(SLICS) or die "Failed writing '$write_str' to '$chipregs': $!"; ++ main::mysleep(0.001); ++ ++} ++ ++sub write_to_ring_register($) { ++ my $write_str = shift; ++ ++ open(SLICS,">$ring_registers") or ++ die("Failed writing to ring_registers file $ring_registers"); ++ print SLICS $write_str; ++ close(SLICS) or die "Failed writing '$write_str' to '$ring_registers': $!"; ++ main::mysleep(0.001); ++} ++ ++sub read_reg($$$;$) { ++ my $slic = shift; ++ my $addr = shift; ++ my $direct = shift; ++ my $bits_shift = shift; ++ $bits_shift = 0 unless defined $bits_shift; ++ my $addr_low; ++ my $addr_high; ++ main::debug("read_reg: $slic, $addr, $direct"); ++ $addr_low = $addr & 0xFF; ++ $addr_high = $addr >> 8; ++ ++ my $str; ++ if ($direct eq 'D') { ++ $str = sprintf "%s RD %02X", ++ $slic, $addr_low; ++ } else { ++ $str = sprintf "%s RR %02X %02X", ++ $slic, $addr_low, $addr_high; ++ } ++ write_to_slic_file($str); ++ ++ my $retries = 10; ++ my $reply = ""; ++ # If the command queue is long, we may need to wait... ++WAIT_RESULTS: ++ { ++ my @results; ++ ++ # The time to sleep is a tradeoff: ++ # - Too long is a waste of time. ++ # - Too short will cause many retries, wastes time. ++ # So the current value (after trial and error) is... ++ main::mysleep(0.013); ++ open(SLICS,$chipregs) or ++ die("Failed reading from chipregs file $chipregs"); ++ while(){ ++ s/#.*//; ++ next unless /\S/; ++ if ($direct eq 'D') { ++ @results = /^\s*(\d+)\s+[RW][DR]\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/; ++ } else { ++ @results = /^\s*(\d+)\s+[RW][DR]\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/; ++ } ++ if(($direct eq 'D' && @results != 4) || ($direct eq 'R' && @results != 7)) { ++ main::logit "Failed reading from '$chipregs' ($direct, $slic,$addr)"; ++ die; ++ } ++ } ++ close(SLICS); ++ my $read_addr; ++ if ($direct eq 'D') { ++ $read_addr = hex($results[1]); ++ } else { ++ $read_addr = hex(sprintf "0x$results[2]$results[1]"); ++ } ++ if($results[0] ne $slic || $read_addr ne $addr) { ++ # We read obsolete values, need to wait some more ++ if(--$retries) { ++ main::debug "$slic R$direct $addr -- retry (@results, $read_addr)"; ++ redo WAIT_RESULTS; ++ } else { ++ main::logit "Failed: $slic R$direct $addr returned @results, $addr"; ++ die; ++ } ++ } ++ # Good. ++ $results[0] = ""; ++ $results[1] = ""; ++ if ($direct eq 'R') { ++ $results[2] = ""; ++ } ++ foreach my $val (@results) { ++ $reply = sprintf("%s%s", $val, $reply); ++ } ++ $reply = hex(sprintf("0x%s", $reply)); ++ ++ } ++ return $reply >> $bits_shift; ++} ++ ++# TODO: rearange arguments ++sub write_reg{#($$$) { ++ my $slic = shift; ++ my $reg = shift; ++ my $val = shift; ++ ++ my $str = sprintf "%s WD %02X %02X", ++ $slic, $reg, $val; ++ main::debug("write_reg: $slic, $reg, $val"); ++ write_to_slic_file($str); ++} ++ ++# ++# BITS: ++# 3 - port num ++# 1 - read/write ++# 1 - Register / RAM ++# 11 - address ++# 29 - data ++sub write_ram($$$$) { ++ my $slic = shift; ++ my $addr = shift; ++ my $value = shift; ++ my $bits_shift = shift; ++ my $addr_low; ++ my $addr_high; ++ my $value_0; ++ my $value_1; ++ my $value_2; ++ my $value_3; ++ my $log_output = sprintf("write_ram: %s, %4d, 0x%08X", $slic, $addr, $value); ++ main::debug($log_output); ++ $value = $value << $bits_shift; ++ $addr_low = $addr & 0xFF; ++ $addr_high = $addr >> 8; ++ ++ $value_0 = $value & 0xFF; ++ $value >>= 8; ++ $value_1 = $value & 0xFF; ++ $value >>= 8; ++ $value_2 = $value & 0xFF; ++ $value >>= 8; ++ $value_3 = $value & 0xFF; ++ ++ my $str = sprintf "%s WR %02X %02X %02X %02X %02X %02X", ++ $slic, $addr_low, $addr_high, ++ $value_0, $value_1, $value_2, $value_3; ++ write_to_slic_file($str); ++} ++ ++sub set_user_mode { ++ my $slic = shift; ++ my $on = shift; ++ my $current = read_reg($slic, 0x7E, 'D'); ++ $current &= 0x1; ++ $on &= 0x1; ++ main::debug("::set_user_mode($slic, $on): " . $current . " -> " . $on . "\n"); ++ return 1 if $current == $on; ++ write_reg($slic, 126, 0x02); ++ write_reg($slic, 126, 0x08); ++ write_reg($slic, 126, 0x0E); ++ write_reg($slic, 126, 0x00); ++ return 1; ++} ++ ++sub init_early() { ++ # I/O Expander initialization ++ $expander_cmd = sprintf "echo 0A 00 0F %1d0 05 08 00 00 00 FF > %s", ++ $ENV{UNIT_NUMBER}, $command; # enable outputs for Greed LEDs ++ system("$expander_cmd"); ++ $expander_cmd = sprintf "echo 0A 00 0F %1d0 05 08 01 00 AA 55 > %s", ++ $ENV{UNIT_NUMBER}, $command; # enable outputs for Red LEDs and relays ++ system("$expander_cmd"); ++ $expander_cmd = sprintf "echo 0A 00 0F %1d0 05 08 0D 00 AA AA > %s", ++ $ENV{UNIT_NUMBER}, $command; # enable pull-ups for inputs ++ system("$expander_cmd"); ++} ++ ++sub load_patch($) { ++ my $slics_ref = shift; ++ my @slics = @{ $slics_ref }; ++ my $slic; ++ ++ main::debug "Loading patch based on si3226x_patch_C_TSS_ISO_2014JUN18.c"; ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 1); # Turn on user mode ++ } ++ write_reg('*', 81, 0x00); # JMPEN, disable the patch ++ ++ main::debug "=====Patch data======"; ++ my @patch_data_array = ( ++ 141541, ++ 540867, ++ 141541, ++ 543427, ++ 141541, ++ 553155, ++ 141541, ++ 577731, ++ 141541, ++ 579779, ++ 141541, ++ 581315, ++ 141541, ++ 592579, ++ 141541, ++ 633027, ++ 141541, ++ 637635, ++ 141541, ++ 639683, ++ 141541, ++ 650947, ++ 141541, ++ 651459, ++ 141541, ++ 651971, ++ 141541, ++ 652483, ++ 141541, ++ 652995, ++ 141541, ++ 653507, ++ 736, ++ 491712, ++ 452200, ++ 141541, ++ 491200, ++ 5733, ++ 524290, ++ 142565, ++ 550083, ++ 3685, ++ 519266, ++ 5220, ++ 144098, ++ 550083, ++ 3685, ++ 524291, ++ 141541, ++ 551619, ++ 5221, ++ 3682, ++ 524292, ++ 5, ++ 141541, ++ 135362, ++ 98021, ++ 727745, ++ 474213, ++ 17637, ++ 557251, ++ 101093, ++ 557251, ++ 473701, ++ 515653, ++ 843365, ++ 188002, ++ 843355, ++ 145125, ++ 560835, ++ 524290, ++ 660069, ++ 518053, ++ 517224, ++ 518244, ++ 142565, ++ 564419, ++ 524288, ++ 521733, ++ 843365, ++ 188002, ++ 524315, ++ 145125, ++ 568003, ++ 843365, ++ 522850, ++ 523387, ++ 147685, ++ 573123, ++ 522363, ++ 145125, ++ 575171, ++ 521826, ++ 141541, ++ 575683, ++ 518757, ++ 521826, ++ 141541, ++ 575683, ++ 521824, ++ 522245, ++ 522338, ++ 141541, ++ 716481, ++ 173669, ++ 523845, ++ 141541, ++ 730304, ++ 523877, ++ 141541, ++ 690368, ++ 614117, ++ 588995, ++ 457221, ++ 558181, ++ 457122, ++ 457333, ++ 143077, ++ 588995, ++ 144608, ++ 587971, ++ 524292, ++ 141541, ++ 588483, ++ 524304, ++ 671746, ++ 558181, ++ 410018, ++ 437365, ++ 143586, ++ 100034, ++ 141541, ++ 98498, ++ 550117, ++ 619715, ++ 558181, ++ 410018, ++ 403061, ++ 143077, ++ 619715, ++ 524290, ++ 143589, ++ 608963, ++ 402533, ++ 524290, ++ 400901, ++ 29189, ++ 431717, ++ 408133, ++ 432741, ++ 406085, ++ 392805, ++ 407621, ++ 792165, ++ 405573, ++ 406629, ++ 792133, ++ 408677, ++ 431680, ++ 432645, ++ 409189, ++ 392785, ++ 402949, ++ 141541, ++ 630979, ++ 560741, ++ 400482, ++ 398852, ++ 143077, ++ 615107, ++ 402533, ++ 398946, ++ 400901, ++ 29186, ++ 400389, ++ 141541, ++ 630979, ++ 400997, ++ 262242, ++ 143077, ++ 618691, ++ 524291, ++ 400901, ++ 29189, ++ 141541, ++ 630979, ++ 558181, ++ 407458, ++ 524309, ++ 694789, ++ 558085, ++ 694789, ++ 403045, ++ 524290, ++ 143077, ++ 630979, ++ 405605, ++ 792133, ++ 408165, ++ 431685, ++ 406117, ++ 432709, ++ 407653, ++ 392768, ++ 402949, ++ 694789, ++ 560645, ++ 694789, ++ 743525, ++ 119426, ++ 141541, ++ 1003201, ++ 560741, ++ 524290, ++ 143584, ++ 636099, ++ 141541, ++ 191682, ++ 694789, ++ 141541, ++ 859842, ++ 171109, ++ 170565, ++ 141541, ++ 963776, ++ 524291, ++ 144613, ++ 641731, ++ 199685, ++ 667365, ++ 644803, ++ 431717, ++ 197189, ++ 136805, ++ 198725, ++ 170597, ++ 262242, ++ 524291, ++ 144613, ++ 647875, ++ 170501, ++ 667365, ++ 886464, ++ 136805, ++ 180293, ++ 141541, ++ 886464, ++ 524293, ++ 524293, ++ 524293, ++ 524293, ++ 524293, ++ 524293, ++ ); ++ ++ write_ram('*', 1358, 0x00000000, 3); # PRAM_ADDR, reset the patch RAM address ++ foreach my $val (@patch_data_array) { ++ write_ram('*', 1359, $val, 12); # PRAM_DATA, shl 12, addr auto inc ++ } ++ ++ main::debug "=====Patch entries======"; # lowest 8 entries are registers ++ my @patch_entries_array = ( ++ 950, ++ 4347, ++ 3431, ++ 1425, ++ 1347, ++ 4287, ++ 4006, ++ 4469, ++ 1881, ++ 1720, ++ ); ++ ++ my $jmp_table_low = 82; ++ my $jmp_table_high = 1597; ++ foreach my $val (@patch_entries_array) { ++ last if $val == 0; ++ if ($jmp_table_low <= 97) { ++ write_reg('*', $jmp_table_low, $val & 0xFF);# JMPnLO ++ $jmp_table_low++; ++ write_reg('*', $jmp_table_low, $val >> 8 );# JMPnHI ++ $jmp_table_low++; ++ } else { ++ write_ram('*', $jmp_table_high, $val & 0x1FFF, 3); # shl 3 ++ $jmp_table_high++; ++ } ++ } ++ ++ write_ram('*', 448, 0x06182014, 3); # PATCH_ID, shl 3, a unique code which is a hash of the patch. ++ ++ main::debug "=====Patch support======"; ++ my @patch_support_addr_array = ( ++ 800, ++ 795, ++ 799, ++ 798, ++ 794, ++ 787, ++ 786, ++ 782, ++ 892, ++ 893, ++ 925, ++ 926, ++ 1014, ++ 1020, ++ 1021, ++ 1022, ++ 333, ++ 334, ++ 352, ++ ); ++ my @patch_support_data_array = ( ++ 0x200000, ++ 0x7D80000, ++ 0x69580EA, ++ 0x82C58C, ++ 0x1500000, ++ 0x0, ++ 0x320000, ++ 0x0, ++ 0x400000, ++ 0x0, ++ 0xA00000, ++ 0x1F00000, ++ 0x2D8000, ++ 0x0, ++ 0x2075F60, ++ 0x220335B, ++ 0x0, ++ 0x0, ++ 0x0, ++ ); ++ for (my $i = 0; $i < @patch_support_addr_array; $i++) { ++ my $addr = $patch_support_addr_array[$i]; ++ my $val = $patch_support_data_array[$i]; ++ write_ram('*', $addr, $val, 3); ++ } ++ ++ if ($settings{debug}) { ++ foreach $slic (@slics) { ++ main::debug "=====Verify patch======="; ++ my $read_val; ++ # PRAM_ADDR, reset the patch RAM address: ++ write_ram($slic, 1358, 0x00000000, 3); ++ foreach my $val (@patch_data_array) { ++ # PRAM_DATA, shr 12, addr auto inc ++ $read_val = read_reg($slic, 1359, 'R', 12); ++ if ($val != $read_val) { ++ printf "0x%X =? 0x%X\n", $val, $read_val; ++ printf "patch verification failed\n"; ++ exit 0; ++ } ++ } ++ main::debug "Patch has been verified!"; ++ ++ main::debug "=====Verify patch entries======="; ++ $jmp_table_low = 82; ++ $jmp_table_high = 1597; ++ foreach my $val (@patch_entries_array) { ++ last if $val == 0; ++ if ($jmp_table_low <= 97) { ++ $read_val = read_reg($slic, $jmp_table_low, 'D');# JMPnLO ++ $jmp_table_low++; ++ $read_val |= read_reg($slic, $jmp_table_low, 'D') << 8;# JMPnHI ++ $jmp_table_low++; ++ } else { ++ $read_val = read_reg($slic, $jmp_table_high, 'R', 3); # PRAM_DATA, shr 3 ++ $read_val &= 0x1FFF; ++ $jmp_table_high++; ++ } ++ if ($val != $read_val) { ++ printf "0x%X =? 0x%X\n", $val, $read_val; ++ printf "patch entries verification failed\n"; ++ exit 0; ++ } ++ } ++ main::debug "Patch entries has been verified!"; ++ ++ main::debug "=====Verify patch support======="; ++ for (my $i = 0; $i < @patch_support_addr_array; $i++) { ++ my $addr = $patch_support_addr_array[$i]; ++ my $val = $patch_support_data_array[$i]; ++ $read_val = read_reg($slic, $addr, 'R', 3); ++ if ($val != $read_val) { ++ printf "0x%X =? 0x%X\n", $val, $read_val; ++ printf "Patch support verification failed\n"; ++ exit 0; ++ } ++ } ++ main::debug "patch support has been verified!"; ++ } ++ } ++ ++ write_reg('*', 81, 0x01); # JMPEN, enable the patch ++ write_reg('*', 05, 0x00); # RAM_ADDR_HI, back to normal RAM access ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 0); # Turn off user mode ++ } ++} ++ ++sub load_general_params($) { ++ my $slics_ref = shift; ++ my @slics = @{ $slics_ref }; ++ my $slic; ++ ++ main::debug "Loading patch based on si3226x_patch_C_TSS_ISO_2014JUN18.c"; ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 1); # Turn on user mode ++ } ++ ++ write_reg('*', 47, 0x00); # ENHANCE ++ write_reg('*', 80, 0x2F); # AUTO ++ ++ write_ram('*', 764, 0x0050C480, 3); #BAT_HYST ++ # Ringing parameters 65Vrms 0Vdc 20Hz LPR ++ # Loop = 500.0 ft @ 0.044 ohms/ft, REN = 5, Rcpe = 600 ohms ++ # Rprot = 30 ohms, Type = LPR, Waveform = SINE ++ write_ram('*', 637, 0x15E5200E, 3); #ringing impedance = 100 ohms ++ write_ram('*', 766, 0xA3D705, 3); #VBATL_EXPECT 10 V ++ write_ram('*', 767, 0xA3D705, 3); #VBATH_EXPECT 10 V ++ write_ram('*', 768, 0x5ED285F, 3); #VBATR_EXPECT 92.6 V ++ write_ram('*', 768, 0xFFF0000, 3); #PWRSAVE_TIMER ++ write_ram('*', 916, 0x0F5C28F, 3); #OFFHOOK_THRESH ++ write_ram('*', 919, 0x00F00000, 3); #VBAT_TRACK_MIN ++ write_ram('*', 920, 0x02000000, 3); #VBAT_TRACK_MIN_RNG ++ write_ram('*', 970, 0x00800000, 3); #THERM_DBI ++ ++ write_ram('*', 1004, 0x00F18900, 3); #DCDC_VERR ++ write_ram('*', 1005, 0x0080C480, 3); #DCDC_VERR_HYST ++ write_ram('*', 1006, 0x00800000, 3); #DCDC_OITHRESH_LO ++ write_ram('*', 1007, 0x01F00000, 3); #DCDC_OITHRESH_HI ++ write_ram('*', 1540, 0x00200000, 3); #PD_UVLO ++ write_ram('*', 1541, 0x00300000, 3); #PD_OVLO ++ write_ram('*', 1542, 0x00200000, 3); #PD_OCLO ++ ++ write_ram('*', 1545, 0x00C00000, 3); #DCDC_UVHYST, (94v - 90v -1) / 0.257v = 12 ++ write_ram('*', 1546, 0x03D00000, 3); #DCDC_UVTHRESH, 94v / 1.543v = 61 ++ write_ram('*', 1547, 0x1200000, 3); #DCDC_OVTHRESH ++ ++ write_ram('*', 1554, 0x07700000, 3); #DCDC_UVPOL ++ ++ write_ram('*', 1558, 0x00000000, 3); #DCDC_VREF_CTRL ++ write_ram('*', 1560, 0x00200000, 3); #DCDC_RNGTYPE ++ write_ram('*', 1585, 0x00300000, 3); #DCDC_ANA_GAIN ++ write_ram('*', 1586, 0x00300000, 3); #DCDC_ANA_TOFF ++ write_ram('*', 1587, 0x00100000, 3); #DCDC_ANA_TONMIN ++ write_ram('*', 1588, 0x00FFC000, 3); #DCDC_ANA_TONMAX ++ write_ram('*', 1589, 0x00F00000, 3); #DCDC_ANA_DSHIFT ++ write_ram('*', 1590, 0x0FDA4000, 3); #DCDC_ANA_LPOLY ++ ++ write_ram('*', 759, 0x07FEB800, 3); # COEF_P_HVIC ++ write_ram('*', 756, 0x0048D15B, 3); # P_TH_HVIC ++ ++ write_ram('*', 967, 0x03A2E8BA, 3); # SCALE_KAUDIO ++ ++ # /* GC RAM locations that moved from RevB to RevC */ ++ write_ram('*', 1018, 0x03000000, 3); # LKG_OFHK_OFFSET ++ write_ram('*', 1017, 0x05000000, 3); # LKG_LB_OFFSET ++ write_ram('*', 1013, 0x02200000, 3); # VBATH_DELTA ++ write_ram('*', 1012, 0x03700000, 3); # UVTHRESH_MAX ++ write_ram('*', 1011, 0x04F80200, 3); # UVTHRESH_SCALE ++ write_ram('*', 1010, 0x00A23000, 3); # UVTHRESH_BIAS ++ ++ # /* Hardcoded mods to default settings */ ++ write_reg('*', 98, 0x80); #PDN ++ write_ram('*', 626, 0x723F235, 3); # ROW0_C2 ++ write_ram('*', 627, 0x57A9804, 3); # ROW1_C2 ++ write_ram('*', 918, 0x36000, 3); # XTALK_TIMER ++ write_ram('*', 1616, 0x1100000, 3); # DCDC_CPUMP_LP_MASK ++ ++ #/* Smart VOV Default Settings - set here in case no ring preset is loaded */ ++ write_ram('*', 973, 0xFFFFFF, 3); # VOV_DCDC_SLOPE ++ write_ram('*', 974, 0xA18937, 3); # VOV_DCDC_OS ++ write_ram('*', 975, 0xE49BA5, 3); # VOV_RING_BAT_MAX ++ ++ write_ram('*', 516, 0x10038D, 3); # VDIFFLPF ++ write_ram('*', 513, 0x4EDDB9, 3); # ILOOPLPF ++ write_ram('*', 514, 0x806D6, 3); # ILONGLPF ++ write_ram('*', 517, 0x10059F, 3); # VCMLPF ++ write_ram('*', 708, 0xF0000, 3); # CM_SPEEDUP_TIMER ++ write_ram('*', 709, 0x106240, 3); # VCM_TH ++ ++ # /* Prevent Ref Osc from powering down in PLL Freerun mode (pd_ref_osc) */ ++# write_ram('*', 709, 0x106240, 3); # PWRSAVE_CTRL_LO shall be arithmetic here ++ ++ # batType == VCM_HYST ++ write_ram('*', 1565, 0xC00000, 3); # ++ write_ram('*', 750, 0x0306280, 3); #VCM_HYST ++ write_ram('*', 971, 0x2A00000, 3); #LPR_SCALE ++ write_ram('*', 972, 0x061EB80, 3); #LPR_CM_OS ++ write_ram('*', 1565, 0x0A00000, 3); #DCDC_OIMASK ++ write_ram('*', 1643, 0x000000, 3); #DCDC_OV_DEBOUNCE ++ write_ram('*', 1641, 0x0D00000, 3); #DCDC_UV_DEBOUNCE ++ ++ write_ram('*', 1512, 0x00200000, 3); # PD_OFFLD_DAC ++ write_ram('*', 1513, 0x00200000, 3); # PD_OFFLD_GM ++ write_ram('*', 1592, 0x0300000, 3); #DCDC_PD_ANA ++ write_ram('*', 897, 0x0480CBF, 3); #P_TH_OFFLOAD ++ ++ write_reg('*', 35, 0x03); #OFFLOAD ++ ++ write_ram('*', 1553, 0x00000000, 3); #DCDC_SWDRV_POL ++ write_ram('*', 860, 0x008B9ACA, 3); # IRING_LIM (90.000 mA) ++ ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 0); # Turn on user mode ++ } ++ ++# Loading Coeff before cal to ensure accurate zsynth results in OHT ++# This set of coefficients are for the following input parameters: ++# Device = Si3217x, R1 = 600, R2 = 0, C = 0, R_surge = 20, R_fuse = 24, 10.txt ++# Generated on 9/30/2009 2:51:17 PM ++ # TXACEQ ++ write_ram('*', 540, 0x07F55480, 3); #TXACEQ_CO ++ write_ram('*', 541, 0x000D6400, 3); #TXACEQ_C1 ++ write_ram('*', 542, 0x00011A00, 3); #TXACEQ_C2 ++ write_ram('*', 543, 0x1FFD7F00, 3); #TXACEQ_C3 ++ ++ # RXACEQ ++ write_ram('*', 546, 0x07F04900, 3); #RXACEQ_CO ++ write_ram('*', 547, 0x00126A00, 3); #RXACEQ_C1 ++ write_ram('*', 548, 0x1FFE1D00, 3); #RXACEQ_C2 ++ write_ram('*', 549, 0x1FFC9480, 3); #RXACEQ_C3 ++ ++ # ECFIR/ECIIR ++ write_ram('*', 563, 0x0012A580, 3); #ECFIR_C2 ++ write_ram('*', 564, 0x1FE59900, 3); #ECFIR_C3 ++ write_ram('*', 565, 0x01BCB180, 3); #ECFIR_C4 ++ write_ram('*', 566, 0x00790780, 3); #ECFIR_C5 ++ write_ram('*', 567, 0x02113380, 3); #ECFIR_C6 ++ write_ram('*', 568, 0x1F172380, 3); #ECFIR_C7 ++ write_ram('*', 569, 0x00805080, 3); #ECFIR_C8 ++ write_ram('*', 570, 0x1FD6E600, 3); #ECFIR_C9 ++ write_ram('*', 571, 0x1FFDF800, 3); #ECIIR_B0 ++ write_ram('*', 572, 0x00010980, 3); #ECIIR_B1 ++ write_ram('*', 573, 0x0E46D280, 3); #ECIIR_A1 ++ write_ram('*', 574, 0x19B4F900, 3); #ECIIR_A2 ++ ++ # ZSYNTH ++ write_ram('*', 653, 0x007A8C00, 3); #ZSYNTH_B0 ++ write_ram('*', 654, 0x1F0BB880, 3); #ZSYNTH_B1 ++ write_ram('*', 655, 0x0079BD00, 3); #ZSYNTH_B2 ++ write_ram('*', 656, 0x0FF66D00, 3); #ZSYNTH_A1 ++ write_ram('*', 657, 0x18099080, 3); #ZSYNTH_A2 ++ ++ write_reg('*', 45, 0x59); #RA ++ ++ # TXGAIN/RXGAIN ++ write_ram('*', 544, 0x08769A80, 3); #TXACGAIN ++ write_ram('*', 545, 0x0141E080, 3); #RXACGAIN ++ write_ram('*', 906, 0x0141E080, 3); #RXACGAIN_SAVE ++ ++ # RXACHPF ++ write_ram('*', 658, 0x07AC0400, 3); #RXACHPF_B0_1 ++ write_ram('*', 659, 0x1853FC80, 3); #RXACHPF_B1_1 ++ write_ram('*', 660, 0x07580880, 3); #RXACHPF_A1_1 ++ ++ write_ram('*', 666, 0x8000000, 3); #RXACHPF_GAIN ++ ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 1); # Turn on user mode ++ } ++ write_reg('*', 98, 0x80); # Power up MADC ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 0); # Turn off user mode ++ } ++} ++ ++sub calibrate_slics($$$) { ++ my $cal0 = shift; ++ my $cal1 = shift; ++ my $cal2 = shift; ++ ++ main::debug "Calibrating channels @SlicNums"; ++ write_reg('*', 26, $cal0); # CAL0 ++ write_reg('*', 27, $cal1); # CAL1 ++ write_reg('*', 28, $cal2); # CAL2 ++ write_reg('*', 29, 0x80); # CAL3, CAL_EN ++ ++ # wait until all slics have finished calibration, or for timeout ++ # time periods in seconds: ++ my $sleep_time = 0.001; ++ my $timeout_time = 0.600; # Maximum from the spec ++ my @curr_slics = @SlicNums; ++ my $sleep_cnt = 0; ++CALIB_LOOP: ++ while(1) { ++ main::mysleep($sleep_time); ++ my @next_slics; ++ for my $slic (@curr_slics) { ++ my $val = read_reg($slic, 29, 'D'); ++ main::debug("checking slic $slic: $val."); ++ push(@next_slics, $slic) if ($val & 0x80) != 0; ++ } ++ @curr_slics = @next_slics; ++ last unless @curr_slics; ++ if ($sleep_cnt * $sleep_time > $timeout_time) { ++ main::logit("Auto Calibration: Exiting on timeout: $timeout_time."); ++ last CALIB_LOOP; ++ } ++ main::debug("auto_calibrate not done yet($sleep_cnt): @curr_slics"); ++ $sleep_cnt++; ++ } ++ #log_calib_params(); ++ ++} ++ ++sub dc_powerup($) { ++ my $slics_ref = shift; ++ my @slics = @{ $slics_ref }; ++ ++ foreach my $slic (@slics) { ++ FXS::set_user_mode($slic, 1); # Turn on user mode ++ } ++ write_ram('*', 1538, 0x700000, 3); # PD_DCDC, In case OV or UV previously occurred ++# write_ram('*', 1555, 0x100000, 3); # DCDC_CPUMP, Turn on charge pump ++ main::mysleep(0.010); ++# write_ram('*', 1538, 0x00600000, 3); # start up converter ++ main::mysleep(0.500); ++ write_ram('*', 1555, 0x000000, 3); # DCDC_CPUMP, Turn off charge pump ++ write_ram('*', 1542, 0x300000, 3); # PD_OCLO ++ write_ram('*', 1551, 0x00000000, 3); # sClear DCDC status ++ main::mysleep(0.030); ++ write_ram('*', 1538, 0x00400000, 3); ++ foreach my $slic (@slics) { ++ FXS::set_user_mode($slic, 0); # Turn off user mode ++ } ++} ++ ++sub read_defaults() { ++ if(XppConfig::read_config(\%settings)) { ++ main::logit "Defaults from $settings{xppconf}"; ++ } else { ++ main::logit "No defaults file, use hard-coded defaults."; ++ } ++} ++ ++sub soft_reset() { ++ write_reg('*', 1, 0x03); # RESET ++} ++ ++# Try to identify which slics are valid ++sub check_slics() { ++ my @slics; ++ main::debug "check_slics()"; ++ foreach my $slic (0 .. 7) { ++ my $value = read_reg($slic, 0, 'D'); ++ #main::logit sprintf "Slic($slic): RD 00 0x%X\n", $value; ++ next if($value != 0xC3); ++ write_reg($slic, 14, 0x40); ++ $value = read_reg($slic, 14, 'D'); ++ #main::logit sprintf "Slic($slic): RD 14 0x%X\n", $value; ++ next if($value != 0x40); ++ $value = read_reg($slic, 3, 'D') & 0x1F; ++ #main::logit sprintf "Slic($slic): RD 03 0x%X\n", $value; ++ push(@slics, $slic) if $value == 0x1F; ++ } ++ main::logit "Found " . scalar(@slics) . " SLICS (@slics)"; ++ return @slics; ++} ++ ++sub load_custom_preset($) { ++ my $slics_ref = shift; ++ my @slics = @{ $slics_ref }; ++ my $slic; ++ ++ main::debug "Loading patch based on si3226x_patch_C_TSS_ISO_2014JUN18.c"; ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 1); # Turn on user mode ++ } ++ write_ram('*', 755, 0x00050000, 3); #RTPER ++ write_ram('*', 844, 0x7EFE000, 3); #RINGFR = 20Hz ++ write_ram('*', 845, 0x00208847, 3); #RINGAMP = 53 Vrms open circuit with 100ohm ring impedance ++ write_ram('*', 846, 0x00000000, 3); #RINGPHAS ++ write_ram('*', 843, 0x00000000, 3); #RINGOF ++ write_ram('*', 637, 0x15E5200E, 3); #SLOPE_RING (100.000 ohms) ++ write_ram('*', 848, 0x007B9068, 3); #RTACTH (68.236 mA) ++ write_ram('*', 847, 0x0FFFFFFF, 3); #RTDCTH (450.000 mA) */ ++ write_ram('*', 850, 0x00006000, 3); #RTACDB (75.000 ms) ++ write_ram('*', 849, 0x00006000, 3); #RTDCDB (75.000 ms) ++ write_ram('*', 753, 0x00C49BA0, 3); # VOV_RING_BAT (12.000 v) ++ write_ram('*', 896, 0x00000000, 3); # VOV_RING_GND (0.000 v) ++ write_ram('*', 975, 0xE49BA5, 3);#vov_ring_bat_max = ~14V ++ ++ write_reg('*', 39, 0x80); #RINGTALO ++ write_reg('*', 40, 0x3E); #RINGTAHI ++ write_reg('*', 41, 0x00); #RINGTILO ++ write_reg('*', 42, 0x7D); #RINGTIHI ++ write_reg('*', 38, 0x80); #RINGCON Both timers are disabled; enable LPR ++ write_ram('*', 483, 0x28C000, 3);#delta_vcm: This means ring side needs 2v extra. ++ write_ram('*', 973, 0xFFFFFF, 3);# slope_vov_dcdc ++ write_ram('*', 974, 0xA18937, 3);# vov_dcdc_os = ~10v ++ write_ram('*', 509, 0x00C49BA0, 3);# VOV_RING_BAT (12.000 v) ++ write_ram('*', 975, 0xE49BA5, 3);#vov_ring_bat_max = ~14V ++ write_ram('*', 971, 0x2A00000, 3);# scale for LPR amplitude, full scale 28-bit ++ write_ram('*', 972, 0x61EB80, 3);# 6v CM offset ++ write_ram('*', 970, 0x800000, 3);# ++ ++ ++# DC_FEED: ++ write_ram('*', 634, 0x1C8A024C, 3); # SLOPE_VLIM ++ write_ram('*', 635, 0x1E3081AA, 3); # SLOPE_RFEED ++ write_ram('*', 636, 0x0040A0E0, 3); # SLOPE_ILIM ++ write_ram('*', 638, 0x1B27130B, 3); # SLOPE_DELTA1 ++ write_ram('*', 639, 0x1DD87A3E, 3); # SLOPE_DELTA2 ++ write_ram('*', 640, 0x034A1036, 3); # V_VLIM (28.000 v) ++ write_ram('*', 641, 0x03A446AC, 3); # V_RFEED (31.000 v) ++ write_ram('*', 642, 0x034A0E48, 3); # V_ILIM (28.000 v) ++ write_ram('*', 643, 0x01363429, 3); # CONST_RFEED (15.000 mA) ++ write_ram('*', 644, 0x0045CBC2, 3); # CONST_ILIM = 15 mA ++ write_ram('*', 645, 0x00222A30, 3); # I_VLIM = 0.000 mA ++ write_ram('*', 853, 0x005B0AFB, 3); # LCRONHK (10.000 mA) ++ write_ram('*', 852, 0x006D4060, 3); # LCROFFHK (12.000 mA) ++ write_ram('*', 701, 0x00008000, 3); # LCRDBI (5.000 ms) ++ write_ram('*', 858, 0x0048D595, 3); # LONGHITH (8.000 mA) ++ write_ram('*', 859, 0x003FBAE2, 3); # LONGLOTH (7.000 mA) ++ write_ram('*', 702, 0x00008000, 3); # LONGDBI (5.000 ms) ++ write_ram('*', 854, 0x000F0000, 3); # LCRMASK (150.000 ms) ++ write_ram('*', 855, 0x00080000, 3); # LCRMASK_POLREV (80.000 ms) ++ write_ram('*', 856, 0x00140000, 3); # LCRMASK_STATE (200.000 ms) ++ write_ram('*', 857, 0x00140000, 3); # LCRMASK_LINECAP (200.000 ms) ++ write_ram('*', 748, 0x01BA5E35, 3); # VCM_OH (27.000 v) ++ write_ram('*', 752, 0x0051EB85, 3); # VOV_BAT (5.000 v) ++ write_ram('*', 751, 0x00415F45, 3); # VOV_GND (3.990 v) ++ ++ write_reg('*', 46, 0x04); # zcal_en ++ write_reg('*', 23, 0x10); # DTMF_EN = 1 Enable Interupts in IRQ2 Register 19 ++ write_reg('*', 24, 0x03); # P_HVIC_IE = 1, P_THERM_IE = 1 Enable Interupts in IRQ3 Register 20 ++ ++ write_reg('*', 66, 0x00); # USERSTAT ++ write_reg('*', 71, 0x00); # DIAG1 ++ write_ram('*', 799, 95 * 1074 * 1000, 3); #PRAM_VBATH_NEON = -95 V ++ write_ram('*', 786, 70 * 65536, 3); #PRAM_LCRMASK_MWI = 70 mSec ++ ++ foreach $slic (@slics) { ++ FXS::set_linefeed($slic, 1); ++ } ++ write_ram('*', 918, 0x36000, 3); ++ ++ foreach $slic (@slics) { ++ FXS::set_user_mode($slic, 1); # Turn on user mode ++ } ++ write_ram('*', 1018, 0x03000000, 3); # LKG_OFHK_OFFSET ++ write_ram('*', 1017, 0x05000000, 3); # LKG_LB_OFFSET ++ ++ foreach $slic (@slics) { ++ if (($slic & 0x01) == 0) { ++ FXS::set_linefeed($slic, 0); ++ write_ram($slic, 1538, 0x00600000, 3); ++ } else { ++ write_ram($slic & 0xFE, 1538, 0x00400000, 3); ++ } ++ FXS::set_user_mode($slic, 0); # Turn off user mode ++ } ++} ++ ++sub configure_pcm($) { ++ my $slic = shift; ++ main::debug "Configure_pcm()"; ++ my $pcm_offset = $slic * 8; ++ write_reg($slic, 12, $pcm_offset); #PCMTXLO ++ write_reg($slic, 13, 0x00); #PCMTXHI ++ write_reg($slic, 14, $pcm_offset); #PCMTXLO ++ write_reg($slic, 15, 0x00); #PCMTXHI ++ ++ write_reg($slic, 11, 0x11); #PCMMODE, u-Law ++ ++# write_reg($slic, 43, 0x00); #LOOPBACK ++# write_reg($slic, 44, 0x00); #DIGCON ++} ++ ++sub set_linefeed($$) { ++ my $slic = shift; ++ my $lfd = shift; ++ write_reg($slic, 30, $lfd); #LINEFEED ++} ++ ++sub overwrite_ring_registers() { ++} ++ ++package main; ++ ++main::logit "Starting '$0' (@SlicNums)\n"; ++ ++FXS::read_defaults(); ++FXS::soft_reset(); ++@SlicNums = FXS::check_slics(); ++FXS::init_early(); ++FXS::load_patch(\@SlicNums); ++FXS::load_general_params(\@SlicNums); ++ ++if($settings{fxs_skip_calib}) { ++ main::logit "==== WARNING: SKIPPED SLIC CALIBRATION ====="; ++} else { ++ FXS::calibrate_slics(0x00, 0x00, 0x01); ++ main::mysleep(0.060); ++ FXS::dc_powerup(\@SlicNums); ++ FXS::calibrate_slics(0x00, 0xC0, 0x18); # remaining cals (except mads, lb) ++ main::mysleep(0.700); ++ foreach my $slic (@SlicNums) { ++ FXS::set_linefeed($slic, 0); ++ FXS::set_linefeed($slic, 1); ++ } ++ main::mysleep(1.000); ++ ++} ++FXS::load_custom_preset(\@SlicNums); ++foreach my $slic (@SlicNums) { ++ FXS::configure_pcm($slic); ++ FXS::set_linefeed($slic, 1); ++} ++ ++set_output; ++while() { ++ chomp; ++ s/[#;].*$//; # remove comments ++ s/^\s+//; # trim whitespace ++ s/\s+$//; # trim whitespace ++ s/\t+/ /g; # replace tabs with spaces (for logs) ++ next unless /\S/; # Skip empty lines ++ main::debug "writing: '$_'"; ++ print "$_\n"; ++} ++close REG; ++FXS::overwrite_ring_registers(); ++ ++main::debug "Ending '$0'"; ++close STDERR; ++exit 0; ++ ++# ----------------------------------==== 8-channel FXS unit initialization ===----------------------------------------- ++ ++__DATA__ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/mmapbus.c linux-source-4.19-dahdi/drivers/dahdi/xpp/mmapbus.c +--- linux-source-4.19/drivers/dahdi/xpp/mmapbus.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/mmapbus.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,91 @@ ++#include ++#include ++#include ++#include "mmapbus.h" ++ ++static int mmap_match(struct device *dev, struct device_driver *driver) ++{ ++ return !strncmp(dev_name(dev), driver->name, strlen(driver->name)); ++} ++ ++static int mmap_uevent(struct device *dev, char **envp, int num_envp, ++ char *buffer, int buffer_size) ++{ ++ envp[0] = buffer; ++ envp[1] = NULL; ++ return 0; ++} ++ ++static void mmap_bus_release(struct device *dev) ++{ ++} ++ ++static void mmap_dev_release(struct device *dev) ++{ ++} ++ ++static struct bus_type mmap_bus_type = { ++ .name = "mmap", ++ .match = mmap_match, ++ .uevent = mmap_uevent, ++}; ++ ++static struct device mmap_bus = { ++ .bus_id = "mmap0", ++ .release = mmap_bus_release, ++}; ++ ++int register_mmap_device(struct mmap_device *dev) ++{ ++ dev->dev.bus = &mmap_bus_type; ++ dev->dev.parent = &mmap_bus; ++ dev->dev.release = mmap_dev_release; ++ strncpy(dev->dev.bus_id, dev->name, BUS_ID_SIZE); ++ return device_register(&dev->dev); ++} ++EXPORT_SYMBOL(register_mmap_device); ++ ++void unregister_mmap_device(struct mmap_device *dev) ++{ ++ device_unregister(&dev->dev); ++} ++EXPORT_SYMBOL(unregister_mmap_device); ++ ++int register_mmap_driver(struct mmap_driver *driver) ++{ ++ driver->driver.bus = &mmap_bus_type; ++ return driver_register(&driver->driver); ++} ++EXPORT_SYMBOL(register_mmap_driver); ++ ++void unregister_mmap_driver(struct mmap_driver *driver) ++{ ++ driver_unregister(&driver->driver); ++} ++EXPORT_SYMBOL(unregister_mmap_driver); ++ ++int register_mmap_bus(void) ++{ ++ int ret = 0; ++ if ((ret = bus_register(&mmap_bus_type)) < 0) ++ goto bus_type_reg; ++ if ((ret = device_register(&mmap_bus)) < 0) ++ goto bus_reg; ++ return ret; ++ ++bus_reg: ++ bus_unregister(&mmap_bus_type); ++bus_type_reg: ++ return ret; ++} ++EXPORT_SYMBOL(register_mmap_bus); ++ ++void unregister_mmap_bus(void) ++{ ++ device_unregister(&mmap_bus); ++ bus_unregister(&mmap_bus_type); ++} ++EXPORT_SYMBOL(unregister_mmap_bus); ++ ++MODULE_AUTHOR("Alexander Landau "); ++MODULE_LICENSE("GPL"); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/mmapbus.h linux-source-4.19-dahdi/drivers/dahdi/xpp/mmapbus.h +--- linux-source-4.19/drivers/dahdi/xpp/mmapbus.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/mmapbus.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,26 @@ ++#ifndef MMAPBUS_H ++#define MMAPBUS_H ++ ++#include ++ ++struct mmap_device { ++ char *name; ++ struct mmap_driver *driver; ++ struct device dev; ++}; ++#define to_mmap_device(x) container_of(x, struct mmap_device, dev) ++ ++struct mmap_driver { ++ struct module *module; ++ struct device_driver driver; ++}; ++#define to_mmap_driver(x) container_of(x, struct mmap_driver, driver) ++ ++int register_mmap_bus(void); ++void unregister_mmap_bus(void); ++int register_mmap_device(struct mmap_device *dev); ++void unregister_mmap_device(struct mmap_device *dev); ++int register_mmap_driver(struct mmap_driver *driver); ++void unregister_mmap_driver(struct mmap_driver *driver); ++ ++#endif +diff -Nru linux-source-4.19/drivers/dahdi/xpp/mmapdrv.c linux-source-4.19-dahdi/drivers/dahdi/xpp/mmapdrv.c +--- linux-source-4.19/drivers/dahdi/xpp/mmapdrv.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/mmapdrv.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,640 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mmapbus.h" ++#include "xbus-core.h" ++#include "dahdi_debug.h" ++#include "xdefs.h" ++#include "xproto.h" ++#include "xframe_queue.h" ++ ++/* Check at compile time that sizeof(xframe_t) is a multiple of 4 */ ++typedef char ++ sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) == ++ 0) * 2 - 1]; ++ ++#define ssync() __builtin_bfin_ssync() ++ ++//#define AB_IN_BUF PF5 ++/* firmware pins */ ++#define DATA PG8 ++#define NCONFIG PG9 ++#define CONF_DONE PG10 ++#define DCLK PG11 ++#define NSTATUS PG12 ++ ++#ifdef DEBUG_VIA_GPIO ++/* ++ * For debugging we can use the following two pins. ++ * These two pins are not used *after initialization* ++ */ ++#define DEBUG_GPIO1 CONF_DONE ++#define DEBUG_GPIO2 NSTATUS ++ ++static int rx_intr_counter; ++#endif ++ ++#define FPGA_RX_IRQ IRQ_PF7 ++#define FPGA_TX_IRQ IRQ_PF4 ++#define FPGA_BASE_ADDR ((volatile char __iomem *)0x203FA800) ++ ++#define END_OF_FRAME 0x0001 ++#define GET_LEN 0x0002 ++#define START_RD_BURST 0x0008 ++/* stand alone Astribank without USB (Asterisk BlackFin Mode) */ ++#define AS_BF_MODE 0x0010 ++/* ++ * all data between Astribank and USB routed ++ * thru BF(EchoCanceler BlackFin Mode) ++ */ ++#define EC_BF_MODE 0x0020 ++/* Astribank worke with USB only (no BlackFin Mode) */ ++#define NO_BF_MODE 0x0040 ++#define SET_XA_DIR 0x0080 ++#define GET_XPD_STS 0x0100 ++#define GET_CHECKSUM 0x0200 ++ ++static const char rcsid[] = "$Id$"; ++ ++static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++static DEF_PARM(int, notxrx, 0, 0644, "Don't send or receive anything"); ++ ++struct counter { ++ long intr_min, intr_max; ++ long intr_avg, intr_count; ++}; ++ ++static xbus_t *global_xbus; ++static bool tx_ready = 1; ++static DEFINE_SPINLOCK(tx_ready_lock); ++static struct xframe_queue txpool; ++static unsigned int pcm_in_pool_count; ++static bool disconnecting; ++static struct kmem_cache *xframe_cache; ++static struct counter tx_counter, rx_counter; ++static unsigned long pcm_dropped; ++ ++static void print_buffer(const char *msg, const char *buf, int len) ++{ ++ int i; ++ printk(KERN_ERR "%s", msg); ++ for (i = 0; i < len; i++) ++ printk("%02X ", (unsigned char)buf[i]); ++ printk("\n"); ++} ++ ++static void update_counter(struct counter *c, struct timeval *tv1) ++{ ++ struct timeval tv2; ++ long diff; ++ do_gettimeofday(&tv2); ++ diff = usec_diff(&tv2, tv1); ++ if (c->intr_min > diff) ++ c->intr_min = diff; ++ if (c->intr_max < diff) ++ c->intr_max = diff; ++ c->intr_avg = ++ (c->intr_avg * c->intr_count + diff) / (c->intr_count + 1); ++ c->intr_count++; ++} ++ ++static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id) ++{ ++ unsigned short rxcnt; ++ xbus_t *xbus; ++ xframe_t *xframe; ++ __u8 *buf; ++ bool in_use = 0; ++ struct timeval tv1; ++ ++ do_gettimeofday(&tv1); ++ if (unlikely(disconnecting)) ++ return IRQ_HANDLED; ++ ++ xbus = xbus_num(global_xbus->num); ++ BUG_ON(!xbus); ++ if (!XBUS_GET(xbus)) { ++ if (printk_ratelimit()) ++ XBUS_ERR(xbus, "Dropping packet. Is shutting down.\n"); ++ goto out; ++ } ++ in_use = 1; ++ ++ outw(GET_LEN, FPGA_BASE_ADDR + 4); ++ rxcnt = inw(FPGA_BASE_ADDR); ++ if (rxcnt < 3) { ++ if (printk_ratelimit()) ++ NOTICE("Got %d bytes\n", rxcnt); ++ goto out; ++ } ++ if (rxcnt >= XFRAME_DATASIZE) { ++ if (printk_ratelimit()) ++ ERR("Bad rxcnt=%d\n", rxcnt); ++ goto out; ++ } ++ ++ xframe = ALLOC_RECV_XFRAME(xbus); ++ if (!xframe) { ++ if (printk_ratelimit()) ++ XBUS_ERR(xbus, "Empty receive_pool\n"); ++ goto out; ++ } ++ buf = xframe->packets; ++ atomic_set(&xframe->frame_len, rxcnt); ++ do_gettimeofday(&xframe->tv_received); ++#ifdef DEBUG_VIA_GPIO ++ if (rx_intr_counter & 1) ++ bfin_write_PORTGIO_SET(DEBUG_GPIO1); ++ else ++ bfin_write_PORTGIO_CLEAR(DEBUG_GPIO1); ++#endif ++ outw(START_RD_BURST, FPGA_BASE_ADDR + 4); ++ insw((unsigned long)FPGA_BASE_ADDR, buf, rxcnt / 2); ++#if 0 ++ for (count = 0; count < rxcnt; count += 2) { ++ unsigned short v = inw(FPGA_BASE_ADDR); ++ buf[count] = v & 0xFF; ++ buf[count + 1] = v >> 8; ++ } ++#endif ++ if (rxcnt & 1) ++ buf[rxcnt - 1] = inw(FPGA_BASE_ADDR); ++ /* ++ * Sanity check: length of first packet in frame ++ * should be no more than the frame length ++ */ ++ if (((buf[0] | (buf[1] << 8)) & 0x3FF) > rxcnt) { ++ if (printk_ratelimit()) { ++ ERR("Packet len=%d, frame len=%d\n", ++ (buf[0] | (buf[1] << 8)) & 0x3FF, rxcnt); ++ print_buffer("16 bytes of packet: ", buf, 16); ++ } ++ goto free; ++ } ++ if (debug && buf[2] != 0x12) ++ print_buffer("Received: ", buf, rxcnt); ++ if (!notxrx) { ++ xbus_receive_xframe(xbus, xframe); ++#ifdef DEBUG_VIA_GPIO ++ if (rx_intr_counter & 1) ++ bfin_write_PORTGIO_SET(DEBUG_GPIO2); ++ else ++ bfin_write_PORTGIO_CLEAR(DEBUG_GPIO2); ++#endif ++ goto out; ++ } ++free: ++ FREE_RECV_XFRAME(xbus, xframe); ++out: ++ if (in_use) ++ XBUS_PUT(xbus); ++#ifdef DEBUG_VIA_GPIO ++ rx_intr_counter++; ++#endif ++ update_counter(&rx_counter, &tv1); ++ return IRQ_HANDLED; ++} ++ ++static void send_buffer(unsigned char *buf, unsigned long len) ++{ ++ if (debug && len >= 3 && buf[2] != 0x11) ++ print_buffer("Sent: ", buf, len); ++ outsw((unsigned long)FPGA_BASE_ADDR, buf, len / 2); ++ if (len & 1) ++ outw((unsigned short)buf[len - 1], FPGA_BASE_ADDR); ++ outw(END_OF_FRAME, FPGA_BASE_ADDR + 4); ++} ++ ++static irqreturn_t xpp_mmap_tx_irq(int irq, void *dev_id) ++{ ++ unsigned long flags; ++ xbus_t *xbus; ++ xframe_t *xframe; ++ struct timeval tv1; ++ ++ do_gettimeofday(&tv1); ++ if (unlikely(disconnecting)) { ++ update_counter(&tx_counter, &tv1); ++ return IRQ_HANDLED; ++ } ++ spin_lock_irqsave(&tx_ready_lock, flags); ++ xframe = xframe_dequeue(&txpool); ++ if (!xframe) { ++ tx_ready = 1; ++ spin_unlock_irqrestore(&tx_ready_lock, flags); ++ update_counter(&tx_counter, &tv1); ++ return IRQ_HANDLED; ++ } ++ tx_ready = 0; ++ if (XPACKET_IS_PCM((xpacket_t *)xframe->packets)) ++ pcm_in_pool_count--; ++ spin_unlock_irqrestore(&tx_ready_lock, flags); ++ xbus = (xbus_t *)xframe->priv; ++ BUG_ON(!xbus); ++ xbus = xbus_num(xbus->num); ++ BUG_ON(!xbus); ++ send_buffer(xframe->packets, XFRAME_LEN(xframe)); ++ FREE_SEND_XFRAME(xbus, xframe); ++ update_counter(&tx_counter, &tv1); ++ return IRQ_HANDLED; ++} ++ ++static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm) ++{ ++ unsigned long flags; ++ if (unlikely(disconnecting)) { ++ FREE_SEND_XFRAME(xbus, xframe); ++ return -ENODEV; ++ } ++ if (unlikely(notxrx)) { ++ FREE_SEND_XFRAME(xbus, xframe); ++ return 0; ++ } ++ spin_lock_irqsave(&tx_ready_lock, flags); ++ if (tx_ready) { ++ tx_ready = 0; ++ send_buffer(xframe->packets, XFRAME_LEN(xframe)); ++ spin_unlock_irqrestore(&tx_ready_lock, flags); ++ FREE_SEND_XFRAME(xbus, xframe); ++ } else { ++ if (pcm && pcm_in_pool_count >= 1) { ++ static int rate_limit; ++ if ((rate_limit++ % 1000) == 0) ++ XBUS_ERR(xbus, ++ "Dropped PCM xframe " ++ "(pcm_in_pool_count=%d).\n", ++ pcm_in_pool_count); ++ FREE_SEND_XFRAME(xbus, xframe); ++ pcm_dropped++; ++ } else { ++ if (!xframe_enqueue(&txpool, xframe)) { ++ static int rate_limit; ++ spin_unlock_irqrestore(&tx_ready_lock, flags); ++ if ((rate_limit++ % 1000) == 0) ++ XBUS_ERR(xbus, ++ "Dropped xframe. " ++ "Cannot enqueue.\n"); ++ FREE_SEND_XFRAME(xbus, xframe); ++ return -E2BIG; ++ } ++ if (pcm) ++ pcm_in_pool_count++; ++ } ++ spin_unlock_irqrestore(&tx_ready_lock, flags); ++ } ++ return 0; ++} ++ ++static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) ++{ ++ xframe_t *xframe = kmem_cache_alloc(xframe_cache, gfp_flags); ++ if (!xframe) { ++ static int rate_limit; ++ if ((rate_limit++ % 1000) < 5) ++ XBUS_ERR(xbus, "frame allocation failed (%d)\n", ++ rate_limit); ++ return NULL; ++ } ++ xframe_init(xbus, xframe, ((__u8 *)xframe) + sizeof(xframe_t), ++ XFRAME_DATASIZE, xbus); ++ return xframe; ++} ++ ++static void free_xframe(xbus_t *xbus, xframe_t *xframe) ++{ ++ memset(xframe, 0, sizeof(*xframe)); ++ kmem_cache_free(xframe_cache, xframe); ++} ++ ++static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe) ++{ ++ return xframe_send_common(xbus, xframe, 1); ++} ++ ++static int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe) ++{ ++ return xframe_send_common(xbus, xframe, 0); ++} ++ ++static struct xbus_ops xmmap_ops = { ++ .xframe_send_pcm = xframe_send_pcm, ++ .xframe_send_cmd = xframe_send_cmd, ++ .alloc_xframe = alloc_xframe, ++ .free_xframe = free_xframe, ++}; ++ ++static int fill_proc_queue(char *p, struct xframe_queue *q) ++{ ++ int len; ++ ++ len = sprintf(p, ++ "%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d " ++ "worst_lag %02ld.%ld ms\n", ++ q->name, q->steady_state_count, q->count, q->max_count, ++ q->worst_count, q->overflows, q->worst_lag_usec / 1000, ++ q->worst_lag_usec % 1000); ++ xframe_queue_clearstats(q); ++ return len; ++} ++ ++static int fill_proc_counter(char *p, struct counter *c) ++{ ++ return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min, ++ c->intr_max, c->intr_avg, c->intr_count); ++} ++ ++static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, ++ int *eof, void *data) ++{ ++ int len = 0; ++ len += fill_proc_queue(page + len, &txpool); ++ len += sprintf(page + len, "pcm_in_pool_count=%d\n", pcm_in_pool_count); ++ len += sprintf(page + len, "pcm_dropped=%lu\n", pcm_dropped); ++ len += sprintf(page + len, "\nrx_counter:\n"); ++ len += fill_proc_counter(page + len, &rx_counter); ++ len += sprintf(page + len, "\ntx_counter:\n"); ++ len += fill_proc_counter(page + len, &tx_counter); ++ if (len <= off + count) { ++ *eof = 1; ++ tx_counter.intr_min = rx_counter.intr_min = INT_MAX; ++ tx_counter.intr_max = rx_counter.intr_max = 0; ++ tx_counter.intr_avg = rx_counter.intr_avg = 0; ++ tx_counter.intr_count = rx_counter.intr_count = 0; ++ } ++ *start = page + off; ++ len -= off; ++ if (len > count) ++ len = count; ++ if (len < 0) ++ len = 0; ++ return len; ++} ++ ++static int xpp_mmap_proc_write(struct file *file, const char __user *buffer, ++ unsigned long count, void *data) ++{ ++ int i = 0; ++ char *txchunk, *p, *endp; ++ ++ if (count >= XFRAME_DATASIZE * 3 + 10) ++ return -EINVAL; ++ p = txchunk = kmalloc(count + 1, GFP_KERNEL); ++ if (copy_from_user(txchunk, buffer, count)) { ++ count = -EFAULT; ++ goto out; ++ } ++ txchunk[count] = '\0'; ++ ++ while (*p) { ++ unsigned long value; ++ while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') ++ p++; ++ if (*p == '\0') ++ break; ++ value = simple_strtoul(p, &endp, 16); ++ if (endp == p || value > 0xFF) { ++ INFO("%s: Bad input\n", __func__); ++ count = -EINVAL; ++ goto out; ++ } ++ p = endp; ++ txchunk[i++] = (char)value; ++ } ++ send_buffer(txchunk, i); ++out: ++ kfree(txchunk); ++ return count; ++} ++ ++static struct mmap_driver astribank_driver = { ++ .module = THIS_MODULE, ++ .driver = { ++ .name = "xpp_mmap", ++ }, ++}; ++ ++static struct mmap_device astribank_dev = { ++ .name = "astribank0", ++ .driver = &astribank_driver, ++}; ++ ++static int __init xpp_mmap_load_fpga(u8 * data, size_t size) ++{ ++ size_t i; ++ /* set data, nconfig and dclk to port out */ ++ bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK); ++ bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DATA | NCONFIG | DCLK)); ++ /* set conf_done and nstatus to port in */ ++ bfin_write_PORTGIO_DIR( ++ bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS)); ++ bfin_write_PORTGIO_INEN( ++ bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK)); ++ bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() | CONF_DONE | NSTATUS); ++ ++ /* reset fpga during configuration holds nCONFIG low */ ++ bfin_write_PORTGIO_CLEAR(NCONFIG); ++ udelay(40); /* Tcfg ~40us delay */ ++ /* transition nCONFIG to high - reset end. */ ++ bfin_write_PORTGIO_SET(NCONFIG); ++ udelay(40); /* Tcf2ck ~40us delay */ ++ if (!(bfin_read_PORTGIO() & NSTATUS)) ++ return -EIO; /* report reset faill - Tcf2st1 pass */ ++ ++#if 0 ++ if (!(bfin_read_PORTGIO() & CONF_DONE)) ++ return -EIO; ++#endif ++ bfin_write_PORTGIO_CLEAR(DCLK); ++ for (i = 0; i < size; i++) { /* loop EP2OUT buffer data to FPGA */ ++ int j; ++ u8 __u8 = data[i]; ++ /* ++ * Send the configuration data through the DATA0 pin ++ * one bit at a time. ++ */ ++ for (j = 0; j < 8; j++) ++ { ++ if (__u8 & 1) ++ bfin_write_PORTGIO_SET(DATA); ++ else ++ bfin_write_PORTGIO_CLEAR(DATA); ++ __u8 >>= 1; ++ bfin_write_PORTGIO_SET(DCLK); ++ bfin_write_PORTGIO_CLEAR(DCLK); ++ } ++ if (!(bfin_read_PORTGIO() & NSTATUS)) ++ return -EIO; /* check the nSTATUS */ ++ } ++ bfin_write_PORTGIO_CLEAR(DATA); ++ udelay(1); ++ if (!(bfin_read_PORTGIO() & CONF_DONE)) ++ return -EIO; ++#ifdef DEBUG_VIA_GPIO ++ /* ++ * Normal initialization is done. Now we can reuse ++ * some pins that were used only during initialization ++ * to be used for debugging from now on. ++ */ ++ /* set to port out */ ++ bfin_write_PORTGIO_DIR( ++ bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2); ++ bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ++ ~(DEBUG_GPIO1 | DEBUG_GPIO2)); ++ bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ++ ~(DEBUG_GPIO1 | DEBUG_GPIO2)); ++#endif ++ udelay(40); /* tCD2UM - CONF_DONE high to user mode */ ++ return 0; ++} ++ ++static void __exit xpp_mmap_unload_fpga(void) ++{ ++ /* reset fpga during configuration holds nCONFIG low */ ++ bfin_write_PORTGIO_CLEAR(NCONFIG); ++ udelay(40); /* Tcfg ~40us delay */ ++ /* disable output pin */ ++ bfin_write_PORTGIO_DIR( ++ bfin_read_PORTGIO_DIR() & ~(DATA | NCONFIG | DCLK)); ++ /* disable input buffer */ ++ bfin_write_PORTGIO_INEN( ++ bfin_read_PORTGIO_INEN() & ~(CONF_DONE | NSTATUS)); ++ INFO("FPGA Firmware unloaded\n"); ++} ++ ++static int __init xpp_mmap_load_firmware(void) ++{ ++ const struct firmware *fw; ++ int ret; ++ if ((ret = ++ request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0) ++ return ret; ++ xpp_mmap_load_fpga(fw->data, fw->size); ++ release_firmware(fw); ++ return ret; ++} ++ ++static int __init xpp_mmap_init(void) ++{ ++ int ret; ++ struct proc_dir_entry *proc_entry; ++ ++ if ((ret = register_mmap_bus()) < 0) ++ goto bus_reg; ++ if ((ret = register_mmap_driver(&astribank_driver)) < 0) ++ goto driver_reg; ++ if ((ret = register_mmap_device(&astribank_dev)) < 0) ++ goto dev_reg; ++ if ((ret = xpp_mmap_load_firmware()) < 0) { ++ ERR("xpp_mmap_load_firmware() failed, errno=%d\n", ret); ++ goto fail_fw; ++ } ++ ++ if ((ret = ++ request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING, ++ "xpp_mmap_rx", NULL)) < 0) { ++ ERR("Unable to attach to RX interrupt %d\n", FPGA_RX_IRQ); ++ goto fail_irq_rx; ++ } ++ if ((ret = ++ request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING, ++ "xpp_mmap_tx", NULL)) < 0) { ++ ERR("Unable to attach to TX interrupt %d\n", FPGA_TX_IRQ); ++ goto fail_irq_tx; ++ } ++ if (!request_region((resource_size_t) FPGA_BASE_ADDR, 8, "xpp_mmap")) { ++ ERR("Unable to request memory region at %p\n", FPGA_BASE_ADDR); ++ goto fail_region; ++ } ++ outw(AS_BF_MODE, FPGA_BASE_ADDR + 4); ++ ++ xframe_cache = ++ kmem_cache_create("xframe_cache", ++ sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0, ++ NULL); ++ if (!xframe_cache) { ++ ret = -ENOMEM; ++ goto fail_cache; ++ } ++ /* interface with Dahdi */ ++ global_xbus = xbus_new(&xmmap_ops, XFRAME_DATASIZE, NULL); ++ if (!global_xbus) { ++ ret = -ENOMEM; ++ goto fail_xbus; ++ } ++ strncpy(global_xbus->connector, "mmap", XBUS_DESCLEN); ++ strncpy(global_xbus->label, "mmap:0", LABEL_SIZE); ++ ++ xframe_queue_init(&txpool, 10, 200, "mmap_txpool", global_xbus); ++ if (! ++ (proc_entry = ++ create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) { ++ ERR("create_proc_entry() failed\n"); ++ ret = -EINVAL; ++ goto fail_proc; ++ } ++ proc_entry->write_proc = xpp_mmap_proc_write; ++ proc_entry->read_proc = xpp_mmap_proc_read; ++ /* Go xbus, go! */ ++ xbus_connect(global_xbus); ++ INFO("xpp_mmap module loaded\n"); ++ ++ return 0; ++ ++fail_proc: ++ xbus_disconnect(global_xbus); ++fail_xbus: ++ kmem_cache_destroy(xframe_cache); ++fail_cache: ++ release_region((resource_size_t) FPGA_BASE_ADDR, 8); ++fail_region: ++ free_irq(FPGA_TX_IRQ, NULL); ++fail_irq_tx: ++ free_irq(FPGA_RX_IRQ, NULL); ++fail_irq_rx: ++fail_fw: ++ unregister_mmap_device(&astribank_dev); ++dev_reg: ++ unregister_mmap_driver(&astribank_driver); ++driver_reg: ++ unregister_mmap_bus(); ++bus_reg: ++ return ret; ++} ++ ++static void __exit xpp_mmap_exit(void) ++{ ++ xbus_t *xbus; ++ DBG(GENERAL, "\n"); ++ disconnecting = 1; ++ xbus = xbus_num(global_xbus->num); ++ remove_proc_entry("xpp_mmap", xbus->proc_xbus_dir); ++ xframe_queue_clear(&txpool); ++ xbus_disconnect(xbus); ++ kmem_cache_destroy(xframe_cache); ++ ++ release_region((resource_size_t) FPGA_BASE_ADDR, 8); ++ free_irq(FPGA_RX_IRQ, NULL); ++ free_irq(FPGA_TX_IRQ, NULL); ++ ++ unregister_mmap_device(&astribank_dev); ++ unregister_mmap_driver(&astribank_driver); ++ unregister_mmap_bus(); ++ xpp_mmap_unload_fpga(); ++ INFO("xpp_mmap module unloaded\n"); ++} ++ ++module_init(xpp_mmap_init); ++module_exit(xpp_mmap_exit); ++MODULE_AUTHOR("Alexander Landau "); ++MODULE_LICENSE("GPL"); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/param_doc linux-source-4.19-dahdi/drivers/dahdi/xpp/param_doc +--- linux-source-4.19/drivers/dahdi/xpp/param_doc 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/param_doc 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,40 @@ ++#! /usr/bin/perl -w ++use strict; ++# ++# Extract parameter documentation from *.ko files. ++# Assumes that parameter description include the default ++# value in the format we use in our DEF_PARM() macro ++# ++ ++@ARGV || die "Usage: $0 module.ko....\n"; ++ ++my $modinfo = '/sbin/modinfo'; ++my @mod_params; ++ ++foreach my $file (glob "@ARGV") { ++ undef @mod_params; ++ print "$file:\n"; ++ open(F, "$modinfo '$file' |") || die; ++ while() { ++ chomp; ++ next unless s/^parm:\s*//; ++ my ($name, $description) = split(/:/, $_, 2); ++ # Extract type ++ $description =~ s/\s*\(([^)]+)\)$//; ++ my $type = $1; ++ # Extract default value ++ $description =~ s/\s*\[default\s+([^]]+)\]$//; ++ my $default = $1; ++ push(@mod_params, { ++ NAME => $name, ++ TYPE => $type, ++ DEFVAL => $default, ++ DESC => $description, ++ }); ++ } ++ # Print sorted list ++ foreach my $p (sort { $a->{NAME} cmp $b->{NAME} } @mod_params) { ++ printf "\t%-8s %-22s = %-20s %s\n", $p->{TYPE}, $p->{NAME}, $p->{DEFVAL}, $p->{DESC}; ++ } ++ close F || die; ++} +diff -Nru linux-source-4.19/drivers/dahdi/xpp/parport_debug.c linux-source-4.19-dahdi/drivers/dahdi/xpp/parport_debug.c +--- linux-source-4.19/drivers/dahdi/xpp/parport_debug.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/parport_debug.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,108 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2007, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "parport_debug.h" ++ ++static struct parport *debug_sync_parport; ++static int parport_toggles[8]; /* 8 bit flip-flop */ ++ ++void flip_parport_bit(unsigned char bitnum) ++{ ++ static unsigned char last_value; ++ DEFINE_SPINLOCK(lock); ++ unsigned long flags; ++ unsigned char mask; ++ unsigned char value; ++ ++ if (!debug_sync_parport) { ++ if (printk_ratelimit()) { ++ printk(KERN_NOTICE "%s: no debug parallel port\n", ++ THIS_MODULE->name); ++ } ++ return; ++ } ++ BUG_ON(bitnum > 7); ++ mask = 1 << bitnum; ++ spin_lock_irqsave(&lock, flags); ++ value = last_value & ~mask; ++ if (parport_toggles[bitnum] % 2) /* square wave */ ++ value |= mask; ++ last_value = value; ++ parport_toggles[bitnum]++; ++ spin_unlock_irqrestore(&lock, flags); ++ parport_write_data(debug_sync_parport, value); ++} ++EXPORT_SYMBOL(flip_parport_bit); ++ ++static void parport_attach(struct parport *port) ++{ ++ printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name, ++ port->name); ++ if (debug_sync_parport) { ++ printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n", ++ THIS_MODULE->name, debug_sync_parport->name, port->name); ++ return; ++ } ++ parport_get_port(port); ++ debug_sync_parport = port; ++} ++ ++static void parport_detach(struct parport *port) ++{ ++ printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name); ++ if (debug_sync_parport != port) { ++ printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n", ++ THIS_MODULE->name, debug_sync_parport->name, port->name); ++ return; ++ } ++ parport_put_port(debug_sync_parport); ++ debug_sync_parport = NULL; ++} ++ ++static struct parport_driver debug_parport_driver = { ++ .name = "parport_debug", ++ .attach = parport_attach, ++ .detach = parport_detach, ++}; ++ ++int __init parallel_dbg_init(void) ++{ ++ int ret; ++ ++ ret = parport_register_driver(&debug_parport_driver); ++ return ret; ++} ++ ++void __exit parallel_dbg_cleanup(void) ++{ ++ parport_unregister_driver(&debug_parport_driver); ++} ++ ++MODULE_DESCRIPTION("Use parallel port to debug drivers"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++ ++module_init(parallel_dbg_init); ++module_exit(parallel_dbg_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/parport_debug.h linux-source-4.19-dahdi/drivers/dahdi/xpp/parport_debug.h +--- linux-source-4.19/drivers/dahdi/xpp/parport_debug.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/parport_debug.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,31 @@ ++#ifndef PARPORT_DEBUG_H ++#define PARPORT_DEBUG_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2007, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ */ ++ ++#ifdef DEBUG_SYNC_PARPORT ++void flip_parport_bit(unsigned char bitnum); ++#else ++#define flip_parport_bit(bitnum) ++#endif ++ ++#endif /* PARPORT_DEBUG_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/print_fxo_modes.c linux-source-4.19-dahdi/drivers/dahdi/xpp/print_fxo_modes.c +--- linux-source-4.19/drivers/dahdi/xpp/print_fxo_modes.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/print_fxo_modes.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,37 @@ ++#include ++ ++int main(int argc, char *argv[]) ++{ ++ size_t i; ++ ++ for (i = 0; i < (sizeof(fxo_modes) / sizeof(struct fxo_mode)); i++) { ++ if (fxo_modes[i].name == NULL) ++ break; ++ int reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0x20; ++ char ring_osc[BUFSIZ] = "", ring_x[BUFSIZ] = ""; ++ ++ reg16 |= (fxo_modes[i].ohs << 6); ++ reg16 |= (fxo_modes[i].rz << 1); ++ reg16 |= (fxo_modes[i].rt); ++ ++ reg26 |= (fxo_modes[i].dcv << 6); ++ reg26 |= (fxo_modes[i].mini << 4); ++ reg26 |= (fxo_modes[i].ilim << 1); ++ ++ reg30 = (fxo_modes[i].acim); ++ ++ reg31 |= (fxo_modes[i].ohs2 << 3); ++ ++ if (fxo_modes[i].ring_osc) ++ snprintf(ring_osc, BUFSIZ, "ring_osc=%04X", ++ fxo_modes[i].ring_osc); ++ if (fxo_modes[i].ring_x) ++ snprintf(ring_x, BUFSIZ, "ring_x=%04X", ++ fxo_modes[i].ring_x); ++ printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\t" ++ "reg31=%02X\t%s\t%s\n", ++ fxo_modes[i].name, reg16, reg26, reg30, reg31, ++ ring_osc, ring_x); ++ } ++ return 0; ++} +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xbus-core.c linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-core.c +--- linux-source-4.19/drivers/dahdi/xpp/xbus-core.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-core.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,2119 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 ++#include ++#ifdef PROTOCOL_DEBUG ++#include ++#endif ++#include ++#include ++#include /* for msleep() to debug */ ++#include "xpd.h" ++#include "xpp_dahdi.h" ++#include "xbus-core.h" ++#include "card_global.h" ++#include "dahdi_debug.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++/* Defines */ ++#define INITIALIZATION_TIMEOUT (90*HZ) /* in jiffies */ ++#define PROC_XBUSES "xbuses" ++#define PROC_XBUS_SUMMARY "summary" ++ ++#ifdef PROTOCOL_DEBUG ++#ifdef CONFIG_PROC_FS ++#define PROC_XBUS_COMMAND "command" ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_xbus_command_ops; ++#else ++static const struct file_operations proc_xbus_command_ops; ++#endif ++#endif ++#endif ++ ++/* Command line parameters */ ++extern int debug; ++static DEF_PARM(uint, command_queue_length, 1500, 0444, ++ "Maximal command queue length"); ++static DEF_PARM(uint, poll_timeout, 1000, 0644, ++ "Timeout (in jiffies) waiting for units to reply"); ++static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets"); ++static DEF_PARM_BOOL(dahdi_autoreg, 0, 0444, ++ "Register devices automatically (1) or not (0). UNUSED."); ++ ++#ifdef CONFIG_PROC_FS ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops xbus_read_proc_ops; ++#else ++static const struct file_operations xbus_read_proc_ops; ++#endif ++#endif ++static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ++ ushort max_send_size, ++ struct device *transport_device, void *priv); ++static void transport_destroy(xbus_t *xbus); ++ ++/* Data structures */ ++static DEFINE_SPINLOCK(xbuses_lock); ++#ifdef CONFIG_PROC_FS ++static struct proc_dir_entry *proc_xbuses; ++#endif ++ ++static struct xbus_desc { ++ xbus_t *xbus; ++ int shutting_down; ++} xbuses_array[MAX_BUSES]; ++ ++static int xbus_is_shutting_down(int num) ++{ ++ return xbuses_array[num].shutting_down; ++} ++ ++static xbus_t *xbus_byhwid(const char *hwid) ++{ ++ int i; ++ xbus_t *xbus; ++ ++ for (i = 0; i < ARRAY_SIZE(xbuses_array); i++) { ++ xbus = xbuses_array[i].xbus; ++ if (xbus && strcmp(hwid, xbus->label) == 0) ++ return xbus; ++ } ++ return NULL; ++} ++ ++int xbus_check_unique(xbus_t *xbus) ++{ ++ if (!xbus) ++ return -ENOENT; ++ if (xbus->label && *(xbus->label)) { ++ xbus_t *xbus_old; ++ ++ XBUS_DBG(DEVICES, xbus, "Checking LABEL='%s'\n", xbus->label); ++ xbus_old = xbus_byhwid(xbus->label); ++ if (xbus_old && xbus_old != xbus) { ++ XBUS_NOTICE(xbus_old, ++ "Duplicate LABEL='%s'. Leave %s unused. " ++ "refcount_xbus=%d\n", ++ xbus_old->label, xbus->busname, ++ refcount_xbus(xbus_old)); ++ return -EBUSY; ++ } ++ } else { ++ XBUS_NOTICE(xbus, "Missing board label (old Astribank?)\n"); ++ } ++ return 0; ++} ++ ++const char *xbus_statename(enum xbus_state st) ++{ ++ switch (st) { ++ case XBUS_STATE_START: ++ return "START"; ++ case XBUS_STATE_IDLE: ++ return "IDLE"; ++ case XBUS_STATE_SENT_REQUEST: ++ return "SENT_REQUEST"; ++ case XBUS_STATE_RECVD_DESC: ++ return "RECVD_DESC"; ++ case XBUS_STATE_READY: ++ return "READY"; ++ case XBUS_STATE_DEACTIVATING: ++ return "DEACTIVATING"; ++ case XBUS_STATE_DEACTIVATED: ++ return "DEACTIVATED"; ++ case XBUS_STATE_FAIL: ++ return "FAIL"; ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(xbus_statename); ++ ++static void init_xbus(uint num, xbus_t *xbus) ++{ ++ struct xbus_desc *desc; ++ ++ BUG_ON(num >= ARRAY_SIZE(xbuses_array)); ++ desc = &xbuses_array[num]; ++ desc->xbus = xbus; ++ if (xbus) ++ desc->shutting_down = 0; ++} ++ ++xbus_t *xbus_num(uint num) ++{ ++ struct xbus_desc *desc; ++ ++ if (num >= ARRAY_SIZE(xbuses_array)) ++ return NULL; ++ desc = &xbuses_array[num]; ++ return desc->xbus; ++} ++EXPORT_SYMBOL(xbus_num); ++ ++static void initialize_xbuses_array(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(xbuses_array); i++) ++ init_xbus(i, NULL); ++} ++ ++static void finalize_xbuses_array(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(xbuses_array); i++) { ++ if (xbuses_array[i].xbus != NULL) { ++ ERR("%s: xbus #%d is not NULL\n", __func__, i); ++ BUG(); ++ } ++ } ++} ++ ++/* ++ * Called by put_xbus() when XBUS has no more references. ++ */ ++static void xbus_destroy(struct kref *kref) ++{ ++ xbus_t *xbus; ++ int num; ++ ++ xbus = kref_to_xbus(kref); ++ XBUS_DBG(DEVICES, xbus, "%s\n", __func__); ++ num = xbus->num; ++ xbuses_array[num].shutting_down = 1; ++ xbus_sysfs_remove(xbus); ++} ++ ++xbus_t *get_xbus(const char *msg, uint num) ++{ ++ unsigned long flags; ++ xbus_t *xbus; ++ ++ if (xbus_is_shutting_down(num)) { ++ DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n", __func__, ++ msg, num); ++ return NULL; ++ } ++ spin_lock_irqsave(&xbuses_lock, flags); ++ xbus = xbus_num(num); ++ if (xbus != NULL) { ++ kref_get(&xbus->kref); ++ XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n", msg, ++ refcount_xbus(xbus)); ++ } ++ spin_unlock_irqrestore(&xbuses_lock, flags); ++ return xbus; ++} ++ ++void put_xbus(const char *msg, xbus_t *xbus) ++{ ++ if (xbus_is_shutting_down(xbus->num)) { ++ if (!refcount_xbus(xbus)) { ++ DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n", ++ __func__, msg, xbus->num); ++ return; ++ } ++ } ++ XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n", msg, ++ refcount_xbus(xbus)); ++ kref_put(&xbus->kref, xbus_destroy); ++} ++ ++int refcount_xbus(xbus_t *xbus) ++{ ++ struct kref *kref = &xbus->kref; ++ ++ return refcount_read(&kref->refcount); ++} ++ ++/*------------------------- Frame Handling ------------------------*/ ++ ++void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, ++ void *priv) ++{ ++ memset(xframe, 0, sizeof(*xframe)); ++ INIT_LIST_HEAD(&xframe->frame_list); ++ xframe->priv = priv; ++ xframe->xbus = xbus; ++ xframe->packets = xframe->first_free = buf; ++ xframe->frame_maxlen = maxsize; ++ atomic_set(&xframe->frame_len, 0); ++ xframe->kt_created = ktime_get(); ++ xframe->xframe_magic = XFRAME_MAGIC; ++} ++EXPORT_SYMBOL(xframe_init); ++ ++/* ++ * Return pointer to next packet slot in the frame ++ * or NULL if the frame is full. ++ * ++ * FIXME: we do not use atomic_add_return() because kernel-2.6.8 ++ * does not have it. This make this code a little racy, ++ * but we currently call xframe_next_packet() only in the ++ * PCM loop (xbus_tick() etc.) ++ */ ++xpacket_t *xframe_next_packet(xframe_t *frm, int len) ++{ ++ int newlen = XFRAME_LEN(frm); ++ ++ newlen += len; ++#if 0 ++ DBG(GENERAL, "len=%d, newlen=%d, frm->frame_len=%d\n", ++ len, newlen, XFRAME_LEN(frm)); ++#endif ++ if (newlen > XFRAME_DATASIZE) ++ return NULL; ++ atomic_add(len, &frm->frame_len); ++ return (xpacket_t *)(frm->packets + newlen - len); ++} ++EXPORT_SYMBOL(xframe_next_packet); ++ ++static DEFINE_SPINLOCK(serialize_dump_xframe); ++ ++static void do_hexdump(const char msg[], __u8 *data, uint16_t len) ++{ ++ int i; ++ int debug = DBG_ANY; /* mask global debug */ ++ ++ for (i = 0; i < len; i++) ++ DBG(ANY, "%s: %3d> %02X\n", msg, i, data[i]); ++} ++ ++void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, ++ int debug) ++{ ++ const uint16_t frm_len = XFRAME_LEN(xframe); ++ xpacket_t *pack; ++ uint16_t pos = 0; ++ uint16_t nextpos; ++ int num = 1; ++ bool do_print; ++ unsigned long flags; ++ ++ if (xframe->xframe_magic != XFRAME_MAGIC) { ++ XBUS_ERR(xbus, "%s: bad xframe_magic %lX\n", __func__, ++ xframe->xframe_magic); ++ return; ++ } ++ spin_lock_irqsave(&serialize_dump_xframe, flags); ++ do { ++ if (pos >= xbus->transport.max_send_size) { ++ if (printk_ratelimit()) { ++ XBUS_NOTICE(xbus, ++ "%s: xframe overflow (%d bytes)\n", ++ msg, frm_len); ++ do_hexdump(msg, xframe->packets, frm_len); ++ } ++ break; ++ } ++ if (pos > frm_len) { ++ if (printk_ratelimit()) { ++ XBUS_NOTICE(xbus, ++ "%s: packet overflow pos=%d " ++ "frame_len=%d\n", ++ msg, pos, frm_len); ++ do_hexdump(msg, xframe->packets, frm_len); ++ } ++ break; ++ } ++ pack = (xpacket_t *)&xframe->packets[pos]; ++ if (XPACKET_LEN(pack) <= 0) { ++ if (printk_ratelimit()) { ++ XBUS_NOTICE(xbus, ++ "%s: xframe -- bad packet_len=%d " ++ "pos=%d frame_len=%d\n", ++ msg, XPACKET_LEN(pack), pos, frm_len); ++ do_hexdump(msg, xframe->packets, frm_len); ++ } ++ break; ++ } ++ nextpos = pos + XPACKET_LEN(pack); ++ if (nextpos > frm_len) { ++ if (printk_ratelimit()) { ++ XBUS_NOTICE(xbus, ++ "%s: packet overflow nextpos=%d " ++ "frame_len=%d\n", ++ msg, nextpos, frm_len); ++ do_hexdump(msg, xframe->packets, frm_len); ++ } ++ break; ++ } ++ do_print = 0; ++ if (debug == DBG_ANY) ++ do_print = 1; ++ else if (XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_READ) ++ && XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_WRITE)) ++ do_print = 1; ++ else if (debug & DBG_PCM) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) ++ do_print = 1; ++ } ++ if (do_print) { ++ if (num == 1) { ++ XBUS_DBG(ANY, xbus, "%s: frame_len=%d. %s\n", ++ msg, frm_len, (XPACKET_IS_PCM(pack)) ++ ? "(IS_PCM)" : ""); ++ } ++ XBUS_DBG(ANY, xbus, ++ " %3d. DATALEN=%d pcm=%d slot=%d OP=0x%02X " ++ "XPD-%d%d (pos=%d)\n", ++ num, XPACKET_LEN(pack), XPACKET_IS_PCM(pack), ++ XPACKET_PCMSLOT(pack), XPACKET_OP(pack), ++ XPACKET_ADDR_UNIT(pack), ++ XPACKET_ADDR_SUBUNIT(pack), pos); ++ dump_packet(" ", pack, debug); ++ } ++ num++; ++ pos = nextpos; ++ if (pos >= frm_len) ++ break; ++ } while (1); ++ spin_unlock_irqrestore(&serialize_dump_xframe, flags); ++} ++EXPORT_SYMBOL(dump_xframe); ++ ++/** ++ * ++ * Frame is freed: ++ * - In case of error, by this function. ++ * - Otherwise, by the underlying sending mechanism ++ */ ++int send_pcm_frame(xbus_t *xbus, xframe_t *xframe) ++{ ++ struct xbus_ops *ops; ++ int ret = -ENODEV; ++ ++ BUG_ON(!xframe); ++ if (!XBUS_IS(xbus, READY)) { ++ XBUS_ERR(xbus, ++ "Dropped a pcm frame -- hardware is not ready.\n"); ++ ret = -ENODEV; ++ goto error; ++ } ++ ops = transportops_get(xbus); ++ BUG_ON(!ops); ++ ret = ops->xframe_send_pcm(xbus, xframe); ++ transportops_put(xbus); ++ if (ret) ++ XBUS_COUNTER(xbus, TX_BYTES) += XFRAME_LEN(xframe); ++ return ret; ++ ++error: ++ FREE_SEND_XFRAME(xbus, xframe); ++ return ret; ++} ++EXPORT_SYMBOL(send_pcm_frame); ++ ++static int really_send_cmd_frame(xbus_t *xbus, xframe_t *xframe) ++{ ++ struct xbus_ops *ops; ++ int ret; ++ ++ BUG_ON(!xbus); ++ BUG_ON(!xframe); ++ BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); ++ if (!XBUS_FLAGS(xbus, CONNECTED)) { ++ XBUS_ERR(xbus, ++ "Dropped command before sending -- " ++ "hardware deactivated.\n"); ++ dump_xframe("Dropped", xbus, xframe, DBG_ANY); ++ FREE_SEND_XFRAME(xbus, xframe); ++ return -ENODEV; ++ } ++ ops = transportops_get(xbus); ++ BUG_ON(!ops); ++ if (debug & DBG_COMMANDS) ++ dump_xframe("TX-CMD", xbus, xframe, DBG_ANY); ++ ret = ops->xframe_send_cmd(xbus, xframe); ++ transportops_put(xbus); ++ if (ret == 0) { ++ XBUS_COUNTER(xbus, TX_CMD)++; ++ XBUS_COUNTER(xbus, TX_BYTES) += XFRAME_LEN(xframe); ++ } ++ return ret; ++} ++ ++int xbus_command_queue_tick(xbus_t *xbus) ++{ ++ xframe_t *frm; ++ int ret = 0; ++ int packno; ++ ++ xbus->command_tick_counter++; ++ xbus->usec_nosend -= 1000; /* That's our budget */ ++ for (packno = 0; packno < 3; packno++) { ++ if (xbus->usec_nosend > 0) ++ break; ++ frm = xframe_dequeue(&xbus->command_queue); ++ if (!frm) { ++ wake_up(&xbus->command_queue_empty); ++ break; ++ } ++ BUG_ON(frm->xframe_magic != XFRAME_MAGIC); ++ xbus->usec_nosend += frm->usec_towait; ++ ret = really_send_cmd_frame(xbus, frm); ++ if (ret < 0) { ++ XBUS_ERR(xbus, ++ "Failed to send from command_queue (ret=%d)\n", ++ ret); ++ xbus_setstate(xbus, XBUS_STATE_FAIL); ++ } ++ } ++ if (xbus->usec_nosend < 0) ++ xbus->usec_nosend = 0; ++ return ret; ++} ++EXPORT_SYMBOL(xbus_command_queue_tick); ++ ++static void xbus_command_queue_clean(xbus_t *xbus) ++{ ++ xframe_t *frm; ++ ++ XBUS_DBG(DEVICES, xbus, "count=%d\n", xbus->command_queue.count); ++ xframe_queue_disable(&xbus->command_queue, 1); ++ while ((frm = xframe_dequeue(&xbus->command_queue)) != NULL) ++ FREE_SEND_XFRAME(xbus, frm); ++} ++ ++static int xbus_command_queue_waitempty(xbus_t *xbus) ++{ ++ int ret; ++ ++ XBUS_DBG(DEVICES, xbus, "Waiting for command_queue to empty\n"); ++ ret = ++ wait_event_interruptible(xbus->command_queue_empty, ++ xframe_queue_count(&xbus->command_queue) == ++ 0); ++ if (ret) ++ XBUS_ERR(xbus, "waiting for command_queue interrupted!!!\n"); ++ return ret; ++} ++ ++int send_cmd_frame(xbus_t *xbus, xframe_t *xframe) ++{ ++ static int rate_limit; ++ int ret = 0; ++ ++ BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); ++ if (!XBUS_FLAGS(xbus, CONNECTED)) { ++ XBUS_ERR(xbus, ++ "Dropped command before queueing -- " ++ "hardware deactivated.\n"); ++ ret = -ENODEV; ++ goto err; ++ } ++ if (debug & DBG_COMMANDS) ++ dump_xframe(__func__, xbus, xframe, DBG_ANY); ++ if (!xframe_enqueue(&xbus->command_queue, xframe)) { ++ if ((rate_limit++ % 1003) == 0) { ++ XBUS_ERR(xbus, ++ "Dropped command xframe. Cannot enqueue (%d)\n", ++ rate_limit); ++ dump_xframe(__func__, xbus, xframe, DBG_ANY); ++ } ++ xbus_setstate(xbus, XBUS_STATE_FAIL); ++ ret = -E2BIG; ++ goto err; ++ } ++ return 0; ++err: ++ FREE_SEND_XFRAME(xbus, xframe); ++ return ret; ++} ++EXPORT_SYMBOL(send_cmd_frame); ++ ++/*------------------------- Receive Tasklet Handling ---------------*/ ++ ++static void xframe_enqueue_recv(xbus_t *xbus, xframe_t *xframe) ++{ ++ int cpu = smp_processor_id(); ++ ++ BUG_ON(!xbus); ++ xbus->cpu_rcv_intr[cpu]++; ++ if (!xframe_enqueue(&xbus->receive_queue, xframe)) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) ++ XBUS_ERR(xbus, ++ "Failed to enqueue for receive_tasklet (%d)\n", ++ rate_limit); ++ FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */ ++ return; ++ } ++ tasklet_schedule(&xbus->receive_tasklet); ++} ++ ++/* ++ * process frames in the receive_queue in a tasklet ++ */ ++static void receive_tasklet_func(unsigned long data) ++{ ++ xbus_t *xbus = (xbus_t *)data; ++ xframe_t *xframe = NULL; ++ int cpu = smp_processor_id(); ++ ++ BUG_ON(!xbus); ++ xbus->cpu_rcv_tasklet[cpu]++; ++ while ((xframe = xframe_dequeue(&xbus->receive_queue)) != NULL) ++ xframe_receive(xbus, xframe); ++} ++ ++void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe) ++{ ++ BUG_ON(!xbus); ++ if (xbus_is_shutting_down(xbus->num)) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1000) == 0) ++ XBUS_NOTICE(xbus, "%s: during shutdown (%d)\n", ++ __func__, rate_limit); ++ return; ++ } ++ if (rx_tasklet) { ++ xframe_enqueue_recv(xbus, xframe); ++ } else { ++ if (likely(XBUS_FLAGS(xbus, CONNECTED))) ++ xframe_receive(xbus, xframe); ++ else ++ /* return to receive_pool */ ++ FREE_RECV_XFRAME(xbus, xframe); ++ } ++} ++EXPORT_SYMBOL(xbus_receive_xframe); ++ ++/*------------------------- Bus Management -------------------------*/ ++xpd_t *xpd_of(const xbus_t *xbus, int xpd_num) ++{ ++ if (!VALID_XPD_NUM(xpd_num)) ++ return NULL; ++ return xbus->xpds[xpd_num]; ++} ++EXPORT_SYMBOL(xpd_of); ++ ++xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit) ++{ ++ if (unit > MAX_UNIT || subunit > MAX_SUBUNIT) ++ return NULL; ++ return xbus->xpds[XPD_IDX(unit, subunit)]; ++} ++EXPORT_SYMBOL(xpd_byaddr); ++ ++int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit) ++{ ++ unsigned int xpd_num; ++ unsigned long flags; ++ ++ BUG_ON(!xbus); ++ xpd_num = XPD_IDX(unit, subunit); ++ XBUS_DBG(DEVICES, xbus, "XPD #%d\n", xpd_num); ++ spin_lock_irqsave(&xbus->lock, flags); ++ if (!VALID_XPD_NUM(xpd_num)) { ++ XBUS_ERR(xbus, "Bad xpd_num = %d\n", xpd_num); ++ BUG(); ++ } ++ if (xbus->xpds[xpd_num] != NULL) { ++ xpd_t *other = xbus->xpds[xpd_num]; ++ ++ XBUS_ERR(xbus, "xpd_num=%d is occupied by %p (%s)\n", xpd_num, ++ other, other->xpdname); ++ BUG(); ++ } ++ snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%1d%1d", unit, subunit); ++ MKADDR(&xpd->addr, unit, subunit); ++ xpd->xbus_idx = xpd_num; ++ xbus->xpds[xpd_num] = xpd; ++ xpd->xbus = xbus; ++ atomic_inc(&xbus->num_xpds); ++ spin_unlock_irqrestore(&xbus->lock, flags); ++ /* Must be done out of atomic context */ ++ if (xpd_device_register(xbus, xpd) < 0) { ++ XPD_ERR(xpd, "%s: xpd_device_register() failed\n", __func__); ++ /* FIXME: What to do? */ ++ } ++ return 0; ++} ++ ++int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd) ++{ ++ unsigned int xpd_num = xpd->xbus_idx; ++ unsigned long flags; ++ ++ XBUS_DBG(DEVICES, xbus, "XPD #%d\n", xpd_num); ++ if (!VALID_XPD_NUM(xpd_num)) { ++ XBUS_ERR(xbus, "%s: Bad xpd_num = %d\n", __func__, xpd_num); ++ BUG(); ++ } ++ if (xbus->xpds[xpd_num] == NULL) { ++ XBUS_ERR(xbus, "%s: slot xpd_num=%d is empty\n", __func__, ++ xpd_num); ++ BUG(); ++ } ++ if (xbus->xpds[xpd_num] != xpd) { ++ xpd_t *other = xbus->xpds[xpd_num]; ++ ++ XBUS_ERR(xbus, "%s: slot xpd_num=%d is occupied by %p (%s)\n", ++ __func__, xpd_num, other, other->xpdname); ++ BUG(); ++ } ++ spin_lock_irqsave(&xbus->lock, flags); ++ xpd->xbus = NULL; ++ xbus->xpds[xpd_num] = NULL; ++ if (atomic_dec_and_test(&xbus->num_xpds)) ++ xbus_setstate(xbus, XBUS_STATE_IDLE); ++ spin_unlock_irqrestore(&xbus->lock, flags); ++ return 0; ++} ++ ++static xpd_type_t xpd_hw2xpd_type(const struct unit_descriptor *unit_descriptor) ++{ ++ xpd_type_t xpd_type; ++ ++ switch (unit_descriptor->type) { ++ case 1: ++ case 6: ++ xpd_type = XPD_TYPE_FXS; ++ break; ++ case 2: ++ xpd_type = XPD_TYPE_FXO; ++ break; ++ case 3: ++ xpd_type = XPD_TYPE_BRI; ++ break; ++ case 4: ++ xpd_type = XPD_TYPE_PRI; ++ break; ++ case 5: ++ xpd_type = XPD_TYPE_ECHO; ++ break; ++ case 7: ++ xpd_type = XPD_TYPE_NOMODULE; ++ break; ++ default: ++ NOTICE("WARNING: xpd hw type is: %d\n", unit_descriptor->type); ++ xpd_type = XPD_TYPE_NOMODULE; ++ break; ++ } ++ return xpd_type; ++} ++ ++int subunits_of_xpd(const struct unit_descriptor* unit_descriptor, ++ const xproto_table_t *proto_table) { ++ int ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips; ++ ++ return ++ (ports + proto_table->ports_per_subunit - 1) ++ / proto_table->ports_per_subunit; ++} ++ ++static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor) ++{ ++ int unit = unit_descriptor->addr.unit; ++ xpd_type_t xpd_type; ++ __u8 hw_type; ++ __u8 numchips; ++ __u8 ports_per_chip; ++ __u8 ports; ++ __u8 port_dir; ++ const xproto_table_t *proto_table; ++ int i; ++ int subunits; ++ int ret = 0; ++ int remaining_ports; ++ const struct echoops *echoops; ++ ++ /* Translate parameters from "unit_descriptor" */ ++ hw_type = unit_descriptor->type; ++ numchips = unit_descriptor->numchips; ++ ports_per_chip = unit_descriptor->ports_per_chip; ++ port_dir = unit_descriptor->port_dir; ++ ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips; ++ xpd_type = xpd_hw2xpd_type(unit_descriptor); ++ proto_table = xproto_get(xpd_type); ++ if (!proto_table) { ++ XBUS_NOTICE(xbus, ++ "CARD %d: missing protocol table for xpd_type %d. " ++ "Ignored.\n", ++ unit, xpd_type); ++ return -EINVAL; ++ } ++ echoops = proto_table->echoops; ++ if (echoops) { ++ XBUS_INFO(xbus, "Detected ECHO Canceler (%d)\n", unit); ++ if (ECHOOPS(xbus)) { ++ XBUS_NOTICE(xbus, ++ "CARD %d: tryies to define echoops (xpd_type %d) " ++ "but we already have one. Ignored.\n", ++ unit, xpd_type); ++ return -EINVAL; ++ } ++ xbus->echo_state.echoops = echoops; ++ xbus->echo_state.xpd_idx = XPD_IDX(unit, 0); ++ } ++ remaining_ports = ports; ++ subunits = subunits_of_xpd(unit_descriptor, proto_table); ++ XBUS_DBG(DEVICES, xbus, ++ "CARD %d xpd_type=%d/hw_type=%d ports=%d (%dx%d), " ++ "%d subunits, port-dir=0x%02X\n", ++ unit, xpd_type, hw_type, ports, numchips, ports_per_chip, subunits, ++ port_dir); ++ if (xpd_type == XPD_TYPE_PRI || xpd_type == XPD_TYPE_BRI) ++ xbus->quirks.has_digital_span = 1; ++ if (xpd_type == XPD_TYPE_FXO) ++ xbus->quirks.has_fxo = 1; ++ xbus->worker.num_units += subunits - 1; ++ for (i = 0; i < subunits; i++) { ++ int subunit_ports = proto_table->ports_per_subunit; ++ ++ if (subunit_ports > remaining_ports) ++ subunit_ports = remaining_ports; ++ remaining_ports -= proto_table->ports_per_subunit; ++ if (subunit_ports <= 0) { ++ XBUS_NOTICE(xbus, ++ "Subunit XPD=%d%d without ports (%d of %d)\n", ++ unit, i, subunit_ports, ports); ++ ret = -ENODEV; ++ goto out; ++ } ++ if (!XBUS_IS(xbus, RECVD_DESC)) { ++ XBUS_NOTICE(xbus, ++ "Cannot create XPD=%d%d in state %s\n", ++ unit, i, xbus_statename(XBUS_STATE(xbus))); ++ ret = -ENODEV; ++ goto out; ++ } ++ XBUS_DBG(DEVICES, xbus, ++ "Creating XPD=%d%d xpd_type=%d.%d hw_type=%d (%d ports)\n", unit, i, ++ xpd_type, unit_descriptor->subtype, hw_type, subunit_ports); ++ ret = ++ create_xpd(xbus, proto_table, unit_descriptor, unit, i, xpd_type); ++ if (ret < 0) { ++ XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", unit, ++ i, ret); ++ goto out; ++ } ++ xbus->worker.num_units_initialized++; ++ } ++out: ++ xproto_put(proto_table); /* ref count is inside the xpds now */ ++ return ret; ++} ++ ++static void xbus_release_xpds(xbus_t *xbus) ++{ ++ int i; ++ ++ XBUS_DBG(DEVICES, xbus, "[%s] Release XPDS\n", xbus->label); ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd_t *xpd = xpd_of(xbus, i); ++ ++ if (xpd) ++ put_xpd(__func__, xpd); ++ } ++} ++ ++static int xbus_aquire_xpds(xbus_t *xbus) ++{ ++ unsigned long flags; ++ int i; ++ int ret = 0; ++ xpd_t *xpd; ++ ++ XBUS_DBG(DEVICES, xbus, "[%s] Aquire XPDS\n", xbus->label); ++ spin_lock_irqsave(&xbus->lock, flags); ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd = xpd_of(xbus, i); ++ if (xpd) { ++ xpd = get_xpd(__func__, xpd); ++ if (!xpd) ++ goto err; ++ } ++ } ++out: ++ spin_unlock_irqrestore(&xbus->lock, flags); ++ return ret; ++err: ++ for (--i; i >= 0; i--) { ++ xpd = xpd_of(xbus, i); ++ if (xpd) ++ put_xpd(__func__, xpd); ++ } ++ ret = -EBUSY; ++ goto out; ++} ++ ++static int xpd_initialize(xpd_t *xpd) ++{ ++ int ret = -ENODEV; ++ ++ if (CALL_XMETHOD(card_init, xpd) < 0) { ++ XPD_ERR(xpd, "Card Initialization failed\n"); ++ goto out; ++ } ++ xpd->card_present = 1; ++ if (IS_PHONEDEV(xpd)) { ++ /* ++ * Set echo canceler channels (off) ++ * Asterisk will tell us when/if it's needed. ++ */ ++ CALL_PHONE_METHOD(echocancel_setmask, xpd, 0); ++ /* Turn on all channels */ ++ CALL_PHONE_METHOD(card_state, xpd, 1); ++ } ++ if (!xpd_setstate(xpd, XPD_STATE_READY)) ++ goto out; ++ XPD_INFO(xpd, "Initialized: %s\n", xpd->type_name); ++ ret = 0; ++out: ++ return ret; ++} ++ ++static int xbus_echocancel(xbus_t *xbus, int on) ++{ ++ int unit; ++ int subunit; ++ xpd_t *xpd; ++ ++ if (!ECHOOPS(xbus)) ++ return 0; ++ for (unit = 0; unit < MAX_UNIT; unit++) { ++ xpd = xpd_byaddr(xbus, unit, 0); ++ if (!xpd || !IS_PHONEDEV(xpd)) ++ continue; ++ for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) { ++ int ret; ++ ++ xpd = xpd_byaddr(xbus, unit, subunit); ++ if (!xpd || !IS_PHONEDEV(xpd)) ++ continue; ++ ret = echocancel_xpd(xpd, on); ++ if (ret < 0) { ++ XPD_ERR(xpd, "Fail in xbus_echocancel()\n"); ++ return ret; ++ } ++ } ++ } ++ return 0; ++} ++ ++static void xbus_deactivate_xpds(xbus_t *xbus) ++{ ++ unsigned long flags; ++ int unit; ++ int subunit; ++ xpd_t *xpd; ++ ++ for (unit = 0; unit < MAX_UNIT; unit++) { ++ xpd = xpd_byaddr(xbus, unit, 0); ++ if (!xpd) ++ continue; ++ for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) { ++ xpd = xpd_byaddr(xbus, unit, subunit); ++ if (!xpd) ++ continue; ++ spin_lock_irqsave(&xpd->lock, flags); ++ xpd->card_present = 0; ++ xpd_setstate(xpd, XPD_STATE_NOHW); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ } ++ } ++} ++ ++static int xbus_initialize(xbus_t *xbus) ++{ ++ int unit; ++ int subunit; ++ xpd_t *xpd; ++ ktime_t time_start; ++ ktime_t time_end; ++ unsigned long timediff; ++ int res = 0; ++ ++ time_start = ktime_get(); ++ XBUS_DBG(DEVICES, xbus, "refcount_xbus=%d\n", refcount_xbus(xbus)); ++ if (xbus_aquire_xpds(xbus) < 0) /* Until end of initialization */ ++ return -EBUSY; ++ for (unit = 0; unit < MAX_UNIT; unit++) { ++ xpd = xpd_byaddr(xbus, unit, 0); ++ if (!xpd) ++ continue; ++ if (!XBUS_IS(xbus, RECVD_DESC)) { ++ XBUS_NOTICE(xbus, ++ "Cannot initialize UNIT=%d in state %s\n", ++ unit, xbus_statename(XBUS_STATE(xbus))); ++ goto err; ++ } ++ if (run_initialize_registers(xpd) < 0) { ++ XBUS_ERR(xbus, ++ "Register Initialization of card #%d failed\n", ++ unit); ++ goto err; ++ } ++ for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) { ++ int ret; ++ ++ xpd = xpd_byaddr(xbus, unit, subunit); ++ if (!xpd) ++ continue; ++ if (!XBUS_IS(xbus, RECVD_DESC)) { ++ XBUS_ERR(xbus, ++ "XPD-%d%d Not in 'RECVD_DESC' state\n", ++ unit, subunit); ++ goto err; ++ } ++ ret = xpd_initialize(xpd); ++ if (ret < 0) ++ goto err; ++ } ++ } ++ xbus_echocancel(xbus, 1); ++ time_end = ktime_get(); ++ timediff = usec_diff(&time_end, &time_start); ++ timediff /= 1000 * 100; ++ XBUS_INFO(xbus, "Initialized in %ld.%1ld sec\n", timediff / 10, ++ timediff % 10); ++out: ++ xbus_release_xpds(xbus); /* Initialization done/failed */ ++ return res; ++err: ++ xbus_setstate(xbus, XBUS_STATE_FAIL); ++ res = -EINVAL; ++ goto out; ++} ++ ++int xbus_is_registered(xbus_t *xbus) ++{ ++ return xbus->ddev && xbus->ddev->dev.parent; ++} ++ ++static void xbus_free_ddev(xbus_t *xbus) ++{ ++ if (!xbus->ddev) ++ return; ++ kfree(xbus->ddev->devicetype); /* NULL is safe */ ++ xbus->ddev->devicetype = NULL; ++ xbus->ddev->location = NULL; ++ xbus->ddev->hardware_id = NULL; ++ dahdi_free_device(xbus->ddev); ++ xbus->ddev = NULL; ++} ++ ++static DEFINE_MUTEX(dahdi_registration_mutex); ++ ++int xbus_register_dahdi_device(xbus_t *xbus) ++{ ++ int i; ++ int offset = 0; ++ int ret; ++ ++ XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__); ++ ret = mutex_lock_interruptible(&dahdi_registration_mutex); ++ if (ret < 0) { ++ XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n"); ++ goto err; ++ } ++ if (xbus_is_registered(xbus)) { ++ /* ++ * Ignore duplicate registrations (from dahdi_registration) ++ * Until we completely migrate to dahdi_autoreg=1 and ++ * hotplug-based span-assignments ++ */ ++ XBUS_DBG(DEVICES, xbus, "Already registered to DAHDI\n"); ++ ret = 0; ++ goto out; ++ } ++ xbus->ddev = dahdi_create_device(); ++ if (!xbus->ddev) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ /* ++ * This actually describe the dahdi_spaninfo version 3 ++ * A bunch of unrelated data exported via a modified ioctl() ++ * What a bummer... ++ */ ++ xbus->ddev->manufacturer = "Xorcom Inc."; /* OK, that's obvious */ ++ /* span->spantype = "...."; set in card_dahdi_preregistration() */ ++ /* ++ * Yes, this basically duplicates information available ++ * from the description field. If some more is needed ++ * why not add it there? ++ * OK, let's add to the kernel more useless info. ++ */ ++ xbus->ddev->devicetype = kasprintf(GFP_KERNEL, "Astribank2"); ++ if (!xbus->ddev->devicetype) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ /* ++ * location is the only usefull new data item. ++ * For our devices it was available for ages via: ++ * - The legacy "/proc/xpp/XBUS-??/summary" (CONNECTOR=...) ++ * - The same info in "/proc/xpp/xbuses" ++ * - The modern "/sys/bus/astribanks/devices/xbus-??/connector" ++ * attribute ++ * So let's also export it via the newfangled "location" field. ++ */ ++ xbus->ddev->location = xbus->connector; ++ xbus->ddev->hardware_id = xbus->label; ++ ++ /* ++ * Prepare the span list ++ */ ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd_t *xpd = xpd_of(xbus, i); ++ if (xpd && IS_PHONEDEV(xpd)) { ++ XPD_DBG(DEVICES, xpd, "offset=%d\n", offset); ++ xpd_dahdi_preregister(xpd, offset++); ++ } ++ } ++ if (dahdi_register_device(xbus->ddev, &xbus->astribank)) { ++ XBUS_ERR(xbus, "Failed to dahdi_register_device()\n"); ++ ret = -ENODEV; ++ goto err; ++ } ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd_t *xpd = xpd_of(xbus, i); ++ if (xpd && IS_PHONEDEV(xpd)) { ++ XPD_DBG(DEVICES, xpd, "\n"); ++ xpd_dahdi_postregister(xpd); ++ } ++ } ++ ret = 0; ++out: ++ mutex_unlock(&dahdi_registration_mutex); ++ return ret; ++err: ++ xbus_free_ddev(xbus); ++ goto out; ++} ++ ++void xbus_unregister_dahdi_device(xbus_t *xbus) ++{ ++ int i; ++ int ret; ++ ++ XBUS_DBG(DEVICES, xbus, "%s\n", __func__); ++ ret = mutex_lock_interruptible(&dahdi_registration_mutex); ++ if (ret < 0) { ++ XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n"); ++ return; ++ } ++ if (!xbus_is_registered(xbus)) { ++ /* ++ * Ignore duplicate unregistrations ++ */ ++ XBUS_DBG(DEVICES, xbus, "Already unregistered to DAHDI\n"); ++ goto err; ++ } ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd_t *xpd = xpd_of(xbus, i); ++ xpd_dahdi_preunregister(xpd); ++ } ++ if (xbus->ddev) { ++ dahdi_unregister_device(xbus->ddev); ++ XBUS_DBG(DEVICES, xbus, ++ "%s: finished dahdi_unregister_device()\n", __func__); ++ xbus_free_ddev(xbus); ++ } ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd_t *xpd = xpd_of(xbus, i); ++ xpd_dahdi_postunregister(xpd); ++ } ++err: ++ mutex_unlock(&dahdi_registration_mutex); ++} ++ ++/* ++ * This must be called from synchronous (non-interrupt) context ++ * it returns only when all XPD's on the bus are detected and ++ * initialized. ++ */ ++static void xbus_populate(struct work_struct *work) ++{ ++ struct xbus_workqueue *worker = ++ container_of(work, struct xbus_workqueue, xpds_init_work); ++ xbus_t *xbus; ++ struct list_head *card; ++ struct list_head *next_card; ++ unsigned long flags; ++ int ret = 0; ++ ++ xbus = container_of(worker, xbus_t, worker); ++ xbus = get_xbus(__func__, xbus->num); /* return in function end */ ++ XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__); ++ spin_lock_irqsave(&worker->worker_lock, flags); ++ list_for_each_safe(card, next_card, &worker->card_list) { ++ struct card_desc_struct *card_desc = ++ list_entry(card, struct card_desc_struct, card_list); ++ ++ list_del(card); ++ BUG_ON(card_desc->magic != CARD_DESC_MAGIC); ++ /* Release/Reacquire locks around blocking calls */ ++ spin_unlock_irqrestore(&xbus->worker.worker_lock, flags); ++ ret = new_card(xbus, &card_desc->unit_descriptor); ++ spin_lock_irqsave(&xbus->worker.worker_lock, flags); ++ KZFREE(card_desc); ++ if (ret) ++ break; ++ } ++ spin_unlock_irqrestore(&worker->worker_lock, flags); ++ if (xbus_initialize(xbus) < 0) { ++ XBUS_NOTICE(xbus, ++ "Initialization failed. Leave unused. " ++ "refcount_xbus=%d\n", ++ refcount_xbus(xbus)); ++ goto failed; ++ } ++ if (!xbus_setstate(xbus, XBUS_STATE_READY)) { ++ XBUS_NOTICE(xbus, ++ "Illegal transition. Leave unused. refcount_xbus=%d\n", ++ refcount_xbus(xbus)); ++ goto failed; ++ } ++ worker->xpds_init_done = 1; ++ /* ++ * Now request Astribank to start self_ticking. ++ * This is the last initialization command. So ++ * all others will reach the device before it. ++ */ ++ xbus_request_sync(xbus, SYNC_MODE_PLL); ++ elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */ ++ if (!dahdi_get_auto_assign_spans()) ++ xbus_register_dahdi_device(xbus); ++out: ++ XBUS_DBG(DEVICES, xbus, "Leaving\n"); ++ wake_up_interruptible_all(&worker->wait_for_xpd_initialization); ++ XBUS_DBG(DEVICES, xbus, "populate release\n"); ++ up(&worker->running_initialization); ++ put_xbus(__func__, xbus); /* taken at function entry */ ++ return; ++failed: ++ xbus_setstate(xbus, XBUS_STATE_FAIL); ++ goto out; ++} ++ ++int xbus_process_worker(xbus_t *xbus) ++{ ++ struct xbus_workqueue *worker; ++ ++ if (!xbus) { ++ ERR("%s: xbus gone -- skip initialization\n", __func__); ++ return 0; ++ } ++ worker = &xbus->worker; ++ if (down_trylock(&worker->running_initialization)) { ++ ERR("%s: xbus is disconnected -- skip initialization\n", ++ __func__); ++ return 0; ++ } ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ /* Initialize the work. (adapt to kernel API changes). */ ++ INIT_WORK(&worker->xpds_init_work, xbus_populate); ++ BUG_ON(!xbus); ++ /* Now send it */ ++ if (!queue_work(worker->wq, &worker->xpds_init_work)) { ++ XBUS_ERR(xbus, "Failed to queue xpd initialization work\n"); ++ up(&worker->running_initialization); ++ return 0; ++ } ++ return 1; ++} ++ ++static void worker_reset(xbus_t *xbus) ++{ ++ struct xbus_workqueue *worker; ++ struct list_head *card; ++ struct list_head *next_card; ++ unsigned long flags; ++ char *name; ++ ++ BUG_ON(!xbus); ++ worker = &xbus->worker; ++ name = (xbus) ? xbus->busname : "detached"; ++ DBG(DEVICES, "%s\n", name); ++ if (!worker->xpds_init_done) { ++ XBUS_NOTICE(xbus, "XPDS initialization was not finished\n"); ++ } ++ spin_lock_irqsave(&worker->worker_lock, flags); ++ list_for_each_safe(card, next_card, &worker->card_list) { ++ struct card_desc_struct *card_desc = ++ list_entry(card, struct card_desc_struct, card_list); ++ ++ BUG_ON(card_desc->magic != CARD_DESC_MAGIC); ++ list_del(card); ++ KZFREE(card_desc); ++ } ++ worker->xpds_init_done = 0; ++ worker->num_units = 0; ++ worker->num_units_initialized = 0; ++ wake_up_interruptible_all(&worker->wait_for_xpd_initialization); ++ spin_unlock_irqrestore(&worker->worker_lock, flags); ++} ++ ++/* ++ * Called only after worker_reset(xbus) ++ */ ++static void worker_destroy(xbus_t *xbus) ++{ ++ struct xbus_workqueue *worker; ++ ++ BUG_ON(!xbus); ++ worker = &xbus->worker; ++ XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish...\n"); ++ down(&worker->running_initialization); ++ XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish -- done\n"); ++ if (worker->wq) { ++ XBUS_DBG(DEVICES, xbus, "destroying workqueue...\n"); ++ flush_workqueue(worker->wq); ++ destroy_workqueue(worker->wq); ++ worker->wq = NULL; ++ XBUS_DBG(DEVICES, xbus, "destroying workqueue -- done\n"); ++ } ++ XBUS_DBG(DEVICES, xbus, "detach worker\n"); ++ put_xbus(__func__, xbus); /* got from worker_run() */ ++} ++ ++static void worker_init(xbus_t *xbus) ++{ ++ struct xbus_workqueue *worker; ++ ++ BUG_ON(!xbus); ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ worker = &xbus->worker; ++ /* poll related variables */ ++ spin_lock_init(&worker->worker_lock); ++ INIT_LIST_HEAD(&worker->card_list); ++ init_waitqueue_head(&worker->wait_for_xpd_initialization); ++ worker->wq = NULL; ++ sema_init(&xbus->worker.running_initialization, 1); ++} ++ ++/* ++ * Allocate a worker for the xbus including the nessessary workqueue. ++ * May call blocking operations, but only briefly (as we are called ++ * from xbus_new() which is called from khubd. ++ */ ++static int worker_run(xbus_t *xbus) ++{ ++ struct xbus_workqueue *worker; ++ ++ xbus = get_xbus(__func__, xbus->num); /* return in worker_destroy() */ ++ BUG_ON(!xbus); ++ BUG_ON(xbus->busname[0] == '\0'); /* No name? */ ++ worker = &xbus->worker; ++ BUG_ON(worker->wq); /* Hmmm... nested workers? */ ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ /* poll related variables */ ++ worker->wq = create_singlethread_workqueue(xbus->busname); ++ if (!worker->wq) { ++ XBUS_ERR(xbus, "Failed to create worker workqueue.\n"); ++ goto err; ++ } ++ return 1; ++err: ++ worker_reset(xbus); ++ worker_destroy(xbus); ++ return 0; ++} ++ ++bool xbus_setflags(xbus_t *xbus, int flagbit, bool on) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&xbus->transport.state_lock, flags); ++ XBUS_DBG(DEVICES, xbus, "%s flag %d\n", (on) ? "Set" : "Clear", ++ flagbit); ++ if (on) ++ set_bit(flagbit, &(xbus->transport.transport_flags)); ++ else ++ clear_bit(flagbit, &(xbus->transport.transport_flags)); ++ spin_unlock_irqrestore(&xbus->transport.state_lock, flags); ++ return 1; ++} ++ ++bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate) ++{ ++ unsigned long flags; ++ bool ret = 0; ++ int state_flip = 0; ++ ++ spin_lock_irqsave(&xbus->transport.state_lock, flags); ++ if (newstate == XBUS_STATE(xbus)) { ++ XBUS_DBG(DEVICES, xbus, "stay at %s\n", ++ xbus_statename(newstate)); ++ goto out; ++ } ++ /* Sanity tests */ ++ switch (newstate) { ++ case XBUS_STATE_START: ++ goto bad_state; ++ case XBUS_STATE_IDLE: ++ if (!XBUS_IS(xbus, START) && !XBUS_IS(xbus, DEACTIVATED)) ++ goto bad_state; ++ break; ++ case XBUS_STATE_SENT_REQUEST: ++ if (!XBUS_IS(xbus, IDLE) && !XBUS_IS(xbus, SENT_REQUEST)) ++ goto bad_state; ++ break; ++ case XBUS_STATE_RECVD_DESC: ++ if (!XBUS_IS(xbus, SENT_REQUEST)) ++ goto bad_state; ++ break; ++ case XBUS_STATE_READY: ++ if (!XBUS_IS(xbus, RECVD_DESC)) ++ goto bad_state; ++ state_flip = 1; /* We are good */ ++ break; ++ case XBUS_STATE_DEACTIVATING: ++ if (XBUS_IS(xbus, DEACTIVATING)) ++ goto bad_state; ++ if (XBUS_IS(xbus, DEACTIVATED)) ++ goto bad_state; ++ break; ++ case XBUS_STATE_DEACTIVATED: ++ if (!XBUS_IS(xbus, DEACTIVATING)) ++ goto bad_state; ++ break; ++ case XBUS_STATE_FAIL: ++ if (XBUS_IS(xbus, DEACTIVATING)) ++ goto bad_state; ++ if (XBUS_IS(xbus, DEACTIVATED)) ++ goto bad_state; ++ break; ++ default: ++ XBUS_NOTICE(xbus, "%s: unknown state %d\n", __func__, newstate); ++ goto out; ++ } ++ /* All good */ ++ XBUS_DBG(DEVICES, xbus, "%s -> %s\n", xbus_statename(XBUS_STATE(xbus)), ++ xbus_statename(newstate)); ++ if (xbus->transport.xbus_state == XBUS_STATE_READY ++ && newstate != XBUS_STATE_READY) ++ state_flip = -1; /* We became bad */ ++ xbus->transport.xbus_state = newstate; ++ ret = 1; ++out: ++ spin_unlock_irqrestore(&xbus->transport.state_lock, flags); ++ /* Should be sent out of spinlocks */ ++ if (state_flip > 0) ++ astribank_uevent_send(xbus, KOBJ_ONLINE); ++ else if (state_flip < 0) ++ astribank_uevent_send(xbus, KOBJ_OFFLINE); ++ return ret; ++bad_state: ++ XBUS_NOTICE(xbus, "Bad state transition %s -> %s ignored.\n", ++ xbus_statename(XBUS_STATE(xbus)), xbus_statename(newstate)); ++ goto out; ++} ++EXPORT_SYMBOL(xbus_setstate); ++ ++int xbus_activate(xbus_t *xbus) ++{ ++ XBUS_INFO(xbus, "[%s] Activating\n", xbus->label); ++ xpp_drift_init(xbus); ++ xbus_set_command_timer(xbus, 1); ++ xframe_queue_disable(&xbus->command_queue, 0); ++ /* must be done after transport is valid */ ++ xbus_setstate(xbus, XBUS_STATE_IDLE); ++ CALL_PROTO(GLOBAL, AB_REQUEST, xbus, NULL); ++ /* ++ * Make sure Astribank knows not to send us ticks. ++ */ ++ xbus_request_sync(xbus, SYNC_MODE_NONE); ++ return 0; ++} ++EXPORT_SYMBOL(xbus_activate); ++ ++int xbus_connect(xbus_t *xbus) ++{ ++ struct xbus_ops *ops; ++ ++ BUG_ON(!xbus); ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ ops = transportops_get(xbus); ++ BUG_ON(!ops); ++ /* Sanity checks */ ++ BUG_ON(!ops->xframe_send_pcm); ++ BUG_ON(!ops->xframe_send_cmd); ++ BUG_ON(!ops->alloc_xframe); ++ BUG_ON(!ops->free_xframe); ++ xbus_setflags(xbus, XBUS_FLAG_CONNECTED, 1); ++ xbus_activate(xbus); ++ return 0; ++} ++EXPORT_SYMBOL(xbus_connect); ++ ++void xbus_deactivate(xbus_t *xbus) ++{ ++ BUG_ON(!xbus); ++ XBUS_INFO(xbus, "[%s] Deactivating\n", xbus->label); ++ if (!xbus_setstate(xbus, XBUS_STATE_DEACTIVATING)) ++ return; ++ xbus_request_sync(xbus, SYNC_MODE_NONE); /* no more ticks */ ++ elect_syncer("deactivate"); ++ xbus_echocancel(xbus, 0); ++ xbus_deactivate_xpds(xbus); ++ XBUS_DBG(DEVICES, xbus, "[%s] Waiting for queues\n", xbus->label); ++ xbus_command_queue_clean(xbus); ++ xbus_command_queue_waitempty(xbus); ++ xbus_setstate(xbus, XBUS_STATE_DEACTIVATED); ++ worker_reset(xbus); ++ xbus_unregister_dahdi_device(xbus); ++ xbus_release_xpds(xbus); /* taken in xpd_alloc() [kref_init] */ ++} ++EXPORT_SYMBOL(xbus_deactivate); ++ ++void xbus_disconnect(xbus_t *xbus) ++{ ++ BUG_ON(!xbus); ++ XBUS_INFO(xbus, "[%s] Disconnecting\n", xbus->label); ++ xbus_setflags(xbus, XBUS_FLAG_CONNECTED, 0); ++ xbus_deactivate(xbus); ++ xbus_command_queue_clean(xbus); ++ xbus_command_queue_waitempty(xbus); ++ tasklet_kill(&xbus->receive_tasklet); ++ xframe_queue_clear(&xbus->receive_queue); ++ xframe_queue_clear(&xbus->send_pool); ++ xframe_queue_clear(&xbus->receive_pool); ++ xframe_queue_clear(&xbus->pcm_tospan); ++ del_timer_sync(&xbus->command_timer); ++ transportops_put(xbus); ++ transport_destroy(xbus); ++ /* worker_reset(xbus) was called in xbus_deactivate(xbus) */ ++ worker_destroy(xbus); ++ XBUS_DBG(DEVICES, xbus, "Deactivated refcount_xbus=%d\n", ++ refcount_xbus(xbus)); ++ xbus_sysfs_transport_remove(xbus); /* Device-Model */ ++ put_xbus(__func__, xbus); /* from xbus_new() [kref_init()] */ ++} ++EXPORT_SYMBOL(xbus_disconnect); ++ ++static xbus_t *xbus_alloc(void) ++{ ++ unsigned long flags; ++ xbus_t *xbus; ++ int i; ++ ++ xbus = KZALLOC(sizeof(xbus_t), GFP_KERNEL); ++ if (!xbus) { ++ ERR("%s: out of memory\n", __func__); ++ return NULL; ++ } ++ spin_lock_irqsave(&xbuses_lock, flags); ++ for (i = 0; i < MAX_BUSES; i++) ++ if (xbuses_array[i].xbus == NULL) ++ break; ++ if (i >= MAX_BUSES) { ++ ERR("%s: No free slot for new bus. i=%d\n", __func__, i); ++ KZFREE(xbus); ++ xbus = NULL; ++ goto out; ++ } ++ /* Found empty slot */ ++ xbus->num = i; ++ init_xbus(i, xbus); ++out: ++ spin_unlock_irqrestore(&xbuses_lock, flags); ++ return xbus; ++} ++ ++void xbus_free(xbus_t *xbus) ++{ ++ unsigned long flags; ++ uint num; ++ ++ if (!xbus) ++ return; ++ XBUS_DBG(DEVICES, xbus, "Free\n"); ++ spin_lock_irqsave(&xbuses_lock, flags); ++ num = xbus->num; ++ BUG_ON(!xbuses_array[num].xbus); ++ BUG_ON(xbus != xbuses_array[num].xbus); ++ init_xbus(num, NULL); ++ spin_unlock_irqrestore(&xbuses_lock, flags); ++#ifdef CONFIG_PROC_FS ++ if (xbus->proc_xbus_dir) { ++ if (xbus->proc_xbus_summary) { ++ XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", ++ PROC_XBUS_SUMMARY); ++ remove_proc_entry(PROC_XBUS_SUMMARY, ++ xbus->proc_xbus_dir); ++ xbus->proc_xbus_summary = NULL; ++ } ++#ifdef PROTOCOL_DEBUG ++ if (xbus->proc_xbus_command) { ++ XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", ++ PROC_XBUS_COMMAND); ++ remove_proc_entry(PROC_XBUS_COMMAND, ++ xbus->proc_xbus_dir); ++ xbus->proc_xbus_command = NULL; ++ } ++#endif ++ XBUS_DBG(PROC, xbus, "Removing proc directory\n"); ++ remove_proc_entry(xbus->busname, xpp_proc_toplevel); ++ xbus->proc_xbus_dir = NULL; ++ } ++#endif ++ spin_lock_irqsave(&xbuses_lock, flags); ++ XBUS_DBG(DEVICES, xbus, "Going to free...\n"); ++ spin_unlock_irqrestore(&xbuses_lock, flags); ++ KZFREE(xbus); ++} ++EXPORT_SYMBOL(xbus_free); ++ ++xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, ++ struct device *transport_device, void *priv) ++{ ++ int err; ++ xbus_t *xbus = NULL; ++ ++ BUG_ON(!ops); ++ xbus = xbus_alloc(); ++ if (!xbus) { ++ ERR("%s: Failed allocating new xbus\n", __func__); ++ return NULL; ++ } ++ snprintf(xbus->busname, XBUS_NAMELEN, "XBUS-%02d", xbus->num); ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ transport_init(xbus, ops, max_send_size, transport_device, priv); ++ spin_lock_init(&xbus->lock); ++ init_waitqueue_head(&xbus->command_queue_empty); ++ atomic_set(&xbus->pcm_rx_counter, 0); ++ xbus->min_tx_sync = INT_MAX; ++ xbus->min_rx_sync = INT_MAX; ++ ++ kref_init(&xbus->kref); ++ worker_init(xbus); ++ atomic_set(&xbus->num_xpds, 0); ++ xbus->sync_mode = SYNC_MODE_NONE; ++ xbus->sync_mode_default = SYNC_MODE_PLL; ++ err = xbus_sysfs_create(xbus); ++ if (err) { ++ XBUS_ERR(xbus, "SYSFS creation failed: %d\n", err); ++ goto nobus; ++ } ++ err = xbus_sysfs_transport_create(xbus); ++ if (err) { ++ XBUS_ERR(xbus, "SYSFS transport link creation failed: %d\n", ++ err); ++ goto nobus; ++ } ++ xbus_reset_counters(xbus); ++#ifdef CONFIG_PROC_FS ++ XBUS_DBG(PROC, xbus, "Creating xbus proc directory\n"); ++ xbus->proc_xbus_dir = proc_mkdir(xbus->busname, xpp_proc_toplevel); ++ if (!xbus->proc_xbus_dir) { ++ XBUS_ERR(xbus, "Failed to create proc directory\n"); ++ err = -EIO; ++ goto nobus; ++ } ++ xbus->proc_xbus_summary = proc_create_data(PROC_XBUS_SUMMARY, 0444, ++ xbus->proc_xbus_dir, ++ &xbus_read_proc_ops, ++ (void *)((unsigned long)xbus->num)); ++ if (!xbus->proc_xbus_summary) { ++ XBUS_ERR(xbus, "Failed to create proc file '%s'\n", ++ PROC_XBUS_SUMMARY); ++ err = -EIO; ++ goto nobus; ++ } ++#ifdef PROTOCOL_DEBUG ++ xbus->proc_xbus_command = proc_create_data(PROC_XBUS_COMMAND, 0200, ++ xbus->proc_xbus_dir, ++ &proc_xbus_command_ops, xbus); ++ if (!xbus->proc_xbus_command) { ++ XBUS_ERR(xbus, "Failed to create proc file '%s'\n", ++ PROC_XBUS_COMMAND); ++ err = -EIO; ++ goto nobus; ++ } ++#endif ++#endif ++ xframe_queue_init(&xbus->command_queue, 10, command_queue_length, ++ "command_queue", xbus); ++ xframe_queue_init(&xbus->receive_queue, 10, 50, "receive_queue", xbus); ++ xframe_queue_init(&xbus->send_pool, 10, 100, "send_pool", xbus); ++ xframe_queue_init(&xbus->receive_pool, 10, 50, "receive_pool", xbus); ++ xframe_queue_init(&xbus->pcm_tospan, 5, 10, "pcm_tospan", xbus); ++ tasklet_init(&xbus->receive_tasklet, receive_tasklet_func, ++ (unsigned long)xbus); ++ /* ++ * Create worker after /proc/XBUS-?? so the directory exists ++ * before /proc/XBUS-??/waitfor_xpds tries to get created. ++ */ ++ if (!worker_run(xbus)) { ++ ERR("Failed to allocate worker\n"); ++ goto nobus; ++ } ++ return xbus; ++nobus: ++ xbus_free(xbus); ++ return NULL; ++} ++EXPORT_SYMBOL(xbus_new); ++ ++/*------------------------- Proc handling --------------------------*/ ++ ++void xbus_reset_counters(xbus_t *xbus) ++{ ++ int i; ++ ++ XBUS_DBG(GENERAL, xbus, "Reseting counters\n"); ++ for (i = 0; i < XBUS_COUNTER_MAX; i++) ++ xbus->counters[i] = 0; ++} ++EXPORT_SYMBOL(xbus_reset_counters); ++ ++static bool xpds_done(xbus_t *xbus) ++{ ++ if (XBUS_IS(xbus, FAIL)) ++ return 1; /* Nothing to wait for */ ++ if (xbus->worker.xpds_init_done) ++ return 1; /* All good */ ++ /* Keep waiting */ ++ return 0; ++} ++ ++int waitfor_xpds(xbus_t *xbus, char *buf) ++{ ++ struct xbus_workqueue *worker; ++ unsigned long flags; ++ int ret; ++ int len = 0; ++ ++ /* ++ * FIXME: worker is created before ????? ++ * So by now it exists and initialized. ++ */ ++ worker = &xbus->worker; ++ BUG_ON(!worker); ++ if (!worker->wq) { ++ XBUS_ERR(xbus, "Missing worker thread. Skipping.\n"); ++ len = -ENODEV; ++ goto out; ++ } ++ XBUS_DBG(DEVICES, xbus, ++ "Waiting for card init of XPDs max %d seconds\n", ++ INITIALIZATION_TIMEOUT / HZ); ++ ret = ++ wait_event_interruptible_timeout(worker-> ++ wait_for_xpd_initialization, ++ xpds_done(xbus), ++ INITIALIZATION_TIMEOUT); ++ if (ret == 0) { ++ XBUS_ERR(xbus, "Card Initialization Timeout\n"); ++ len = -ETIMEDOUT; ++ goto out; ++ } else if (ret < 0) { ++ XBUS_ERR(xbus, "Card Initialization Interrupted %d\n", ret); ++ len = ret; ++ goto out; ++ } else ++ XBUS_DBG(DEVICES, xbus, ++ "Finished initialization of %d XPD's in %d seconds.\n", ++ worker->num_units_initialized, ++ (INITIALIZATION_TIMEOUT - ret) / HZ); ++ if (XBUS_IS(xbus, FAIL)) { ++ len += sprintf(buf, "FAILED: %s\n", xbus->busname); ++ } else { ++ spin_lock_irqsave(&xbus->lock, flags); ++ len += ++ sprintf(buf, "XPDS_READY: %s: %d/%d\n", xbus->busname, ++ worker->num_units_initialized, worker->num_units); ++ spin_unlock_irqrestore(&xbus->lock, flags); ++ } ++out: ++ return len; ++} ++ ++#ifdef CONFIG_PROC_FS ++ ++static void xbus_fill_proc_queue(struct seq_file *sfile, struct xframe_queue *q) ++{ ++ seq_printf(sfile, ++ "%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02lld.%lld ms\n", ++ q->name, q->steady_state_count, q->count, q->max_count, ++ q->worst_count, q->overflows, q->worst_lag_usec / 1000, ++ q->worst_lag_usec % 1000); ++ xframe_queue_clearstats(q); ++} ++ ++static int xbus_proc_show(struct seq_file *sfile, void *data) ++{ ++ xbus_t *xbus; ++ unsigned long flags; ++ int len = 0; ++ int i = (int)((unsigned long)sfile->private); ++ ++ xbus = get_xbus(__func__, i); /* until end of xbus_proc_show() */ ++ if (!xbus) ++ return -EINVAL; ++ spin_lock_irqsave(&xbus->lock, flags); ++ ++ seq_printf(sfile, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n", ++ xbus->busname, xbus->connector, xbus->label, ++ (XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing"); ++ xbus_fill_proc_queue(sfile, &xbus->send_pool); ++ xbus_fill_proc_queue(sfile, &xbus->receive_pool); ++ xbus_fill_proc_queue(sfile, &xbus->command_queue); ++ xbus_fill_proc_queue(sfile, &xbus->receive_queue); ++ xbus_fill_proc_queue(sfile, &xbus->pcm_tospan); ++ if (rx_tasklet) { ++ seq_printf(sfile, "\ncpu_rcv_intr: "); ++ for_each_online_cpu(i) ++ seq_printf(sfile, "%5d ", xbus->cpu_rcv_intr[i]); ++ seq_printf(sfile, "\ncpu_rcv_tasklet: "); ++ for_each_online_cpu(i) ++ seq_printf(sfile, "%5d ", xbus->cpu_rcv_tasklet[i]); ++ seq_printf(sfile, "\n"); ++ } ++ seq_printf(sfile, "self_ticking: %d (last_tick at %lld)\n", ++ xbus->self_ticking, ktime_divns(xbus->ticker.last_sample, ++ NSEC_PER_SEC)); ++ seq_printf(sfile, "command_tick: %d\n", ++ xbus->command_tick_counter); ++ seq_printf(sfile, "usec_nosend: %d\n", xbus->usec_nosend); ++ seq_printf(sfile, "xbus: pcm_rx_counter = %d, frag = %d\n", ++ atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count); ++ seq_printf(sfile, "max_rx_process = %2ld.%ld ms\n", ++ xbus->max_rx_process / 1000, xbus->max_rx_process % 1000); ++ xbus->max_rx_process = 0; ++ seq_printf(sfile, "\nTRANSPORT: max_send_size=%d refcount=%d\n", ++ MAX_SEND_SIZE(xbus), ++ atomic_read(&xbus->transport.transport_refcount) ++ ); ++ seq_printf(sfile, "PCM Metrices:\n"); ++ seq_printf(sfile, "\tPCM TX: min=%ld max=%ld\n", ++ xbus->min_tx_sync, xbus->max_tx_sync); ++ seq_printf(sfile, "\tPCM RX: min=%ld max=%ld\n", ++ xbus->min_rx_sync, xbus->max_rx_sync); ++ seq_printf(sfile, "COUNTERS:\n"); ++ for (i = 0; i < XBUS_COUNTER_MAX; i++) { ++ seq_printf(sfile, "\t%-15s = %d\n", xbus_counters[i].name, ++ xbus->counters[i]); ++ } ++ seq_printf(sfile, "<-- len=%d\n", len); ++ spin_unlock_irqrestore(&xbus->lock, flags); ++ put_xbus(__func__, xbus); /* from xbus_proc_show() */ ++ return 0; ++ ++} ++ ++static int xbus_read_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, xbus_proc_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops xbus_read_proc_ops = { ++ .proc_open = xbus_read_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations xbus_read_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = xbus_read_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++#ifdef PROTOCOL_DEBUG ++static ssize_t proc_xbus_command_write(struct file *file, ++ const char __user *buffer, size_t count, loff_t *offset) ++{ ++ char *buf; ++ xbus_t *xbus = file->private_data; ++ char *p; ++ __u8 *pack_start; ++ __u8 *q; ++ xframe_t *xframe; ++ size_t len; ++ const size_t max_len = xbus->transport.max_send_size; ++ const size_t max_text = max_len * 3 + 10; ++ ++ if (count > max_text) { ++ XBUS_ERR(xbus, "%s: line too long (%zd > %zd)\n", __func__, ++ count, max_len); ++ return -EFBIG; ++ } ++ /* 3 bytes per hex-digit and space */ ++ buf = kmalloc(max_text, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ if (copy_from_user(buf, buffer, count)) { ++ count = -EINVAL; ++ goto out; ++ } ++ buf[count] = '\0'; ++ XBUS_DBG(GENERAL, xbus, "count=%zd\n", count); ++ /* ++ * We replace the content of buf[] from ++ * ascii representation to packet content ++ * as the binary representation is shorter ++ */ ++ q = pack_start = buf; ++ for (p = buf; *p;) { ++ int val; ++ char hexdigit[3]; ++ ++ /* skip whitespace */ ++ while (*p && isspace(*p)) ++ p++; ++ if (!(*p)) ++ break; ++ if (!isxdigit(*p)) { ++ XBUS_ERR(xbus, ++ "%s: bad hex value ASCII='0x%X' " ++ "at position %ld\n", ++ __func__, *p, (long)(p - buf)); ++ count = -EINVAL; ++ goto out; ++ } ++ hexdigit[0] = *p++; ++ hexdigit[1] = '\0'; ++ hexdigit[2] = '\0'; ++ if (isxdigit(*p)) ++ hexdigit[1] = *p++; ++ if (sscanf(hexdigit, "%2X", &val) != 1) { ++ XBUS_ERR(xbus, ++ "%s: bad hex value '%s' at position %ld\n", ++ __func__, hexdigit, (long)(p - buf)); ++ count = -EINVAL; ++ goto out; ++ } ++ *q++ = val; ++ XBUS_DBG(GENERAL, xbus, "%3zd> '%s' val=%d\n", q - pack_start, ++ hexdigit, val); ++ } ++ len = q - pack_start; ++ xframe = ALLOC_SEND_XFRAME(xbus); ++ if (!xframe) { ++ count = -ENOMEM; ++ goto out; ++ } ++ if (len > max_len) ++ len = max_len; ++ atomic_set(&xframe->frame_len, len); ++ memcpy(xframe->packets, pack_start, len); /* FIXME: checksum? */ ++ dump_xframe("COMMAND", xbus, xframe, debug); ++ send_cmd_frame(xbus, xframe); ++out: ++ kfree(buf); ++ return count; ++} ++ ++static int proc_xbus_command_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = PDE_DATA(inode); ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops proc_xbus_command_ops = { ++ .proc_open = proc_xbus_command_open, ++ .proc_write = proc_xbus_command_write, ++}; ++#else ++static const struct file_operations proc_xbus_command_ops = { ++ .owner = THIS_MODULE, ++ .open = proc_xbus_command_open, ++ .write = proc_xbus_command_write, ++}; ++#endif ++#endif ++ ++static int xpp_proc_read_show(struct seq_file *sfile, void *data) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_BUSES; i++) { ++ xbus_t *xbus = get_xbus(__func__, i); ++ ++ if (xbus) { ++ seq_printf(sfile, ++ "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n", ++ xbus->busname, xbus->connector, xbus->label, ++ (XBUS_FLAGS(xbus, CONNECTED)) ? "connected" ++ : "missing"); ++ put_xbus(__func__, xbus); ++ } ++ } ++#if 0 ++ seq_printf(sfile, "<-- len=%d\n", len); ++#endif ++ return 0; ++} ++ ++static int xpp_proc_read_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, xpp_proc_read_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops xpp_proc_read_ops = { ++ .proc_open = xpp_proc_read_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations xpp_proc_read_ops = { ++ .owner = THIS_MODULE, ++ .open = xpp_proc_read_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++#endif ++ ++static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ++ ushort max_send_size, ++ struct device *transport_device, void *priv) ++{ ++ BUG_ON(!xbus); ++ BUG_ON(!ops); ++ BUG_ON(!ops->xframe_send_pcm); ++ BUG_ON(!ops->xframe_send_cmd); ++ BUG_ON(!ops->alloc_xframe); ++ BUG_ON(!ops->free_xframe); ++ xbus->transport.ops = ops; ++ xbus->transport.max_send_size = max_send_size; ++ xbus->transport.transport_device = transport_device; ++ xbus->transport.priv = priv; ++ xbus->transport.xbus_state = XBUS_STATE_START; ++ spin_lock_init(&xbus->transport.state_lock); ++ spin_lock_init(&xbus->transport.lock); ++ atomic_set(&xbus->transport.transport_refcount, 0); ++ xbus_setflags(xbus, XBUS_FLAG_CONNECTED, 0); ++ init_waitqueue_head(&xbus->transport.transport_unused); ++} ++ ++static void transport_destroy(xbus_t *xbus) ++{ ++ int ret; ++ ++ BUG_ON(!xbus); ++ XBUS_DBG(DEVICES, xbus, "Waiting... (transport_refcount=%d)\n", ++ atomic_read(&xbus->transport.transport_refcount)); ++ ret = ++ wait_event_interruptible(xbus->transport.transport_unused, ++ atomic_read(&xbus->transport. ++ transport_refcount) == 0); ++ if (ret) ++ XBUS_ERR(xbus, ++ "Waiting for transport_refcount interrupted!!!\n"); ++ xbus->transport.ops = NULL; ++ xbus->transport.priv = NULL; ++} ++ ++struct xbus_ops *transportops_get(xbus_t *xbus) ++{ ++ struct xbus_ops *ops; ++ ++ BUG_ON(!xbus); ++ atomic_inc(&xbus->transport.transport_refcount); ++ ops = xbus->transport.ops; ++ if (!ops) ++ atomic_dec(&xbus->transport.transport_refcount); ++ /* fall through */ ++ return ops; ++} ++EXPORT_SYMBOL(transportops_get); ++ ++void transportops_put(xbus_t *xbus) ++{ ++ struct xbus_ops *ops; ++ ++ BUG_ON(!xbus); ++ ops = xbus->transport.ops; ++ BUG_ON(!ops); ++ if (atomic_dec_and_test(&xbus->transport.transport_refcount)) ++ wake_up(&xbus->transport.transport_unused); ++} ++EXPORT_SYMBOL(transportops_put); ++ ++/*------------------------- Initialization -------------------------*/ ++static void xbus_core_cleanup(void) ++{ ++ finalize_xbuses_array(); ++#ifdef CONFIG_PROC_FS ++ if (proc_xbuses) { ++ DBG(PROC, "Removing " PROC_XBUSES " from proc\n"); ++ remove_proc_entry(PROC_XBUSES, xpp_proc_toplevel); ++ proc_xbuses = NULL; ++ } ++#endif ++} ++ ++int __init xbus_core_init(void) ++{ ++ int ret = 0; ++ ++ if (dahdi_autoreg == 1) { ++ NOTICE("WARNING: The dahdi_autoreg parameter is deprecated " \ ++ "-- just set dahdi.auto_assign_spans=0\n"); ++ } ++ initialize_xbuses_array(); ++#ifdef PROTOCOL_DEBUG ++ INFO("FEATURE: with PROTOCOL_DEBUG\n"); ++#endif ++#ifdef CONFIG_PROC_FS ++ proc_xbuses = proc_create_data(PROC_XBUSES, 0444, xpp_proc_toplevel, ++ &xpp_proc_read_ops, NULL); ++ if (!proc_xbuses) { ++ ERR("Failed to create proc file %s\n", PROC_XBUSES); ++ ret = -EFAULT; ++ goto err; ++ } ++#endif ++ if ((ret = xpp_driver_init()) < 0) ++ goto err; ++ return 0; ++err: ++ xbus_core_cleanup(); ++ return ret; ++} ++ ++void xbus_core_shutdown(void) ++{ ++ xbus_core_cleanup(); ++ xpp_driver_exit(); ++} +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xbus-core.h linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-core.h +--- linux-source-4.19/drivers/dahdi/xpp/xbus-core.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-core.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,366 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ */ ++#ifndef XBUS_CORE_H ++#define XBUS_CORE_H ++ ++#include ++#include /* for tasklets */ ++#include ++#include "xpd.h" ++#include "xframe_queue.h" ++#include "xbus-pcm.h" ++ ++#define MAX_BUSES 128 ++#define XFRAME_DATASIZE 512 ++#define MAX_ENV_STR 40 ++ ++/* forward declarations */ ++struct xbus_workqueue; ++ ++#ifdef __KERNEL__ ++ ++struct xbus_ops { ++ int (*xframe_send_pcm) (xbus_t *xbus, xframe_t *xframe); ++ int (*xframe_send_cmd) (xbus_t *xbus, xframe_t *xframe); ++ xframe_t *(*alloc_xframe) (xbus_t *xbus, gfp_t gfp_flags); ++ void (*free_xframe) (xbus_t *xbus, xframe_t *xframe); ++}; ++ ++/* ++ * XBUS statistics counters ++ */ ++enum { ++ XBUS_N_UNITS, ++ XBUS_N_TX_XFRAME_PCM, ++ XBUS_N_RX_XFRAME_PCM, ++ XBUS_N_TX_PACK_PCM, ++ XBUS_N_RX_PACK_PCM, ++ XBUS_N_TX_BYTES, ++ XBUS_N_RX_BYTES, ++ XBUS_N_TX_PCM_FRAG, ++ XBUS_N_RX_CMD, ++ XBUS_N_TX_CMD, ++}; ++ ++#define XBUS_COUNTER(xbus, counter) ((xbus)->counters[XBUS_N_ ## counter]) ++ ++#define C_(x) [ XBUS_N_ ## x ] = { #x } ++ ++/* yucky, make an instance so we can size it... */ ++static struct xbus_counters { ++ char *name; ++} xbus_counters[] = { ++C_(UNITS), C_(TX_XFRAME_PCM), C_(RX_XFRAME_PCM), C_(TX_PACK_PCM), ++ C_(RX_PACK_PCM), C_(TX_BYTES), C_(RX_BYTES), ++ C_(TX_PCM_FRAG), C_(RX_CMD), C_(TX_CMD),}; ++ ++#undef C_ ++ ++#define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters) ++ ++enum xbus_state { ++ XBUS_STATE_START, ++ XBUS_STATE_IDLE, ++ XBUS_STATE_SENT_REQUEST, ++ XBUS_STATE_RECVD_DESC, ++ XBUS_STATE_READY, ++ XBUS_STATE_DEACTIVATING, ++ XBUS_STATE_DEACTIVATED, ++ XBUS_STATE_FAIL, ++}; ++ ++const char *xbus_statename(enum xbus_state st); ++ ++struct xbus_transport { ++ struct xbus_ops *ops; ++ void *priv; ++ struct device *transport_device; ++ ushort max_send_size; ++ enum xbus_state xbus_state; ++ unsigned long transport_flags; ++ spinlock_t state_lock; ++ atomic_t transport_refcount; ++ wait_queue_head_t transport_unused; ++ spinlock_t lock; ++ char model_string[MAX_ENV_STR]; ++}; ++ ++#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size) ++#define XBUS_STATE(xbus) ((xbus)->transport.xbus_state) ++#define XBUS_IS(xbus, st) (XBUS_STATE(xbus) == XBUS_STATE_ ## st) ++#define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL) ++ ++#define XBUS_FLAG_CONNECTED 0 ++#define XBUS_FLAGS(xbus, flg) \ ++ test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags)) ++ ++struct xbus_ops *transportops_get(xbus_t *xbus); ++void transportops_put(xbus_t *xbus); ++ ++/* ++ * Encapsulate all poll related data of a single xbus. ++ */ ++struct xbus_workqueue { ++ struct workqueue_struct *wq; ++ struct work_struct xpds_init_work; ++ bool xpds_init_done; ++ struct list_head card_list; ++ int num_units; ++ int num_units_initialized; ++ wait_queue_head_t wait_for_xpd_initialization; ++ spinlock_t worker_lock; ++ struct semaphore running_initialization; ++}; ++ ++/* ++ * Allocate/Free an xframe from pools of empty xframes. ++ * Calls to {get, put}_xframe are wrapped in ++ * the macros bellow, so we take/return it ++ * to the correct pool. ++ */ ++xframe_t *get_xframe(struct xframe_queue *q); ++void put_xframe(struct xframe_queue *q, xframe_t *xframe); ++ ++#define ALLOC_SEND_XFRAME(xbus) \ ++ get_xframe(&(xbus)->send_pool) ++#define ALLOC_RECV_XFRAME(xbus) \ ++ get_xframe(&(xbus)->receive_pool) ++#define FREE_SEND_XFRAME(xbus, xframe) \ ++ put_xframe(&(xbus)->send_pool, (xframe)) ++#define FREE_RECV_XFRAME(xbus, xframe) \ ++ put_xframe(&(xbus)->receive_pool, (xframe)) ++ ++xbus_t *xbus_num(uint num); ++xbus_t *get_xbus(const char *msg, uint num); ++void put_xbus(const char *msg, xbus_t *xbus); ++int refcount_xbus(xbus_t *xbus); ++ ++/* ++ * Echo canceller related data ++ */ ++#define ECHO_TIMESLOTS 128 ++ ++struct echoops { ++ int (*ec_set) (xpd_t *xpd, int pos, bool on); ++ int (*ec_get) (xpd_t *xpd, int pos); ++ int (*ec_update) (xbus_t *xbus); ++ void (*ec_dump) (xbus_t *xbus); ++}; ++ ++struct xbus_echo_state { ++ const struct echoops *echoops; ++ __u8 timeslots[ECHO_TIMESLOTS]; ++ int xpd_idx; ++ struct device_attribute *da[MAX_XPDS]; ++}; ++#define ECHOOPS(xbus) ((xbus)->echo_state.echoops) ++#define EC_METHOD(name, xbus) (ECHOOPS(xbus)->name) ++#define CALL_EC_METHOD(name, xbus, ...) (EC_METHOD(name, (xbus))(__VA_ARGS__)) ++ ++/* ++ * An xbus is a transport layer for Xorcom Protocol commands ++ */ ++struct xbus { ++ char busname[XBUS_NAMELEN]; /* set by xbus_new() */ ++ ++ /* low-level bus drivers set these 2 fields */ ++ char connector[XBUS_DESCLEN]; ++ char label[LABEL_SIZE]; ++ __u8 revision; /* Protocol revision */ ++ struct xbus_transport transport; ++ struct dahdi_device *ddev; ++ ++ int num; ++ struct xpd *xpds[MAX_XPDS]; ++ struct xbus_echo_state echo_state; ++ ++ int command_tick_counter; ++ int usec_nosend; /* Firmware flow control */ ++ struct xframe_queue command_queue; ++ wait_queue_head_t command_queue_empty; ++ ++ struct xframe_queue send_pool; /* empty xframes for send */ ++ struct xframe_queue receive_pool; /* empty xframes for receive */ ++ ++ /* tasklet processing */ ++ struct xframe_queue receive_queue; ++ struct tasklet_struct receive_tasklet; ++ int cpu_rcv_intr[NR_CPUS]; ++ int cpu_rcv_tasklet[NR_CPUS]; ++ ++ struct quirks { ++ unsigned int has_fxo:1; ++ unsigned int has_digital_span:1; ++ } quirks; ++ bool self_ticking; ++ enum sync_mode sync_mode; ++ /* Managed by low-level drivers: */ ++ enum sync_mode sync_mode_default; ++ struct timer_list command_timer; ++ unsigned int xbus_frag_count; ++ struct xframe_queue pcm_tospan; ++ ++ struct xpp_ticker ticker; /* for tick rate */ ++ struct xpp_drift drift; /* for tick offset */ ++ ++ atomic_t pcm_rx_counter; ++ unsigned int global_counter; ++ ++ /* Device-Model */ ++ struct device astribank; ++#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank) ++ struct kref kref; ++#define kref_to_xbus(k) container_of(k, struct xbus, kref) ++ ++ spinlock_t lock; ++ ++ /* PCM metrics */ ++ ktime_t last_tx_sync; ++ ktime_t last_rx_sync; ++ unsigned long max_tx_sync; ++ unsigned long min_tx_sync; ++ unsigned long max_rx_sync; ++ unsigned long min_rx_sync; ++ unsigned long max_rx_process; /* packet processing time (usec) */ ++#ifdef SAMPLE_TICKS ++#define SAMPLE_SIZE 1000 ++ int sample_ticks[SAMPLE_SIZE]; ++ bool sample_running; ++ int sample_pos; ++#endif ++ ++ struct xbus_workqueue worker; ++ ++ /* ++ * Sync adjustment ++ */ ++ int sync_adjustment; ++ int sync_adjustment_offset; ++ ktime_t pll_updated_at; ++ ++ atomic_t num_xpds; ++ ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *proc_xbus_dir; ++ struct proc_dir_entry *proc_xbus_summary; ++#ifdef PROTOCOL_DEBUG ++ struct proc_dir_entry *proc_xbus_command; ++#endif ++#endif ++ ++ /* statistics */ ++ int counters[XBUS_COUNTER_MAX]; ++}; ++#endif ++ ++#define XFRAME_MAGIC 123456L ++ ++struct xframe { ++ unsigned long xframe_magic; ++ struct list_head frame_list; ++ atomic_t frame_len; ++ xbus_t *xbus; ++ ktime_t kt_created; ++ ktime_t kt_queued; ++ ktime_t kt_submitted; ++ ktime_t kt_received; ++ /* filled by transport layer */ ++ size_t frame_maxlen; ++ __u8 *packets; /* max XFRAME_DATASIZE */ ++ __u8 *first_free; ++ int usec_towait; /* prevent overflowing AB */ ++ void *priv; ++}; ++ ++void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, ++ void *priv); ++ ++#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len) ++ ++int xbus_core_init(void); /* Initializer */ ++void xbus_core_shutdown(void); /* Terminator */ ++ ++/* Frame handling */ ++void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, ++ int debug); ++int send_cmd_frame(xbus_t *xbus, xframe_t *xframe); ++ ++/* ++ * Return pointer to next packet slot in the frame ++ * or NULL if the frame is full. ++ */ ++xpacket_t *xframe_next_packet(xframe_t *xframe, int len); ++ ++/* XBUS handling */ ++ ++/* ++ * Map: unit+subunit <--> index in xbus->xpds[] ++ */ ++#define XPD_IDX(unit, subunit) ((unit) * MAX_SUBUNIT + (subunit)) ++#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT) ++#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT) ++ ++xpd_t *xpd_of(const xbus_t *xbus, int xpd_num); ++xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit); ++int xbus_check_unique(xbus_t *xbus); ++bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate); ++bool xbus_setflags(xbus_t *xbus, int flagbit, bool on); ++xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, ++ struct device *transport_device, void *priv); ++void xbus_free(xbus_t *xbus); ++int xbus_connect(xbus_t *xbus); ++int xbus_activate(xbus_t *xbus); ++void xbus_deactivate(xbus_t *xbus); ++void xbus_disconnect(xbus_t *xbus); ++void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe); ++int xbus_process_worker(xbus_t *xbus); ++int waitfor_xpds(xbus_t *xbus, char *buf); ++ ++int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit); ++int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd); ++ ++int subunits_of_xpd(const struct unit_descriptor* unit_descriptor, ++ const xproto_table_t *proto_table); ++/* sysfs */ ++int xpd_device_register(xbus_t *xbus, xpd_t *xpd); ++void xpd_device_unregister(xpd_t *xpd); ++int echocancel_xpd(xpd_t *xpd, int on); ++ ++int xbus_is_registered(xbus_t *xbus); ++int xbus_register_dahdi_device(xbus_t *xbus); ++void xbus_unregister_dahdi_device(xbus_t *xbus); ++ ++int xpp_driver_init(void); ++void xpp_driver_exit(void); ++int xbus_sysfs_transport_create(xbus_t *xbus); ++void xbus_sysfs_transport_remove(xbus_t *xbus); ++int xbus_sysfs_create(xbus_t *xbus); ++void xbus_sysfs_remove(xbus_t *xbus); ++ ++void astribank_uevent_send(xbus_t *xbus, enum kobject_action act); ++ ++static inline s64 xpp_ktime_sec_delta(ktime_t later, ktime_t earlier) ++{ ++ return ktime_divns(ktime_sub(later, earlier), NSEC_PER_SEC); ++} ++ ++#endif /* XBUS_CORE_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xbus-pcm.c linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-pcm.c +--- linux-source-4.19/drivers/dahdi/xpp/xbus-pcm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-pcm.c 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,1334 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2007, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xbus-pcm.h" ++#include "xbus-core.h" ++#include "xpp_dahdi.h" ++#include "dahdi_debug.h" ++#include "parport_debug.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++extern int debug; ++#ifdef OPTIMIZE_CHANMUTE ++static DEF_PARM_BOOL(optimize_chanmute, 1, 0644, ++ "Optimize by muting inactive channels"); ++#endif ++ ++static DEF_PARM(int, disable_pcm, 0, 0644, "Disable all PCM transmissions"); ++#ifdef DEBUG_PCMTX ++DEF_PARM(int, pcmtx, -1, 0644, ++ "Forced PCM value to transmit (negative to disable)"); ++EXPORT_SYMBOL(pcmtx); ++DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value"); ++EXPORT_SYMBOL(pcmtx_chan); ++#endif ++static DEF_PARM_BOOL(disable_pll_sync, 0, 0644, ++ "Disable automatic adjustment of AB clocks"); ++ ++static xbus_t *syncer; /* current syncer */ ++static atomic_t xpp_tick_counter = ATOMIC_INIT(0); ++static struct xpp_ticker dahdi_ticker; ++/* ++ * The ref_ticker points to the current referece tick source. ++ * I.e: one of our AB or dahdi_ticker ++ */ ++static struct xpp_ticker *ref_ticker; ++static DEFINE_SPINLOCK(ref_ticker_lock); ++static DEFINE_SPINLOCK(elect_syncer_lock); ++/* from /sys/bus/astribanks/drivers/xppdrv/sync */ ++static bool force_dahdi_sync; ++static xbus_t *global_ticker; ++static struct xpp_ticker global_ticks_series; ++ ++#define PROC_SYNC "sync" ++/* Sampling cycle in usec */ ++#define SYNC_CYCLE 500 ++/* Samples from end of SYNC_CYCLE */ ++#define SYNC_CYCLE_SAMPLE 100 ++/* Number of SYNC_CYCLE's to converge speed */ ++#define SYNC_CONVERGE 10 ++/* Offset from ref_ticker to other AB's */ ++#define SYNC_CENTER 500 ++/* If within +/-SYNC_DELTA, try to stay there */ ++#define SYNC_DELTA 40 ++#define BIG_TICK_INTERVAL 1000 ++/* maximal firmware drift unit (hardware limit 63) */ ++#define SYNC_ADJ_MAX 20 ++ ++/* ++ * The USB bulk endpoints have a large jitter in the timing of frames ++ * from the AB to the ehci-hcd. This is because we cannot predict ++ * in which USB micro-frame our data passes. Each micro-frame is ++ * A 125 usec. ++ */ ++#define SYNC_ADJ_QUICK 1000 ++#define SYNC_ADJ_SLOW 10000 ++ ++#ifdef DAHDI_SYNC_TICK ++static unsigned int dahdi_tick_count; ++#endif ++ ++/*------------------------- SYNC Handling --------------------------*/ ++ ++static void send_drift(xbus_t *xbus, int drift); ++ ++static void ticker_set_cycle(struct xpp_ticker *ticker, int cycle) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ticker->lock, flags); ++ if (cycle < SYNC_ADJ_QUICK) ++ cycle = SYNC_ADJ_QUICK; ++ if (cycle > SYNC_ADJ_SLOW) ++ cycle = SYNC_ADJ_SLOW; ++ ticker->cycle = cycle; ++ spin_unlock_irqrestore(&ticker->lock, flags); ++} ++ ++static void xpp_ticker_init(struct xpp_ticker *ticker) ++{ ++ memset(ticker, 0, sizeof(*ticker)); ++ spin_lock_init(&ticker->lock); ++ ticker->last_sample = ktime_get(); ++ ticker->first_sample = ticker->last_sample; ++ ticker_set_cycle(ticker, SYNC_ADJ_QUICK); ++} ++ ++static int xpp_ticker_step(struct xpp_ticker *ticker, const ktime_t t) ++{ ++ unsigned long flags; ++ s64 usec; ++ bool cycled = 0; ++ ++ spin_lock_irqsave(&ticker->lock, flags); ++ ticker->last_sample = t; ++ /* rate adjust */ ++ if ((ticker->count % ticker->cycle) == ticker->cycle - 1) { ++ usec = ktime_us_delta(ticker->last_sample, ++ ticker->first_sample); ++ ticker->first_sample = ticker->last_sample; ++ ticker->tick_period = usec / ticker->cycle; ++ cycled = 1; ++ } ++ ticker->count++; ++ spin_unlock_irqrestore(&ticker->lock, flags); ++ return cycled; ++} ++ ++/* ++ * No locking. It is called only from: ++ * - update_sync_master() in a globall spinlock protected code. ++ * - initalization. ++ */ ++static inline void xbus_drift_clear(xbus_t *xbus) ++{ ++ struct xpp_drift *di = &xbus->drift; ++ ++ di->last_lost_tick = ktime_get(); ++ ticker_set_cycle(&xbus->ticker, SYNC_ADJ_QUICK); ++ di->max_speed = -SYNC_ADJ_MAX; ++ di->min_speed = SYNC_ADJ_MAX; ++} ++ ++void xpp_drift_init(xbus_t *xbus) ++{ ++ memset(&xbus->drift, 0, sizeof(xbus->drift)); ++ spin_lock_init(&xbus->drift.lock); ++ xpp_ticker_init(&xbus->ticker); ++ xbus_drift_clear(xbus); ++} ++ ++#ifdef SAMPLE_TICKS ++static void sample_tick(xbus_t *xbus, int sample) ++{ ++ if (!xbus->sample_running) ++ return; ++ if (xbus->sample_pos < SAMPLE_SIZE) ++ xbus->sample_ticks[xbus->sample_pos++] = sample; ++ else { ++ xbus->sample_running = 0; ++ xbus->sample_pos = 0; ++ } ++} ++#else ++#define sample_tick(x, y) ++#endif ++ ++/* ++ * The following function adjust the clock of an astribank according ++ * to our reference clock (another astribank or another DAHDI device). ++ * ++ * It is VERY hard to stabilise these corrections: ++ * - The measurments are affected by 125usec USB micro-frames. ++ * - However, if we are off by more than +/-500usec we are risking ++ * loosing frames. ++ * ++ * Every change must be tested rigorously with many device combinations ++ * including abrupt changes in sync -- to verify the stability of the ++ * algorithm. ++ */ ++static void xpp_drift_step(xbus_t *xbus, const ktime_t kt) ++{ ++ struct xpp_drift *di = &xbus->drift; ++ struct xpp_ticker *ticker = &xbus->ticker; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&di->lock, flags); ++ xpp_ticker_step(&xbus->ticker, kt); ++ /* ++ * Do we need to be synchronized and is there an established reference ++ * ticker (another Astribank or another DAHDI device) already? ++ */ ++ if (ref_ticker && ref_ticker != &xbus->ticker && syncer ++ && xbus->sync_mode == SYNC_MODE_PLL) { ++ int new_delta_tick = ticker->count - ref_ticker->count; ++ int lost_ticks = new_delta_tick - di->delta_tick; ++ s64 usec_delta; ++ ++ di->delta_tick = new_delta_tick; ++ if (lost_ticks) { ++ static int rate_limit; ++ ++ /* ++ * We just lost some ticks. Just report it and don't ++ * try to adjust anything until we are stable again. ++ */ ++ di->lost_ticks++; ++ di->lost_tick_count += abs(lost_ticks); ++ if ((rate_limit++ % 1003) == 0) { ++ /* FIXME: This should be a NOTICE. ++ * However we have several false ones at ++ * startup. ++ */ ++ XBUS_DBG(SYNC, xbus, "Lost %d tick%s\n", ++ lost_ticks, ++ (abs(lost_ticks) > 1) ? "s" : ""); ++ } ++ if (abs(lost_ticks) > 100) { ++ xbus_drift_clear(xbus); ++ ticker->count = ref_ticker->count; ++ } ++ } else { ++ /* Sample a delta */ ++ usec_delta = ktime_us_delta(ticker->last_sample, ++ ref_ticker->last_sample); ++ sample_tick(xbus, usec_delta); ++ if ((ticker->count % SYNC_CYCLE) > ++ (SYNC_CYCLE - SYNC_CYCLE_SAMPLE)) ++ di->delta_sum += usec_delta; ++ ++ if ((ticker->count % SYNC_CYCLE) == 0) { ++ /* ++ * Full sampling cycle passed. Let's calculate ++ */ ++ int offset = ++ di->delta_sum / SYNC_CYCLE_SAMPLE - ++ SYNC_CENTER; ++ int offset_prev = di->offset_prev; ++ int speed = xbus->sync_adjustment; ++ int fix = 0; ++ int best_speed = ++ (di->max_speed + di->min_speed) >> 1; ++ ++ if (offset > 0 && offset < SYNC_DELTA) { ++ speed = best_speed - 1; ++ } else if (offset < 0 && offset > -SYNC_DELTA) { ++ speed = best_speed + 1; ++ } else { ++ if (offset > 0) { ++ if (offset > offset_prev) ++ fix--; ++ } else { ++ if (offset < offset_prev) ++ fix++; ++ } ++ speed += fix; ++ } ++ if (speed < -SYNC_ADJ_MAX) ++ speed = -SYNC_ADJ_MAX; ++ if (speed > SYNC_ADJ_MAX) ++ speed = SYNC_ADJ_MAX; ++ if (speed < di->min_speed) ++ di->min_speed = speed; ++ if (speed > di->max_speed) ++ di->max_speed = speed; ++ if (offset > di->offset_max) ++ di->offset_max = offset; ++ if (offset < di->offset_min) ++ di->offset_min = offset; ++ ++ XBUS_DBG(SYNC, xbus, ++ "offset: %d, min_speed=%d, max_speed=%d, usec_delta(last)=%lld\n", ++ offset_prev, di->min_speed, ++ di->max_speed, usec_delta); ++ XBUS_DBG(SYNC, xbus, ++ "ADJ: speed=%d (best_speed=%d) fix=%d\n", ++ speed, best_speed, fix); ++ xbus->sync_adjustment_offset = speed; ++ if (xbus != syncer ++ && xbus->sync_adjustment != speed) ++ send_drift(xbus, speed); ++ di->sync_inaccuracy = ++ abs(offset) + abs(di->offset_range) / 2; ++ if (ticker->count >= SYNC_CYCLE * SYNC_CONVERGE) { ++ di->offset_range = ++ di->offset_max - di->offset_min; ++ di->offset_min = INT_MAX; ++ di->offset_max = -INT_MAX; ++ if (di->max_speed > best_speed) ++ di->max_speed--; ++ if (di->min_speed < best_speed) ++ di->min_speed++; ++ } ++ di->offset_prev = offset; ++ di->delta_sum = 0; ++ } ++ } ++ } ++ spin_unlock_irqrestore(&di->lock, flags); ++} ++ ++const char *sync_mode_name(enum sync_mode mode) ++{ ++ static const char *sync_mode_names[] = { ++ [SYNC_MODE_AB] = "AB", ++ [SYNC_MODE_NONE] = "NONE", ++ [SYNC_MODE_PLL] = "PLL", ++ [SYNC_MODE_QUERY] = "QUERY", ++ }; ++ if (mode >= ARRAY_SIZE(sync_mode_names)) ++ return NULL; ++ return sync_mode_names[mode]; ++} ++EXPORT_SYMBOL(sync_mode_name); ++ ++/* ++ * Caller must aquire/release the 'ref_ticker_lock' spinlock ++ */ ++static void xpp_set_syncer(xbus_t *xbus, bool on) ++{ ++ if (!xbus) { /* Special case, no more syncers */ ++ DBG(SYNC, "No more syncers\n"); ++ syncer = NULL; ++ if (ref_ticker != &dahdi_ticker) ++ ref_ticker = NULL; ++ return; ++ } ++ if (syncer != xbus && on) { ++ XBUS_DBG(SYNC, xbus, "New syncer\n"); ++ syncer = xbus; ++ } else if (syncer == xbus && !on) { ++ XBUS_DBG(SYNC, xbus, "Lost syncer\n"); ++ syncer = NULL; ++ if (ref_ticker != &dahdi_ticker) ++ ref_ticker = NULL; ++ } else ++ XBUS_DBG(SYNC, xbus, "ignore %s (current syncer: %s)\n", ++ (on) ? "ON" : "OFF", ++ (syncer) ? syncer->busname : "NO-SYNC"); ++} ++ ++static void xbus_command_timer(TIMER_DATA_TYPE timer) ++{ ++ xbus_t *xbus = from_timer(xbus, timer, command_timer); ++ ++ BUG_ON(!xbus); ++ xbus_command_queue_tick(xbus); ++ if (!xbus->self_ticking) /* Must be 1KHz rate */ ++ mod_timer(&xbus->command_timer, jiffies + 1); ++} ++ ++void xbus_set_command_timer(xbus_t *xbus, bool on) ++{ ++ XBUS_DBG(SYNC, xbus, "%s\n", (on) ? "ON" : "OFF"); ++ if (on) { ++ if (!timer_pending(&xbus->command_timer)) { ++ XBUS_DBG(SYNC, xbus, "add_timer\n"); ++ timer_setup(&xbus->command_timer, ++ xbus_command_timer, 0); ++ mod_timer(&xbus->command_timer, jiffies + 1); ++ } ++ } else if (timer_pending(&xbus->command_timer)) { ++ XBUS_DBG(SYNC, xbus, "del_timer\n"); ++ del_timer(&xbus->command_timer); ++ } ++ xbus->self_ticking = !on; ++} ++ ++/* ++ * Called when the Astribank replies to a sync change request ++ */ ++void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift) ++{ ++ unsigned long flags; ++ unsigned long flags2; ++ ++ spin_lock_irqsave(&xbus->lock, flags); ++ spin_lock_irqsave(&ref_ticker_lock, flags2); ++ xbus->sync_adjustment = (signed char)drift; ++ if (xbus->sync_mode == mode) { ++ XBUS_DBG(SYNC, xbus, "Already in mode '%s'. Ignored\n", ++ sync_mode_name(mode)); ++ goto out; ++ } ++ XBUS_DBG(SYNC, xbus, "Mode %s (%d), drift=%d (pcm_rx_counter=%d)\n", ++ sync_mode_name(mode), mode, drift, ++ atomic_read(&xbus->pcm_rx_counter)); ++ switch (mode) { ++ case SYNC_MODE_AB: ++ xbus->sync_mode = mode; ++ xbus_set_command_timer(xbus, 0); ++ xpp_set_syncer(xbus, 1); ++ global_ticker = xbus; ++ break; ++ case SYNC_MODE_PLL: ++ xbus->sync_mode = mode; ++ xbus_set_command_timer(xbus, 0); ++ xpp_set_syncer(xbus, 0); ++ global_ticker = xbus; ++ break; ++ case SYNC_MODE_NONE: /* lost sync source */ ++ xbus->sync_mode = mode; ++ xbus_set_command_timer(xbus, 1); ++ xpp_set_syncer(xbus, 0); ++ break; ++ case SYNC_MODE_QUERY: /* ignore */ ++ break; ++ default: ++ XBUS_ERR(xbus, "%s: unknown mode=0x%X\n", __func__, mode); ++ } ++out: ++ spin_unlock_irqrestore(&ref_ticker_lock, flags2); ++ spin_unlock_irqrestore(&xbus->lock, flags); ++} ++EXPORT_SYMBOL(got_new_syncer); ++ ++void xbus_request_sync(xbus_t *xbus, enum sync_mode mode) ++{ ++ unsigned long flags; ++ ++ BUG_ON(!xbus); ++ XBUS_DBG(SYNC, xbus, "sent request (mode=%d)\n", mode); ++ CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, mode, 0); ++ if (mode == SYNC_MODE_NONE) { ++ /* ++ * We must deselect the syncer *now* and not wait for the ++ * reply from the AB. Otherwise, a disconnect of the syncing ++ * AB would result in a corrupted 'syncer'. ++ */ ++ spin_lock_irqsave(&ref_ticker_lock, flags); ++ xpp_set_syncer(xbus, 0); ++ spin_unlock_irqrestore(&ref_ticker_lock, flags); ++ /* ++ * We must activate timer now since the commands go to ++ * the command queue, and we should maintain something to ++ * "tick" meanwhile until the AB get these commands and ++ * start being "self_ticking". ++ */ ++ xbus_set_command_timer(xbus, 1); ++ } ++} ++EXPORT_SYMBOL(xbus_request_sync); ++ ++static void reset_sync_counters(void) ++{ ++ int i; ++ ++ //DBG(SYNC, "%d\n", atomic_read(&xpp_tick_counter)); ++ for (i = 0; i < MAX_BUSES; i++) { ++ xbus_t *xbus = get_xbus(__func__, i); ++ ++ if (xbus == NULL) ++ continue; ++ /* ++ * Don't send to non self_ticking Astribanks: ++ * - Maybe they didn't finish initialization ++ * - Or maybe they didn't answer us in the first place ++ (e.g: wrong firmware version, etc). ++ */ ++ if (xbus->self_ticking) { ++ if (!XBUS_FLAGS(xbus, CONNECTED)) { ++ XBUS_DBG(GENERAL, xbus, ++ "Dropped packet. Is shutting down.\n"); ++ } else { ++ /* Reset sync LEDs once in a while */ ++ CALL_PROTO(GLOBAL, RESET_SYNC_COUNTERS, xbus, ++ NULL); ++ } ++ } ++ put_xbus(__func__, xbus); ++ } ++} ++ ++static void send_drift(xbus_t *xbus, int drift) ++{ ++ const ktime_t now = ktime_get(); ++ const char *msg; ++ s64 msec_delta; ++ ++ BUG_ON(abs(drift) > SYNC_ADJ_MAX); ++ if (drift > xbus->sync_adjustment) ++ msg = "up"; ++ else ++ msg = "down"; ++ msec_delta = ktime_ms_delta(now, xbus->pll_updated_at); ++ XBUS_DBG(SYNC, xbus, ++ "%sDRIFT adjust %s (%d) (last update %lld seconds ago)\n", ++ (disable_pll_sync) ? "Fake " : "", msg, drift, ++ msec_delta / MSEC_PER_SEC); ++ if (!disable_pll_sync) ++ CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL, ++ drift); ++ xbus->pll_updated_at = now; ++} ++ ++static void global_tick(void) ++{ ++ ktime_t now = ktime_get(); ++ ++ atomic_inc(&xpp_tick_counter); ++ if ((atomic_read(&xpp_tick_counter) % BIG_TICK_INTERVAL) == 0) ++ reset_sync_counters(); ++ xpp_ticker_step(&global_ticks_series, now); ++} ++ ++#ifdef DAHDI_SYNC_TICK ++void dahdi_sync_tick(struct dahdi_span *span, int is_master) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ static int redundant_ticks; /* for extra spans */ ++ ktime_t now; ++ ++ if (!force_dahdi_sync) ++ goto noop; ++ now = ktime_get(); ++ BUG_ON(!xpd); ++ /* ++ * Detect if any of our spans is dahdi sync master ++ */ ++ if (is_master) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 10003) == 0) ++ XPD_NOTICE(xpd, ++ "Is a DAHDI sync master: " ++ "ignore sync from DAHDI\n"); ++ goto noop; ++ } ++ /* Now we know for sure someone else is dahdi sync master */ ++ if (syncer) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 5003) == 0) ++ XBUS_DBG(SYNC, syncer, ++ "is a SYNCer: ignore sync from DAHDI\n"); ++ goto noop; ++ } ++ /* ignore duplicate calls from all our registered spans */ ++ if ((redundant_ticks++ % total_registered_spans()) != 0) { ++#if 0 ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) < 16) ++ XPD_NOTICE(xpd, "boop (%d)\n", dahdi_tick_count); ++#endif ++ goto noop; ++ } ++ xpp_ticker_step(&dahdi_ticker, now); ++ dahdi_tick_count++; ++ //flip_parport_bit(1); ++noop: ++ return; ++} ++EXPORT_SYMBOL(dahdi_sync_tick); ++#endif ++ ++/* ++ * called from elect_syncer() ++ * if new_syncer is NULL, than we move all to SYNC_MODE_PLL ++ * for DAHDI sync. ++ */ ++static void update_sync_master(xbus_t *new_syncer, bool force_dahdi) ++{ ++ const char *msg; ++ int i; ++ unsigned long flags; ++ ++ WARN_ON(new_syncer && force_dahdi); /* Ambigous */ ++ force_dahdi_sync = force_dahdi; ++ msg = (force_dahdi_sync) ? "DAHDI" : "NO-SYNC"; ++ DBG(SYNC, "%s => %s\n", (syncer) ? syncer->busname : msg, ++ (new_syncer) ? new_syncer->busname : msg); ++ /* ++ * This global locking protects: ++ * - The ref_ticker so it won't be used while we change it. ++ * - The xbus_drift_clear() from corrupting driftinfo data. ++ * It's important to set ref_ticker now: ++ * - We cannot make the new xbus a syncer yet (until we get ++ * a reply from AB). Maybe it's still not self_ticking, so ++ * we must keep the timer for the command_queue to function. ++ * - However, we must not send drift commands to it, because ++ * they'll revert it to PLL instead of AB. ++ */ ++ spin_lock_irqsave(&ref_ticker_lock, flags); ++ if (syncer) ++ xbus_drift_clear(syncer); /* Clean old data */ ++ if (new_syncer) { ++ XBUS_DBG(SYNC, new_syncer, "pcm_rx_counter=%d\n", ++ atomic_read(&new_syncer->pcm_rx_counter)); ++ force_dahdi_sync = 0; ++ ref_ticker = &new_syncer->ticker; ++ xbus_drift_clear(new_syncer); /* Clean new data */ ++ xpp_set_syncer(new_syncer, 1); ++ xbus_request_sync(new_syncer, SYNC_MODE_AB); ++ } else if (force_dahdi_sync) { ++ ref_ticker = &dahdi_ticker; ++ } else { ++ ref_ticker = NULL; ++ } ++ spin_unlock_irqrestore(&ref_ticker_lock, flags); ++ DBG(SYNC, "stop unwanted syncers\n"); ++ /* Shut all down except the wanted sync master */ ++ for (i = 0; i < MAX_BUSES; i++) { ++ xbus_t *xbus = get_xbus(__func__, i); ++ if (xbus == NULL) ++ continue; ++ if (XBUS_FLAGS(xbus, CONNECTED) && xbus != new_syncer) { ++ if (xbus->self_ticking) ++ xbus_request_sync(xbus, ++ xbus->sync_mode_default); ++ else ++ XBUS_DBG(SYNC, xbus, ++ "Not self_ticking yet. Ignore\n"); ++ } ++ put_xbus(__func__, xbus); ++ } ++} ++ ++void elect_syncer(const char *msg) ++{ ++ int i; ++ int j; ++ uint timing_priority = INT_MAX; ++ xpd_t *best_xpd = NULL; ++ xbus_t *the_xbus = NULL; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&elect_syncer_lock, flags); ++ DBG(SYNC, "%s: %s syncer=%s\n", __func__, msg, ++ (syncer) ? syncer->busname : "NULL"); ++ for (i = 0; i < MAX_BUSES; i++) { ++ xbus_t *xbus = get_xbus(__func__, i); ++ ++ if (xbus == NULL) ++ continue; ++ if (XBUS_IS(xbus, READY)) { ++ if (!the_xbus) ++ the_xbus = xbus; /* First candidate */ ++ for (j = 0; j < MAX_XPDS; j++) { ++ xpd_t *xpd = xpd_of(xbus, j); ++ int prio; ++ ++ if (!xpd || !xpd->card_present ++ || !IS_PHONEDEV(xpd)) ++ continue; ++ prio = ++ CALL_PHONE_METHOD(card_timing_priority, ++ xpd); ++ if (prio < 0) { ++ DBG(SYNC, "%s/%s: skip sync\n", ++ xbus->busname, xpd->xpdname); ++ continue; ++ } ++ if (prio > 0 && prio < timing_priority) { ++ timing_priority = prio; ++ best_xpd = xpd; ++ } ++ } ++ } ++ put_xbus(__func__, xbus); ++ } ++ if (best_xpd) { ++ the_xbus = best_xpd->xbus; ++ XPD_DBG(SYNC, best_xpd, "%s: elected with priority %d\n", msg, ++ timing_priority); ++ } else if (the_xbus) { ++ XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg); ++ } else { ++ unsigned long flags; ++ ++ DBG(SYNC, "%s: No more syncers\n", msg); ++ spin_lock_irqsave(&ref_ticker_lock, flags); ++ xpp_set_syncer(NULL, 0); ++ spin_unlock_irqrestore(&ref_ticker_lock, flags); ++ the_xbus = NULL; ++ } ++ if (the_xbus != syncer) ++ update_sync_master(the_xbus, force_dahdi_sync); ++ spin_unlock_irqrestore(&elect_syncer_lock, flags); ++} ++EXPORT_SYMBOL(elect_syncer); ++ ++/* ++ * This function should be called with the xpd already locked ++ */ ++void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len) ++{ ++ PHONEDEV(xpd).pcm_len = new_pcm_len; ++ PHONEDEV(xpd).wanted_pcm_mask = new_mask; ++ XPD_DBG(SIGNAL, xpd, "pcm_len=%d wanted_pcm_mask=0x%X\n", ++ PHONEDEV(xpd).pcm_len, PHONEDEV(xpd).wanted_pcm_mask); ++} ++EXPORT_SYMBOL(update_wanted_pcm_mask); ++ ++/* ++ * This function is used by FXS/FXO. The pcm_mask argument signifies ++ * channels which should be *added* to the automatic calculation. ++ * Normally, this argument is 0. ++ */ ++void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask) ++{ ++ int i; ++ int line_count = 0; ++ unsigned long flags; ++ uint pcm_len; ++ ++ spin_lock_irqsave(&PHONEDEV(xpd).lock_recompute_pcm, flags); ++ //XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask); ++ /* Add/remove all the trivial cases */ ++ pcm_mask |= PHONEDEV(xpd).offhook_state; ++ pcm_mask |= PHONEDEV(xpd).oht_pcm_pass; ++ pcm_mask &= ~(PHONEDEV(xpd).digital_inputs); ++ pcm_mask &= ~(PHONEDEV(xpd).digital_outputs); ++ for_each_line(xpd, i) ++ if (IS_SET(pcm_mask, i)) ++ line_count++; ++ /* ++ * FIXME: Workaround a bug in sync code of the Astribank. ++ * Send dummy PCM for sync. ++ */ ++ if (xpd->addr.unit == 0 && pcm_mask == 0) { ++ pcm_mask = BIT(0); ++ line_count = 1; ++ } ++ pcm_len = (line_count) ++ ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + ++ line_count * DAHDI_CHUNKSIZE : 0L; ++ update_wanted_pcm_mask(xpd, pcm_mask, pcm_len); ++ spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags); ++} ++EXPORT_SYMBOL(generic_card_pcm_recompute); ++ ++void fill_beep(u_char *buf, int num, int duration) ++{ ++ bool alternate = (duration) ? (jiffies / (duration * 1000)) & 0x1 : 0; ++ int which; ++ u_char *snd; ++ ++ /* ++ * debug tones ++ */ ++ static u_char beep[] = { ++ 0x7F, 0xBE, 0xD8, 0xBE, 0x80, 0x41, 0x24, 0x41, /* Dima */ ++ 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */ ++ }; ++ static u_char beep_alt[] = { ++ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, /* silence */ ++ }; ++ if (alternate) { ++ which = num % ARRAY_SIZE(beep_alt); ++ snd = &beep_alt[which]; ++ } else { ++ which = num % ARRAY_SIZE(beep); ++ snd = &beep[which]; ++ } ++ memcpy(buf, snd, DAHDI_CHUNKSIZE); ++} ++ ++static void do_ec(xpd_t *xpd) ++{ ++ int i; ++ ++ for (i = 0; i < PHONEDEV(xpd).span.channels; i++) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ ++ /* Don't echo cancel BRI D-chans */ ++ if (unlikely(IS_SET(PHONEDEV(xpd).digital_signalling, i))) ++ continue; ++ /* No ec for unwanted PCM */ ++ if (!IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i)) ++ continue; ++ dahdi_ec_chunk(chan, chan->readchunk, ++ PHONEDEV(xpd).ec_chunk2[i]); ++ memcpy(PHONEDEV(xpd).ec_chunk2[i], PHONEDEV(xpd).ec_chunk1[i], ++ DAHDI_CHUNKSIZE); ++ memcpy(PHONEDEV(xpd).ec_chunk1[i], chan->writechunk, ++ DAHDI_CHUNKSIZE); ++ } ++} ++ ++#if 0 ++/* Okay, now we get to the signalling. You have several options: */ ++ ++/* Option 1: If you're a T1 like interface, you can just provide a ++ rbsbits function and we'll assert robbed bits for you. Be sure to ++ set the DAHDI_FLAG_RBS in this case. */ ++ ++/* Opt: If the span uses A/B bits, set them here */ ++int (*rbsbits) (struct dahdi_chan * chan, int bits); ++ ++/* Option 2: If you don't know about sig bits, but do have their ++ equivalents (i.e. you can disconnect battery, detect off hook, ++ generate ring, etc directly) then you can just specify a ++ sethook function, and we'll call you with appropriate hook states ++ to set. Still set the DAHDI_FLAG_RBS in this case as well */ ++int (*hooksig) (struct dahdi_chan * chan, enum dahdi_txsig hookstate); ++ ++/* Option 3: If you can't use sig bits, you can write a function ++ which handles the individual hook states */ ++int (*sethook) (struct dahdi_chan * chan, int hookstate); ++#endif ++ ++static bool pcm_valid(xpd_t *xpd, xpacket_t *pack) ++{ ++ xpp_line_t lines = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines); ++ int i; ++ int count = 0; ++ uint16_t good_len; ++ ++ BUG_ON(!pack); ++ BUG_ON(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_READ)); ++ /* ++ * Don't use for_each_line(xpd, i) here because for BRI it will ++ * ignore the channels of the other xpd's in the same unit. ++ */ ++ for (i = 0; i < CHANNELS_PERXPD; i++) ++ if (IS_SET(lines, i)) ++ count++; ++ /* FRAMES: include opcode in calculation */ ++ good_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + count * 8; ++ if (XPACKET_LEN(pack) != good_len) { ++ static int rate_limit; ++ ++ XPD_COUNTER(xpd, RECV_ERRORS)++; ++ if ((rate_limit++ % 1000) <= 10) { ++ XPD_ERR(xpd, ++ "BAD PCM REPLY: packet_len=%d " ++ "(should be %d), count=%d\n", ++ XPACKET_LEN(pack), good_len, count); ++ dump_packet("BAD PCM REPLY", pack, 1); ++ } ++ return 0; ++ } ++ return 1; ++} ++ ++static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe) ++{ ++ unsigned long flags; ++ const ktime_t now = ktime_get(); ++ s64 usec; ++ ++ spin_lock_irqsave(&xbus->lock, flags); ++ if (unlikely(disable_pcm || !XBUS_IS(xbus, READY))) ++ goto dropit; ++ if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { ++ usec = ktime_us_delta(now, xbus->last_tx_sync); ++ xbus->last_tx_sync = now; ++ /* ignore startup statistics */ ++ if (likely ++ (atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) { ++ if (abs(usec - 1000) > TICK_TOLERANCE) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 5003) == 0) ++ XBUS_DBG(SYNC, xbus, ++ "Bad PCM TX timing(%d): usec=%lld.\n", ++ rate_limit, usec); ++ } ++ if (usec > xbus->max_tx_sync) ++ xbus->max_tx_sync = usec; ++ if (usec < xbus->min_tx_sync) ++ xbus->min_tx_sync = usec; ++ } ++ } ++ spin_unlock_irqrestore(&xbus->lock, flags); ++ /* OK, really send it */ ++ if (debug & DBG_PCM) ++ dump_xframe("TX_XFRAME_PCM", xbus, xframe, debug); ++ send_pcm_frame(xbus, xframe); ++ XBUS_COUNTER(xbus, TX_XFRAME_PCM)++; ++ return; ++dropit: ++ spin_unlock_irqrestore(&xbus->lock, flags); ++ FREE_SEND_XFRAME(xbus, xframe); ++} ++ ++/* ++ * Generic implementations of card_pcmfromspan()/card_pcmtospan() ++ * For FXS/FXO ++ */ ++void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack) ++{ ++ __u8 *pcm; ++ unsigned long flags; ++ xpp_line_t wanted_lines; ++ int i; ++ ++ BUG_ON(!xpd); ++ BUG_ON(!pack); ++ wanted_lines = PHONEDEV(xpd).wanted_pcm_mask; ++ RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = wanted_lines; ++ pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); ++ spin_lock_irqsave(&xpd->lock, flags); ++ for (i = 0; i < PHONEDEV(xpd).channels; i++) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ ++ if (IS_SET(wanted_lines, i)) { ++ if (SPAN_REGISTERED(xpd)) { ++#ifdef DEBUG_PCMTX ++ int channo = chan->channo; ++ ++ if (pcmtx >= 0 && pcmtx_chan == channo) ++ memset((u_char *)pcm, pcmtx, ++ DAHDI_CHUNKSIZE); ++ else ++#endif ++ memcpy((u_char *)pcm, chan->writechunk, ++ DAHDI_CHUNKSIZE); ++ } else ++ memset((u_char *)pcm, 0x7F, DAHDI_CHUNKSIZE); ++ pcm += DAHDI_CHUNKSIZE; ++ } ++ } ++ XPD_COUNTER(xpd, PCM_WRITE)++; ++ spin_unlock_irqrestore(&xpd->lock, flags); ++} ++EXPORT_SYMBOL(generic_card_pcm_fromspan); ++ ++void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack) ++{ ++ __u8 *pcm; ++ xpp_line_t pcm_mask; ++ xpp_line_t pcm_mute; ++ unsigned long flags; ++ int i; ++ ++ pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); ++ pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines); ++ spin_lock_irqsave(&xpd->lock, flags); ++ /* ++ * Calculate the channels we want to mute ++ */ ++ pcm_mute = ~(PHONEDEV(xpd).wanted_pcm_mask); ++ pcm_mute |= PHONEDEV(xpd).mute_dtmf | PHONEDEV(xpd).silence_pcm; ++ if (!SPAN_REGISTERED(xpd)) ++ goto out; ++ for (i = 0; i < PHONEDEV(xpd).channels; i++) { ++ volatile u_char *r = XPD_CHAN(xpd, i)->readchunk; ++ bool got_data = IS_SET(pcm_mask, i); ++ ++ if (got_data && !IS_SET(pcm_mute, i)) { ++ /* We have and want real data */ ++ // memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG ++ memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE); ++ } else ++ if (IS_SET ++ (PHONEDEV(xpd).wanted_pcm_mask | PHONEDEV(xpd). ++ silence_pcm, i)) { ++ /* Inject SILENCE */ ++ memset((u_char *)r, 0x7F, DAHDI_CHUNKSIZE); ++ if (IS_SET(PHONEDEV(xpd).silence_pcm, i)) { ++ /* ++ * This will clear the EC buffers until next ++ * tick so we don't have noise residues ++ * from the past. ++ */ ++ memset(PHONEDEV(xpd).ec_chunk2[i], 0x7F, ++ DAHDI_CHUNKSIZE); ++ memset(PHONEDEV(xpd).ec_chunk1[i], 0x7F, ++ DAHDI_CHUNKSIZE); ++ } ++ } ++ if (got_data) ++ pcm += DAHDI_CHUNKSIZE; ++ } ++out: ++ XPD_COUNTER(xpd, PCM_READ)++; ++ spin_unlock_irqrestore(&xpd->lock, flags); ++} ++EXPORT_SYMBOL(generic_card_pcm_tospan); ++ ++int generic_echocancel_timeslot(xpd_t *xpd, int pos) ++{ ++ return xpd->addr.unit * 32 + pos; ++} ++EXPORT_SYMBOL(generic_echocancel_timeslot); ++ ++int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask) ++{ ++ int i; ++ ++ BUG_ON(!xpd); ++ XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask); ++ if (!ECHOOPS(xpd->xbus)) { ++ XPD_DBG(GENERAL, xpd, ++ "No echo canceller in XBUS: Doing nothing.\n"); ++ return -EINVAL; ++ } ++ for (i = 0; i < PHONEDEV(xpd).channels; i++) { ++ int on = BIT(i) & ec_mask; ++ CALL_EC_METHOD(ec_set, xpd->xbus, xpd, i, on); ++ } ++ CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus); ++ return 0; ++} ++EXPORT_SYMBOL(generic_echocancel_setmask); ++ ++static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe) ++{ ++ __u8 *xframe_end; ++ xpacket_t *pack; ++ __u8 *p; ++ int ret = -EPROTO; /* Assume error */ ++ ++ if (debug & DBG_PCM) ++ dump_xframe("RX_XFRAME_PCM", xbus, xframe, debug); ++ /* handle content */ ++ ++ p = xframe->packets; ++ xframe_end = p + XFRAME_LEN(xframe); ++ do { ++ int len; ++ xpd_t *xpd; ++ ++ pack = (xpacket_t *)p; ++ len = XPACKET_LEN(pack); ++ /* Sanity checks */ ++ if (unlikely(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_READ))) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) { ++ XBUS_NOTICE(xbus, ++ "%s: Non-PCM packet within " ++ "a PCM xframe. (%d)\n", ++ __func__, rate_limit); ++ dump_xframe("In PCM xframe", xbus, xframe, ++ debug); ++ } ++ goto out; ++ } ++ p += len; ++ if (p > xframe_end || len < RPACKET_HEADERSIZE) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) { ++ XBUS_NOTICE(xbus, ++ "%s: Invalid packet length %d. (%d)\n", ++ __func__, len, rate_limit); ++ dump_xframe("BAD LENGTH", xbus, xframe, debug); ++ } ++ goto out; ++ } ++ xpd = ++ xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), ++ XPACKET_ADDR_SUBUNIT(pack)); ++ if (unlikely(!xpd)) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) { ++ notify_bad_xpd(__func__, xbus, ++ XPACKET_ADDR(pack), ++ "RECEIVE PCM"); ++ dump_xframe("Unknown XPD addr", xbus, xframe, ++ debug); ++ } ++ goto out; ++ } ++ if (!pcm_valid(xpd, pack)) ++ goto out; ++ if (SPAN_REGISTERED(xpd)) { ++ XBUS_COUNTER(xbus, RX_PACK_PCM)++; ++ CALL_PHONE_METHOD(card_pcm_tospan, xpd, pack); ++ } ++ } while (p < xframe_end); ++ ret = 0; /* all good */ ++ XBUS_COUNTER(xbus, RX_XFRAME_PCM)++; ++out: ++ FREE_RECV_XFRAME(xbus, xframe); ++ return ret; ++} ++ ++int generic_timing_priority(xpd_t *xpd) ++{ ++ return PHONEDEV(xpd).timing_priority; ++} ++EXPORT_SYMBOL(generic_timing_priority); ++ ++static void xbus_tick(xbus_t *xbus) ++{ ++ int i; ++ xpd_t *xpd; ++ xframe_t *xframe = NULL; ++ xpacket_t *pack = NULL; ++ bool sent_sync_bit = 0; ++ ++ /* ++ * Update dahdi ++ */ ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd = xpd_of(xbus, i); ++ if (xpd && SPAN_REGISTERED(xpd)) { ++#ifdef OPTIMIZE_CHANMUTE ++ int j; ++ xpp_line_t xmit_mask = PHONEDEV(xpd).wanted_pcm_mask; ++ ++ xmit_mask |= PHONEDEV(xpd).silence_pcm; ++ xmit_mask |= PHONEDEV(xpd).digital_signalling; ++ for_each_line(xpd, j) { ++ XPD_CHAN(xpd, j)->chanmute = (optimize_chanmute) ++ ? !IS_SET(xmit_mask, j) ++ : 0; ++ } ++#endif ++ /* ++ * calls to dahdi_transmit should be out of spinlocks, ++ * as it may call back our hook setting methods. ++ */ ++ dahdi_transmit(&PHONEDEV(xpd).span); ++ } ++ } ++ /* ++ * Fill xframes ++ */ ++ for (i = 0; i < MAX_XPDS; i++) { ++ if ((xpd = xpd_of(xbus, i)) == NULL) ++ continue; ++ if (!IS_PHONEDEV(xpd)) ++ continue; ++ if (SPAN_REGISTERED(xpd)) { ++ size_t pcm_len = PHONEDEV(xpd).pcm_len; ++ ++ if (pcm_len && xpd->card_present) { ++ do { ++#if 0 ++ /* FORCE single packet frames */ ++ pack = NULL; ++#endif ++ if (xframe && !pack) { /* FULL frame */ ++ pcm_frame_out(xbus, xframe); ++ xframe = NULL; ++ XBUS_COUNTER(xbus, ++ TX_PCM_FRAG)++; ++ } ++ if (!xframe) { /* Alloc frame */ ++ xframe = ++ ALLOC_SEND_XFRAME(xbus); ++ if (!xframe) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 3001) == 0) ++ XBUS_ERR(xbus, ++ "%s: failed to allocate new xframe\n", ++ __func__); ++ return; ++ } ++ } ++ pack = ++ xframe_next_packet(xframe, pcm_len); ++ } while (!pack); ++ XPACKET_INIT(pack, GLOBAL, PCM_WRITE, ++ xpd->xbus_idx, 1, 0); ++ XPACKET_LEN(pack) = pcm_len; ++ if (!sent_sync_bit) { ++ XPACKET_ADDR_SYNC(pack) = 1; ++ sent_sync_bit = 1; ++ } ++ CALL_PHONE_METHOD(card_pcm_fromspan, xpd, pack); ++ XBUS_COUNTER(xbus, TX_PACK_PCM)++; ++ } ++ } ++ } ++ if (xframe) /* clean any leftovers */ ++ pcm_frame_out(xbus, xframe); ++ /* ++ * Receive PCM ++ */ ++ while ((xframe = xframe_dequeue(&xbus->pcm_tospan)) != NULL) { ++ copy_pcm_tospan(xbus, xframe); ++ if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { ++ ktime_t now = ktime_get(); ++ s64 usec; ++ ++ usec = ktime_us_delta(now, xbus->last_rx_sync); ++ xbus->last_rx_sync = now; ++ /* ignore startup statistics */ ++ if (likely ++ (atomic_read(&xbus->pcm_rx_counter) > ++ BIG_TICK_INTERVAL)) { ++ if (abs(usec - 1000) > TICK_TOLERANCE) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 5003) == 0) ++ XBUS_DBG(SYNC, xbus, ++ "Bad PCM RX timing(%d): usec=%lld.\n", ++ rate_limit, usec); ++ } ++ if (usec > xbus->max_rx_sync) ++ xbus->max_rx_sync = usec; ++ if (usec < xbus->min_rx_sync) ++ xbus->min_rx_sync = usec; ++ } ++ } ++ } ++ for (i = 0; i < MAX_XPDS; i++) { ++ xpd = xpd_of(xbus, i); ++ if (!xpd || !xpd->card_present) ++ continue; ++ if (IS_PHONEDEV(xpd)) { ++ if (SPAN_REGISTERED(xpd)) { ++ do_ec(xpd); ++ dahdi_receive(&PHONEDEV(xpd).span); ++ } ++ /* silence was injected */ ++ PHONEDEV(xpd).silence_pcm = 0; ++ } ++ xpd->timer_count = xbus->global_counter; ++ /* ++ * Must be called *after* tx/rx so ++ * D-Chan counters may be cleared ++ */ ++ CALL_XMETHOD(card_tick, xpd); ++ } ++} ++ ++static void do_tick(xbus_t *xbus, const ktime_t kt_received) ++{ ++ int counter = atomic_read(&xpp_tick_counter); ++ unsigned long flags; ++ ++ xbus_command_queue_tick(xbus); ++ if (global_ticker == xbus) ++ global_tick(); /* called from here or dahdi_sync_tick() */ ++ spin_lock_irqsave(&ref_ticker_lock, flags); ++ xpp_drift_step(xbus, kt_received); ++ spin_unlock_irqrestore(&ref_ticker_lock, flags); ++ if (likely(xbus->self_ticking)) ++ xbus_tick(xbus); ++ xbus->global_counter = counter; ++} ++ ++void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe) ++{ ++ if (!xframe_enqueue(&xbus->pcm_tospan, xframe)) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) ++ XBUS_DBG(SYNC, xbus, ++ "Failed to enqueue received pcm frame. (%d)\n", ++ rate_limit); ++ FREE_RECV_XFRAME(xbus, xframe); ++ } ++ /* ++ * The sync_master bit is marked at the first packet ++ * of the frame, regardless of the XPD that is sync master. ++ * FIXME: what about PRI split? ++ */ ++ if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { ++ do_tick(xbus, xframe->kt_received); ++ atomic_inc(&xbus->pcm_rx_counter); ++ } else ++ xbus->xbus_frag_count++; ++} ++ ++int exec_sync_command(const char *buf, size_t count) ++{ ++ int ret = count; ++ int xbusno; ++ xbus_t *xbus; ++ ++ if (strncmp("DAHDI", buf, 6) == 0) { /* Ignore the newline */ ++ DBG(SYNC, "DAHDI"); ++ update_sync_master(NULL, 1); ++ } else if (sscanf(buf, "SYNC=%d", &xbusno) == 1) { ++ DBG(SYNC, "SYNC=%d\n", xbusno); ++ xbus = get_xbus(__func__, xbusno); ++ if (xbus == NULL) { ++ ERR("No bus %d exists\n", xbusno); ++ return -ENXIO; ++ } ++ update_sync_master(xbus, 0); ++ put_xbus(__func__, xbus); ++ } else if (sscanf(buf, "QUERY=%d", &xbusno) == 1) { ++ DBG(SYNC, "QUERY=%d\n", xbusno); ++ xbus = get_xbus(__func__, xbusno); ++ if (xbus == NULL) { ++ ERR("No bus %d exists\n", xbusno); ++ return -ENXIO; ++ } ++ CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_QUERY, 0); ++ put_xbus(__func__, xbus); ++ } else { ++ ERR("%s: cannot parse '%s'\n", __func__, buf); ++ ret = -EINVAL; ++ } ++ return ret; ++} ++ ++int fill_sync_string(char *buf, size_t count) ++{ ++ int len = 0; ++ ++ if (!syncer) { ++ len += ++ snprintf(buf, count, "%s\n", ++ (force_dahdi_sync) ? "DAHDI" : "NO-SYNC"); ++ } else ++ len += snprintf(buf, count, "SYNC=%02d\n", syncer->num); ++ return len; ++} ++ ++int xbus_pcm_init(void *toplevel) ++{ ++ int ret = 0; ++ ++#ifdef OPTIMIZE_CHANMUTE ++ INFO("FEATURE: with CHANMUTE optimization (%sactivated)\n", ++ (optimize_chanmute) ? "" : "de"); ++#endif ++#ifdef DAHDI_SYNC_TICK ++ INFO("FEATURE: with sync_tick() from DAHDI\n"); ++#else ++ INFO("FEATURE: without sync_tick() from DAHDI\n"); ++#endif ++ xpp_ticker_init(&global_ticks_series); ++ xpp_ticker_init(&dahdi_ticker); ++ return ret; ++} ++ ++void xbus_pcm_shutdown(void) ++{ ++} +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xbus-pcm.h linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-pcm.h +--- linux-source-4.19/drivers/dahdi/xpp/xbus-pcm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-pcm.h 2020-10-28 00:17:08.675192303 +0100 +@@ -0,0 +1,120 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2007, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ */ ++ ++/* ++ * This source module contains all the PCM and SYNC handling code. ++ */ ++#ifndef XBUS_PCM_H ++#define XBUS_PCM_H ++ ++#include "xdefs.h" ++#include ++#include ++ ++#ifdef __KERNEL__ ++ ++enum sync_mode { ++ SYNC_MODE_NONE = 0x00, ++ SYNC_MODE_AB = 0x01, /* Astribank sync */ ++ SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */ ++ SYNC_MODE_QUERY = 0x80, ++}; ++ ++/* ++ * A ticker encapsulates the timing information of some ++ * abstract tick source. The following tickers are used: ++ * - Each xbus has an embedded ticker. ++ * - There is one global dahdi_ticker to represent ticks ++ * of external dahdi card (in case we want to sync ++ * from other dahdi devices). ++ */ ++struct xpp_ticker { /* for rate calculation */ ++ int count; ++ int cycle; ++ ktime_t first_sample; ++ ktime_t last_sample; ++ int tick_period; /* usec/tick */ ++ spinlock_t lock; ++}; ++ ++/* ++ * xpp_drift represent the measurements of the offset between an ++ * xbus ticker to a reference ticker. ++ */ ++struct xpp_drift { ++ int delta_tick; /* from ref_ticker */ ++ int lost_ticks; /* occurances */ ++ int lost_tick_count; ++ int sync_inaccuracy; ++ ktime_t last_lost_tick; ++ long delta_sum; ++ int offset_prev; ++ int offset_range; ++ int offset_min; ++ int offset_max; ++ int min_speed; ++ int max_speed; ++ spinlock_t lock; ++}; ++ ++void xpp_drift_init(xbus_t *xbus); ++ ++static inline long usec_diff(const ktime_t *tv1, ++ const ktime_t *tv2) ++{ ++ return ktime_us_delta(*tv1, *tv2); ++} ++ ++int xbus_pcm_init(void *top); ++void xbus_pcm_shutdown(void); ++int send_pcm_frame(xbus_t *xbus, xframe_t *xframe); ++void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask); ++void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe); ++void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len); ++void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask); ++void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack); ++void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack); ++int generic_timing_priority(xpd_t *xpd); ++int generic_echocancel_timeslot(xpd_t *xpd, int pos); ++int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask); ++void fill_beep(u_char *buf, int num, int duration); ++const char *sync_mode_name(enum sync_mode mode); ++void xbus_set_command_timer(xbus_t *xbus, bool on); ++void xbus_request_sync(xbus_t *xbus, enum sync_mode mode); ++void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift); ++int xbus_command_queue_tick(xbus_t *xbus); ++void xbus_reset_counters(xbus_t *xbus); ++void elect_syncer(const char *msg); ++int exec_sync_command(const char *buf, size_t count); ++int fill_sync_string(char *buf, size_t count); ++#ifdef DAHDI_SYNC_TICK ++void dahdi_sync_tick(struct dahdi_span *span, int is_master); ++#endif ++ ++#ifdef DEBUG_PCMTX ++extern int pcmtx; ++extern int pcmtx_chan; ++#endif ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* XBUS_PCM_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xbus-sysfs.c linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-sysfs.c +--- linux-source-4.19/drivers/dahdi/xpp/xbus-sysfs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xbus-sysfs.c 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,1106 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 ++#ifdef PROTOCOL_DEBUG ++#include ++#endif ++#include ++#include ++#include /* for msleep() to debug */ ++#include ++#include ++#include "xpd.h" ++#include "xpp_dahdi.h" ++#include "xbus-core.h" ++#include "dahdi_debug.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++/* Command line parameters */ ++extern int debug; ++ ++/*--------- xpp driver attributes -*/ ++static ssize_t sync_show(struct device_driver *driver, char *buf) ++{ ++ DBG(SYNC, "\n"); ++ return fill_sync_string(buf, PAGE_SIZE); ++} ++ ++static ssize_t sync_store(struct device_driver *driver, const char *buf, ++ size_t count) ++{ ++ /* DBG(SYNC, "%s\n", buf); */ ++ return exec_sync_command(buf, count); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) ++static struct driver_attribute xpp_attrs[] = { ++ __ATTR(sync, S_IRUGO | S_IWUSR, sync_show, sync_store), ++ __ATTR_NULL, ++}; ++#else ++static DRIVER_ATTR_RW(sync); ++static struct attribute *xpp_attrs[] = { ++ &driver_attr_sync.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(xpp); ++#endif ++ ++/*--------- Sysfs Bus handling ----*/ ++static DEVICE_ATTR_READER(xbus_state_show, dev, buf) ++{ ++ xbus_t *xbus; ++ int ret; ++ ++ xbus = dev_to_xbus(dev); ++ ret = XBUS_STATE(xbus); ++ ret = snprintf(buf, PAGE_SIZE, "%s (%d)\n", xbus_statename(ret), ret); ++ return ret; ++} ++ ++static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count) ++{ ++ xbus_t *xbus; ++ ++ xbus = dev_to_xbus(dev); ++ XBUS_DBG(GENERAL, xbus, "%s\n", buf); ++ if (strncmp(buf, "stop", 4) == 0) ++ xbus_deactivate(xbus); ++ else if (XBUS_IS(xbus, IDLE) && strncmp(buf, "start", 5) == 0) ++ xbus_activate(xbus); ++ else { ++ XBUS_NOTICE(xbus, ++ "%s: Illegal action %s in state %s. Ignored.\n", ++ __func__, buf, xbus_statename(XBUS_STATE(xbus))); ++ return -EINVAL; ++ } ++ return count; ++} ++ ++static DEVICE_ATTR_READER(status_show, dev, buf) ++{ ++ xbus_t *xbus; ++ int ret; ++ ++ xbus = dev_to_xbus(dev); ++ ret = ++ snprintf(buf, PAGE_SIZE, "%s\n", ++ (XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing"); ++ return ret; ++} ++ ++static DEVICE_ATTR_READER(timing_show, dev, buf) ++{ ++ xbus_t *xbus; ++ struct xpp_drift *driftinfo; ++ int len = 0; ++ ktime_t now; ++ ++ now = ktime_get(); ++ xbus = dev_to_xbus(dev); ++ driftinfo = &xbus->drift; ++ len += ++ snprintf(buf + len, PAGE_SIZE - len, "%-3s", ++ sync_mode_name(xbus->sync_mode)); ++ if (xbus->sync_mode == SYNC_MODE_PLL) { ++ bool pll_updated = !dahdi_ktime_equal(xbus->pll_updated_at, ++ ktime_set(0, 0)); ++ s64 update_delta = ++ (!pll_updated) ? 0 : ++ xpp_ktime_sec_delta(now, xbus->pll_updated_at); ++ len += ++ snprintf(buf + len, PAGE_SIZE - len, ++ " %5d: lost (%4d,%4d) : ", xbus->ticker.cycle, ++ driftinfo->lost_ticks, driftinfo->lost_tick_count); ++ len += ++ snprintf(buf + len, PAGE_SIZE - len, ++ "DRIFT %3d %lld sec ago", xbus->sync_adjustment, ++ update_delta); ++ } ++ len += snprintf(buf + len, PAGE_SIZE - len, "\n"); ++ return len; ++} ++ ++#ifdef SAMPLE_TICKS ++/* ++ * tick sampling: Measure offset from reference ticker: ++ * - Recording start when writing to: ++ * /sys/bus/astribanks/devices/xbus-??/samples ++ * - Recording ends when filling SAMPLE_SIZE ticks ++ * - Results are read from the same sysfs file. ++ * - Trying to read/write during recording, returns -EBUSY. ++ */ ++static DEVICE_ATTR_READER(samples_show, dev, buf) ++{ ++ xbus_t *xbus; ++ int len = 0; ++ int i; ++ ++ xbus = dev_to_xbus(dev); ++ if (xbus->sample_running) ++ return -EBUSY; ++ for (i = 0; i < SAMPLE_SIZE; i++) { ++ if (len > PAGE_SIZE - 20) ++ break; ++ len += ++ snprintf(buf + len, PAGE_SIZE - len, "%d\n", ++ xbus->sample_ticks[i]); ++ } ++ return len; ++} ++ ++static DEVICE_ATTR_WRITER(samples_store, dev, buf, count) ++{ ++ xbus_t *xbus; ++ ++ xbus = dev_to_xbus(dev); ++ if (xbus->sample_running) ++ return -EBUSY; ++ memset(xbus->sample_ticks, 0, sizeof(*xbus->sample_ticks)); ++ xbus->sample_pos = 0; ++ xbus->sample_running = 1; ++ return count; ++} ++#endif ++ ++/* ++ * Clear statistics ++ */ ++static DEVICE_ATTR_WRITER(cls_store, dev, buf, count) ++{ ++ xbus_t *xbus; ++ struct xpp_drift *driftinfo; ++ ++ xbus = dev_to_xbus(dev); ++ driftinfo = &xbus->drift; ++ driftinfo->lost_ticks = 0; ++ driftinfo->lost_tick_count = 0; ++ xbus->min_tx_sync = INT_MAX; ++ xbus->max_tx_sync = 0; ++ xbus->min_rx_sync = INT_MAX; ++ xbus->max_rx_sync = 0; ++#ifdef SAMPLE_TICKS ++ memset(xbus->sample_ticks, 0, sizeof(*xbus->sample_ticks)); ++#endif ++ return count; ++} ++ ++static DEVICE_ATTR_READER(waitfor_xpds_show, dev, buf) ++{ ++ xbus_t *xbus; ++ int len; ++ ++ xbus = dev_to_xbus(dev); ++ len = waitfor_xpds(xbus, buf); ++ return len; ++} ++ ++static DEVICE_ATTR_READER(refcount_xbus_show, dev, buf) ++{ ++ xbus_t *xbus; ++ int len; ++ ++ xbus = dev_to_xbus(dev); ++ len = sprintf(buf, "%d\n", refcount_xbus(xbus)); ++ return len; ++} ++ ++static DEVICE_ATTR_READER(driftinfo_show, dev, buf) ++{ ++ xbus_t *xbus; ++ struct xpp_drift *di; ++ struct xpp_ticker *ticker; ++ ktime_t now = ktime_get(); ++ int len = 0; ++ int hours; ++ int minutes; ++ int seconds; ++ int speed_range; ++ int uframes_inaccuracy; ++ int i; ++ ++ xbus = dev_to_xbus(dev); ++ di = &xbus->drift; ++ ticker = &xbus->ticker; ++ /* ++ * Calculate lost ticks time ++ */ ++ seconds = ktime_ms_delta(now, di->last_lost_tick) / 1000; ++ minutes = seconds / 60; ++ seconds = seconds % 60; ++ hours = minutes / 60; ++ minutes = minutes % 60; ++ len += snprintf(buf + len, PAGE_SIZE - len, ++ "%-15s: %8d (was %d:%02d:%02d ago)\n", "lost_ticks", ++ di->lost_ticks, hours, minutes, seconds); ++ speed_range = abs(di->max_speed - di->min_speed); ++ uframes_inaccuracy = di->sync_inaccuracy / 125; ++ len += snprintf(buf + len, PAGE_SIZE - len, ++ "%-15s: %8d ", "instability", ++ speed_range + uframes_inaccuracy); ++ if (xbus->sync_mode == SYNC_MODE_AB) { ++ buf[len++] = '-'; ++ } else { ++ for (i = 0; ++ len < PAGE_SIZE - 1 ++ && i < speed_range + uframes_inaccuracy; i++) ++ buf[len++] = '#'; ++ } ++ buf[len++] = '\n'; ++ len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d (uframes)\n", ++ "inaccuracy", uframes_inaccuracy); ++ len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", ++ "speed_range", speed_range); ++#define SHOW(ptr, item) \ ++ do { \ ++ len += snprintf(buf + len, PAGE_SIZE - len, \ ++ "%-15s: %8d\n", #item, (ptr)->item); \ ++ } while (0) ++ SHOW(xbus, sync_adjustment); ++ len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", ++ "offset (usec)", di->offset_prev); ++ SHOW(di, offset_range); ++ len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", ++ "best_speed", (di->max_speed + di->min_speed) / 2); ++ SHOW(di, min_speed); ++ SHOW(di, max_speed); ++ SHOW(ticker, cycle); ++ SHOW(ticker, tick_period); ++ SHOW(ticker, count); ++#undef SHOW ++ return len; ++} ++ ++#define xbus_attr(field, format_string) \ ++static ssize_t \ ++field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ xbus_t *xbus; \ ++ xbus = dev_to_xbus(dev); \ ++ return sprintf(buf, format_string, xbus->field); \ ++} ++ ++xbus_attr(connector, "%s\n"); ++xbus_attr(label, "%s\n"); ++ ++static DEVICE_ATTR_WRITER(dahdi_registration_store, dev, buf, count) ++{ ++ xbus_t *xbus; ++ int dahdi_reg; ++ int ret; ++ ++ xbus = dev_to_xbus(dev); ++ if (!xbus) ++ return -ENODEV; ++ ret = sscanf(buf, "%d", &dahdi_reg); ++ if (ret != 1) ++ return -EINVAL; ++ if (dahdi_reg) { ++ ret = xbus_register_dahdi_device(xbus); ++ if (ret < 0) { ++ XBUS_ERR(xbus, ++ "xbus_register_dahdi_device() failed (ret = %d)\n", ++ ret); ++ return ret; ++ } ++ } else { ++ xbus_unregister_dahdi_device(xbus); ++ } ++ return count; ++} ++ ++static DEVICE_ATTR_READER(dahdi_registration_show, dev, buf) ++{ ++ xbus_t *xbus; ++ int len; ++ ++ xbus = dev_to_xbus(dev); ++ len = sprintf(buf, "%d\n", xbus_is_registered(xbus)); ++ return len; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++static struct device_attribute xbus_dev_attrs[] = { ++ __ATTR_RO(connector), ++ __ATTR_RO(label), ++ __ATTR_RO(status), ++ __ATTR_RO(timing), ++ __ATTR_RO(refcount_xbus), ++ __ATTR_RO(waitfor_xpds), ++ __ATTR_RO(driftinfo), ++ __ATTR(cls, S_IWUSR, NULL, cls_store), ++ __ATTR(xbus_state, S_IRUGO | S_IWUSR, xbus_state_show, ++ xbus_state_store), ++#ifdef SAMPLE_TICKS ++ __ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store), ++#endif ++ __ATTR(dahdi_registration, S_IRUGO | S_IWUSR, ++ dahdi_registration_show, ++ dahdi_registration_store), ++ __ATTR_NULL, ++}; ++#else ++static DEVICE_ATTR_RO(connector); ++static DEVICE_ATTR_RO(label); ++static DEVICE_ATTR_RO(status); ++static DEVICE_ATTR_RO(timing); ++static DEVICE_ATTR_RO(refcount_xbus); ++static DEVICE_ATTR_RO(waitfor_xpds); ++static DEVICE_ATTR_RO(driftinfo); ++static DEVICE_ATTR_WO(cls); ++static DEVICE_ATTR_RW(xbus_state); ++#ifdef SAMPLE_TICKS ++static DEVICE_ATTR_RO(samples); ++#endif ++static DEVICE_ATTR_RW(dahdi_registration); ++ ++static struct attribute *xbus_dev_attrs[] = { ++ &dev_attr_connector.attr, ++ &dev_attr_label.attr, ++ &dev_attr_status.attr, ++ &dev_attr_timing.attr, ++ &dev_attr_refcount_xbus.attr, ++ &dev_attr_waitfor_xpds.attr, ++ &dev_attr_driftinfo.attr, ++ &dev_attr_cls.attr, ++ &dev_attr_xbus_state.attr, ++#ifdef SAMPLE_TICKS ++ &dev_attr_samples.attr, ++#endif ++ &dev_attr_dahdi_registration.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(xbus_dev); ++#endif ++ ++static int astribank_match(struct device *dev, struct device_driver *driver) ++{ ++ DBG(DEVICES, "SYSFS MATCH: dev->bus_id = %s, driver->name = %s\n", ++ dev_name(dev), driver->name); ++ return 1; ++} ++ ++#define XBUS_VAR_BLOCK \ ++ do { \ ++ XBUS_ADD_UEVENT_VAR("XPP_INIT_DIR=%s", initdir); \ ++ XBUS_ADD_UEVENT_VAR("XBUS_NUM=%02d", xbus->num); \ ++ XBUS_ADD_UEVENT_VAR("XBUS_NAME=%s", xbus->busname); \ ++ } while (0) ++ ++#define XBUS_ADD_UEVENT_VAR(fmt, val...) \ ++ do { \ ++ int err = add_uevent_var(kenv, fmt, val); \ ++ if (err) \ ++ return err; \ ++ } while (0) ++ ++static int astribank_uevent(struct device *dev, struct kobj_uevent_env *kenv) ++{ ++ xbus_t *xbus; ++ extern char *initdir; ++ ++ if (!dev) ++ return -ENODEV; ++ xbus = dev_to_xbus(dev); ++ DBG(GENERAL, "SYFS bus_id=%s xbus=%s\n", dev_name(dev), xbus->busname); ++ XBUS_VAR_BLOCK; ++ return 0; ++} ++ ++void astribank_uevent_send(xbus_t *xbus, enum kobject_action act) ++{ ++ struct kobject *kobj; ++ ++ kobj = &xbus->astribank.kobj; ++ XBUS_DBG(DEVICES, xbus, "SYFS bus_id=%s action=%d\n", ++ dev_name(&xbus->astribank), act); ++ kobject_uevent(kobj, act); ++} ++ ++static void astribank_release(struct device *dev) ++{ ++ xbus_t *xbus; ++ ++ BUG_ON(!dev); ++ xbus = dev_to_xbus(dev); ++ if (XBUS_FLAGS(xbus, CONNECTED)) { ++ XBUS_ERR(xbus, "Try to release CONNECTED device.\n"); ++ BUG(); ++ } ++ if (!XBUS_IS(xbus, IDLE) && !XBUS_IS(xbus, FAIL) ++ && !XBUS_IS(xbus, DEACTIVATED)) { ++ XBUS_ERR(xbus, "Try to release in state %s\n", ++ xbus_statename(XBUS_STATE(xbus))); ++ BUG(); ++ } ++ XBUS_INFO(xbus, "[%s] Astribank Release\n", xbus->label); ++ xbus_free(xbus); ++} ++ ++static struct bus_type toplevel_bus_type = { ++ .name = "astribanks", ++ .match = astribank_match, ++ .uevent = astribank_uevent, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++ .dev_attrs = xbus_dev_attrs, ++#else ++ .dev_groups = xbus_dev_groups, ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) ++ .drv_attrs = xpp_attrs, ++#else ++ .drv_groups = xpp_groups, ++#endif ++}; ++ ++static int astribank_probe(struct device *dev) ++{ ++ xbus_t *xbus; ++ ++ xbus = dev_to_xbus(dev); ++ XBUS_DBG(DEVICES, xbus, "SYSFS\n"); ++ return 0; ++} ++ ++static int astribank_remove(struct device *dev) ++{ ++ xbus_t *xbus; ++ ++ xbus = dev_to_xbus(dev); ++ XBUS_INFO(xbus, "[%s] Atribank Remove\n", xbus->label); ++ return 0; ++} ++ ++static struct device_driver xpp_driver = { ++ .name = "xppdrv", ++ .bus = &toplevel_bus_type, ++ .probe = astribank_probe, ++ .remove = astribank_remove, ++ .owner = THIS_MODULE ++}; ++ ++/*--------- Sysfs XPD handling ----*/ ++ ++static DEVICE_ATTR_READER(chipregs_show, dev, buf) ++{ ++ xpd_t *xpd; ++ unsigned long flags; ++ reg_cmd_t *regs; ++ bool do_datah; ++ char datah_str[50]; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ regs = &xpd->last_reply; ++ len += sprintf(buf + len, ++ "# Writing bad data to this file may damage your hardware!\n"); ++ len += sprintf(buf + len, "# Consult firmware docs first\n"); ++ len += sprintf(buf + len, "#\n"); ++ do_datah = REG_FIELD(regs, do_datah) ? 1 : 0; ++ if (do_datah) { ++ snprintf(datah_str, ARRAY_SIZE(datah_str), "\t%02X", ++ REG_FIELD(regs, data_high)); ++ } else ++ datah_str[0] = '\0'; ++ if (regs->h.bytes == REG_CMD_SIZE(RAM)) { ++ len += ++ sprintf(buf + len, "#CH\tOP\tAL\tAH\tD0\tD1\tD2\tD3\n"); ++ len += ++ sprintf(buf + len, "%2d\tRR\t%02X\t%02X\t%02X\t%02X\t%02X\t%02X\n", ++ regs->h.portnum, ++ REG_FIELD_RAM(regs, addr_low), ++ REG_FIELD_RAM(regs, addr_high), ++ REG_FIELD_RAM(regs, data_0), ++ REG_FIELD_RAM(regs, data_1), ++ REG_FIELD_RAM(regs, data_2), ++ REG_FIELD_RAM(regs, data_3)); ++ } else if (REG_FIELD(regs, do_subreg)) { ++ len += ++ sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n", ++ (do_datah) ? "\tDH" : ""); ++ len += ++ sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n", ++ regs->h.portnum, REG_FIELD(regs, regnum), ++ REG_FIELD(regs, subreg), REG_FIELD(regs, data_low), ++ datah_str); ++ } else { ++ len += ++ sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n", ++ (do_datah) ? "\tDH" : ""); ++ len += ++ sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->h.portnum, ++ REG_FIELD(regs, regnum), REG_FIELD(regs, data_low), ++ datah_str); ++ } ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR_WRITER(chipregs_store, dev, buf, count) ++{ ++ xpd_t *xpd; ++ const char *p; ++ char tmp[MAX_PROC_WRITE]; ++ int i; ++ int ret; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ //XPD_DBG(GENERAL, xpd, "%s\n", buf); ++ if (!xpd) ++ return -ENODEV; ++ p = buf; ++ while ((p - buf) < count) { ++ i = strcspn(p, "\r\n"); ++ if (i > 0) { ++ if (i >= MAX_PROC_WRITE) { ++ XPD_NOTICE(xpd, "Command too long (%d chars)\n", ++ i); ++ return -E2BIG; ++ } ++ memcpy(tmp, p, i); ++ tmp[i] = '\0'; ++ ret = parse_chip_command(xpd, tmp); ++ if (ret < 0) { ++ XPD_NOTICE(xpd, ++ "Failed writing command: '%s'\n", ++ tmp); ++ return ret; ++ } ++ } ++ p += i + 1; ++ /* Don't flood command_queue */ ++ if (xframe_queue_count(&xpd->xbus->command_queue) > 5) ++ msleep(6); ++ } ++ return count; ++} ++ ++static DEVICE_ATTR_READER(blink_show, dev, buf) ++{ ++ xpd_t *xpd; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += sprintf(buf, "0x%lX\n", xpd->blink_mode); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR_WRITER(blink_store, dev, buf, count) ++{ ++ xpd_t *xpd; ++ char *endp; ++ unsigned long blink; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ //XPD_DBG(GENERAL, xpd, "%s\n", buf); ++ if (!xpd) ++ return -ENODEV; ++ blink = simple_strtoul(buf, &endp, 0); ++ if (*endp != '\0' && *endp != '\n' && *endp != '\r') ++ return -EINVAL; ++ if (blink > 0xFFFF) ++ return -EINVAL; ++ XPD_DBG(GENERAL, xpd, "BLINK channels: 0x%lX\n", blink); ++ xpd->blink_mode = blink; ++ return count; ++} ++ ++static DEVICE_ATTR_READER(span_show, dev, buf) ++{ ++ xpd_t *xpd; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += ++ sprintf(buf, "%d\n", ++ SPAN_REGISTERED(xpd) ? PHONEDEV(xpd).span.spanno : 0); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++/* ++ * For backward compatibility with old dahdi-tools ++ * Remove after dahdi_registration is upgraded ++ */ ++static DEVICE_ATTR_WRITER(span_store, dev, buf, count) ++{ ++ xpd_t *xpd; ++ int dahdi_reg; ++ int ret; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ ret = sscanf(buf, "%d", &dahdi_reg); ++ if (ret != 1) ++ return -EINVAL; ++ if (!XBUS_IS(xpd->xbus, READY)) ++ return -ENODEV; ++ XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use assigned-spans)\n", ++ (dahdi_reg) ? "register" : "unregister"); ++ if (dahdi_reg) ++ xbus_register_dahdi_device(xpd->xbus); ++ else ++ xbus_unregister_dahdi_device(xpd->xbus); ++ return count; ++} ++ ++static DEVICE_ATTR_READER(type_show, dev, buf) ++{ ++ xpd_t *xpd; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ len += sprintf(buf, "%s\n", xpd->type_name); ++ return len; ++} ++ ++static DEVICE_ATTR_READER(hwid_show, dev, buf) ++{ ++ xpd_t *xpd; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ len += sprintf(buf, "%d.%d\n", XPD_HW(xpd).type, XPD_HW(xpd).subtype); ++ return len; ++} ++ ++static DEVICE_ATTR_READER(offhook_show, dev, buf) ++{ ++ xpd_t *xpd; ++ int len = 0; ++ int i; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ for_each_line(xpd, i) { ++ len += sprintf(buf + len, "%d ", IS_OFFHOOK(xpd, i)); ++ } ++ if (len) ++ len--; /* backout last space */ ++ len += sprintf(buf + len, "\n"); ++ return len; ++} ++ ++static DEVICE_ATTR_READER(timing_priority_show, dev, buf) ++{ ++ xpd_t *xpd; ++ unsigned long flags; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ len += sprintf(buf + len, "%d\n", PHONEDEV(xpd).timing_priority); ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR_READER(refcount_xpd_show, dev, buf) ++{ ++ xpd_t *xpd; ++ int len = 0; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ len += sprintf(buf + len, "%d\n", refcount_xpd(xpd)); ++ return len; ++} ++ ++static int xpd_match(struct device *dev, struct device_driver *driver) ++{ ++ struct xpd_driver *xpd_driver; ++ xpd_t *xpd; ++ ++ xpd_driver = driver_to_xpd_driver(driver); ++ xpd = dev_to_xpd(dev); ++ if (xpd_driver->xpd_type != xpd->xpd_type) { ++ XPD_DBG(DEVICES, xpd, ++ "SYSFS match fail: xpd->xpd_type = %d, " ++ "xpd_driver->xpd_type = %d\n", ++ xpd->xpd_type, xpd_driver->xpd_type); ++ return 0; ++ } ++ XPD_DBG(DEVICES, xpd, ++ "SYSFS MATCH: xpd_type=%d dev->bus_id = %s, driver->name = %s\n", ++ xpd->xpd_type, dev_name(dev), driver->name); ++ return 1; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++static struct device_attribute xpd_dev_attrs[] = { ++ __ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store), ++ __ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store), ++ __ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store), ++ __ATTR_RO(type), ++ __ATTR_RO(hwid), ++ __ATTR_RO(offhook), ++ __ATTR_RO(timing_priority), ++ __ATTR_RO(refcount_xpd), ++ __ATTR_NULL, ++}; ++#else ++static DEVICE_ATTR_RW(chipregs); ++static DEVICE_ATTR_RW(blink); ++static DEVICE_ATTR_RW(span); ++static DEVICE_ATTR_RO(type); ++static DEVICE_ATTR_RO(hwid); ++static DEVICE_ATTR_RO(offhook); ++static DEVICE_ATTR_RO(timing_priority); ++static DEVICE_ATTR_RO(refcount_xpd); ++ ++static struct attribute *xpd_dev_attrs[] = { ++ &dev_attr_chipregs.attr, ++ &dev_attr_blink.attr, ++ &dev_attr_span.attr, ++ &dev_attr_type.attr, ++ &dev_attr_hwid.attr, ++ &dev_attr_offhook.attr, ++ &dev_attr_timing_priority.attr, ++ &dev_attr_refcount_xpd.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(xpd_dev); ++#endif ++ ++static struct bus_type xpd_type = { ++ .name = "xpds", ++ .match = xpd_match, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++ .dev_attrs = xpd_dev_attrs, ++#else ++ .dev_groups = xpd_dev_groups, ++#endif ++}; ++ ++int xpd_driver_register(struct device_driver *driver) ++{ ++ int ret; ++ ++ DBG(DEVICES, "%s\n", driver->name); ++ driver->bus = &xpd_type; ++ if ((ret = driver_register(driver)) < 0) { ++ ERR("%s: driver_register(%s) failed. Error number %d", __func__, ++ driver->name, ret); ++ } ++ return ret; ++} ++EXPORT_SYMBOL(xpd_driver_register); ++ ++void xpd_driver_unregister(struct device_driver *driver) ++{ ++ DBG(DEVICES, "%s\n", driver->name); ++ driver_unregister(driver); ++} ++EXPORT_SYMBOL(xpd_driver_unregister); ++ ++static void xpd_release(struct device *dev) ++{ ++ xpd_t *xpd; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ xpd_remove(xpd); ++} ++ ++int xpd_device_register(xbus_t *xbus, xpd_t *xpd) ++{ ++ struct device *dev = &xpd->xpd_dev; ++ int ret; ++ ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ dev->bus = &xpd_type; ++ dev->parent = &xbus->astribank; ++ dev_set_name(dev, "%02d:%1x:%1x", xbus->num, xpd->addr.unit, ++ xpd->addr.subunit); ++ dev_set_drvdata(dev, xpd); ++ dev->release = xpd_release; ++ ret = device_register(dev); ++ if (ret) { ++ XPD_ERR(xpd, "%s: device_register failed: %d\n", __func__, ret); ++ return ret; ++ } ++ return 0; ++} ++ ++void xpd_device_unregister(xpd_t *xpd) ++{ ++ xbus_t *xbus; ++ struct device *dev; ++ ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ XPD_DBG(DEVICES, xpd, "SYSFS\n"); ++ dev = &xpd->xpd_dev; ++ if (!dev_get_drvdata(dev)) ++ return; ++ BUG_ON(dev_get_drvdata(dev) != xpd); ++ device_unregister(dev); ++ dev_set_drvdata(dev, NULL); ++} ++ ++static DEVICE_ATTR_READER(echocancel_show, dev, buf) ++{ ++ xpd_t *xpd; ++ unsigned long flags; ++ int len = 0; ++ xpp_line_t ec_mask = 0; ++ int i; ++ int ret; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ if (!xpd) ++ return -ENODEV; ++ if (!ECHOOPS(xpd->xbus)) ++ return -ENODEV; ++ spin_lock_irqsave(&xpd->lock, flags); ++ for (i = 0; i < PHONEDEV(xpd).channels; i++) { ++ ret = CALL_EC_METHOD(ec_get, xpd->xbus, xpd, i); ++ if (ret < 0) { ++ LINE_ERR(xpd, i, "ec_get failed\n"); ++ len = -ENODEV; ++ goto out; ++ } ++ if (ret) ++ ec_mask |= (1 << i); ++ } ++ len += sprintf(buf, "0x%08X\n", ec_mask); ++out: ++ spin_unlock_irqrestore(&xpd->lock, flags); ++ return len; ++} ++ ++static DEVICE_ATTR_WRITER(echocancel_store, dev, buf, count) ++{ ++ xpd_t *xpd; ++ char *endp; ++ unsigned long mask; ++ int channels; ++ int ret; ++ ++ BUG_ON(!dev); ++ xpd = dev_to_xpd(dev); ++ XPD_DBG(GENERAL, xpd, "%s\n", buf); ++ if (!xpd) ++ return -ENODEV; ++ if (!ECHOOPS(xpd->xbus)) { ++ XPD_ERR(xpd, "No echo canceller in this XBUS\n"); ++ return -ENODEV; ++ } ++ if (!IS_PHONEDEV(xpd)) { ++ XPD_ERR(xpd, "Not a phone device\n"); ++ return -ENODEV; ++ } ++ channels = PHONEDEV(xpd).channels; ++ mask = simple_strtoul(buf, &endp, 0); ++ if (*endp != '\0' && *endp != '\n' && *endp != '\r') { ++ XPD_ERR(xpd, "Too many channels: %d\n", channels); ++ return -EINVAL; ++ } ++ if (mask != 0 && __ffs(mask) > channels) { ++ XPD_ERR(xpd, ++ "Channel mask (0x%lX) larger than " ++ "available channels (%d)\n", ++ mask, channels); ++ return -EINVAL; ++ } ++ XPD_DBG(GENERAL, xpd, "ECHOCANCEL channels: 0x%lX\n", mask); ++ ret = CALL_PHONE_METHOD(echocancel_setmask, xpd, mask); ++ if (ret < 0) { ++ XPD_ERR(xpd, "echocancel_setmask failed\n"); ++ return ret; ++ } ++ return count; ++} ++ ++static DEVICE_ATTR(echocancel, S_IRUGO | S_IWUSR, echocancel_show, ++ echocancel_store); ++ ++int echocancel_xpd(xpd_t *xpd, int on) ++{ ++ int ret; ++ ++ XPD_DBG(GENERAL, xpd, "echocancel_xpd(%s)\n", (on) ? "on" : "off"); ++ if (!on) { ++ device_remove_file(xpd->echocancel, &dev_attr_echocancel); ++ return 0; ++ } ++ ++ ret = device_create_file(&xpd->xpd_dev, &dev_attr_echocancel); ++ if (ret) ++ XPD_ERR(xpd, "%s: device_create_file(echocancel) failed: %d\n", ++ __func__, ret); ++ ++ return ret; ++} ++EXPORT_SYMBOL(echocancel_xpd); ++ ++/*--------- Sysfs Device handling ----*/ ++ ++void xbus_sysfs_transport_remove(xbus_t *xbus) ++{ ++ struct device *astribank; ++ ++ BUG_ON(!xbus); ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ astribank = &xbus->astribank; ++ sysfs_remove_link(&astribank->kobj, "transport"); ++} ++ ++int xbus_sysfs_transport_create(xbus_t *xbus) ++{ ++ struct device *astribank; ++ struct device *transport_device; ++ int ret = 0; ++ ++ BUG_ON(!xbus); ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ astribank = &xbus->astribank; ++ BUG_ON(!astribank); ++ transport_device = xbus->transport.transport_device; ++ if (!transport_device) { ++ XBUS_ERR(xbus, "%s: Missing transport_device\n", __func__); ++ return -ENODEV; ++ } ++ ret = ++ sysfs_create_link(&astribank->kobj, &transport_device->kobj, ++ "transport"); ++ if (ret < 0) { ++ XBUS_ERR(xbus, "%s: sysfs_create_link failed: %d\n", __func__, ++ ret); ++ dev_set_drvdata(astribank, NULL); ++ } ++ return ret; ++} ++ ++void xbus_sysfs_remove(xbus_t *xbus) ++{ ++ struct device *astribank; ++ ++ BUG_ON(!xbus); ++ astribank = &xbus->astribank; ++ if (!dev_get_drvdata(astribank)) { ++ XBUS_NOTICE(xbus, "%s: already removed\n", __func__); ++ return; ++ } ++ XBUS_DBG(DEVICES, xbus, "going to unregister: refcount=%d\n", ++ refcount_read(&astribank->kobj.kref.refcount)); ++ BUG_ON(dev_get_drvdata(astribank) != xbus); ++ device_unregister(astribank); ++ dev_set_drvdata(astribank, NULL); ++} ++ ++int xbus_sysfs_create(xbus_t *xbus) ++{ ++ struct device *astribank; ++ int ret = 0; ++ ++ BUG_ON(!xbus); ++ astribank = &xbus->astribank; ++ XBUS_DBG(DEVICES, xbus, "\n"); ++ astribank->bus = &toplevel_bus_type; ++ astribank->parent = xbus->transport.transport_device; ++ dev_set_name(astribank, "xbus-%02d", xbus->num); ++ dev_set_drvdata(astribank, xbus); ++ astribank->release = astribank_release; ++ ret = device_register(astribank); ++ if (ret) { ++ XBUS_ERR(xbus, "%s: device_register failed: %d\n", __func__, ++ ret); ++ dev_set_drvdata(astribank, NULL); ++ } ++ return ret; ++} ++ ++int __init xpp_driver_init(void) ++{ ++ int ret; ++ ++ DBG(DEVICES, "SYSFS\n"); ++ if ((ret = bus_register(&toplevel_bus_type)) < 0) { ++ ERR("%s: bus_register(%s) failed. Error number %d", __func__, ++ toplevel_bus_type.name, ret); ++ goto failed_toplevel; ++ } ++ if ((ret = driver_register(&xpp_driver)) < 0) { ++ ERR("%s: driver_register(%s) failed. Error number %d", __func__, ++ xpp_driver.name, ret); ++ goto failed_xpp_driver; ++ } ++ if ((ret = bus_register(&xpd_type)) < 0) { ++ ERR("%s: bus_register(%s) failed. Error number %d", __func__, ++ xpd_type.name, ret); ++ goto failed_xpd_bus; ++ } ++ return 0; ++failed_xpd_bus: ++ driver_unregister(&xpp_driver); ++failed_xpp_driver: ++ bus_unregister(&toplevel_bus_type); ++failed_toplevel: ++ return ret; ++} ++ ++void xpp_driver_exit(void) ++{ ++ DBG(DEVICES, "SYSFS\n"); ++ bus_unregister(&xpd_type); ++ driver_unregister(&xpp_driver); ++ bus_unregister(&toplevel_bus_type); ++} +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xdefs.h linux-source-4.19-dahdi/drivers/dahdi/xpp/xdefs.h +--- linux-source-4.19/drivers/dahdi/xpp/xdefs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xdefs.h 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,147 @@ ++#ifndef XDEFS_H ++#define XDEFS_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ */ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++ ++#else ++ ++/* This is to enable user-space programs to include this. */ ++ ++#include ++typedef uint8_t __u8; ++typedef uint32_t __u32; ++ ++#include ++ ++#define DBG(fmt, ...) printf("DBG: %s: " fmt, __func__, ## __VA_ARGS__) ++#define INFO(fmt, ...) printf("INFO: " fmt, ## __VA_ARGS__) ++#define NOTICE(fmt, ...) printf("NOTICE: " fmt, ## __VA_ARGS__) ++#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__) ++#define __user ++ ++struct list_head { ++ struct list_head *next; ++ struct list_head *prev; ++}; ++ ++#endif ++ ++#define PACKED __attribute__((packed)) ++ ++#define ALL_LINES ((lineno_t)-1) ++ ++#ifndef BIT /* added in 2.6.24 */ ++#define BIT(i) (1UL << (i)) ++#endif ++#define BIT_SET(x, i) ((x) |= BIT(i)) ++#define BIT_CLR(x, i) ((x) &= ~BIT(i)) ++#define IS_SET(x, i) (((x) & BIT(i)) != 0) ++#define BITMASK(i) (((u64)1 << (i)) - 1) ++ ++#define MAX_PROC_WRITE 100 /* Longest write allowed to our /proc files */ ++#define CHANNELS_PERXPD 32 /* Depends on xpp_line_t and protocol fields */ ++ ++#define MAX_SPANNAME 20 /* From dahdi/kernel.h */ ++#define MAX_SPANDESC 40 /* From dahdi/kernel.h */ ++#define MAX_CHANNAME 40 /* From dahdi/kernel.h */ ++ ++#define XPD_NAMELEN 10 /* must be <= from maximal workqueue name */ ++#define XPD_DESCLEN 20 ++#define XBUS_NAMELEN 20 /* must be <= from maximal workqueue name */ ++#define XBUS_DESCLEN 40 ++#define LABEL_SIZE 20 ++ ++#define UNIT_BITS 3 /* Bit for Astribank unit number */ ++#define SUBUNIT_BITS 3 /* Bit for Astribank subunit number */ ++ ++/* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */ ++#define MAX_UNIT (1 << UNIT_BITS) ++#define MAX_SUBUNIT (1 << SUBUNIT_BITS) /* 8 port BRI */ ++ ++/* ++ * Compile time sanity checks ++ */ ++#if MAX_UNIT > BIT(UNIT_BITS) ++#error "MAX_UNIT too large" ++#endif ++ ++#if MAX_SUBUNIT > BIT(SUBUNIT_BITS) ++#error "MAX_SUBUNIT too large" ++#endif ++ ++#define MAX_XPDS (MAX_UNIT*MAX_SUBUNIT) ++ ++#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0) ++ ++#define CHAN_BITS 5 /* 0-31 for E1 */ ++ ++typedef char *charp; ++#ifdef __KERNEL__ ++ ++/* Kernel versions... */ ++#define KMEM_CACHE_T struct kmem_cache ++ ++#define KZALLOC(size, gfp) my_kzalloc(size, gfp) ++#define KZFREE(p) \ ++ do { \ ++ memset((p), 0, sizeof(*(p))); \ ++ kfree(p); \ ++ } while (0); ++ ++#define DEVICE_ATTR_READER(name, dev, buf) \ ++ ssize_t name(struct device *dev, \ ++ struct device_attribute *attr, char *buf) ++#define DEVICE_ATTR_WRITER(name, dev, buf, count) \ ++ ssize_t name(struct device *dev, \ ++ struct device_attribute *attr, \ ++ const char *buf, size_t count) ++#define DRIVER_ATTR_READER(name, drv, buf) \ ++ ssize_t name(struct device_driver *drv, char * buf) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ++#define SET_PROC_DIRENTRY_OWNER(p) \ ++ do { \ ++ (p)->owner = THIS_MODULE; \ ++ } while (0); ++#else ++#define SET_PROC_DIRENTRY_OWNER(p) do { } while (0); ++#endif ++ ++#else ++typedef int bool; ++#endif /* ifdef __KERNEL__ */ ++typedef struct xbus xbus_t; ++typedef struct xpd xpd_t; ++typedef struct xframe xframe_t; ++typedef struct xpacket xpacket_t; ++typedef __u32 xpp_line_t; /* at most 31 lines for E1 */ ++typedef __u8 lineno_t; ++typedef __u8 xportno_t; ++ ++#define PORT_BROADCAST 255 ++ ++#endif /* XDEFS_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xframe_queue.c linux-source-4.19-dahdi/drivers/dahdi/xpp/xframe_queue.c +--- linux-source-4.19/drivers/dahdi/xpp/xframe_queue.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xframe_queue.c 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,311 @@ ++#include "xframe_queue.h" ++#include "xbus-core.h" ++#include "dahdi_debug.h" ++ ++extern int debug; ++ ++static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags); ++static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe); ++ ++void xframe_queue_init(struct xframe_queue *q, ++ unsigned int steady_state_count, unsigned int max_count, ++ const char *name, void *priv) ++{ ++ memset(q, 0, sizeof(*q)); ++ spin_lock_init(&q->lock); ++ INIT_LIST_HEAD(&q->head); ++ q->max_count = XFRAME_QUEUE_MARGIN + max_count; ++ q->steady_state_count = XFRAME_QUEUE_MARGIN + steady_state_count; ++ q->name = name; ++ q->priv = priv; ++} ++EXPORT_SYMBOL(xframe_queue_init); ++ ++void xframe_queue_clearstats(struct xframe_queue *q) ++{ ++ q->worst_count = 0; ++ //q->overflows = 0; /* Never clear overflows */ ++ q->worst_lag_usec = 0L; ++} ++EXPORT_SYMBOL(xframe_queue_clearstats); ++ ++static void __xframe_dump_queue(struct xframe_queue *q) ++{ ++ xframe_t *xframe; ++ int i = 0; ++ char prefix[30]; ++ ktime_t now = ktime_get(); ++ ++ printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n", ++ THIS_MODULE->name, q->name); ++ list_for_each_entry_reverse(xframe, &q->head, frame_list) { ++ xpacket_t *pack = (xpacket_t *)&xframe->packets[0]; ++ s64 usec = ktime_us_delta(now, xframe->kt_queued); ++ ++ snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5lld.%03lld msec", ++ i++, usec / 1000, usec % 1000); ++ dump_packet(prefix, pack, 1); ++ } ++} ++ ++static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe) ++{ ++ int ret = 1; ++ static int overflow_cnt; ++ ++ if (unlikely(q->disabled)) { ++ ret = 0; ++ goto out; ++ } ++ if (q->count >= q->max_count) { ++ q->overflows++; ++ if ((overflow_cnt++ % 1000) < 5) { ++ NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02lld.%lld ms\n", ++ q->name, q->steady_state_count, q->count, ++ q->max_count, q->worst_count, q->overflows, ++ q->worst_lag_usec / 1000, ++ q->worst_lag_usec % 1000); ++ __xframe_dump_queue(q); ++ } ++ ret = 0; ++ goto out; ++ } ++ if (++q->count > q->worst_count) ++ q->worst_count = q->count; ++ list_add_tail(&xframe->frame_list, &q->head); ++ xframe->kt_queued = ktime_get(); ++out: ++ return ret; ++} ++ ++bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe) ++{ ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&q->lock, flags); ++ ret = __xframe_enqueue(q, xframe); ++ spin_unlock_irqrestore(&q->lock, flags); ++ return ret; ++} ++EXPORT_SYMBOL(xframe_enqueue); ++ ++static xframe_t *__xframe_dequeue(struct xframe_queue *q) ++{ ++ xframe_t *frm = NULL; ++ struct list_head *h; ++ ktime_t now; ++ s64 usec_lag; ++ ++ if (list_empty(&q->head)) ++ goto out; ++ h = q->head.next; ++ list_del_init(h); ++ --q->count; ++ frm = list_entry(h, xframe_t, frame_list); ++ now = ktime_get(); ++ usec_lag = ktime_us_delta(now, frm->kt_queued); ++ if (q->worst_lag_usec < usec_lag) ++ q->worst_lag_usec = usec_lag; ++out: ++ return frm; ++} ++ ++xframe_t *xframe_dequeue(struct xframe_queue *q) ++{ ++ unsigned long flags; ++ xframe_t *frm; ++ ++ spin_lock_irqsave(&q->lock, flags); ++ frm = __xframe_dequeue(q); ++ spin_unlock_irqrestore(&q->lock, flags); ++ return frm; ++} ++EXPORT_SYMBOL(xframe_dequeue); ++ ++void xframe_queue_disable(struct xframe_queue *q, bool disabled) ++{ ++ q->disabled = disabled; ++} ++EXPORT_SYMBOL(xframe_queue_disable); ++ ++void xframe_queue_clear(struct xframe_queue *q) ++{ ++ xframe_t *xframe; ++ xbus_t *xbus = q->priv; ++ int i = 0; ++ ++ xframe_queue_disable(q, 1); ++ while ((xframe = xframe_dequeue(q)) != NULL) { ++ transport_free_xframe(xbus, xframe); ++ i++; ++ } ++ XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n", ++ q->name, i); ++} ++EXPORT_SYMBOL(xframe_queue_clear); ++ ++uint xframe_queue_count(struct xframe_queue *q) ++{ ++ return q->count; ++} ++EXPORT_SYMBOL(xframe_queue_count); ++ ++/*------------------------- Frame Alloc/Dealloc --------------------*/ ++ ++static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) ++{ ++ struct xbus_ops *ops; ++ xframe_t *xframe; ++ unsigned long flags; ++ ++ BUG_ON(!xbus); ++ ops = transportops_get(xbus); ++ if (unlikely(!ops)) { ++ XBUS_ERR(xbus, "Missing transport\n"); ++ return NULL; ++ } ++ spin_lock_irqsave(&xbus->transport.lock, flags); ++#if 0 ++ XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", ++ __func__, atomic_read(&xbus->transport.transport_refcount)); ++#endif ++ xframe = ops->alloc_xframe(xbus, gfp_flags); ++ if (!xframe) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 3001) == 0) ++ XBUS_ERR(xbus, ++ "Failed xframe allocation from transport (%d)\n", ++ rate_limit); ++ transportops_put(xbus); ++ /* fall through */ ++ } ++ spin_unlock_irqrestore(&xbus->transport.lock, flags); ++ return xframe; ++} ++ ++static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe) ++{ ++ struct xbus_ops *ops; ++ unsigned long flags; ++ ++ BUG_ON(!xbus); ++ ops = xbus->transport.ops; ++ BUG_ON(!ops); ++ spin_lock_irqsave(&xbus->transport.lock, flags); ++#if 0 ++ XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", ++ __func__, atomic_read(&xbus->transport.transport_refcount)); ++#endif ++ ops->free_xframe(xbus, xframe); ++ transportops_put(xbus); ++ spin_unlock_irqrestore(&xbus->transport.lock, flags); ++} ++ ++static bool xframe_queue_adjust(struct xframe_queue *q) ++{ ++ xbus_t *xbus; ++ xframe_t *xframe; ++ int delta; ++ unsigned long flags; ++ int ret = 0; ++ ++ BUG_ON(!q); ++ xbus = q->priv; ++ BUG_ON(!xbus); ++ spin_lock_irqsave(&q->lock, flags); ++ delta = q->count - q->steady_state_count; ++ if (delta < -XFRAME_QUEUE_MARGIN) { ++ /* Increase pool by one frame */ ++ //XBUS_INFO(xbus, "%s(%d): Allocate one\n", q->name, delta); ++ xframe = transport_alloc_xframe(xbus, GFP_ATOMIC); ++ if (!xframe) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 3001) == 0) ++ XBUS_ERR(xbus, "%s: failed frame allocation\n", ++ q->name); ++ goto out; ++ } ++ if (!__xframe_enqueue(q, xframe)) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 3001) == 0) ++ XBUS_ERR(xbus, "%s: failed enqueueing frame\n", ++ q->name); ++ transport_free_xframe(xbus, xframe); ++ goto out; ++ } ++ } else if (delta > XFRAME_QUEUE_MARGIN) { ++ /* Decrease pool by one frame */ ++ //XBUS_INFO(xbus, "%s(%d): Free one\n", q->name, delta); ++ xframe = __xframe_dequeue(q); ++ if (!xframe) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 3001) == 0) ++ XBUS_ERR(xbus, "%s: failed dequeueing frame\n", ++ q->name); ++ goto out; ++ } ++ transport_free_xframe(xbus, xframe); ++ } ++ ret = 1; ++out: ++ spin_unlock_irqrestore(&q->lock, flags); ++ return ret; ++} ++ ++xframe_t *get_xframe(struct xframe_queue *q) ++{ ++ xframe_t *xframe; ++ xbus_t *xbus; ++ ++ BUG_ON(!q); ++ xbus = (xbus_t *)q->priv; ++ BUG_ON(!xbus); ++ xframe_queue_adjust(q); ++ xframe = xframe_dequeue(q); ++ if (!xframe) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 3001) == 0) ++ XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, ++ rate_limit); ++ return NULL; ++ } ++ BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); ++ atomic_set(&xframe->frame_len, 0); ++ xframe->first_free = xframe->packets; ++ xframe->kt_created = ktime_get(); ++ /* ++ * If later parts bother to correctly initialize their ++ * headers, there is no need to memset() the whole data. ++ * ++ * ticket:403 ++ * ++ * memset(xframe->packets, 0, xframe->frame_maxlen); ++ */ ++ //XBUS_INFO(xbus, "%s\n", __func__); ++ return xframe; ++} ++EXPORT_SYMBOL(get_xframe); ++ ++void put_xframe(struct xframe_queue *q, xframe_t *xframe) ++{ ++ xbus_t *xbus; ++ ++ BUG_ON(!q); ++ xbus = (xbus_t *)q->priv; ++ BUG_ON(!xbus); ++ //XBUS_INFO(xbus, "%s\n", __func__); ++ BUG_ON(!TRANSPORT_EXIST(xbus)); ++ if (unlikely(!xframe_enqueue(q, xframe))) { ++ XBUS_ERR(xbus, "Failed returning xframe to %s\n", q->name); ++ transport_free_xframe(xbus, xframe); ++ return; ++ } ++ xframe_queue_adjust(q); ++} ++EXPORT_SYMBOL(put_xframe); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xframe_queue.h linux-source-4.19-dahdi/drivers/dahdi/xpp/xframe_queue.h +--- linux-source-4.19/drivers/dahdi/xpp/xframe_queue.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xframe_queue.h 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,34 @@ ++#ifndef XFRAME_QUEUE_H ++#define XFRAME_QUEUE_H ++ ++#include ++#include ++#include "xdefs.h" ++ ++#define XFRAME_QUEUE_MARGIN 10 ++ ++struct xframe_queue { ++ struct list_head head; ++ bool disabled; ++ unsigned int count; ++ unsigned int max_count; ++ unsigned int steady_state_count; ++ spinlock_t lock; ++ const char *name; ++ void *priv; ++ /* statistics */ ++ unsigned int worst_count; ++ unsigned int overflows; ++ s64 worst_lag_usec; /* since xframe creation */ ++}; ++ ++void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, ++ unsigned int max_count, const char *name, void *priv); ++__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe); ++__must_check xframe_t *xframe_dequeue(struct xframe_queue *q); ++void xframe_queue_clearstats(struct xframe_queue *q); ++void xframe_queue_disable(struct xframe_queue *q, bool disabled); ++void xframe_queue_clear(struct xframe_queue *q); ++uint xframe_queue_count(struct xframe_queue *q); ++ ++#endif /* XFRAME_QUEUE_ */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xpd.h linux-source-4.19-dahdi/drivers/dahdi/xpp/xpd.h +--- linux-source-4.19/drivers/dahdi/xpp/xpd.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xpd.h 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,245 @@ ++#ifndef XPD_H ++#define XPD_H ++ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xdefs.h" ++#include "xproto.h" ++ ++#ifdef __KERNEL__ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#endif /* __KERNEL__ */ ++ ++#include ++ ++#ifdef __KERNEL__ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) ++/* ++ * FIXME: Kludge for 2.6.19 ++ * bool is now defined as a proper boolean type (gcc _Bool) ++ * but the command line parsing framework handles it as int. ++ */ ++#define DEF_PARM_BOOL(name, init, perm, desc) \ ++ int name = init; \ ++ module_param(name, bool, perm); \ ++ MODULE_PARM_DESC(name, desc " [default " #init "]") ++#else ++#define DEF_PARM_BOOL(name, init, perm, desc) \ ++ bool name = init; \ ++ module_param(name, bool, perm); \ ++ MODULE_PARM_DESC(name, desc " [default " #init "]") ++#endif ++ ++#define DEF_PARM(type, name, init, perm, desc) \ ++ type name = init; \ ++ module_param(name, type, perm); \ ++ MODULE_PARM_DESC(name, desc " [default " #init "]") ++ ++#define DEF_ARRAY(type, name, count, init, desc) \ ++ unsigned int name ## _num_values; \ ++ type name[count] = {[0 ... ((count)-1)] = init}; \ ++ module_param_array(name, type, &name ## _num_values, 0644); \ ++ MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")") ++#endif // __KERNEL__ ++ ++#define CARD_DESC_MAGIC 0xca9dde5c ++ ++struct card_desc_struct { ++ struct list_head card_list; ++ u32 magic; ++ struct unit_descriptor unit_descriptor; ++}; ++ ++typedef enum xpd_direction { ++ TO_PSTN = 0, ++ TO_PHONE = 1, ++} xpd_direction_t; ++ ++#ifdef __KERNEL__ ++ ++/* ++ * XPD statistics counters ++ */ ++enum { ++ XPD_N_PCM_READ, ++ XPD_N_PCM_WRITE, ++ XPD_N_RECV_ERRORS, ++}; ++ ++#define XPD_COUNTER(xpd, counter) ((xpd)->counters[XPD_N_ ## counter]) ++ ++#define C_(x) [ XPD_N_ ## x ] = { #x } ++ ++/* yucky, make an instance so we can size it... */ ++static struct xpd_counters { ++ char *name; ++} xpd_counters[] = { ++C_(PCM_READ), C_(PCM_WRITE), C_(RECV_ERRORS),}; ++ ++#undef C_ ++ ++#define XPD_COUNTER_MAX (sizeof(xpd_counters)/sizeof(xpd_counters[0])) ++ ++enum xpd_state { ++ XPD_STATE_START, ++ XPD_STATE_INIT_REGS, ++ XPD_STATE_READY, ++ XPD_STATE_NOHW, ++}; ++ ++bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate); ++const char *xpd_statename(enum xpd_state st); ++ ++#define PHONEDEV(xpd) ((xpd)->phonedev) ++#define IS_PHONEDEV(xpd) (PHONEDEV(xpd).phoneops) ++ ++struct phonedev { ++ const struct phoneops *phoneops; /* Card level operations */ ++ struct dahdi_span span; ++ struct dahdi_chan *chans[32]; ++#define XPD_CHAN(xpd, chan) (PHONEDEV(xpd).chans[(chan)]) ++ struct dahdi_echocan_state *ec[32]; ++ ++ int channels; ++ xpd_direction_t direction; /* TO_PHONE, TO_PSTN */ ++ xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */ ++ xpp_line_t offhook_state; /* chip state: 0 - ONHOOK, 1 - OFHOOK */ ++ xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */ ++ /* Voice Mail Waiting Indication: */ ++ unsigned int msg_waiting[CHANNELS_PERXPD]; ++ xpp_line_t digital_outputs; /* 0 - no, 1 - yes */ ++ xpp_line_t digital_inputs; /* 0 - no, 1 - yes */ ++ xpp_line_t digital_signalling; /* BRI signalling channels */ ++ uint timing_priority; /* from 'span' directives in chan_dahdi.conf */ ++ ++ /* Assure atomicity of changes to pcm_len and wanted_pcm_mask */ ++ spinlock_t lock_recompute_pcm; ++ /* maintained by card drivers */ ++ uint pcm_len; /* allocation length of PCM packet (dynamic) */ ++ xpp_line_t wanted_pcm_mask; ++ xpp_line_t silence_pcm; /* inject silence during next tick */ ++ xpp_line_t mute_dtmf; ++ ++ bool ringing[CHANNELS_PERXPD]; ++ ++ atomic_t dahdi_registered; /* Am I fully registered with dahdi */ ++ atomic_t open_counter; /* Number of open channels */ ++ ++ /* Echo cancelation */ ++ u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE]; ++ u_char ec_chunk2[CHANNELS_PERXPD][DAHDI_CHUNKSIZE]; ++}; ++ ++/* ++ * An XPD is a single Xorcom Protocol Device ++ */ ++struct xpd { ++ char xpdname[XPD_NAMELEN]; ++ struct phonedev phonedev; ++ struct unit_descriptor unit_descriptor; ++#define XPD_HW(xpd) ((xpd)->unit_descriptor) ++ ++ const struct xops *xops; ++ xpd_type_t xpd_type; ++ const char *type_name; ++ int subunits; /* all siblings */ ++ enum xpd_state xpd_state; ++ struct device xpd_dev; ++#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev) ++ struct kref kref; ++#define kref_to_xpd(k) container_of(k, struct xpd, kref) ++ ++ xbus_t *xbus; /* The XBUS we are connected to */ ++ struct device *echocancel; ++ ++ spinlock_t lock; ++ ++ int flags; ++ unsigned long blink_mode; /* bitmask of blinking ports */ ++#define DEFAULT_LED_PERIOD (1000/8) /* in tick */ ++ ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *proc_xpd_dir; ++ struct proc_dir_entry *proc_xpd_summary; ++#endif ++ ++ int counters[XPD_COUNTER_MAX]; ++ ++ const xproto_table_t *xproto; /* Card level protocol table */ ++ void *priv; /* Card level private data */ ++ bool card_present; ++ reg_cmd_t requested_reply; ++ reg_cmd_t last_reply; ++ ++ unsigned long last_response; /* in jiffies */ ++ unsigned xbus_idx; /* index in xbus->xpds[] */ ++ struct xpd_addr addr; ++ struct list_head xpd_list; ++ unsigned int timer_count; ++}; ++ ++#define for_each_line(xpd, i) \ ++ for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++) ++#define IS_BRI(xpd) ((xpd)->xpd_type == XPD_TYPE_BRI) ++#define TICK_TOLERANCE 500 /* usec */ ++ ++#ifdef DEBUG_SYNC_PARPORT ++void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1); ++#else ++#define xbus_flip_bit(xbus, bitnum0, bitnum1) ++#endif ++ ++static inline void *my_kzalloc(size_t size, gfp_t flags) ++{ ++ void *p; ++ ++ p = kmalloc(size, flags); ++ if (p) ++ memset(p, 0, size); ++ return p; ++} ++ ++struct xpd_driver { ++ xpd_type_t xpd_type; ++ ++ struct device_driver driver; ++#define driver_to_xpd_driver(driver) \ ++ container_of(driver, struct xpd_driver, driver) ++}; ++ ++int xpd_driver_register(struct device_driver *driver); ++void xpd_driver_unregister(struct device_driver *driver); ++xpd_t *get_xpd(const char *msg, xpd_t *xpd); ++void put_xpd(const char *msg, xpd_t *xpd); ++int refcount_xpd(xpd_t *xpd); ++ ++#endif ++ ++#endif /* XPD_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xpp.conf linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp.conf +--- linux-source-4.19/drivers/dahdi/xpp/xpp.conf 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp.conf 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,33 @@ ++# /etc/dahdi/xpp.conf ++# ++# This file is used to configure the operation ++# of init_card_* initialization scripts. ++# ++ ++# pri_protocol: is an XPP PRI device E1 (default) or T1? ++#pri_protocol E1 ++# ++# Alternatively you can set this on a port by port basis if you have a strange ++# setup where some of the ports are E1 and some are T1. These specific ++# settings will override the default set above. ++#pri_protocol/xbus-00/xpd-02 T1 ++#pri_protocol/connector:usb-0000:00:1d.7-7/xpd-03 T1 ++#pri_protocol/label:usb:0000183/xpd-03 T1 ++ ++# International settings for the XPP FXO module. This is similar to the ++# 'opermode' kernel module of wctdm and wctdm24xxp . The default value ++# is 'FCC' (US settings). ++# ++# The valid settings can be shown by running the init_card_2_30 script with ++# the '-L' option. For example: ++# /usr/share/dahdi/init_card_2_30 -L ++# ++#opermode UK ++ ++# Set this to enable debug mode for the scripts: ++#debug 1 ++# ++# Skip the long calibration of the FXS modules. This saves time, but ++# makes the units consume much more power and hence highly unreocmmended ++# and unsupported. ++#fxs_skip_calib 1 +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xpp_dahdi.c linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_dahdi.c +--- linux-source-4.19/drivers/dahdi/xpp/xpp_dahdi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_dahdi.c 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,1252 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004, Xorcom ++ * ++ * Derived from ztdummy ++ * ++ * Copyright (C) 2002, Hermes Softlab ++ * Copyright (C) 2004, 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 /* for udelay */ ++#include ++#include ++#include ++#include ++#include "xbus-core.h" ++#include "xproto.h" ++#include "xpp_dahdi.h" ++#include "parport_debug.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++#ifdef CONFIG_PROC_FS ++struct proc_dir_entry *xpp_proc_toplevel = NULL; ++#define PROC_DIR "xpp" ++#define PROC_XPD_SUMMARY "summary" ++#endif ++ ++#define MAX_QUEUE_LEN 10000 ++#define DELAY_UNTIL_DIALTONE 3000 ++ ++DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++EXPORT_SYMBOL(debug); ++static DEF_PARM_BOOL(prefmaster, 0, 0644, ++ "Do we want to be dahdi preferred sync master"); ++// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit"); ++ ++#include "dahdi_debug.h" ++ ++static void phonedev_cleanup(xpd_t *xpd); ++ ++#ifdef DEBUG_SYNC_PARPORT ++/* ++ * Use parallel port to sample our PCM sync and diagnose quality and ++ * potential problems. A logic analizer or a scope should be connected ++ * to the data bits of the parallel port. ++ * ++ * Array parameter: Choose the two xbuses Id's to sample. ++ * This can be changed on runtime as well. Example: ++ * echo "3,5" > /sys/module/xpp/parameters/parport_xbuses ++ */ ++static int parport_xbuses[2] = { 0, 1 }; ++ ++unsigned int parport_xbuses_num_values; ++module_param_array(parport_xbuses, int, &parport_xbuses_num_values, 0577); ++MODULE_PARM_DESC(parport_xbuses, "Id's of xbuses to sample (1-2)"); ++ ++/* ++ * Flip a single bit in the parallel port: ++ * - The bit number is either bitnum0 or bitnum1 ++ * - Bit is selected by xbus number from parport_xbuses[] ++ */ ++void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1) ++{ ++ int num = xbus->num; ++ ++ if (num == parport_xbuses[0]) ++ flip_parport_bit(bitnum0); ++ if (num == parport_xbuses[1]) ++ flip_parport_bit(bitnum1); ++} ++EXPORT_SYMBOL(xbus_flip_bit); ++#endif ++ ++static atomic_t num_registered_spans = ATOMIC_INIT(0); ++ ++int total_registered_spans(void) ++{ ++ return atomic_read(&num_registered_spans); ++} ++ ++#ifdef CONFIG_PROC_FS ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops xpd_read_proc_ops; ++#else ++static const struct file_operations xpd_read_proc_ops; ++#endif ++#endif ++ ++/*------------------------- XPD Management -------------------------*/ ++ ++/* ++ * Called by put_xpd() when XPD has no more references. ++ */ ++static void xpd_destroy(struct kref *kref) ++{ ++ xpd_t *xpd; ++ ++ xpd = kref_to_xpd(kref); ++ XPD_DBG(DEVICES, xpd, "%s\n", __func__); ++ xpd_device_unregister(xpd); ++} ++ ++int refcount_xpd(xpd_t *xpd) ++{ ++ struct kref *kref = &xpd->kref; ++ ++ return refcount_read(&kref->refcount); ++} ++ ++xpd_t *get_xpd(const char *msg, xpd_t *xpd) ++{ ++ XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", msg, refcount_xpd(xpd)); ++ kref_get(&xpd->kref); ++ return xpd; ++} ++EXPORT_SYMBOL(get_xpd); ++ ++void put_xpd(const char *msg, xpd_t *xpd) ++{ ++ XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", msg, refcount_xpd(xpd)); ++ kref_put(&xpd->kref, xpd_destroy); ++} ++EXPORT_SYMBOL(put_xpd); ++ ++static void xpd_proc_remove(xbus_t *xbus, xpd_t *xpd) ++{ ++#ifdef CONFIG_PROC_FS ++ if (xpd->proc_xpd_dir) { ++ if (xpd->proc_xpd_summary) { ++ XPD_DBG(PROC, xpd, "Removing proc '%s'\n", ++ PROC_XPD_SUMMARY); ++ remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir); ++ xpd->proc_xpd_summary = NULL; ++ } ++ XPD_DBG(PROC, xpd, "Removing %s/%s proc directory\n", ++ xbus->busname, xpd->xpdname); ++ remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir); ++ xpd->proc_xpd_dir = NULL; ++ } ++#endif ++} ++ ++static int xpd_proc_create(xbus_t *xbus, xpd_t *xpd) ++{ ++#ifdef CONFIG_PROC_FS ++ XPD_DBG(PROC, xpd, "Creating proc directory\n"); ++ xpd->proc_xpd_dir = proc_mkdir(xpd->xpdname, xbus->proc_xbus_dir); ++ if (!xpd->proc_xpd_dir) { ++ XPD_ERR(xpd, "Failed to create proc directory\n"); ++ goto err; ++ } ++ xpd->proc_xpd_summary = proc_create_data(PROC_XPD_SUMMARY, 0444, ++ xpd->proc_xpd_dir, ++ &xpd_read_proc_ops, xpd); ++ if (!xpd->proc_xpd_summary) { ++ XPD_ERR(xpd, "Failed to create proc file '%s'\n", ++ PROC_XPD_SUMMARY); ++ goto err; ++ } ++ SET_PROC_DIRENTRY_OWNER(xpd->proc_xpd_summary); ++#endif ++ return 0; ++#ifdef CONFIG_PROC_FS ++err: ++ xpd_proc_remove(xbus, xpd); ++ return -EFAULT; ++#endif ++} ++ ++void xpd_free(xpd_t *xpd) ++{ ++ xbus_t *xbus = NULL; ++ ++ if (!xpd) ++ return; ++ if (xpd->xproto) ++ xproto_put(xpd->xproto); /* was taken in xpd_alloc() */ ++ xpd->xproto = NULL; ++ xbus = xpd->xbus; ++ if (!xbus) ++ return; ++ XPD_DBG(DEVICES, xpd, "\n"); ++ xpd_proc_remove(xbus, xpd); ++ xbus_xpd_unbind(xbus, xpd); ++ phonedev_cleanup(xpd); ++ KZFREE(xpd); ++ DBG(DEVICES, "refcount_xbus=%d\n", refcount_xbus(xbus)); ++ /* ++ * This must be last, so the xbus cannot be released before the xpd ++ */ ++ put_xbus(__func__, xbus); /* was taken in xpd_alloc() */ ++} ++EXPORT_SYMBOL(xpd_free); ++ ++/* ++ * Synchronous part of XPD detection. ++ * Called from new_card() ++ */ ++int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ int unit, ++ int subunit, __u8 type) ++{ ++ xpd_t *xpd = NULL; ++ bool to_phone; ++ ++ BUG_ON(type == XPD_TYPE_NOMODULE); ++ to_phone = BIT(subunit) & unit_descriptor->port_dir; ++ BUG_ON(!xbus); ++ xpd = xpd_byaddr(xbus, unit, subunit); ++ if (xpd) { ++ XPD_NOTICE(xpd, "XPD at %d%d already exists\n", unit, subunit); ++ return 0; ++ } ++ INFO("%s: [%d.%d] type=%d subtype=%d numchips=%d ports_per_chip=%d ports_dir=%d\n", ++ __func__, ++ unit_descriptor->addr.unit, ++ unit_descriptor->addr.subunit, ++ unit_descriptor->type, ++ unit_descriptor->subtype, ++ unit_descriptor->numchips, ++ unit_descriptor->ports_per_chip, ++ unit_descriptor->port_dir); ++ if (unit_descriptor->ports_per_chip <= 0 || unit_descriptor->ports_per_chip > CHANNELS_PERXPD) { ++ XBUS_NOTICE(xbus, "Illegal number of ports %d for XPD %d%d\n", ++ unit_descriptor->ports_per_chip, unit, subunit); ++ return 0; ++ } ++ xpd = ++ proto_table->xops->card_new(xbus, unit, subunit, proto_table, ++ unit_descriptor, ++ to_phone); ++ if (!xpd) { ++ XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d) failed. Ignored.\n", ++ unit, subunit, proto_table->type, ++ to_phone); ++ return -EINVAL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(create_xpd); ++ ++#ifdef CONFIG_PROC_FS ++ ++/** ++ * Prints a general procfs entry for the bus, under xpp/BUSNAME/summary ++ */ ++static int xpd_read_proc_show(struct seq_file *sfile, void *data) ++{ ++ int len = 0; ++ xpd_t *xpd = sfile->private; ++ int i; ++ ++ if (!xpd) ++ return -EINVAL; ++ ++ seq_printf(sfile, ++ "%s (%s, card %s, span %d)\n" "timing_priority: %d\n" ++ "timer_count: %d span->mainttimer=%d\n", xpd->xpdname, ++ xpd->type_name, (xpd->card_present) ? "present" : "missing", ++ (SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0, ++ PHONEDEV(xpd).timing_priority, xpd->timer_count, ++ PHONEDEV(xpd).span.mainttimer); ++ seq_printf(sfile, "xpd_state: %s (%d)\n", ++ xpd_statename(xpd->xpd_state), xpd->xpd_state); ++ seq_printf(sfile, "open_counter=%d refcount=%d\n", ++ atomic_read(&PHONEDEV(xpd).open_counter), ++ refcount_xpd(xpd)); ++ seq_printf(sfile, "Address: U=%d S=%d\n", xpd->addr.unit, ++ xpd->addr.subunit); ++ seq_printf(sfile, "Subunits: %d\n", xpd->subunits); ++ seq_printf(sfile, "Type: %d.%d\n", xpd->xpd_type, XPD_HW(xpd).subtype); ++ seq_printf(sfile, "Hardware type: %d.%d\nn", XPD_HW(xpd).type, XPD_HW(xpd).subtype); ++ seq_printf(sfile, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len); ++ seq_printf(sfile, "wanted_pcm_mask=0x%04X\n\n", ++ PHONEDEV(xpd).wanted_pcm_mask); ++ seq_printf(sfile, "mute_dtmf=0x%04X\n\n", ++ PHONEDEV(xpd).mute_dtmf); ++ seq_printf(sfile, "STATES:"); ++ seq_printf(sfile, "\n\t%-17s: ", "output_relays"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d ", ++ IS_SET(PHONEDEV(xpd).digital_outputs, i)); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "input_relays"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d ", ++ IS_SET(PHONEDEV(xpd).digital_inputs, i)); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "offhook"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d ", IS_OFFHOOK(xpd, i)); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "oht_pcm_pass"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d ", ++ IS_SET(PHONEDEV(xpd).oht_pcm_pass, i)); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "msg_waiting"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d ", PHONEDEV(xpd).msg_waiting[i]); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "ringing"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d ", PHONEDEV(xpd).ringing[i]); ++ } ++ seq_printf(sfile, "\n\t%-17s: ", "no_pcm"); ++ for_each_line(xpd, i) { ++ seq_printf(sfile, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i)); ++ } ++#if 1 ++ if (SPAN_REGISTERED(xpd)) { ++ seq_printf(sfile, ++ "\nPCM:\n |" ++ " [readchunk] |" ++ " [writechunk] | W D"); ++ for_each_line(xpd, i) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ __u8 rchunk[DAHDI_CHUNKSIZE]; ++ __u8 wchunk[DAHDI_CHUNKSIZE]; ++ __u8 *rp; ++ __u8 *wp; ++ int j; ++ ++ if (IS_SET(PHONEDEV(xpd).digital_outputs, i)) ++ continue; ++ if (IS_SET(PHONEDEV(xpd).digital_inputs, i)) ++ continue; ++ if (IS_SET(PHONEDEV(xpd).digital_signalling, i)) ++ continue; ++ rp = chan->readchunk; ++ wp = chan->writechunk; ++ memcpy(rchunk, rp, DAHDI_CHUNKSIZE); ++ memcpy(wchunk, wp, DAHDI_CHUNKSIZE); ++ seq_printf(sfile, "\n port %2d> | ", i); ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) ++ seq_printf(sfile, "%02X ", rchunk[j]); ++ seq_printf(sfile, " | "); ++ for (j = 0; j < DAHDI_CHUNKSIZE; j++) ++ seq_printf(sfile, "%02X ", wchunk[j]); ++ seq_printf(sfile, " | %c", ++ (IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i)) ++ ? '+' : ' '); ++ seq_printf(sfile, " %c", ++ (IS_SET(PHONEDEV(xpd).mute_dtmf, i)) ++ ? '-' : ' '); ++ } ++ } ++#endif ++#if 0 ++ if (SPAN_REGISTERED(xpd)) { ++ seq_printf(sfile, "\nSignalling:\n"); ++ for_each_line(xpd, i) { ++ struct dahdi_chan *chan = XPD_CHAN(xpd, i); ++ seq_printf(sfile, ++ "\t%2d> sigcap=0x%04X sig=0x%04X\n", i, ++ chan->sigcap, chan->sig); ++ } ++ } ++#endif ++ seq_printf(sfile, "\nCOUNTERS:\n"); ++ for (i = 0; i < XPD_COUNTER_MAX; i++) { ++ seq_printf(sfile, "\t\t%-20s = %d\n", ++ xpd_counters[i].name, xpd->counters[i]); ++ } ++ seq_printf(sfile, "<-- len=%d\n", len); ++ return 0; ++} ++ ++static int xpd_read_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, xpd_read_proc_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops xpd_read_proc_ops = { ++ .proc_open = xpd_read_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations xpd_read_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = xpd_read_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++#endif ++ ++const char *xpd_statename(enum xpd_state st) ++{ ++ switch (st) { ++ case XPD_STATE_START: ++ return "START"; ++ case XPD_STATE_INIT_REGS: ++ return "INIT_REGS"; ++ case XPD_STATE_READY: ++ return "READY"; ++ case XPD_STATE_NOHW: ++ return "NOHW"; ++ } ++ return NULL; ++} ++ ++bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate) ++{ ++ BUG_ON(!xpd); ++ XPD_DBG(DEVICES, xpd, "%s: %s (%d) -> %s (%d)\n", __func__, ++ xpd_statename(xpd->xpd_state), xpd->xpd_state, ++ xpd_statename(newstate), newstate); ++ switch (newstate) { ++ case XPD_STATE_START: ++ goto badstate; ++ case XPD_STATE_INIT_REGS: ++ if (xpd->xpd_state != XPD_STATE_START) ++ goto badstate; ++ if (xpd->addr.subunit != 0) { ++ XPD_NOTICE(xpd, ++ "%s: Moving to %s allowed only for subunit 0\n", ++ __func__, xpd_statename(newstate)); ++ goto badstate; ++ } ++ break; ++ case XPD_STATE_READY: ++ if (xpd->addr.subunit == 0) { ++ /* Unit 0 script initialize registers of all subunits */ ++ if (xpd->xpd_state != XPD_STATE_INIT_REGS) ++ goto badstate; ++ } else { ++ if (xpd->xpd_state != XPD_STATE_START) ++ goto badstate; ++ } ++ break; ++ case XPD_STATE_NOHW: ++ break; ++ default: ++ XPD_ERR(xpd, "%s: Unknown newstate=%d\n", __func__, newstate); ++ } ++ xpd->xpd_state = newstate; ++ return 1; ++badstate: ++ XPD_NOTICE(xpd, "%s: cannot transition: %s (%d) -> %s (%d)\n", __func__, ++ xpd_statename(xpd->xpd_state), xpd->xpd_state, ++ xpd_statename(newstate), newstate); ++ return 0; ++} ++ ++/* ++ * Cleanup/initialize phonedev ++ */ ++static void phonedev_cleanup(xpd_t *xpd) ++{ ++ struct phonedev *phonedev = &PHONEDEV(xpd); ++ unsigned int x; ++ ++ for (x = 0; x < phonedev->channels; x++) { ++ if (phonedev->chans[x]) { ++ KZFREE(phonedev->chans[x]); ++ phonedev->chans[x] = NULL; ++ } ++ if (phonedev->ec[x]) { ++ KZFREE(phonedev->ec[x]); ++ phonedev->ec[x] = NULL; ++ } ++ } ++ phonedev->channels = 0; ++} ++ ++int phonedev_alloc_channels(xpd_t *xpd, int channels) ++{ ++ struct phonedev *phonedev = &PHONEDEV(xpd); ++ int old_channels = phonedev->channels; ++ unsigned int x; ++ ++ XPD_DBG(DEVICES, xpd, "Reallocating channels: %d -> %d\n", ++ old_channels, channels); ++ phonedev_cleanup(xpd); ++ phonedev->channels = channels; ++ for (x = 0; x < phonedev->channels; x++) { ++ if (! ++ (phonedev->chans[x] = ++ KZALLOC(sizeof(*(phonedev->chans[x])), GFP_KERNEL))) { ++ ERR("%s: Unable to allocate channel %d\n", __func__, x); ++ goto err; ++ } ++ phonedev->ec[x] = ++ KZALLOC(sizeof(*(phonedev->ec[x])), GFP_KERNEL); ++ if (!phonedev->ec[x]) { ++ ERR("%s: Unable to allocate ec state %d\n", __func__, ++ x); ++ goto err; ++ } ++ } ++ return 0; ++err: ++ phonedev_cleanup(xpd); ++ return -ENOMEM; ++} ++EXPORT_SYMBOL(phonedev_alloc_channels); ++ ++__must_check static int phonedev_init(xpd_t *xpd, ++ const xproto_table_t *proto_table, ++ int channels, xpp_line_t no_pcm) ++{ ++ struct phonedev *phonedev = &PHONEDEV(xpd); ++ ++ spin_lock_init(&phonedev->lock_recompute_pcm); ++ phonedev->no_pcm = no_pcm; ++ phonedev->offhook_state = 0x0; /* ONHOOK */ ++ phonedev->phoneops = proto_table->phoneops; ++ phonedev->digital_outputs = 0; ++ phonedev->digital_inputs = 0; ++ atomic_set(&phonedev->dahdi_registered, 0); ++ atomic_set(&phonedev->open_counter, 0); ++ if (phonedev_alloc_channels(xpd, channels) < 0) ++ goto err; ++ return 0; ++err: ++ return -ENOMEM; ++} ++ ++ ++/* ++ * xpd_alloc - Allocator for new XPD's ++ * ++ */ ++__must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, ++ size_t privsize, ++ const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ int channels) ++{ ++ xpd_t *xpd = NULL; ++ size_t alloc_size = sizeof(xpd_t) + privsize; ++ int type = proto_table->type; ++ xpp_line_t no_pcm = 0; ++ ++ BUG_ON(!proto_table); ++ XBUS_DBG(DEVICES, xbus, "type=%d channels=%d (alloc_size=%zd)\n", type, ++ channels, alloc_size); ++ if (channels > CHANNELS_PERXPD) { ++ XBUS_ERR(xbus, "%s: type=%d: too many channels %d\n", __func__, ++ type, channels); ++ goto err; ++ } ++ ++ if ((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) { ++ XBUS_ERR(xbus, "%s: type=%d: Unable to allocate memory\n", ++ __func__, type); ++ goto err; ++ } ++ xpd->priv = (__u8 *)xpd + sizeof(xpd_t); ++ spin_lock_init(&xpd->lock); ++ xpd->card_present = 0; ++ xpd->xpd_type = proto_table->type; ++ xpd->xproto = proto_table; ++ xpd->unit_descriptor = *unit_descriptor; ++ xpd->xops = proto_table->xops; ++ xpd->xpd_state = XPD_STATE_START; ++ xpd->subunits = subunits_of_xpd(unit_descriptor, proto_table); ++ kref_init(&xpd->kref); ++ ++ /* For USB-1 disable some channels */ ++ if (MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) { ++ no_pcm = ++ 0x7F | PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd). ++ digital_inputs; ++ XBUS_NOTICE(xbus, ++ "max xframe size = %d, disabling some PCM channels. " ++ "no_pcm=0x%04X\n", ++ MAX_SEND_SIZE(xbus), PHONEDEV(xpd).no_pcm); ++ } ++ if (phonedev_init(xpd, proto_table, channels, no_pcm) < 0) ++ goto err; ++ xbus_xpd_bind(xbus, xpd, unit, subunit); ++ if (xpd_proc_create(xbus, xpd) < 0) ++ goto err; ++ /* ++ * This makes sure the xbus cannot be removed before this xpd ++ * is removed in xpd_free() ++ */ ++ xbus = get_xbus(__func__, xbus->num); /* returned in xpd_free() */ ++ xproto_get(type); /* will be returned in xpd_free() */ ++ return xpd; ++err: ++ if (xpd) { ++ xpd_proc_remove(xbus, xpd); ++ phonedev_cleanup(xpd); ++ KZFREE(xpd); ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(xpd_alloc); ++ ++/* ++ * The xpd isn't open by anyone, we can unregister it and free it ++ */ ++void xpd_remove(xpd_t *xpd) ++{ ++ BUG_ON(!xpd); ++ XPD_INFO(xpd, "Remove\n"); ++ CALL_XMETHOD(card_remove, xpd); ++ xpd_free(xpd); ++} ++ ++void update_xpd_status(xpd_t *xpd, int alarm_flag) ++{ ++ struct dahdi_span *span = &PHONEDEV(xpd).span; ++ ++ if (!SPAN_REGISTERED(xpd)) { ++#if 0 ++ XPD_NOTICE(xpd, ++ "%s: XPD is not registered. Skipping.\n", ++ __func__); ++#endif ++ return; ++ } ++ switch (alarm_flag) { ++ case DAHDI_ALARM_NONE: ++ xpd->last_response = jiffies; ++ break; ++ default: ++ // Nothing ++ break; ++ } ++ if (span->alarms == alarm_flag) ++ return; ++ XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", ++ PHONEDEV(xpd).span.name, alarm_flag); ++ span->alarms = alarm_flag; ++ dahdi_alarm_notify(span); ++} ++EXPORT_SYMBOL(update_xpd_status); ++ ++/* ++ * Used to block/pass PCM during onhook-transfers. E.g: ++ * - Playing FSK after FXS ONHOOK for MWI (non-neon style) ++ * - Playing DTFM/FSK for FXO Caller-ID detection. ++ */ ++void oht_pcm(xpd_t *xpd, int pos, bool pass) ++{ ++ if (pass) { ++ LINE_DBG(SIGNAL, xpd, pos, "OHT PCM: pass\n"); ++ BIT_SET(PHONEDEV(xpd).oht_pcm_pass, pos); ++ } else { ++ LINE_DBG(SIGNAL, xpd, pos, "OHT PCM: block\n"); ++ BIT_CLR(PHONEDEV(xpd).oht_pcm_pass, pos); ++ } ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++} ++EXPORT_SYMBOL(oht_pcm); ++ ++/* ++ * Update our hookstate -- for PCM block/pass ++ */ ++void mark_offhook(xpd_t *xpd, int pos, bool to_offhook) ++{ ++ if (to_offhook) { ++ LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK\n"); ++ BIT_SET(PHONEDEV(xpd).offhook_state, pos); ++ } else { ++ LINE_DBG(SIGNAL, xpd, pos, "ONHOOK\n"); ++ BIT_CLR(PHONEDEV(xpd).offhook_state, pos); ++ } ++ CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); ++} ++EXPORT_SYMBOL(mark_offhook); ++ ++/* ++ * Send a signalling notification to Asterisk ++ */ ++void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig) ++{ ++ /* ++ * We should not spinlock before calling dahdi_hooksig() as ++ * it may call back into our xpp_hooksig() and cause ++ * a nested spinlock scenario ++ */ ++ LINE_DBG(SIGNAL, xpd, pos, "rxsig=%s\n", rxsig2str(rxsig)); ++ if (SPAN_REGISTERED(xpd)) ++ dahdi_hooksig(XPD_CHAN(xpd, pos), rxsig); ++} ++EXPORT_SYMBOL(notify_rxsig); ++ ++/* ++ * Called when hardware state changed: ++ * - FXS -- the phone was picked up or hanged-up. ++ * - FXO -- we answered the phone or handed-up. ++ */ ++void hookstate_changed(xpd_t *xpd, int pos, bool to_offhook) ++{ ++ BUG_ON(!xpd); ++ mark_offhook(xpd, pos, to_offhook); ++ if (!to_offhook) { ++ oht_pcm(xpd, pos, 0); ++ /* ++ * To prevent latest PCM to stay in buffers ++ * indefinitely, mark this channel for a ++ * single silence transmittion. ++ * ++ * This bit will be cleared on the next tick. ++ */ ++ BIT_SET(PHONEDEV(xpd).silence_pcm, pos); ++ } ++ notify_rxsig(xpd, pos, ++ (to_offhook) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK); ++} ++EXPORT_SYMBOL(hookstate_changed); ++ ++#define XPP_MAX_LEN 512 ++ ++/*------------------------- Dahdi Interfaces -----------------------*/ ++ ++/* ++ * Called with spinlock held on chan. Must not call back ++ * dahdi functions. ++ */ ++static int _xpp_open(struct dahdi_chan *chan) ++{ ++ xpd_t *xpd; ++ xbus_t *xbus; ++ int pos; ++ int open_counter; ++ ++ if (!chan) { ++ NOTICE("open called on a null chan\n"); ++ return -EINVAL; ++ } ++ xpd = chan->pvt; ++ if (!xpd) { ++ NOTICE("open called on a chan with no pvt (xpd)\n"); ++ BUG(); ++ } ++ xbus = xpd->xbus; ++ if (!xbus) { ++ NOTICE("open called on a chan with no xbus\n"); ++ BUG(); ++ } ++ pos = chan->chanpos - 1; ++ if (!xpd->card_present) { ++ LINE_NOTICE(xpd, pos, "Cannot open -- device not ready\n"); ++ return -ENODEV; ++ } ++ open_counter = atomic_inc_return(&PHONEDEV(xpd).open_counter); ++ LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm, ++ current->pid, open_counter); ++ if (PHONE_METHOD(card_open, xpd)) ++ CALL_PHONE_METHOD(card_open, xpd, pos); ++ return 0; ++} ++ ++int xpp_open(struct dahdi_chan *chan) ++{ ++ unsigned long flags; ++ int res; ++ spin_lock_irqsave(&chan->lock, flags); ++ res = _xpp_open(chan); ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return res; ++} ++EXPORT_SYMBOL(xpp_open); ++ ++int xpp_close(struct dahdi_chan *chan) ++{ ++ xpd_t *xpd = chan->pvt; ++ int pos = chan->chanpos - 1; ++ int open_counter; ++ ++ if (PHONE_METHOD(card_close, xpd)) ++ CALL_PHONE_METHOD(card_close, xpd, pos); ++ /* from xpp_open(): */ ++ open_counter = atomic_dec_return(&PHONEDEV(xpd).open_counter); ++ LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm, ++ current->pid, open_counter); ++ return 0; ++} ++EXPORT_SYMBOL(xpp_close); ++ ++void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd) ++{ ++ char *extra_msg = ""; ++ ++ if (_IOC_TYPE(cmd) == 'J') ++ extra_msg = " (for old ZAPTEL)"; ++ XPD_NOTICE(xpd, "%s: Bad ioctl%s\n", msg, extra_msg); ++ XPD_NOTICE(xpd, "ENOTTY: chan=%d cmd=0x%x\n", pos, cmd); ++ XPD_NOTICE(xpd, " IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd)); ++ XPD_NOTICE(xpd, " IOC_DIR=0x%02X\n", _IOC_DIR(cmd)); ++ XPD_NOTICE(xpd, " IOC_NR=%d\n", _IOC_NR(cmd)); ++ XPD_NOTICE(xpd, " IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd)); ++} ++EXPORT_SYMBOL(report_bad_ioctl); ++ ++int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg) ++{ ++ xpd_t *xpd = chan->pvt; ++ int pos = chan->chanpos - 1; ++ ++ if (!xpd) { ++ ERR("%s: channel in pos %d, was already closed. Ignore.\n", ++ __func__, pos); ++ return -ENODEV; ++ } ++ switch (cmd) { ++ default: ++ /* Some span-specific commands before we give up: */ ++ if (PHONE_METHOD(card_ioctl, xpd)) { ++ return CALL_PHONE_METHOD(card_ioctl, xpd, pos, cmd, ++ arg); ++ } ++ report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); ++ return -ENOTTY; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(xpp_ioctl); ++ ++int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) ++{ ++ xpd_t *xpd = chan->pvt; ++ xbus_t *xbus; ++ int pos = chan->chanpos - 1; ++ ++ if (!xpd) { ++ ERR("%s: channel in pos %d, was already closed. Ignore.\n", ++ __func__, pos); ++ return -ENODEV; ++ } ++ if (!PHONE_METHOD(card_hooksig, xpd)) { ++ LINE_ERR(xpd, pos, ++ "%s: No hooksig method for this channel. Ignore.\n", ++ __func__); ++ return -ENODEV; ++ } ++ xbus = xpd->xbus; ++ BUG_ON(!xbus); ++ DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), ++ txsig); ++ return CALL_PHONE_METHOD(card_hooksig, xpd, pos, txsig); ++} ++EXPORT_SYMBOL(xpp_hooksig); ++ ++/* Req: Set the requested chunk size. This is the unit in which you must ++ report results for conferencing, etc */ ++int xpp_setchunksize(struct dahdi_span *span, int chunksize); ++ ++/* Enable maintenance modes */ ++int xpp_maint(struct dahdi_span *span, int cmd) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ int ret = 0; ++#if 0 ++ char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG"; ++#endif ++ ++ DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer); ++ switch (cmd) { ++ case DAHDI_MAINT_NONE: ++ INFO("XXX Turn off local and remote loops XXX\n"); ++ break; ++ case DAHDI_MAINT_LOCALLOOP: ++ INFO("XXX Turn on local loopback XXX\n"); ++ break; ++ case DAHDI_MAINT_REMOTELOOP: ++ INFO("XXX Turn on remote loopback XXX\n"); ++ break; ++ case DAHDI_MAINT_LOOPUP: ++ INFO("XXX Send loopup code XXX\n"); ++ break; ++ case DAHDI_MAINT_LOOPDOWN: ++ INFO("XXX Send loopdown code XXX\n"); ++ break; ++ default: ++ ERR("XPP: Unknown maint command: %d\n", cmd); ++ ret = -EINVAL; ++ break; ++ } ++ if (span->mainttimer || span->maintstat) ++ update_xpd_status(xpd, DAHDI_ALARM_LOOPBACK); ++ return ret; ++} ++EXPORT_SYMBOL(xpp_maint); ++ ++#ifdef CONFIG_DAHDI_WATCHDOG ++/* ++ * If the watchdog detects no received data, it will call the ++ * watchdog routine ++ */ ++int xpp_watchdog(struct dahdi_span *span, int cause) ++{ ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1000) == 0) ++ DBG(GENERAL, "\n"); ++ return 0; ++} ++EXPORT_SYMBOL(xpp_watchdog); ++#endif ++ ++/* ++ * Hardware Echo Canceller management ++ */ ++static void echocan_free(struct dahdi_chan *chan, ++ struct dahdi_echocan_state *ec) ++{ ++ xpd_t *xpd; ++ xbus_t *xbus; ++ int pos = chan->chanpos - 1; ++ const struct echoops *echoops; ++ ++ xpd = chan->pvt; ++ xbus = xpd->xbus; ++ echoops = ECHOOPS(xbus); ++ if (!echoops) ++ return; ++ LINE_DBG(GENERAL, xpd, pos, "mode=0x%X\n", ec->status.mode); ++ CALL_EC_METHOD(ec_set, xbus, xpd, pos, 0); ++ CALL_EC_METHOD(ec_update, xbus, xbus); ++ put_xpd(__func__, xpd); /* aquired in xpp_echocan_create() */ ++} ++ ++static const struct dahdi_echocan_features xpp_ec_features = { ++}; ++ ++static const struct dahdi_echocan_ops xpp_ec_ops = { ++ .echocan_free = echocan_free, ++}; ++ ++const char *xpp_echocan_name(const struct dahdi_chan *chan) ++{ ++ xpd_t *xpd; ++ xbus_t *xbus; ++ int pos; ++ ++ if (!chan) { ++ NOTICE("%s(NULL)\n", __func__); ++ return "XPP"; ++ } ++ xpd = chan->pvt; ++ xbus = xpd->xbus; ++ pos = chan->chanpos - 1; ++ LINE_DBG(GENERAL, xpd, pos, "\n"); ++ if (!ECHOOPS(xbus)) ++ return NULL; ++ /* ++ * quirks and limitations ++ */ ++ if (xbus->quirks.has_fxo) { ++ if (xbus->quirks.has_digital_span && xpd->xpd_type == XPD_TYPE_FXO) { ++ LINE_NOTICE(xpd, pos, ++ "quirk: give up HWEC on FXO: " ++ "AB has digital span\n"); ++ return NULL; ++ } else if (xbus->sync_mode != SYNC_MODE_AB ++ && xpd->xpd_type == XPD_TYPE_FXS) { ++ LINE_NOTICE(xpd, pos, ++ "quirk: give up HWEC on FXS: " ++ "AB has FXO and is sync slave\n"); ++ return NULL; ++ } ++ } ++ return "XPP"; ++} ++EXPORT_SYMBOL(xpp_echocan_name); ++ ++int xpp_echocan_create(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec) ++{ ++ xpd_t *xpd; ++ xbus_t *xbus; ++ int pos; ++ struct phonedev *phonedev; ++ const struct echoops *echoops; ++ int ret; ++ ++ xpd = chan->pvt; ++ xbus = xpd->xbus; ++ pos = chan->chanpos - 1; ++ echoops = ECHOOPS(xbus); ++ if (!echoops) ++ return -ENODEV; ++ phonedev = &PHONEDEV(xpd); ++ *ec = phonedev->ec[pos]; ++ (*ec)->ops = &xpp_ec_ops; ++ (*ec)->features = xpp_ec_features; ++ xpd = get_xpd(__func__, xpd); /* Returned in echocan_free() */ ++ LINE_DBG(GENERAL, xpd, pos, "(tap=%d, param_count=%d)\n", ++ ecp->tap_length, ecp->param_count); ++ ret = CALL_EC_METHOD(ec_set, xbus, xpd, pos, 1); ++ CALL_EC_METHOD(ec_update, xbus, xbus); ++ return ret; ++} ++EXPORT_SYMBOL(xpp_echocan_create); ++ ++void xpp_span_assigned(struct dahdi_span *span) ++{ ++ struct phonedev *phonedev = container_of(span, struct phonedev, span); ++ xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); ++ ++ XPD_INFO(xpd, "Span assigned: %d\n", span->spanno); ++ if (xpd->card_present) { ++ span->alarms &= ~DAHDI_ALARM_NOTOPEN; ++ dahdi_alarm_notify(&phonedev->span); ++ } ++ if (PHONE_METHOD(span_assigned, xpd)) ++ CALL_PHONE_METHOD(span_assigned, xpd); ++} ++EXPORT_SYMBOL(xpp_span_assigned); ++ ++static const struct dahdi_span_ops xpp_span_ops = { ++ .owner = THIS_MODULE, ++ .open = xpp_open, ++ .close = xpp_close, ++ .ioctl = xpp_ioctl, ++ .maint = xpp_maint, ++ .echocan_create = xpp_echocan_create, ++ .echocan_name = xpp_echocan_name, ++ .assigned = xpp_span_assigned, ++}; ++ ++static const struct dahdi_span_ops xpp_rbs_span_ops = { ++ .owner = THIS_MODULE, ++ .hooksig = xpp_hooksig, ++ .open = xpp_open, ++ .close = xpp_close, ++ .ioctl = xpp_ioctl, ++ .maint = xpp_maint, ++ .echocan_create = xpp_echocan_create, ++ .echocan_name = xpp_echocan_name, ++ .assigned = xpp_span_assigned, ++}; ++ ++void xpd_set_spanname(xpd_t *xpd) ++{ ++ struct dahdi_span *span = &PHONEDEV(xpd).span; ++ ++ snprintf(span->name, MAX_SPANNAME, "%s/%s", xpd->xbus->busname, ++ xpd->xpdname); ++ /* ++ * The "Xorcom XPD" is a prefix in one of the regexes we ++ * use in our dahdi_genconf to match for PRI cards. ++ * FIXME: After moving completely to sysfs, we can remove ++ * this horseshit. ++ */ ++ snprintf(span->desc, MAX_SPANDESC, "Xorcom XPD [%s].%d: %s", ++ xpd->xbus->label, span->offset + 1, xpd->type_name); ++} ++EXPORT_SYMBOL(xpd_set_spanname); ++ ++static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn) ++{ ++ struct dahdi_span *span; ++ ++ memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span)); ++ phonedev_alloc_channels(xpd, cn); ++ span = &PHONEDEV(xpd).span; ++ span->deflaw = DAHDI_LAW_MULAW; /* card_* drivers may override */ ++ span->channels = cn; ++ span->chans = PHONEDEV(xpd).chans; ++ ++ span->flags = DAHDI_FLAG_RBS; ++ span->offset = offset; ++ if (PHONEDEV(xpd).phoneops->card_hooksig) ++ span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */ ++ else ++ span->ops = &xpp_span_ops; ++ xpd_set_spanname(xpd); ++ list_add_tail(&span->device_node, &xpd->xbus->ddev->spans); ++} ++ ++int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset) ++{ ++ xbus_t *xbus; ++ int cn; ++ struct phonedev *phonedev; ++ ++ BUG_ON(!xpd); ++ ++ xbus = xpd->xbus; ++ ++ if (!IS_PHONEDEV(xpd)) { ++ XPD_ERR(xpd, "Not a telephony device\n"); ++ return -EBADF; ++ } ++ ++ phonedev = &PHONEDEV(xpd); ++ ++ if (SPAN_REGISTERED(xpd)) { ++ XPD_ERR(xpd, "Already registered\n"); ++ return -EEXIST; ++ } ++ ++ cn = PHONEDEV(xpd).channels; ++ xpd_init_span(xpd, offset, cn); ++ XPD_DBG(DEVICES, xpd, "Preregister local span %d: %d channels.\n", ++ offset + 1, cn); ++ CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 1); ++ return 0; ++} ++ ++int xpd_dahdi_postregister(xpd_t *xpd) ++{ ++ int cn; ++ ++ atomic_inc(&num_registered_spans); ++ atomic_inc(&PHONEDEV(xpd).dahdi_registered); ++ CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 1); ++ /* ++ * Update dahdi about our state: ++ * - Since asterisk didn't open the channel yet, ++ * the report is discarded anyway. ++ * - Our FXS driver have another notification mechanism that ++ * is triggered (indirectly) by the open() of the channe. ++ * - The real fix should be in Asterisk (to get the correct state ++ * after open). ++ */ ++ for_each_line(xpd, cn) { ++ if (IS_OFFHOOK(xpd, cn)) ++ notify_rxsig(xpd, cn, DAHDI_RXSIG_OFFHOOK); ++ } ++ return 0; ++} ++ ++/* ++ * Try our best to make asterisk close all channels related to ++ * this Astribank: ++ * - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans. ++ * - Notify dahdi afterwards about spans ++ * (so it can see all changes at once). ++ * - Also send DAHDI_EVENT_REMOVED on all channels. ++ */ ++void xpd_dahdi_preunregister(xpd_t *xpd) ++{ ++ if (!xpd || !IS_PHONEDEV(xpd)) ++ return; ++ XPD_DBG(DEVICES, xpd, "\n"); ++ update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN); ++ if (xpd->card_present) ++ CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0); ++ /* Now notify dahdi */ ++ if (SPAN_REGISTERED(xpd)) { ++ int j; ++ ++ dahdi_alarm_notify(&PHONEDEV(xpd).span); ++ XPD_DBG(DEVICES, xpd, ++ "Queuing DAHDI_EVENT_REMOVED on all channels " ++ "to ask user to release them\n"); ++ for (j = 0; j < PHONEDEV(xpd).span.channels; j++) { ++ dahdi_qevent_lock(XPD_CHAN(xpd, j), ++ DAHDI_EVENT_REMOVED); ++ } ++ } ++} ++ ++void xpd_dahdi_postunregister(xpd_t *xpd) ++{ ++ if (!xpd || !IS_PHONEDEV(xpd)) ++ return; ++ atomic_dec(&PHONEDEV(xpd).dahdi_registered); ++ atomic_dec(&num_registered_spans); ++ if (xpd->card_present) ++ CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0); ++} ++ ++/*------------------------- Initialization -------------------------*/ ++ ++static void do_cleanup(void) ++{ ++#ifdef CONFIG_PROC_FS ++ if (xpp_proc_toplevel) { ++ DBG(GENERAL, "Removing '%s' from proc\n", PROC_DIR); ++ remove_proc_entry(PROC_DIR, NULL); ++ xpp_proc_toplevel = NULL; ++ } ++#endif ++} ++ ++static int __init xpp_dahdi_init(void) ++{ ++ int ret = 0; ++ void *top = NULL; ++ ++ INFO("MAX_XPDS=%d (%d*%d)\n", MAX_XPDS, MAX_UNIT, MAX_SUBUNIT); ++#ifdef CONFIG_PROC_FS ++ xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL); ++ if (!xpp_proc_toplevel) { ++ ret = -EIO; ++ goto err; ++ } ++ top = xpp_proc_toplevel; ++#endif ++ ret = xbus_core_init(); ++ if (ret) { ++ ERR("xbus_core_init failed (%d)\n", ret); ++ goto err; ++ } ++ ret = xbus_pcm_init(top); ++ if (ret) { ++ ERR("xbus_pcm_init failed (%d)\n", ret); ++ xbus_core_shutdown(); ++ goto err; ++ } ++ return 0; ++err: ++ do_cleanup(); ++ return ret; ++} ++ ++static void __exit xpp_dahdi_cleanup(void) ++{ ++ xbus_pcm_shutdown(); ++ xbus_core_shutdown(); ++ do_cleanup(); ++} ++ ++MODULE_DESCRIPTION("XPP Dahdi Driver"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++ ++module_init(xpp_dahdi_init); ++module_exit(xpp_dahdi_cleanup); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xpp_dahdi.h linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_dahdi.h +--- linux-source-4.19/drivers/dahdi/xpp/xpp_dahdi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_dahdi.h 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,73 @@ ++#ifndef XPP_DAHDI_H ++#define XPP_DAHDI_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++#include "xproto.h" ++ ++void xpd_set_spanname(xpd_t *xpd); ++int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset); ++int xpd_dahdi_postregister(xpd_t *xpd); ++void xpd_dahdi_preunregister(xpd_t *xpd); ++void xpd_dahdi_postunregister(xpd_t *xpd); ++int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ int unit, ++ int subunit, __u8 type); ++xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, ++ size_t privsize, const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ int channels); ++void xpd_free(xpd_t *xpd); ++void xpd_remove(xpd_t *xpd); ++int phonedev_alloc_channels(xpd_t *xpd, int channels); ++void update_xpd_status(xpd_t *xpd, int alarm_flag); ++const char *xpp_echocan_name(const struct dahdi_chan *chan); ++int xpp_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec); ++void hookstate_changed(xpd_t *xpd, int pos, bool good); ++int xpp_open(struct dahdi_chan *chan); ++int xpp_close(struct dahdi_chan *chan); ++int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg); ++int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig); ++int xpp_maint(struct dahdi_span *span, int cmd); ++int xpp_watchdog(struct dahdi_span *span, int cause); ++void xpp_span_assigned(struct dahdi_span *span); ++void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd); ++int total_registered_spans(void); ++void oht_pcm(xpd_t *xpd, int pos, bool pass); ++void mark_offhook(xpd_t *xpd, int pos, bool to_offhook); ++#define IS_OFFHOOK(xpd, pos) IS_SET((xpd)->phonedev.offhook_state, (pos)) ++void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig); ++ ++#ifdef CONFIG_PROC_FS ++#include ++ ++extern struct proc_dir_entry *xpp_proc_toplevel; ++#endif ++ ++#define SPAN_REGISTERED(xpd) (atomic_read(&PHONEDEV(xpd).dahdi_registered) && \ ++ test_bit(DAHDI_FLAGBIT_REGISTERED, &PHONEDEV(xpd).span.flags)) ++ ++#endif /* XPP_DAHDI_H */ +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xpp_debug linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_debug +--- linux-source-4.19/drivers/dahdi/xpp/xpp_debug 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_debug 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,109 @@ ++#! /bin/sh ++# ++# xpp_debug: Turn on/off debugging flags via /sys/module/*/parameters/debug ++# ++ ++modules="xpp xpp_usb xpd_fxs xpd_fxo xpd_bri xpd_pri xpd_echo" ++dbg_names="DEFAULT PCM LEDS SYNC SIGNAL PROC REGS DEVICES COMMANDS" ++ ++usage() { ++ echo 1>&2 "Usage: $0 [module_name] [[-]flags...]" ++ echo 1>&2 " module_name => $modules" ++ echo 1>&2 " flags => NONE $dbg_names ANY" ++ echo 1>&2 "" ++ echo 1>&2 " Example: $0 xpp ANY -PCM -LEDS" ++ echo 1>&2 "" ++} ++ ++sysfs_name() { ++ f='' ++ if [ -f "/sys/module/$1/parameters/debug" ]; then ++ f="/sys/module/$1/parameters/debug" ++ elif [ -f "/sys/module/$1/debug" ]; then ++ f="/sys/module/$1/debug" ++ fi ++ echo "$f" ++} ++ ++sysfs_value() { ++ f=`sysfs_name "$1"` ++ if [ "$f" != "" ]; then ++ cat "$f" ++ fi ++} ++ ++show_debug() { ++ usage ++ for i in $modules ++ do ++ f=`sysfs_name "$i"` ++ if [ -f "$f" ]; then ++ val=`cat $f` ++ j=0 ++ list='' ++ for n in $dbg_names ++ do ++ if [ $(( val & (1 << j) )) -ne 0 ]; then ++ list="$list $n" ++ fi ++ j=$((j+1)) ++ done ++ if [ "$list" = "" ]; then ++ list=' NONE' ++ fi ++ echo "$i $list" ++ fi ++ done ++} ++ ++calc_debug() { ++ val="$1" ++ shift ++ for wanted in $* ++ do ++ j=0 ++ found=0 ++ for n in $dbg_names ++ do ++ if [ "$wanted" = "$n" ]; then ++ : $(( val |= (1 << j) )) ++ found=1 ++ elif [ "$wanted" = -"$n" ]; then ++ : $(( val &= ~(1 << j) )) ++ found=1 ++ elif [ "$wanted" = "ANY" ]; then ++ : $(( val = ~0 )) ++ found=1 ++ elif [ "$wanted" = -"ANY" -o "$wanted" = "NONE" ]; then ++ val=0 ++ found=1 ++ fi ++ j=$((j+1)) ++ done ++ if [ "$found" -eq 0 ]; then ++ echo >&2 "$0: Unknown debug flag '$wanted'" ++ exit 1 ++ fi ++ done ++ echo $val ++} ++ ++if [ "$#" = 0 ]; then ++ show_debug ++ exit 0 ++fi ++ ++module="$1" ++shift ++ ++if ! echo "$modules" | grep -w "$module" > /dev/null; then ++ echo >&2 "$0: Unknown module $module" ++ exit 1 ++fi ++ ++oldval=`sysfs_value "$module"` ++val=`calc_debug "$oldval" $*` ++file=`sysfs_name $module` ++ ++echo "$val" > "$file" ++show_debug +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xpp_usb.c linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_usb.c +--- linux-source-4.19/drivers/dahdi/xpp/xpp_usb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xpp_usb.c 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,1140 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 /* for udelay */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "xpd.h" ++#include "xproto.h" ++#include "xbus-core.h" ++#include "xframe_queue.h" ++#ifdef DEBUG ++#include "card_fxs.h" ++#include "card_fxo.h" ++#endif ++#include "parport_debug.h" ++ ++static const char rcsid[] = "$Id$"; ++ ++/* must be before dahdi_debug.h */ ++static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); ++static DEF_PARM(int, usb1, 0, 0644, "Allow using USB 1.1 interfaces"); ++static DEF_PARM(uint, tx_sluggish, 2000, 0644, "A sluggish transmit (usec)"); ++static DEF_PARM(uint, drop_pcm_after, 6, 0644, ++ "Number of consecutive tx_sluggish to start dropping PCM"); ++static DEF_PARM(uint, sluggish_pcm_keepalive, 50, 0644, ++ "During sluggish -- Keep-alive PCM (1 every #)"); ++ ++#include "dahdi_debug.h" ++ ++#define XUSB_PRINTK(level, xusb, fmt, ...) \ ++ printk(KERN_ ## level "%s-%s: xusb-%d (%s) [%s]: " fmt, #level, \ ++ THIS_MODULE->name, (xusb)->index, xusb->path, \ ++ xusb->serial, ## __VA_ARGS__) ++ ++#define XUSB_DBG(bits, xusb, fmt, ...) \ ++ ((void)((debug & (DBG_ ## bits)) && XUSB_PRINTK(DEBUG, \ ++ xusb, "%s: " fmt, __func__, ## __VA_ARGS__))) ++#define XUSB_ERR(xusb, fmt, ...) \ ++ XUSB_PRINTK(ERR, xusb, fmt, ## __VA_ARGS__) ++#define XUSB_NOTICE(xusb, fmt, ...) \ ++ XUSB_PRINTK(NOTICE, xusb, fmt, ## __VA_ARGS__) ++#define XUSB_INFO(xusb, fmt, ...) \ ++ XUSB_PRINTK(INFO, xusb, fmt, ## __VA_ARGS__) ++ ++/* Get a minor range for your devices from the usb maintainer */ ++#define USB_SKEL_MINOR_BASE 192 ++ ++#ifdef CONFIG_PROC_FS ++#define PROC_USBXPP_SUMMARY "xpp_usb" ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) ++#define usb_alloc_coherent(dev, size, mem_flags, dma) \ ++ usb_buffer_alloc(dev, size, mem_flags, dma) ++#define usb_free_coherent(dev, size, addr, dma) \ ++ usb_buffer_free(dev, size, addr, dma) ++#endif ++ ++#ifdef DEBUG_PCM_TIMING ++static cycles_t stamp_last_pcm_read; ++static cycles_t accumulate_diff; ++#endif ++ ++struct xusb_model_info; ++ ++struct xusb_endpoint { ++ int ep_addr; ++ int max_size; ++ usb_complete_t callback; ++}; ++ ++enum xusb_dir { ++ XUSB_RECV = 0, ++ XUSB_SEND = 1, ++}; ++ ++static __must_check int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe); ++static __must_check int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe); ++static __must_check xframe_t *alloc_xframe(xbus_t *xbus, gfp_t flags); ++static void free_xframe(xbus_t *xbus, xframe_t *frm); ++ ++static struct xbus_ops xusb_ops = { ++ .xframe_send_pcm = xframe_send_pcm, ++ .xframe_send_cmd = xframe_send_cmd, ++ .alloc_xframe = alloc_xframe, ++ .free_xframe = free_xframe, ++}; ++ ++enum { ++ XUSB_N_RX_FRAMES, ++ XUSB_N_TX_FRAMES, ++ XUSB_N_RX_ERRORS, ++ XUSB_N_TX_ERRORS, ++ XUSB_N_RX_DROPS, ++ XUSB_N_TX_DROPS, ++ XUSB_N_RCV_ZERO_LEN, ++}; ++ ++#define XUSB_COUNTER(xusb, counter) ((xusb)->counters[XUSB_N_ ## counter]) ++ ++#define C_(x) [ XUSB_N_ ## x ] = { #x } ++ ++static struct xusb_counters { ++ char *name; ++} xusb_counters[] = { ++ C_(RX_FRAMES), ++ C_(TX_FRAMES), ++ C_(RX_ERRORS), ++ C_(TX_ERRORS), ++ C_(RX_DROPS), ++ C_(TX_DROPS), ++ C_(RCV_ZERO_LEN), ++}; ++ ++#undef C_ ++ ++#define XUSB_COUNTER_MAX ARRAY_SIZE(xusb_counters) ++ ++#define MAX_PENDING_WRITES 100 ++ ++static KMEM_CACHE_T *xusb_cache; ++ ++typedef struct xusb xusb_t; ++ ++/* ++ * A uframe is our low level representation of a frame. ++ * ++ * It contains the metadata for the usb stack (a urb) ++ * and the metadata for the xbus-core (an xframe) ++ * as well as pointing to the data (transfer_buffer, transfer_buffer_length) ++ * directionality (send/receive) and ownership (xusb). ++ */ ++struct uframe { ++ unsigned long uframe_magic; ++#define UFRAME_MAGIC 654321L ++ struct urb urb; ++ xframe_t xframe; ++ size_t transfer_buffer_length; ++ void *transfer_buffer; /* max XFRAME_DATASIZE */ ++ xusb_t *xusb; ++}; ++ ++#define urb_to_uframe(urb) \ ++ container_of(urb, struct uframe, urb) ++#define xframe_to_uframe(xframe) \ ++ container_of(xframe, struct uframe, xframe) ++#define xusb_of(xbus) \ ++ ((xusb_t *)((xbus)->transport.priv)) ++ ++#define USEC_BUCKET 100 /* usec */ ++#define NUM_BUCKETS 15 ++#define BUCKET_START (500/USEC_BUCKET) /* skip uninteresting */ ++ ++/* ++ * USB XPP Bus (a USB Device) ++ */ ++struct xusb { ++ uint xbus_num; ++ struct usb_device *udev; /* save off the usb device pointer */ ++ struct usb_interface *interface; /* the interface for this device */ ++ unsigned char minor; /* the starting minor number for this device */ ++ uint index; ++ char path[XBUS_DESCLEN]; /* a unique path */ ++ ++ struct xusb_model_info *model_info; ++ struct xusb_endpoint endpoints[2]; /* RECV/SEND endpoints */ ++ ++ int present; /* if the device is not disconnected */ ++ atomic_t pending_writes; /* submited but not out yet */ ++ atomic_t pending_reads; /* submited but not in yet */ ++ struct semaphore sem; /* locks this structure */ ++ int counters[XUSB_COUNTER_MAX]; ++ ++ /* metrics */ ++ ktime_t last_tx; ++ unsigned int max_tx_delay; ++ uint usb_tx_delay[NUM_BUCKETS]; ++ uint sluggish_debounce; ++ bool drop_pcm; /* due to sluggishness */ ++ atomic_t usb_sluggish_count; ++ ++ const char *manufacturer; ++ const char *product; ++ const char *serial; ++ const char *interface_name; ++ ++}; ++ ++static DEFINE_SPINLOCK(xusb_lock); ++static xusb_t *xusb_array[MAX_BUSES] = { }; ++ ++static unsigned bus_count; ++ ++/* prevent races between open() and disconnect() */ ++static DEFINE_MUTEX(protect_xusb_devices); ++ ++static void xpp_send_callback(struct urb *urb); ++static void xpp_receive_callback(struct urb *urb); ++static int xusb_probe(struct usb_interface *interface, ++ const struct usb_device_id *id); ++static void xusb_disconnect(struct usb_interface *interface); ++#ifdef CONFIG_PROC_FS ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops xusb_read_proc_ops; ++#else ++static const struct file_operations xusb_read_proc_ops; ++#endif ++#endif ++ ++/*------------------------------------------------------------------*/ ++ ++/* ++ * Updates the urb+xframe metadata from the uframe information. ++ */ ++static void uframe_recompute(struct uframe *uframe, enum xusb_dir dir) ++{ ++ struct urb *urb = &uframe->urb; ++ xusb_t *xusb = uframe->xusb; ++ struct usb_device *udev = xusb->udev; ++ struct xusb_endpoint *xusb_ep = &xusb->endpoints[dir]; ++ unsigned int ep_addr = xusb_ep->ep_addr; ++ usb_complete_t urb_cb = xusb_ep->callback; ++ unsigned int epnum = ep_addr & USB_ENDPOINT_NUMBER_MASK; ++ int pipe = usb_pipein(ep_addr) ++ ? usb_rcvbulkpipe(udev, epnum) ++ : usb_sndbulkpipe(udev, epnum); ++ ++ BUG_ON(uframe->uframe_magic != UFRAME_MAGIC); ++ usb_fill_bulk_urb(urb, udev, pipe, uframe->transfer_buffer, ++ uframe->transfer_buffer_length, urb_cb, uframe); ++ urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP); ++} ++ ++static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) ++{ ++ struct uframe *uframe; ++ xusb_t *xusb; ++ void *p; ++ int size; ++ static int rate_limit; ++ ++ BUG_ON(!xbus); ++ xusb = xusb_of(xbus); ++ BUG_ON(!xusb); ++ if (!xusb->present) { ++ if ((rate_limit++ % 1003) == 0) ++ XUSB_ERR(xusb, ++ "abort allocations during " ++ "device disconnect (%d)\n", ++ rate_limit); ++ return NULL; ++ } ++ size = ++ min(xusb->endpoints[XUSB_SEND].max_size, ++ xusb->endpoints[XUSB_RECV].max_size); ++ uframe = kmem_cache_alloc(xusb_cache, gfp_flags); ++ if (!uframe) { ++ if ((rate_limit++ % 1003) == 0) ++ XUSB_ERR(xusb, "frame allocation failed (%d)\n", ++ rate_limit); ++ return NULL; ++ } ++ usb_init_urb(&uframe->urb); ++ p = usb_alloc_coherent(xusb->udev, size, gfp_flags, ++ &uframe->urb.transfer_dma); ++ if (!p) { ++ if ((rate_limit++ % 1003) == 0) ++ XUSB_ERR(xusb, "buffer allocation failed (%d)\n", ++ rate_limit); ++ kmem_cache_free(xusb_cache, uframe); ++ return NULL; ++ } ++ uframe->uframe_magic = UFRAME_MAGIC; ++ uframe->transfer_buffer_length = size; ++ uframe->transfer_buffer = p; ++ uframe->xusb = xusb; ++ xframe_init(xbus, &uframe->xframe, uframe->transfer_buffer, ++ uframe->transfer_buffer_length, uframe); ++ return &uframe->xframe; ++} ++ ++static void free_xframe(xbus_t *xbus, xframe_t *xframe) ++{ ++ struct uframe *uframe = xframe_to_uframe(xframe); ++ struct urb *urb = &uframe->urb; ++ ++ BUG_ON(xbus->transport.priv != uframe->xusb); ++ //XUSB_INFO(uframe->xusb, "frame_free\n"); ++ usb_free_coherent(urb->dev, uframe->transfer_buffer_length, ++ urb->transfer_buffer, urb->transfer_dma); ++ memset(uframe, 0, sizeof(*uframe)); ++ kmem_cache_free(xusb_cache, uframe); ++} ++ ++/*------------------------------------------------------------------*/ ++ ++/* ++ * Actuall frame sending -- both PCM and commands. ++ */ ++static int do_send_xframe(xbus_t *xbus, xframe_t *xframe) ++{ ++ struct urb *urb; ++ xusb_t *xusb; ++ int ret = 0; ++ struct uframe *uframe; ++ ++ BUG_ON(!xframe); ++ BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); ++ xusb = xusb_of(xbus); ++ BUG_ON(!xusb); ++ if (!xusb->present) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) ++ XUSB_ERR(xusb, ++ "abort do_send_xframe during " ++ "device disconnect (%d)\n", ++ rate_limit); ++ ret = -ENODEV; ++ goto failure; ++ } ++ /* ++ * If something really bad happend, do not overflow the USB stack ++ */ ++ if (atomic_read(&xusb->pending_writes) > MAX_PENDING_WRITES) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 5000) == 0) ++ XUSB_ERR(xusb, ++ "USB device is totaly stuck. " ++ "Dropping packets (#%d).\n", ++ rate_limit); ++ ret = -ENODEV; ++ goto failure; ++ } ++ uframe = xframe->priv; ++ BUG_ON(!uframe); ++ BUG_ON(uframe->uframe_magic != UFRAME_MAGIC); ++ uframe_recompute(uframe, XUSB_SEND); ++ urb = &uframe->urb; ++ BUG_ON(!urb); ++ /* update urb length */ ++ urb->transfer_buffer_length = XFRAME_LEN(xframe); ++ xframe->kt_submitted = ktime_get(); ++ ret = usb_submit_urb(urb, GFP_ATOMIC); ++ if (ret < 0) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1000) == 0) ++ XBUS_ERR(xbus, "%s: usb_submit_urb failed: %d\n", ++ __func__, ret); ++ ret = -EBADF; ++ goto failure; ++ } ++// if (debug) ++// dump_xframe("USB_FRAME_SEND", xbus, xframe, debug); ++ atomic_inc(&xusb->pending_writes); ++ return 0; ++failure: ++ XUSB_COUNTER(xusb, TX_ERRORS)++; ++ FREE_SEND_XFRAME(xbus, xframe); /* return to pool */ ++ return ret; ++} ++ ++/* ++ * PCM wrapper ++ */ ++static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe) ++{ ++ xusb_t *xusb; ++ ++ BUG_ON(!xbus); ++ BUG_ON(!xframe); ++ xusb = xusb_of(xbus); ++ BUG_ON(!xusb); ++ if (xusb->drop_pcm) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1000) == 0) ++ XUSB_ERR(xusb, "Sluggish USB: drop tx-pcm (%d)\n", ++ rate_limit); ++ /* Let trickle of TX-PCM, so Astribank will not reset */ ++ if (sluggish_pcm_keepalive && ++ ((rate_limit % sluggish_pcm_keepalive) != 0)) { ++ XUSB_COUNTER(xusb, TX_DROPS)++; ++ goto err; ++ } ++ } ++ return do_send_xframe(xbus, xframe); ++err: ++ FREE_SEND_XFRAME(xbus, xframe); /* return to pool */ ++ return -EIO; ++} ++ ++/* ++ * commands wrapper ++ */ ++static int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe) ++{ ++ BUG_ON(!xbus); ++ BUG_ON(!xframe); ++ //XBUS_INFO(xbus, "%s:\n", __func__); ++ return do_send_xframe(xbus, xframe); ++} ++ ++/* ++ * get a urb from the receive_pool and submit it on the read endpoint. ++ */ ++static bool xusb_listen(xusb_t *xusb) ++{ ++ xbus_t *xbus = xbus_num(xusb->xbus_num); ++ xframe_t *xframe; ++ struct uframe *uframe; ++ int ret = 0; ++ ++ BUG_ON(!xbus); ++ xframe = ALLOC_RECV_XFRAME(xbus); ++ if (!xframe) { ++ XBUS_ERR(xbus, "Empty receive_pool\n"); ++ goto out; ++ } ++ uframe = xframe_to_uframe(xframe); ++ uframe_recompute(uframe, XUSB_RECV); ++ ret = usb_submit_urb(&uframe->urb, GFP_ATOMIC); ++ if (ret < 0) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1000) == 0) ++ XBUS_ERR(xbus, "%s: usb_submit_urb failed: %d\n", ++ __func__, ret); ++ FREE_RECV_XFRAME(xbus, xframe); ++ goto out; ++ } ++ atomic_inc(&xusb->pending_reads); ++ ret = 1; ++out: ++ return ret; ++} ++ ++/*------------------------- XPP USB Bus Handling -------------------*/ ++ ++enum XUSB_MODELS { ++ MODEL_FPGA_XPD ++}; ++ ++static const struct xusb_model_info { ++ const char *desc; ++ int iface_num; ++ struct xusb_endpoint in; ++ struct xusb_endpoint out; ++} model_table[] = { ++ [MODEL_FPGA_XPD] = { ++ .iface_num = 0, ++ .in = { .ep_addr = 0x86 }, ++ .out = { .ep_addr = 0x02 }, ++ .desc = "FPGA_XPD" ++ }, ++}; ++ ++/* table of devices that work with this driver */ ++static const struct usb_device_id xusb_table[] = { ++/* FPGA_FXS */ {USB_DEVICE(0xE4E4, 0x1132), ++ .driver_info = (kernel_ulong_t)&model_table[MODEL_FPGA_XPD]}, ++/* FPGA_1141 */ {USB_DEVICE(0xE4E4, 0x1142), ++ .driver_info = (kernel_ulong_t)&model_table[MODEL_FPGA_XPD]}, ++/* FPGA_1151 */ {USB_DEVICE(0xE4E4, 0x1152), ++ .driver_info = (kernel_ulong_t)&model_table[MODEL_FPGA_XPD]}, ++/* FPGA_1161 */ {USB_DEVICE(0xE4E4, 0x1162), ++ .driver_info = (kernel_ulong_t)&model_table[MODEL_FPGA_XPD]}, ++/* Terminate */ {} ++}; ++ ++MODULE_DEVICE_TABLE(usb, xusb_table); ++ ++/* ++ * USB specific object needed to register this driver ++ * with the usb subsystem ++ */ ++static struct usb_driver xusb_driver = { ++ .name = "xpp_usb", ++ .probe = xusb_probe, ++ .disconnect = xusb_disconnect, ++ .id_table = xusb_table, ++}; ++ ++/* ++ * File operations needed when we register this driver. ++ * This assumes that this driver NEEDS file operations, ++ * of course, which means that the driver is expected ++ * to have a node in the /dev directory. If the USB ++ * device were for a network interface then the driver ++ * would use "struct net_driver" instead, and a serial ++ * device would use "struct tty_driver". ++ */ ++static const struct file_operations xusb_fops = { ++ /* ++ * The owner field is part of the module-locking ++ * mechanism. The idea is that the kernel knows ++ * which module to increment the use-counter of ++ * BEFORE it calls the device's open() function. ++ * This also means that the kernel can decrement ++ * the use-counter again before calling release() ++ * or should the open() function fail. ++ */ ++ .owner = THIS_MODULE, ++}; ++ ++/* ++ * usb class driver info in order to get a minor number from the usb core, ++ * and to have the device registered with devfs and the driver core ++ */ ++static struct usb_class_driver xusb_class = { ++ .name = "usb/xpp_usb%d", ++ .fops = &xusb_fops, ++ .minor_base = USB_SKEL_MINOR_BASE, ++}; ++ ++/* ++ * Check that an endpoint's wMaxPacketSize attribute is 512. This ++ * indicates that it is a USB2's high speed end point. ++ * ++ * If it is 64, it means we have a USB1 controller. By default we do not ++ * support it and just fail the probe of the device. However if the user ++ * has set usb1=1, we continue and just put a notice. ++ * ++ * Returns true if all OK, false otherwise. ++ */ ++static int check_usb1(struct usb_endpoint_descriptor *endpoint) ++{ ++ const char *msg = ++ (usb_pipein(endpoint->bEndpointAddress)) ? "input" : "output"; ++ ++ if (endpoint->wMaxPacketSize >= sizeof(xpacket_t)) ++ return 1; ++ ++ if (usb1) { ++ NOTICE("USB1 endpoint detected: " ++ "USB %s endpoint 0x%X support only wMaxPacketSize=%d\n", ++ msg, ++ endpoint->bEndpointAddress, ++ endpoint->wMaxPacketSize); ++ return 1; ++ } ++ NOTICE("USB1 endpoint detected: " ++ "Device disabled. To enable: usb1=1, and read docs. " ++ "(%s, endpoint %d, size %d)\n", ++ msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize); ++ return 0; ++} ++ ++/* ++ * set up the endpoint information ++ * check out the endpoints ++ * FIXME: Should be simplified (above 2.6.10) to use ++ * usb_dev->ep_in[0..16] and usb_dev->ep_out[0..16] ++ */ ++static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, ++ struct xusb_model_info *model_info) ++{ ++ struct usb_endpoint_descriptor *endpoint; ++ struct xusb_endpoint *xusb_ep; ++ int ep_addr; ++ int i; ++ ++#define BULK_ENDPOINT(ep) \ ++ (((ep)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == \ ++ USB_ENDPOINT_XFER_BULK) ++ ++ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { ++ endpoint = &iface_desc->endpoint[i].desc; ++ ep_addr = endpoint->bEndpointAddress; ++ ++ if (!BULK_ENDPOINT(endpoint)) { ++ DBG(DEVICES, ++ "endpoint 0x%x is not bulk: mbAttributes=0x%X\n", ++ ep_addr, endpoint->bmAttributes); ++ continue; ++ } ++ if (usb_pipein(ep_addr)) { /* Input */ ++ if (ep_addr == model_info->in.ep_addr) { ++ if (!check_usb1(endpoint)) ++ return 0; ++ xusb_ep = &xusb->endpoints[XUSB_RECV]; ++ xusb_ep->ep_addr = ep_addr; ++ xusb_ep->max_size = endpoint->wMaxPacketSize; ++ xusb_ep->callback = xpp_receive_callback; ++ } ++ } else { /* Output */ ++ if (ep_addr == model_info->out.ep_addr) { ++ if (!check_usb1(endpoint)) ++ return 0; ++ xusb_ep = &xusb->endpoints[XUSB_SEND]; ++ xusb_ep->ep_addr = ep_addr; ++ xusb_ep->max_size = endpoint->wMaxPacketSize; ++ xusb_ep->callback = xpp_send_callback; ++ } ++ } ++ } ++ if (!xusb->endpoints[XUSB_RECV].ep_addr ++ || !xusb->endpoints[XUSB_SEND].ep_addr) { ++ XUSB_ERR(xusb, "Couldn't find bulk-in or bulk-out endpoints\n"); ++ return 0; ++ } ++ DBG(DEVICES, "in=0x%02X out=0x%02X\n", ++ xusb->endpoints[XUSB_RECV].ep_addr, ++ xusb->endpoints[XUSB_SEND].ep_addr); ++ return 1; ++} ++ ++/** ++ * xusb_probe ++ * ++ * Called by the usb core when a new device is connected that it thinks ++ * this driver might be interested in. ++ */ ++static int xusb_probe(struct usb_interface *interface, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *udev = interface_to_usbdev(interface); ++ struct usb_host_interface *iface_desc = ++ usb_altnum_to_altsetting(interface, 0); ++ xusb_t *xusb = NULL; ++ struct xusb_model_info *model_info = ++ (struct xusb_model_info *)id->driver_info; ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *procsummary = NULL; ++#endif ++ xbus_t *xbus = NULL; ++ unsigned long flags; ++ int retval = -ENOMEM; ++ int i; ++ ++ DBG(DEVICES, "New XUSB device MODEL=%s\n", model_info->desc); ++ if (iface_desc->desc.bInterfaceNumber != model_info->iface_num) { ++ DBG(DEVICES, "Skip interface #%d != #%d\n", ++ iface_desc->desc.bInterfaceNumber, model_info->iface_num); ++ return -ENODEV; ++ } ++ mutex_lock(&protect_xusb_devices); ++ if ((retval = usb_reset_device(udev)) < 0) { ++ ERR("usb_reset_device failed: %d\n", retval); ++ goto probe_failed; ++ } ++ if (!model_info) { ++ ERR("Missing endpoint setup for this device %d:%d\n", ++ udev->descriptor.idVendor, udev->descriptor.idProduct); ++ retval = -ENODEV; ++ goto probe_failed; ++ } ++ ++ /* allocate memory for our device state and initialize it */ ++ xusb = KZALLOC(sizeof(xusb_t), GFP_KERNEL); ++ if (xusb == NULL) { ++ ERR("xpp_usb: Unable to allocate new xpp usb bus\n"); ++ retval = -ENOMEM; ++ goto probe_failed; ++ } ++ sema_init(&xusb->sem, 1); ++ atomic_set(&xusb->pending_writes, 0); ++ atomic_set(&xusb->pending_reads, 0); ++ atomic_set(&xusb->usb_sluggish_count, 0); ++ xusb->udev = udev; ++ xusb->interface = interface; ++ xusb->model_info = model_info; ++ ++ if (!set_endpoints(xusb, iface_desc, model_info)) { ++ retval = -ENODEV; ++ goto probe_failed; ++ } ++ xusb->serial = udev->serial; ++ xusb->manufacturer = udev->manufacturer; ++ xusb->product = udev->product; ++ xusb->interface_name = iface_desc->string; ++ INFO("XUSB: %s -- %s -- %s\n", xusb->manufacturer, xusb->product, ++ xusb->interface_name); ++ ++ /* allow device read, write and ioctl */ ++ xusb->present = 1; ++ ++ /* we can register the device now, as it is ready */ ++ usb_set_intfdata(interface, xusb); ++ retval = usb_register_dev(interface, &xusb_class); ++ if (retval) { ++ /* something prevented us from registering this driver */ ++ ERR("Not able to get a minor for this device.\n"); ++ goto probe_failed; ++ } ++ ++ xusb->minor = interface->minor; ++ ++ /* let the user know what node this device is now attached to */ ++ DBG(DEVICES, "USB XPP device now attached to minor %d\n", xusb->minor); ++ xbus = ++ xbus_new(&xusb_ops, ++ min(xusb->endpoints[XUSB_SEND].max_size, ++ xusb->endpoints[XUSB_RECV].max_size), &udev->dev, ++ xusb); ++ if (!xbus) { ++ retval = -ENOMEM; ++ goto probe_failed; ++ } ++ snprintf(xbus->transport.model_string, ++ ARRAY_SIZE(xbus->transport.model_string), "usb:%04x/%04x/%x", ++ udev->descriptor.idVendor, udev->descriptor.idProduct, ++ udev->descriptor.bcdDevice); ++ spin_lock_irqsave(&xusb_lock, flags); ++ for (i = 0; i < MAX_BUSES; i++) { ++ if (xusb_array[i] == NULL) ++ break; ++ } ++ spin_unlock_irqrestore(&xusb_lock, flags); ++ if (i >= MAX_BUSES) { ++ ERR("xpp_usb: Too many XPP USB buses\n"); ++ retval = -ENOMEM; ++ goto probe_failed; ++ } ++ /* May trunacte... ignore */ ++ usb_make_path(udev, xusb->path, XBUS_DESCLEN); ++ snprintf(xbus->connector, XBUS_DESCLEN, "%s", xusb->path); ++ if (xusb->serial && xusb->serial[0]) ++ snprintf(xbus->label, LABEL_SIZE, "usb:%s", xusb->serial); ++ xusb->index = i; ++ xusb_array[i] = xusb; ++ XUSB_DBG(DEVICES, xusb, "GOT XPP USB BUS: %s\n", xbus->connector); ++ ++#ifdef CONFIG_PROC_FS ++ DBG(PROC, ++ "Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n"); ++ procsummary = proc_create_data(PROC_USBXPP_SUMMARY, 0444, ++ xbus->proc_xbus_dir, &xusb_read_proc_ops, ++ xusb); ++ if (!procsummary) { ++ XBUS_ERR(xbus, "Failed to create proc file '%s'\n", ++ PROC_USBXPP_SUMMARY); ++ // FIXME: better error handling ++ retval = -EIO; ++ goto probe_failed; ++ } ++#endif ++ bus_count++; ++ xusb->xbus_num = xbus->num; ++ /* prepare several pending frames for receive side */ ++ for (i = 0; i < 10; i++) ++ xusb_listen(xusb); ++ xbus_connect(xbus); ++ mutex_unlock(&protect_xusb_devices); ++ return retval; ++probe_failed: ++ ERR("Failed to initialize xpp usb bus: %d\n", retval); ++ usb_set_intfdata(interface, NULL); ++ if (xusb) { ++ if (xusb->minor) { /* passed registration phase */ ++ ERR("Calling usb_deregister_dev()\n"); ++ usb_deregister_dev(interface, &xusb_class); ++ } ++ ERR("Removing failed xusb\n"); ++ KZFREE(xusb); ++ } ++ if (xbus) { ++#ifdef CONFIG_PROC_FS ++ if (procsummary) { ++ XBUS_DBG(PROC, xbus, ++ "Remove proc_entry: " PROC_USBXPP_SUMMARY ++ "\n"); ++ remove_proc_entry(PROC_USBXPP_SUMMARY, ++ xbus->proc_xbus_dir); ++ procsummary = NULL; ++ } ++#endif ++ ERR("Calling xbus_disconnect()\n"); ++ xbus_disconnect(xbus); // Blocking until fully deactivated! ++ } ++ mutex_unlock(&protect_xusb_devices); ++ return retval; ++} ++ ++/** ++ * xusb_disconnect ++ * ++ * Called by the usb core when the device is removed from the system. ++ * ++ * This routine guarantees that the driver will not submit any more urbs ++ * by clearing dev->udev. It is also supposed to terminate any currently ++ * active urbs. Unfortunately, usb_bulk_msg(), used in xusb_read(), does ++ * not provide any way to do this. But at least we can cancel an active ++ * write. ++ */ ++static void xusb_disconnect(struct usb_interface *interface) ++{ ++ struct usb_host_interface *iface_desc = ++ usb_altnum_to_altsetting(interface, 0); ++ xusb_t *xusb; ++ xbus_t *xbus; ++ int i; ++ ++ DBG(DEVICES, "CALLED on interface #%d\n", ++ iface_desc->desc.bInterfaceNumber); ++ /* prevent races with open() */ ++ mutex_lock(&protect_xusb_devices); ++ ++ xusb = usb_get_intfdata(interface); ++ usb_set_intfdata(interface, NULL); ++ xusb->present = 0; ++ xbus = xbus_num(xusb->xbus_num); ++ ++ /* find our xusb */ ++ for (i = 0; i < MAX_BUSES; i++) { ++ if (xusb_array[i] == xusb) ++ break; ++ } ++ BUG_ON(i >= MAX_BUSES); ++ xusb_array[i] = NULL; ++ ++#ifdef CONFIG_PROC_FS ++ if (xbus->proc_xbus_dir) { ++ XBUS_DBG(PROC, xbus, ++ "Remove proc_entry: " PROC_USBXPP_SUMMARY "\n"); ++ remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir); ++ } ++#endif ++ xbus_disconnect(xbus); // Blocking until fully deactivated! ++ ++ down(&xusb->sem); ++ ++ /* give back our minor */ ++ usb_deregister_dev(interface, &xusb_class); ++ ++ up(&xusb->sem); ++ DBG(DEVICES, "Semaphore released\n"); ++ XUSB_INFO(xusb, "now disconnected\n"); ++ KZFREE(xusb); ++ ++ mutex_unlock(&protect_xusb_devices); ++} ++ ++static void xpp_send_callback(struct urb *urb) ++{ ++ struct uframe *uframe = urb_to_uframe(urb); ++ xframe_t *xframe = &uframe->xframe; ++ xusb_t *xusb = uframe->xusb; ++ xbus_t *xbus = xbus_num(xusb->xbus_num); ++ ktime_t now; ++ s64 usec; ++ int writes = atomic_read(&xusb->pending_writes); ++ int i; ++ ++ if (!xbus) { ++ XUSB_ERR(xusb, ++ "Sent URB does not belong to a valid xbus...\n"); ++ return; ++ } ++ //flip_parport_bit(6); ++ atomic_dec(&xusb->pending_writes); ++ now = ktime_get(); ++ xusb->last_tx = xframe->kt_submitted; ++ usec = ktime_us_delta(now, xframe->kt_submitted); ++ if (usec < 0) ++ usec = 0; /* System clock jumped */ ++ if (usec > xusb->max_tx_delay) ++ xusb->max_tx_delay = usec; ++ i = usec / USEC_BUCKET; ++ if (i >= NUM_BUCKETS) ++ i = NUM_BUCKETS - 1; ++ xusb->usb_tx_delay[i]++; ++ if (unlikely(usec > tx_sluggish)) { ++ if (xusb->sluggish_debounce++ > drop_pcm_after) { ++ static int rate_limit; ++ ++ /* skip first messages */ ++ if ((rate_limit++ % 1003) == 500) ++ XUSB_NOTICE(xusb, ++ "Sluggish USB. Dropping next PCM frame " ++ "(pending_writes=%d)\n", ++ writes); ++ atomic_inc(&xusb->usb_sluggish_count); ++ xusb->drop_pcm = 1; ++ xusb->sluggish_debounce = 0; ++ } ++ } else { ++ xusb->sluggish_debounce = 0; ++ xusb->drop_pcm = 0; ++ } ++ /* sync/async unlink faults aren't errors */ ++ if (urb->status ++ && !(urb->status == -ENOENT || urb->status == -ECONNRESET)) { ++ static int rate_limit; ++ if ((rate_limit++ % 1000) < 10) { ++ XUSB_ERR(xusb, ++ "nonzero write bulk status received: " ++ "%d (pending_writes=%d)\n", ++ urb->status, writes); ++ dump_xframe("usb-write-error", xbus, xframe, DBG_ANY); ++ } ++ XUSB_COUNTER(xusb, TX_ERRORS)++; ++ } else ++ XUSB_COUNTER(xusb, TX_FRAMES)++; ++ FREE_SEND_XFRAME(xbus, xframe); ++ if (!xusb->present) ++ XUSB_ERR(xusb, "A urb from non-connected device?\n"); ++} ++ ++static void xpp_receive_callback(struct urb *urb) ++{ ++ struct uframe *uframe = urb_to_uframe(urb); ++ xframe_t *xframe = &uframe->xframe; ++ xusb_t *xusb = uframe->xusb; ++ xbus_t *xbus = xbus_num(xusb->xbus_num); ++ size_t size; ++ bool do_resubmit = 1; ++ ktime_t now = ktime_get(); ++ ++ atomic_dec(&xusb->pending_reads); ++ if (!xbus) { ++ XUSB_ERR(xusb, ++ "Received URB does not belong to a valid xbus...\n"); ++ return; ++ } ++ if (!xusb->present) { ++ do_resubmit = 0; ++ goto err; ++ } ++ if (urb->status) { ++ DBG(GENERAL, "nonzero read bulk status received: %d\n", ++ urb->status); ++ XUSB_COUNTER(xusb, RX_ERRORS)++; ++ goto err; ++ } ++ size = urb->actual_length; ++ if (size == 0) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 5003) == 0) ++ XUSB_NOTICE(xusb, "Received a zero length URBs (%d)\n", ++ rate_limit); ++ XUSB_COUNTER(xusb, RCV_ZERO_LEN)++; ++ goto err; ++ } ++ atomic_set(&xframe->frame_len, size); ++ xframe->kt_received = now; ++ ++// if (debug) ++// dump_xframe("USB_FRAME_RECEIVE", xbus, xframe, debug); ++ XUSB_COUNTER(xusb, RX_FRAMES)++; ++ if (xusb->drop_pcm) { ++ /* some protocol analysis */ ++ static int rate_limit; ++ xpacket_t *pack = (xpacket_t *)(xframe->packets); ++ bool is_pcm = XPACKET_IS_PCM(pack); ++ ++ if (is_pcm) { ++ if ((rate_limit++ % 1000) == 0) ++ XUSB_ERR(xusb, ++ "Sluggish USB: drop rx-pcm (%d)\n", ++ rate_limit); ++ /* Let trickle of RX-PCM, so Astribank will not reset */ ++ if (sluggish_pcm_keepalive && ++ ((rate_limit % sluggish_pcm_keepalive) ++ != 0)) { ++ XUSB_COUNTER(xusb, RX_DROPS)++; ++ goto err; ++ } ++ } ++ } ++ /* Send UP */ ++ xbus_receive_xframe(xbus, xframe); ++end: ++ if (do_resubmit) ++ xusb_listen(xusb); ++ return; ++err: ++ FREE_RECV_XFRAME(xbus, xframe); ++ goto end; ++} ++ ++/*------------------------- Initialization -------------------------*/ ++ ++static void xpp_usb_cleanup(void) ++{ ++ if (xusb_cache) { ++ kmem_cache_destroy(xusb_cache); ++ xusb_cache = NULL; ++ } ++} ++ ++static int __init xpp_usb_init(void) ++{ ++ int ret; ++ //xusb_t *xusb; ++ ++ xusb_cache = ++ kmem_cache_create("xusb_cache", sizeof(xframe_t) + XFRAME_DATASIZE, ++ 0, 0, NULL); ++ if (!xusb_cache) { ++ ret = -ENOMEM; ++ goto failure; ++ } ++ ++ /* register this driver with the USB subsystem */ ++ ret = usb_register(&xusb_driver); ++ if (ret) { ++ ERR("usb_register failed. Error number %d\n", ret); ++ goto failure; ++ } ++ return 0; ++failure: ++ xpp_usb_cleanup(); ++ return ret; ++} ++ ++static void __exit xpp_usb_shutdown(void) ++{ ++ DBG(GENERAL, "\n"); ++ /* deregister this driver with the USB subsystem */ ++ usb_deregister(&xusb_driver); ++ xpp_usb_cleanup(); ++} ++ ++#ifdef CONFIG_PROC_FS ++ ++static int xusb_read_proc_show(struct seq_file *sfile, void *data) ++{ ++ unsigned long flags; ++ int i; ++ //unsigned long stamp = jiffies; ++ xusb_t *xusb = sfile->private; ++ uint usb_tx_delay[NUM_BUCKETS]; ++ const int mark_limit = tx_sluggish / USEC_BUCKET; ++ ++ if (!xusb) ++ return 0; ++ ++ // TODO: probably needs a per-xusb lock: ++ spin_lock_irqsave(&xusb_lock, flags); ++ seq_printf(sfile, "Device: %03d/%03d\n", xusb->udev->bus->busnum, ++ xusb->udev->devnum); ++ seq_printf(sfile, "USB: manufacturer=%s\n", xusb->manufacturer); ++ seq_printf(sfile, "USB: product=%s\n", xusb->product); ++ seq_printf(sfile, "USB: serial=%s\n", xusb->serial); ++ seq_printf(sfile, "Minor: %d\nModel Info: %s\n", xusb->minor, ++ xusb->model_info->desc); ++ seq_printf(sfile, ++ "Endpoints:\n" "\tIn: 0x%02X - Size: %d)\n" ++ "\tOut: 0x%02X - Size: %d)\n", ++ xusb->endpoints[XUSB_RECV].ep_addr, ++ xusb->endpoints[XUSB_RECV].max_size, ++ xusb->endpoints[XUSB_SEND].ep_addr, ++ xusb->endpoints[XUSB_SEND].max_size); ++ seq_printf(sfile, "\npending_writes=%d\n", ++ atomic_read(&xusb->pending_writes)); ++ seq_printf(sfile, "pending_reads=%d\n", ++ atomic_read(&xusb->pending_reads)); ++ seq_printf(sfile, "max_tx_delay=%d\n", xusb->max_tx_delay); ++ xusb->max_tx_delay = 0; ++#ifdef DEBUG_PCM_TIMING ++ seq_printf(sfile, ++ "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", ++ stamp_last_pcm_read, accumulate_diff); ++#endif ++ memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay)); ++ seq_printf(sfile, "usb_tx_delay[%dus - %dus]: ", ++ USEC_BUCKET * BUCKET_START, ++ USEC_BUCKET * NUM_BUCKETS); ++ for (i = BUCKET_START; i < NUM_BUCKETS; i++) { ++ seq_printf(sfile, "%6d ", usb_tx_delay[i]); ++ if (i == mark_limit) ++ seq_printf(sfile, "| "); ++ } ++ seq_printf(sfile, "\nSluggish events: %d\n", ++ atomic_read(&xusb->usb_sluggish_count)); ++ seq_printf(sfile, "\nCOUNTERS:\n"); ++ for (i = 0; i < XUSB_COUNTER_MAX; i++) { ++ seq_printf(sfile, "\t%-15s = %d\n", xusb_counters[i].name, ++ xusb->counters[i]); ++ } ++#if 0 ++ seq_printf(sfile, "<-- len=%d\n", len); ++#endif ++ spin_unlock_irqrestore(&xusb_lock, flags); ++ return 0; ++} ++ ++static int xusb_read_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, xusb_read_proc_show, PDE_DATA(inode)); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) ++static const struct proc_ops xusb_read_proc_ops = { ++ .proc_open = xusb_read_proc_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release, ++}; ++#else ++static const struct file_operations xusb_read_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = xusb_read_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++ ++#endif ++ ++MODULE_DESCRIPTION("XPP USB Transport Driver"); ++MODULE_AUTHOR("Oron Peled "); ++MODULE_LICENSE("GPL"); ++ ++module_init(xpp_usb_init); ++module_exit(xpp_usb_shutdown); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xproto.c linux-source-4.19-dahdi/drivers/dahdi/xpp/xproto.c +--- linux-source-4.19/drivers/dahdi/xpp/xproto.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xproto.c 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,545 @@ ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xpd.h" ++#include "xproto.h" ++#include "xpp_dahdi.h" ++#include "xbus-core.h" ++#include "dahdi_debug.h" ++#include ++#include ++ ++static const char rcsid[] = "$Id$"; ++ ++extern int debug; ++ ++static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE]; ++ ++#if MAX_UNIT*MAX_SUBUNIT > MAX_XPDS ++#error MAX_XPDS is too small ++#endif ++ ++bool valid_xpd_addr(const struct xpd_addr *addr) ++{ ++ return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) ++ && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0); ++} ++EXPORT_SYMBOL(valid_xpd_addr); ++ ++/*------ General Protocol Management ----------------------------*/ ++ ++const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, ++ __u8 opcode) ++{ ++ const xproto_entry_t *xe; ++ ++ //DBG(GENERAL, "\n"); ++ xe = &table->entries[opcode]; ++ return (xe->handler != NULL) ? xe : NULL; ++} ++EXPORT_SYMBOL(xproto_card_entry); ++ ++const xproto_entry_t *xproto_global_entry(__u8 opcode) ++{ ++ const xproto_entry_t *xe; ++ ++ xe = xproto_card_entry(&PROTO_TABLE(GLOBAL), opcode); ++ //DBG(GENERAL, "opcode=0x%X xe=%p\n", opcode, xe); ++ return xe; ++} ++EXPORT_SYMBOL(xproto_global_entry); ++ ++xproto_handler_t xproto_global_handler(__u8 opcode) ++{ ++ return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode); ++} ++ ++static const xproto_table_t *xproto_table(xpd_type_t cardtype) ++{ ++ if (cardtype >= XPD_TYPE_NOMODULE) ++ return NULL; ++ return xprotocol_tables[cardtype]; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) || \ ++ LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++#define MODULE_REFCOUNT_FORMAT "%s refcount was %d\n" ++#else ++#define MODULE_REFCOUNT_FORMAT "%s refcount was %lu\n" ++#endif ++ ++const xproto_table_t *xproto_get(xpd_type_t cardtype) ++{ ++ const xproto_table_t *xtable; ++ ++ if (cardtype >= XPD_TYPE_NOMODULE) ++ return NULL; ++ xtable = xprotocol_tables[cardtype]; ++ if (!xtable) { /* Try to load the relevant module */ ++ int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype); ++ if (ret != 0) { ++ NOTICE("%s: Failed to load module for type=%d. " ++ "exit status=%d.\n", ++ __func__, cardtype, ret); ++ /* Drop through: we may be lucky... */ ++ } ++ xtable = xprotocol_tables[cardtype]; ++ } ++ if (xtable) { ++ BUG_ON(!xtable->owner); ++#ifdef CONFIG_MODULE_UNLOAD ++ DBG(GENERAL, MODULE_REFCOUNT_FORMAT, xtable->name, ++ module_refcount(xtable->owner)); ++#endif ++ if (!try_module_get(xtable->owner)) { ++ ERR("%s: try_module_get for %s failed.\n", __func__, ++ xtable->name); ++ return NULL; ++ } ++ } ++ return xtable; ++} ++ ++void xproto_put(const xproto_table_t *xtable) ++{ ++ BUG_ON(!xtable); ++#ifdef CONFIG_MODULE_UNLOAD ++ DBG(GENERAL, MODULE_REFCOUNT_FORMAT, xtable->name, ++ module_refcount(xtable->owner)); ++ BUG_ON(module_refcount(xtable->owner) <= 0); ++#endif ++ module_put(xtable->owner); ++} ++ ++xproto_handler_t xproto_card_handler(const xproto_table_t *table, ++ __u8 opcode) ++{ ++ const xproto_entry_t *xe; ++ ++ //DBG(GENERAL, "\n"); ++ xe = xproto_card_entry(table, opcode); ++ return xe->handler; ++} ++ ++void notify_bad_xpd(const char *funcname, xbus_t *xbus, ++ const struct xpd_addr addr, const char *msg) ++{ ++ XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n", funcname, ++ addr.unit, addr.subunit, msg); ++} ++EXPORT_SYMBOL(notify_bad_xpd); ++ ++static int packet_process(xbus_t *xbus, xpacket_t *pack) ++{ ++ __u8 op; ++ const xproto_entry_t *xe; ++ xproto_handler_t handler; ++ xproto_table_t *table; ++ xpd_t *xpd; ++ int ret = -EPROTO; ++ ++ BUG_ON(!pack); ++ if (!valid_xpd_addr(&XPACKET_ADDR(pack))) { ++ if (printk_ratelimit()) { ++ XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n", ++ __func__, XPACKET_ADDR_UNIT(pack), ++ XPACKET_ADDR_SUBUNIT(pack)); ++ dump_packet("packet_process -- bad address", pack, ++ debug); ++ } ++ goto out; ++ } ++ op = XPACKET_OP(pack); ++ xpd = ++ xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), ++ XPACKET_ADDR_SUBUNIT(pack)); ++ /* XPD may be NULL (e.g: during bus polling */ ++ xe = xproto_global_entry(op); ++ /*-------- Validations -----------*/ ++ if (!xe) { ++ const xproto_table_t *xtable; ++ ++ if (!xpd) { ++ if (printk_ratelimit()) { ++ XBUS_NOTICE(xbus, ++ "%s: from %d%d opcode=0x%02X: " ++ "no such global command.\n", ++ __func__, XPACKET_ADDR_UNIT(pack), ++ XPACKET_ADDR_SUBUNIT(pack), op); ++ dump_packet ++ ("packet_process -- no such global command", ++ pack, 1); ++ } ++ goto out; ++ } ++ xtable = xproto_table(xpd->xpd_type); ++ if (!xtable) { ++ if (printk_ratelimit()) ++ XPD_ERR(xpd, ++ "%s: no protocol table (xpd_type=%d)\n", ++ __func__, xpd->xpd_type); ++ goto out; ++ } ++ xe = xproto_card_entry(xtable, op); ++ if (!xe) { ++ if (printk_ratelimit()) { ++ XPD_NOTICE(xpd, ++ "%s: bad command (xpd_type=%d,opcode=0x%x)\n", ++ __func__, xpd->xpd_type, op); ++ dump_packet("packet_process -- bad command", ++ pack, 1); ++ } ++ goto out; ++ } ++ } ++ table = xe->table; ++ BUG_ON(!table); ++ if (!table->packet_is_valid(pack)) { ++ if (printk_ratelimit()) { ++ ERR("xpp: %s: wrong size %d for opcode=0x%02X\n", ++ __func__, XPACKET_LEN(pack), op); ++ dump_packet("packet_process -- wrong size", pack, ++ debug); ++ } ++ goto out; ++ } ++ ret = 0; /* All well */ ++ handler = xe->handler; ++ BUG_ON(!handler); ++ XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack); ++ handler(xbus, xpd, xe, pack); ++out: ++ return ret; ++} ++ ++static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe) ++{ ++ __u8 *xframe_end; ++ xpacket_t *pack; ++ __u8 *p; ++ int len; ++ int ret; ++ ++ if (debug & DBG_COMMANDS) ++ dump_xframe("RX-CMD", xbus, xframe, DBG_ANY); ++ p = xframe->packets; ++ xframe_end = p + XFRAME_LEN(xframe); ++ do { ++ pack = (xpacket_t *)p; ++ len = XPACKET_LEN(pack); ++ /* Sanity checks */ ++ if (unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL, PCM_READ))) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) { ++ XBUS_DBG(GENERAL, xbus, ++ "A PCM packet within a Non-PCM xframe\n"); ++ dump_xframe("In Non-PCM xframe", ++ xbus, xframe, debug); ++ } ++ ret = -EPROTO; ++ goto out; ++ } ++ p += len; ++ if (p > xframe_end || len < RPACKET_HEADERSIZE) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) { ++ XBUS_NOTICE(xbus, "Invalid packet length %d\n", ++ len); ++ dump_xframe("BAD LENGTH", xbus, xframe, debug); ++ } ++ ret = -EPROTO; ++ goto out; ++ } ++ ret = packet_process(xbus, pack); ++ if (unlikely(ret < 0)) ++ break; ++ } while (p < xframe_end); ++out: ++ FREE_RECV_XFRAME(xbus, xframe); ++ return ret; ++} ++ ++int xframe_receive(xbus_t *xbus, xframe_t *xframe) ++{ ++ int ret = 0; ++ ktime_t kt_received; ++ s64 usec; ++ ++ if (XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) { ++ static int rate_limit; ++ ++ if ((rate_limit++ % 1003) == 0) { ++ XBUS_NOTICE(xbus, "short xframe\n"); ++ dump_xframe("short xframe", xbus, xframe, debug); ++ } ++ FREE_RECV_XFRAME(xbus, xframe); ++ return -EPROTO; ++ } ++ if (!XBUS_FLAGS(xbus, CONNECTED)) { ++ XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n"); ++ return -ENODEV; ++ } ++ kt_received = xframe->kt_received; ++ /* ++ * We want to check that xframes do not mix PCM and other commands ++ */ ++ if (XPACKET_IS_PCM((xpacket_t *)xframe->packets)) { ++ if (!XBUS_IS(xbus, READY)) ++ FREE_RECV_XFRAME(xbus, xframe); ++ else ++ xframe_receive_pcm(xbus, xframe); ++ } else { ++ XBUS_COUNTER(xbus, RX_CMD)++; ++ ret = xframe_receive_cmd(xbus, xframe); ++ } ++ /* Calculate total processing time */ ++ usec = ktime_us_delta(ktime_get(), kt_received); ++ if (usec > xbus->max_rx_process) ++ xbus->max_rx_process = usec; ++ return ret; ++} ++EXPORT_SYMBOL(xframe_receive); ++ ++#define VERBOSE_DEBUG 1 ++#define ERR_REPORT_LIMIT 20 ++ ++void dump_packet(const char *msg, const xpacket_t *packet, bool debug) ++{ ++ __u8 op = XPACKET_OP(packet); ++ __u8 *addr = (__u8 *)&XPACKET_ADDR(packet); ++ ++ if (!debug) ++ return; ++ printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d", msg, ++ XPACKET_ADDR_UNIT(packet), XPACKET_ADDR_SUBUNIT(packet), ++ (XPACKET_ADDR_SYNC(packet)) ? '+' : ' ', *addr, op, ++ XPACKET_LEN(packet)); ++#if VERBOSE_DEBUG ++ { ++ int i; ++ __u8 *p = (__u8 *)packet; ++ ++ printk(" BYTES: "); ++ for (i = 0; i < XPACKET_LEN(packet); i++) { ++ static int limiter; ++ ++ if (i >= sizeof(xpacket_t)) { ++ if (limiter < ERR_REPORT_LIMIT) { ++ ERR("%s: length overflow " ++ "i=%d > sizeof(xpacket_t)=%lu\n", ++ __func__, i + 1, ++ (long)sizeof(xpacket_t)); ++ } else if (limiter == ERR_REPORT_LIMIT) { ++ ERR("%s: error packet #%d... " ++ "squelsh reports.\n", ++ __func__, limiter); ++ } ++ limiter++; ++ break; ++ } ++ if (debug) ++ printk("%02X ", p[i]); ++ } ++ } ++#endif ++ printk("\n"); ++} ++EXPORT_SYMBOL(dump_packet); ++ ++void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, ++ __u8 unit, xportno_t port, const reg_cmd_t *regcmd) ++{ ++ char action; ++ char modifier; ++ char port_buf[MAX_PROC_WRITE]; ++ char reg_buf[MAX_PROC_WRITE]; ++ char data_buf[MAX_PROC_WRITE]; ++ ++ /* The size byte is not included */ ++ if (regcmd->h.bytes > sizeof(*regcmd) - 1) { ++ PORT_NOTICE(xbus, unit, port, ++ "%s: %s: Too long: regcmd->bytes = %d\n", __func__, ++ msg, regcmd->h.bytes); ++ return; ++ } ++ if (regcmd->h.bytes == REG_CMD_SIZE(RAM)) { ++ snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum, ++ (REG_FIELD_RAM(regcmd, all_ports_broadcast)) ? "*" : ""); ++ if (REG_FIELD_RAM(regcmd, read_request)) { ++ action = 'R'; ++ } else { ++ action = 'W'; ++ } ++ PORT_DBG(REGS, xbus, unit, port, ++ "%s: %s %cR %02X %02X %02X %02X %02X %02X\n", ++ msg, port_buf, action, ++ REG_FIELD_RAM(regcmd, addr_low), ++ REG_FIELD_RAM(regcmd, addr_high), ++ REG_FIELD_RAM(regcmd, data_0), ++ REG_FIELD_RAM(regcmd, data_1), ++ REG_FIELD_RAM(regcmd, data_2), ++ REG_FIELD_RAM(regcmd, data_3)); ++ return; ++ } ++ if (regcmd->h.is_multibyte) { ++ char buf[MAX_PROC_WRITE + 1]; ++ int i; ++ int n = 0; ++ size_t len = regcmd->h.bytes; ++ const __u8 *p = REG_XDATA(regcmd); ++ ++ buf[0] = '\0'; ++ for (i = 0; i < len && n < MAX_PROC_WRITE; i++) ++ n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ", ++ p[i]); ++ PORT_DBG(REGS, xbus, unit, port, ++ "UNIT-%d PORT-%d: Multibyte(eoframe=%d) " ++ "%s[0..%zd]: %s%s\n", ++ unit, port, regcmd->h.eoframe, msg, len - 1, buf, ++ (n >= MAX_PROC_WRITE) ? "..." : ""); ++ return; ++ } ++ /* The size byte is not included */ ++ if (regcmd->h.bytes != REG_CMD_SIZE(REG)) { ++ PORT_NOTICE(xbus, unit, port, ++ "%s: %s: Wrong size: regcmd->bytes = %d\n", ++ __func__, msg, regcmd->h.bytes); ++ return; ++ } ++ snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum, ++ (REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : ""); ++ action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W'; ++ modifier = 'D'; ++ if (REG_FIELD(regcmd, do_subreg)) { ++ snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X", ++ REG_FIELD(regcmd, regnum), REG_FIELD(regcmd, subreg)); ++ modifier = 'S'; ++ } else { ++ snprintf(reg_buf, MAX_PROC_WRITE, "%02X", ++ REG_FIELD(regcmd, regnum)); ++ } ++ if (REG_FIELD(regcmd, read_request)) { ++ data_buf[0] = '\0'; ++ } else if (REG_FIELD(regcmd, do_datah)) { ++ snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X", ++ REG_FIELD(regcmd, data_low), REG_FIELD(regcmd, ++ data_high)); ++ modifier = 'I'; ++ } else { ++ snprintf(data_buf, MAX_PROC_WRITE, "%02X", ++ REG_FIELD(regcmd, data_low)); ++ } ++ PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n", msg, port_buf, ++ action, modifier, reg_buf, data_buf); ++} ++EXPORT_SYMBOL(dump_reg_cmd); ++ ++const char *xproto_name(xpd_type_t xpd_type) ++{ ++ const xproto_table_t *proto_table; ++ ++ BUG_ON(xpd_type >= XPD_TYPE_NOMODULE); ++ proto_table = xprotocol_tables[xpd_type]; ++ if (!proto_table) ++ return NULL; ++ return proto_table->name; ++} ++EXPORT_SYMBOL(xproto_name); ++ ++#define CHECK_XOP(xops, f) \ ++ if (!(xops)->f) { \ ++ ERR("%s: missing xmethod %s [%s (%d)]\n", \ ++ __func__, #f, name, type); \ ++ return -EINVAL; \ ++ } ++ ++#define CHECK_PHONEOP(phoneops, f) \ ++ if (!(phoneops)->f) { \ ++ ERR("%s: missing phone method %s [%s (%d)]\n", \ ++ __func__, #f, name, type); \ ++ return -EINVAL; \ ++ } ++ ++int xproto_register(const xproto_table_t *proto_table) ++{ ++ int type; ++ const char *name; ++ const struct xops *xops; ++ const struct phoneops *phoneops; ++ ++ BUG_ON(!proto_table); ++ type = proto_table->type; ++ name = proto_table->name; ++ if (type >= XPD_TYPE_NOMODULE) { ++ NOTICE("%s: Bad xproto type %d\n", __func__, type); ++ return -EINVAL; ++ } ++ DBG(GENERAL, "%s (%d)\n", name, type); ++ if (xprotocol_tables[type]) ++ NOTICE("%s: overriding registration of %s (%d)\n", __func__, ++ name, type); ++ xops = proto_table->xops; ++ CHECK_XOP(xops, card_new); ++ CHECK_XOP(xops, card_init); ++ CHECK_XOP(xops, card_remove); ++ CHECK_XOP(xops, card_tick); ++ CHECK_XOP(xops, card_register_reply); ++ ++ phoneops = proto_table->phoneops; ++ if (phoneops) { ++ CHECK_PHONEOP(phoneops, card_pcm_recompute); ++ CHECK_PHONEOP(phoneops, card_pcm_fromspan); ++ CHECK_PHONEOP(phoneops, card_pcm_tospan); ++ CHECK_PHONEOP(phoneops, echocancel_timeslot); ++ CHECK_PHONEOP(phoneops, echocancel_setmask); ++ CHECK_PHONEOP(phoneops, card_dahdi_preregistration); ++ CHECK_PHONEOP(phoneops, card_dahdi_postregistration); ++ /* optional method -- call after testing: */ ++ /*CHECK_PHONEOP(phoneops, card_ioctl); */ ++ } ++ ++ xprotocol_tables[type] = proto_table; ++ return 0; ++} ++EXPORT_SYMBOL(xproto_register); ++ ++void xproto_unregister(const xproto_table_t *proto_table) ++{ ++ int type; ++ const char *name; ++ ++ BUG_ON(!proto_table); ++ type = proto_table->type; ++ name = proto_table->name; ++ DBG(GENERAL, "%s (%d)\n", name, type); ++ if (type >= XPD_TYPE_NOMODULE) { ++ NOTICE("%s: Bad xproto type %s (%d)\n", __func__, name, type); ++ return; ++ } ++ if (!xprotocol_tables[type]) ++ NOTICE("%s: xproto type %s (%d) is already unregistered\n", ++ __func__, name, type); ++ xprotocol_tables[type] = NULL; ++} ++EXPORT_SYMBOL(xproto_unregister); +diff -Nru linux-source-4.19/drivers/dahdi/xpp/xproto.h linux-source-4.19-dahdi/drivers/dahdi/xpp/xproto.h +--- linux-source-4.19/drivers/dahdi/xpp/xproto.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/drivers/dahdi/xpp/xproto.h 2020-10-28 00:17:08.679192322 +0100 +@@ -0,0 +1,369 @@ ++#ifndef XPROTO_H ++#define XPROTO_H ++/* ++ * Written by Oron Peled ++ * Copyright (C) 2004-2006, Xorcom ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 "xdefs.h" ++ ++#ifdef __KERNEL__ ++#include ++#include ++#include ++ ++/* ++ * This must match the firmware protocol version ++ */ ++#define XPP_PROTOCOL_VERSION 30 ++ ++struct unit_descriptor; ++ ++struct xpd_addr { ++ uint8_t subunit:SUBUNIT_BITS; ++ uint8_t reserved:1; ++ uint8_t unit:UNIT_BITS; ++ uint8_t sync_master:1; ++} PACKED; ++ ++#define MKADDR(p, u, s) do { \ ++ (p)->unit = (u); \ ++ (p)->subunit = (s); \ ++ (p)->sync_master = 0; \ ++ } while (0) ++ ++struct xpacket_header { ++ uint16_t packet_len:10; ++ uint16_t reserved:1; ++ uint16_t is_pcm:1; ++ uint16_t pcmslot:4; ++ uint8_t opcode; ++ struct xpd_addr addr; ++} PACKED; ++ ++#define XPACKET_OP(p) ((p)->head.opcode) ++#define XPACKET_LEN(p) ((p)->head.packet_len) ++#define XPACKET_IS_PCM(p) ((p)->head.is_pcm) ++#define XPACKET_PCMSLOT(p) ((p)->head.pcmslot) ++#define XPACKET_RESERVED(p) ((p)->head.reserved) ++#define XPACKET_ADDR(p) ((p)->head.addr) ++#define XPACKET_ADDR_UNIT(p) (XPACKET_ADDR(p).unit) ++#define XPACKET_ADDR_SUBUNIT(p) (XPACKET_ADDR(p).subunit) ++#define XPACKET_ADDR_SYNC(p) (XPACKET_ADDR(p).sync_master) ++#define XPACKET_ADDR_RESERVED(p) (XPACKET_ADDR(p).reserved) ++ ++#define PROTO_TABLE(n) n ## _protocol_table ++ ++/* ++ * The LSB of the type number signifies: ++ * 0 - TO_PSTN ++ * 1 - TO_PHONE ++ */ ++#define XPD_TYPE_FXS 1 // TO_PHONE ++#define XPD_TYPE_FXO 2 // TO_PSTN ++#define XPD_TYPE_BRI 3 // TO_PSTN/TO_PHONE (from hardware) ++#define XPD_TYPE_PRI 4 // TO_PSTN/TO_PHONE (runtime) ++#define XPD_TYPE_ECHO 5 // Octasic echo canceller ++#define XPD_TYPE_NOMODULE 7 ++ ++typedef __u8 xpd_type_t; ++ ++#define XPD_TYPE_PREFIX "xpd-type-" ++ ++#define MODULE_ALIAS_XPD(type) \ ++ MODULE_ALIAS(XPD_TYPE_PREFIX __stringify(type)) ++ ++#define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */ ++ ++bool valid_xpd_addr(const struct xpd_addr *addr); ++ ++#define XPROTO_NAME(card, op) card ## _ ## op ++#define XPROTO_HANDLER(card, op) XPROTO_NAME(card, op ## _handler) ++#define XPROTO_CALLER(card, op) XPROTO_NAME(card, op ## _send) ++ ++#define HANDLER_DEF(card, op) \ ++ static int XPROTO_HANDLER(card, op) ( \ ++ xbus_t *xbus, \ ++ xpd_t *xpd, \ ++ const xproto_entry_t *cmd, \ ++ xpacket_t *pack) ++ ++#define CALL_PROTO(card, op, ...) XPROTO_CALLER(card, op)(__VA_ARGS__) ++ ++#define DECLARE_CMD(card, op, ...) \ ++ int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__) ++ ++#define HOSTCMD(card, op, ...) \ ++ DECLARE_CMD(card, op, ## __VA_ARGS__) ++ ++#define RPACKET_NAME(card, op) XPROTO_NAME(RPACKET_ ## card, op) ++#define RPACKET_TYPE(card, op) struct RPACKET_NAME(card, op) ++ ++#define DEF_RPACKET_DATA(card, op, ...) \ ++ RPACKET_TYPE(card, op) { \ ++ struct xpacket_header head; \ ++ __VA_ARGS__ \ ++ } PACKED ++#define RPACKET_HEADERSIZE sizeof(struct xpacket_header) ++#define RPACKET_FIELD(p, card, op, field) \ ++ (((RPACKET_TYPE(card, op) *)(p))->field) ++#define RPACKET_SIZE(card, op) sizeof(RPACKET_TYPE(card, op)) ++ ++#define XENTRY(prototab, module, op) \ ++ [ XPROTO_NAME(module, op) ] = { \ ++ .handler = XPROTO_HANDLER(module, op), \ ++ .name = #op, \ ++ .table = &PROTO_TABLE(prototab) \ ++ } ++ ++#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \ ++ do { \ ++ XPACKET_OP(p) = XPROTO_NAME(card, op); \ ++ XPACKET_LEN(p) = RPACKET_SIZE(card, op); \ ++ XPACKET_IS_PCM(p) = (pcm); \ ++ XPACKET_PCMSLOT(p) = (pcmslot); \ ++ XPACKET_RESERVED(p) = 0; \ ++ XPACKET_ADDR_UNIT(p) = XBUS_UNIT(to); \ ++ XPACKET_ADDR_SUBUNIT(p) = XBUS_SUBUNIT(to); \ ++ XPACKET_ADDR_SYNC(p) = 0; \ ++ XPACKET_ADDR_RESERVED(p) = 0; \ ++ } while (0) ++ ++#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \ ++ do { \ ++ int pack_len = RPACKET_SIZE(card, op); \ ++ \ ++ if (!XBUS_FLAGS(xbus, CONNECTED)) \ ++ return -ENODEV; \ ++ (frm) = ALLOC_SEND_XFRAME(xbus); \ ++ if (!(frm)) \ ++ return -ENOMEM; \ ++ (p) = xframe_next_packet(frm, pack_len); \ ++ if (!(p)) \ ++ return -ENOMEM; \ ++ XPACKET_INIT(p, card, op, to, 0, 0); \ ++ (frm)->usec_towait = 0; \ ++ } while (0) ++ ++#endif ++ ++/*----------------- register handling --------------------------------*/ ++ ++#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */ ++ ++struct reg_cmd_header { ++ __u8 bytes:3; /* Length (for Multibyte) */ ++ __u8 eoframe:1; /* For BRI -- end of frame */ ++ __u8 portnum:3; /* For port specific registers */ ++ __u8 is_multibyte:1; ++} PACKED; ++ ++struct reg_cmd_REG { ++ __u8 reserved:3; ++ __u8 do_expander:1; ++ __u8 do_datah:1; ++ __u8 do_subreg:1; ++ __u8 read_request:1; ++ __u8 all_ports_broadcast:1; ++ __u8 regnum; ++ __u8 subreg; ++ __u8 data_low; ++ __u8 data_high; ++} PACKED; ++ ++struct reg_cmd_RAM { ++ __u8 reserved:4; ++ __u8 do_datah:1; ++ __u8 do_subreg:1; ++ __u8 read_request:1; ++ __u8 all_ports_broadcast:1; ++ __u8 addr_low; ++ __u8 addr_high; ++ __u8 data_0; ++ __u8 data_1; ++ __u8 data_2; ++ __u8 data_3; ++} PACKED; ++ ++typedef struct reg_cmd { ++ struct reg_cmd_header h; ++ union { ++ struct reg_cmd_REG r; ++ /* For Write-Multibyte commands in BRI */ ++ struct { ++ __u8 xdata[MULTIBYTE_MAX_LEN]; ++ } PACKED d; ++ struct reg_cmd_RAM m; ++ } PACKED alt; ++} PACKED reg_cmd_t; ++ ++/* Shortcut access macros */ ++#define REG_CMD_SIZE(variant) (sizeof(struct reg_cmd_ ## variant)) ++#define REG_FIELD(regptr, member) ((regptr)->alt.r.member) ++#define REG_XDATA(regptr) ((regptr)->alt.d.xdata) ++#define REG_FIELD_RAM(regptr, member) ((regptr)->alt.m.member) ++ ++#ifdef __KERNEL__ ++ ++#define XFRAME_CMD_LEN(variant) \ ++ ( \ ++ sizeof(struct xpacket_header) + \ ++ sizeof(struct reg_cmd_header) + \ ++ sizeof(struct reg_cmd_ ## variant) \ ++ ) ++ ++#define XFRAME_NEW_REG_CMD(frm, p, xbus, card, variant, to) \ ++ do { \ ++ int pack_len = XFRAME_CMD_LEN(variant); \ ++ \ ++ if (!XBUS_FLAGS(xbus, CONNECTED)) \ ++ return -ENODEV; \ ++ (frm) = ALLOC_SEND_XFRAME(xbus); \ ++ if (!(frm)) \ ++ return -ENOMEM; \ ++ (p) = xframe_next_packet(frm, pack_len); \ ++ if (!(p)) \ ++ return -ENOMEM; \ ++ XPACKET_INIT(p, card, REGISTER_REQUEST, to, 0, 0); \ ++ XPACKET_LEN(p) = pack_len; \ ++ (frm)->usec_towait = 0; \ ++ } while (0) ++ ++/*----------------- protocol tables ----------------------------------*/ ++ ++typedef struct xproto_entry xproto_entry_t; ++typedef struct xproto_table xproto_table_t; ++ ++typedef int (*xproto_handler_t) (xbus_t *xbus, xpd_t *xpd, ++ const xproto_entry_t *cmd, xpacket_t *pack); ++ ++const xproto_table_t *xproto_get(xpd_type_t cardtype); ++void xproto_put(const xproto_table_t *xtable); ++const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, ++ __u8 opcode); ++xproto_handler_t xproto_card_handler(const xproto_table_t *table, ++ __u8 opcode); ++ ++const xproto_entry_t *xproto_global_entry(__u8 opcode); ++xproto_handler_t xproto_global_handler(__u8 opcode); ++ ++/* ++ * XMETHOD() resolve to method pointer (NULL for optional methods) ++ * CALL_XMETHOD() calls the method, passing mandatory arguments ++ */ ++#define XMETHOD(name, xpd) ((xpd)->xops->name) ++#define CALL_XMETHOD(name, xpd, ...) \ ++ (XMETHOD(name, (xpd))((xpd)->xbus, (xpd), ## __VA_ARGS__)) ++ ++/* ++ * PHONE_METHOD() resolve to method pointer (NULL for optional methods) ++ * CALL_PHONE_METHOD() calls the method, passing mandatory arguments ++ */ ++#define PHONE_METHOD(name, xpd) (PHONEDEV(xpd).phoneops->name) ++#define CALL_PHONE_METHOD(name, xpd, ...) \ ++ (PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__)) ++ ++struct phoneops { ++ void (*card_pcm_recompute) (xpd_t *xpd, xpp_line_t pcm_mask); ++ void (*card_pcm_fromspan) (xpd_t *xpd, xpacket_t *pack); ++ void (*card_pcm_tospan) (xpd_t *xpd, xpacket_t *pack); ++ int (*echocancel_timeslot) (xpd_t *xpd, int pos); ++ int (*echocancel_setmask) (xpd_t *xpd, xpp_line_t ec_mask); ++ int (*card_timing_priority) (xpd_t *xpd); ++ int (*card_dahdi_preregistration) (xpd_t *xpd, bool on); ++ int (*card_dahdi_postregistration) (xpd_t *xpd, bool on); ++ int (*card_hooksig) (xpd_t *xpd, int pos, enum dahdi_txsig txsig); ++ int (*card_ioctl) (xpd_t *xpd, int pos, unsigned int cmd, ++ unsigned long arg); ++ int (*card_open) (xpd_t *xpd, lineno_t pos); ++ int (*card_close) (xpd_t *xpd, lineno_t pos); ++ int (*card_state) (xpd_t *xpd, bool on); ++ int (*span_assigned) (xpd_t *xpd); ++}; ++ ++struct xops { ++ xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit, ++ const xproto_table_t *proto_table, ++ const struct unit_descriptor *unit_descriptor, ++ bool to_phone); ++ int (*card_init) (xbus_t *xbus, xpd_t *xpd); ++ int (*card_remove) (xbus_t *xbus, xpd_t *xpd); ++ int (*card_tick) (xbus_t *xbus, xpd_t *xpd); ++ int (*card_register_reply) (xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg); ++}; ++ ++struct xproto_entry { ++ xproto_handler_t handler; ++ const char *name; ++ xproto_table_t *table; ++}; ++ ++struct xproto_table { ++ struct module *owner; ++ xproto_entry_t entries[256]; /* Indexed by opcode */ ++ const struct xops *xops; /* Card level operations */ ++ const struct phoneops *phoneops; /* DAHDI operations */ ++ const struct echoops *echoops; /* Echo Canceller operations */ ++ xpd_type_t type; ++ __u8 ports_per_subunit; ++ const char *name; ++ bool (*packet_is_valid) (xpacket_t *pack); ++ void (*packet_dump) (const char *msg, xpacket_t *pack); ++}; ++ ++#include "card_global.h" ++#include "card_fxs.h" ++#include "card_fxo.h" ++#include "card_bri.h" ++#include "card_pri.h" ++ ++#define MEMBER(card, op) RPACKET_TYPE(card, op) RPACKET_NAME(card, op) ++ ++struct xpacket { ++ struct xpacket_header head; ++ union { ++ MEMBER(GLOBAL, NULL_REPLY); ++ MEMBER(GLOBAL, PCM_WRITE); ++ MEMBER(GLOBAL, PCM_READ); ++ MEMBER(GLOBAL, SYNC_REPLY); ++ MEMBER(GLOBAL, ERROR_CODE); ++ ++ MEMBER(FXS, SIG_CHANGED); ++ MEMBER(FXO, SIG_CHANGED); ++ ++ __u8 data[0]; ++ }; ++ /* Last byte is chksum */ ++} PACKED; ++ ++void dump_packet(const char *msg, const xpacket_t *packet, bool debug); ++void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, ++ __u8 unit, xportno_t port, const reg_cmd_t *regcmd); ++int xframe_receive(xbus_t *xbus, xframe_t *xframe); ++void notify_bad_xpd(const char *funcname, xbus_t *xbus, ++ const struct xpd_addr addr, const char *msg); ++int xproto_register(const xproto_table_t *proto_table); ++void xproto_unregister(const xproto_table_t *proto_table); ++const xproto_entry_t *xproto_global_entry(__u8 opcode); ++const char *xproto_name(xpd_type_t xpd_type); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* XPROTO_H */ +diff -Nru linux-source-4.19/include/linux/dahdi/Kbuild linux-source-4.19-dahdi/include/linux/dahdi/Kbuild +--- linux-source-4.19/include/linux/dahdi/Kbuild 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/include/linux/dahdi/Kbuild 2020-10-28 00:17:08.663192245 +0100 +@@ -0,0 +1,4 @@ ++header-y += kernel.h ++header-y += user.h ++header-y += wctdm_user.h ++header-y += version.h +diff -Nru linux-source-4.19/include/linux/dahdi/dahdi_config.h linux-source-4.19-dahdi/include/linux/dahdi/dahdi_config.h +--- linux-source-4.19/include/linux/dahdi/dahdi_config.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/include/linux/dahdi/dahdi_config.h 2020-10-28 00:17:08.663192245 +0100 +@@ -0,0 +1,201 @@ ++/* ++ * DAHDI configuration options ++ * ++ */ ++ ++/* ++ * 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 _DAHDI_CONFIG_H ++#define _DAHDI_CONFIG_H ++ ++#ifdef __KERNEL__ ++#include ++#endif ++ ++/* DAHDI compile time options */ ++ ++/* These default tone lengths are in units of milliseconds. */ ++#define DAHDI_CONFIG_DEFAULT_DTMF_LENGTH 100 ++#define DAHDI_CONFIG_DEFAULT_MFR1_LENGTH 68 ++#define DAHDI_CONFIG_DEFAULT_MFR2_LENGTH 100 ++#define DAHDI_CONFIG_PAUSE_LENGTH 500 ++ ++/* ++ * Uncomment if you have a European phone, or any other phone with a ++ * short flash time. ++ * This will stop the flash being mis-detected as a pulse dial "1" on ++ * phones with short flashes ++ */ ++/* #define SHORT_FLASH_TIME */ ++ ++/* ++ * Uncomment to disable calibration tests ++ * (not generally recommended) ++ */ ++/* #define NO_CALIBRATION */ ++ ++/* ++ * Boost ring voltage (Higher ring voltage, takes more power) ++ * Note: this only affects the wcfxsusb and wcusb drivers; all other ++ * drivers have a 'boostringer' module parameter. ++ */ ++/* #define BOOST_RINGER */ ++ ++/* ++ * Define CONFIG_CALC_XLAW if you have a small number of channels and/or ++ * a small level 2 cache, to optimize for few channels ++ * ++ */ ++/* #define CONFIG_CALC_XLAW */ ++ ++/* ++ * Define if you want MMX optimizations in DAHDI ++ * ++ * Note: CONFIG_DAHDI_MMX is generally incompatible with AMD ++ * processors and can cause system instability! ++ * ++ */ ++/* #define CONFIG_DAHDI_MMX */ ++ ++/* We now use the linux kernel config to detect which options to use */ ++/* You can still override them below */ ++#if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE) ++#define DAHDI_HDLC_TYPE_TRANS ++#define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT ++#endif ++ ++/* ++ * Uncomment CONFIG_DAHDI_NET to enable SyncPPP, CiscoHDLC, and Frame Relay ++ * support. ++ */ ++#define CONFIG_DAHDI_NET ++ ++/* ++ * Uncomment for Generic PPP support (i.e. DAHDIRAS) ++ */ ++ ++#if defined(CONFIG_PPP) || defined(CONFIG_PPP_MODULE) ++/* #define CONFIG_DAHDI_PPP */ ++#endif ++ ++/* ++ * Uncomment to enable "watchdog" to monitor if interfaces ++ * stop taking interrupts or otherwise misbehave ++ */ ++/* #define CONFIG_DAHDI_WATCHDOG */ ++ ++/* ++ * Uncomment the following to include extra debugging output. ++ */ ++/* #define CONFIG_DAHDI_DEBUG */ ++ ++/* ++ * Uncomment for Non-standard FXS groundstart start state (A=Low, B=Low) ++ * particularly for CAC channel bank groundstart FXO ports. ++ */ ++/* #define CONFIG_CAC_GROUNDSTART */ ++ ++/* ++ * Define CONFIG_DAHDI_CORE_TIMER if you would like dahdi to always provide a ++ * timing source regardless of which spans / drivers are configured. ++ */ ++#define CONFIG_DAHDI_CORE_TIMER ++ ++/* ++ * Define CONFIG_DAHDI_NO_ECHOCAN_DISABLE to prevent the 2100Hz tone detector ++ * from disabling any installed software echocan. ++ * ++ */ ++/* #define CONFIG_DAHDI_NO_ECHOCAN_DISABLE */ ++ ++/* ++ * Define if you would like to allow software echocans to process the tx audio ++ * in addition to the rx audio. Used for things like DC removal. ++ * ++ */ ++/* #define CONFIG_DAHDI_ECHOCAN_PROCESS_TX */ ++ ++/* ++ * Uncomment if you happen have an early TDM400P Rev H which ++ * sometimes forgets its PCI ID to have wcfxs match essentially all ++ * subvendor ID's ++ */ ++/* #define TDM_REVH_MATCHALL */ ++ ++/* ++ * Uncomment the following if you want to support E&M trunks being ++ * able to "flash" after going off-hook (dont ask why, just nod :-) ). ++ * ++ * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! ++ * ++ */ ++/* #define EMFLASH */ ++ ++/* ++ * Uncomment the following if you want to support E&M trunks being ++ * able to recognize Dial Pulse digits. This can validly be enabled ++ * so that either Dial Pulse or DTMF/MF tones will be recognized, but ++ * the drawback is that the ONHOOK will take an extra {rxwinktime} ++ * to be recognized. ++ * ++ * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! ++ * ++ */ ++/* #define EMPULSE */ ++ ++/* ++ * Comment out the following if you dont want events to indicate the ++ * beginning of an incoming ring. Most non-Asterisk applications will ++ * want this commented out. ++ */ ++#define RINGBEGIN ++ ++/* ++ * Uncomment the following if you need to support FXS Flash events. ++ * Most applications will want this commented out. ++ */ ++/* #define FXSFLASH */ ++ ++/* ++ * Enable sync_tick() calls. Allows low-level drivers to synchronize ++ * their internal clocks to the DAHDI master clock. ++ */ ++#define DAHDI_SYNC_TICK ++ ++/* ++ * Skip processing PCM if low-level driver won't use it anyway ++ */ ++/* #define OPTIMIZE_CHANMUTE */ ++ ++ ++/* ++ * Pass DAHDI_AUDIOMODE to channel driver as well ++ */ ++/* #define DAHDI_AUDIO_NOTIFY */ ++ ++/* ++ * Creates an interface for mirroring the raw channel data out to a pseudo-chan ++ */ ++/* #define CONFIG_DAHDI_MIRROR */ ++ ++/* ++ * Adds support for conference links. There are some non-Asterisk users of this ++ * functionality. ++ */ ++/* #define CONFIG_DAHDI_CONFLINK */ ++ ++#define CONFIG_DAHDI_DYNAMIC ++#define CONFIG_DAHDI_DYNAMIC_LOC ++ ++#endif +diff -Nru linux-source-4.19/include/linux/dahdi/fasthdlc.h linux-source-4.19-dahdi/include/linux/dahdi/fasthdlc.h +--- linux-source-4.19/include/linux/dahdi/fasthdlc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/include/linux/dahdi/fasthdlc.h 2020-10-28 00:17:08.663192245 +0100 +@@ -0,0 +1,533 @@ ++/* ++ * Mark's Mythical Table-based raw HDLC implementation ++ * ++ * This is designed to be a very fast, but memory efficient ++ * implementation of standard HDLC protocol. ++ * ++ * This table based HDLC technology is PATENT PENDING, but will always be ++ * remain freely distributable under the terms of the GPL version 2. ++ * ++ * For non-GPL licensing, please contact Mark Spencer at ++ * the below e-mail address. ++ * ++ * Copyright (C) 2001-2008, Digium, Inc. ++ * ++ * Written by Mark Spencer ++ * ++ */ ++ ++/* ++ * 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 _FASTHDLC_H ++#define _FASTHDLC_H ++ ++enum fasthdlc_mode { ++ FASTHDLC_MODE_64 = 0, ++ FASTHDLC_MODE_56, ++ FASTHDLC_MODE_16, ++}; ++ ++struct fasthdlc_state { ++ int state; /* What state we are in */ ++ unsigned int data; /* Our current data queue */ ++ int bits; /* Number of bits in our data queue */ ++ int ones; /* Number of ones */ ++ enum fasthdlc_mode mode; ++ unsigned int minbits; ++}; ++ ++#ifdef FAST_HDLC_NEED_TABLES ++#define RETURN_COMPLETE_FLAG (0x1000) ++#define RETURN_DISCARD_FLAG (0x2000) ++#define RETURN_EMPTY_FLAG (0x4000) ++ ++/* Unlike most HDLC implementations, we define only two states, ++ when we are in a valid frame, and when we are searching for ++ a frame header */ ++ ++#define FRAME_SEARCH 0 ++#define PROCESS_FRAME 1 ++ ++/* ++ ++ HDLC Search State table -- Look for a frame header. The return value ++ of this table is as follows: ++ ++ |---8---|---7---|---6---|---5---|---4---|---3---|---2---|---1---| ++ | Z E R O E S | Next | Bits Consumed | ++ |-------|-------|-------|-------|-------|-------|-------|-------| ++ ++ The indexes for this table are the state (0 or 1) and the next 8 ++ bits of the stream. ++ ++ Note that this table is only used for state 0 and 1. ++ ++ The user should discard the top "bits consumed" bits of data before ++ the next call. "Next state" represents the actual next state for ++ decoding. ++ ++*/ ++static unsigned char hdlc_search[256]; ++ ++/* ++ HDLC Data Table ++ ++ The indexes to this table are the number of one's we've seen so far (0-5) and ++ the next 10 bits of input (which is enough to guarantee us that we ++ will retrieve at least one byte of data (or frame or whatever). ++ ++ The format for the return value is: ++ ++ Bits 15: Status (1=Valid Data, 0=Control Frame (see bits 7-0 for type)) ++ Bits 14-12: Number of ones in a row, so far ++ Bits 11-8: The number of bits consumed (0-10) ++ Bits 7-0: The return data (if appropriate) ++ ++ The next state is simply bit #15 ++ ++*/ ++ ++#define CONTROL_COMPLETE 1 ++#define CONTROL_ABORT 2 ++ ++#define STATUS_MASK (1 << 15) ++#define STATUS_VALID (1 << 15) ++#define STATUS_CONTROL (0 << 15) ++#define STATE_MASK (1 << 15) ++#define ONES_MASK (7 << 12) ++#define DATA_MASK (0xff) ++ ++static unsigned short hdlc_frame[6][1024]; ++ ++static unsigned int minbits[2] = { 8, 10 }; ++ ++/* ++ Last, but not least, we have the encoder table. It takes ++ as its indices the number of ones so far and a byte of data ++ and returns an int composed of the following fields: ++ ++ Bots 31-22: Actual Data ++ Bits 21-16: Unused ++ Bits 15-8: Number of ones ++ Bits 3-0: Number of bits of output (13-4) to use ++ ++ Of course we could optimize by reducing to two tables, but I don't ++ really think it's worth the trouble at this point. ++ */ ++ ++static unsigned int hdlc_encode[6][256]; ++ ++static inline char hdlc_search_precalc(unsigned char c) ++{ ++ int x, p=0; ++ /* Look for a flag. If this isn't a flag, ++ line us up for the next possible shot at ++ a flag */ ++ ++ /* If it's a flag, we go to state 1, and have ++ consumed 8 bits */ ++ if (c == 0x7e) ++ return 0x10 | 8; ++ ++ /* If it's an abort, we stay in the same state ++ and have consumed 8 bits */ ++ if (c == 0x7f) ++ return 0x00 | 8; ++ ++ /* If it's all 1's, we state in the same state and ++ have consumed 8 bits */ ++ if (c == 0xff) ++ return 0x00 | 8; ++ ++ /* If we get here, we must have at least one zero in us ++ but we're not the flag. So, start at the end (LSB) and ++ work our way to the top (MSB) looking for a zero. The ++ position of that 0 is most optimistic start of a real ++ frame header */ ++ x=1; ++ p=7; ++ while(p && (c & x)) { ++ x <<= 1; ++ p--; ++ } ++ return p; ++} ++ ++#ifdef DEBUG_PRECALC ++static inline void hdlc_search_print(char c, char r) ++{ ++ int x=0x80; ++ while(x) { ++ printf("%s", c & x ? "1" : "0"); ++ x >>= 1; ++ } ++ printf(" => State %d, Consume %d\n", (r & 0x10) >> 4, r & 0xf); ++} ++#endif ++ ++#define HFP(status, ones, bits, data) \ ++ ((status) | ((ones) << 12) | ((bits) << 8) | (data)) ++ ++static inline unsigned int hdlc_frame_precalc(unsigned char x, unsigned short c) ++{ ++ /* Assume we have seen 'x' one's so far, and have read the ++ bottom 10 bytes of c (MSB first). Now, we HAVE to have ++ a byte of data or a frame or something. We are assumed ++ to be at the beginning of a byte of data or something */ ++ unsigned char ones = x; ++ unsigned char data=0; ++ int bits=0; ++ int consumed=0; ++ while(bits < 8) { ++ data >>=1; ++ consumed++; ++ if (ones == 5) { ++ /* We've seen five ones */ ++ if (c & 0x0200) { ++ /* Another one -- Some sort of signal frame */ ++ if ((!(c & 0x0100)) && (bits == 6)) { ++ /* This is a frame terminator (10) */ ++ return HFP(0, ++ 0, 8, CONTROL_COMPLETE); ++ } else { ++ /* Yuck! It's something else... ++ Abort this entire frame, and ++ start looking for a good frame */ ++ return HFP(0, ++ 0, consumed+1, CONTROL_ABORT); ++ } ++ } else { ++ /* It's an inserted zero, just skip it */ ++ ones = 0; ++ data <<= 1; ++ } ++ } else { ++ /* Add it to our bit list, LSB to ++ MSB */ ++ if (c & 0x0200) { ++ data |= 0x80; ++ ones++; ++ } else ++ ones=0; ++ bits++; ++ } ++ c <<= 1; ++ } ++ /* Consume the extra 0 now rather than later. */ ++ if (ones == 5) { ++ ones = 0; ++ consumed++; ++ } ++ return HFP(STATUS_VALID, ones, consumed, data); ++} ++ ++#ifdef DEBUG_PRECALC ++ ++static inline void hdlc_frame_print(unsigned char x, unsigned short c, unsigned int res) ++{ ++ int z=0x0200; ++ char *status[] = { ++ "Control", ++ "Valid", ++ }; ++ printf("%d one's then ", x); ++ while(z) { ++ printf("%s", c & z ? "1" : "0"); ++ z >>= 1; ++ } ++ printf(" => Status %s, ", res & STATUS_MASK ? "1" : "0"); ++ printf("Consumed: %d, ", (res & 0x0f00) >> 8); ++ printf("Status: %s, ", status[(res & STATUS_MASK) >> 15]); ++ printf("Ones: %d, ", (res & ONES_MASK) >> 12); ++ printf("Data: %02x\n", res & 0xff); ++ ++} ++ ++#endif ++ ++static inline unsigned int hdlc_encode_precalc(int x, unsigned char y) ++{ ++ int bits=0; ++ int ones=x; ++ unsigned short data=0; ++ int z; ++ for (z=0;z<8;z++) { ++ /* Zero-stuff if needed */ ++ if (ones == 5) { ++ /* Stuff a zero */ ++ data <<= 1; ++ ones=0; ++ bits++; ++ } ++ if (y & 0x01) { ++ /* There's a one */ ++ data <<= 1; ++ data |= 0x1; ++ ones++; ++ bits++; ++ } else { ++ data <<= 1; ++ ones = 0; ++ bits++; ++ } ++ y >>= 1; ++ } ++ /* Special case -- Stuff the zero at the end if appropriate */ ++ if (ones == 5) { ++ /* Stuff a zero */ ++ data <<= 1; ++ ones=0; ++ bits++; ++ } ++ data <<= (10-bits); ++ return (data << 22) | (ones << 8) | (bits); ++} ++ ++#ifdef DEBUG_PRECALC ++static inline void hdlc_encode_print(int x, unsigned char y, unsigned int val) ++{ ++ unsigned int z; ++ unsigned short c; ++ printf("%d ones, %02x (", x, y); ++ z = 0x80; ++ while(z) { ++ printf("%s", y & z ? "1" : "0"); ++ z >>= 1; ++ } ++ printf(") encoded as "); ++ z = 1 << 31; ++ for (x=0;x<(val & 0xf);x++) { ++ printf("%s", val & z ? "1" : "0"); ++ z >>= 1; ++ } ++ printf(" with %d ones now, %d bits in len\n", (val & 0xf00) >> 8, val & 0xf); ++ ++ ++} ++#endif ++ ++static inline void fasthdlc_precalc(void) ++{ ++ int x; ++ int y; ++ /* First the easy part -- the searching */ ++ for (x=0;x<256;x++) { ++ hdlc_search[x] = hdlc_search_precalc(x); ++#ifdef DEBUG_PRECALC ++ hdlc_search_print(x, hdlc_search[x]); ++#endif ++ } ++ /* Now the hard part -- the frame tables */ ++ for (x=0;x<6;x++) { ++ /* Given the # of preceeding ones, process the next ++ byte of input (up to 10 actual bits) */ ++ for (y=0;y<1024;y++) { ++ hdlc_frame[x][y] = hdlc_frame_precalc(x, y); ++#ifdef DEBUG_PRECALC ++ hdlc_frame_print(x, y, hdlc_frame[x][y]); ++#endif ++ } ++ } ++ /* Now another not-so-hard part, the encoding table */ ++ for (x=0;x<6;x++) { ++ for (y=0;y<256;y++) { ++ hdlc_encode[x][y] = hdlc_encode_precalc(x,y); ++#ifdef DEBUG_PRECALC ++ hdlc_encode_print(x,y,hdlc_encode[x][y]); ++#endif ++ } ++ } ++} ++ ++ ++static inline void fasthdlc_init(struct fasthdlc_state *h, enum fasthdlc_mode mode) ++{ ++ /* Initializes all states appropriately */ ++ h->mode = mode; ++ h->state = 0; ++ h->bits = 0; ++ h->data = 0; ++ h->ones = 0; ++ ++ switch (mode) { ++ case FASTHDLC_MODE_64: ++ h->minbits = 8; ++ break; ++ case FASTHDLC_MODE_56: ++ h->minbits = 7; ++ break; ++ case FASTHDLC_MODE_16: ++ h->minbits = 2; ++ break; ++ } ++ ++} ++ ++static inline int fasthdlc_tx_load_nocheck(struct fasthdlc_state *h, unsigned char c) ++{ ++ unsigned int res; ++ res = hdlc_encode[h->ones][c]; ++ h->ones = (res & 0xf00) >> 8; ++ h->data |= (res & 0xffc00000) >> h->bits; ++ h->bits += (res & 0xf); ++ return 0; ++} ++ ++static inline int fasthdlc_tx_load(struct fasthdlc_state *h, unsigned char c) ++{ ++ /* Gotta have at least 10 bits left */ ++ if (h->bits > 22) ++ return -1; ++ return fasthdlc_tx_load_nocheck(h, c); ++} ++ ++static inline int fasthdlc_tx_frame_nocheck(struct fasthdlc_state *h) ++{ ++ h->ones = 0; ++ h->data |= ( 0x7e000000 >> h->bits); ++ h->bits += 8; ++ return 0; ++} ++ ++static inline int fasthdlc_tx_frame(struct fasthdlc_state *h) ++{ ++ if (h->bits > 24) ++ return -1; ++ return fasthdlc_tx_frame_nocheck(h); ++} ++ ++static inline int fasthdlc_tx_need_data(struct fasthdlc_state *h) ++{ ++ if (h->mode == FASTHDLC_MODE_56) { ++ if (h->bits < 7) ++ return 1; ++ } else if (h->mode == FASTHDLC_MODE_16) { ++ if (h->bits < 2) ++ return 1; ++ } else { ++ if (h->bits < 8) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static inline int fasthdlc_tx_run_nocheck(struct fasthdlc_state *h) ++{ ++ unsigned char b; ++ if (h->mode == FASTHDLC_MODE_16) { ++ b = h->data >> 30; ++ h->bits -= 2; ++ h->data <<= 2; ++ ++ return (b & 3) << 6; ++ } else if (h->mode == FASTHDLC_MODE_56) { ++ b = h->data >> 25; ++ h->bits -= 7; ++ h->data <<= 7; ++ ++ return ((b & 0x7f) << 1) | 1; ++ } else { ++ b = h->data >> 24; ++ h->bits -= 8; ++ h->data <<= 8; ++ ++ return b; ++ } ++ ++} ++ ++static inline int fasthdlc_tx_run(struct fasthdlc_state *h) ++{ ++ if (h->bits < h->minbits) ++ return -1; ++ return fasthdlc_tx_run_nocheck(h); ++} ++ ++static inline int fasthdlc_rx_load_nocheck(struct fasthdlc_state *h, unsigned char b) ++{ ++ if (h->mode == FASTHDLC_MODE_16) { ++ h->data |= (b >> 6) << (30-h->bits); ++ h->bits += 2; ++ } else if (h->mode == FASTHDLC_MODE_56) { ++ h->data |= (b >> 1) << (25-h->bits); ++ h->bits += 7; ++ } else { ++ /* Put the new byte in the data stream */ ++ h->data |= b << (24-h->bits); ++ h->bits += 8; ++ } ++ return 0; ++} ++ ++static inline int fasthdlc_rx_load(struct fasthdlc_state *h, unsigned char b) ++{ ++ /* Make sure we have enough space */ ++ if (h->bits > 24) ++ return -1; ++ return fasthdlc_rx_load_nocheck(h, b); ++} ++ ++/* ++ Returns a data character if available, logical OR'd with ++ zero or more of RETURN_COMPLETE_FLAG, RETURN_DISCARD_FLAG, ++ and RETURN_EMPTY_FLAG, signifying a complete frame, a ++ discarded frame, or there is nothing to return. ++ */ ++ ++static inline int fasthdlc_rx_run(struct fasthdlc_state *h) ++{ ++ unsigned short next; ++ int retval=RETURN_EMPTY_FLAG; ++ while ((h->bits >= minbits[h->state]) && (retval == RETURN_EMPTY_FLAG)) { ++ /* Run until we can no longer be assured that we will ++ have enough bits to continue */ ++ switch(h->state) { ++ case FRAME_SEARCH: ++ /* Look for an HDLC frame, keying from ++ the top byte. */ ++ next = hdlc_search[h->data >> 24]; ++ h->bits -= next & 0x0f; ++ h->data <<= next & 0x0f; ++ h->state = next >> 4; ++ h->ones = 0; ++ break; ++ case PROCESS_FRAME: ++ /* Process as much as the next ten bits */ ++ next = hdlc_frame[h->ones][h->data >> 22]; ++ h->bits -= ((next & 0x0f00) >> 8); ++ h->data <<= ((next & 0x0f00) >> 8); ++ h->state = (next & STATE_MASK) >> 15; ++ h->ones = (next & ONES_MASK) >> 12; ++ switch(next & STATUS_MASK) { ++ case STATUS_CONTROL: ++ if (next & CONTROL_COMPLETE) { ++ /* A complete, valid frame received */ ++ retval = (RETURN_COMPLETE_FLAG); ++ /* Stay in this state */ ++ h->state = 1; ++ } else { ++ /* An abort (either out of sync of explicit) */ ++ retval = (RETURN_DISCARD_FLAG); ++ } ++ break; ++ case STATUS_VALID: ++ retval = (next & DATA_MASK); ++ } ++ } ++ } ++ return retval; ++} ++#endif /* FAST_HDLC_NEED_TABLES */ ++#endif +diff -Nru linux-source-4.19/include/linux/dahdi/kernel.h linux-source-4.19-dahdi/include/linux/dahdi/kernel.h +--- linux-source-4.19/include/linux/dahdi/kernel.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/include/linux/dahdi/kernel.h 2020-10-28 00:17:08.663192245 +0100 +@@ -0,0 +1,1641 @@ ++/* ++ * DAHDI Telephony Interface ++ * ++ * Written by Mark Spencer ++ * Based on previous works, designs, and architectures conceived and ++ * written by Jim Dixon . ++ * ++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony. ++ * Copyright (C) 2001 - 2012 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. ++ */ ++ ++/*! ++ * \file ++ * \brief DAHDI kernel interface definitions ++ */ ++ ++#ifndef _DAHDI_KERNEL_H ++#define _DAHDI_KERNEL_H ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_DAHDI_NET ++#include ++#endif ++ ++#ifdef CONFIG_DAHDI_PPP ++#include ++#include ++#include ++#endif ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_PCI ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) ++#include ++#else ++#include ++#endif ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#define HAVE_NET_DEVICE_OPS ++#endif ++ ++/* __dev* were removed in 3.8. They still have effect in 2.6.18. */ ++#ifndef __devinit ++# define __devinit ++# define __devinitdata ++# define __devexit ++# define __devexit_p(x) x ++#endif ++ ++/*! Default chunk size for conferences and such -- static right now, might make ++ variable sometime. 8 samples = 1 ms = most frequent service interval possible ++ for a USB device */ ++#define DAHDI_CHUNKSIZE 8 ++#define DAHDI_MIN_CHUNKSIZE DAHDI_CHUNKSIZE ++#define DAHDI_DEFAULT_CHUNKSIZE DAHDI_CHUNKSIZE ++#define DAHDI_MAX_CHUNKSIZE DAHDI_CHUNKSIZE ++#define DAHDI_CB_SIZE (1 << 3) ++ ++/* DAHDI operates at 8Khz by default */ ++#define DAHDI_MS_TO_SAMPLES(ms) ((ms) * 8) ++ ++#define DAHDI_MSECS_PER_CHUNK (DAHDI_CHUNKSIZE/DAHDI_MS_TO_SAMPLES(1)) ++ ++#define RING_DEBOUNCE_TIME 2000 /*!< 2000 ms ring debounce time */ ++ ++typedef struct ++{ ++ int32_t gain; ++ int32_t a1; ++ int32_t a2; ++ int32_t b1; ++ int32_t b2; ++ ++ int32_t z1; ++ int32_t z2; ++} biquad2_state_t; ++ ++typedef struct ++{ ++ biquad2_state_t notch; ++ int notch_level; ++ int channel_level; ++ int tone_present; ++ int tone_cycle_duration; ++ int good_cycles; ++ int hit; ++} echo_can_disable_detector_state_t; ++ ++struct sf_detect_state { ++ long x1; ++ long x2; ++ long y1; ++ long y2; ++ long e1; ++ long e2; ++ int samps; ++ int lastdetect; ++}; ++ ++struct dahdi_tone_state { ++ int v1_1; ++ int v2_1; ++ int v3_1; ++ int v1_2; ++ int v2_2; ++ int v3_2; ++ int modulate; ++}; ++ ++/*! \brief Conference queue structure */ ++struct confq { ++ u_char buffer[DAHDI_CHUNKSIZE * DAHDI_CB_SIZE]; ++ u_char *buf[DAHDI_CB_SIZE]; ++ int inbuf; ++ int outbuf; ++}; ++ ++struct dahdi_chan; ++struct dahdi_echocan_state; ++ ++/*! Features a DAHDI echo canceler (software or hardware) can provide to the DAHDI core. */ ++struct dahdi_echocan_features { ++ ++ /*! Able to detect CED tone (2100 Hz with phase reversals) in the transmit direction. ++ * If the echocan can detect this tone, it may report it it as an event (see ++ * the events.CED_tx_detected field of dahdi_echocan_state), and if it will automatically ++ * disable itself or its non-linear processor, then the NLP_automatic feature flag should also ++ * be set so that the DAHDI core doesn't bother trying to do so. ++ */ ++ u32 CED_tx_detect:1; ++ ++ /*! Able to detect CED tone (2100 Hz with phase reversals) in the receive direction. ++ * If the echocan can detect this tone, it may report it it as an event (see ++ * the events.CED_rx_detected field of dahdi_echocan_state), and if it will automatically ++ * disable itself or its non-linear processor, then the NLP_automatic flag feature should also ++ * be set so that the DAHDI core doesn't bother trying to do so. ++ */ ++ u32 CED_rx_detect:1; ++ ++ /*! Able to detect CNG tone (1100 Hz) in the transmit direction. */ ++ u32 CNG_tx_detect:1; ++ ++ /*! Able to detect CNG tone (1100 Hz) in the receive direction. */ ++ u32 CNG_rx_detect:1; ++ ++ /*! If the echocan's NLP can be enabled and disabled without requiring destruction ++ * and recreation of the state structure, this feature flag should be set and the ++ * echocan_NLP_toggle field of the dahdi_echocan_ops structure should be filled with a ++ * pointer to the function to perform that operation. ++ */ ++ u32 NLP_toggle:1; ++ ++ /*! If the echocan will automatically disable itself (or even just its NLP) based on ++ * detection of a CED tone in either direction, this feature flag should be set (along ++ * with the tone detection feature flags). ++ */ ++ u32 NLP_automatic:1; ++}; ++ ++/*! Operations (methods) that can be performed on a DAHDI echo canceler instance (state ++ * structure) after it has been created, by either a software or hardware echo canceller. ++ * The echo canceler must populate the owner field of the dahdi_echocan_state structure ++ * with a pointer to the relevant operations structure for that instance. ++ */ ++struct dahdi_echocan_ops { ++ ++ /*! \brief Free an echocan state structure. ++ * \param[in,out] ec Pointer to the state structure to free. ++ * ++ * \return Nothing. ++ */ ++ void (*echocan_free)(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); ++ ++ /*! \brief Process an array of audio samples through the echocan. ++ * \param[in,out] ec Pointer to the state structure. ++ * \param[in,out] isig The receive direction data (will be modified). ++ * \param[in] iref The transmit direction data. ++ * \param[in] size The number of elements in the isig and iref arrays. ++ * ++ * Note: This function can also return events in the events field of the ++ * dahdi_echocan_state structure. If it can do so, then the echocan does ++ * not need to provide the echocan_events function. ++ * ++ * \return Nothing. ++ */ ++ void (*echocan_process)(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); ++ ++ /*! \brief Retrieve events from the echocan. ++ * \param[in,out] ec Pointer to the state structure. ++ * ++ * ++ * If any events have occurred, the events field of the dahdi_echocan_state ++ * structure should be updated to include them. ++ * ++ * \return Nothing. ++ */ ++ void (*echocan_events)(struct dahdi_echocan_state *ec); ++ ++ /*! \brief Feed a sample (and its position) for echocan training. ++ * \param[in,out] ec Pointer to the state structure. ++ * \param[in] pos The tap position to be 'trained'. ++ * \param[in] val The receive direction sample for the specified tap position. ++ * ++ * \retval Zero if training should continue. ++ * \retval Non-zero if training is complete. ++ */ ++ int (*echocan_traintap)(struct dahdi_echocan_state *ec, int pos, short val); ++ ++ /*! \brief Enable or disable non-linear processing (NLP) in the echocan. ++ * \param[in,out] ec Pointer to the state structure. ++ * \param[in] enable Zero to disable, non-zero to enable. ++ * ++ * \return Nothing. ++ */ ++ void (*echocan_NLP_toggle)(struct dahdi_echocan_state *ec, unsigned int enable); ++ ++#ifdef CONFIG_DAHDI_ECHOCAN_PROCESS_TX ++ /*! \brief Process an array of TX audio samples. ++ * ++ * \return Nothing. ++ */ ++ void (*echocan_process_tx)(struct dahdi_echocan_state *ec, ++ short *tx, u32 size); ++#endif ++}; ++ ++/*! A factory for creating instances of software echo cancelers to be used on DAHDI channels. */ ++struct dahdi_echocan_factory { ++ ++ /*! Get the name of the factory. */ ++ const char *(*get_name)(const struct dahdi_chan *chan); ++ ++ /*! Pointer to the module that owns this factory; the module's reference count will be ++ * incremented/decremented by the DAHDI core as needed. ++ */ ++ struct module *owner; ++ ++ /*! \brief Function to create an instance of the echocan. ++ * \param[in] ecp Structure defining parameters to be used for the instance creation. ++ * \param[in] p Pointer to the beginning of an (optional) array of user-defined parameters. ++ * \param[out] ec Pointer to the state structure that is created, if any. ++ * ++ * \retval Zero on success. ++ * \retval Non-zero on failure (return value will be returned to userspace so it should be a ++ * standard error number). ++ */ ++ int (*echocan_create)(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); ++}; ++ ++/*! \brief Register an echo canceler factory with the DAHDI core. ++ * \param[in] ec Pointer to the dahdi_echocan_factory structure to be registered. ++ * ++ * \retval Zero on success. ++ * \retval Non-zero on failure (return value will be a standard error number). ++ */ ++int dahdi_register_echocan_factory(const struct dahdi_echocan_factory *ec); ++ ++/*! \brief Unregister a previously-registered echo canceler factory from the DAHDI core. ++ * \param[in] ec Pointer to the dahdi_echocan_factory structure to be unregistered. ++ * ++ * \return Nothing. ++ */ ++void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec); ++ ++enum dahdi_echocan_mode { ++ __ECHO_MODE_MUTE = 1 << 8, ++ ECHO_MODE_IDLE = 0, ++ ECHO_MODE_PRETRAINING = 1 | __ECHO_MODE_MUTE, ++ ECHO_MODE_STARTTRAINING = 2 | __ECHO_MODE_MUTE, ++ ECHO_MODE_AWAITINGECHO = 3 | __ECHO_MODE_MUTE, ++ ECHO_MODE_TRAINING = 4 | __ECHO_MODE_MUTE, ++ ECHO_MODE_ACTIVE = 5, ++ ECHO_MODE_FAX = 6, ++}; ++ ++/*! An instance of a DAHDI echo canceler (software or hardware). */ ++struct dahdi_echocan_state { ++ ++ /*! Pointer to a dahdi_echocan_ops structure of operations that can be ++ * performed on this instance. ++ */ ++ const struct dahdi_echocan_ops *ops; ++ ++ /*! State data used by the DAHDI core's CED detector for the transmit ++ * direction, if needed. ++ */ ++ echo_can_disable_detector_state_t txecdis; ++ ++ /*! State data used by the DAHDI core's CED detector for the receive ++ * direction, if needed. ++ */ ++ echo_can_disable_detector_state_t rxecdis; ++ ++ /*! Features offered by the echo canceler that provided this instance. */ ++ struct dahdi_echocan_features features; ++ ++ struct { ++ /*! The mode the echocan is currently in. */ ++ enum dahdi_echocan_mode mode; ++ ++ /*! The last tap position that was fed to the echocan's training function. */ ++ u32 last_train_tap; ++ ++ /*! How many samples to wait before beginning the training operation. */ ++ u32 pretrain_timer; ++ } status; ++ ++ /*! This structure contains event flags, allowing the echocan to report ++ * events that occurred as it processed the transmit and receive streams ++ * of samples. Each call to the echocan_process operation for this ++ * instance may report events, so the structure should be cleared before ++ * calling that operation. ++ */ ++ union dahdi_echocan_events { ++ u32 all; ++ struct { ++ /*! CED tone was detected in the transmit direction. If the ++ * echocan automatically disables its NLP when this occurs, ++ * it must also signal the NLP_auto_disabled event during the *same* ++ * call to echocan_process that reports the CED detection. ++ */ ++ u32 CED_tx_detected:1; ++ ++ /*! CED tone was detected in the receive direction. If the ++ * echocan automatically disables its NLP when this occurs, ++ * it must also signal the NLP_auto_disabled event during the *same* ++ * call to echocan_process that reports the CED detection. ++ */ ++ u32 CED_rx_detected:1; ++ ++ /*! CNG tone was detected in the transmit direction. */ ++ u32 CNG_tx_detected:1; ++ ++ /*! CNG tone was detected in the receive direction. */ ++ u32 CNG_rx_detected:1; ++ ++ /*! The echocan disabled its NLP automatically. ++ */ ++ u32 NLP_auto_disabled:1; ++ ++ /*! The echocan enabled its NLP automatically. ++ */ ++ u32 NLP_auto_enabled:1; ++ } bit; ++ } events; ++}; ++ ++struct dahdi_chan { ++#ifdef CONFIG_DAHDI_NET ++ /*! \note Must be first */ ++ struct dahdi_hdlc *hdlcnetdev; ++#endif ++#ifdef CONFIG_DAHDI_PPP ++ struct ppp_channel *ppp; ++ struct tasklet_struct ppp_calls; ++ int do_ppp_wakeup; ++ int do_ppp_error; ++ struct sk_buff_head ppp_rq; ++#endif ++#ifdef BUFFER_DEBUG ++ int statcount; ++ int lastnumbufs; ++#endif ++ spinlock_t lock; ++ struct mutex mutex; ++ char name[40]; ++ /* Specified by DAHDI */ ++ /*! \brief DAHDI channel number */ ++ int channo; ++ int chanpos; ++ unsigned long flags; ++ long rxp1; ++ long rxp2; ++ long rxp3; ++ int txtone; ++ int tx_v2; ++ int tx_v3; ++ int v1_1; ++ int v2_1; ++ int v3_1; ++ int toneflags; ++ struct sf_detect_state rd; ++ ++ struct dahdi_chan *master; /*!< Our Master channel (could be us) */ ++ /*! \brief Next slave (if appropriate) */ ++ struct dahdi_chan *nextslave; ++ ++ u_char *writechunk; /*!< Actual place to write to */ ++ u_char swritechunk[DAHDI_MAX_CHUNKSIZE]; /*!< Buffer to be written */ ++ u_char *readchunk; /*!< Actual place to read from */ ++ u_char sreadchunk[DAHDI_MAX_CHUNKSIZE]; /*!< Preallocated static area */ ++ short *readchunkpreec; ++ ++ /* Channel from which to read when DACSed. */ ++ struct dahdi_chan *dacs_chan; ++ ++ /*! Pointer to tx and rx gain tables */ ++ const u_char *rxgain; ++ const u_char *txgain; ++ ++ /* Specified by driver, readable by DAHDI */ ++ void *pvt; /*!< Private channel data */ ++ struct file *file; /*!< File structure */ ++ ++ ++#ifdef CONFIG_DAHDI_MIRROR ++ struct dahdi_chan *rxmirror; /*!< channel we mirror reads to */ ++ struct dahdi_chan *txmirror; /*!< channel we mirror writes to */ ++ struct dahdi_chan *srcmirror; /*!< channel we mirror from */ ++#endif /* CONFIG_DAHDI_MIRROR */ ++ struct dahdi_span *span; /*!< Span we're a member of */ ++ int sig; /*!< Signalling */ ++ int sigcap; /*!< Capability for signalling */ ++ __u32 chan_alarms; /*!< alarms status */ ++ ++ wait_queue_head_t waitq; ++ ++ /* Used only by DAHDI -- NO DRIVER SERVICEABLE PARTS BELOW */ ++ /* Buffer declarations */ ++ u_char *readbuf[DAHDI_MAX_NUM_BUFS]; /*!< read buffer */ ++ int inreadbuf; ++ int outreadbuf; ++ ++ u_char *writebuf[DAHDI_MAX_NUM_BUFS]; /*!< write buffers */ ++ int inwritebuf; ++ int outwritebuf; ++ ++ int blocksize; /*!< Block size */ ++ ++ int eventinidx; /*!< out index in event buf (circular) */ ++ int eventoutidx; /*!< in index in event buf (circular) */ ++ unsigned int eventbuf[DAHDI_MAX_EVENTSIZE]; /*!< event circ. buffer */ ++ ++ int readn[DAHDI_MAX_NUM_BUFS]; /*!< # of bytes ready in read buf */ ++ int readidx[DAHDI_MAX_NUM_BUFS]; /*!< current read pointer */ ++ int writen[DAHDI_MAX_NUM_BUFS]; /*!< # of bytes ready in write buf */ ++ int writeidx[DAHDI_MAX_NUM_BUFS]; /*!< current write pointer */ ++ ++ int numbufs; /*!< How many buffers in channel */ ++ int txbufpolicy; /*!< Buffer policy */ ++ int txdisable; /*!< Disable transmitter */ ++ ++ /* Tone zone stuff */ ++ struct dahdi_zone *curzone; /*!< Zone for selecting tones */ ++ struct dahdi_tone *curtone; /*!< Current tone we're playing (if any) */ ++ int tonep; /*!< Current position in tone */ ++ struct dahdi_tone_state ts; /*!< Tone state */ ++ ++ /* Pulse dial stuff */ ++ int pdialcount; /*!< pulse dial count */ ++ ++ /*! Ring cadence */ ++ int ringcadence[DAHDI_MAX_CADENCE]; ++ int firstcadencepos; /*!< Where to restart ring cadence */ ++ ++ /* Digit string dialing stuff */ ++ int digitmode; /*!< What kind of tones are we sending? */ ++ char txdialbuf[DAHDI_MAX_DTMF_BUF]; ++ int dialing; ++ int afterdialingtimer; ++ int cadencepos; /*!< Where in the cadence we are */ ++ ++ /* I/O Mask */ ++ unsigned int iomask; /*! I/O Mux signal mask */ ++ ++ /* HDLC state machines */ ++ struct fasthdlc_state txhdlc; ++ struct fasthdlc_state rxhdlc; ++ int infcs; ++ ++ /* Conferencing stuff */ ++ int confna; /*! conference number (alias) */ ++ int _confn; /*! Actual conference number */ ++ int confmode; /*! conference mode */ ++ int confmute; /*! conference mute mode */ ++ struct dahdi_chan *conf_chan; ++ ++ /* Incoming and outgoing conference chunk queues for ++ communicating between DAHDI master time and ++ other boards */ ++ struct confq confin; ++ struct confq confout; ++ ++ short getlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples */ ++ unsigned char getraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */ ++ short putlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last received samples */ ++ unsigned char putraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */ ++ short conflast[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- base part of channel */ ++ short conflast1[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- pseudo part of channel */ ++ short conflast2[DAHDI_MAX_CHUNKSIZE]; /*!< Previous last conference sample -- pseudo part of channel */ ++ ++ ++ /*! The echo canceler module that should be used to create an ++ instance when this channel needs one */ ++ const struct dahdi_echocan_factory *ec_factory; ++ /*! The echo canceler module that owns the instance currently ++ on this channel, if one is present */ ++ const struct dahdi_echocan_factory *ec_current; ++ /*! The state data of the echo canceler instance in use */ ++ struct dahdi_echocan_state *ec_state; ++ ++ /* RBS timings */ ++ int prewinktime; /*!< pre-wink time (ms) */ ++ int preflashtime; /*!< pre-flash time (ms) */ ++ int winktime; /*!< wink time (ms) */ ++ int flashtime; /*!< flash time (ms) */ ++ int starttime; /*!< start time (ms) */ ++ int rxwinktime; /*!< rx wink time (ms) */ ++ int rxflashtime; /*!< rx flash time (ms) */ ++ int debouncetime; /*!< FXS GS sig debounce time (ms) */ ++ int pulsebreaktime; /*!< pulse line open time (ms) */ ++ int pulsemaketime; /*!< pulse line closed time (ms) */ ++ int pulseaftertime; /*!< pulse time between digits (ms) */ ++ ++ /*! RING debounce timer */ ++ int ringdebtimer; ++ ++ /*! RING trailing detector to make sure a RING is really over */ ++ int ringtrailer; ++ ++ /* PULSE digit receiver stuff */ ++ int pulsecount; ++ int pulsetimer; ++ ++ /* RBS timers */ ++ int itimerset; /*!< what the itimer was set to last */ ++ int itimer; ++ int otimer; ++ ++ /* RBS state */ ++ int gotgs; ++ int txstate; ++ int rxsig; ++ int txsig; ++ int rxsigstate; ++ ++ /* non-RBS rx state */ ++ int rxhooksig; ++ int txhooksig; ++ int kewlonhook; ++ ++ /*! Idle signalling if CAS signalling */ ++ int idlebits; ++ ++ int deflaw; /*! 1 = mulaw, 2=alaw, 0=undefined */ ++ short *xlaw; ++#ifdef OPTIMIZE_CHANMUTE ++ int chanmute; /*!< no need for PCM data */ ++#endif ++#ifdef CONFIG_CALC_XLAW ++ unsigned char (*lineartoxlaw)(short a); ++#else ++ unsigned char *lin2x; ++#endif ++ struct device chan_device; /*!< Kernel object for this chan */ ++#define dev_to_chan(dev) container_of(dev, struct dahdi_chan, chan_device) ++}; ++ ++#ifdef CONFIG_DAHDI_NET ++struct dahdi_hdlc { ++ struct net_device *netdev; ++ struct dahdi_chan *chan; ++}; ++#endif ++ ++/*! Define the maximum block size */ ++#define DAHDI_MAX_BLOCKSIZE 8192 ++ ++ ++#define DAHDI_DEFAULT_WINKTIME 150 /*!< 150 ms default wink time */ ++#define DAHDI_DEFAULT_FLASHTIME 750 /*!< 750 ms default flash time */ ++ ++#define DAHDI_DEFAULT_PREWINKTIME 50 /*!< 50 ms before wink */ ++#define DAHDI_DEFAULT_PREFLASHTIME 50 /*!< 50 ms before flash */ ++#define DAHDI_DEFAULT_STARTTIME 1500 /*!< 1500 ms of start */ ++#define DAHDI_DEFAULT_RINGTIME 2000 /*!< 2000 ms of ring on (start, FXO) */ ++#if 0 ++#define DAHDI_DEFAULT_RXWINKTIME 250 /*!< 250ms longest rx wink */ ++#endif ++#define DAHDI_DEFAULT_RXWINKTIME 300 /*!< 300ms longest rx wink (to work with the Atlas) */ ++#define DAHDI_DEFAULT_RXFLASHTIME 1250 /*!< 1250ms longest rx flash */ ++#define DAHDI_DEFAULT_DEBOUNCETIME 600 /*!< 600ms of FXS GS signalling debounce */ ++#define DAHDI_DEFAULT_PULSEMAKETIME 50 /*!< 50 ms of line closed when dial pulsing */ ++#define DAHDI_DEFAULT_PULSEBREAKTIME 50 /*!< 50 ms of line open when dial pulsing */ ++#define DAHDI_DEFAULT_PULSEAFTERTIME 750 /*!< 750ms between dial pulse digits */ ++ ++#define DAHDI_MINPULSETIME (15 * 8) /*!< 15 ms minimum */ ++ ++#ifdef SHORT_FLASH_TIME ++#define DAHDI_MAXPULSETIME (80 * 8) /*!< we need 80 ms, not 200ms, as we have a short flash */ ++#else ++#define DAHDI_MAXPULSETIME (200 * 8) /*!< 200 ms maximum */ ++#endif ++ ++#define DAHDI_PULSETIMEOUT ((DAHDI_MAXPULSETIME / 8) + 50) ++ ++#define DAHDI_RINGTRAILER (50 * 8) /*!< Don't consider a ring "over" until it's been gone at least this ++ much time */ ++ ++#define DAHDI_LOOPCODE_TIME 10000 /*!< send loop codes for 10 secs */ ++#define DAHDI_ALARMSETTLE_TIME 5000 /*!< allow alarms to settle for 5 secs */ ++#define DAHDI_AFTERSTART_TIME 500 /*!< 500ms after start */ ++ ++#define DAHDI_RINGOFFTIME 4000 /*!< Turn off ringer for 4000 ms */ ++#define DAHDI_KEWLTIME 500 /*!< 500ms for kewl pulse */ ++#define DAHDI_AFTERKEWLTIME 300 /*!< 300ms after kewl pulse */ ++ ++#define DAHDI_MAX_PRETRAINING 1000 /*!< 1000ms max pretraining time */ ++ ++#ifdef FXSFLASH ++#define DAHDI_FXSFLASHMINTIME 450 /*!< min 450ms */ ++#define DAHDI_FXSFLASHMAXTIME 550 /*!< max 550ms */ ++#endif ++ ++ ++struct dahdi_chardev { ++ const char *name; ++ __u8 minor; ++}; ++ ++int dahdi_register_chardev(struct dahdi_chardev *dev); ++int dahdi_unregister_chardev(struct dahdi_chardev *dev); ++ ++/*! \brief defines for transmit signalling */ ++enum dahdi_txsig { ++ DAHDI_TXSIG_ONHOOK, /*!< On hook */ ++ DAHDI_TXSIG_OFFHOOK, /*!< Off hook */ ++ DAHDI_TXSIG_START, /*!< Start / Ring */ ++ DAHDI_TXSIG_KEWL, /*!< Drop battery if possible */ ++ /*! Leave this as the last entry */ ++ DAHDI_TXSIG_TOTAL, ++}; ++ ++enum dahdi_rxsig { ++ DAHDI_RXSIG_ONHOOK, ++ DAHDI_RXSIG_OFFHOOK, ++ DAHDI_RXSIG_START, ++ DAHDI_RXSIG_RING, ++ DAHDI_RXSIG_INITIAL ++}; ++ ++enum { ++ /* Span flags */ ++ DAHDI_FLAGBIT_REGISTERED= 0, ++ DAHDI_FLAGBIT_RUNNING = 1, ++ DAHDI_FLAGBIT_RBS = 12, /*!< Span uses RBS signalling */ ++ ++ /* Channel flags */ ++ DAHDI_FLAGBIT_DTMFDECODE= 2, /*!< Channel supports native DTMF decode */ ++ DAHDI_FLAGBIT_MFDECODE = 3, /*!< Channel supports native MFr2 decode */ ++ DAHDI_FLAGBIT_ECHOCANCEL= 4, /*!< Channel supports native echo cancellation */ ++ DAHDI_FLAGBIT_HDLC = 5, /*!< Perform HDLC */ ++#ifdef CONFIG_DAHDI_NET ++ DAHDI_FLAGBIT_NETDEV = 6, /*!< Send to network */ ++#endif ++ DAHDI_FLAGBIT_CLEAR = 8, /*!< Clear channel */ ++ DAHDI_FLAGBIT_AUDIO = 9, /*!< Audio mode channel */ ++ DAHDI_FLAGBIT_OPEN = 10, /*!< Channel is open */ ++ DAHDI_FLAGBIT_FCS = 11, /*!< Calculate FCS */ ++ /* Reserve 12 for uniqueness with span flags */ ++ DAHDI_FLAGBIT_LINEAR = 13, /*!< Talk to user space in linear */ ++ DAHDI_FLAGBIT_PPP = 14, /*!< PPP is available */ ++ DAHDI_FLAGBIT_T1PPP = 15, ++ DAHDI_FLAGBIT_SIGFREEZE = 16, /*!< Freeze signalling */ ++ DAHDI_FLAGBIT_NOSTDTXRX = 17, /*!< Do NOT do standard transmit and receive on every interrupt */ ++ DAHDI_FLAGBIT_LOOPED = 18, /*!< Loopback the receive data from the channel to the transmit */ ++ DAHDI_FLAGBIT_MTP2 = 19, /*!< Repeats last message in buffer and also discards repeating messages sent to us */ ++ DAHDI_FLAGBIT_HDLC56 = 20, /*!< Sets the given channel (if in HDLC mode) to use 56K HDLC instead of 64K */ ++ DAHDI_FLAGBIT_BUFEVENTS = 21, /*!< Report buffer events */ ++ DAHDI_FLAGBIT_TXUNDERRUN = 22, /*!< Transmit underrun condition */ ++ DAHDI_FLAGBIT_RXOVERRUN = 23, /*!< Receive overrun condition */ ++ DAHDI_FLAGBIT_DEVFILE = 25, /*!< Channel has a sysfs dev file */ ++}; ++ ++#ifdef CONFIG_DAHDI_NET ++/** ++ * have_netdev() - Return true if a channel has an associated network device. ++ * @chan: Then channel to check. ++ * ++ */ ++static inline int dahdi_have_netdev(const struct dahdi_chan *chan) ++{ ++ return test_bit(DAHDI_FLAGBIT_NETDEV, &chan->flags); ++} ++#else ++static inline int dahdi_have_netdev(const struct dahdi_chan *chan) { return 0; } ++#endif ++ ++struct dahdi_count { ++ u32 fe; /*!< Framing error counter */ ++ u32 cv; /*!< Coding violations counter */ ++ u32 bpv; /*!< Bipolar Violation counter */ ++ u32 crc4; /*!< CRC4 error counter */ ++ u32 ebit; /*!< current E-bit error count */ ++ u32 fas; /*!< current FAS error count */ ++ u32 be; /*!< current bit error count */ ++ u32 prbs; /*!< current PRBS detected pattern */ ++ u32 errsec; /*!< errored seconds */ ++ u32 timingslips; /*!< Clock slips */ ++}; ++ ++/* map flagbits to flag masks */ ++#define DAHDI_FLAG(x) (1 << (DAHDI_FLAGBIT_ ## x)) ++ ++/*! This is a redefinition of the flags from above to allow use of the ++ * legacy drivers that do not use the kernel atomic bit testing and ++ * changing routines. ++ * ++ * See the above descriptions for DAHDI_FLAGBIT_.... for documentation ++ * about function. */ ++/* Span flags */ ++#define DAHDI_FLAG_REGISTERED DAHDI_FLAG(REGISTERED) ++#define DAHDI_FLAG_RUNNING DAHDI_FLAG(RUNNING) ++#define DAHDI_FLAG_RBS DAHDI_FLAG(RBS) ++ ++/* Channel flags */ ++#define DAHDI_FLAG_DTMFDECODE DAHDI_FLAG(DTMFDECODE) ++#define DAHDI_FLAG_MFDECODE DAHDI_FLAG(MFDECODE) ++#define DAHDI_FLAG_ECHOCANCEL DAHDI_FLAG(ECHOCANCEL) ++ ++#define DAHDI_FLAG_HDLC DAHDI_FLAG(HDLC) ++/* #define DAHDI_FLAG_NETDEV DAHDI_FLAG(NETDEV) */ ++#define DAHDI_FLAG_CLEAR DAHDI_FLAG(CLEAR) ++#define DAHDI_FLAG_AUDIO DAHDI_FLAG(AUDIO) ++ ++#define DAHDI_FLAG_OPEN DAHDI_FLAG(OPEN) ++#define DAHDI_FLAG_FCS DAHDI_FLAG(FCS) ++/* Reserve 12 for uniqueness with span flags */ ++#define DAHDI_FLAG_LINEAR DAHDI_FLAG(LINEAR) ++#define DAHDI_FLAG_PPP DAHDI_FLAG(PPP) ++#define DAHDI_FLAG_T1PPP DAHDI_FLAG(T1PPP) ++#define DAHDI_FLAG_SIGFREEZE DAHDI_FLAG(SIGFREEZE) ++#define DAHDI_FLAG_NOSTDTXRX DAHDI_FLAG(NOSTDTXRX) ++#define DAHDI_FLAG_LOOPED DAHDI_FLAG(LOOPED) ++#define DAHDI_FLAG_MTP2 DAHDI_FLAG(MTP2) ++#define DAHDI_FLAG_HDLC56 DAHDI_FLAG(HDLC56) ++#define DAHDI_FLAG_BUFEVENTS DAHDI_FLAG(BUFEVENTS) ++#define DAHDI_FLAG_TXUNDERRUN DAHDI_FLAG(TXUNDERRUN) ++#define DAHDI_FLAG_RXOVERRUN DAHDI_FLAG(RXOVERRUN) ++ ++enum spantypes { ++ SPANTYPE_INVALID = 0, ++ SPANTYPE_ANALOG_FXS, ++ SPANTYPE_ANALOG_FXO, ++ SPANTYPE_ANALOG_MIXED, ++ SPANTYPE_DIGITAL_E1, ++ SPANTYPE_DIGITAL_T1, ++ SPANTYPE_DIGITAL_J1, ++ SPANTYPE_DIGITAL_BRI_NT, ++ SPANTYPE_DIGITAL_BRI_TE, ++ SPANTYPE_DIGITAL_BRI_SOFT, ++ SPANTYPE_DIGITAL_DYNAMIC, ++}; ++const char *dahdi_spantype2str(enum spantypes st); ++enum spantypes dahdi_str2spantype(const char *name); ++const char *dahdi_lineconfig_bit_name(int lineconfig_bit); ++ssize_t lineconfig_str(int lineconfig, char buf[], size_t size); ++ ++struct file; ++ ++struct dahdi_span_ops { ++ struct module *owner; /*!< Which module is exporting this span. */ ++ ++ /* ==== Span Callback Operations ==== */ ++ /*! Req: Set the requested chunk size. This is the unit in which you must ++ report results for conferencing, etc */ ++ int (*setchunksize)(struct dahdi_span *span, int chunksize); ++ ++ /*! Opt: Configure the span (if appropriate) */ ++ int (*spanconfig)(struct file *file, struct dahdi_span *span, ++ struct dahdi_lineconfig *lc); ++ ++ /*! Opt: Start the span */ ++ int (*startup)(struct file *file, struct dahdi_span *span); ++ ++ /*! Opt: Shutdown the span */ ++ int (*shutdown)(struct dahdi_span *span); ++ ++ /*! Opt: Enable maintenance modes */ ++ int (*maint)(struct dahdi_span *span, int mode); ++ ++#ifdef DAHDI_SYNC_TICK ++ /*! Opt: send sync to spans. Called in hard_irq context with chan_lock ++ * held.*/ ++ void (*sync_tick)(struct dahdi_span *span, int is_master); ++#endif ++ /* ==== Channel Callback Operations ==== */ ++ /*! Opt: Set signalling type (if appropriate) */ ++ int (*chanconfig)(struct file *file, struct dahdi_chan *chan, ++ int sigtype); ++ ++ /*! Opt: Prepare a channel for I/O */ ++ int (*open)(struct dahdi_chan *chan); ++ ++ /*! Opt: Close channel for I/O */ ++ int (*close)(struct dahdi_chan *chan); ++ ++ /*! Opt: IOCTL */ ++ int (*ioctl)(struct dahdi_chan *chan, unsigned int cmd, unsigned long data); ++ ++ /* Okay, now we get to the signalling. You have several options: */ ++ ++ /* Option 1: If you're a T1 like interface, you can just provide a ++ rbsbits function and we'll assert robbed bits for you. Be sure to ++ set the DAHDI_FLAG_RBS in this case. */ ++ ++ /*! Opt: If the span uses A/B bits, set them here */ ++ int (*rbsbits)(struct dahdi_chan *chan, int bits); ++ ++ /*! Option 2: If you don't know about sig bits, but do have their ++ equivalents (i.e. you can disconnect battery, detect off hook, ++ generate ring, etc directly) then you can just specify a ++ sethook function, and we'll call you with appropriate hook states ++ to set. Still set the DAHDI_FLAG_RBS in this case as well */ ++ int (*hooksig)(struct dahdi_chan *chan, enum dahdi_txsig hookstate); ++ ++ /*! Option 3: If you can't use sig bits, you can write a function ++ which handles the individual hook states */ ++ int (*sethook)(struct dahdi_chan *chan, int hookstate); ++ ++ /*! Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */ ++ void (*hdlc_hard_xmit)(struct dahdi_chan *chan); ++ ++ /*! If the watchdog detects no received data, it will call the ++ watchdog routine */ ++ int (*watchdog)(struct dahdi_span *span, int cause); ++ ++#ifdef DAHDI_AUDIO_NOTIFY ++ /*! Opt: audio is used, don't optimize out */ ++ int (*audio_notify)(struct dahdi_chan *chan, int yes); ++#endif ++ ++ /*! Opt: Enable preechocan stream from inline HW echocanceler. */ ++ int (*enable_hw_preechocan)(struct dahdi_chan *chan); ++ ++ /*! Opt: Disable preechocan stream from inline HW echocanceler. */ ++ void (*disable_hw_preechocan)(struct dahdi_chan *chan); ++ ++ /*! Opt: Dacs the contents of chan2 into chan1 if possible */ ++ int (*dacs)(struct dahdi_chan *chan1, struct dahdi_chan *chan2); ++ ++ /*! Opt: Provide echo cancellation on a channel */ ++ int (*echocan_create)(struct dahdi_chan *chan, ++ struct dahdi_echocanparams *ecp, ++ struct dahdi_echocanparam *p, ++ struct dahdi_echocan_state **ec); ++ ++ /*! Opt: Provide the name of the echo canceller on a channel */ ++ const char *(*echocan_name)(const struct dahdi_chan *chan); ++ ++ /*! When using "assigned spans", this function is called back when this ++ * span has been assigned with the system. */ ++ void (*assigned)(struct dahdi_span *span); ++ ++ /*! Called when the spantype / linemode is changed before the span is ++ * assigned a number. */ ++ int (*set_spantype)(struct dahdi_span *span, enum spantypes st); ++}; ++ ++/** ++ * dahdi_device - Represents a device that can contain one or more spans. ++ * ++ * @spans: List of child spans. ++ * @manufacturer: Device manufacturer. ++ * @location: The location of this device. This should not change if ++ * the device is replaced (e.g: in the same PCI slot) ++ * @hardware_id: The hardware_id of this device (NULL for devices without ++ * a hardware_id). This should not change if the device is ++ * relocated to a different location (e.g: different PCI slot) ++ * @devicetype: What type of device this is. ++ * @irqmisses: Count of "interrupt misses" for this device. ++ * ++ */ ++struct dahdi_device { ++ struct list_head spans; ++ const char *manufacturer; ++ const char *location; ++ const char *hardware_id; ++ const char *devicetype; ++ struct device dev; ++ unsigned int irqmisses; ++ ktime_t registration_time; ++}; ++ ++struct dahdi_span { ++ spinlock_t lock; ++ char name[40]; /*!< Span name */ ++ char desc[80]; /*!< Span description */ ++ enum spantypes spantype; /*!< span type */ ++ int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */ ++ int alarms; /*!< Pending alarms on span */ ++ unsigned long flags; ++ u8 cannot_provide_timing:1; ++ int lbo; /*!< Span Line-Buildout */ ++ int lineconfig; /*!< Span line configuration */ ++ int linecompat; /*!< Span line compatibility (0 for ++ analog spans)*/ ++ int channels; /*!< Number of channels in span */ ++ int txlevel; /*!< Tx level */ ++ int rxlevel; /*!< Rx level */ ++ int syncsrc; /*!< current sync src (gets copied here) */ ++ struct dahdi_count count; /*!< Performance and Error counters */ ++ ++ int maintstat; /*!< Maintenance state */ ++ int mainttimer; /*!< Maintenance timer */ ++ ++ struct dahdi_chan **chans; /*!< Member channel structures */ ++ ++ const struct dahdi_span_ops *ops; /*!< span callbacks. */ ++ ++ /* Used by DAHDI only -- no user servicable parts inside */ ++ int spanno; /*!< Span number for DAHDI */ ++ int offset; /*!< Offset within a given card */ ++ int lastalarms; /*!< Previous alarms */ ++ ++#ifdef CONFIG_DAHDI_WATCHDOG ++ int watchcounter; ++ int watchstate; ++#endif ++ ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *proc_entry; ++#endif ++ struct list_head spans_node; ++ ++ struct dahdi_device *parent; ++ struct list_head device_node; ++ struct device *span_device; ++}; ++ ++struct dahdi_transcoder_channel { ++ void *pvt; ++ struct dahdi_transcoder *parent; ++ wait_queue_head_t ready; ++ __u32 built_fmts; ++#define DAHDI_TC_FLAG_BUSY 1 ++#define DAHDI_TC_FLAG_CHAN_BUILT 2 ++#define DAHDI_TC_FLAG_NONBLOCK 3 ++#define DAHDI_TC_FLAG_DATA_WAITING 4 ++ unsigned long flags; ++ u32 dstfmt; ++ u32 srcfmt; ++}; ++ ++int dahdi_is_sync_master(const struct dahdi_span *span); ++struct dahdi_span *get_master_span(void); ++void set_master_span(int spanno); ++ ++static inline int ++dahdi_tc_is_built(struct dahdi_transcoder_channel *dtc) { ++ return test_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags); ++} ++static inline void ++dahdi_tc_set_built(struct dahdi_transcoder_channel *dtc) { ++ set_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags); ++} ++static inline void ++dahdi_tc_clear_built(struct dahdi_transcoder_channel *dtc) { ++ clear_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags); ++} ++static inline int ++dahdi_tc_is_nonblock(struct dahdi_transcoder_channel *dtc) { ++ return test_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags); ++} ++static inline void ++dahdi_tc_set_nonblock(struct dahdi_transcoder_channel *dtc) { ++ set_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags); ++} ++static inline void ++dahdi_tc_clear_nonblock(struct dahdi_transcoder_channel *dtc) { ++ clear_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags); ++} ++static inline int ++dahdi_tc_is_data_waiting(struct dahdi_transcoder_channel *dtc) { ++ return test_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags); ++} ++static inline int ++dahdi_tc_is_busy(struct dahdi_transcoder_channel *dtc) { ++ return test_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); ++} ++static inline void ++dahdi_tc_set_busy(struct dahdi_transcoder_channel *dtc) { ++ set_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); ++} ++static inline void ++dahdi_tc_clear_busy(struct dahdi_transcoder_channel *dtc) { ++ clear_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); ++} ++static inline void ++dahdi_tc_set_data_waiting(struct dahdi_transcoder_channel *dtc) { ++ set_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags); ++} ++static inline void ++dahdi_tc_clear_data_waiting(struct dahdi_transcoder_channel *dtc) { ++ clear_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags); ++} ++ ++struct dahdi_transcoder { ++ struct list_head active_list_node; ++ struct list_head registration_list_node; ++ char name[80]; ++ int numchannels; ++ unsigned int srcfmts; ++ unsigned int dstfmts; ++ struct file_operations fops; ++ int (*allocate)(struct dahdi_transcoder_channel *channel); ++ int (*release)(struct dahdi_transcoder_channel *channel); ++ /* Transcoder channels */ ++ struct dahdi_transcoder_channel channels[0]; ++}; ++ ++#define DAHDI_WATCHDOG_NOINTS (1 << 0) ++ ++#define DAHDI_WATCHDOG_INIT 1000 ++ ++#define DAHDI_WATCHSTATE_UNKNOWN 0 ++#define DAHDI_WATCHSTATE_OK 1 ++#define DAHDI_WATCHSTATE_RECOVERING 2 ++#define DAHDI_WATCHSTATE_FAILED 3 ++ ++ ++struct dahdi_dynamic { ++ char addr[40]; ++ char dname[20]; ++ int err; ++ struct kref kref; ++ long rxjif; ++ unsigned short txcnt; ++ unsigned short rxcnt; ++ struct dahdi_device *ddev; ++ struct dahdi_span span; ++ struct dahdi_chan *chans[256]; ++ struct dahdi_dynamic_driver *driver; ++ void *pvt; ++ int timing; ++ int master; ++ unsigned char *msgbuf; ++ struct device *dev; ++ ++ struct list_head list; ++}; ++ ++struct dahdi_dynamic_driver { ++ /*! Driver name (e.g. Eth) */ ++ const char *name; ++ ++ /*! Driver description */ ++ const char *desc; ++ ++ /*! Create a new transmission pipe */ ++ int (*create)(struct dahdi_dynamic *d, const char *address); ++ ++ /*! Destroy a created transmission pipe */ ++ void (*destroy)(struct dahdi_dynamic *d); ++ ++ /*! Transmit a given message */ ++ void (*transmit)(struct dahdi_dynamic *d, u8 *msg, size_t msglen); ++ ++ /*! Flush any pending messages */ ++ int (*flush)(void); ++ ++ struct list_head list; ++ struct module *owner; ++ ++ /*! Numberic id of next device created by this driver. */ ++ unsigned int id; ++}; ++ ++/*! \brief Receive a dynamic span message */ ++void dahdi_dynamic_receive(struct dahdi_span *span, unsigned char *msg, int msglen); ++ ++/*! \brief Register a dynamic driver */ ++int dahdi_dynamic_register_driver(struct dahdi_dynamic_driver *driver); ++ ++/*! \brief Unregister a dynamic driver */ ++void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *driver); ++ ++int _dahdi_receive(struct dahdi_span *span); ++ ++/*! Receive on a span. The DAHDI interface will handle all the calculations for ++ all member channels of the span, pulling the data from the readchunk buffer */ ++static inline int dahdi_receive(struct dahdi_span *span) ++{ ++ unsigned long flags; ++ int ret; ++ local_irq_save(flags); ++ ret = _dahdi_receive(span); ++ local_irq_restore(flags); ++ return ret; ++} ++ ++int _dahdi_transmit(struct dahdi_span *span); ++ ++/*! Prepare writechunk buffers on all channels for this span */ ++static inline int dahdi_transmit(struct dahdi_span *span) ++{ ++ unsigned long flags; ++ int ret; ++ local_irq_save(flags); ++ ret = _dahdi_transmit(span); ++ local_irq_restore(flags); ++ return ret; ++} ++ ++static inline int dahdi_is_digital_span(const struct dahdi_span *s) ++{ ++ return (s->linecompat > 0); ++} ++ ++static inline int dahdi_is_t1_span(const struct dahdi_span *s) ++{ ++ return (s->linecompat & (DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF | ++ DAHDI_CONFIG_B8ZS)) > 0; ++} ++ ++static inline int dahdi_is_e1_span(const struct dahdi_span *s) ++{ ++ return dahdi_is_digital_span(s) && !dahdi_is_t1_span(s); ++} ++ ++/*! Abort the buffer currently being receive with event "event" */ ++void dahdi_hdlc_abort(struct dahdi_chan *ss, int event); ++ ++/*! Indicate to DAHDI that the end of frame was received and rotate buffers */ ++void dahdi_hdlc_finish(struct dahdi_chan *ss); ++ ++/*! Put a chunk of data into the current receive buffer */ ++void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int bytes); ++ ++/*! Get a chunk of data from the current transmit buffer. Returns -1 if no data ++ * is left to send, 0 if there is data remaining in the current message to be sent ++ * and 1 if the currently transmitted message is now done */ ++int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size); ++ ++/*! Register a device. Returns 0 on success, -1 on failure. */ ++struct dahdi_device *dahdi_create_device(void); ++int dahdi_register_device(struct dahdi_device *ddev, struct device *parent); ++void dahdi_unregister_device(struct dahdi_device *ddev); ++void dahdi_free_device(struct dahdi_device *ddev); ++void dahdi_init_span(struct dahdi_span *span); ++ ++/*! Allocate / free memory for a transcoder */ ++struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans); ++void dahdi_transcoder_free(struct dahdi_transcoder *ztc); ++ ++/*! \brief Register a transcoder */ ++int dahdi_transcoder_register(struct dahdi_transcoder *tc); ++ ++/*! \brief Unregister a transcoder */ ++int dahdi_transcoder_unregister(struct dahdi_transcoder *tc); ++ ++/*! \brief Alert a transcoder */ ++int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc); ++ ++/*! \brief Gives a name to an LBO */ ++const char *dahdi_lboname(int lbo); ++ ++/*! \brief Tell DAHDI about changes in received rbs bits */ ++void dahdi_rbsbits(struct dahdi_chan *chan, int bits); ++ ++/*! \brief Tell DAHDI abou changes in received signalling */ ++void dahdi_hooksig(struct dahdi_chan *chan, enum dahdi_rxsig rxsig); ++ ++/*! \brief Queue an event on a channel */ ++void dahdi_qevent_nolock(struct dahdi_chan *chan, int event); ++ ++/*! \brief Queue an event on a channel, locking it first */ ++void dahdi_qevent_lock(struct dahdi_chan *chan, int event); ++ ++/*! \brief Notify a change possible change in alarm status on a channel */ ++void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms); ++ ++/*! \brief Notify a change possible change in alarm status on a span */ ++void dahdi_alarm_notify(struct dahdi_span *span); ++ ++/*! \brief Initialize a tone state */ ++void dahdi_init_tone_state(struct dahdi_tone_state *ts, struct dahdi_tone *zt); ++ ++/*! \brief Get a given MF tone struct, suitable for dahdi_tone_nextsample. */ ++struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int digitmode); ++ ++/*! \brief Convert signalling bits to human readable string */ ++const char *sigstr(int sig); ++ ++/*! \brief Convert alarm bits to human readable string */ ++int fill_alarm_string(char *buf, int count, int alarms); ++ ++/* Echo cancel a receive and transmit chunk for a given channel. This ++ should be called by the low-level driver as close to the interface ++ as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE ++ AT THE DAHDI LEVEL. dahdi_ec_chunk will not echo cancel if it should ++ not be doing so. rxchunk is modified in-place */ ++void __dahdi_ec_chunk(struct dahdi_chan *ss, u8 *rxchunk, ++ const u8 *preecchunk, const u8 *txchunk); ++ ++static inline void _dahdi_ec_chunk(struct dahdi_chan *chan, ++ u8 *rxchunk, const u8 *txchunk) ++{ ++ __dahdi_ec_chunk(chan, rxchunk, rxchunk, txchunk); ++} ++ ++static inline void dahdi_ec_chunk(struct dahdi_chan *ss, unsigned char *rxchunk, ++ const unsigned char *txchunk) ++{ ++ unsigned long flags; ++ local_irq_save(flags); ++ _dahdi_ec_chunk(ss, rxchunk, txchunk); ++ local_irq_restore(flags); ++} ++ ++void _dahdi_ec_span(struct dahdi_span *span); ++static inline void dahdi_ec_span(struct dahdi_span *span) ++{ ++ unsigned long flags; ++ local_irq_save(flags); ++ _dahdi_ec_span(span); ++ local_irq_restore(flags); ++} ++ ++extern struct file_operations *dahdi_transcode_fops; ++ ++int dahdi_get_auto_assign_spans(void); ++ ++/* Don't use these directly -- they're not guaranteed to ++ be there. */ ++extern short __dahdi_mulaw[256]; ++extern short __dahdi_alaw[256]; ++#ifdef CONFIG_CALC_XLAW ++u_char __dahdi_lineartoulaw(short a); ++u_char __dahdi_lineartoalaw(short a); ++#else ++extern u_char __dahdi_lin2mu[16384]; ++extern u_char __dahdi_lin2a[16384]; ++#endif ++ ++struct dahdi_dynamic_ops { ++ struct module *owner; ++ int (*ioctl)(unsigned int cmd, unsigned long data); ++}; ++ ++/*! \brief Used by dynamic DAHDI -- don't use directly */ ++void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops); ++ ++/*! \brief Used by DAHDI HPEC module -- don't use directly */ ++void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data)); ++ ++/*! \brief Used privately by DAHDI. Avoid touching directly */ ++struct dahdi_tone { ++ int fac1; ++ int init_v2_1; ++ int init_v3_1; ++ ++ int fac2; ++ int init_v2_2; ++ int init_v3_2; ++ ++ int tonesamples; /*!< How long to play this tone before ++ going to the next (in samples) */ ++ struct dahdi_tone *next; /* Next tone in this sequence */ ++ ++ int modulate; ++}; ++ ++static inline short dahdi_tone_nextsample(struct dahdi_tone_state *ts, struct dahdi_tone *zt) ++{ ++ /* follow the curves, return the sum */ ++ ++ int p; ++ ++ ts->v1_1 = ts->v2_1; ++ ts->v2_1 = ts->v3_1; ++ ts->v3_1 = (zt->fac1 * ts->v2_1 >> 15) - ts->v1_1; ++ ++ ts->v1_2 = ts->v2_2; ++ ts->v2_2 = ts->v3_2; ++ ts->v3_2 = (zt->fac2 * ts->v2_2 >> 15) - ts->v1_2; ++ ++ /* Return top 16 bits */ ++ if (!ts->modulate) return ts->v3_1 + ts->v3_2; ++ /* we are modulating */ ++ p = ts->v3_2 - 32768; ++ if (p < 0) p = -p; ++ p = ((p * 9) / 10) + 1; ++ return (ts->v3_1 * p) >> 15; ++ ++} ++ ++static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss) ++{ ++ /* follow the curves, return the sum */ ++ ++ ss->v1_1 = ss->v2_1; ++ ss->v2_1 = ss->v3_1; ++ ss->v3_1 = (ss->txtone * ss->v2_1 >> 15) - ss->v1_1; ++ return ss->v3_1; ++} ++ ++/* These are the right functions to use. */ ++ ++#define DAHDI_MULAW(a) (__dahdi_mulaw[(a)]) ++#define DAHDI_ALAW(a) (__dahdi_alaw[(a)]) ++#define DAHDI_XLAW(a,c) (c->xlaw[(a)]) ++ ++#ifdef CONFIG_CALC_XLAW ++#define DAHDI_LIN2MU(a) (__dahdi_lineartoulaw((a))) ++#define DAHDI_LIN2A(a) (__dahdi_lineartoalaw((a))) ++ ++#define DAHDI_LIN2X(a,c) ((c)->lineartoxlaw((a))) ++ ++#else ++/* Use tables */ ++#define DAHDI_LIN2MU(a) (__dahdi_lin2mu[((unsigned short)(a)) >> 2]) ++#define DAHDI_LIN2A(a) (__dahdi_lin2a[((unsigned short)(a)) >> 2]) ++ ++/* Manipulate as appropriate for x-law */ ++#define DAHDI_LIN2X(a,c) ((c)->lin2x[((unsigned short)(a)) >> 2]) ++ ++#endif /* CONFIG_CALC_XLAW */ ++ ++/* Data formats for capabilities and frames alike (from Asterisk) */ ++/*! G.723.1 compression */ ++#define DAHDI_FORMAT_G723_1 (1 << 0) ++/*! GSM compression */ ++#define DAHDI_FORMAT_GSM (1 << 1) ++/*! Raw mu-law data (G.711) */ ++#define DAHDI_FORMAT_ULAW (1 << 2) ++/*! Raw A-law data (G.711) */ ++#define DAHDI_FORMAT_ALAW (1 << 3) ++/*! ADPCM (G.726, 32kbps) */ ++#define DAHDI_FORMAT_G726 (1 << 4) ++/*! ADPCM (IMA) */ ++#define DAHDI_FORMAT_ADPCM (1 << 5) ++/*! Raw 16-bit Signed Linear (8000 Hz) PCM */ ++#define DAHDI_FORMAT_SLINEAR (1 << 6) ++/*! LPC10, 180 samples/frame */ ++#define DAHDI_FORMAT_LPC10 (1 << 7) ++/*! G.729A audio */ ++#define DAHDI_FORMAT_G729A (1 << 8) ++/*! SpeeX Free Compression */ ++#define DAHDI_FORMAT_SPEEX (1 << 9) ++/*! iLBC Free Compression */ ++#define DAHDI_FORMAT_ILBC (1 << 10) ++/*! Maximum audio format */ ++#define DAHDI_FORMAT_MAX_AUDIO (1 << 15) ++/*! Maximum audio mask */ ++#define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) ++ ++#ifndef TIMER_DATA_TYPE ++#define TIMER_DATA_TYPE unsigned long ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) ++ ++#ifdef RHEL_RELEASE_VERSION ++#if RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7, 5) ++#define DAHDI_HAVE_TIMER_SETUP ++#undef TIMER_DATA_TYPE ++#define TIMER_DATA_TYPE struct timer_list * ++#endif ++#endif ++ ++#ifndef DAHDI_HAVE_TIMER_SETUP ++/** ++ * timer_setup - Added in 4.13.0. We can make a direct translation to the ++ * setup_timer interface since DAHDI does not pass any flags to any of the ++ * timer_setup functions. ++ * ++ */ ++static inline void ++timer_setup(struct timer_list *timer, ++ void (*timer_callback)(TIMER_DATA_TYPE data), ++ unsigned long flags) ++{ ++ WARN_ON(flags != 0); ++ setup_timer(timer, timer_callback, (TIMER_DATA_TYPE)timer); ++} ++ ++#define from_timer(var, callback_timer, timer_fieldname) \ ++ container_of((struct timer_list *)(callback_timer), \ ++ typeof(*var), timer_fieldname) ++ ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) ++#define refcount_read atomic_read ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) ++#define dahdi_ktime_equal ktime_equal ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) ++ ++#ifdef RHEL_RELEASE_VERSION ++#if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 8) ++#define DAHDI_HAVE_KTIME_MS_DELTA ++#endif ++#endif ++ ++#ifndef DAHDI_HAVE_KTIME_MS_DELTA ++static inline s64 dahdi_ktime_to_ms(const ktime_t kt) ++{ ++ struct timeval tv = ktime_to_timeval(kt); ++ ++ return (s64) tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC; ++} ++ ++static inline s64 ktime_ms_delta(const ktime_t later, const ktime_t earlier) ++{ ++ return dahdi_ktime_to_ms(ktime_sub(later, earlier)); ++} ++#else ++#undef DAHDI_HAVE_KTIME_MS_DELTA ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) ++ ++/* DAHDI only was using the xxx_clear_bit variants. */ ++#ifndef smp_mb__before_atomic ++#define smp_mb__before_atomic smp_mb__before_clear_bit ++#endif ++ ++#ifndef smp_mb__after_atomic ++#define smp_mb__after_atomic smp_mb__after_clear_bit ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) ++#ifdef RHEL_RELEASE_VERSION ++#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6, 5) ++#ifdef CONFIG_PROC_FS ++#include ++static inline void *PDE_DATA(const struct inode *inode) ++{ ++ return PDE(inode)->data; ++} ++#endif ++#endif ++#else ++#ifdef CONFIG_PROC_FS ++#include ++static inline void *PDE_DATA(const struct inode *inode) ++{ ++ return PDE(inode)->data; ++} ++#endif ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) ++ ++#define KERN_CONT "" ++ ++#endif /* 2.6.31 */ ++#endif /* 3.10.0 */ ++#endif /* 3.16.0 */ ++#endif /* 4.0.0 */ ++#endif /* 4.10.0 */ ++#endif /* 4.11.0 */ ++#endif /* 4.13.0 */ ++#else /* >= 4.15.0 */ ++ ++#ifndef TIMER_DATA_TYPE ++#define TIMER_DATA_TYPE struct timer_list * ++#endif ++ ++#endif /* 4.15.0 */ ++ ++#ifndef dahdi_ktime_equal ++static inline int dahdi_ktime_equal(const ktime_t cmp1, const ktime_t cmp2) ++{ ++ return cmp1 == cmp2; ++} ++#endif ++ ++#ifndef DEFINE_SPINLOCK ++#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED ++#endif ++ ++#ifndef DEFINE_SEMAPHORE ++#define DEFINE_SEMAPHORE(name) \ ++ struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1) ++#endif ++ ++#ifndef DEFINE_MUTEX ++struct mutex { ++ struct semaphore sem; ++}; ++#define DEFINE_MUTEX(name) \ ++ struct mutex name = { \ ++ .sem = __SEMAPHORE_INITIALIZER((name).sem, 1), \ ++ } ++#define mutex_lock(_x) down(&(_x)->sem) ++#define mutex_unlock(_x) up(&(_x)->sem) ++#define mutex_init(_x) sema_init(&(_x)->sem, 1) ++#endif ++ ++#ifndef DEFINE_PCI_DEVICE_TABLE ++#define DEFINE_PCI_DEVICE_TABLE(_x) \ ++ const struct pci_device_id _x[] __devinitdata ++#endif ++ ++#ifndef DMA_BIT_MASK ++#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) ++#endif ++ ++/* WARN_ONCE first showed up in the kernel in 2.6.27 but it may have been ++ * backported. */ ++#ifndef WARN_ONCE ++#define WARN_ONCE(condition, format...) WARN_ON_ONCE(condition) ++#endif ++ ++#define DAHDI_CTL 0 ++#define DAHDI_TRANSCODE 250 ++#define DAHDI_TIMER 253 ++#define DAHDI_CHANNEL 254 ++#define DAHDI_PSEUDO 255 ++ ++/* prink-wrapper macros */ ++ ++#define module_printk(level, fmt, args...) \ ++ printk(level "%s: " fmt, THIS_MODULE->name, ## args) ++ ++#define DAHDI_PRINTK(level, category, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, \ ++ THIS_MODULE->name, ## __VA_ARGS__) ++#define span_printk(level, category, span, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: span-%d: " fmt, #level, \ ++ category, THIS_MODULE->name, (span)->spanno, ## __VA_ARGS__) ++#define chan_printk(level, category, chan, fmt, ...) \ ++ printk(KERN_ ## level "%s%s-%s: chan-%d: " fmt, #level, \ ++ category, THIS_MODULE->name, (chan)->channo, ## __VA_ARGS__) ++#define dahdi_err(fmt, ...) DAHDI_PRINTK(ERR, "", fmt, ## __VA_ARGS__) ++#define span_info(span, fmt, ...) span_printk(INFO, "", span, fmt, \ ++ ## __VA_ARGS__) ++#define span_notice(span, fmt, ...) span_printk(NOTICE, "", span, fmt, \ ++ ## __VA_ARGS__) ++#define span_err(span, fmt, ...) span_printk(ERR, "", span, fmt, \ ++ ## __VA_ARGS__) ++#define chan_notice(chan, fmt, ...) chan_printk(NOTICE, "", chan, fmt, \ ++ ## __VA_ARGS__) ++#define chan_err(chan, fmt, ...) chan_printk(ERR, "", chan, fmt, \ ++ ## __VA_ARGS__) ++ ++#ifndef pr_fmt ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++#endif ++ ++#ifndef pr_err ++#define pr_err(fmt, ...) \ ++ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) ++#endif ++#ifndef pr_warning ++#define pr_warning(fmt, ...) \ ++ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) ++#endif ++#ifndef pr_warn ++#define pr_warn pr_warning ++#endif ++#ifndef pr_notice ++#define pr_notice(fmt, ...) \ ++ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) ++#endif ++#ifndef pr_info ++#define pr_info(fmt, ...) \ ++ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) ++#endif ++ ++/* If KBUILD_MODNAME is not defined in a compilation unit, then the dev_dbg ++ * macro will not work properly. */ ++#ifndef KBUILD_MODNAME ++ #undef dev_dbg ++ #ifdef DEBUG ++ #define dev_dbg dev_info ++ #else ++ #define dev_dbg(...) do { } while (0) ++ #endif ++#endif ++ ++/* The dbg_* ones use a magical variable 'debug' and the user should be ++ * aware of that. ++*/ ++#ifdef DAHDI_PRINK_MACROS_USE_debug ++#ifndef BIT /* added in 2.6.24 */ ++#define BIT(i) (1UL << (i)) ++#endif ++/* Standard debug bit values. Any module may define others. They must ++ * be of the form DAHDI_DBG_* ++ */ ++#define DAHDI_DBG_GENERAL BIT(0) ++#define DAHDI_DBG_ASSIGN BIT(1) ++#define DAHDI_DBG_DEVICES BIT(7) /* instantiation/destruction etc. */ ++#define dahdi_dbg(bits, fmt, ...) \ ++ ((void)((debug & (DAHDI_DBG_ ## bits)) && DAHDI_PRINTK(DEBUG, \ ++ "-" #bits, "%s: " fmt, __func__, ## __VA_ARGS__))) ++#define span_dbg(bits, span, fmt, ...) \ ++ ((void)((debug & (DAHDI_DBG_ ## bits)) && \ ++ span_printk(DEBUG, "-" #bits, span, "%s: " \ ++ fmt, __func__, ## __VA_ARGS__))) ++#define chan_dbg(bits, chan, fmt, ...) \ ++ ((void)((debug & (DAHDI_DBG_ ## bits)) && \ ++ chan_printk(DEBUG, "-" #bits, chan, \ ++ "%s: " fmt, __func__, ## __VA_ARGS__))) ++#define dahdi_dev_dbg(bits, dev, fmt, ...) \ ++ do { if (debug & (DAHDI_DBG_ ## bits)) { \ ++ dev_printk(KERN_DEBUG, dev, \ ++ "DBG-%s(%s): " fmt, #bits, __func__, ## __VA_ARGS__); \ ++ } } while (0) ++ ++#endif /* DAHDI_PRINK_MACROS_USE_debug */ ++ ++#endif /* _DAHDI_KERNEL_H */ +diff -Nru linux-source-4.19/include/linux/dahdi/user.h linux-source-4.19-dahdi/include/linux/dahdi/user.h +--- linux-source-4.19/include/linux/dahdi/user.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/include/linux/dahdi/user.h 2020-10-28 00:17:08.663192245 +0100 +@@ -0,0 +1,1220 @@ ++/* ++ * DAHDI Telephony Interface ++ * ++ * Written by Mark Spencer ++ * Based on previous works, designs, and architectures conceived and ++ * written by Jim Dixon . ++ * ++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony. ++ * Copyright (C) 2001 - 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 Lesser General Public License Version 2.1 as published ++ * by the Free Software Foundation. See the LICENSE.LGPL file ++ * included with this program for more details. ++ * ++ * In addition, when this program is distributed with Asterisk in ++ * any form that would qualify as a 'combined work' or as a ++ * 'derivative work' (but not mere aggregation), you can redistribute ++ * and/or modify the combination under the terms of the license ++ * provided with that copy of Asterisk, instead of the license ++ * terms granted here. ++ */ ++ ++#ifndef _DAHDI_USER_H ++#define _DAHDI_USER_H ++ ++#include ++#include ++#include ++ ++#ifndef ELAST ++#define ELAST 500 ++#endif ++ ++/* Per-span configuration values */ ++#define DAHDI_CONFIG_TXLEVEL 7 /* bits 0-2 are tx level */ ++ ++/* Line configuration */ ++/* These apply to T1 */ ++#define DAHDI_CONFIG_D4 (1 << 4) ++#define DAHDI_CONFIG_ESF (1 << 5) ++#define DAHDI_CONFIG_AMI (1 << 6) ++#define DAHDI_CONFIG_B8ZS (1 << 7) ++/* These apply to E1 */ ++#define DAHDI_CONFIG_CCS (1 << 8) /* CCS (ISDN) instead of CAS (Robbed Bit) */ ++#define DAHDI_CONFIG_HDB3 (1 << 9) /* HDB3 instead of AMI (line coding) */ ++#define DAHDI_CONFIG_CRC4 (1 << 10) /* CRC4 framing */ ++#define DAHDI_CONFIG_NOTOPEN (1 << 16) ++/* These apply to BRI */ ++#define DAHDI_CONFIG_NTTE (1 << 11) /* To enable NT mode, set this bit to 1, for TE this should be 0 */ ++#define DAHDI_CONFIG_TERM (1 << 12) /* To enable Termination resistance set this bit to 1 */ ++ ++/* Signalling types */ ++#define DAHDI_SIG_BROKEN (1 << 31) /* The port is broken and/or failed initialization */ ++ ++#define __DAHDI_SIG_FXO (1 << 12) /* Never use directly */ ++#define __DAHDI_SIG_FXS (1 << 13) /* Never use directly */ ++ ++#define DAHDI_SIG_NONE (0) /* Channel not configured */ ++#define DAHDI_SIG_FXSLS ((1 << 0) | __DAHDI_SIG_FXS) /* FXS, Loopstart */ ++#define DAHDI_SIG_FXSGS ((1 << 1) | __DAHDI_SIG_FXS) /* FXS, Groundstart */ ++#define DAHDI_SIG_FXSKS ((1 << 2) | __DAHDI_SIG_FXS) /* FXS, Kewlstart */ ++ ++#define DAHDI_SIG_FXOLS ((1 << 3) | __DAHDI_SIG_FXO) /* FXO, Loopstart */ ++#define DAHDI_SIG_FXOGS ((1 << 4) | __DAHDI_SIG_FXO) /* FXO, Groupstart */ ++#define DAHDI_SIG_FXOKS ((1 << 5) | __DAHDI_SIG_FXO) /* FXO, Kewlstart */ ++ ++#define DAHDI_SIG_EM (1 << 6) /* Ear & Mouth (E&M) */ ++ ++/* The following are all variations on clear channel */ ++ ++#define __DAHDI_SIG_DACS (1 << 16) ++ ++#define DAHDI_SIG_CLEAR (1 << 7) /* Clear channel */ ++#define DAHDI_SIG_HDLCRAW ((1 << 8) | DAHDI_SIG_CLEAR) /* Raw unchecked HDLC */ ++#define DAHDI_SIG_HDLCFCS ((1 << 9) | DAHDI_SIG_HDLCRAW) /* HDLC with FCS calculation */ ++#define DAHDI_SIG_HDLCNET ((1 << 10) | DAHDI_SIG_HDLCFCS) /* HDLC Network */ ++#define DAHDI_SIG_SLAVE (1 << 11) /* Slave to another channel */ ++#define DAHDI_SIG_SF (1 << 14) /* Single Freq. tone only, no sig bits */ ++#define DAHDI_SIG_CAS (1 << 15) /* Just get bits */ ++#define DAHDI_SIG_DACS (__DAHDI_SIG_DACS | DAHDI_SIG_CLEAR) /* Cross connect */ ++#define DAHDI_SIG_EM_E1 (1 << 17) /* E1 E&M Variation */ ++#define DAHDI_SIG_DACS_RBS ((1 << 18) | __DAHDI_SIG_DACS) /* Cross connect w/ RBS */ ++#define DAHDI_SIG_HARDHDLC ((1 << 19) | DAHDI_SIG_CLEAR) ++#define DAHDI_SIG_MTP2 ((1 << 20) | DAHDI_SIG_HDLCFCS) /* MTP2 support Need HDLC bitstuff and FCS calcuation too */ ++ ++/* tone flag values */ ++#define DAHDI_REVERSE_RXTONE 1 /* reverse polarity rx tone logic */ ++#define DAHDI_REVERSE_TXTONE 2 /* reverse polarity tx tone logic */ ++ ++#define DAHDI_ABIT (1 << 3) ++#define DAHDI_BBIT (1 << 2) ++#define DAHDI_CBIT (1 << 1) ++#define DAHDI_DBIT (1 << 0) ++ ++#define DAHDI_BITS_ABCD (DAHDI_ABIT | DAHDI_BBIT | DAHDI_CBIT | DAHDI_DBIT) ++#define DAHDI_BITS_ABD (DAHDI_ABIT | DAHDI_BBIT | DAHDI_DBIT) ++#define DAHDI_BITS_ACD (DAHDI_ABIT | DAHDI_CBIT | DAHDI_DBIT) ++#define DAHDI_BITS_BCD (DAHDI_BBIT | DAHDI_CBIT | DAHDI_DBIT) ++#define DAHDI_BITS_AC (DAHDI_ABIT | DAHDI_CBIT) ++#define DAHDI_BITS_BD (DAHDI_BBIT | DAHDI_DBIT) ++ ++#define DAHDI_MAJOR 196 ++ ++#define DAHDI_MAX_BLOCKSIZE 8192 ++#define DAHDI_DEFAULT_NUM_BUFS 2 ++#define DAHDI_MAX_NUM_BUFS 32 ++#define DAHDI_MAX_BUF_SPACE 32768 ++ ++#define DAHDI_DEFAULT_BLOCKSIZE 1024 ++#define DAHDI_DEFAULT_MTR_MRU 2048 ++ ++/*! Define the default network block size */ ++#define DAHDI_DEFAULT_MTU_MRU 2048 ++ ++#define DAHDI_POLICY_IMMEDIATE 0 /* Start play/record immediately */ ++#define DAHDI_POLICY_WHEN_FULL 1 /* Start play/record when buffer is full */ ++#define DAHDI_POLICY_HALF_FULL 2 /* Start play/record when buffer is half full. ++ Note -- This policy only works on tx buffers */ ++ ++#define DAHDI_GET_PARAMS_RETURN_MASTER 0x40000000 ++ ++#define DAHDI_TONE_ZONE_MAX 128 ++ ++#define DAHDI_TONE_ZONE_DEFAULT -1 /* To restore default */ ++ ++#define DAHDI_TONE_STOP -1 ++#define DAHDI_TONE_DIALTONE 0 ++#define DAHDI_TONE_BUSY 1 ++#define DAHDI_TONE_RINGTONE 2 ++#define DAHDI_TONE_CONGESTION 3 ++#define DAHDI_TONE_CALLWAIT 4 ++#define DAHDI_TONE_DIALRECALL 5 ++#define DAHDI_TONE_RECORDTONE 6 ++#define DAHDI_TONE_INFO 7 ++#define DAHDI_TONE_CUST1 8 ++#define DAHDI_TONE_CUST2 9 ++#define DAHDI_TONE_STUTTER 10 ++#define DAHDI_TONE_MAX 16 ++ ++#define DAHDI_TONE_DTMF_BASE 64 ++#define DAHDI_TONE_MFR1_BASE 80 ++#define DAHDI_TONE_MFR2_FWD_BASE 96 ++#define DAHDI_TONE_MFR2_REV_BASE 112 ++ ++enum { ++ DAHDI_TONE_DTMF_0 = DAHDI_TONE_DTMF_BASE, ++ DAHDI_TONE_DTMF_1, ++ DAHDI_TONE_DTMF_2, ++ DAHDI_TONE_DTMF_3, ++ DAHDI_TONE_DTMF_4, ++ DAHDI_TONE_DTMF_5, ++ DAHDI_TONE_DTMF_6, ++ DAHDI_TONE_DTMF_7, ++ DAHDI_TONE_DTMF_8, ++ DAHDI_TONE_DTMF_9, ++ DAHDI_TONE_DTMF_s, ++ DAHDI_TONE_DTMF_p, ++ DAHDI_TONE_DTMF_A, ++ DAHDI_TONE_DTMF_B, ++ DAHDI_TONE_DTMF_C, ++ DAHDI_TONE_DTMF_D ++}; ++ ++#define DAHDI_TONE_DTMF_MAX DAHDI_TONE_DTMF_D ++ ++enum { ++ DAHDI_TONE_MFR1_0 = DAHDI_TONE_MFR1_BASE, ++ DAHDI_TONE_MFR1_1, ++ DAHDI_TONE_MFR1_2, ++ DAHDI_TONE_MFR1_3, ++ DAHDI_TONE_MFR1_4, ++ DAHDI_TONE_MFR1_5, ++ DAHDI_TONE_MFR1_6, ++ DAHDI_TONE_MFR1_7, ++ DAHDI_TONE_MFR1_8, ++ DAHDI_TONE_MFR1_9, ++ DAHDI_TONE_MFR1_KP, ++ DAHDI_TONE_MFR1_ST, ++ DAHDI_TONE_MFR1_STP, ++ DAHDI_TONE_MFR1_ST2P, ++ DAHDI_TONE_MFR1_ST3P, ++}; ++ ++#define DAHDI_TONE_MFR1_MAX DAHDI_TONE_MFR1_ST3P ++ ++enum { ++ DAHDI_TONE_MFR2_FWD_1 = DAHDI_TONE_MFR2_FWD_BASE, ++ DAHDI_TONE_MFR2_FWD_2, ++ DAHDI_TONE_MFR2_FWD_3, ++ DAHDI_TONE_MFR2_FWD_4, ++ DAHDI_TONE_MFR2_FWD_5, ++ DAHDI_TONE_MFR2_FWD_6, ++ DAHDI_TONE_MFR2_FWD_7, ++ DAHDI_TONE_MFR2_FWD_8, ++ DAHDI_TONE_MFR2_FWD_9, ++ DAHDI_TONE_MFR2_FWD_10, ++ DAHDI_TONE_MFR2_FWD_11, ++ DAHDI_TONE_MFR2_FWD_12, ++ DAHDI_TONE_MFR2_FWD_13, ++ DAHDI_TONE_MFR2_FWD_14, ++ DAHDI_TONE_MFR2_FWD_15, ++}; ++ ++#define DAHDI_TONE_MFR2_FWD_MAX DAHDI_TONE_MFR2_FWD_15 ++ ++enum { ++ DAHDI_TONE_MFR2_REV_1 = DAHDI_TONE_MFR2_REV_BASE, ++ DAHDI_TONE_MFR2_REV_2, ++ DAHDI_TONE_MFR2_REV_3, ++ DAHDI_TONE_MFR2_REV_4, ++ DAHDI_TONE_MFR2_REV_5, ++ DAHDI_TONE_MFR2_REV_6, ++ DAHDI_TONE_MFR2_REV_7, ++ DAHDI_TONE_MFR2_REV_8, ++ DAHDI_TONE_MFR2_REV_9, ++ DAHDI_TONE_MFR2_REV_10, ++ DAHDI_TONE_MFR2_REV_11, ++ DAHDI_TONE_MFR2_REV_12, ++ DAHDI_TONE_MFR2_REV_13, ++ DAHDI_TONE_MFR2_REV_14, ++ DAHDI_TONE_MFR2_REV_15, ++}; ++ ++#define DAHDI_TONE_MFR2_REV_MAX DAHDI_TONE_MFR2_REV_15 ++ ++#define DAHDI_LAW_DEFAULT 0 /* Default law for span */ ++#define DAHDI_LAW_MULAW 1 /* Mu-law */ ++#define DAHDI_LAW_ALAW 2 /* A-law */ ++ ++#define DAHDI_DIAL_OP_APPEND 1 ++#define DAHDI_DIAL_OP_REPLACE 2 ++#define DAHDI_DIAL_OP_CANCEL 3 ++ ++#define DAHDI_MAX_CADENCE 16 ++ ++#define DAHDI_TONEDETECT_ON (1 << 0) /* Detect tones */ ++#define DAHDI_TONEDETECT_MUTE (1 << 1) /* Mute audio in received channel */ ++ ++/* Define the max # of outgoing DTMF, MFR1 or MFR2 digits to queue */ ++#define DAHDI_MAX_DTMF_BUF 256 ++ ++#define DAHDI_MAX_EVENTSIZE 64 /* 64 events max in buffer */ ++ ++/* Value for DAHDI_HOOK, set to ON hook */ ++#define DAHDI_ONHOOK 0 ++ ++/* Value for DAHDI_HOOK, set to OFF hook */ ++#define DAHDI_OFFHOOK 1 ++ ++/* Value for DAHDI_HOOK, wink (off hook momentarily) */ ++#define DAHDI_WINK 2 ++ ++/* Value for DAHDI_HOOK, flash (on hook momentarily) */ ++#define DAHDI_FLASH 3 ++ ++/* Value for DAHDI_HOOK, start line */ ++#define DAHDI_START 4 ++ ++/* Value for DAHDI_HOOK, ring line (same as start line) */ ++#define DAHDI_RING 5 ++ ++/* Value for DAHDI_HOOK, turn ringer off */ ++#define DAHDI_RINGOFF 6 ++ ++/* Flush and stop the read (input) process */ ++#define DAHDI_FLUSH_READ 1 ++ ++/* Flush and stop the write (output) process */ ++#define DAHDI_FLUSH_WRITE 2 ++ ++/* Flush and stop both (input and output) processes */ ++#define DAHDI_FLUSH_BOTH (DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE) ++ ++/* Flush the event queue */ ++#define DAHDI_FLUSH_EVENT 4 ++ ++/* Flush everything */ ++#define DAHDI_FLUSH_ALL (DAHDI_FLUSH_BOTH | DAHDI_FLUSH_EVENT) ++ ++#define DAHDI_MAX_SPANS 128 /* Max, 128 spans */ ++#define DAHDI_MAX_CHANNELS 1024 /* Max, 1024 channels */ ++#define DAHDI_MAX_CONF 1024 /* Max, 1024 conferences */ ++ ++/* Conference modes */ ++#define DAHDI_CONF_MODE_MASK 0xFF /* mask for modes */ ++#define DAHDI_CONF_NORMAL 0 /* normal mode */ ++#define DAHDI_CONF_MONITOR 1 /* monitor mode (rx of other chan) */ ++#define DAHDI_CONF_MONITORTX 2 /* monitor mode (tx of other chan) */ ++#define DAHDI_CONF_MONITORBOTH 3 /* monitor mode (rx & tx of other chan) */ ++#define DAHDI_CONF_CONF 4 /* conference mode */ ++#define DAHDI_CONF_CONFANN 5 /* conference announce mode */ ++#define DAHDI_CONF_CONFMON 6 /* conference monitor mode */ ++#define DAHDI_CONF_CONFANNMON 7 /* conference announce/monitor mode */ ++#define DAHDI_CONF_REALANDPSEUDO 8 /* real and pseudo port both on conf */ ++#define DAHDI_CONF_DIGITALMON 9 /* Do not decode or interpret */ ++#define DAHDI_CONF_MONITOR_RX_PREECHO 10 /* monitor mode (rx of other chan) - before echo can is done */ ++#define DAHDI_CONF_MONITOR_TX_PREECHO 11 /* monitor mode (tx of other chan) - before echo can is done */ ++#define DAHDI_CONF_MONITORBOTH_PREECHO 12 /* monitor mode (rx & tx of other chan) - before echo can is done */ ++#define DAHDI_CONF_FLAG_MASK 0xFF00 /* mask for flags */ ++#define DAHDI_CONF_LISTENER 0x100 /* is a listener on the conference */ ++#define DAHDI_CONF_TALKER 0x200 /* is a talker on the conference */ ++#define DAHDI_CONF_PSEUDO_LISTENER 0x400 /* pseudo is a listener on the conference */ ++#define DAHDI_CONF_PSEUDO_TALKER 0x800 /* pseudo is a talker on the conference */ ++ ++/* Alarm Condition bits */ ++#define DAHDI_ALARM_NONE 0 /* No alarms */ ++#define DAHDI_ALARM_RECOVER (1 << 0) /* Recovering from alarm */ ++#define DAHDI_ALARM_LOOPBACK (1 << 1) /* In loopback */ ++#define DAHDI_ALARM_YELLOW (1 << 2) /* Yellow Alarm */ ++#define DAHDI_ALARM_RED (1 << 3) /* Red Alarm */ ++#define DAHDI_ALARM_BLUE (1 << 4) /* Blue Alarm */ ++#define DAHDI_ALARM_NOTOPEN (1 << 5) ++/* Verbose alarm states (upper byte) */ ++#define DAHDI_ALARM_LOS (1 << 8) /* Loss of Signal */ ++#define DAHDI_ALARM_LFA (1 << 9) /* Loss of Frame Alignment */ ++#define DAHDI_ALARM_LMFA (1 << 10)/* Loss of Multi-Frame Align */ ++ ++/* Maintenance modes */ ++#define DAHDI_MAINT_NONE 0 /* Normal Mode */ ++#define DAHDI_MAINT_LOCALLOOP 1 /* Local Loopback */ ++#define DAHDI_MAINT_REMOTELOOP 2 /* Remote Loopback */ ++#define DAHDI_MAINT_NETWORKLINELOOP 2 /* Remote Loopback */ ++#define DAHDI_MAINT_LOOPUP 3 /* send loopup code */ ++#define DAHDI_MAINT_LOOPDOWN 4 /* send loopdown code */ ++#define DAHDI_MAINT_FAS_DEFECT 6 /* insert a FAS defect */ ++#define DAHDI_MAINT_MULTI_DEFECT 7 /* insert a Multiframe defect */ ++#define DAHDI_MAINT_CRC_DEFECT 8 /* insert a FAS defect */ ++#define DAHDI_MAINT_CAS_DEFECT 9 /* insert a FAS defect */ ++#define DAHDI_MAINT_PRBS_DEFECT 10 /* insert a FAS defect */ ++#define DAHDI_MAINT_BIPOLAR_DEFECT 11 /* insert a FAS defect */ ++#define DAHDI_MAINT_PRBS 12 /* enable the PRBS gen/mon */ ++#define DAHDI_MAINT_NETWORKPAYLOADLOOP 13 /* Remote Loopback */ ++#define DAHDI_RESET_COUNTERS 14 /* Clear the error counters */ ++#define DAHDI_MAINT_ALARM_SIM 15 /* Simulate alarms */ ++ ++/* Flag Value for IOMUX, read avail */ ++#define DAHDI_IOMUX_READ 1 ++ ++/* Flag Value for IOMUX, write avail */ ++#define DAHDI_IOMUX_WRITE 2 ++ ++/* Flag Value for IOMUX, write done */ ++#define DAHDI_IOMUX_WRITEEMPTY 4 ++ ++/* Flag Value for IOMUX, signalling event avail */ ++#define DAHDI_IOMUX_SIGEVENT 8 ++ ++/* Flag Value for IOMUX, Do Not Wait if nothing to report */ ++#define DAHDI_IOMUX_NOWAIT 0x100 ++ ++/* Ret. Value for GET/WAIT Event, no event */ ++#define DAHDI_EVENT_NONE 0 ++ ++/* Ret. Value for GET/WAIT Event, Went Onhook */ ++#define DAHDI_EVENT_ONHOOK 1 ++ ++/* Ret. Value for GET/WAIT Event, Went Offhook or got Ring */ ++#define DAHDI_EVENT_RINGOFFHOOK 2 ++ ++/* Ret. Value for GET/WAIT Event, Got Wink or Flash */ ++#define DAHDI_EVENT_WINKFLASH 3 ++ ++/* Ret. Value for GET/WAIT Event, Got Alarm */ ++#define DAHDI_EVENT_ALARM 4 ++ ++/* Ret. Value for GET/WAIT Event, Got No Alarm (after alarm) */ ++#define DAHDI_EVENT_NOALARM 5 ++ ++/* Ret. Value for GET/WAIT Event, HDLC Abort frame */ ++#define DAHDI_EVENT_ABORT 6 ++ ++/* Ret. Value for GET/WAIT Event, HDLC Frame overrun */ ++#define DAHDI_EVENT_OVERRUN 7 ++ ++/* Ret. Value for GET/WAIT Event, Bad FCS */ ++#define DAHDI_EVENT_BADFCS 8 ++ ++/* Ret. Value for dial complete */ ++#define DAHDI_EVENT_DIALCOMPLETE 9 ++ ++/* Ret Value for ringer going on */ ++#define DAHDI_EVENT_RINGERON 10 ++ ++/* Ret Value for ringer going off */ ++#define DAHDI_EVENT_RINGEROFF 11 ++ ++/* Ret Value for hook change complete */ ++#define DAHDI_EVENT_HOOKCOMPLETE 12 ++ ++/* Ret Value for bits changing on a CAS / User channel */ ++#define DAHDI_EVENT_BITSCHANGED 13 ++ ++/* Ret value for the beginning of a pulse coming on its way */ ++#define DAHDI_EVENT_PULSE_START 14 ++ ++/* Timer event -- timer expired */ ++#define DAHDI_EVENT_TIMER_EXPIRED 15 ++ ++/* Timer event -- ping ready */ ++#define DAHDI_EVENT_TIMER_PING 16 ++ ++/* Polarity reversal event */ ++#define DAHDI_EVENT_POLARITY 17 ++ ++/* Ring Begin event */ ++#define DAHDI_EVENT_RINGBEGIN 18 ++ ++/* Echo can disabled event */ ++#define DAHDI_EVENT_EC_DISABLED 19 ++ ++/* Channel was disconnected. Hint user to close channel */ ++#define DAHDI_EVENT_REMOVED 20 ++ ++/* A neon MWI pulse was detected */ ++#define DAHDI_EVENT_NEONMWI_ACTIVE 21 ++ ++/* No neon MWI pulses were detected over some period of time */ ++#define DAHDI_EVENT_NEONMWI_INACTIVE 22 ++ ++/* A CED tone was detected on the channel in the transmit direction */ ++#define DAHDI_EVENT_TX_CED_DETECTED 23 ++ ++/* A CED tone was detected on the channel in the receive direction */ ++#define DAHDI_EVENT_RX_CED_DETECTED 24 ++ ++/* A CNG tone was detected on the channel in the transmit direction */ ++#define DAHDI_EVENT_TX_CNG_DETECTED 25 ++ ++/* A CNG tone was detected on the channel in the receive direction */ ++#define DAHDI_EVENT_RX_CNG_DETECTED 26 ++ ++/* The echo canceler's NLP (only) was disabled */ ++#define DAHDI_EVENT_EC_NLP_DISABLED 27 ++ ++/* The echo canceler's NLP (only) was enabled */ ++#define DAHDI_EVENT_EC_NLP_ENABLED 28 ++ ++/* The channel's read buffer encountered an overrun condition */ ++#define DAHDI_EVENT_READ_OVERRUN 29 ++ ++/* The channel's write buffer encountered an underrun condition */ ++#define DAHDI_EVENT_WRITE_UNDERRUN 30 ++ ++#define DAHDI_EVENT_PULSEDIGIT (1 << 16) /* This is OR'd with the digit received */ ++#define DAHDI_EVENT_DTMFDOWN (1 << 17) /* Ditto for DTMF key down event */ ++#define DAHDI_EVENT_DTMFUP (1 << 18) /* Ditto for DTMF key up event */ ++ ++/* Transcoder related definitions */ ++ ++struct dahdi_transcoder_formats { ++ __u32 srcfmt; ++ __u32 dstfmt; ++}; ++struct dahdi_transcoder_info { ++ __u32 tcnum; ++ char name[80]; ++ __u32 numchannels; ++ __u32 dstfmts; ++ __u32 srcfmts; ++}; ++ ++#define DAHDI_MAX_ECHOCANPARAMS 8 ++ ++/* ioctl definitions */ ++#define DAHDI_CODE 0xDA ++ ++/* ++ * Get/Set Transfer Block Size. ++ */ ++#define DAHDI_GET_BLOCKSIZE _IOR(DAHDI_CODE, 1, int) ++#define DAHDI_SET_BLOCKSIZE _IOW(DAHDI_CODE, 1, int) ++ ++/* ++ * Flush Buffer(s) and stop I/O ++ */ ++#define DAHDI_FLUSH _IOW(DAHDI_CODE, 3, int) ++ ++/* ++ * Wait for Write to Finish ++ */ ++#define DAHDI_SYNC _IO(DAHDI_CODE, 4) ++ ++/* ++ * Get/set channel parameters ++ */ ++ ++struct dahdi_params { ++ int channo; /* Channel number */ ++ int spanno; /* Span itself */ ++ int chanpos; /* Channel number in span */ ++ int sigtype; /* read-only */ ++ int sigcap; /* read-only */ ++ int rxisoffhook; /* read-only */ ++ int rxbits; /* read-only */ ++ int txbits; /* read-only */ ++ int txhooksig; /* read-only */ ++ int rxhooksig; /* read-only */ ++ int curlaw; /* read-only -- one of DAHDI_LAW_MULAW or DAHDI_LAW_ALAW */ ++ int idlebits; /* read-only -- What is considered the idle state */ ++ char name[40]; /* Name of channel */ ++ int prewinktime; ++ int preflashtime; ++ int winktime; ++ int flashtime; ++ int starttime; ++ int rxwinktime; ++ int rxflashtime; ++ int debouncetime; ++ int pulsebreaktime; ++ int pulsemaketime; ++ int pulseaftertime; ++ __u32 chan_alarms; /* alarms on this channel */ ++}; ++ ++#define DAHDI_GET_PARAMS_V1 _IOR(DAHDI_CODE, 5, struct dahdi_params) ++#define DAHDI_GET_PARAMS _IOWR(DAHDI_CODE, 5, struct dahdi_params) ++#define DAHDI_SET_PARAMS _IOW(DAHDI_CODE, 5, struct dahdi_params) ++ ++/* ++ * Set Hookswitch Status ++ */ ++#define DAHDI_HOOK _IOW(DAHDI_CODE, 7, int) ++ ++/* ++ * Get Signalling Event ++ */ ++#define DAHDI_GETEVENT _IOR(DAHDI_CODE, 8, int) ++ ++/* ++ * Wait for something to happen (IO Mux) ++ */ ++#define DAHDI_IOMUX _IOWR(DAHDI_CODE, 9, int) ++ ++/* ++ * Get Span Status ++ */ ++struct dahdi_spaninfo { ++ int spanno; /* span number */ ++ char name[20]; /* Name */ ++ char desc[40]; /* Description */ ++ int alarms; /* alarms status */ ++ int txlevel; /* what TX level is set to */ ++ int rxlevel; /* current RX level */ ++ ++ int bpvcount; /* current BPV count */ ++ int crc4count; /* current CRC4 error count */ ++ int ebitcount; /* current E-bit error count */ ++ int fascount; /* current FAS error count */ ++ __u32 fecount; /* Framing error counter */ ++ __u32 cvcount; /* Coding violations counter */ ++ __u32 becount; /* current bit error count */ ++ __u32 prbs; /* current PRBS detected pattern */ ++ __u32 errsec; /* errored seconds */ ++ ++ int irqmisses; /* current IRQ misses */ ++ int syncsrc; /* span # of current sync source, ++ or 0 for free run */ ++ int numchans; /* number of configured channels on this span */ ++ int totalchans; /* total number of channels on the span */ ++ int totalspans; /* total number of spans in entire system */ ++ int lbo; /* line build out */ ++ int lineconfig; /* framing/coding */ ++ char lboname[40]; /* line build out in text form */ ++ char location[40]; /* span's device location in system */ ++ char manufacturer[40]; /* manufacturer of span's device */ ++ char devicetype[40]; /* span's device type */ ++ int irq; /* span's device IRQ */ ++ int linecompat; /* span global signaling or 0 for ++ analog spans.*/ ++ char spantype[6]; /* type of span in text form */ ++} __attribute__((packed)); ++ ++struct dahdi_spaninfo_v1 { ++ int spanno; /* span number */ ++ char name[20]; /* Name */ ++ char desc[40]; /* Description */ ++ int alarms; /* alarms status */ ++ int txlevel; /* what TX level is set to */ ++ int rxlevel; /* current RX level */ ++ int bpvcount; /* current BPV count */ ++ int crc4count; /* current CRC4 error count */ ++ int ebitcount; /* current E-bit error count */ ++ int fascount; /* current FAS error count */ ++ int irqmisses; /* current IRQ misses */ ++ int syncsrc; /* span # of current sync source, or 0 for free run */ ++ int numchans; /* number of configured channels on this span */ ++ int totalchans; /* total number of channels on the span */ ++ int totalspans; /* total number of spans in entire system */ ++ int lbo; /* line build out */ ++ int lineconfig; /* framing/coding */ ++ char lboname[40]; /* line build out in text form */ ++ char location[40]; /* span's device location in system */ ++ char manufacturer[40]; /* manufacturer of span's device */ ++ char devicetype[40]; /* span's device type */ ++ int irq; /* span's device IRQ */ ++ int linecompat; /* signaling modes possible on this span */ ++ char spantype[6]; /* type of span in text form */ ++}; ++#define DAHDI_SPANSTAT _IOWR(DAHDI_CODE, 10, struct dahdi_spaninfo) ++#define DAHDI_SPANSTAT_V1 _IOWR(DAHDI_CODE, 10, struct dahdi_spaninfo_v1) ++ ++/* ++ * Set Maintenance Mode ++ */ ++struct dahdi_maintinfo { ++ int spanno; /* span number */ ++ int command; /* command */ ++}; ++ ++#define DAHDI_MAINT _IOW(DAHDI_CODE, 11, struct dahdi_maintinfo) ++ ++/* ++ * Get/Set Conference Mode ++ */ ++struct dahdi_confinfo { ++ int chan; /* channel number, 0 for current */ ++ int confno; /* conference number */ ++ int confmode; /* conferencing mode */ ++}; ++ ++#define DAHDI_GETCONF_V1 _IOR(DAHDI_CODE, 12, struct dahdi_confinfo) ++#define DAHDI_GETCONF _IOWR(DAHDI_CODE, 12, struct dahdi_confinfo) ++ ++#define DAHDI_SETCONF_V1 _IOW(DAHDI_CODE, 12, struct dahdi_confinfo) ++#define DAHDI_SETCONF _IOWR(DAHDI_CODE, 13, struct dahdi_confinfo) ++ ++/* ++ * Setup or Remove Conference Link ++ */ ++#define DAHDI_CONFLINK _IOW(DAHDI_CODE, 14, struct dahdi_confinfo) ++ ++/* ++ * Display Conference Diagnostic Information on Console ++ */ ++#define DAHDI_CONFDIAG_V1 _IOR(DAHDI_CODE, 15, int) ++#define DAHDI_CONFDIAG _IOW(DAHDI_CODE, 15, int) ++ ++/* ++ * Get/Set Channel audio gains ++ */ ++struct dahdi_gains { ++ int chan; /* channel number, 0 for current */ ++ unsigned char rxgain[256]; /* Receive gain table */ ++ unsigned char txgain[256]; /* Transmit gain table */ ++}; ++ ++#define DAHDI_GETGAINS_V1 _IOR(DAHDI_CODE, 16, struct dahdi_gains) ++#define DAHDI_GETGAINS _IOWR(DAHDI_CODE, 16, struct dahdi_gains) ++#define DAHDI_SETGAINS _IOW(DAHDI_CODE, 16, struct dahdi_gains) ++ ++/* ++ * Set Line (T1) Configurations ++ */ ++struct dahdi_lineconfig { ++ int span; /* Which span number (0 to use name) */ ++ char name[20]; /* Name of span to use */ ++ int lbo; /* line build-outs */ ++ int lineconfig; /* line config parameters (framing, coding) */ ++ int sync; /* what level of sync source we are */ ++}; ++ ++#define DAHDI_SPANCONFIG _IOW(DAHDI_CODE, 18, struct dahdi_lineconfig) ++ ++/* ++ * Set Channel Configuration ++ */ ++struct dahdi_chanconfig { ++ int chan; /* Channel we're applying this to (0 to use name) */ ++ char name[40]; /* Name of channel to use */ ++ int sigtype; /* Signal type */ ++ int deflaw; /* Default law (DAHDI_LAW_DEFAULT, DAHDI_LAW_MULAW, or DAHDI_LAW_ALAW) */ ++ int master; /* Master channel if sigtype is DAHDI_SLAVE */ ++ int idlebits; /* Idle bits (if this is a CAS channel) or ++ channel to monitor (if this is DACS channel) */ ++ char netdev_name[16];/* name for the hdlc network device*/ ++}; ++ ++#define DAHDI_CHANCONFIG _IOW(DAHDI_CODE, 19, struct dahdi_chanconfig) ++ ++/* ++ * Set Conference to mute mode ++ */ ++#define DAHDI_CONFMUTE _IOW(DAHDI_CODE, 20, int) ++ ++/* ++ * Send a particular tone (see DAHDI_TONE_*) ++ */ ++#define DAHDI_SENDTONE _IOW(DAHDI_CODE, 21, int) ++ ++/* ++ * Get/Set your region for tones ++ */ ++#define DAHDI_GETTONEZONE _IOR(DAHDI_CODE, 22, int) ++#define DAHDI_SETTONEZONE _IOW(DAHDI_CODE, 22, int) ++ ++/* ++ * Master unit only -- set default zone (see DAHDI_TONE_ZONE_*) ++ */ ++#define DAHDI_DEFAULTZONE _IOW(DAHDI_CODE, 24, int) ++ ++/* ++ * Load a tone zone from a dahdi_tone_def_header ++ */ ++struct dahdi_tone_def { ++ int tone; /* See DAHDI_TONE_* */ ++ int next; /* What the next position in the cadence is ++ (They're numbered by the order the appear here) */ ++ int samples; /* How many samples to play for this cadence */ ++ int shift; /* How much to scale down the volume (2 is nice) */ ++ ++ /* Now come the constants we need to make tones */ ++ ++ /* ++ Calculate the next 6 factors using the following equations: ++ l = , f1 = , f2 = ++ gain = pow(10.0, (l - 3.14) / 20.0) * 65536.0 / 2.0; ++ ++ // Frequency factor 1 ++ fac_1 = 2.0 * cos(2.0 * M_PI * (f1/8000.0)) * 32768.0; ++ // Last previous two samples ++ init_v2_1 = sin(-4.0 * M_PI * (f1/8000.0)) * gain; ++ init_v3_1 = sin(-2.0 * M_PI * (f1/8000.0)) * gain; ++ ++ // Frequency factor 2 ++ fac_2 = 2.0 * cos(2.0 * M_PI * (f2/8000.0)) * 32768.0; ++ // Last previous two samples ++ init_v2_2 = sin(-4.0 * M_PI * (f2/8000.0)) * gain; ++ init_v3_2 = sin(-2.0 * M_PI * (f2/8000.0)) * gain; ++ */ ++ int fac1; ++ int init_v2_1; ++ int init_v3_1; ++ int fac2; ++ int init_v2_2; ++ int init_v3_2; ++ int modulate; ++}; ++ ++struct dahdi_tone_def_header { ++ int count; /* How many samples follow */ ++ int zone; /* Which zone we are loading */ ++ int ringcadence[DAHDI_MAX_CADENCE]; /* Ring cadence in ms (0=on, 1=off, ends with 0 value) */ ++ char name[40]; /* Informational name of zone */ ++ /* immediately follow this structure with dahdi_tone_def structures */ ++ struct dahdi_tone_def tones[0]; ++}; ++ ++#define DAHDI_LOADZONE _IOW(DAHDI_CODE, 25, struct dahdi_tone_def_header) ++ ++/* ++ * Free a tone zone ++ */ ++#define DAHDI_FREEZONE _IOW(DAHDI_CODE, 26, int) ++ ++/* ++ * Get/Set buffer policy ++ */ ++struct dahdi_bufferinfo { ++ int txbufpolicy; /* Policy for handling receive buffers */ ++ int rxbufpolicy; /* Policy for handling receive buffers */ ++ int numbufs; /* How many buffers to use */ ++ int bufsize; /* How big each buffer is */ ++ int readbufs; /* How many read buffers are full (read-only) */ ++ int writebufs; /* How many write buffers are full (read-only) */ ++}; ++ ++#define DAHDI_GET_BUFINFO _IOR(DAHDI_CODE, 27, struct dahdi_bufferinfo) ++#define DAHDI_SET_BUFINFO _IOW(DAHDI_CODE, 27, struct dahdi_bufferinfo) ++ ++/* ++ * Get/Set dialing parameters ++ */ ++struct dahdi_dialparams { ++ int mfv1_tonelen; /* MF R1 tone length for digits */ ++ int dtmf_tonelen; /* DTMF tone length */ ++ int mfr2_tonelen; /* MF R2 tone length */ ++ int reserved[3]; /* Reserved for future expansion -- always set to 0 */ ++}; ++ ++#define DAHDI_GET_DIALPARAMS _IOR(DAHDI_CODE, 29, struct dahdi_dialparams) ++#define DAHDI_SET_DIALPARAMS _IOW(DAHDI_CODE, 29, struct dahdi_dialparams) ++ ++/* ++ * Append, replace, or cancel a dial string ++ */ ++struct dahdi_dialoperation { ++ int op; ++ char dialstr[DAHDI_MAX_DTMF_BUF]; ++}; ++ ++#define DAHDI_DIAL _IOW(DAHDI_CODE, 31, struct dahdi_dialoperation) ++ ++/* ++ * Set a clear channel into audio mode ++ */ ++#define DAHDI_AUDIOMODE _IOW(DAHDI_CODE, 32, int) ++ ++/* ++ * Enable or disable echo cancellation on a channel ++ * ++ * For ECHOCANCEL: ++ * The number is zero to disable echo cancellation and non-zero ++ * to enable echo cancellation. If the number is between 32 ++ * and 1024, it will also set the number of taps in the echo canceller ++ * ++ * For ECHOCANCEL_PARAMS: ++ * The structure contains parameters that should be passed to the ++ * echo canceler instance for the selected channel. ++ */ ++#define DAHDI_ECHOCANCEL _IOW(DAHDI_CODE, 33, int) ++ ++struct dahdi_echocanparam { ++ char name[16]; ++ __s32 value; ++}; ++ ++struct dahdi_echocanparams { ++ /* 8 taps per millisecond */ ++ __u32 tap_length; ++ /* number of parameters supplied */ ++ __u32 param_count; ++ /* immediately follow this structure with dahdi_echocanparam structures */ ++ struct dahdi_echocanparam params[0]; ++}; ++ ++#define DAHDI_ECHOCANCEL_PARAMS _IOW(DAHDI_CODE, 33, struct dahdi_echocanparams) ++ ++/* ++ * Return a channel's channel number ++ */ ++#define DAHDI_CHANNO _IOR(DAHDI_CODE, 34, int) ++ ++/* ++ * Return a flag indicating whether channel is currently dialing ++ */ ++#define DAHDI_DIALING _IOR(DAHDI_CODE, 35, int) ++ ++/* ++ * Set a clear channel into HDLC w/out FCS checking/calculation mode ++ */ ++#define DAHDI_HDLCRAWMODE _IOW(DAHDI_CODE, 36, int) ++ ++/* ++ * Set a clear channel into HDLC w/ FCS mode ++ */ ++#define DAHDI_HDLCFCSMODE _IOW(DAHDI_CODE, 37, int) ++ ++/* ++ * Specify a channel on generic channel selector - must be done before ++ * performing any other ioctls ++ */ ++#define DAHDI_SPECIFY _IOW(DAHDI_CODE, 38, int) ++ ++/* ++ * Temporarily set the law on a channel to ++ * DAHDI_LAW_DEFAULT, DAHDI_LAW_ALAW, or DAHDI_LAW_MULAW. Is reset on close. ++ */ ++#define DAHDI_SETLAW _IOW(DAHDI_CODE, 39, int) ++ ++/* ++ * Temporarily set the channel to operate in linear mode when non-zero ++ * or default law if 0 ++ */ ++#define DAHDI_SETLINEAR _IOW(DAHDI_CODE, 40, int) ++ ++/* ++ * Set a clear channel into HDLC w/ PPP interface mode ++ */ ++#define DAHDI_HDLCPPP _IOW(DAHDI_CODE, 41, int) ++ ++/* ++ * Set the ring cadence for FXS interfaces ++ */ ++struct dahdi_ring_cadence { ++ int ringcadence[DAHDI_MAX_CADENCE]; ++}; ++ ++#define DAHDI_SETCADENCE _IOW(DAHDI_CODE, 42, struct dahdi_ring_cadence) ++ ++/* ++ * Get/Set the signaling bits for CAS interface ++ */ ++#define DAHDI_GETRXBITS _IOR(DAHDI_CODE, 43, int) ++#define DAHDI_SETTXBITS _IOW(DAHDI_CODE, 43, int) ++ ++/* ++ * Display Channel Diagnostic Information on Console ++ */ ++#define DAHDI_CHANDIAG_V1 _IOR(DAHDI_CODE, 44, int) ++#define DAHDI_CHANDIAG _IOW(DAHDI_CODE, 44, int) ++ ++/* ++ * Set Channel's SF Tone Configuration ++ */ ++struct dahdi_sfconfig { ++ int chan; /* Channel we're applying this to (0 to use name) */ ++ char name[40]; /* Name of channel to use */ ++ long rxp1; /* receive tone det. p1 */ ++ long rxp2; /* receive tone det. p2 */ ++ long rxp3; /* receive tone det. p3 */ ++ int txtone; /* Tx tone factor */ ++ int tx_v2; /* initial v2 value */ ++ int tx_v3; /* initial v3 value */ ++ int toneflag; /* Tone flags */ ++}; ++ ++#define DAHDI_SFCONFIG _IOW(DAHDI_CODE, 46, struct dahdi_sfconfig) ++ ++/* ++ * Set timer expiration (in samples) ++ */ ++#define DAHDI_TIMERCONFIG _IOW(DAHDI_CODE, 47, int) ++ ++/* ++ * Acknowledge timer expiration (number to acknowledge, or -1 for all) ++ */ ++#define DAHDI_TIMERACK _IOW(DAHDI_CODE, 48, int) ++ ++/* ++ * Get Conference to mute mode ++ */ ++#define DAHDI_GETCONFMUTE _IOR(DAHDI_CODE, 49, int) ++ ++/* ++ * Request echo training in some number of ms (with muting in the mean time) ++ */ ++#define DAHDI_ECHOTRAIN _IOW(DAHDI_CODE, 50, int) ++ ++/* ++ * Set on hook transfer for n number of ms -- implemented by low level driver ++ */ ++#define DAHDI_ONHOOKTRANSFER _IOW(DAHDI_CODE, 51, int) ++ ++/* ++ * Queue Ping ++ */ ++#define DAHDI_TIMERPING _IO(DAHDI_CODE, 52) ++ ++/* ++ * Acknowledge ping ++ */ ++#define DAHDI_TIMERPONG _IO(DAHDI_CODE, 53) ++ ++/* ++ * Get/set signalling freeze ++ */ ++#define DAHDI_GETSIGFREEZE _IOR(DAHDI_CODE, 54, int) ++#define DAHDI_SETSIGFREEZE _IOW(DAHDI_CODE, 54, int) ++ ++/* ++ * Perform an indirect ioctl (on a specified channel via master interface) ++ */ ++struct dahdi_indirect_data { ++ int chan; ++ int op; ++ void *data; ++}; ++ ++#define DAHDI_INDIRECT _IOWR(DAHDI_CODE, 56, struct dahdi_indirect_data) ++ ++ ++/* ++ * Get the version of DAHDI that is running, and a description ++ * of the compiled-in echo cancellers (if any) ++ */ ++struct dahdi_versioninfo { ++ char version[80]; ++ char echo_canceller[80]; ++}; ++ ++#define DAHDI_GETVERSION _IOR(DAHDI_CODE, 57, struct dahdi_versioninfo) ++ ++/* ++ * Put the channel in loopback mode (receive from the channel is ++ * transmitted back on the interface) ++ */ ++#define DAHDI_LOOPBACK _IOW(DAHDI_CODE, 58, int) ++ ++/* ++ Attach the desired echo canceler module (or none) to a channel in an ++ audio-supporting mode, so that when the channel needs an echo canceler ++ that module will be used to supply one. ++ */ ++struct dahdi_attach_echocan { ++ int chan; /* Channel we're applying this to */ ++ char echocan[16]; /* Name of echo canceler to attach to this channel ++ (leave empty to have no echocan attached */ ++}; ++ ++#define DAHDI_ATTACH_ECHOCAN _IOW(DAHDI_CODE, 59, struct dahdi_attach_echocan) ++ ++ ++/* ++ * 60-80 are reserved for private drivers ++ * 80-85 are reserved for dynamic span stuff ++ */ ++ ++/* ++ * Create a dynamic span ++ */ ++struct dahdi_dynamic_span { ++ char driver[20]; /* Which low-level driver to use */ ++ char addr[40]; /* Destination address */ ++ int numchans; /* Number of channels */ ++ int timing; /* Timing source preference */ ++ int spanno; /* Span number (filled in by DAHDI) */ ++}; ++ ++#define DAHDI_DYNAMIC_CREATE _IOWR(DAHDI_CODE, 80, struct dahdi_dynamic_span) ++ ++/* ++ * Destroy a dynamic span ++ */ ++#define DAHDI_DYNAMIC_DESTROY _IOW(DAHDI_CODE, 81, struct dahdi_dynamic_span) ++ ++/* ++ * Set the HW gain for a device ++ */ ++struct dahdi_hwgain { ++ __s32 newgain; /* desired gain in dB but x10. -3.5dB would be -35 */ ++ __u32 tx:1; /* 0=rx; 1=tx */ ++}; ++#define DAHDI_SET_HWGAIN _IOW(DAHDI_CODE, 86, struct dahdi_hwgain) ++ ++/* ++ * Enable tone detection -- implemented by low level driver ++ */ ++#define DAHDI_TONEDETECT _IOW(DAHDI_CODE, 91, int) ++ ++/* ++ * Set polarity -- implemented by individual driver. 0 = forward, 1 = reverse ++ */ ++#define DAHDI_SETPOLARITY _IOW(DAHDI_CODE, 92, int) ++ ++/* ++ * Transcoder operations ++ */ ++ ++/* DAHDI_TRANSCODE_OP is an older interface that is deprecated and no longer ++ * supported. ++ */ ++#define DAHDI_TRANSCODE_OP _IOWR(DAHDI_CODE, 93, int) ++ ++#define DAHDI_TC_CODE 'T' ++#define DAHDI_TC_ALLOCATE _IOW(DAHDI_TC_CODE, 1, struct dahdi_transcoder_formats) ++#define DAHDI_TC_GETINFO _IOWR(DAHDI_TC_CODE, 2, struct dahdi_transcoder_info) ++ ++/* ++ * VMWI Specification ++ */ ++struct dahdi_vmwi_info { ++ unsigned int vmwi_type; ++}; ++ ++#define DAHDI_VMWI_LREV (1 << 0) /* Line Reversal */ ++#define DAHDI_VMWI_HVDC (1 << 1) /* HV 90VDC */ ++#define DAHDI_VMWI_HVAC (1 << 2) /* HV 90VAC Neon lamp */ ++ ++/* ++ * VoiceMail Waiting Indication (VMWI) -- implemented by low-level driver. ++ * Value: number of waiting messages (hence 0: switch messages off). ++ */ ++#define DAHDI_VMWI _IOWR(DAHDI_CODE, 94, int) ++#define DAHDI_VMWI_CONFIG _IOW(DAHDI_CODE, 95, struct dahdi_vmwi_info) ++ ++/* ++ * Startup or Shutdown a span ++ */ ++#define DAHDI_STARTUP _IOW(DAHDI_CODE, 99, int) ++#define DAHDI_SHUTDOWN _IOW(DAHDI_CODE, 100, int) ++ ++#define DAHDI_HDLC_RATE _IOW(DAHDI_CODE, 101, int) ++ ++/* Put a channel's echo canceller into 'FAX mode' if possible */ ++ ++#define DAHDI_ECHOCANCEL_FAX_MODE _IOW(DAHDI_CODE, 102, int) ++ ++/* ++ * Defines which channel to receive mirrored traffic from ++ */ ++#ifdef CONFIG_DAHDI_MIRROR ++#define DAHDI_RXMIRROR _IOW(DAHDI_CODE, 103, int) ++#define DAHDI_TXMIRROR _IOW(DAHDI_CODE, 104, int) ++#endif /* CONFIG_DAHDI_MIRROR */ ++ ++/* ++ Set the desired state for channel buffer event generation which is disabled ++ by default to allow for backwards compatibility for dumb users of channels ++ such as pattern utilities. ++ */ ++#define DAHDI_BUFFER_EVENTS _IOW(DAHDI_CODE, 105, int) ++ ++/* Get current status IOCTL */ ++/* Defines for Radio Status (dahdi_radio_stat.radstat) bits */ ++ ++#define DAHDI_RADSTAT_RX 1 /* currently "receiving " */ ++#define DAHDI_RADSTAT_TX 2 /* currently "transmitting" */ ++#define DAHDI_RADSTAT_RXCT 4 /* currently receiving continuous tone with ++ current settings */ ++#define DAHDI_RADSTAT_RXCOR 8 /* currently receiving COR (irrelevant of COR ++ ignore) */ ++#define DAHDI_RADSTAT_IGNCOR 16 /* currently ignoring COR */ ++#define DAHDI_RADSTAT_IGNCT 32 /* currently ignoring CTCSS/DCS decode */ ++#define DAHDI_RADSTAT_NOENCODE 64 /* currently blocking CTCSS/DCS encode */ ++ ++struct dahdi_radio_stat { ++ unsigned short ctcode_rx; /* code of currently received CTCSS ++ or DCS, 0 for none */ ++ unsigned short ctclass; /* class of currently received CTCSS or ++ DCS code */ ++ unsigned short ctcode_tx; /* code of currently encoded CTCSS or ++ DCS, 0 for none */ ++ unsigned char radstat; /* status bits of radio */ ++}; ++ ++#define DAHDI_RADIO_GETSTAT _IOR(DAHDI_CODE, 57, struct dahdi_radio_stat) ++ ++/* Get/Set a radio channel parameter */ ++/* Defines for Radio Parameters (dahdi_radio_param.radpar) */ ++#define DAHDI_RADPAR_INVERTCOR 1 /* invert the COR signal (0/1) */ ++#define DAHDI_RADPAR_IGNORECOR 2 /* ignore the COR signal (0/1) */ ++#define DAHDI_RADPAR_IGNORECT 3 /* ignore the CTCSS/DCS decode (0/1) */ ++#define DAHDI_RADPAR_NOENCODE 4 /* block the CTCSS/DCS encode (0/1) */ ++#define DAHDI_RADPAR_CORTHRESH 5 /* COR trigger threshold (0-7) */ ++ ++#define DAHDI_RADPAR_EXTRXTONE 6 /* 0 means use internal decoder, 1 means UIOA ++ logic true is CT decode, 2 means UIOA logic ++ false is CT decode */ ++#define DAHDI_RADPAR_NUMTONES 7 /* returns maximum tone index (curently 15) */ ++#define DAHDI_RADPAR_INITTONE 8 /* init all tone indexes to 0 (no tones) */ ++#define DAHDI_RADPAR_RXTONE 9 /* CTCSS tone, (1-32) or DCS tone (1-777), ++ or 0 meaning no tone, set index also (1-15) */ ++#define DAHDI_RADPAR_RXTONECLASS 10 /* Tone class (0-65535), set index also (1-15) */ ++#define DAHDI_RADPAR_TXTONE 11 /* CTCSS tone (1-32) or DCS tone (1-777) or 0 ++ to indicate no tone, to transmit ++ for this tone index (0-32, 0 disables ++ transmit CTCSS), set index also (0-15) */ ++#define DAHDI_RADPAR_DEBOUNCETIME 12 /* receive indication debounce time, ++ milliseconds (1-999) */ ++#define DAHDI_RADPAR_BURSTTIME 13 /* end of transmit with no CT tone in ++ milliseconds (0-999) */ ++ ++ ++#define DAHDI_RADPAR_UIODATA 14 /* read/write UIOA and UIOB data. Bit 0 is ++ UIOA, bit 1 is UIOB */ ++#define DAHDI_RADPAR_UIOMODE 15 /* 0 means UIOA and UIOB are both outputs, 1 ++ means UIOA is input, UIOB is output, 2 ++ means UIOB is input and UIOA is output, ++ 3 means both UIOA and UIOB are inputs. Note ++ mode for UIOA is overridden when in ++ EXTRXTONE mode. */ ++ ++#define DAHDI_RADPAR_REMMODE 16 /* Remote control data mode */ ++ #define DAHDI_RADPAR_REM_NONE 0 /* no remote control data mode */ ++ #define DAHDI_RADPAR_REM_RBI1 1 /* Doug Hall RBI-1 data mode */ ++ #define DAHDI_RADPAR_REM_SERIAL 2 /* Serial Data, 9600 BPS */ ++ #define DAHDI_RADPAR_REM_SERIAL_ASCII 3 /* Serial Ascii Data, 9600 BPS */ ++ ++#define DAHDI_RADPAR_REMCOMMAND 17 /* Remote conrtol write data block & do cmd */ ++ ++#define DAHDI_RADPAR_DEEMP 18 /* Audio De-empahsis (on or off) */ ++ ++#define DAHDI_RADPAR_PREEMP 19 /* Audio Pre-empahsis (on or off) */ ++ ++#define DAHDI_RADPAR_RXGAIN 20 /* Audio (In to system) Rx Gain */ ++ ++#define DAHDI_RADPAR_TXGAIN 21 /* Audio (Out from system) Tx Gain */ ++ ++#define RAD_SERIAL_BUFLEN 128 ++ ++struct dahdi_radio_param { ++ unsigned short radpar; /* param identifier */ ++ unsigned short index; /* tone number */ ++ int data; /* param */ ++ int data2; /* param 2 */ ++ unsigned char buf[RAD_SERIAL_BUFLEN]; ++}; ++#define DAHDI_RADIO_GETPARAM _IOR(DAHDI_CODE, 58, struct dahdi_radio_param) ++#define DAHDI_RADIO_SETPARAM _IOW(DAHDI_CODE, 58, struct dahdi_radio_param) ++ ++ ++/*! ++ \brief Size-limited null-terminating string copy. ++ \param dst The destination buffer ++ \param src The source string ++ \param size The size of the destination buffer ++ \return Nothing. ++ ++ This is similar to \a strncpy, with two important differences: ++ - the destination buffer will \b always be null-terminated ++ - the destination buffer is not filled with zeros past the copied string length ++ These differences make it slightly more efficient, and safer to use since it will ++ not leave the destination buffer unterminated. There is no need to pass an artificially ++ reduced buffer size to this function (unlike \a strncpy), and the buffer does not need ++ to be initialized to zeroes prior to calling this function. ++*/ ++static inline void dahdi_copy_string(char *dst, const char *src, unsigned int size) ++{ ++ while (*src && size) { ++ *dst++ = *src++; ++ size--; ++ } ++ if (__builtin_expect(!size, 0)) ++ dst--; ++ *dst = '\0'; ++} ++ ++#endif /* _DAHDI_USER_H */ +diff -Nru linux-source-4.19/include/linux/dahdi/version.h linux-source-4.19-dahdi/include/linux/dahdi/version.h +--- linux-source-4.19/include/linux/dahdi/version.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/include/linux/dahdi/version.h 2020-10-28 00:17:08.663192245 +0100 +@@ -0,0 +1,6 @@ ++/* ++ * version.h ++ * Automatically generated ++ */ ++#define DAHDI_VERSION "3.1.0-7-g699e7a0" ++ +diff -Nru linux-source-4.19/include/linux/dahdi/wctdm_user.h linux-source-4.19-dahdi/include/linux/dahdi/wctdm_user.h +--- linux-source-4.19/include/linux/dahdi/wctdm_user.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-source-4.19-dahdi/include/linux/dahdi/wctdm_user.h 2020-10-28 00:17:08.663192245 +0100 +@@ -0,0 +1,68 @@ ++/* ++ * Wildcard S100P FXS Interface Driver for DAHDI Telephony interface ++ * ++ * Written by Mark Spencer ++ * ++ * Copyright (C) 2001-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 _WCTDM_H ++#define _WCTDM_H ++ ++#include ++ ++#define NUM_REGS 109 ++#define NUM_INDIRECT_REGS 105 ++ ++struct wctdm_stats { ++ int tipvolt; /* TIP voltage (mV) */ ++ int ringvolt; /* RING voltage (mV) */ ++ int batvolt; /* VBAT voltage (mV) */ ++}; ++ ++struct wctdm_regs { ++ unsigned char direct[NUM_REGS]; ++ unsigned short indirect[NUM_INDIRECT_REGS]; ++}; ++ ++struct wctdm_regop { ++ int indirect; ++ unsigned char reg; ++ unsigned short val; ++}; ++ ++struct wctdm_echo_coefs { ++ unsigned char acim; ++ unsigned char coef1; ++ unsigned char coef2; ++ unsigned char coef3; ++ unsigned char coef4; ++ unsigned char coef5; ++ unsigned char coef6; ++ unsigned char coef7; ++ unsigned char coef8; ++}; ++ ++#define WCTDM_GET_STATS _IOR (DAHDI_CODE, 60, struct wctdm_stats) ++#define WCTDM_GET_REGS _IOR (DAHDI_CODE, 61, struct wctdm_regs) ++#define WCTDM_SET_REG _IOW (DAHDI_CODE, 62, struct wctdm_regop) ++#define WCTDM_SET_ECHOTUNE _IOW (DAHDI_CODE, 63, struct wctdm_echo_coefs) ++ ++ ++#endif /* _WCTDM_H */ diff --git a/debian/patches/series b/debian/patches/series index 399538ed1..f0567446d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -301,3 +301,7 @@ debian/ntfs-mark-it-as-broken.patch debian/Revert-perf-cs-etm-Move-definition-of-traceid_list-g.patch # ABI maintenance +linux-4.19-dahdi-3.1.0-7-g699e7a0.patch +hdlc-mtu.patch +dahdi-no-vpm.patch +dahdi-integration.patch